Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 19 Jun 2009 17:07:38 +0000 (UTC)
From:      Brian Somers <brian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r194497 - in head/usr.sbin/pkg_install: add create info lib
Message-ID:  <200906191707.n5JH7c2Q049387@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: brian
Date: Fri Jun 19 17:07:38 2009
New Revision: 194497
URL: http://svn.freebsd.org/changeset/base/194497

Log:
  When running pkg_add -r, check & install our dependencies for each
  package rather than expecting our top level package to get all of
  the dependencies correct.
  
  Previously, the code depended on the top level package having all
  of the pkgdep lines in +CONTENTS correct and in the right order,
  but that doesn't always happen due to code such as this (in
  security/gnutls/Makefile):
  
      .if (defined(WITH_LZO) || exists(${LOCALBASE}/lib/liblzo2.so)) && !defined(WITHOUT_LZO)
      LIB_DEPENDS+=           lzo2:${PORTSDIR}/archivers/lzo2
      ....
  
  With such conditional dependencies, my 'sophox-packages' package won't
  install.  The dependency tree looks like this:
  
      sophox-packages
        ...
        x11/gnome2
          x11/gnome-applets
            net/libgweather
              devel/libsoup
                security/gnutls
                  security/libgcrypt
                    security/libgpg-error
        ...
        x11/gnome2
          archivers/file-roller
            archivers/gtar
              archivers/lzop
                archivers/lzo2
        ...
  
  gnutls doesn't depend on lzo2 initially, but lzo2 is dragged into the
  mix via other dependencies and is built by the initial 'make'.  The
  subsequent package generation for gnutls adds a pkgdep line for lzo2
  to gnutls' +CONTENTS but the pkgdeps in sophox-packages' +CONTENTS
  has gnutls *before* lzo2.
  
  As a result, sophox-packages cannot install; gnutls fails because lzo2
  is missing, 82 more packages fail because gnutls is missing and the
  whole thing spirals into a super-confusing mess!
  
  MFC after:	3 weeks

Modified:
  head/usr.sbin/pkg_install/add/perform.c
  head/usr.sbin/pkg_install/create/perform.c
  head/usr.sbin/pkg_install/info/perform.c
  head/usr.sbin/pkg_install/lib/lib.h
  head/usr.sbin/pkg_install/lib/pen.c
  head/usr.sbin/pkg_install/lib/url.c

Modified: head/usr.sbin/pkg_install/add/perform.c
==============================================================================
--- head/usr.sbin/pkg_install/add/perform.c	Fri Jun 19 17:07:15 2009	(r194496)
+++ head/usr.sbin/pkg_install/add/perform.c	Fri Jun 19 17:07:38 2009	(r194497)
@@ -52,9 +52,6 @@ pkg_perform(char **pkgs)
     return err_cnt;
 }
 
