xref: /minix/external/bsd/pkg_install/dist/create/pl.c (revision 0a6a1f1d)
1 /*	$NetBSD: pl.c,v 1.1.1.4 2009/11/05 18:39:03 joerg Exp $	*/
2 
3 #if HAVE_CONFIG_H
4 #include "config.h"
5 #endif
6 #include <nbcompat.h>
7 #if HAVE_SYS_CDEFS_H
8 #include <sys/cdefs.h>
9 #endif
10 __RCSID("$NetBSD: pl.c,v 1.1.1.4 2009/11/05 18:39:03 joerg Exp $");
11 
12 /*
13  * FreeBSD install - a package for the installation and maintainance
14  * of non-core utilities.
15  *
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that the following conditions
18  * are met:
19  * 1. Redistributions of source code must retain the above copyright
20  *    notice, this list of conditions and the following disclaimer.
21  * 2. Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in the
23  *    documentation and/or other materials provided with the distribution.
24  *
25  * Jordan K. Hubbard
26  * 18 July 1993
27  *
28  * Routines for dealing with the packing list.
29  *
30  */
31 
32 #include "lib.h"
33 #include "create.h"
34 #if HAVE_ERR_H
35 #include <err.h>
36 #endif
37 #ifndef NETBSD
38 #include <nbcompat/md5.h>
39 #else
40 #include <md5.h>
41 #endif
42 
43 /*
44  * Check that any symbolic link is relative to the prefix
45  */
46 static void
47 CheckSymlink(char *name, char *prefix, size_t prefixcc)
48 {
49 	char    newtgt[MaxPathSize];
50 	char    oldtgt[MaxPathSize];
51 	char   *slash;
52 	int     slashc;
53 	int     cc;
54 	int     i;
55 
56 	if ((cc = readlink(name, oldtgt, sizeof(oldtgt) - 1)) > 0) {
57 		oldtgt[cc] = 0;
58 		if (strncmp(oldtgt, prefix, prefixcc) == 0 && oldtgt[prefixcc] == '/') {
59 			for (slashc = 0, slash = &name[prefixcc + 1]; (slash = strchr(slash, '/')) != (char *) NULL; slash++, slashc++) {
60 			}
61 			for (cc = i = 0; i < slashc; i++) {
62 				strlcpy(&newtgt[cc], "../", sizeof(newtgt) - cc);
63 				cc += 3;
64 			}
65 			strlcpy(&newtgt[cc], &oldtgt[prefixcc + 1], sizeof(newtgt) - cc);
66 			(void) fprintf(stderr, "Full pathname symlink `%s' is target of `%s' - adjusting to `%s'\n", oldtgt, name, newtgt);
67 			if (unlink(name) != 0) {
68 				warn("can't unlink `%s'", name);
69 			} else if (symlink(newtgt, name) != 0) {
70 				warn("can't symlink `%s' called `%s'", newtgt, name);
71 			}
72 		}
73 	}
74 }
75 
76 /*
77  * Check a list for files that require preconversion
78  */
79 void
80 check_list(package_t *pkg, const char *PkgName)
81 {
82 	struct stat st;
83 	plist_t *tmp;
84 	plist_t *p;
85 	char    buf[ChecksumHeaderLen + LegibleChecksumLen];
86 	char    target[MaxPathSize + SymlinkHeaderLen];
87 	char    name[MaxPathSize];
88 	char   *cwd = NULL;
89 	char   *pkgname = NULL;
90 	int	cc;
91 
92 	/* Open Package Database for writing */
93 	if (update_pkgdb && !pkgdb_open(ReadWrite))
94 		err(EXIT_FAILURE, "can't open pkgdb");
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 			if (update_pkgdb) {
113 				add_pkgdir(pkgname, cwd, p->name);
114 				/* mkdir_p(cwd, p->name); */
115 			}
116 			break;
117 		case PLIST_FILE:
118 			/*
119 			 * pkgdb handling - usually, we enter files
120 			 * into the pkgdb as soon as they hit the disk,
121 			 * but as they are present before pkg_create
122 			 * starts, it's ok to do this somewhere here
123 			 */
124 			if (cwd == NULL)
125 				errx(2, "file without preceding @cwd found");
126 			if (update_pkgdb) {
127 				char   *s, t[MaxPathSize];
128 
129 				(void) snprintf(t, sizeof(t), "%s%s%s",
130 					cwd,
131 					(strcmp(cwd, "/") == 0) ? "" : "/",
132 					p->name);
133 
134 				s = pkgdb_retrieve(t);
135 				if (s && PlistOnly)
136 					warnx("Overwriting %s - "
137 					    "pkg %s bogus/conflicting?", t, s);
138 				else {
139 					pkgdb_store(t, PkgName);
140 				}
141 			}
142 
143 			/* prepend DESTDIR if set?  - HF */
144 			(void) snprintf(name, sizeof(name), "%s%s%s",
145 				cwd,
146 				(strcmp(cwd, "/") == 0) ? "" : "/",
147 				p->name);
148 			if (lstat(name, &st) < 0) {
149 				warnx("can't stat `%s'", name);
150 				continue;
151 			}
152 			switch (st.st_mode & S_IFMT) {
153 			case S_IFDIR:
154 				warnx("Warning - directory `%s' in PLIST", name);
155 				break;
156 			case S_IFLNK:
157 				if (RelativeLinks) {
158 					CheckSymlink(name, cwd, strlen(cwd));
159 				}
160 				(void) strlcpy(target, SYMLINK_HEADER,
161 				    sizeof(target));
162 				if ((cc = readlink(name, &target[SymlinkHeaderLen],
163 					  sizeof(target) - SymlinkHeaderLen - 1)) < 0) {
164 					warnx("can't readlink `%s'", name);
165 					continue;
166 				}
167 				target[SymlinkHeaderLen + cc] = 0x0;
168 				tmp = new_plist_entry();
169 				tmp->name = xstrdup(target);
170 				tmp->type = PLIST_COMMENT;
171 				tmp->next = p->next;
172 				tmp->prev = p;
173 				if (p == pkg->tail) {
174 					pkg->tail = tmp;
175 				}
176 				p->next = tmp;
177 				p = tmp;
178 				break;
179 			case S_IFCHR:
180 				warnx("Warning - char special device `%s' in PLIST", name);
181 				break;
182 			case S_IFBLK:
183 				warnx("Warning - block special device `%s' in PLIST", name);
184 				break;
185 			default:
186 				(void) strlcpy(buf, CHECKSUM_HEADER,
187 				    sizeof(buf));
188 				if (MD5File(name, &buf[ChecksumHeaderLen]) != (char *) NULL) {
189 					tmp = new_plist_entry();
190 					tmp->name = xstrdup(buf);
191 					tmp->type = PLIST_COMMENT;	/* PLIST_MD5 - HF */
192 					tmp->next = p->next;
193 					tmp->prev = p;
194 					if (p == pkg->tail) {
195 						pkg->tail = tmp;
196 					}
197 					p->next = tmp;
198 					p = tmp;
199 				}
200 				break;
201 			}
202 			break;
203 		default:
204 			break;
205 		}
206 	}
207 
208 	if (update_pkgdb) {
209 		pkgdb_close();
210 	}
211 }
212