PERFORCE change 181154 for review
Julien Laffaye
jlaffaye at FreeBSD.org
Sun Jul 18 21:59:12 UTC 2010
http://p4web.freebsd.org/@@181154?ac=10
Change 181154 by jlaffaye at 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 <bsd.prog.mk>
==== //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 <sys/cdefs.h>
__FBSDID("$FreeBSD: src/usr.sbin/pkg_install/add/extract.c,v 1.46 2010/04/23 11:07:43 flz Exp $");
+#include <archive.h>
+#include <archive_entry.h>
+#include <assert.h>
#include <ctype.h>
#include <err.h>
+#include <paths.h>
#include <pkg.h>
+
#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) <<<
More information about the p4-projects
mailing list