-static Package Plist;
-static char *Home;
-
 /*
  * This is seriously ugly code following.  Written very fast!
  * [And subsequently made even worse..  Sigh!  This code was just born
@@ -63,10 +60,12 @@ static char *Home;
 static int
 pkg_do(char *pkg)
 {
+    Package Plist;
     char pkg_fullname[FILENAME_MAX];
     char playpen[FILENAME_MAX];
     char extract_contents[FILENAME_MAX];
-    char *where_to, *extract;
+    char *extract;
+    const char *where_to;
     FILE *cfile;
     int code;
     PackingList p;
@@ -87,6 +86,8 @@ pkg_do(char *pkg)
     strcpy(playpen, FirstPen);
     inPlace = 0;
 
+    memset(&Plist, '\0', sizeof(Plist));
+
     /* Are we coming in for a second pass, everything already extracted? */
     if (!pkg) {
 	fgets(playpen, FILENAME_MAX, stdin);
@@ -102,11 +103,10 @@ pkg_do(char *pkg)
     else {
 	/* Is it an ftp://foo.bar.baz/file.t[bg]z specification? */
 	if (isURL(pkg)) {
-	    if (!(Home = fileGetURL(NULL, pkg, KeepPackage))) {
+	    if (!(where_to = fileGetURL(NULL, pkg, KeepPackage))) {
 		warnx("unable to fetch '%s' by URL", pkg);
 		return 1;
 	    }
-	    where_to = Home;
 	    strcpy(pkg_fullname, pkg);
 	    cfile = fopen(CONTENTS_FNAME, "r");
 	    if (!cfile) {
@@ -135,13 +135,11 @@ pkg_do(char *pkg)
 		extract = NULL;
 		sb.st_size = 100000;	/* Make up a plausible average size */
 	    }
-	    Home = make_playpen(playpen, sb.st_size * 4);
-	    if (!Home)
+	    if (!(where_to = make_playpen(playpen, sb.st_size * 4)))
 		errx(1, "unable to make playpen for %lld bytes", (long long)sb.st_size * 4);
-	    where_to = Home;
 	    /* Since we can call ourselves recursively, keep notes on where we came from */
 	    if (!getenv("_TOP"))
-		setenv("_TOP", Home, 1);
+		setenv("_TOP", where_to, 1);
 	    if (unpack(pkg_fullname, extract)) {
 		warnx(
 	"unable to extract table of contents file from '%s' - not a package?",
@@ -280,6 +278,42 @@ pkg_do(char *pkg)
 	    warnx("-f specified; proceeding anyway");
     }
 
+    /*
+     * 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 ? Plist.head : NULL; p; p = p->next) {
+	const char *ext;
+	char *deporigin;
+
+	if (p->type != PLIST_PKGDEP)
+	    continue;
+	deporigin = (p->next->type == PLIST_DEPORIGIN) ? p->next->name : NULL;
+
+	if (isinstalledpkg(p->name) <= 0 &&
+	    !(deporigin != NULL && matchbyorigin(deporigin, NULL) != NULL)) {
+	    char subpkg[FILENAME_MAX], *sep;
+
+	    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);
+		}
+	    }
+	}
+    }
+
     /* Now check the packing list for dependencies */
     for (p = Plist.head; p ; p = p->next) {
 	char *deporigin;
@@ -295,7 +329,8 @@ pkg_do(char *pkg)
 	}
 	if (isinstalledpkg(p->name) <= 0 &&
 	    !(deporigin != NULL && matchbyorigin(deporigin, NULL) != NULL)) {
-	    char path[FILENAME_MAX], *cp = NULL;
+	    char path[FILENAME_MAX];
+	    const char *cp = NULL;
 
 	    if (!Fake) {
 		char prefixArg[2 + MAXPATHLEN]; /* "-P" + Prefix */
@@ -333,7 +368,7 @@ pkg_do(char *pkg)
 		}
 		else if ((cp = fileGetURL(pkg, p->name, KeepPackage)) != NULL) {
 		    if (Verbose)
-			printf("Finished loading %s over FTP.\n", p->name);
+			printf("Finished loading %s via a URL\n", p->name);
 		    if (!fexists("+CONTENTS")) {
 			warnx("autoloaded package %s has no +CONTENTS file?",
 				p->name);
@@ -645,7 +680,8 @@ cleanup(int sig)
 	    printf("Signal %d received, cleaning up..\n", sig);
     	if (!Fake && zapLogDir && LogDir[0])
 	    vsystem("%s -rf %s", REMOVE_CMD, LogDir);
-    	leave_playpen();
+    	while (leave_playpen())
+	    ;
     }
     if (sig)
 	exit(1);

Modified: head/usr.sbin/pkg_install/create/perform.c
==============================================================================
--- head/usr.sbin/pkg_install/create/perform.c	Fri Jun 19 17:07:15 2009	(r194496)
+++ head/usr.sbin/pkg_install/create/perform.c	Fri Jun 19 17:07:38 2009	(r194497)
@@ -39,11 +39,10 @@ static void make_dist(const char *, cons
 static int create_from_installed_recursive(const char *, const char *);
 static int create_from_installed(const char *, const char *, const char *);
 
-static char *home;
-
 int
 pkg_perform(char **pkgs)
 {
+    static const char *home;
     char *pkg = *pkgs;		/* Only one arg to create */
     char *cp;
     FILE *pkg_in, *fp;

Modified: head/usr.sbin/pkg_install/info/perform.c
==============================================================================
--- head/usr.sbin/pkg_install/info/perform.c	Fri Jun 19 17:07:15 2009	(r194496)
+++ head/usr.sbin/pkg_install/info/perform.c	Fri Jun 19 17:07:38 2009	(r194497)
@@ -85,8 +85,6 @@ pkg_perform(char **pkgs)
     return err_cnt;
 }
 
-static char *Home;
-
 static int
 pkg_do(char *pkg)
 {
@@ -96,7 +94,7 @@ pkg_do(char *pkg)
     Package plist;
     FILE *fp;
     struct stat sb;
-    char *cp = NULL;
+    const char *cp = NULL;
     int code = 0;
 
     if (isURL(pkg)) {
@@ -138,7 +136,7 @@ pkg_do(char *pkg)
 	        code = 1;
 	        goto bail;
 	    }
-	    Home = make_playpen(PlayPen, sb.st_size / 2);
+	    make_playpen(PlayPen, sb.st_size / 2);
 	    if (unpack(fname, "'+*'")) {
 		warnx("error during unpacking, no info for '%s' available", pkg);
 		code = 1;

Modified: head/usr.sbin/pkg_install/lib/lib.h
==============================================================================
--- head/usr.sbin/pkg_install/lib/lib.h	Fri Jun 19 17:07:15 2009	(r194496)
+++ head/usr.sbin/pkg_install/lib/lib.h	Fri Jun 19 17:07:38 2009	(r194497)
@@ -159,9 +159,9 @@ STAILQ_HEAD(reqr_by_head, reqr_by_entry)
 int		vsystem(const char *, ...);
 char		*vpipe(const char *, ...);
 void		cleanup(int);
-char		*make_playpen(char *, off_t);
+const char	*make_playpen(char *, off_t);
 char		*where_playpen(void);
-void		leave_playpen(void);
+int		leave_playpen(void);
 off_t		min_free(const char *);
 
 /* String */
@@ -183,7 +183,7 @@ Boolean		isfile(const char *);
 Boolean		isempty(const char *);
 Boolean		issymlink(const char *);
 Boolean		isURL(const char *);
-char		*fileGetURL(const char *, const char *, int);
+const char	*fileGetURL(const char *, const char *, int);
 char		*fileFindByPath(const char *, const char *);
 char		*fileGetContents(const char *);
 void		write_file(const char *, const char *);

Modified: head/usr.sbin/pkg_install/lib/pen.c
==============================================================================
--- head/usr.sbin/pkg_install/lib/pen.c	Fri Jun 19 17:07:15 2009	(r194496)
+++ head/usr.sbin/pkg_install/lib/pen.c	Fri Jun 19 17:07:38 2009	(r194497)
@@ -31,7 +31,6 @@ __FBSDID("$FreeBSD$");
 
 /* For keeping track of where we are */
 static char PenLocation[FILENAME_MAX];
-static char Previous[FILENAME_MAX];
 
 char *
 where_playpen(void)
@@ -76,12 +75,14 @@ find_play_pen(char *pen, off_t sz)
 static char *pstack[MAX_STACK];
 static int pdepth = -1;
 
-static void
+static const char *
 pushPen(const char *pen)
 {
     if (++pdepth == MAX_STACK)
 	errx(2, "%s: stack overflow.\n", __func__);
     pstack[pdepth] = strdup(pen);
+
+    return pstack[pdepth];
 }
 
 static void
@@ -99,10 +100,11 @@ popPen(char *pen)
  * Make a temporary directory to play in and chdir() to it, returning
  * pathname of previous working directory.
  */
-char *
+const char *
 make_playpen(char *pen, off_t sz)
 {
     char humbuf1[6], humbuf2[6];
+    char cwd[FILENAME_MAX];
 
     if (!find_play_pen(pen, sz))
 	return NULL;
@@ -134,7 +136,7 @@ make_playpen(char *pen, off_t sz)
 	     "with more space and\ntry the command again", __func__, pen);
     }
 
-    if (!getcwd(Previous, FILENAME_MAX)) {
+    if (!getcwd(cwd, FILENAME_MAX)) {
 	upchuck("getcwd");
 	return NULL;
     }
@@ -144,34 +146,35 @@ make_playpen(char *pen, off_t sz)
 	errx(2, "%s: can't chdir to '%s'", __func__, pen);
     }
 
-    if (PenLocation[0])
-	pushPen(PenLocation);
-
     strcpy(PenLocation, pen);
-    return Previous;
+    return pushPen(cwd);
 }
 
 /* Convenience routine for getting out of playpen */
-void
+int
 leave_playpen()
 {
+    static char left[FILENAME_MAX];
     void (*oldsig)(int);
 
+    if (!PenLocation[0])
+	return 0;
+
     /* Don't interrupt while we're cleaning up */
     oldsig = signal(SIGINT, SIG_IGN);
-    if (Previous[0]) {
-	if (chdir(Previous) == FAIL) {
-	    cleanup(0);
-	    errx(2, "%s: can't chdir back to '%s'", __func__, Previous);
-	}
-	Previous[0] = '\0';
-    }
-    if (PenLocation[0]) {
-	if (PenLocation[0] == '/' && vsystem("/bin/rm -rf %s", PenLocation))
-	    warnx("couldn't remove temporary dir '%s'", PenLocation);
-	popPen(PenLocation);
+    strcpy(left, PenLocation);
+    popPen(PenLocation);
+
+    if (chdir(PenLocation) == FAIL) {
+	cleanup(0);
+	errx(2, "%s: can't chdir back to '%s'", __func__, PenLocation);
     }
+
+    if (left[0] == '/' && vsystem("/bin/rm -rf %s", left))
+	warnx("couldn't remove temporary dir '%s'", left);
     signal(SIGINT, oldsig);
+
+    return 1;
 }
 
 off_t

Modified: head/usr.sbin/pkg_install/lib/url.c
==============================================================================
--- head/usr.sbin/pkg_install/lib/url.c	Fri Jun 19 17:07:15 2009	(r194496)
+++ head/usr.sbin/pkg_install/lib/url.c	Fri Jun 19 17:07:38 2009	(r194497)
@@ -32,10 +32,11 @@ __FBSDID("$FreeBSD$");
  * Try and fetch a file by URL, returning the directory name for where
  * it's unpacked, if successful.
  */
-char *
+const char *
 fileGetURL(const char *base, const char *spec, int keep_package)
 {
-    char *cp, *rp, *tmp;
+    const char *rp;
+    char *cp, *tmp;
     char fname[FILENAME_MAX];
     char pen[FILENAME_MAX];
     char pkg[FILENAME_MAX];



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