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