Subject: Re: PR/36464 CVS commit: src/lib/libc/gen
To: None <lib-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: Christos Zoulas <christos@zoulas.com>
List: netbsd-bugs
Date: 06/12/2007 12:00:04
The following reply was made to PR lib/36464; it has been noted by GNATS.

From: christos@zoulas.com (Christos Zoulas)
To: Ed Ravin <eravin@panix.com>, gnats-bugs@NetBSD.org
Cc: 
Subject: Re: PR/36464 CVS commit: src/lib/libc/gen
Date: Tue, 12 Jun 2007 07:58:44 -0400

 On Jun 12, 12:29am, eravin@panix.com (Ed Ravin) wrote:
 -- Subject: Re: PR/36464 CVS commit: src/lib/libc/gen
 
 Thanks, I will ask releng to pull it up.
 
 christos
 
 | See attached for a patch against 3.1.  It seems to work for the two apps
 | I tried that use scandir() (Pine, Midnight Commander).
 | 
 | I got lazy and left the "divide by 24" bit in there, but otherwise
 | I think it matches what you did with the current tree.
 | 
 | 
 | --rwEMma7ioTxnRzrJ
 | Content-Type: application/DEFANGED-11858; charset="us-ascii"
 | Content-Disposition: attachment; filename="scandir_c_diff.DEFANGED-11858"
 | 
 | --- scandir.c	2007/06/11 23:17:07	1.1
 | +++ scandir.c	2007/06/12 04:25:56
 | @@ -60,6 +60,34 @@
 |  __weak_alias(alphasort,_alphasort)
 |  #endif
 |  
 | +
 | +/*
 | + * Compute an estimate of the number of entries in a directory based on
 | + * the file size. Returns the estimated number of entries or 0 on failure.
 | + */
 | +static size_t
 | +dirsize(int fd, size_t olen)
 | +{
 | +	struct stat stb;
 | +	size_t nlen;
 | +
 | +	if (fstat(fd, &stb) == -1)
 | +		return 0;
 | +	/*
 | +	 * Estimate the array size by taking the size of the directory file
 | +	 * and dividing it by a multiple of the minimum size entry. 
 | +	 */
 | +	nlen = (size_t)(stb.st_size / 24 /*_DIRENT_MINSIZE((struct dirent *)0)*/ );
 | +	/*
 | +	 * If the size turns up 0, switch to an alternate strategy and use the
 | +	 * file size as the number of entries like ZFS returns. If that turns
 | +	 * out to be 0 too return a minimum of 10 entries, plus the old length.
 | +	 */
 | +	if (nlen == 0)
 | +		nlen = (size_t)(stb.st_size ? stb.st_size : 10);
 | +	return olen + nlen;
 | +}
 | +
 |  /*
 |   * The DIRSIZ macro is the minimum record length which will hold the directory
 |   * entry.  This requires the amount of space in struct dirent without the
 | @@ -80,7 +108,6 @@
 |  {
 |  	struct dirent *d, *p, **names, **newnames;
 |  	size_t nitems, arraysz;
 | -	struct stat stb;
 |  	DIR *dirp;
 |  
 |  	_DIAGASSERT(dirname != NULL);
 | @@ -88,14 +115,10 @@
 |  
 |  	if ((dirp = opendir(dirname)) == NULL)
 |  		return (-1);
 | -	if (fstat(dirp->dd_fd, &stb) < 0)
 | +
 | +	if ((arraysz = dirsize(dirp->dd_fd, 0)) == 0)
 |  		goto bad;
 |  
 | -	/*
 | -	 * estimate the array size by taking the size of the directory file
 | -	 * and dividing it by a multiple of the minimum size entry. 
 | -	 */
 | -	arraysz = (size_t)(stb.st_size / 24);
 |  	names = malloc(arraysz * sizeof(struct dirent *));
 |  	if (names == NULL)
 |  		goto bad;
 | @@ -110,9 +133,8 @@
 |  		 * realloc the maximum size.
 |  		 */
 |  		if (nitems >= arraysz) {
 | -			if (fstat(dirp->dd_fd, &stb) < 0)
 | -				goto bad2;	/* just might have grown */
 | -			arraysz = (size_t)(stb.st_size / 12);
 | +			if ((arraysz = dirsize(dirp->dd_fd, arraysz)) == 0)
 | +				goto bad2;
 |  			newnames = realloc(names,
 |  			    arraysz * sizeof(struct dirent *));
 |  			if (newnames == NULL)
 | 
 | --rwEMma7ioTxnRzrJ
 | Content-Type: text/sanitizer-log; charset="iso-8859-1"
 | Content-Transfer-Encoding: 8bit
 | Content-Disposition: attachment; filename="sanitizer.log"
 | 
 | This message has been 'sanitized'.  This means that potentially
 | dangerous content has been rewritten or removed.  The following
 | log describes which actions were taken.
 | 
 | Sanitizer (start="1181622556"):
 |   Part (pos="1903"):
 |     SanitizeFile (filename="unnamed.txt", mimetype="text/plain"):
 |       Match (names="unnamed.txt", rule="2"):
 |         Enforced policy: accept
 | 
 |   Part (pos="2951"):
 |     SanitizeFile (filename="scandir.c.diff", mimetype="text/plain"):
 |       Match (rule="default"):
 |         Enforced policy: defang
 | 
 |       Replaced mime type with: application/DEFANGED-11858
 |       Replaced file name with: scandir_c_diff.DEFANGED-11858
 | 
 |   Total modifications so far: 1
 | 
 | 
 | Anomy 0.0.0 : Sanitizer.pm
 | $Id: Sanitizer.pm,v 1.89 2004/09/02 10:14:15 bre Exp $
 | $Id: gw.conf,v 1.1 2005/06/23 02:18:04 kim Exp $
 | 
 | --rwEMma7ioTxnRzrJ--
 -- End of excerpt from Ed Ravin