* Copyright (c) 1983 Regents of the University of California.
* Redistribution and use in source and binary forms are permitted provided
* that: (1) source distributions retain this entire copyright notice and
* comment, and (2) distributions including binaries display the following
* acknowledgement: ``This product includes software developed by the
* University of California, Berkeley and its contributors'' in the
* documentation or other materials provided with the distribution and in
* all advertising materials mentioning features or use of this software.
* Neither the name of the University nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid
[] = "@(#)scandir.c 5.9 (Berkeley) 6/24/90";
#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))
char *malloc (), *realloc ();
scandir(dirname
, namelist
, select
, dcomp
)
struct dirent
***namelist
;
int (*select
)(), (*dcomp
)();
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((unsigned int) (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
= (struct dirent
*)malloc((unsigned int) d
->d_reclen
);
p->d_reclen = d->d_reclen;
p->d_namlen = d->d_namlen;
bcopy(d->d_name, p->d_name, p->d_namlen + 1);
bcopy((char *)d
, (char *)p
, (int)d
->d_reclen
);
* 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
,
(unsigned int) arraysz
* sizeof(struct dirent
*));
if (nitems
&& dcomp
!= NULL
)
qsort((char *) 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
));