* Copyright (c) 1983 Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid
[] = "@(#)scandir.c 5.4 (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.
scandir(dirname
, namelist
, select
, dcomp
)
struct dirent
*(*namelist
[]);
int (*select
)(), (*dcomp
)();
register struct dirent
*d
, *p
, **names
;
register char *cp1
, *cp2
;
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
;
for (cp1
= p
->d_name
, cp2
= d
->d_name
; *cp1
++ = *cp2
++; );
* 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.
struct dirent
**d1
, **d2
;
return(strcmp((*d1
)->d_name
, (*d2
)->d_name
));