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