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 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 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, ".") == 0 || 228 strcmp(drp->d_name, "..") == 0) 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 * 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