From owner-p4-projects@FreeBSD.ORG Sun Jul 18 21:59:12 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id EEA821065677; Sun, 18 Jul 2010 21:59:11 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B275A1065673 for ; Sun, 18 Jul 2010 21:59:11 +0000 (UTC) (envelope-from jlaffaye@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 9E9918FC13 for ; Sun, 18 Jul 2010 21:59:11 +0000 (UTC) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id o6ILxB53023262 for ; Sun, 18 Jul 2010 21:59:11 GMT (envelope-from jlaffaye@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id o6ILxBSq023260 for perforce@freebsd.org; Sun, 18 Jul 2010 21:59:11 GMT (envelope-from jlaffaye@FreeBSD.org) Date: Sun, 18 Jul 2010 21:59:11 GMT Message-Id: <201007182159.o6ILxBSq023260@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to jlaffaye@FreeBSD.org using -f From: Julien Laffaye To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 181154 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 18 Jul 2010 21:59:12 -0000 http://p4web.freebsd.org/@@181154?ac=10 Change 181154 by jlaffaye@jlaffaye-chulak on 2010/07/18 21:58:13 Work In Progress!! First step using libarchive(3) instead of tar(1). The code needs to be more tested, especially with flags such as Fake. TODO: - Download the file in pkg_do() if it is an url - Read from stdin if the name is "-" in pkg_do() - Re-implement cleanup() - Find packages for dependencies in extract_package() - Add complete package support in pkg_do() - Slave/Master mode?! in pkg_do() Affected files ... .. //depot/projects/soc2010/pkg_complete/usr.sbin/pkg_install/add/Makefile#2 edit .. //depot/projects/soc2010/pkg_complete/usr.sbin/pkg_install/add/add.h#2 edit .. //depot/projects/soc2010/pkg_complete/usr.sbin/pkg_install/add/extract.c#2 edit .. //depot/projects/soc2010/pkg_complete/usr.sbin/pkg_install/add/futil.c#2 edit .. //depot/projects/soc2010/pkg_complete/usr.sbin/pkg_install/add/perform.c#3 edit .. //depot/projects/soc2010/pkg_complete/usr.sbin/pkg_install/complete/perform.c#6 edit Differences ... ==== //depot/projects/soc2010/pkg_complete/usr.sbin/pkg_install/add/Makefile#2 (text+ko) ==== @@ -14,7 +14,7 @@ LIBPKG_INSTALL= ${.OBJDIR}/../lib/libpkg_install.a -DPADD+= ${LIBPKG_INSTALL} -LPADD+= ${LIBPKG_INSTALL} +DPADD+= ${LIBPKG_INSTALL} ${LIBARCHIVE} +LPADD+= ${LIBPKG_INSTALL} -larchive .include ==== //depot/projects/soc2010/pkg_complete/usr.sbin/pkg_install/add/add.h#2 (text+ko) ==== @@ -42,7 +42,7 @@ extern add_mode_t AddMode; int make_hierarchy(char *); -void extract_plist(const char *, Package *); void apply_perms(const char *, const char *); +int extract_package(const char *pkg); #endif /* _INST_ADD_H_INCLUDE */ ==== //depot/projects/soc2010/pkg_complete/usr.sbin/pkg_install/add/extract.c#2 (text+ko) ==== @@ -21,255 +21,620 @@ #include __FBSDID("$FreeBSD: src/usr.sbin/pkg_install/add/extract.c,v 1.46 2010/04/23 11:07:43 flz Exp $"); +#include +#include +#include #include #include +#include #include + #include "add.h" -#define STARTSTRING "/usr/bin/tar cf -" -#define TOOBIG(str) \ - (((int)strlen(str) + FILENAME_MAX + where_count > maxargs) ||\ - ((int)strlen(str) + FILENAME_MAX + perm_count > maxargs)) +int extract_package(const char *fname) +{ + Package pkg; + PackingList p; + struct archive *a; + struct archive_entry *entry; + ssize_t sz; + char *plist_buf; + int retcode; -#define PUSHOUT(todir) /* push out string */ \ - if (where_count > (int)sizeof(STARTSTRING)-1) { \ - strcat(where_args, "|/usr/bin/tar --unlink -xpPf - -C "); \ - strcat(where_args, todir); \ - if (system(where_args)) { \ - errx(EXIT_FAILURE, "%s: can not invoke %ld byte tar pipeline: %s", \ - __func__, (long)strlen(where_args), where_args); \ - } \ - strcpy(where_args, STARTSTRING); \ - where_count = sizeof(STARTSTRING)-1; \ - } \ - if (perm_count) { \ - apply_perms(todir, perm_args); \ - perm_args[0] = 0;\ - perm_count = 0; \ - } + char **matched; + char *conflict[2]; + int conflictsfound = 0; + int code = 0; + int errcode = 0; + char cmd[FILENAME_MAX]; + char db_dir_tmp[FILENAME_MAX]; + char db_dir[FILENAME_MAX]; + char pre_script[FILENAME_MAX] = INSTALL_FNAME; + char post_script[FILENAME_MAX]; + char pre_arg[FILENAME_MAX]; + char post_arg[FILENAME_MAX]; + char *prefix = NULL; + char *last_file = NULL; + char *last_dir = NULL; + int fd; + struct stat sb; -static void -rollback(const char *name, const char *home, PackingList start, PackingList stop) -{ - PackingList q; - char try[FILENAME_MAX], bup[FILENAME_MAX]; - const char *dir; - char *prefix = NULL; + a = archive_read_new(); + archive_read_support_compression_all(a); + archive_read_support_format_tar(a); + if (archive_read_open_filename(a, fname, 10240) != ARCHIVE_OK) { + warnx("Can not open archive: %s", archive_error_string(a)); + return (1); + } - dir = home; - for (q = start; q != stop; q = q->next) { - if (q->type == PLIST_FILE) { - snprintf(try, FILENAME_MAX, "%s/%s", dir, q->name); - if (make_preserve_name(bup, FILENAME_MAX, name, try) && fexists(bup)) { - (void)chflags(try, 0); - (void)unlink(try); - if (rename(bup, try)) - warnx("rollback: unable to rename %s back to %s", bup, try); + /* Extract the plist in memory */ + if ((retcode = archive_read_next_header(a, &entry)) == ARCHIVE_OK) { + if (strcmp(archive_entry_pathname(entry), CONTENTS_FNAME) == 0){ + sz = archive_entry_size(entry); + if ((plist_buf = malloc(sz+1)) == NULL) + err(EXIT_FAILURE, NULL); + if (archive_read_data(a, plist_buf, sz) != sz) { + warnx("Can not read plist: %s", archive_error_string(a)); + return (1); + } + plist_buf[sz] = '\0'; + } else { + warnx(CONTENTS_FNAME " not found - bad package!"); + return (1); } + } else if (retcode == ARCHIVE_EOF) { + warnx("Archive is empty - bad package!"); + return (1); + } else { + warnx("Can not read archive: %s - aborting", + archive_error_string(a)); + return (1); + } + + /* Parse the plist now so we can check the depends, etc */ + pkg.head = pkg.tail = NULL; + retcode = read_plist_from_buffer(&pkg, plist_buf, sz); + free(plist_buf); + if (retcode != 0) { + warnx("Unable to parse plist"); + return (1); } - else if (q->type == PLIST_CWD) { - if (!prefix) - prefix = q->name; - if (q->name == NULL) - q->name = prefix; - else if (strcmp(q->name, ".")) - dir = q->name; - else - dir = home; + + /* + * If we have a prefix, delete the first one we see and add this + * one in place of it. + */ + if (Prefix) { + delete_plist(&pkg, FALSE, PLIST_CWD, NULL); + if (add_plist_top(&pkg, PLIST_CWD, Prefix) == -1) + err(EXIT_FAILURE, "%s: add_plist_top failed", __func__); } - } -} + + setenv(PKG_PREFIX_VNAME, (p = find_plist(&pkg, PLIST_CWD)) ? p->name : + ".", 1); + /* Protect against old packages with bogus @name and origin fields */ + if (pkg.name == NULL) + pkg.name = "anonymous"; + if (pkg.origin == NULL) + pkg.origin = "anonymous/anonymous"; -#define add_char(buf, len, pos, ch) do {\ - if ((pos) < (len)) { \ - buf[(pos)] = (ch); \ - buf[(pos) + 1] = '\0'; \ - } \ - ++(pos); \ -} while (0) + /* + * See if we're already registered either with the same name (the same + * version) or some other version with the same origin. + */ + if ((isinstalledpkg(pkg.name) > 0 || + matchbyorigin(pkg.origin, NULL) != NULL) && !Force) { + warnx("package '%s' or its older version already installed%s", + pkg.name, FailOnAlreadyInstalled ? "" : " (ignored)"); + if (FailOnAlreadyInstalled == TRUE) + return (1); /* close enough for government work */ + } -static int -add_arg(char *buf, int len, const char *str) -{ - int i = 0; + /* Now check the packing list for conflicts */ + if (!IgnoreDeps) { + for (p = pkg.head; p != NULL; p = p->next) { + if (p->type == PLIST_CONFLICTS) { + int i; + conflict[0] = strdup(p->name); + conflict[1] = NULL; + matched = matchinstalled(MATCH_GLOB, conflict, &errcode); + free(conflict[0]); + if (errcode == 0 && matched != NULL) + for (i = 0; matched[i] != NULL; i++) + if (isinstalledpkg(matched[i]) > 0) { + warnx("package '%s' conflicts with %s", + pkg.name, matched[i]); + conflictsfound = 1; + } - add_char(buf, len, i, ' '); - for (; *str != '\0'; ++str) { - if (!isalnum(*str) && *str != '/' && *str != '.' && *str != '-') - add_char(buf, len, i, '\\'); - add_char(buf, len, i, *str); - } - return (i); -} + continue; + } + } + if(conflictsfound) { + if(!Force) { + warnx("please use pkg_delete first to remove conflicting " + "package(s) or -f to force installation"); + return (1); + } else + warnx("-f specified; proceeding anyway"); + } -void -extract_plist(const char *home, Package *pkg) -{ - PackingList p = pkg->head; - char *last_file, *prefix = NULL; - char *where_args, *perm_args, *last_chdir; - int maxargs, where_count = 0, perm_count = 0, add_count; - Boolean preserve; +#if ENSURE_THAT_ALL_REQUIREMENTS_ARE_MET + /* + * Before attempting to do the slave mode bit, ensure that we've + * downloaded & processed everything we need. + * It's possible that we haven't already installed all of our + * dependencies if the dependency list was misgenerated due to + * other dynamic dependencies or if a dependency was added to a + * package without all REQUIRED_BY packages being regenerated. + */ + for (p = pkg ? pkg.head : NULL; p; p = p->next) { + const char *ext; + char *deporigin; - maxargs = sysconf(_SC_ARG_MAX) / 2; /* Just use half the argument space */ - where_args = alloca(maxargs); - if (where_args == NULL) - err(EXIT_FAILURE, "%s: can't get argument list space", __func__); - perm_args = alloca(maxargs); - if (perm_args == NULL) - err(EXIT_FAILURE, "%s: can't get argument list space", __func__); + if (p->type != PLIST_PKGDEP) + continue; - strcpy(where_args, STARTSTRING); - where_count = sizeof(STARTSTRING)-1; - perm_args[0] = 0; + if (p->next->type == PLIST_DEPORIGIN) + deporigin = p->next->name; + else + deporigin = NULL; - last_chdir = 0; - preserve = find_plist_option(pkg, "preserve") ? TRUE : FALSE; + if (isinstalledpkg(p->name) <= 0 && + !(deporigin != NULL && matchbyorigin(deporigin, NULL) != NULL)){ + char subpkg[FILENAME_MAX], *sep; - /* Reset the world */ - Owner = NULL; - Group = NULL; - Mode = NULL; - last_file = NULL; - Directory = (char *)home; + strlcpy(subpkg, pkg, sizeof subpkg); + if ((sep = strrchr(subpkg, '/')) != NULL) { + *sep = '\0'; + if ((sep = strrchr(subpkg, '/')) != NULL) { + *sep = '\0'; + strlcat(subpkg, "/All/", sizeof subpkg); + strlcat(subpkg, p->name, sizeof subpkg); + if ((ext = strrchr(pkg, '.')) == NULL) + ext = ".tbz"; + strlcat(subpkg, ext, sizeof subpkg); + pkg_do(subpkg); + } + } + } + } +#endif - /* Do it */ - while (p) { - char cmd[FILENAME_MAX]; + /* Now check the packing list for dependencies */ + for (p = pkg.head; p ; p = p->next) { + char *deporigin; - switch(p->type) { - case PLIST_NAME: - PkgName = p->name; - if (Verbose) - printf("extract: Package name is %s\n", p->name); - break; + if (p->type != PLIST_PKGDEP) + continue; + deporigin = (p->next->type == PLIST_DEPORIGIN) ? p->next->name : NULL; + if (Verbose) { + printf("Package '%s' depends on '%s'", pkg.name, p->name); + if (deporigin != NULL) + printf(" with '%s' origin", deporigin); + printf(".\n"); + } +#if 0 + if (isinstalledpkg(p->name) <= 0 && + !(deporigin != NULL && matchbyorigin(deporigin, NULL) != NULL)) { + char path[FILENAME_MAX]; + const char *cp = NULL; - case PLIST_FILE: - last_file = p->name; - if (Verbose) - printf("extract: %s/%s\n", Directory, p->name); if (!Fake) { - char try[FILENAME_MAX]; + char prefixArg[2 + MAXPATHLEN]; /* "-P" + Prefix */ + if (PrefixRecursive) { + strlcpy(prefixArg, "-P", sizeof(prefixArg)); + strlcat(prefixArg, Prefix, sizeof(prefixArg)); + } + if (!isURL(pkg) && !getenv("PKG_ADD_BASE")) { + const char *ext; - /* first try to rename it into place */ - snprintf(try, FILENAME_MAX, "%s/%s", Directory, p->name); - if (fexists(try)) { - /* XXX hack - if truly immutable, rename fails */ - (void)chflags(try, 0); - if (preserve && PkgName) { - char pf[FILENAME_MAX]; - - if (make_preserve_name(pf, FILENAME_MAX, PkgName, try)) { - if (rename(try, pf)) { - warnx( - "unable to back up %s to %s, aborting pkg_add", - try, pf); - rollback(PkgName, home, pkg->head, p); - return; - } + ext = strrchr(pkg, '.'); + if (ext == NULL) + ext = ".tbz"; + snprintf(path, FILENAME_MAX, "%s/%s%s", getenv("_TOP"), + p->name, ext); + if (fexists(path)) + cp = path; + else + cp = fileFindByPath(pkg, p->name); + if (cp) { + if (Verbose) + printf("Loading it from %s.\n", cp); + if (vsystem("%s %s %s '%s'", PkgAddCmd, Verbose ? "-v " +: "", PrefixRecursive ? prefixArg : "", cp)) { + warnx("autoload of dependency '%s' failed%s", + cp, Force ? " (proceeding anyway)" : "!"); + if (!Force) + ++code; } } - } - if (rename(p->name, try) == 0) { - /* try to add to list of perms to be changed and run in bulk. */ - if (p->name[0] == '/' || TOOBIG(p->name)) { - PUSHOUT(Directory); + else { + warnx("could not find package %s %s", + p->name, Force ? " (proceeding anyway)" : "!"); + if (!Force) + ++code; } - add_count = add_arg(&perm_args[perm_count], - maxargs - perm_count, p->name); - if (add_count < 0 || add_count >= maxargs - perm_count) - errx(EXIT_FAILURE, "%s: oops, miscounted strings!", - __func__); - perm_count += add_count; } else { - /* rename failed, try copying with a big tar command */ - if (last_chdir != Directory) { - if (last_chdir == NULL) { - PUSHOUT(Directory); - } else { - PUSHOUT(last_chdir); + + if ((cp = fileGetURL(pkg, p->name, KeepPackage)) == NULL) { + cleanup(); + warnx("Getting pkg '%s' by URL failed", pkg); + goto bomb; + } else { + + if (Verbose) + printf("Finished loading %s via a URL\n", p->name); + if (!fexists(CONTENTS_FNAME)) { + warnx("autoloaded package %s has no %s file?", + p->name, CONTENTS_FNAME); + if (!Force) + ++code; + } + else if (vsystem("(pwd; /bin/cat " CONTENTS_FNAME + ") | %s %s %s %s -S", PkgAddCmd, + Verbose ? "-v" : "", + PrefixRecursive ? prefixArg : "", + KeepPackage ? "-K" : "")) { + warnx("pkg_add of dependency '%s' failed%s", + p->name, Force ? " (proceeding anyway)" : "!"); + if (!Force) + ++code; } - last_chdir = Directory; + else if (Verbose) + printf("\t'%s' loaded successfully.\n", p->name); + /* Nuke the temporary playpen */ + leave_playpen(); + } - else if (p->name[0] == '/' || TOOBIG(p->name)) { - PUSHOUT(Directory); - } - add_count = add_arg(&where_args[where_count], maxargs - where_count, p->name); - if (add_count < 0 || add_count >= maxargs - where_count) - errx(EXIT_FAILURE, "%s: oops, miscounted strings!", - __func__); - where_count += add_count; - add_count = add_arg(&perm_args[perm_count], maxargs - perm_count, p->name); - if (add_count < 0 || add_count >= maxargs - perm_count) - errx(EXIT_FAILURE, "%s: oops, miscounted strings!", - __func__); - perm_count += add_count; + + } + + } + else { + if (Verbose) + printf("and was not found%s.\n", + Force ? " (proceeding anyway)" : ""); + else + printf("Package dependency %s for %s not found%s\n", + p->name, pkg, Force ? " (proceeding anyway)" : "!"); + if (!Force) + ++code; + } + } + else if (Verbose) + printf(" - already installed.\n"); +#endif + } + } /* if (!IgnoreDeps) */ + + if (code != 0) + return (1); + + /* + * Create a temporary entry in LOG_DIR for the package. + * Extract the meta files into it now. + * Later, we will rename(2) the directory to validate the installation. + */ + snprintf(db_dir_tmp, sizeof(db_dir_tmp), "%s/.%s", LOG_DIR, pkg.name); + snprintf(db_dir, sizeof(db_dir), "%s/%s", LOG_DIR, pkg.name); + if (make_hierarchy(db_dir_tmp) == -1) { + warnx("Can not create '%s' directory - aborting", db_dir_tmp); + return (1); + } + if (chdir(db_dir_tmp) == -1) { + warn("chdir(%s) - aborting", db_dir_tmp); + vsystem("%s -rf %s", REMOVE_CMD, db_dir_tmp); + return (1); + } + for (p = pkg.head; p; p = p->next) + if (p->type == PLIST_IGNORE) { + if (archive_read_next_header(a, &entry) == ARCHIVE_OK) { + /* XXX: temporary assert */ + assert(strcmp(p->next->name, + archive_entry_pathname(entry)) == 0); + archive_read_extract(a, entry, ARCHIVE_EXTRACT_PERM); + } else { + warnx("Can not read archive: %s - aborting", + archive_error_string(a)); + vsystem("%s -rf %s", REMOVE_CMD, db_dir_tmp); + return (1); + } + } + + /* Look for the requirements file */ + if ((fd = open(REQUIRE_FNAME, O_RDWR)) != -1) { + fstat(fd, &sb); + fchmod(fd, sb.st_mode | S_IXALL); /* be sure, chmod a+x */ + close(fd); + if (Verbose) + printf("Running requirements file first for %s..\n", + pkg.name); + if (!Fake && vsystem("./%s %s INSTALL", REQUIRE_FNAME, pkg.name)){ + warnx("package %s fails requirements %s", pkg.name, + Force ? "installing anyway" : "- not installed"); + if (!Force) { + vsystem("%s -rf %s", REMOVE_CMD, db_dir_tmp); + return (1); } } + } + + /* + * Test whether to use the old method of passing tokens to installation + * scripts, and set appropriate variables.. + */ + if (fexists(POST_INSTALL_FNAME)) { + sprintf(post_script, "%s", POST_INSTALL_FNAME); + pre_arg[0] = '\0'; + post_arg[0] = '\0'; + } else { + if (fexists(INSTALL_FNAME)) { + sprintf(post_script, "%s", INSTALL_FNAME); + sprintf(pre_arg, "PRE-INSTALL"); + sprintf(post_arg, "POST-INSTALL"); + } + } + + /* If we're really installing, and have an installation file, run it */ + if (!NoInstall && (fd = open(pre_script, O_RDWR)) != -1) { + fstat(fd, &sb); + fchmod(fd, sb.st_mode | S_IXALL); /* be sure, chmod a+x */ + close(fd); + if (Verbose) + printf("Running pre-install for %s..\n", pkg.name); + if (!Fake && vsystem("./%s %s %s", pre_script, pkg.name, pre_arg)) { + warnx("install script returned error status - aborting"); + vsystem("%s -rf %s", REMOVE_CMD, db_dir_tmp); + return (1); + } + } + + /* Install it, yay! */ + for (p = pkg.head; p; p = p->next) { + switch (p->type) { + case PLIST_NAME: + if (Verbose) + printf("extract: Package name is %s\n", p->name); break; + case PLIST_FILE: + if (Verbose) + printf("extract: %s/%s\n", last_dir, p->name); + if (archive_read_next_header(a, &entry) == ARCHIVE_OK) { + assert(strcmp(p->name, archive_entry_pathname(entry)) == 0); + archive_read_extract(a, entry, ARCHIVE_EXTRACT_PERM); + } else { + warnx("Can not read archive: %s", archive_error_string(a)); + return (1); + } + last_file = p->name; + break; - case PLIST_CWD: - if (!prefix) - prefix = p->name; - if (p->name == NULL) - p->name = strdup(prefix); + case PLIST_CWD: + if (prefix == NULL) + prefix = p->name; + if (p->name == NULL) + p->name = strdup(prefix); + if (Verbose) + printf("extract: CWD to %s\n", p->name); + if (!Fake && make_hierarchy(p->name) == -1) { + warnx("Can not create '%s' directory.", p->name); + return (1); + } + if (!Fake && chdir(p->name) == -1) { + warn("chdir(%s)", p->name); + return 1; + } + last_dir = p->name; + break; + + case PLIST_CMD: + if ((strstr(p->name, "%B") || strstr(p->name, "%F") || + strstr(p->name, "%f")) && last_file == NULL) + errx(EXIT_FAILURE, "%s: no last file specified for '%s' " + "command", __func__, p->name); + if (strstr(p->name, "%D") && last_dir == NULL) + errx(2, "%s: no directory specified for '%s' command", + __func__, p->name); + format_cmd(cmd, FILENAME_MAX, p->name, last_dir, last_file); + if (Verbose) + printf("extract: execute '%s'\n", cmd); + if (!Fake && system(cmd)) + warnx("command '%s' failed", cmd); + break; + + case PLIST_IGNORE: + p = p->next; + break; + + default: + break; + } + } + + /* + * Go back to the temporary entry in LOG_DIR to: + * execute the last scripts + * write the plist + */ + if (chdir(db_dir_tmp) == -1) { + warn("Can not chdir to '%s' - aborting", db_dir_tmp); + delete_package(FALSE, FALSE, &pkg); + vsystem("%s -rf %s", REMOVE_CMD, db_dir_tmp); + return (1); + } + + if (!Fake && fexists(MTREE_FNAME)) { + if (Verbose) + printf("Running mtree for %s..\n", pkg.name); + p = find_plist(&pkg, PLIST_CWD); if (Verbose) - printf("extract: CWD to %s\n", p->name); - PUSHOUT(Directory); - if (strcmp(p->name, ".")) { - if (!Fake && make_hierarchy(p->name) == -1) - errx(EXIT_FAILURE, "%s: unable to cwd to '%s'", __func__, - p->name); - Directory = p->name; + printf("mtree -U -f %s -d -e -p %s >%s\n", + MTREE_FNAME, p ? p->name : "/", _PATH_DEVNULL); + if (!Fake) { + if (vsystem("/usr/sbin/mtree -U -f %s -d -e -p %s >%s", + MTREE_FNAME, p ? p->name : "/", _PATH_DEVNULL)) + warnx("mtree returned a non-zero status - continuing"); } - else - Directory = (char *)home; - break; + } - case PLIST_CMD: - if ((strstr(p->name, "%B") || strstr(p->name, "%F") || - strstr(p->name, "%f")) && last_file == NULL) - errx(EXIT_FAILURE, "%s: no last file specified for '%s' " - "command", __func__, p->name); - if (strstr(p->name, "%D") && Directory == NULL) - errx(2, "%s: no directory specified for '%s' command", - __func__, p->name); - format_cmd(cmd, FILENAME_MAX, p->name, Directory, last_file); - PUSHOUT(Directory); + /* Run the installation script one last time? */ + if (!NoInstall && (fd = open(post_script, O_RDWR)) != -1) { + fstat(fd, &sb); + fchmod(fd, sb.st_mode | S_IXALL); /* be sure, chmod a+x */ + close(fd); if (Verbose) - printf("extract: execute '%s'\n", cmd); - if (!Fake && system(cmd)) - warnx("command '%s' failed", cmd); - break; + printf("Running post-install for %s..\n", pkg.name); + if (!Fake && vsystem("./%s %s %s", post_script, pkg.name, + post_arg)) { + warnx("install script returned error status - aborting"); + delete_package(FALSE, FALSE, &pkg); + vsystem("%s -rf %s", REMOVE_CMD, db_dir_tmp); + } + } - case PLIST_CHMOD: - PUSHOUT(Directory); - Mode = p->name; - break; + /* Time to record the deed? */ + if (!NoRecord && !Fake) { + FILE *contfile; + char contents[FILENAME_MAX]; + char **depnames = NULL, **deporigins = NULL, ***depmatches; + int i, dep_count = 0, rc; - case PLIST_CHOWN: - PUSHOUT(Directory); - Owner = p->name; - break; + sprintf(contents, "%s/%s", db_dir_tmp, CONTENTS_FNAME); + contfile = fopen(contents, "w"); + if (!contfile) { + warnx("can't open new contents file '%s'! can't register pkg", + contents); + return (1); /* can't log, but still keep pkg */ + } + rc = write_plist(&pkg, contfile); + fclose(contfile); + if (rc != 0) + return (1); + for (p = pkg.head; p ; p = p->next) { + char *deporigin; - case PLIST_CHGRP: - PUSHOUT(Directory); - Group = p->name; - break; + if (p->type != PLIST_PKGDEP) + continue; + if (p->next->type == PLIST_DEPORIGIN) + deporigin = p->next->name; + else + deporigin = NULL; + if (Verbose) { + printf("Trying to record dependency on package '%s'", + p->name); + if (deporigin != NULL) + printf(" with '%s' origin", deporigin); + printf(".\n"); + } - case PLIST_COMMENT: /* FALLTHROUGH */ - case PLIST_NOINST: - break; + if (deporigin) { + /* Defer to origin lookup */ + depnames = realloc(depnames, (dep_count + 1) * + sizeof(*depnames)); + depnames[dep_count] = p->name; + deporigins = realloc(deporigins, (dep_count + 2) * + sizeof(*deporigins)); + deporigins[dep_count] = deporigin; + deporigins[dep_count + 1] = NULL; + dep_count++; + } else { + /* + * No origin recorded, try to register on + * literal package name + */ + sprintf(contents, "%s/%s/%s", LOG_DIR, p->name, + REQUIRED_BY_FNAME); + contfile = fopen(contents, "a"); + if (!contfile) { + warnx("can't open dependency file '%s'!\n" + "dependency registration is incomplete", + contents); + } else { + fprintf(contfile, "%s\n", pkg.name); + if (fclose(contfile) == EOF) { + warnx("cannot properly close file %s", contents); + } + } + } + } + if (dep_count > 0) { + depmatches = matchallbyorigin((const char **)deporigins, NULL); + free(deporigins); + if (!IgnoreDeps && depmatches) { + for (i = 0; i < dep_count; i++) { + if (depmatches[i]) { + int j; + char **tmp = depmatches[i]; + for (j = 0; tmp[j] != NULL; j++) { + /* Origin looked up */ + sprintf(contents, "%s/%s/%s", LOG_DIR, tmp[j], + REQUIRED_BY_FNAME); + if (depnames[i] && strcmp(depnames[i], tmp[j]) + != 0) + warnx("warning: package '%s' requires '%s'," + " but '%s' is installed", pkg.name, + depnames[i], tmp[j]); + contfile = fopen(contents, "a"); + if (!contfile) { + warnx("can't open dependency file '%s'!\n" + "dependency registration is " + "incomplete", contents); + } else { + fprintf(contfile, "%s\n", pkg.name); + if (fclose(contfile) == EOF) + warnx("cannot properly close file %s", + contents); + } + } + } else if (depnames[i]) { + /* + * No package present with this origin, + * try literal package name + */ + sprintf(contents, "%s/%s/%s", LOG_DIR, depnames[i], + REQUIRED_BY_FNAME); + contfile = fopen(contents, "a"); + if (!contfile) { + warnx("can't open dependency file '%s'!\n" + "dependency registration is incomplete", + contents); + } else { + fprintf(contfile, "%s\n", pkg.name); + if (fclose(contfile) == EOF) { + warnx("cannot properly close file %s", + contents); + } + } + } + } + } + } + /* Atomically register the package */ + if (rename(db_dir_tmp, db_dir) == -1) + warn("Can not rename '%s' to '%s'", db_dir_tmp, db_dir); + else if (Verbose) + printf("Package %s registered in %s\n", pkg.name, db_dir); + } - case PLIST_IGNORE: - p = p->next; - break; + if ((p = find_plist(&pkg, PLIST_DISPLAY)) != NULL) { + FILE *fp; + char buf[BUFSIZ]; - default: - break; + snprintf(buf, sizeof buf, "%s/%s", db_dir_tmp, p->name); + fp = fopen(buf, "r"); + if (fp) { + putc('\n', stdout); + while (fgets(buf, sizeof(buf), fp)) + fputs(buf, stdout); + putc('\n', stdout); + (void) fclose(fp); + } else + warnx("cannot open %s as display file", buf); } - p = p->next; - } - PUSHOUT(Directory); + + archive_read_finish(a); + free_plist(&pkg); + return (0); } ==== //depot/projects/soc2010/pkg_complete/usr.sbin/pkg_install/add/futil.c#2 (text+ko) ==== @@ -94,4 +94,3 @@ if (vsystem("cd %s && /usr/bin/chgrp -R %s %s", cd_to, Group, arg)) warnx("couldn't change group of '%s' to '%s'", arg, Group); } - ==== //depot/projects/soc2010/pkg_complete/usr.sbin/pkg_install/add/perform.c#3 (text+ko) ==== @@ -32,11 +32,7 @@ void cleanup(void); static int pkg_do(char *); -static int sanity_check(char *); -static char LogDir[FILENAME_MAX]; -static int zapLogDir; /* Should we delete LogDir? */ - int pkg_perform(char **pkgs) { @@ -62,33 +58,15 @@ static int pkg_do(char *pkg) { - struct stat sb; - Package Plist; - PackingList p; - char playpen[FILENAME_MAX]; - char pre_script[FILENAME_MAX] = INSTALL_FNAME; - char post_script[FILENAME_MAX]; - char pre_arg[FILENAME_MAX], post_arg[FILENAME_MAX]; - char *conflict[2]; - char **matched; - const char *where_to; - int cfile; - int code; - int inPlace, conflictsfound, errcode; - int rc; - /* support for separate pre/post install scripts */ - int new_m = 0; - int fd; + /* + * TODO: + * dowload the package if it is an URL, read from stdin if "-" + * Deal with master/slave modes. + * add support for complete packages + */ + return extract_package(pkg); - conflictsfound = 0; - code = 0; - zapLogDir = 0; - LogDir[0] = '\0'; - strcpy(playpen, FirstPen); - inPlace = 0; - - memset(&Plist, '\0', sizeof(Plist)); - +# if 0 /* Are we coming in for a second pass, everything already extracted? */ if (!pkg) { fgets(playpen, FILENAME_MAX, stdin); @@ -130,18 +108,11 @@ */ Boolean extract_whole_archive_from_stdin = FALSE; - if (strcmp(pkg, "-") == 0) { + if (strcmp(pkg, "-") == 0) extract_whole_archive_from_stdin = TRUE; - sb.st_size = 100000; /* Make up a plausible average size */ - } else { - if (stat(pkg, &sb) == -1) { - warnx("can't stat package file '%s'", pkg); - goto bomb; - } - } - if ((where_to = make_playpen(playpen, sb.st_size * 4)) == NULL) - err(1, "unable to make playpen for %lld bytes", (long long)sb.st_size * 4); - /* Since we can call ourselves recursively, keep notes on where we came from */ + + /* Since we can call ourselves recursively, keep notes on where we +came from */ if (!getenv("_TOP")) setenv("_TOP", where_to, 1); if (extract_whole_archive_from_stdin == TRUE) { @@ -150,7 +121,6 @@ else { warnx("unable to extract table of contents file from '%s' " "- not a package?", pkg); - goto bomb; } } else cfile = unpack_to_fd(pkg, CONTENTS_FNAME); @@ -164,63 +134,8 @@ (void) close(cfile); if (rc != 0) goto bomb; - - /* Extract directly rather than moving? Oh goodie! */ - if (find_plist_option(&Plist, "extract-in-place")) { - if (Verbose) - printf("Doing in-place extraction for %s\n", pkg); - p = find_plist(&Plist, PLIST_CWD); - if (p) { - if (!isdir(p->name) && !Fake) { - if (Verbose) - printf("Desired prefix of %s does not exist, creating..\n", p->name); - vsystem("/bin/mkdir -p %s", p->name); - if (chdir(p->name) == -1) { - warn("unable to change directory to '%s'", p->name); - goto bomb; - } - } - where_to = p->name; - inPlace = 1; - } - else { - warnx("no prefix specified in '%s' - this is a bad " - "package!", pkg); >>> TRUNCATED FOR MAIL (1000 lines) <<<