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