Subject: pkg/33884: PKG_PATH handling is weird
To: None <pkg-manager@netbsd.org, gnats-admin@netbsd.org,>
From: None <yamt@mwd.biglobe.ne.jp>
List: pkgsrc-bugs
Date: 07/01/2006 13:05:00
>Number:         33884
>Category:       pkg
>Synopsis:       PKG_PATH handling is weird
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    pkg-manager
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Jul 01 13:05:00 +0000 2006
>Originator:     YAMAMOTO Takashi <yamt@mwd.biglobe.ne.jp>
>Release:        NetBSD 3.99.21
>Organization:

>Environment:
	
	
System: NetBSD kaeru 3.99.21 NetBSD 3.99.21 (build.kaeru.xen.nodebug) #: Fri Jun 30 09:45:59 JST 2006 takashi@kaeru:/home/takashi/work/kernel/build.kaeru.xen.nodebug i386
Architecture: i386
Machine: i386
>Description:
	the behaviour of PKG_PATH is not straightforward, at best.

	if you do:
		PKG_PATH=/aa;/bb pkg_add cc/dd.tgz

	a package "dd.tgz" will be searched in the following order:
		1. ./cc/cc/dd.tgz  <= weird
		2. /aa/cc/dd.tgz
		3. /bb/cc/dd.tgz

	see this thread:
		http://mail-index.NetBSD.org/tech-pkg/2002/10/29/0002.html
>How-To-Repeat:
	
>Fix:
	i'm using the following patch. (revert path_prepend hack)
	i think it can make some people unhappy, tho.

