Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 22 Jul 2010 21:30:03 GMT
From:      Julien Laffaye <jlaffaye@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 181342 for review
Message-ID:  <201007222130.o6MLU38S027960@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@181342?ac=10

Change 181342 by jlaffaye@jlaffaye-chulak on 2010/07/22 21:30:01

	Refactor to welcome (on an other iteration):
	  * on the fly installation from an URL
	  * complete package support

Affected files ...

.. //depot/projects/soc2010/pkg_complete/usr.sbin/pkg_install/add/add.h#3 edit
.. //depot/projects/soc2010/pkg_complete/usr.sbin/pkg_install/add/extract.c#5 edit
.. //depot/projects/soc2010/pkg_complete/usr.sbin/pkg_install/add/perform.c#4 edit

Differences ...

==== //depot/projects/soc2010/pkg_complete/usr.sbin/pkg_install/add/add.h#3 (text+ko) ====

@@ -38,11 +38,11 @@
 extern char	*Directory;
 extern char	*PkgName;
 extern char	*PkgAddCmd;
-extern char	FirstPen[];
 extern add_mode_t AddMode;
 
-int		make_hierarchy(char *);
-void		apply_perms(const char *, const char *);
-int		extract_package(const char *pkg);
+int	make_hierarchy(char *);
+void	apply_perms(const char *, const char *);
+int	extract_package(struct archive *, Package *);
+int	extract_plist(struct archive *, struct archive_entry *, Package *);
 
 #endif	/* _INST_ADD_H_INCLUDE */

==== //depot/projects/soc2010/pkg_complete/usr.sbin/pkg_install/add/extract.c#5 (text+ko) ====

@@ -31,16 +31,39 @@
 
 #include "add.h"
 
-int extract_package(const char *fname)
+int
+extract_plist(struct archive *a, struct archive_entry *entry, Package *pkg) {
+	char *plist_buf;
+	ssize_t s;
+	int retcode;
+
+	assert(strcmp(archive_entry_pathname(entry), CONTENTS_FNAME) == 0);
+
+	s = archive_entry_size(entry);
+	if ((plist_buf = malloc(s+1)) == NULL)
+	    err(EXIT_FAILURE, "malloc()");
+	if (archive_read_data(a, plist_buf, s) != s) {
+	    warnx("Can not extract plist: %s", archive_error_string(a));
+	    return (1);
+	}
+	plist_buf[s] = '\0';
+
+	pkg->head = pkg->tail = NULL;
+	retcode = read_plist_from_buffer(pkg, plist_buf, s);
+	free(plist_buf);
+	if (retcode != 0) {
+	    warnx("Unable to parse plist!");
+	    return (1);
+	}
+
+	return (0);
+}
+
+int
+extract_package(struct archive *a, Package *pkg)
 {
-	Package pkg;
 	PackingList p;
-	struct archive *a;
 	struct archive_entry *entry;
-	ssize_t sz;
-	char *plist_buf;
-	int retcode;
-
 	char **matched;
 	char *conflict[2];
 	Boolean conflictsfound = FALSE;
@@ -59,80 +82,39 @@
 	int fd;
 	struct stat sb;
 
-	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);
-	}
-
-	/* 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);
-	}
-
 	/*
 	* 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)
+	    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 :
+	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";
+	if (pkg->name == NULL)
+	    pkg->name = "anonymous";
+	if (pkg->origin == NULL)
+	    pkg->origin = "anonymous/anonymous";
 
 	/*
 	* 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) {
+	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)");
+		pkg->name, FailOnAlreadyInstalled ? "" : " (ignored)");
 	    if (FailOnAlreadyInstalled == TRUE)
 		return (1);
 	}
 
 	/* Now check the packing list for conflicts */
 	if (!IgnoreDeps) {
-	    for (p = pkg.head; p != NULL; p = p->next) {
+	    for (p = pkg->head; p != NULL; p = p->next) {
 		if (p->type == PLIST_CONFLICTS) {
 		    int i;
 		    conflict[0] = strdup(p->name);
@@ -143,7 +125,7 @@
 			for (i = 0; matched[i] != NULL; i++)
 			    if (isinstalledpkg(matched[i]) > 0) {
 				warnx("package '%s' conflicts with %s",
-				      pkg.name, matched[i]);
+				      pkg->name, matched[i]);
 				conflictsfound = TRUE;
 			    }
 		}
@@ -166,7 +148,7 @@
 	* 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) {
+	for (p = pkg ? pkg->head : NULL; p; p = p->next) {
 	    const char *ext;
 	    char *deporigin;
 
@@ -200,14 +182,14 @@
 #endif
 
     /* Now check the packing list for dependencies */
-    for (p = pkg.head; p ; p = p->next) {
+    for (p = pkg->head; p ; p = p->next) {
 	char *deporigin;
 
 	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);
+	    printf("Package '%s' depends on '%s'", pkg->name, p->name);
 	    if (deporigin != NULL)
 		printf(" with '%s' origin", deporigin);
 	    printf(".\n");
@@ -315,8 +297,8 @@
 	 * 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);
+	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);
@@ -326,7 +308,7 @@
 	    vsystem("%s -rf %s", REMOVE_CMD, db_dir_tmp);
 	    return (1);
 	}
-	for (p = pkg.head; p; p = p->next)
+	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 */
@@ -348,9 +330,9 @@
 	    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,
+		       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);
@@ -380,8 +362,8 @@
 	    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)) {
+		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);
@@ -389,7 +371,7 @@
 	}
 
 	/* Install it, yay! */
