xref: /netbsd/external/bsd/pkg_install/dist/create/pl.c (revision a24fe59c)
1 /*	$NetBSD: pl.c,v 1.5 2021/04/10 19:49:59 nia Exp $	*/
2 
3 #ifdef HAVE_NBTOOL_CONFIG_H
4 #include "nbtool_config.h"
5 #else
6 #if HAVE_CONFIG_H
7 #include "config.h"
8 #endif
9 #include <nbcompat.h>
10 #if HAVE_SYS_CDEFS_H
11 #include <sys/cdefs.h>
12 #endif
13 #endif
14 __RCSID("$NetBSD: pl.c,v 1.5 2021/04/10 19:49:59 nia Exp $");
15 
16 /*
17  * FreeBSD install - a package for the installation and maintainance
18  * of non-core utilities.
19  *
20  * Redistribution and use in source and binary forms, with or without
21  * modification, are permitted provided that the following conditions
22  * are met:
23  * 1. Redistributions of source code must retain the above copyright
24  *    notice, this list of conditions and the following disclaimer.
25  * 2. Redistributions in binary form must reproduce the above copyright
26  *    notice, this list of conditions and the following disclaimer in the
27  *    documentation and/or other materials provided with the distribution.
28  *
29  * Jordan K. Hubbard
30  * 18 July 1993
31  *
32  * Routines for dealing with the packing list.
33  *
34  */
35 
36 #include "lib.h"
37 #include "create.h"
38 #if HAVE_ERR_H
39 #include <err.h>
40 #endif
41 #ifndef NETBSD
42 #include <nbcompat/md5.h>
43 #else
44 #include <md5.h>
45 #endif
46 
47 /*
48  * Check that any symbolic link is relative to the prefix
49  */
50 static void
CheckSymlink(char * name,char * prefix,size_t prefixcc)51 CheckSymlink(char *name, char *prefix, size_t prefixcc)
52 {
53 	char    newtgt[MaxPathSize];
54 	char    oldtgt[MaxPathSize];
55 	char   *slash;
56 	int     slashc;
57 	int     cc;
58 	int     i;
59 
60 	if ((cc = readlink(name, oldtgt, sizeof(oldtgt) - 1)) > 0) {
61 		oldtgt[cc] = 0;
62 		if (strncmp(oldtgt, prefix, prefixcc) == 0 && oldtgt[prefixcc] == '/') {
63 			for (slashc = 0, slash = &name[prefixcc + 1]; (slash = strchr(slash, '/')) != (char *) NULL; slash++, slashc++) {
64 			}
65 			for (cc = i = 0; i < slashc; i++) {
66 				strlcpy(&newtgt[cc], "../", sizeof(newtgt) - cc);
67 				cc += 3;
68 			}
69 			strlcpy(&newtgt[cc], &oldtgt[prefixcc + 1], sizeof(newtgt) - cc);
70 			(void) fprintf(stderr, "Full pathname symlink `%s' is target of `%s' - adjusting to `%s'\n", oldtgt, name, newtgt);
71 			if (unlink(name) != 0) {
72 				warn("can't unlink `%s'", name);
73 			} else if (symlink(newtgt, name) != 0) {
74 				warn("can't symlink `%s' called `%s'", newtgt, name);
75 			}
76 		}
77 	}
78 }
79 
80 /*
81  * Check a list for files that require preconversion
82  */
83 void
check_list(package_t * pkg,const char * PkgName)84 check_list(package_t *pkg, const char *PkgName)
85 {
86 	struct stat st;
87 	plist_t *tmp;
88 	plist_t *p;
89 	char    buf[ChecksumHeaderLen + LegibleChecksumLen];
90 	char    target[MaxPathSize + SymlinkHeaderLen];
91 	char    name[MaxPathSize];
92 	char   *cwd = NULL;
93 	char   *pkgname = NULL;
94 	int	cc;
95 
96 	for (p = pkg->head; p; p = p->next) {
97 		switch (p->type) {
98 		case PLIST_CWD:
99 			cwd = p->name;
100 			break;
101 		case PLIST_NAME:
102 			pkgname = p->name;
103 			break;
104 		case PLIST_IGNORE:
105 			p = p->next;
106 			break;
107 		case PLIST_PKGDIR:
108 			if (cwd == NULL)
109 				errx(2, "@pkgdir without preceding @cwd found");
110 			if (pkgname == NULL)
111 				errx(2, "@pkgdir without preceding @name found");
112 			break;
113 		case PLIST_FILE:
114 			if (cwd == NULL)
115 				errx(2, "file without preceding @cwd found");
116 			(void) snprintf(name, sizeof(name), "%s%s%s",
117 				cwd,
118 				(strcmp(cwd, "/") == 0) ? "" : "/",
119 				p->name);
120 			if (lstat(name, &st) < 0) {
121 				warnx("can't stat `%s'", name);
122 				continue;
123 			}
124 			switch (st.st_mode & S_IFMT) {
125 			case S_IFDIR:
126 				warnx("Warning - directory `%s' in PLIST", name);
127 				break;
128 			case S_IFLNK:
129 				if (RelativeLinks) {
130 					CheckSymlink(name, cwd, strlen(cwd));
131 				}
132 				(void) strlcpy(target, SYMLINK_HEADER,
133 				    sizeof(target));
134 				if ((cc = readlink(name, &target[SymlinkHeaderLen],
135 					  sizeof(target) - SymlinkHeaderLen - 1)) < 0) {
136 					warnx("can't readlink `%s'", name);
137 					continue;
138 				}
139 				target[SymlinkHeaderLen + cc] = 0x0;
140 				tmp = new_plist_entry();
141 				tmp->name = xstrdup(target);
142 				tmp->type = PLIST_COMMENT;
143 				tmp->next = p->next;
144 				tmp->prev = p;
145 				if (p == pkg->tail) {
146 					pkg->tail = tmp;
147 				}
148 				p->next = tmp;
149 				p = tmp;
150 				break;
151 			case S_IFCHR:
152 				warnx("Warning - char special device `%s' in PLIST", name);
153 				break;
154 			case S_IFBLK:
155 				warnx("Warning - block special device `%s' in PLIST", name);
156 				break;
157 			default:
158 				(void) strlcpy(buf, CHECKSUM_HEADER,
159 				    sizeof(buf));
160 				if (MD5File(name, &buf[ChecksumHeaderLen]) != (char *) NULL) {
161 					tmp = new_plist_entry();
162 					tmp->name = xstrdup(buf);
163 					tmp->type = PLIST_COMMENT;	/* PLIST_MD5 - HF */
164 					tmp->next = p->next;
165 					tmp->prev = p;
166 					if (p == pkg->tail) {
167 						pkg->tail = tmp;
168 					}
169 					p->next = tmp;
170 					p = tmp;
171 				}
172 				break;
173 			}
174 			break;
175 		default:
176 			break;
177 		}
178 	}
179 }
180