bin/75742: [patch] pkg_add does not honour prefix for dependency packages

Frerich Raabe raabe at
Mon Jan 3 09:00:48 GMT 2005

>Number:         75742
>Category:       bin
>Synopsis:       [patch] pkg_add does not honour prefix for dependency packages
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Mon Jan 03 09:00:47 GMT 2005
>Originator:     Frerich Raabe
>Release:        FreeBSD 5.3-STABLE i386
System: FreeBSD icarus.lan 5.3-STABLE FreeBSD 5.3-STABLE #3: Thu Dec 30 07:40:26 CET 2004 frerich at icarus.lan:/usr/obj/usr/src/sys/IBMTPR51 i386
When installing a software package and passing the '-p' switch to pkg_add to
enforce installing the package into the given prefix, that prefix is not
taken into account for dependency packages. For instance, assuming package B
depends on package A, running 'pkg_add -p /foo B' will install B into /foo, but
not A.

This is particularly annoying for big packages with a lot of dependencies, such
as KDE. When trying to install KDE into a prefix, it's common to do something
like 'pkg_add -p /usr/local/kde kdenetwork' and assuming that all the other
KDE packages on which kdenetwork depends are installed in the same prefix. Since
this is not the case (the other KDE packages such as kdelibs will end up in
/usr/local), the KDE desktop is largely non-functional at runtime, and it's
nontrivial to trace this back to the fact that kdenetwork's dependencies were
not installed in the same prefix.
1.) Install any package (distcc in this example) and all of it's dependencies
    into some prefix (/tmp/x):
$ pkg_add -r -p /tmp/x distcc

2.) Check which packages distcc depends on
$ pkg_info -r distcc\*
Dependency: libiconv-1.9.2_1
Dependency: gettext-0.13.1_1
Dependency: popt-1.7

3.) Check where distcc's files reside
$ pkg_info -qL distcc\* | head -n 3

4.) Check where the files of the dependency packages reside:
$ pkg_info -qL libiconv\* | head -n 3

$ pkg_info -qL gettext\* | head -n 3

$ pkg_info -qL popt\* | head -n 3

5.) As one can see, distcc got installed into the /tmp/x prefix (as expected,
since -p /tmp/x was passed to pkg_add) but all three dependencies ended up in
/usr/local. If distcc would rely on those dependencies being in the same
prefix (as is the case for i.e. KDE), things could go wrong.

Since I didn't know whether it's always desireable to have -p use the given
prefix recursively for all dependencies, the patch given in the 'Fix' section
below introduces a new -P option which behaves just like -p except that the
prefix is propagated to dependency packages as well. The patch is to be applied
from within /usr/src.
diff -ruN usr.sbin/pkg_install/add.orig/add.h usr.sbin/pkg_install/add/add.h
--- usr.sbin/pkg_install/add.orig/add.h	Tue Jun 29 21:06:41 2004
+++ usr.sbin/pkg_install/add/add.h	Mon Jan  3 09:47:01 2005
@@ -26,6 +26,7 @@
 typedef enum { NORMAL, MASTER, SLAVE } add_mode_t;
 extern char	*Prefix;
+extern Boolean PrefixRecursive;
 extern Boolean	NoInstall;
 extern Boolean	NoRecord;
 extern char	*Mode;
diff -ruN usr.sbin/pkg_install/add.orig/main.c usr.sbin/pkg_install/add/main.c
--- usr.sbin/pkg_install/add.orig/main.c	Sun Nov 28 20:14:36 2004
+++ usr.sbin/pkg_install/add/main.c	Mon Jan  3 09:51:21 2005
@@ -27,9 +27,10 @@
 #include "lib.h"
 #include "add.h"
-static char Options[] = "hvIRfnrp:SMt:C:";
+static char Options[] = "hvIRfnrp:P:SMt:C:";
 char	*Prefix		= NULL;
+Boolean PrefixRecursive = FALSE;
 char	*Chroot		= NULL;
 Boolean	NoInstall	= FALSE;
 Boolean	NoRecord	= FALSE;
@@ -105,6 +106,12 @@
 	case 'p':
 	    Prefix = optarg;
+	    PrefixRecursive = FALSE;
+	    break;
+	case 'P':
+	    Prefix = optarg;
+	    PrefixRecursive = TRUE;
 	case 'I':
diff -ruN usr.sbin/pkg_install/add.orig/perform.c usr.sbin/pkg_install/add/perform.c
--- usr.sbin/pkg_install/add.orig/perform.c	Wed Jul 28 18:03:13 2004
+++ usr.sbin/pkg_install/add/perform.c	Mon Jan  3 09:48:42 2005
@@ -299,6 +299,7 @@
 	    if (!Fake) {
 		if (!isURL(pkg) && !getenv("PKG_ADD_BASE")) {
 		    const char *ext;
+		    char prefixArg[2 + MAXPATHLEN]; /* "-P" + Prefix */
 		    ext = strrchr(pkg_fullname, '.');
 		    if (ext == NULL)
@@ -315,7 +316,11 @@
 		    if (cp) {
 			if (Verbose)
 			    printf("Loading it from %s.\n", cp);
-			if (vsystem("%s %s'%s'", PkgAddCmd, Verbose ? "-v " : "", cp)) {
+			if (PrefixRecursive) {
+			    strlcpy(prefixArg, "-P", sizeof(prefixArg));
+			    strlcat(prefixArg, Prefix, sizeof(prefixArg));
+			}
+			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)
diff -ruN usr.sbin/pkg_install/add.orig/pkg_add.1 usr.sbin/pkg_install/add/pkg_add.1
--- usr.sbin/pkg_install/add.orig/pkg_add.1	Wed Aug 11 17:47:13 2004
+++ usr.sbin/pkg_install/add/pkg_add.1	Mon Jan  3 08:23:27 2005
@@ -26,6 +26,7 @@
 .Op Fl vInfrRMS
 .Op Fl t Ar template
 .Op Fl p Ar prefix
+.Op Fl P Ar prefix
 .Op Fl C Ar chrootdir
 .Ar pkg-name Op Ar pkg-name ...
@@ -127,7 +128,29 @@
 .Fl M
 .Fl S
+options). If the
+.Fl p
+flag appears after any
+.Fl P
+flag on the commandline, it overrides it's effect, causing
+not to use the given
+.Ar prefix
+.It Fl P Ar prefix
+Does the same as the
+.Fl p
+option, except that the given
+.Ar prefix
+is also used recursively for the dependency packages, if any. If the
+.Fl P
+flag appears after any
+.Fl p
+flag on the commandline, it overrides it's effect, causing
+to use the given
+.Ar prefix
 .It Fl t Ar template
 .Ar template
@@ -358,9 +381,10 @@
 .Pa prefix
 is either the prefix specified with the
 .Fl p
-flag or, if no
-.Fl p
-flag was specified, the name of the first directory named by a
+.Fl P
+flag or,
+if neither flag was specified, the name of the first directory named by a
 .Cm @cwd
 directive within this package.
@@ -421,12 +445,16 @@
 set to the installation prefix (see the
 .Fl p
-option above).
+.Fl P
+options above).
 This allows a package author to write a script
 that reliably performs some action on the directory where the package
 is installed, even if the user might change it with the
 .Fl p
-flag to
+.Fl P
+flags to
 .Cm pkg_add .
 The value of the

More information about the freebsd-bugs mailing list