-	for (p = pkg.head; p; p = p->next) {
+	for (p = pkg->head; p; p = p->next) {
 	    switch (p->type) {
 	    case PLIST_NAME:
 		if (Verbose)
@@ -464,15 +446,15 @@
 	 */
 	if (chdir(db_dir_tmp) == -1) {
 	    warn("Can not chdir to '%s' - aborting", db_dir_tmp);
-	    delete_package(FALSE, FALSE, &pkg);
+	    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);
+		printf("Running mtree for %s..\n", pkg->name);
+	    p = find_plist(pkg, PLIST_CWD);
 	    if (Verbose)
 		printf("mtree -U -f %s -d -e -p %s >%s\n", 
 			MTREE_FNAME, p ? p->name    : "/", _PATH_DEVNULL);
@@ -489,11 +471,11 @@
 	    fchmod(fd, sb.st_mode | S_IXALL);	/* be sure, chmod a+x */
 	    close(fd);
 	    if (Verbose)
-		printf("Running post-install for %s..\n", pkg.name);
-	    if (!Fake && vsystem("./%s %s %s", post_script, pkg.name,
+		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);
+		delete_package(FALSE, FALSE, pkg);
 		vsystem("%s -rf %s", REMOVE_CMD, db_dir_tmp);
 	    }
 	}
@@ -512,11 +494,11 @@
 		    contents);
 		return (1); /* can't log, but still keep pkg */
 	    }
-	    rc = write_plist(&pkg, contfile);
+	    rc = write_plist(pkg, contfile);
 	    fclose(contfile);
 	    if (rc != 0)
 		return (1);
-	    for (p = pkg.head; p ; p = p->next) {
+	    for (p = pkg->head; p ; p = p->next) {
 		char *deporigin;
 
 		if (p->type != PLIST_PKGDEP)
@@ -556,7 +538,7 @@
 			      "dependency registration is incomplete",
 			      contents);
 		    } else {
-			fprintf(contfile, "%s\n", pkg.name);
+			fprintf(contfile, "%s\n", pkg->name);
 			if (fclose(contfile) == EOF) {
 			    warnx("cannot properly close file %s", contents);
 			}
@@ -578,7 +560,7 @@
 				if (depnames[i] && strcmp(depnames[i], tmp[j])
 				    != 0)
 				    warnx("warning: package '%s' requires '%s',"
-					  " but '%s' is installed", pkg.name,
+					  " but '%s' is installed", pkg->name,
 					  depnames[i], tmp[j]);
 				contfile = fopen(contents, "a");
 				if (!contfile) {
@@ -586,7 +568,7 @@
 					  "dependency registration is "
 					  "incomplete", contents);
 				} else {
-				    fprintf(contfile, "%s\n", pkg.name);
+				    fprintf(contfile, "%s\n", pkg->name);
 				    if (fclose(contfile) == EOF)
 					warnx("cannot properly close file %s",
 					      contents);
@@ -605,7 +587,7 @@
 				      "dependency registration is incomplete",
 				      contents);
 			    } else {
-				fprintf(contfile, "%s\n", pkg.name);
+				fprintf(contfile, "%s\n", pkg->name);
 				if (fclose(contfile) == EOF) {
 				    warnx("cannot properly close file %s",
 					  contents);
@@ -619,10 +601,10 @@
 	    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);
+		printf("Package %s registered in %s\n", pkg->name, db_dir);
 	}
 
