Subject: pkg/32228: pkg_add does not execute /usr/pkg/bin/tar even when it says so
To: None <pkg-manager@netbsd.org, gnats-admin@netbsd.org,>
From: Peter Postma <peter@pointless.nl>
List: pkgsrc-bugs
Date: 12/03/2005 18:48:10
>Number:         32228
>Category:       pkg
>Synopsis:       pkg_add does not execute /usr/pkg/bin/tar even when it says so
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    pkg-manager
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Dec 03 18:48:10 +0000 2005
>Originator:     Peter Postma
>Release:        OpenBSD 3.8 + pkgsrc -current
>Organization:
>Environment:
>Description:
I just installed pkgsrc current on OpenBSD 3.8 and I noticed problems with
pkg_add using tar. It looks likes pkg_add is executing /bin/tar even when
the verbose output says that it is executing /usr/pkg/bin/tar.

Here's the pkg_add verbose output:

# /usr/pkg/sbin/pkg_add -v -K /var/db/pkgdb /usr/pkgsrc/packages/All/audit-packages-1.41.tgz
parsing: .
path: /usr/pkgsrc/.
increasing RLIMIT_NOFILE to max. 1024 open files
Requested space: 35412 bytes, free space: 8587143168 bytes in /var/tmp/instmp.b26295
running: /usr/pkg/bin/tar --fast-read --use-compress-program gzip -xpf /usr/pkgsrc/packages/All/audit-packages-1.41.tgz +CONTENTS
tar: unknown option -- -
usage: tar {crtux}[014578befHhLmOoPpqsvwXZz]
          [blocking-factor | archive | replstr] [-C directory] [-I file]
          [file ...]
       tar {-crtux} [-014578eHhLmOoPpqvwXZz] [-b blocking-factor]
          [-C directory] [-f archive] [-I file] [-s replstr] [file ...]
pkg_add: extract of /usr/pkgsrc/packages/All/audit-packages-1.41.tgz failed
pkg_add: unable to extract table of contents file from `/usr/pkgsrc/packages/All/audit-packages-1.41.tgz' - not a package?
pkg_add: 1 package addition failed


Renaming /bin/tar seems to help, pkg_add now picks up the pkg_add in
/usr/pkg/bin:

# mv /bin/tar /bin/tar.orig

# /usr/pkg/sbin/pkg_add -v -K /var/db/pkgdb /usr/pkgsrc/packages/All/audit-packages-1.41.tgz
parsing: .
path: /usr/pkgsrc/.
increasing RLIMIT_NOFILE to max. 1024 open files
Requested space: 35412 bytes, free space: 8587143168 bytes in /var/tmp/instmp.qg8160
running: /usr/pkg/bin/tar --fast-read --use-compress-program gzip -xpf /usr/pkgsrc/packages/All/audit-packages-1.41.tgz +CONTENTS
running: /usr/pkg/bin/tar --use-compress-program gzip -xpf /usr/pkgsrc/packages/All/audit-packages-1.41.tgz
Depends pre-scan: `digest-[0-9]*' required.
Package `audit-packages-1.41' depends on `digest-[0-9]*'.
 - digest-20050731 already installed.
extract: Package name is audit-packages-1.41
[....]

>How-To-Repeat:
Install current pkgsrc on OpenBSD. Create a package and pkg_add it.

>Fix:
It seems that in lib/file.c, the path is stripped off:

	up_argv[i] = strrchr(TAR_CMD, '/');
	if (up_argv[i] == NULL)
		up_argv[i] = TAR_CMD;
	else
		up_argv[i]++;  /* skip / character */

Then pfcexec() is called with up_argv not having the full path for tar.
execvp() finds /bin/tar first in the path and executes that instead of
/usr/pkg/bin/tar.

A quick fix is below, add an extra argument to pfcexec() for the full 
name of the file to execute. There might be a better fix, but this works
for me.


Index: files/add/futil.c
===================================================================
RCS file: /cvsroot/pkgsrc/pkgtools/pkg_install/files/add/futil.c,v
retrieving revision 1.8
diff -u -u -r1.8 futil.c
--- files/add/futil.c	23 Nov 2005 14:33:50 -0000	1.8
+++ files/add/futil.c	3 Dec 2005 16:17:26 -0000
@@ -107,7 +107,7 @@
 		argv[0] = CHMOD_CMD;
 		argv[1] = "-R";
 		argv[2] = Mode;
