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, 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 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 * 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