-	if ((p = find_plist(&pkg, PLIST_DISPLAY)) != NULL) {
+	if ((p = find_plist(pkg, PLIST_DISPLAY)) != NULL) {
 	    FILE *fp;
 	    char buf[BUFSIZ];
 
@@ -638,7 +620,5 @@
 		warnx("cannot open %s as display file", buf);
 	}
 
-	archive_read_finish(a);
-	free_plist(&pkg);
 	return (0);
 }

==== //depot/projects/soc2010/pkg_complete/usr.sbin/pkg_install/add/perform.c#4 (text+ko) ====

@@ -22,6 +22,8 @@
 __FBSDID("$FreeBSD: src/usr.sbin/pkg_install/add/perform.c,v 1.90 2010/04/23 11:07:43 flz Exp $");
 
 #include <sys/wait.h>
+#include <archive.h>
+#include <archive_entry.h>
 #include <err.h>
 #include <libgen.h>
 #include <paths.h>
@@ -51,20 +53,72 @@
 }
 
 /*
- * This is seriously ugly code following.  Written very fast!
- * [And subsequently made even worse..  Sigh!  This code was just born
- * to be hacked, I guess.. :) -jkh]
+ * pkg_do() takes a package filename (on local disk, or an url scheme)
+ * as first parameter and install it.
+ * Returns 0 on success, 1 otherwise.
  */
 static int
-pkg_do(char *pkg)
+pkg_do(char *fname)
 {
+	Package pkg;
+	struct archive *a = NULL;
+	struct archive_entry *entry;
+	const char *pathname;
+	int retcode = 0;
+
+	a = archive_read_new();
+	archive_read_support_compression_all(a);
+	archive_read_support_format_tar(a);
+
 	/*
 	 * 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);
+	if (isURL(fname)) {
+	    /* TODO: add support */
+	    return (1);
+	} else {
+	    if (archive_read_open_filename(a, fname, 10240) != ARCHIVE_OK) {
+		warnx("Can not open '%s' archive: %s", fname,
+		      archive_error_string(a));
+		retcode = 1;
+		goto cleanup;
+	    }
+	}
+
+	if (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
+	    pathname = archive_entry_pathname(entry);
+	    if (strcmp(pathname, CONTENTS_FNAME) == 0) {
+		if (extract_plist(a, entry, &pkg) != 0) {
+		    warnx("Can not extract & parse " CONTENTS_FNAME);
+		    retcode = 1;
+		    goto cleanup;
+		}
+		extract_package(a, &pkg);
+	    } else if (strcmp(pathname, "+PKG_COMPLETE") == 0) {
+		if (Verbose)
+		    printf("'%s' is a complete package...\n", fname);
+		/* TODO: add support */
+	    } else {
+		warnx("Unknown package type!");
+		retcode = 1;
+		goto cleanup;
+	    }
+	} else {
+	    warnx("Can not read '%s' archive: %s", fname,
+		  archive_error_string(a));
+	    retcode = 1;
+	    goto cleanup;
+	}
+
+	cleanup:
+	if (a != NULL)
+	    archive_read_finish(a);
+	if (pkg.head != NULL)
+	    free_plist(&pkg);
+	return (retcode);
 
 # if 0
     /* Are we coming in for a second pass, everything already extracted? */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201007222130.o6MLU38S027960>