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
This commit is contained in:
parent
45fa2c8a87
commit
18798c64f0
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user