1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29 
30 
31 #include <stdio.h>
32 #include <memory.h>
33 #include <string.h>
34 #include <limits.h>
35 #include <dirent.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <pkgstrct.h>
39 #include <locale.h>
40 #include <libintl.h>
41 #include <unistd.h>
42 #include <stdlib.h>
43 #include "pkglib.h"
44 #include "install.h"
45 #include "libadm.h"
46 #include "libinst.h"
47 
48 extern int	Lflag, lflag, aflag, cflag, fflag, qflag, nflag, xflag, vflag;
49 extern char	*basedir, *device, pkgspool[];
50 
51 #define	NXTENTRY(P, VFP) (gpkgmapvfp((P), (VFP)))
52 
53 #define	ERR_SPOOLED	"ERROR: unable to locate spooled object <%s>"
54 #define	MSG_NET_OBJ	"It is remote and may be available from the network."
55 #define	ERR_RMHIDDEN	"unable to remove hidden file"
56 #define	ERR_HIDDEN	"ERROR: hidden file in exclusive directory"
57 
58 static char	*findspool(struct cfent *ept);
59 static int	xdir(int maptyp, VFP_T *vfp, PKGserver server, char *dirname);
60 
61 int
ckentry(int envflag,int maptyp,struct cfent * ept,VFP_T * vfp,PKGserver server)62 ckentry(int envflag, int maptyp, struct cfent *ept, VFP_T *vfp,
63     PKGserver server)
64 {
65 	int	a_err, c_err, errflg;
66 	char	*path;
67 	char	*ir = get_inst_root();
68 
69 	if (ept->ftype != 'i') {
70 		if (envflag)
71 			mappath(2, ept->path);
72 		if (!device)
73 			basepath(ept->path, maptyp ? NULL : basedir, ir);
74 	}
75 	canonize(ept->path);
76 	if (strchr("sl", ept->ftype)) {
77 		if (envflag)				/* -e option */
78 			mappath(2, ept->ainfo.local);
79 		if (!RELATIVE(ept->ainfo.local)) {	/* Absolute Path */
80 			if (!device) {
81 				if (ept->ftype == 'l')	/* Hard Link */
82 					basepath(ept->ainfo.local, NULL, ir);
83 			}
84 		}
85 		if (!RELATIVE(ept->ainfo.local))	/* Absolute Path */
86 			canonize(ept->ainfo.local);
87 	}
88 	if (envflag) {
89 		if (!strchr("isl", ept->ftype)) {
90 			mapvar(2, ept->ainfo.owner);
91 			mapvar(2, ept->ainfo.group);
92 		}
93 	}
94 
95 	if (lflag) {
96 		tputcfent(ept, stdout);
97 		return (0);
98 	} else if (Lflag)
99 		return (putcfile(ept, stdout));
100 
101 	errflg = 0;
102 	if (device) {
103 		if (strchr("dxslcbp", ept->ftype))
104 			return (0);
105 		if ((path = findspool(ept)) == NULL) {
106 			logerr(gettext(ERR_SPOOLED), ept->path);
107 			return (-1);
108 		}
109 
110 		/*
111 		 * If the package file attributes are to be sync'd up with
112 		 * the pkgmap, we fix the attributes here.
113 		 */
114 		if (fflag) {
115 			a_err = 0;
116 			/* Clear dangerous bits. */
117 			ept->ainfo.mode = (ept->ainfo.mode & S_IAMB);
118 			/*
119 			 * Make sure the file is readable by the world and
120 			 * writeable by root.
121 			 */
122 			ept->ainfo.mode |= 0644;
123 			if (!strchr("in", ept->ftype)) {
124 				/* Set the safe attributes. */
125 				if (a_err = averify(fflag, &ept->ftype,
126 				    path, &ept->ainfo)) {
127 					errflg++;
128 					if (!qflag || (a_err != VE_EXIST)) {
129 						logerr(gettext("ERROR: %s"),
130 						    ept->path);
131 						logerr(getErrbufAddr());
132 					}
133 					if (a_err == VE_EXIST)
134 						return (-1);
135 				}
136 			}
137 		}
138 		/* Report invalid modtimes by passing cverify a -1 */
139 		c_err = cverify((!fflag ? (-1) : fflag),  &ept->ftype, path,
140 		    &ept->cinfo, 1);
141 		if (c_err) {
142 			logerr(gettext("ERROR: %s"), path);
143 			logerr(getErrbufAddr());
144 			return (-1);
145 		}
146 	} else {
147 		a_err = 0;
148 		if (aflag && !strchr("in", ept->ftype)) {
149 			/* validate attributes */
150 			if (a_err = averify(fflag, &ept->ftype, ept->path,
151 			    &ept->ainfo)) {
152 				errflg++;
153 				if (!qflag || (a_err != VE_EXIST)) {
154 					logerr(gettext("ERROR: %s"),
155 					    ept->path);
156 					logerr(getErrbufAddr());
157 					if (maptyp && ept->pinfo->status ==
158 					    SERVED_FILE)
159 						logerr(gettext(MSG_NET_OBJ));
160 				}
161 				if (a_err == VE_EXIST)
162 					return (-1);
163 			}
164 		}
165 		if (cflag && strchr("fev", ept->ftype) &&
166 		    (!nflag || ept->ftype != 'v') && /* bug # 1082144 */
167 		    (!nflag || ept->ftype != 'e')) {
168 			/* validate contents */
169 			/* Report invalid modtimes by passing cverify a -1 */
170 			if (c_err = cverify((!fflag ? (-1) : fflag),
171 			    &ept->ftype, ept->path, &ept->cinfo, 1)) {
172 				errflg++;
173 				if (!qflag || (c_err != VE_EXIST)) {
174 					if (!a_err)
175 						logerr(gettext("ERROR: %s"),
176 						    ept->path);
177 					logerr(getErrbufAddr());
178 					if (maptyp && ept->pinfo->status ==
179 					    SERVED_FILE)
180 						logerr(gettext(MSG_NET_OBJ));
181 				}
182 				if (c_err == VE_EXIST)
183 					return (-1);
184 			}
185 		}
186 		if (xflag && (ept->ftype == 'x')) {
187 			/* must do verbose here since ept->path will change */
188 			path = strdup(ept->path);
189 			if (xdir(maptyp, vfp, server, path))
190 				errflg++;
191 			(void) strcpy(ept->path, path);
192 			free(path);
193 		}
194 	}
195 	if (vflag)
196 		(void) fprintf(stderr, "%s\n", ept->path);
197 	return (errflg);
198 }
199 
200 static int
xdir(int maptyp,VFP_T * vfp,PKGserver server,char * dirname)201 xdir(int maptyp, VFP_T *vfp, PKGserver server, char *dirname)
202 {
203 	DIR		*dirfp;
204 	char		badpath[PATH_MAX];
205 	int		dirfound;
206 	int		errflg;
207 	int		len;
208 	int		n;
209 	struct cfent	mine;
210 	struct dirent	*drp;
211 	struct pinfo	*pinfo;
212 	void		*pos = NULL;
213 
214 	if (!maptyp)
215 		pos = vfpGetCurrCharPtr(vfp); /* get current position in file */
216 
217 	if ((dirfp = opendir(dirname)) == NULL) {
218 		progerr(gettext("unable to open directory <%s>"), dirname);
219 		return (-1);
220 	}
221 	len = strlen(dirname);
222 
223 	errflg = 0;
224 	(void) memset((char *)&mine, '\0', sizeof (struct cfent));
225 	while ((drp = readdir(dirfp)) != NULL) {
226 		if (strcmp(drp->d_name, ".") == 0 ||
227 		    strcmp(drp->d_name, "..") == 0)
228 			continue;
229 		(void) snprintf(badpath, sizeof (badpath), "%s/%s",
230 		    dirname, drp->d_name);
231 		if (!maptyp) {
232 			dirfound = 0;
233 			while ((n = NXTENTRY(&mine, vfp)) != 0) {
234 				if (n < 0) {
235 					char	*errstr = getErrstr();
236 					logerr(gettext("ERROR: garbled entry"));
237 					logerr(gettext("pathname: %s"),
238 					    (mine.path && *mine.path) ?
239 					    mine.path : "Unknown");
240 					logerr(gettext("problem: %s"),
241 					    (errstr && *errstr) ? errstr :
242 					    "Unknown");
243 					exit(99);
244 				}
245 				if (strncmp(mine.path, dirname, len) ||
246 				    (mine.path[len] != '/'))
247 					break;
248 				if (strcmp(drp->d_name, &mine.path[len+1]) ==
249 				    0) {
250 					dirfound++;
251 					break;
252 				}
253 			}
254 
255 			vfpGetCurrCharPtr(vfp) = pos;
256 
257 			if (dirfound)
258 				continue;
259 		} else {
260 			if (srchcfile(&mine, badpath, server) == 1) {
261 				while ((pinfo = mine.pinfo) != NULL) {
262 					mine.pinfo = pinfo->next;
263 					free((char *)pinfo);
264 				}
265 				continue;
266 			}
267 		}
268 
269 		if (fflag) {
270 			if (unlink(badpath)) {
271 				errflg++;
272 				logerr(gettext("ERROR: %s"), badpath);
273 				logerr(gettext(ERR_RMHIDDEN));
274 			}
275 		} else {
276 			errflg++;
277 			logerr(gettext("ERROR: %s"), badpath);
278 			logerr(gettext(ERR_HIDDEN));
279 		}
280 	}
281 
282 	(void) closedir(dirfp);
283 	return (errflg);
284 }
285 
286 static char *
findspool(struct cfent * ept)287 findspool(struct cfent *ept)
288 {
289 	static char	path[2*PATH_MAX+1];
290 	char		host[PATH_MAX+1];
291 
292 	(void) strcpy(host, pkgspool);
293 	if (ept->ftype == 'i') {
294 		if (strcmp(ept->path, "pkginfo"))
295 			(void) strcat(host, "/install");
296 	} else if (ept->path[0] == '/') {
297 		(void) strcat(host, "/root");
298 	} else {
299 		(void) strcat(host, "/reloc");
300 	}
301 
302 	(void) snprintf(path, sizeof (path), "%s/%s", host,
303 	    ept->path + (ept->path[0] == '/'));
304 
305 	if (access(path, 0) == 0) {
306 		return (path);
307 	}
308 
309 	if ((ept->ftype != 'i') && (ept->volno > 0)) {
310 		(void) snprintf(path, sizeof (path),
311 		    "%s.%d/%s", host, ept->volno,
312 		    ept->path + (ept->path[0] == '/'));
313 		if (access(path, 0) == 0) {
314 			return (path);
315 		}
316 	}
317 	return (NULL);
318 }
319