summaryrefslogtreecommitdiffstats
path: root/lib/libc/gen
diff options
context:
space:
mode:
authordas <das@FreeBSD.org>2008-03-16 19:08:53 +0000
committerdas <das@FreeBSD.org>2008-03-16 19:08:53 +0000
commit6f407f2920aabd83849ef82bbae7a7aded2d68e3 (patch)
treead83a5de29b27154002e898c9720dd5248f47544 /lib/libc/gen
parente7b290ea3d25b7552b89e1f0f99985a9e6e3654d (diff)
downloadFreeBSD-src-6f407f2920aabd83849ef82bbae7a7aded2d68e3.zip
FreeBSD-src-6f407f2920aabd83849ef82bbae7a7aded2d68e3.tar.gz
scandir(3) previously used st_size to obtain an initial estimate
of the array length needed to store all the directory entries. Although BSD has historically guaranteed that st_size is the size of the directory file, POSIX does not, and more to the point, some recent filesystems such as ZFS use st_size to mean something else. The fix is to not stat the directory at all, set the initial array size to 32 entries, and realloc it in powers of 2 if that proves insufficient. PR: 113668
Diffstat (limited to 'lib/libc/gen')
-rw-r--r--lib/libc/gen/scandir.c16
1 files changed, 3 insertions, 13 deletions
diff --git a/lib/libc/gen/scandir.c b/lib/libc/gen/scandir.c
index cfe765d..1dae85d 100644
--- a/lib/libc/gen/scandir.c
+++ b/lib/libc/gen/scandir.c
@@ -41,8 +41,6 @@ __FBSDID("$FreeBSD$");
*/
#include "namespace.h"
-#include <sys/types.h>
-#include <sys/stat.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
@@ -68,20 +66,13 @@ scandir(dirname, namelist, select, dcomp)
{
struct dirent *d, *p, **names = NULL;
size_t nitems = 0;
- struct stat stb;
long arraysz;
DIR *dirp;
if ((dirp = opendir(dirname)) == NULL)
return(-1);
- if (_fstat(dirp->dd_fd, &stb) < 0)
- goto fail;
- /*
- * estimate the array size by taking the size of the directory file
- * and dividing it by a multiple of the minimum size entry.
- */
- arraysz = (stb.st_size / 24);
+ arraysz = 32; /* initial estimate of the array size */
names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
if (names == NULL)
goto fail;
@@ -105,17 +96,16 @@ scandir(dirname, namelist, select, dcomp)
* realloc the maximum size.
*/
if (nitems >= arraysz) {
- const int inc = 10; /* increase by this much */
struct dirent **names2;
names2 = (struct dirent **)realloc((char *)names,
- (arraysz + inc) * sizeof(struct dirent *));
+ (arraysz * 2) * sizeof(struct dirent *));
if (names2 == NULL) {
free(p);
goto fail;
}
names = names2;
- arraysz += inc;
+ arraysz *= 2;
}
names[nitems++] = p;
}
OpenPOWER on IntegriCloud