-		if (pfcexec(cd_to, argv))
+		if (pfcexec(cd_to, argv[0], argv))
 			warnx("couldn't change modes of '%s' ... to '%s'",
 			    args[0], Mode);
 	}
@@ -122,7 +122,7 @@
 		argv[0] = CHOWN_CMD;
 		argv[1] = "-R";
 		argv[2] = owner_group;
-		if (pfcexec(cd_to, argv))
+		if (pfcexec(cd_to, argv[0], argv))
 			warnx("couldn't change owner/group of '%s' ... to '%s:%s'",
 				args[0], Owner, Group);
 		free(argv);
@@ -132,7 +132,7 @@
 		argv[0] = CHOWN_CMD;
 		argv[1] = "-R";
 		argv[2] = Owner;
-		if (pfcexec(cd_to, argv))
+		if (pfcexec(cd_to, argv[0], argv))
 			warnx("couldn't change owner of '%s' ... to '%s'",
 				args[0], Owner);
 		free(argv);
@@ -143,7 +143,7 @@
 		argv[0] = CHGRP_CMD;
 		argv[1] = "-R";
 		argv[2] = Group;
-		if (pfcexec(cd_to, argv))
+		if (pfcexec(cd_to, argv[0], argv))
 			warnx("couldn't change group of '%s' ... to '%s'",
 				args[0], Group);
 	}
Index: files/lib/fexec.c
===================================================================
RCS file: /cvsroot/pkgsrc/pkgtools/pkg_install/files/lib/fexec.c,v
retrieving revision 1.7
diff -u -u -r1.7 fexec.c
--- files/lib/fexec.c	23 Nov 2005 04:49:51 -0000	1.7
+++ files/lib/fexec.c	3 Dec 2005 16:17:26 -0000
@@ -76,7 +76,7 @@
  * wait for the command to finish, then return the exit status.
  */
 int
-pfcexec(const char *path, const char **argv)
+pfcexec(const char *path, const char *file, const char **argv)
 {
 	pid_t			child;
 	int			status;
@@ -87,7 +87,7 @@
 		if ((path != NULL) && (chdir(path) < 0))
 			_exit(127);
 
-		(void) execvp(argv[0], (char ** const)argv);
+		(void)execvp(file, (char ** const)argv);
 		_exit(127);
 		/* NOTREACHED */
 	case -1:
@@ -146,7 +146,7 @@
 		argv[argc++] = arg;
 	} while (arg != NULL);
 
-	return pfcexec(path, argv);
+	return pfcexec(path, argv[0], argv);
 }
 
 int
Index: files/lib/file.c
===================================================================
RCS file: /cvsroot/pkgsrc/pkgtools/pkg_install/files/lib/file.c,v
retrieving revision 1.16
diff -u -u -r1.16 file.c
--- files/lib/file.c	23 Nov 2005 04:49:51 -0000	1.16
+++ files/lib/file.c	3 Dec 2005 16:17:26 -0000
@@ -676,7 +676,7 @@
 		printf("\n");
 	}
 
-	result = pfcexec(NULL, (const char **)up_argv);
+	result = pfcexec(NULL, TAR_CMD, (const char **)up_argv);
 	free(up_argv);
 	if (result != 0) {
 		warnx("extract of %s failed", pkg);
Index: files/lib/lib.h
===================================================================
RCS file: /cvsroot/pkgsrc/pkgtools/pkg_install/files/lib/lib.h,v
retrieving revision 1.20
diff -u -u -r1.20 lib.h
--- files/lib/lib.h	28 Nov 2005 01:50:21 -0000	1.20
+++ files/lib/lib.h	3 Dec 2005 16:17:26 -0000
@@ -313,7 +313,7 @@
 int	fexec(const char *, ...);
 int	fexec_skipempty(const char *, ...);
 int	fcexec(const char *, const char *, ...);
-int	pfcexec(const char *path, const char **argv);
+int	pfcexec(const char *, const char *, const char **);
 pipe_to_system_t	*pipe_to_system_begin(const char *, char *const *, void (*)(void));
 int	pipe_to_system_end(pipe_to_system_t *);