From owner-p4-projects@FreeBSD.ORG Thu Jul 22 21:30:04 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id C9BB0106566C; Thu, 22 Jul 2010 21:30:03 +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 756D1106567B for ; Thu, 22 Jul 2010 21:30:03 +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 6274E8FC25 for ; Thu, 22 Jul 2010 21:30:03 +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 o6MLU3Cx027962 for ; Thu, 22 Jul 2010 21:30:03 GMT (envelope-from jlaffaye@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id o6MLU38S027960 for perforce@freebsd.org; Thu, 22 Jul 2010 21:30:03 GMT (envelope-from jlaffaye@FreeBSD.org) Date: Thu, 22 Jul 2010 21:30:03 GMT Message-Id: <201007222130.o6MLU38S027960@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 181342 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: Thu, 22 Jul 2010 21:30:04 -0000 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 +#include +#include #include #include #include @@ -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? */