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 (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 29 #include <stdio.h> 30 #include <errno.h> 31 #include <limits.h> 32 #include <stdlib.h> 33 #include <unistd.h> 34 #include <string.h> 35 #include <ctype.h> 36 #include <dirent.h> 37 #include <sys/types.h> 38 #include <pkgstrct.h> 39 #include <pkginfo.h> 40 #include <locale.h> 41 #include <libintl.h> 42 #include <pkglib.h> 43 #include "libinst.h" 44 #include "libadm.h" 45 #include "messages.h" 46 47 #define LSIZE 256 48 #define NVERS 50 49 50 /* 51 * internal global variables 52 */ 53 54 static struct pkginfo info; 55 56 static char type; 57 static char *alist[NVERS]; 58 static char *rmpkginst; 59 static char *vlist[NVERS]; 60 static char file[128]; 61 static char name[128]; 62 static char rmpkg[PKGSIZ+1]; 63 static char wabbrev[128]; 64 65 static int errflg = 0; 66 static int nlist; 67 static int pkgexist; 68 static int pkgokay; 69 static int is_update; 70 static int is_patch_update; 71 72 /* 73 * IMPORTANT NOTE: THE SIZE OF 'abbrev' IS HARD CODED INTO THE CHARACTER 74 * ARRAY SSCANF_FORMAT -- YOU MUST UPDATE BOTH VALUES AT THE SAME TIME!! 75 */ 76 77 static char abbrev[128+1]; 78 static char *SSCANF_FORMAT = "%c %128s %[^\n]"; 79 80 /* 81 * forward declarations 82 */ 83 84 static void ckrdeps(boolean_t a_preinstallCheck); 85 static void ckpreq(FILE *fp, char *dname, boolean_t a_preinstallCheck); 86 static void deponme(char *pkginst, char *pkgname, 87 boolean_t a_preinstallCheck); 88 static void prereq(char *pkginst, char *pkgname, 89 boolean_t a_preinstallCheck); 90 static void incompat(char *pkginst, char *pkgname, 91 boolean_t a_preinstallCheck); 92 static int getaline(FILE *fp); 93 94 /* 95 * ***************************************************************************** 96 * global external (public) functions 97 * ***************************************************************************** 98 */ 99 100 int 101 dockdeps(char *a_depfile, int a_removeFlag, boolean_t a_preinstallCheck) 102 { 103 FILE *fp; 104 int i; 105 char *inst; 106 107 if (a_removeFlag) { 108 /* check removal dependencies */ 109 rmpkginst = a_depfile; 110 (void) strncpy(rmpkg, rmpkginst, PKGSIZ); 111 (void) strtok(rmpkg, "."); 112 (void) snprintf(file, sizeof (file), 113 "%s/%s/%s", pkgdir, rmpkginst, DEPEND_FILE); 114 if ((fp = fopen(file, "r")) == NULL) 115 goto done; 116 } else { 117 if ((fp = fopen(a_depfile, "r")) == NULL) { 118 progerr(ERR_CANNOT_OPEN_DEPEND_FILE, a_depfile, 119 strerror(errno)); 120 quit(99); 121 } 122 } 123 124 while (getaline(fp)) { 125 switch (type) { 126 case 'I': 127 case 'P': 128 if (a_removeFlag) { 129 continue; 130 } 131 break; 132 133 case 'R': 134 if (!a_removeFlag) { 135 continue; 136 } 137 break; 138 139 default: 140 errflg++; 141 progerr(ERR_UNKNOWN_DEPENDENCY, type); 142 break; 143 } 144 145 /* check to see if any versions listed are installed */ 146 pkgexist = pkgokay = 0; 147 i = 0; 148 if (strchr(abbrev, '.')) { 149 progerr(ERR_PKGABRV, abbrev); 150 } 151 (void) snprintf(wabbrev, sizeof (wabbrev), "%s.*", abbrev); 152 153 do { 154 inst = fpkginst(wabbrev, alist[i], vlist[i]); 155 if (inst && (pkginfo(&info, inst, NULL, NULL) == 0)) { 156 pkgexist++; 157 if ((info.status == PI_INSTALLED) || 158 (info.status == PI_PRESVR4)) 159 pkgokay++; 160 } 161 } while (++i < nlist); 162 (void) fpkginst(NULL); /* force closing/rewind of files */ 163 164 if (!info.name) { 165 info.name = name; 166 } 167 168 switch (type) { 169 case 'I': 170 incompat(abbrev, info.name, a_preinstallCheck); 171 break; 172 173 case 'P': 174 prereq(abbrev, name, a_preinstallCheck); 175 break; 176 177 case 'R': 178 deponme(abbrev, info.name, a_preinstallCheck); 179 } 180 } 181 (void) fclose(fp); 182 183 done: 184 if (a_removeFlag) { 185 ckrdeps(a_preinstallCheck); 186 } 187 188 return (errflg); 189 } 190 191 void 192 setPatchUpdate(void) 193 { 194 is_patch_update = 1; 195 } 196 197 int 198 isPatchUpdate(void) 199 { 200 return ((is_patch_update) ? 1 : 0); 201 } 202 203 void 204 setUpdate(void) 205 { 206 is_update = 1; 207 } 208 209 int 210 isUpdate(void) 211 { 212 return ((is_update) ? 1 : 0); 213 } 214 215 /* 216 * ***************************************************************************** 217 * static internal (private) functions 218 * ***************************************************************************** 219 */ 220 221 static void 222 incompat(char *pkginst, char *pkgname, boolean_t a_preinstallCheck) 223 { 224 char buf[512]; 225 226 if (!pkgexist) 227 return; 228 229 errflg++; 230 if (a_preinstallCheck == B_TRUE) { 231 (void) fprintf(stdout, "incompat=%s\n", pkginst); 232 return; 233 } 234 235 logerr(ERR_WARNING); 236 (void) snprintf(buf, sizeof (buf), ERR_INCOMP_VERS, pkginst, pkgname); 237 puttext(stderr, buf, 4, 0); 238 (void) putc('\n', stderr); 239 } 240 241 static void 242 prereq(char *pkginst, char *pkgname, boolean_t a_preinstallCheck) 243 { 244 register int i; 245 char buf[512]; 246 247 if (pkgokay) { 248 return; 249 } 250 251 errflg++; 252 253 if (a_preinstallCheck == B_TRUE) { 254 if (pkgexist) { 255 (void) fprintf(stdout, 256 "prerequisite-incomplete=%s\n", pkginst); 257 } else { 258 (void) fprintf(stdout, 259 "prerequisite-installed=%s\n", pkginst); 260 } 261 return; 262 } 263 264 logerr(ERR_WARNING); 265 if (pkgexist) { 266 (void) snprintf(buf, sizeof (buf), ERR_PRENCI, pkginst, 267 pkgname); 268 puttext(stderr, buf, 4, 0); 269 (void) putc('\n', stderr); 270 } else { 271 (void) snprintf(buf, sizeof (buf), ERR_PREREQ, pkginst, 272 pkgname); 273 if (nlist) { 274 (void) strcat(buf, ERR_VALINST); 275 } 276 puttext(stderr, buf, 4, 0); 277 (void) putc('\n', stderr); 278 for (i = 0; i < nlist; i++) { 279 (void) printf(" "); 280 if (alist[i]) 281 (void) printf("(%s) ", alist[i]); 282 if (vlist[i]) 283 (void) printf("%s", vlist[i]); 284 (void) printf("\n"); 285 } 286 } 287 } 288 289 static void 290 deponme(char *pkginst, char *pkgname, boolean_t a_preinstallCheck) 291 { 292 char buf[512]; 293 294 if (!pkgexist) 295 return; 296 297 errflg++; 298 299 if (a_preinstallCheck == B_TRUE) { 300 if (!pkgname || !pkgname[0]) { 301 (void) snprintf(buf, sizeof (buf), 302 "dependonme=%s", pkginst); 303 } else { 304 (void) snprintf(buf, sizeof (buf), 305 "dependsonme=%s:%s", pkginst, pkgname); 306 } 307 (void) fprintf(stdout, "%s\n", buf); 308 return; 309 } 310 311 logerr(ERR_WARNING); 312 if (!pkgname || !pkgname[0]) { 313 (void) snprintf(buf, sizeof (buf), ERR_DEPONME, pkginst); 314 } else { 315 (void) snprintf(buf, sizeof (buf), ERR_DEPNAM, pkginst, 316 pkgname); 317 } 318 puttext(stderr, buf, 4, 0); 319 (void) putc('\n', stderr); 320 } 321 322 static int 323 getaline(FILE *fp) 324 { 325 register int i, c, found; 326 char *pt, *new, line[LSIZE]; 327 328 abbrev[0] = name[0] = type = '\0'; 329 330 for (i = 0; i < nlist; i++) { 331 if (alist[i]) { 332 free(alist[i]); 333 alist[i] = NULL; 334 } 335 if (vlist[i]) { 336 free(vlist[i]); 337 vlist[i] = NULL; 338 } 339 } 340 alist[0] = vlist[0] = NULL; 341 342 found = (-1); 343 nlist = 0; 344 while ((c = getc(fp)) != EOF) { 345 (void) ungetc(c, fp); 346 if ((found >= 0) && !isspace(c)) 347 return (1); 348 349 if (!fgets(line, LSIZE, fp)) 350 break; 351 352 for (pt = line; isspace(*pt); /* void */) 353 pt++; 354 if (!*pt || (*pt == '#')) 355 continue; 356 357 if (pt == line) { 358 /* begin new definition */ 359 /* LINTED variable format specifier to sscanf(): */ 360 (void) sscanf(line, SSCANF_FORMAT, &type, abbrev, name); 361 found++; 362 continue; 363 } 364 if (found < 0) 365 return (0); 366 367 if (*pt == '(') { 368 /* architecture is specified */ 369 if (new = strchr(pt, ')')) 370 *new++ = '\0'; 371 else 372 return (-1); /* bad specification */ 373 alist[found] = qstrdup(pt+1); 374 pt = new; 375 } 376 while (isspace(*pt)) 377 pt++; 378 if (*pt) { 379 vlist[found] = qstrdup(pt); 380 if (pt = strchr(vlist[found], '\n')) 381 *pt = '\0'; 382 } 383 found++; 384 nlist++; 385 } 386 return ((found >= 0) ? 1 : 0); 387 } 388 389 static void 390 ckrdeps(boolean_t a_preinstallCheck) 391 { 392 struct dirent *drp; 393 DIR *dirfp; 394 FILE *fp; 395 char depfile[PATH_MAX+1]; 396 397 if ((dirfp = opendir(pkgdir)) == NULL) 398 return; 399 400 while ((drp = readdir(dirfp)) != NULL) { 401 if (drp->d_name[0] == '.') 402 continue; 403 404 if (strcmp(drp->d_name, rmpkginst) == 0) 405 continue; /* others don't include me */ 406 (void) snprintf(depfile, sizeof (depfile), 407 "%s/%s/%s", pkgdir, drp->d_name, DEPEND_FILE); 408 if ((fp = fopen(depfile, "r")) == NULL) 409 continue; 410 411 ckpreq(fp, drp->d_name, a_preinstallCheck); 412 } 413 (void) closedir(dirfp); 414 } 415 416 static void 417 ckpreq(FILE *fp, char *dname, boolean_t a_preinstallCheck) 418 { 419 register int i; 420 char *inst; 421 422 while (getaline(fp)) { 423 if (type != 'P') 424 continue; 425 426 if (strcmp(abbrev, rmpkg)) 427 continue; 428 429 /* see if package is installed */ 430 i = 0; 431 if (strchr(abbrev, '.') == 0) { 432 (void) strcat(abbrev, ".*"); 433 } 434 pkgexist = 1; 435 436 do { 437 if (inst = fpkginst(abbrev, alist[i], vlist[i])) { 438 if (strcmp(inst, rmpkginst) == 0) { 439 deponme(dname, "", a_preinstallCheck); 440 (void) fclose(fp); 441 (void) fpkginst(NULL); 442 return; 443 } 444 } 445 } while (++i < nlist); 446 (void) fpkginst(NULL); 447 } 448 (void) fclose(fp); 449 } 450