Index: add/perform.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/pkg_install/add/perform.c,v
retrieving revision 1.120
diff -u -p -r1.120 perform.c
--- add/perform.c	24 Apr 2006 13:36:22 -0000	1.120
+++ add/perform.c	1 Jul 2006 12:54:10 -0000
@@ -1079,9 +1079,7 @@ pkg_perform(lpkg_head_t *pkgs)
 		err_cnt = pkg_do(NULL, NULL);
 	else {
 		while ((lpp = TAILQ_FIRST(pkgs)) != NULL) {
-			path_prepend_from_pkgname(lpp->lp_name);
 			err_cnt += pkg_do(lpp->lp_name, pkgs);
-			path_prepend_clear();
 			TAILQ_REMOVE(pkgs, lpp, lp_link);
 			free_lpkg(lpp);
 		}
Index: lib/path.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/pkg_install/lib/path.c,v
retrieving revision 1.8
diff -u -p -r1.8 path.c
--- lib/path.c	5 Nov 2005 13:11:02 -0000	1.8
+++ lib/path.c	1 Jul 2006 12:54:10 -0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: path.c,v 1.8 2005/11/05 13:11:02 wiz Exp $	*/
+/*	$NetBSD: path.c,v 1.2 2002/08/08 00:17:39 yamt Exp $	*/
 
 /*-
  * Copyright (c)2002 YAMAMOTO Takashi,
@@ -44,9 +44,6 @@ __RCSID("$NetBSD: path.c,v 1.8 2005/11/0
 #include "lib.h"
 
 struct pathhead PkgPath = TAILQ_HEAD_INITIALIZER(PkgPath);
-static struct path *prepend = 0;
-
-static struct path *path_new_entry(const char *cp, size_t len);
 
 /*
  * path_create: make PkgPath from a given string.
@@ -59,6 +56,8 @@ path_create(const char *path)
 {
 	const char *cp;
 	size_t len;
+	char cwd[MAXPATHLEN];
+	size_t cwdlen;
 
 	path_free();
 
@@ -69,6 +68,10 @@ path_create(const char *path)
 	if (Verbose)
 		printf("parsing: %s\n", path);
 
+	if (getcwd(cwd, sizeof(cwd)) == NULL)
+		err(1, "getcwd");
+	cwdlen = strlen(cwd);
+
 	cp = path;
 	while (*cp) {
 		len = strcspn(cp, ";");
@@ -76,7 +79,28 @@ path_create(const char *path)
 			/* add a new path */
 			struct path *new;
 
-			new = path_new_entry(cp, len);
+			new = malloc(sizeof(*new));
+			if (new == NULL)
+				err(1, "path_create");
+
+			if (!IS_FULLPATH(cp) && !IS_URL(cp)) {
+				/* this is a relative path */
+				size_t total;
+
+				total = cwdlen + 1 + len + 1;
+				new->pl_path = malloc(total);
+				if (new->pl_path == NULL)
+					err(1, "path_create");
+				snprintf(new->pl_path, total, "%s/%*.*s", cwd, (int)len, (int)len, cp);
+			}
+			else {
+				new->pl_path = malloc(len + 1);
+				if (new->pl_path == NULL)
+					err(1, "path_create");
+				memcpy(new->pl_path, cp, len);
+				new->pl_path[len] = '\0';
+			}
+
 			if (Verbose)
 				printf("path: %s\n", new->pl_path);
 			TAILQ_INSERT_TAIL(&PkgPath, new, pl_entry);
@@ -105,69 +129,6 @@ path_free()
 }
 
 /*
- * path_new_entry: Generate a new 'struct path' entry to be included in
- * 'PkgPath' using the first 'len' characters of 'cp'.
- */
-static struct path *
-path_new_entry(const char *cp, size_t len)
-{
-	struct path *new;
-
-	new = malloc(sizeof(*new));
-	if (new == NULL)
-		err(EXIT_FAILURE, "path_create");
-
-	if (!IS_FULLPATH(cp) && !IS_URL(cp)) {
-		/* this is a relative path */
-		size_t total;
-		char cwd[MaxPathSize];
-		size_t cwdlen;
-
-		if (getcwd(cwd, sizeof(cwd)) == NULL)
-			err(EXIT_FAILURE, "getcwd");
-		cwdlen = strlen(cwd);
-		total = cwdlen + 1 + len + 1;
-		new->pl_path = malloc(total);
-		if (new->pl_path == NULL)
-			err(EXIT_FAILURE, "path_create");
-		snprintf(new->pl_path, total, "%s/%*.*s", cwd, (int)len, (int)len, cp);
-	}
-	else {
-		new->pl_path = malloc(len + 1);
-		if (new->pl_path == NULL)
-			err(EXIT_FAILURE, "path_create");
-		memcpy(new->pl_path, cp, len);
-		new->pl_path[len] = '\0';
-	}
-	return new;
-}
-
-/*
- * path_prepend_from_pkgname: prepend the path for a package onto 'PkgPath'
- */
-void
-path_prepend_from_pkgname(const char *pkgname)
-{
-	char *ptr;
-	if ((ptr = strrchr(pkgname , '/'))) {
-		prepend = path_new_entry(pkgname, ptr - pkgname);
-		TAILQ_INSERT_HEAD(&PkgPath, prepend, pl_entry);
-	}
-}
-
-/*
- * path_prepend_clear: Remove any prepended entry from 'PkgPath'
- */
-void
-path_prepend_clear()
-{
-	if (prepend) {
-		TAILQ_REMOVE(&PkgPath, prepend, pl_entry);
-		prepend = 0;
-	}
-}
-
-/*
  * path_setenv: construct string from PkgPath and set it to a environment.
  *
  * => the environment name is given by envname.
Index: lib/path.h
===================================================================
RCS file: /cvsroot/src/usr.sbin/pkg_install/lib/path.h,v
retrieving revision 1.4
diff -u -p -r1.4 path.h
--- lib/path.h	2 Sep 2003 07:35:03 -0000	1.4
+++ lib/path.h	1 Jul 2006 12:54:10 -0000
@@ -35,6 +35,4 @@ TAILQ_HEAD(pathhead, path);
 extern struct pathhead PkgPath;
 void path_create(const char *);
 void path_free(void);
-void path_prepend_from_pkgname(const char *);
-void path_prepend_clear(void);
 void path_setenv(const char *);

>Unformatted: