1327Sjkh/* 2228990Suqs * FreeBSD install - a package for the installation and maintenance 3327Sjkh * of non-core utilities. 4327Sjkh * 5327Sjkh * Redistribution and use in source and binary forms, with or without 6327Sjkh * modification, are permitted provided that the following conditions 7327Sjkh * are met: 8327Sjkh * 1. Redistributions of source code must retain the above copyright 9327Sjkh * notice, this list of conditions and the following disclaimer. 10327Sjkh * 2. Redistributions in binary form must reproduce the above copyright 11327Sjkh * notice, this list of conditions and the following disclaimer in the 12327Sjkh * documentation and/or other materials provided with the distribution. 13327Sjkh * 14327Sjkh * Jordan K. Hubbard 15327Sjkh * 18 July 1993 16327Sjkh * 17327Sjkh * This is the main body of the add module. 18327Sjkh * 19327Sjkh */ 20327Sjkh 2193520Sobrien#include <sys/cdefs.h> 2293520Sobrien__FBSDID("$FreeBSD: releng/10.3/usr.sbin/pkg_install/add/perform.c 240476 2012-09-14 00:19:06Z jkim $"); 2393520Sobrien 2430221Scharnier#include <err.h> 2569793Sobrien#include <paths.h> 26222035Sflz#include "lib.h" 27327Sjkh#include "add.h" 28327Sjkh 2984670Ssobomax#include <libgen.h> 30327Sjkh#include <signal.h> 314996Sjkh#include <sys/wait.h> 32327Sjkh 33327Sjkhstatic int pkg_do(char *); 34327Sjkhstatic int sanity_check(char *); 35327Sjkhstatic char LogDir[FILENAME_MAX]; 3637728Seivindstatic int zapLogDir; /* Should we delete LogDir? */ 37327Sjkh 38327Sjkhint 39327Sjkhpkg_perform(char **pkgs) 40327Sjkh{ 41327Sjkh int i, err_cnt = 0; 42327Sjkh 43327Sjkh signal(SIGINT, cleanup); 44327Sjkh signal(SIGHUP, cleanup); 45327Sjkh 46382Sjkh if (AddMode == SLAVE) 47382Sjkh err_cnt = pkg_do(NULL); 48382Sjkh else { 49382Sjkh for (i = 0; pkgs[i]; i++) 50382Sjkh err_cnt += pkg_do(pkgs[i]); 51382Sjkh } 52327Sjkh return err_cnt; 53327Sjkh} 54327Sjkh 558083Sjkh/* 568083Sjkh * This is seriously ugly code following. Written very fast! 578083Sjkh * [And subsequently made even worse.. Sigh! This code was just born 588083Sjkh * to be hacked, I guess.. :) -jkh] 598083Sjkh */ 60327Sjkhstatic int 61327Sjkhpkg_do(char *pkg) 62327Sjkh{ 63194497Sbrian Package Plist; 64327Sjkh char pkg_fullname[FILENAME_MAX]; 6511780Sjkh char playpen[FILENAME_MAX]; 667998Sjkh char extract_contents[FILENAME_MAX]; 67194497Sbrian char *extract; 68194497Sbrian const char *where_to; 69327Sjkh FILE *cfile; 7011780Sjkh int code; 711545Sjkh PackingList p; 723364Sjkh struct stat sb; 73131280Seik int inPlace, conflictsfound, errcode; 7441866Sjkh /* support for separate pre/post install scripts */ 7541866Sjkh int new_m = 0; 7641866Sjkh char pre_script[FILENAME_MAX] = INSTALL_FNAME; 7741866Sjkh char post_script[FILENAME_MAX]; 7841866Sjkh char pre_arg[FILENAME_MAX], post_arg[FILENAME_MAX]; 79113594Skris char *conflict[2]; 80113594Skris char **matched; 81206043Sflz int fd; 82327Sjkh 83113594Skris conflictsfound = 0; 8411780Sjkh code = 0; 8537728Seivind zapLogDir = 0; 86327Sjkh LogDir[0] = '\0'; 8711780Sjkh strcpy(playpen, FirstPen); 8811780Sjkh inPlace = 0; 898075Sjkh 90194497Sbrian memset(&Plist, '\0', sizeof(Plist)); 91194497Sbrian 928083Sjkh /* Are we coming in for a second pass, everything already extracted? */ 9311780Sjkh if (!pkg) { 9411780Sjkh fgets(playpen, FILENAME_MAX, stdin); 9511780Sjkh playpen[strlen(playpen) - 1] = '\0'; /* pesky newline! */ 9611780Sjkh if (chdir(playpen) == FAIL) { 9730221Scharnier warnx("pkg_add in SLAVE mode can't chdir to %s", playpen); 98382Sjkh return 1; 99382Sjkh } 100382Sjkh read_plist(&Plist, stdin); 10111780Sjkh where_to = playpen; 102327Sjkh } 1038083Sjkh /* Nope - do it now */ 104382Sjkh else { 105102383Sobrien /* Is it an ftp://foo.bar.baz/file.t[bg]z specification? */ 1068083Sjkh if (isURL(pkg)) { 107194497Sbrian if (!(where_to = fileGetURL(NULL, pkg, KeepPackage))) { 10881046Ssobomax warnx("unable to fetch '%s' by URL", pkg); 1098083Sjkh return 1; 1108083Sjkh } 11111780Sjkh strcpy(pkg_fullname, pkg); 11211780Sjkh cfile = fopen(CONTENTS_FNAME, "r"); 11311780Sjkh if (!cfile) { 11430221Scharnier warnx( 11581046Ssobomax "unable to open table of contents file '%s' - not a package?", 11630221Scharnier CONTENTS_FNAME); 11711780Sjkh goto bomb; 11811780Sjkh } 11911780Sjkh read_plist(&Plist, cfile); 12011780Sjkh fclose(cfile); 121382Sjkh } 1228083Sjkh else { 12376739Ssobomax strcpy(pkg_fullname, pkg); /* 12476739Ssobomax * Copy for sanity's sake, 12576739Ssobomax * could remove pkg_fullname 12676739Ssobomax */ 12714582Sjkh if (strcmp(pkg, "-")) { 12814582Sjkh if (stat(pkg_fullname, &sb) == FAIL) { 12930221Scharnier warnx("can't stat package file '%s'", pkg_fullname); 13014582Sjkh goto bomb; 13114582Sjkh } 13214582Sjkh sprintf(extract_contents, "--fast-read %s", CONTENTS_FNAME); 13314582Sjkh extract = extract_contents; 13411780Sjkh } 13522750Sjkh else { 13614582Sjkh extract = NULL; 13722750Sjkh sb.st_size = 100000; /* Make up a plausible average size */ 13822750Sjkh } 139194497Sbrian if (!(where_to = make_playpen(playpen, sb.st_size * 4))) 140132799Sstefanf errx(1, "unable to make playpen for %lld bytes", (long long)sb.st_size * 4); 14138583Sjkh /* Since we can call ourselves recursively, keep notes on where we came from */ 14238583Sjkh if (!getenv("_TOP")) 143194497Sbrian setenv("_TOP", where_to, 1); 14414582Sjkh if (unpack(pkg_fullname, extract)) { 14530221Scharnier warnx( 14681046Ssobomax "unable to extract table of contents file from '%s' - not a package?", 14730221Scharnier pkg_fullname); 14811780Sjkh goto bomb; 14911780Sjkh } 15011780Sjkh cfile = fopen(CONTENTS_FNAME, "r"); 15111780Sjkh if (!cfile) { 15230221Scharnier warnx( 15381046Ssobomax "unable to open table of contents file '%s' - not a package?", 15430221Scharnier CONTENTS_FNAME); 15511780Sjkh goto bomb; 15611780Sjkh } 15711780Sjkh read_plist(&Plist, cfile); 15811780Sjkh fclose(cfile); 1597998Sjkh 16011780Sjkh /* Extract directly rather than moving? Oh goodie! */ 16111780Sjkh if (find_plist_option(&Plist, "extract-in-place")) { 16211780Sjkh if (Verbose) 16311780Sjkh printf("Doing in-place extraction for %s\n", pkg_fullname); 16411780Sjkh p = find_plist(&Plist, PLIST_CWD); 16511780Sjkh if (p) { 16611780Sjkh if (!isdir(p->name) && !Fake) { 16711780Sjkh if (Verbose) 16811780Sjkh printf("Desired prefix of %s does not exist, creating..\n", p->name); 169131285Seik vsystem("/bin/mkdir -p %s", p->name); 17011780Sjkh if (chdir(p->name) == -1) { 17181046Ssobomax warn("unable to change directory to '%s'", p->name); 17211780Sjkh goto bomb; 17311780Sjkh } 1747998Sjkh } 17511780Sjkh where_to = p->name; 17611780Sjkh inPlace = 1; 1777998Sjkh } 17811780Sjkh else { 17930221Scharnier warnx( 18081046Ssobomax "no prefix specified in '%s' - this is a bad package!", 18130221Scharnier pkg_fullname); 18211780Sjkh goto bomb; 18311780Sjkh } 1847998Sjkh } 18511780Sjkh 18611780Sjkh /* 18711780Sjkh * Apply a crude heuristic to see how much space the package will 18811780Sjkh * take up once it's unpacked. I've noticed that most packages 18911780Sjkh * compress an average of 75%, so multiply by 4 for good measure. 19011780Sjkh */ 19111780Sjkh 19293660Smurray if (!extract && !inPlace && min_free(playpen) < sb.st_size * 4) { 193132799Sstefanf warnx("projected size of %lld exceeds available free space.\n" 19430221Scharnier"Please set your PKG_TMPDIR variable to point to a location with more\n" 19584745Ssobomax "free space and try again", (long long)sb.st_size * 4); 19630221Scharnier warnx("not extracting %s\ninto %s, sorry!", 19730221Scharnier pkg_fullname, where_to); 1988083Sjkh goto bomb; 1997998Sjkh } 2009786Sjkh 20111780Sjkh /* If this is a direct extract and we didn't want it, stop now */ 20211780Sjkh if (inPlace && Fake) 20311780Sjkh goto success; 2047998Sjkh 20593660Smurray /* Finally unpack the whole mess. If extract is null we 20693660Smurray already + did so so don't bother doing it again. */ 20793660Smurray if (extract && unpack(pkg_fullname, NULL)) { 20881046Ssobomax warnx("unable to extract '%s'!", pkg_fullname); 20911780Sjkh goto bomb; 21011780Sjkh } 21111780Sjkh } 21214582Sjkh 21311780Sjkh /* Check for sanity and dependencies */ 21411780Sjkh if (sanity_check(pkg)) 2157998Sjkh goto bomb; 21611780Sjkh 21711780Sjkh /* If we're running in MASTER mode, just output the plist and return */ 21811780Sjkh if (AddMode == MASTER) { 21911780Sjkh printf("%s\n", where_playpen()); 22011780Sjkh write_plist(&Plist, stdout); 22111780Sjkh return 0; 2227996Sjkh } 22311780Sjkh } 224327Sjkh 22511780Sjkh /* 22611780Sjkh * If we have a prefix, delete the first one we see and add this 22711780Sjkh * one in place of it. 22811780Sjkh */ 22911780Sjkh if (Prefix) { 23011780Sjkh delete_plist(&Plist, FALSE, PLIST_CWD, NULL); 23111780Sjkh add_plist_top(&Plist, PLIST_CWD, Prefix); 23211780Sjkh } 2337998Sjkh 23411780Sjkh setenv(PKG_PREFIX_VNAME, (p = find_plist(&Plist, PLIST_CWD)) ? p->name : ".", 1); 23596613Ssobomax /* Protect against old packages with bogus @name and origin fields */ 23696613Ssobomax if (Plist.name == NULL) 23796613Ssobomax Plist.name = "anonymous"; 23896613Ssobomax if (Plist.origin == NULL) 23996613Ssobomax Plist.origin = "anonymous/anonymous"; 2407998Sjkh 24196613Ssobomax /* 24296613Ssobomax * See if we're already registered either with the same name (the same 24396613Ssobomax * version) or some other version with the same origin. 24496613Ssobomax */ 245131280Seik if ((isinstalledpkg(Plist.name) > 0 || 24696613Ssobomax matchbyorigin(Plist.origin, NULL) != NULL) && !Force) { 247156497Sphk warnx("package '%s' or its older version already installed%s", 248156497Sphk Plist.name, FailOnAlreadyInstalled ? "" : " (ignored)"); 249156497Sphk code = FailOnAlreadyInstalled != FALSE; 25011780Sjkh goto success; /* close enough for government work */ 25111780Sjkh } 2527998Sjkh 253113594Skris /* Now check the packing list for conflicts */ 254177741Srdivacky if (!IgnoreDeps){ 255113594Skris for (p = Plist.head; p != NULL; p = p->next) { 256113594Skris if (p->type == PLIST_CONFLICTS) { 257131280Seik int i; 258113594Skris conflict[0] = strdup(p->name); 259113594Skris conflict[1] = NULL; 260113594Skris matched = matchinstalled(MATCH_GLOB, conflict, &errcode); 261113594Skris free(conflict[0]); 262113594Skris if (errcode == 0 && matched != NULL) 263113594Skris for (i = 0; matched[i] != NULL; i++) 264131280Seik if (isinstalledpkg(matched[i]) > 0) { 265113594Skris warnx("package '%s' conflicts with %s", Plist.name, 266113594Skris matched[i]); 267113594Skris conflictsfound = 1; 268113594Skris } 269113594Skris 270113594Skris continue; 271113594Skris } 272113594Skris } 273113594Skris if(conflictsfound) { 274113594Skris if(!Force) { 275113594Skris warnx("please use pkg_delete first to remove conflicting package(s) or -f to force installation"); 276113594Skris code = 1; 277113594Skris goto bomb; 278113594Skris } else 279113594Skris warnx("-f specified; proceeding anyway"); 280113594Skris } 281113594Skris 282195346Sbrian#if ENSURE_THAT_ALL_REQUIREMENTS_ARE_MET 283194497Sbrian /* 284194497Sbrian * Before attempting to do the slave mode bit, ensure that we've 285194497Sbrian * downloaded & processed everything we need. 286194497Sbrian * It's possible that we haven't already installed all of our 287194497Sbrian * dependencies if the dependency list was misgenerated due to 288194497Sbrian * other dynamic dependencies or if a dependency was added to a 289194497Sbrian * package without all REQUIRED_BY packages being regenerated. 290194497Sbrian */ 291194497Sbrian for (p = pkg ? Plist.head : NULL; p; p = p->next) { 292194497Sbrian const char *ext; 293194497Sbrian char *deporigin; 294194497Sbrian 295194497Sbrian if (p->type != PLIST_PKGDEP) 296194497Sbrian continue; 297194497Sbrian deporigin = (p->next->type == PLIST_DEPORIGIN) ? p->next->name : NULL; 298194497Sbrian 299194497Sbrian if (isinstalledpkg(p->name) <= 0 && 300194497Sbrian !(deporigin != NULL && matchbyorigin(deporigin, NULL) != NULL)) { 301194497Sbrian char subpkg[FILENAME_MAX], *sep; 302194497Sbrian 303194497Sbrian strlcpy(subpkg, pkg, sizeof subpkg); 304194497Sbrian if ((sep = strrchr(subpkg, '/')) != NULL) { 305194497Sbrian *sep = '\0'; 306194497Sbrian if ((sep = strrchr(subpkg, '/')) != NULL) { 307194497Sbrian *sep = '\0'; 308194497Sbrian strlcat(subpkg, "/All/", sizeof subpkg); 309194497Sbrian strlcat(subpkg, p->name, sizeof subpkg); 310236333Sjpaetzel if ((ext = strrchr(pkg, '.')) == NULL) { 311236333Sjpaetzel if (getenv("PACKAGESUFFIX")) 312236333Sjpaetzel ext = getenv("PACKAGESUFFIX"); 313236333Sjpaetzel else 314236333Sjpaetzel ext = ".tbz"; 315236333Sjpaetzel } 316194497Sbrian strlcat(subpkg, ext, sizeof subpkg); 317194497Sbrian pkg_do(subpkg); 318194497Sbrian } 319194497Sbrian } 320194497Sbrian } 321194497Sbrian } 322195346Sbrian#endif 323194497Sbrian 32411780Sjkh /* Now check the packing list for dependencies */ 32511780Sjkh for (p = Plist.head; p ; p = p->next) { 32696613Ssobomax char *deporigin; 32796613Ssobomax 32811780Sjkh if (p->type != PLIST_PKGDEP) 32911780Sjkh continue; 33096613Ssobomax deporigin = (p->next->type == PLIST_DEPORIGIN) ? p->next->name : NULL; 33196613Ssobomax if (Verbose) { 33296613Ssobomax printf("Package '%s' depends on '%s'", Plist.name, p->name); 33396613Ssobomax if (deporigin != NULL) 33496613Ssobomax printf(" with '%s' origin", deporigin); 33596613Ssobomax printf(".\n"); 33696613Ssobomax } 337131280Seik if (isinstalledpkg(p->name) <= 0 && 33896613Ssobomax !(deporigin != NULL && matchbyorigin(deporigin, NULL) != NULL)) { 339194497Sbrian char path[FILENAME_MAX]; 340194497Sbrian const char *cp = NULL; 3418083Sjkh 342177741Srdivacky if (!Fake) { 343152329Skrion char prefixArg[2 + MAXPATHLEN]; /* "-P" + Prefix */ 344152329Skrion if (PrefixRecursive) { 345152329Skrion strlcpy(prefixArg, "-P", sizeof(prefixArg)); 346152329Skrion strlcat(prefixArg, Prefix, sizeof(prefixArg)); 347152329Skrion } 34818929Sjkh if (!isURL(pkg) && !getenv("PKG_ADD_BASE")) { 349102888Ssobomax const char *ext; 350102888Ssobomax 351102888Ssobomax ext = strrchr(pkg_fullname, '.'); 352236333Sjpaetzel if (ext == NULL) { 353236333Sjpaetzel if (getenv("PACKAGESUFFIX")) { 354236333Sjpaetzel ext = getenv("PACKAGESUFFIX"); 355236333Sjpaetzel } else { 356236333Sjpaetzel ext = ".tbz"; 357236333Sjpaetzel } 358236333Sjpaetzel } 359102888Ssobomax snprintf(path, FILENAME_MAX, "%s/%s%s", getenv("_TOP"), p->name, ext); 36018929Sjkh if (fexists(path)) 36118929Sjkh cp = path; 36218929Sjkh else 36318929Sjkh cp = fileFindByPath(pkg, p->name); 36418929Sjkh if (cp) { 36518929Sjkh if (Verbose) 36618929Sjkh printf("Loading it from %s.\n", cp); 367152329Skrion if (vsystem("%s %s %s '%s'", PkgAddCmd, Verbose ? "-v " : "", PrefixRecursive ? prefixArg : "", cp)) { 36881046Ssobomax warnx("autoload of dependency '%s' failed%s", 36930221Scharnier cp, Force ? " (proceeding anyway)" : "!"); 37018929Sjkh if (!Force) 37118929Sjkh ++code; 37218929Sjkh } 37318929Sjkh } 37438931Sjkh else { 37538931Sjkh warnx("could not find package %s %s", 37638931Sjkh p->name, Force ? " (proceeding anyway)" : "!"); 37738931Sjkh if (!Force) 37838931Sjkh ++code; 37938931Sjkh } 38018929Sjkh } 381154145Sflz else if ((cp = fileGetURL(pkg, p->name, KeepPackage)) != NULL) { 3828075Sjkh if (Verbose) 383194497Sbrian printf("Finished loading %s via a URL\n", p->name); 38418929Sjkh if (!fexists("+CONTENTS")) { 38530221Scharnier warnx("autoloaded package %s has no +CONTENTS file?", 38630221Scharnier p->name); 3878075Sjkh if (!Force) 3888075Sjkh ++code; 3898075Sjkh } 390179760Sflz else if (vsystem("(pwd; /bin/cat +CONTENTS) | %s %s %s %s -S", PkgAddCmd, Verbose ? "-v" : "", PrefixRecursive ? prefixArg : "", KeepPackage ? "-K" : "")) { 39181046Ssobomax warnx("pkg_add of dependency '%s' failed%s", 39230221Scharnier p->name, Force ? " (proceeding anyway)" : "!"); 39318929Sjkh if (!Force) 39418929Sjkh ++code; 39518929Sjkh } 39618929Sjkh else if (Verbose) 39781046Ssobomax printf("\t'%s' loaded successfully.\n", p->name); 39818929Sjkh /* Nuke the temporary playpen */ 39933427Sjkh leave_playpen(); 4008075Sjkh } 40111780Sjkh } 40211780Sjkh else { 40311780Sjkh if (Verbose) 40411780Sjkh printf("and was not found%s.\n", Force ? " (proceeding anyway)" : ""); 40511780Sjkh else 40611780Sjkh printf("Package dependency %s for %s not found%s\n", p->name, pkg, 40711780Sjkh Force ? " (proceeding anyway)" : "!"); 40811780Sjkh if (!Force) 40911780Sjkh ++code; 41011780Sjkh } 4118075Sjkh } 41211780Sjkh else if (Verbose) 41311780Sjkh printf(" - already installed.\n"); 414327Sjkh } 415177741Srdivacky } /* if (!IgnoreDeps) */ 4167713Sjkh 41716087Sjkh if (code != 0) 41816087Sjkh goto bomb; 41916087Sjkh 4208075Sjkh /* Look for the requirements file */ 421206043Sflz if ((fd = open(REQUIRE_FNAME, O_RDWR)) != -1) { 422206043Sflz fstat(fd, &sb); 423206043Sflz fchmod(fd, sb.st_mode | S_IXALL); /* be sure, chmod a+x */ 424206043Sflz close(fd); 425327Sjkh if (Verbose) 42696613Ssobomax printf("Running requirements file first for %s..\n", Plist.name); 42796613Ssobomax if (!Fake && vsystem("./%s %s INSTALL", REQUIRE_FNAME, Plist.name)) { 42830221Scharnier warnx("package %s fails requirements %s", pkg_fullname, 42930221Scharnier Force ? "installing anyway" : "- not installed"); 4304996Sjkh if (!Force) { 4314996Sjkh code = 1; 4324996Sjkh goto success; /* close enough for government work */ 4334996Sjkh } 434327Sjkh } 435327Sjkh } 4368075Sjkh 43776739Ssobomax /* 43876739Ssobomax * Test whether to use the old method of passing tokens to installation 43941866Sjkh * scripts, and set appropriate variables.. 44041866Sjkh */ 44141866Sjkh 44241866Sjkh if (fexists(POST_INSTALL_FNAME)) { 44341866Sjkh new_m = 1; 44441866Sjkh sprintf(post_script, "%s", POST_INSTALL_FNAME); 44549637Sbillf pre_arg[0] = '\0'; 44649637Sbillf post_arg[0] = '\0'; 44741866Sjkh } else { 44841866Sjkh if (fexists(INSTALL_FNAME)) { 44941866Sjkh sprintf(post_script, "%s", INSTALL_FNAME); 45041866Sjkh sprintf(pre_arg, "PRE-INSTALL"); 45141866Sjkh sprintf(post_arg, "POST-INSTALL"); 45241866Sjkh } 45341866Sjkh } 45441866Sjkh 4558075Sjkh /* If we're really installing, and have an installation file, run it */ 456206043Sflz if (!NoInstall && (fd = open(pre_script, O_RDWR)) != -1) { 457206043Sflz fstat(fd, &sb); 458206043Sflz fchmod(fd, sb.st_mode | S_IXALL); /* be sure, chmod a+x */ 459206043Sflz close(fd); 460327Sjkh if (Verbose) 46196613Ssobomax printf("Running pre-install for %s..\n", Plist.name); 46296613Ssobomax if (!Fake && vsystem("./%s %s %s", pre_script, Plist.name, pre_arg)) { 46330221Scharnier warnx("install script returned error status"); 46441866Sjkh unlink(pre_script); 4654996Sjkh code = 1; 4664996Sjkh goto success; /* nothing to uninstall yet */ 467327Sjkh } 468327Sjkh } 4698075Sjkh 4708075Sjkh /* Now finally extract the entire show if we're not going direct */ 47111780Sjkh if (!inPlace && !Fake) 47211780Sjkh extract_plist(".", &Plist); 4738075Sjkh 4748075Sjkh if (!Fake && fexists(MTREE_FNAME)) { 4754996Sjkh if (Verbose) 47696613Ssobomax printf("Running mtree for %s..\n", Plist.name); 4774996Sjkh p = find_plist(&Plist, PLIST_CWD); 4784996Sjkh if (Verbose) 47969793Sobrien printf("mtree -U -f %s -d -e -p %s >%s\n", MTREE_FNAME, p ? p->name : "/", _PATH_DEVNULL); 4808115Sjkh if (!Fake) { 48171055Ssobomax if (vsystem("/usr/sbin/mtree -U -f %s -d -e -p %s >%s", MTREE_FNAME, p ? p->name : "/", _PATH_DEVNULL)) 48230221Scharnier warnx("mtree returned a non-zero status - continuing"); 4838115Sjkh } 4844996Sjkh } 4858075Sjkh 4868083Sjkh /* Run the installation script one last time? */ 487206043Sflz if (!NoInstall && (fd = open(post_script, O_RDWR)) != -1) { 488206043Sflz fstat(fd, &sb); 489206043Sflz fchmod(fd, sb.st_mode | S_IXALL); /* be sure, chmod a+x */ 490206043Sflz close(fd); 491327Sjkh if (Verbose) 49296613Ssobomax printf("Running post-install for %s..\n", Plist.name); 49396613Ssobomax if (!Fake && vsystem("./%s %s %s", post_script, Plist.name, post_arg)) { 49430221Scharnier warnx("install script returned error status"); 49541866Sjkh unlink(post_script); 4964996Sjkh code = 1; 497327Sjkh goto fail; 498327Sjkh } 499327Sjkh } 5008075Sjkh 5018083Sjkh /* Time to record the deed? */ 502327Sjkh if (!NoRecord && !Fake) { 503382Sjkh char contents[FILENAME_MAX]; 504178753Spav char **depnames = NULL, **deporigins = NULL, ***depmatches; 505178103Spav int i, dep_count = 0; 50684745Ssobomax FILE *contfile; 507382Sjkh 508327Sjkh if (getuid() != 0) 50930221Scharnier warnx("not running as root - trying to record install anyway"); 51096613Ssobomax sprintf(LogDir, "%s/%s", LOG_DIR, Plist.name); 51137728Seivind zapLogDir = 1; 512327Sjkh if (Verbose) 513327Sjkh printf("Attempting to record package into %s..\n", LogDir); 514240476Sjkim if (make_hierarchy(LogDir, FALSE)) { 51530221Scharnier warnx("can't record package into '%s', you're on your own!", 516327Sjkh LogDir); 517327Sjkh bzero(LogDir, FILENAME_MAX); 518327Sjkh code = 1; 519327Sjkh goto success; /* close enough for government work */ 520327Sjkh } 521477Sjkh /* Make sure pkg_info can read the entry */ 522206043Sflz fd = open(LogDir, O_RDWR); 523206043Sflz fstat(fd, &sb); 524206043Sflz fchmod(fd, sb.st_mode | S_IRALL | S_IXALL); /* be sure, chmod a+rx */ 525206043Sflz close(fd); 52684670Ssobomax move_file(".", DESC_FNAME, LogDir); 52784670Ssobomax move_file(".", COMMENT_FNAME, LogDir); 52884670Ssobomax if (fexists(INSTALL_FNAME)) 52984670Ssobomax move_file(".", INSTALL_FNAME, LogDir); 53084670Ssobomax if (fexists(POST_INSTALL_FNAME)) 53184670Ssobomax move_file(".", POST_INSTALL_FNAME, LogDir); 532327Sjkh if (fexists(DEINSTALL_FNAME)) 5337998Sjkh move_file(".", DEINSTALL_FNAME, LogDir); 53441866Sjkh if (fexists(POST_DEINSTALL_FNAME)) 53541866Sjkh move_file(".", POST_DEINSTALL_FNAME, LogDir); 536327Sjkh if (fexists(REQUIRE_FNAME)) 5377998Sjkh move_file(".", REQUIRE_FNAME, LogDir); 53884670Ssobomax if (fexists(DISPLAY_FNAME)) 53984670Ssobomax move_file(".", DISPLAY_FNAME, LogDir); 54084670Ssobomax if (fexists(MTREE_FNAME)) 54184670Ssobomax move_file(".", MTREE_FNAME, LogDir); 542382Sjkh sprintf(contents, "%s/%s", LogDir, CONTENTS_FNAME); 54384745Ssobomax contfile = fopen(contents, "w"); 54484745Ssobomax if (!contfile) { 54530221Scharnier warnx("can't open new contents file '%s'! can't register pkg", 54630221Scharnier contents); 547382Sjkh goto success; /* can't log, but still keep pkg */ 548382Sjkh } 54984745Ssobomax write_plist(&Plist, contfile); 55084745Ssobomax fclose(contfile); 5514996Sjkh for (p = Plist.head; p ; p = p->next) { 552178103Spav char *deporigin; 55396613Ssobomax 5544996Sjkh if (p->type != PLIST_PKGDEP) 5554996Sjkh continue; 55696613Ssobomax deporigin = (p->next->type == PLIST_DEPORIGIN) ? p->next->name : 55796613Ssobomax NULL; 55896613Ssobomax if (Verbose) { 55996613Ssobomax printf("Trying to record dependency on package '%s'", p->name); 56096613Ssobomax if (deporigin != NULL) 56196613Ssobomax printf(" with '%s' origin", deporigin); 56296613Ssobomax printf(".\n"); 5634996Sjkh } 56496613Ssobomax 565178103Spav if (deporigin) { 566178103Spav /* Defer to origin lookup */ 567178103Spav depnames = realloc(depnames, (dep_count + 1) * sizeof(*depnames)); 568178103Spav depnames[dep_count] = p->name; 569178103Spav deporigins = realloc(deporigins, (dep_count + 2) * sizeof(*deporigins)); 570178103Spav deporigins[dep_count] = deporigin; 571178103Spav deporigins[dep_count + 1] = NULL; 572178103Spav dep_count++; 573178103Spav } else { 574178103Spav /* No origin recorded, try to register on literal package name */ 575178103Spav sprintf(contents, "%s/%s/%s", LOG_DIR, p->name, 576178103Spav REQUIRED_BY_FNAME); 577178103Spav contfile = fopen(contents, "a"); 578178103Spav if (!contfile) { 579178103Spav warnx("can't open dependency file '%s'!\n" 580178103Spav "dependency registration is incomplete", contents); 581178103Spav } else { 582178103Spav fprintf(contfile, "%s\n", Plist.name); 583178103Spav if (fclose(contfile) == EOF) { 584178103Spav warnx("cannot properly close file %s", contents); 585178103Spav } 586178103Spav } 58796613Ssobomax } 588178103Spav } 589178103Spav if (dep_count > 0) { 590178103Spav depmatches = matchallbyorigin((const char **)deporigins, NULL); 591178103Spav free(deporigins); 592178103Spav if (!IgnoreDeps && depmatches) { 593178103Spav for (i = 0; i < dep_count; i++) { 594178103Spav if (depmatches[i]) { 595178753Spav int j; 596178753Spav char **tmp = depmatches[i]; 597178753Spav for (j = 0; tmp[j] != NULL; j++) { 598178753Spav /* Origin looked up */ 599178753Spav sprintf(contents, "%s/%s/%s", LOG_DIR, tmp[j], 600178753Spav REQUIRED_BY_FNAME); 601178753Spav if (depnames[i] && strcmp(depnames[i], tmp[j]) != 0) 602178753Spav warnx("warning: package '%s' requires '%s', but '%s' " 603178753Spav "is installed", Plist.name, depnames[i], tmp[j]); 604178753Spav contfile = fopen(contents, "a"); 605178753Spav if (!contfile) { 606178753Spav warnx("can't open dependency file '%s'!\n" 607178753Spav "dependency registration is incomplete", contents); 608178753Spav } else { 609178753Spav fprintf(contfile, "%s\n", Plist.name); 610178753Spav if (fclose(contfile) == EOF) 611178753Spav warnx("cannot properly close file %s", contents); 612178753Spav } 613178103Spav } 614178103Spav } else if (depnames[i]) { 615178103Spav /* No package present with this origin, try literal package name */ 616178103Spav sprintf(contents, "%s/%s/%s", LOG_DIR, depnames[i], 617178103Spav REQUIRED_BY_FNAME); 618178103Spav contfile = fopen(contents, "a"); 619178103Spav if (!contfile) { 620178103Spav warnx("can't open dependency file '%s'!\n" 621178103Spav "dependency registration is incomplete", contents); 622178103Spav } else { 623178103Spav fprintf(contfile, "%s\n", Plist.name); 624178103Spav if (fclose(contfile) == EOF) { 625178103Spav warnx("cannot properly close file %s", contents); 626178103Spav } 627178103Spav } 628178103Spav } 62996613Ssobomax } 63096613Ssobomax } 6314996Sjkh } 632327Sjkh if (Verbose) 63396613Ssobomax printf("Package %s registered in %s\n", Plist.name, LogDir); 634327Sjkh } 6358857Srgrimes 63616549Sjkh if ((p = find_plist(&Plist, PLIST_DISPLAY)) != NULL) { 6374996Sjkh FILE *fp; 6384996Sjkh char buf[BUFSIZ]; 63916549Sjkh 64021650Sjkh snprintf(buf, sizeof buf, "%s/%s", LogDir, p->name); 64121650Sjkh fp = fopen(buf, "r"); 6424996Sjkh if (fp) { 6434996Sjkh putc('\n', stdout); 6444996Sjkh while (fgets(buf, sizeof(buf), fp)) 6454996Sjkh fputs(buf, stdout); 6464996Sjkh putc('\n', stdout); 6474996Sjkh (void) fclose(fp); 648154145Sflz } else { 649154145Sflz if (!Fake) { 650154145Sflz warnx("cannot open %s as display file", buf); 651154145Sflz } 652154145Sflz } 6534996Sjkh } 6544996Sjkh 655327Sjkh goto success; 656327Sjkh 6577998Sjkh bomb: 6587998Sjkh code = 1; 6597998Sjkh goto success; 6607998Sjkh 661327Sjkh fail: 6624996Sjkh /* Nuke the whole (installed) show, XXX but don't clean directories */ 663327Sjkh if (!Fake) 6644996Sjkh delete_package(FALSE, FALSE, &Plist); 665327Sjkh 666327Sjkh success: 667327Sjkh /* delete the packing list contents */ 66811780Sjkh free_plist(&Plist); 66933427Sjkh leave_playpen(); 670327Sjkh return code; 671327Sjkh} 672327Sjkh 673327Sjkhstatic int 674327Sjkhsanity_check(char *pkg) 675327Sjkh{ 6768075Sjkh int code = 0; 6778075Sjkh 678327Sjkh if (!fexists(CONTENTS_FNAME)) { 67930221Scharnier warnx("package %s has no CONTENTS file!", pkg); 6808075Sjkh code = 1; 681327Sjkh } 6828075Sjkh else if (!fexists(COMMENT_FNAME)) { 68330221Scharnier warnx("package %s has no COMMENT file!", pkg); 6848075Sjkh code = 1; 685327Sjkh } 6868075Sjkh else if (!fexists(DESC_FNAME)) { 68730221Scharnier warnx("package %s has no DESC file!", pkg); 6888075Sjkh code = 1; 689327Sjkh } 6908075Sjkh return code; 691327Sjkh} 692327Sjkh 693327Sjkhvoid 69439068Sjkhcleanup(int sig) 695327Sjkh{ 69633427Sjkh static int in_cleanup = 0; 69733427Sjkh 69833427Sjkh if (!in_cleanup) { 69933427Sjkh in_cleanup = 1; 70039068Sjkh if (sig) 70139068Sjkh printf("Signal %d received, cleaning up..\n", sig); 70237728Seivind if (!Fake && zapLogDir && LogDir[0]) 70339068Sjkh vsystem("%s -rf %s", REMOVE_CMD, LogDir); 704194497Sbrian while (leave_playpen()) 705194497Sbrian ; 70633427Sjkh } 70739068Sjkh if (sig) 70839068Sjkh exit(1); 709327Sjkh} 710