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