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,
66 errflg;
67 char *path;
68 char *ir = get_inst_root();
69
70 if (ept->ftype != 'i') {
71 if (envflag)
72 mappath(2, ept->path);
73 if (!device)
74 basepath(ept->path, maptyp ? NULL : basedir, ir);
75 }
76 canonize(ept->path);
77 if (strchr("sl", ept->ftype)) {
78 if (envflag) /* -e option */
79 mappath(2, ept->ainfo.local);
80 if (!RELATIVE(ept->ainfo.local)) { /* Absolute Path */
81 if (!device) {
82 if (ept->ftype == 'l') /* Hard Link */
83 basepath(ept->ainfo.local, NULL, ir);
84 }
85 }
86 if (!RELATIVE(ept->ainfo.local)) /* Absolute Path */
87 canonize(ept->ainfo.local);
88 }
89 if (envflag) {
90 if (!strchr("isl", ept->ftype)) {
91 mapvar(2, ept->ainfo.owner);
92 mapvar(2, ept->ainfo.group);
93 }
94 }
95
96 if (lflag) {
97 tputcfent(ept, stdout);
98 return (0);
99 } else if (Lflag)
100 return (putcfile(ept, stdout));
101
102 errflg = 0;
103 if (device) {
104 if (strchr("dxslcbp", ept->ftype))
105 return (0);
106 if ((path = findspool(ept)) == NULL) {
107 logerr(gettext(ERR_SPOOLED), ept->path);
108 return (-1);
109 }
110
111 /*
112 * If the package file attributes are to be sync'd up with
113 * the pkgmap, we fix the attributes here.
114 */
115 if (fflag) {
116 a_err = 0;
117 /* Clear dangerous bits. */
118 ept->ainfo.mode = (ept->ainfo.mode & S_IAMB);
119 /*
120 * Make sure the file is readable by the world and
121 * writeable by root.
122 */
123 ept->ainfo.mode |= 0644;
124 if (!strchr("in", ept->ftype)) {
125 /* Set the safe attributes. */
126 if (a_err = averify(fflag, &ept->ftype,
127 path, &ept->ainfo)) {
128 errflg++;
129 if (!qflag || (a_err != VE_EXIST)) {
130 logerr(gettext("ERROR: %s"),
131 ept->path);
132 logerr(getErrbufAddr());
133 }
134 if (a_err == VE_EXIST)
135 return (-1);
136 }
137 }
138 }
139 /* Report invalid modtimes by passing cverify a -1 */
140 c_err = cverify((!fflag ? (-1) : fflag), &ept->ftype, path,
141 &ept->cinfo, 1);
142 if (c_err) {
143 logerr(gettext("ERROR: %s"), path);
144 logerr(getErrbufAddr());
145 return (-1);
146 }
147 } else {
148 a_err = 0;
149 if (aflag && !strchr("in", ept->ftype)) {
150 /* validate attributes */
151 if (a_err = averify(fflag, &ept->ftype, ept->path,
152 &ept->ainfo)) {
153 errflg++;
154 if (!qflag || (a_err != VE_EXIST)) {
155 logerr(gettext("ERROR: %s"),
156 ept->path);
157 logerr(getErrbufAddr());
158 if (maptyp && ept->pinfo->status ==
159 SERVED_FILE)
160 logerr(gettext(MSG_NET_OBJ));
161 }
162 if (a_err == VE_EXIST)
163 return (-1);
164 }
165 }
166 if (cflag && strchr("fev", ept->ftype) &&
167 (!nflag || ept->ftype != 'v') && /* bug # 1082144 */
168 (!nflag || ept->ftype != 'e')) {
169 /* validate contents */
170 /* Report invalid modtimes by passing cverify a -1 */
171 if (c_err = cverify((!fflag ? (-1) : fflag),
172 &ept->ftype, ept->path, &ept->cinfo, 1)) {
173 errflg++;
174 if (!qflag || (c_err != VE_EXIST)) {
175 if (!a_err)
176 logerr(gettext("ERROR: %s"),
177 ept->path);
178 logerr(getErrbufAddr());
179 if (maptyp && ept->pinfo->status ==
180 SERVED_FILE)
181 logerr(gettext(MSG_NET_OBJ));
182 }
183 if (c_err == VE_EXIST)
184 return (-1);
185 }
186 }
187 if (xflag && (ept->ftype == 'x')) {
188 /* must do verbose here since ept->path will change */
189 path = strdup(ept->path);
190 if (xdir(maptyp, vfp, server, path))
191 errflg++;
192 (void) strcpy(ept->path, path);
193 free(path);
194 }
195 }
196 if (vflag)
197 (void) fprintf(stderr, "%s\n", ept->path);
198 return (errflg);
199 }
200
201 static int
xdir(int maptyp,VFP_T * vfp,PKGserver server,char * dirname)202 xdir(int maptyp, VFP_T *vfp, PKGserver server, char *dirname)
203 {
204 DIR *dirfp;
205 char badpath[PATH_MAX];
206 int dirfound;
207 int errflg;
208 int len;
209 int n;
210 struct cfent mine;
211 struct dirent *drp;
212 struct pinfo *pinfo;
213 void *pos;
214
215 if (!maptyp)
216 pos = vfpGetCurrCharPtr(vfp); /* get current position in file */
217
218 if ((dirfp = opendir(dirname)) == NULL) {
219 progerr(gettext("unable to open directory <%s>"), dirname);
220 return (-1);
221 }
222 len = strlen(dirname);
223
224 errflg = 0;
225 (void) memset((char *)&mine, '\0', sizeof (struct cfent));
226 while ((drp = readdir(dirfp)) != NULL) {
227 if (strcmp(drp->d_name, ".") == NULL ||
228 strcmp(drp->d_name, "..") == NULL)
229 continue;
230 (void) snprintf(badpath, sizeof (badpath), "%s/%s",
231 dirname, drp->d_name);
232 if (!maptyp) {
233 dirfound = 0;
234 while ((n = NXTENTRY(&mine, vfp)) != 0) {
235 if (n < 0) {
236 char *errstr = getErrstr();
237 logerr(gettext("ERROR: garbled entry"));
238 logerr(gettext("pathname: %s"),
239 (mine.path && *mine.path) ?
240 mine.path : "Unknown");
241 logerr(gettext("problem: %s"),
242 (errstr && *errstr) ? errstr :
243 "Unknown");
244 exit(99);
245 }
246 if (strncmp(mine.path, dirname, len) ||
247 (mine.path[len] != '/'))
248 break;
249 if (strcmp(drp->d_name, &mine.path[len+1]) ==
250 0) {
251 dirfound++;
252 break;
253 }
254 }
255
256 vfpGetCurrCharPtr(vfp) = pos;
257
258 if (dirfound)
259 continue;
260 } else {
261 if (srchcfile(&mine, badpath, server) == 1) {
262 while ((pinfo = mine.pinfo) != NULL) {
263 mine.pinfo = pinfo->next;
264 free((char *)pinfo);
265 }
266 continue;
267 }
268 }
269
270 if (fflag) {
271 if (unlink(badpath)) {
272 errflg++;
273 logerr(gettext("ERROR: %s"), badpath);
274 logerr(gettext(ERR_RMHIDDEN));
275 }
276 } else {
277 errflg++;
278 logerr(gettext("ERROR: %s"), badpath);
279 logerr(gettext(ERR_HIDDEN));
280 }
281 }
282
283 (void) closedir(dirfp);
284 return (errflg);
285 }
286
287 static char *
findspool(struct cfent * ept)288 findspool(struct cfent *ept)
289 {
290 static char path[2*PATH_MAX+1];
291 char host[PATH_MAX+1];
292
293 (void) strcpy(host, pkgspool);
294 if (ept->ftype == 'i') {
295 if (strcmp(ept->path, "pkginfo"))
296 (void) strcat(host, "/install");
297 } else if (ept->path[0] == '/') {
298 (void) strcat(host, "/root");
299 } else {
300 (void) strcat(host, "/reloc");
301 }
302
303 (void) snprintf(path, sizeof (path), "%s/%s", host,
304 ept->path + (ept->path[0] == '/'));
305
306 if (access(path, 0) == 0) {
307 return (path);
308 }
309
310 if ((ept->ftype != 'i') && (ept->volno > 0)) {
311 (void) snprintf(path, sizeof (path),
312 "%s.%d/%s", host, ept->volno,
313 ept->path + (ept->path[0] == '/'));
314 if (access(path, 0) == 0) {
315 return (path);
316 }
317 }
318 return (NULL);
319 }
320