diff options
author | das <das@FreeBSD.org> | 2008-03-16 19:08:53 +0000 |
---|---|---|
committer | das <das@FreeBSD.org> | 2008-03-16 19:08:53 +0000 |
commit | 6f407f2920aabd83849ef82bbae7a7aded2d68e3 (patch) | |
tree | ad83a5de29b27154002e898c9720dd5248f47544 /lib/libc/gen | |
parent | e7b290ea3d25b7552b89e1f0f99985a9e6e3654d (diff) | |
download | FreeBSD-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.c | 16 |
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; } |