Subject: pkg_install bug
To: None <tech-pkg@netbsd.org>
From: Jukka Salmi <j+nbsd@2007.salmi.ch>
List: tech-pkg
Date: 05/04/2007 00:36:09
--pf9I7BMVVzbSWLtt
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi,

on a NetBSD -current system with a small /var file system I just tried
to use the `-t template' option to pkg_add(8) to make adding a huge
package succeed, but the template I specified was ignored. Glancing
at the code (pkg_install/lib/pen.c) I see why:

[...]
/*
 * Find a good place to play.
 */
static char *
find_play_pen(char *pen, size_t pensize, size_t sz)
{
	char   *cp;
	struct stat sb;
[...]
	if (pen[0] && stat(pen, &sb) != FAIL && (min_free(pen) >= sz))
		return pen;

This stat() call seems wrong. If the -t option is used, *pen is a
mkdtemp(3) template name here. But that directory doesn't exist yet,
thus the stat(2) always fails...

The attached patch fixes this problem by stat()ing pen's parent
directory instead of pen itself.

Comments are welcome.


Cheers, Jukka

-- 
bashian roulette:
$ ((RANDOM%6)) || rm -rf ~

--pf9I7BMVVzbSWLtt
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=diff

Index: usr.sbin/pkg_install/lib/pen.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/pkg_install/lib/pen.c,v
retrieving revision 1.36
diff -u -p -r1.36 pen.c
--- usr.sbin/pkg_install/lib/pen.c	17 Mar 2006 01:58:25 -0000	1.36
+++ usr.sbin/pkg_install/lib/pen.c	3 May 2007 22:24:33 -0000
@@ -102,6 +102,7 @@ find_play_pen(char *pen, size_t pensize,
 {
 	char   *cp;
 	struct stat sb;
+	char   *r;
 
 	if (pen == NULL) {
 		cleanup(0);
@@ -111,8 +112,12 @@ find_play_pen(char *pen, size_t pensize,
 		return NULL;
 	}
 	
-	if (pen[0] && stat(pen, &sb) != FAIL && (min_free(pen) >= sz))
-		return pen;
+	if (pen[0] && (r = rindex(pen, '/')) != NULL) {
+		char pendir[r-pen+1];
+		strlcpy(pendir, pen, sizeof(pendir));
+		if (stat(pendir, &sb) != FAIL && (min_free(pendir) >= sz))
+			return pen;
+	}
 	else if ((cp = getenv("PKG_TMPDIR")) != NULL && stat(cp, &sb) != FAIL && (min_free(cp) >= sz))
 		(void) snprintf(pen, pensize, "%s/instmp.XXXXXX", cp);
 	else if ((cp = getenv("TMPDIR")) != NULL && stat(cp, &sb) != FAIL && (min_free(cp) >= sz))

--pf9I7BMVVzbSWLtt--