* Copyright (c) 1983 Regents of the University of California.
* %sccs.include.redist.c%
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid
[] = "@(#)scandir.c 5.10 (Berkeley) %G%";
#endif /* LIBC_SCCS and not lint */
* Scan the directory dirname calling select to make a list of selected
* directory entries then sort using qsort and compare routine dcomp.
* Returns the number of entries and a pointer to a list of pointers to
* struct dirent (through namelist). Returns -1 if there were any errors.
* The DIRSIZ macro gives the minimum record length which will hold
* the directory entry. This requires the amount of space in struct dirent
* without the d_name field, plus enough space for the name with a terminating
* null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
scandir(dirname
, namelist
, select
, dcomp
)
struct dirent
***namelist
;
int (*select
) __P((struct dirent
*));
int (*dcomp
) __P((const void *, const void *));
register struct dirent
*d
, *p
, **names
;
if ((dirp
= opendir(dirname
)) == NULL
)
if (fstat(dirp
->dd_fd
, &stb
) < 0)
* 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);
names
= (struct dirent
**)malloc(arraysz
* sizeof(struct dirent
*));
while ((d
= readdir(dirp
)) != NULL
) {
if (select
!= NULL
&& !(*select
)(d
))
continue; /* just selected names */
* Make a minimum size copy of the data
p
= (struct dirent
*)malloc(DIRSIZ(d
));
p
->d_reclen
= d
->d_reclen
;
p
->d_namlen
= d
->d_namlen
;
bcopy(d
->d_name
, p
->d_name
, p
->d_namlen
+ 1);
* Check to make sure the array has space left and
* realloc the maximum size.
if (++nitems
>= arraysz
) {
if (fstat(dirp
->dd_fd
, &stb
) < 0)
return(-1); /* just might have grown */
arraysz
= stb
.st_size
/ 12;
names
= (struct dirent
**)realloc((char *)names
,
arraysz
* sizeof(struct dirent
*));
if (nitems
&& dcomp
!= NULL
)
qsort(names
, nitems
, sizeof(struct dirent
*), dcomp
);
* Alphabetic order comparison routine for those who want it.
return(strcmp((*(struct dirent
**)d1
)->d_name
,
(*(struct dirent
**)d2
)->d_name
));