xref: /netbsd-src/external/bsd/pkg_install/dist/create/pl.c (revision 27fd3f6531803adac12382d7643a9a492b576601)
1 /*	$NetBSD: pl.c,v 1.1.1.3 2009/04/24 14:16:59 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.3 2009/04/24 14:16:59 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   *srcdir = NULL;
90 	char   *pkgname = NULL;
91 	int	cc;
92 
93 	/* Open Package Database for writing */
94 	if (update_pkgdb && !pkgdb_open(ReadWrite))
95 		err(EXIT_FAILURE, "can't open pkgdb");
96 
97 	for (p = pkg->head; p; p = p->next) {
98 		switch (p->type) {
99 		case PLIST_CWD:
100 			cwd = p->name;
101 			break;
102 		case PLIST_NAME:
103 			pkgname = p->name;
104 			break;
105 		case PLIST_IGNORE:
106 			p = p->next;
107 			break;
108 		case PLIST_SRC:
109 			srcdir = p->name;
110 			break;
111 		case PLIST_PKGDIR:
112 			if (cwd == NULL)
113 				errx(2, "@pkgdir without preceding @cwd found");
114 			if (pkgname == NULL)
115 				errx(2, "@pkgdir without preceding @name found");
116 			if (update_pkgdb) {
117 				add_pkgdir(pkgname, cwd, p->name);
118 				/* mkdir_p(cwd, p->name); */
119 			}
120 			break;
121 		case PLIST_FILE:
122 			/*
123 			 * pkgdb handling - usually, we enter files
124 			 * into the pkgdb as soon as they hit the disk,
125 			 * but as they are present before pkg_create
126 			 * starts, it's ok to do this somewhere here
127 			 */
128 			if (cwd == NULL)
129 				errx(2, "file without preceding @cwd found");
130 			if (update_pkgdb) {
131 				char   *s, t[MaxPathSize];
132 
133 				(void) snprintf(t, sizeof(t), "%s%s%s",
134 					cwd,
135 					(strcmp(cwd, "/") == 0) ? "" : "/",
136 					p->name);
137 
138 				s = pkgdb_retrieve(t);
139 				if (s && PlistOnly)
140 					warnx("Overwriting %s - "
141 					    "pkg %s bogus/conflicting?", t, s);
142 				else {
143 					pkgdb_store(t, PkgName);
144 				}
145 			}
146 
147 			/* prepend DESTDIR if set?  - HF */
148 			(void) snprintf(name, sizeof(name), "%s%s%s",
149 				cwd,
150 				(strcmp(cwd, "/") == 0) ? "" : "/",
151 				p->name);
152 			if (lstat(name, &st) < 0) {
153 				warnx("can't stat `%s'", name);
154 				continue;
155 			}
156 			switch (st.st_mode & S_IFMT) {
157 			case S_IFDIR:
158 				warnx("Warning - directory `%s' in PLIST", name);
159 				break;
160 			case S_IFLNK:
161 				if (RelativeLinks) {
162 					CheckSymlink(name, cwd, strlen(cwd));
163 				}
164 				(void) strlcpy(target, SYMLINK_HEADER,
165 				    sizeof(target));
166 				if ((cc = readlink(name, &target[SymlinkHeaderLen],
167 					  sizeof(target) - SymlinkHeaderLen - 1)) < 0) {
168 					warnx("can't readlink `%s'", name);
169 					continue;
170 				}
171 				target[SymlinkHeaderLen + cc] = 0x0;
172 				tmp = new_plist_entry();
173 				tmp->name = xstrdup(target);
174 				tmp->type = PLIST_COMMENT;
175 				tmp->next = p->next;
176 				tmp->prev = p;
177 				if (p == pkg->tail) {
178 					pkg->tail = tmp;
179 				}
180 				p->next = tmp;
181 				p = tmp;
182 				break;
183 			case S_IFCHR:
184 				warnx("Warning - char special device `%s' in PLIST", name);
185 				break;
186 			case S_IFBLK:
187 				warnx("Warning - block special device `%s' in PLIST", name);
188 				break;
189 			default:
190 				(void) strlcpy(buf, CHECKSUM_HEADER,
191 				    sizeof(buf));
192 				if (MD5File(name, &buf[ChecksumHeaderLen]) != (char *) NULL) {
193 					tmp = new_plist_entry();
194 					tmp->name = xstrdup(buf);
195 					tmp->type = PLIST_COMMENT;	/* PLIST_MD5 - HF */
196 					tmp->next = p->next;
197 					tmp->prev = p;
198 					if (p == pkg->tail) {
199 						pkg->tail = tmp;
200 					}
201 					p->next = tmp;
202 					p = tmp;
203 				}
204 				break;
205 			}
206 			break;
207 		default:
208 			break;
209 		}
210 	}
211 
212 	if (update_pkgdb) {
213 		pkgdb_close();
214 	}
215 }
216