2 * scandir, alphasort - scan a directory
4 * implementation for systems that do not have it in libc
11 #include <sys/types.h>
18 * convenience helper function for scandir's |compar()| function:
19 * sort directory entries using strcoll(3)
22 alphasort(const void *_a
, const void *_b
)
24 struct dirent
**a
= (struct dirent
**)_a
;
25 struct dirent
**b
= (struct dirent
**)_b
;
26 return strcoll((*a
)->d_name
, (*b
)->d_name
);
30 #define strverscmp(a,b) strcoll(a,b) /* for now */
33 * convenience helper function for scandir's |compar()| function:
34 * sort directory entries using GNU |strverscmp()|
37 versionsort(const void *_a
, const void *_b
)
39 struct dirent
**a
= (struct dirent
**)_a
;
40 struct dirent
**b
= (struct dirent
**)_b
;
41 return strverscmp((*a
)->d_name
, (*b
)->d_name
);
45 * The scandir() function reads the directory dirname and builds an
46 * array of pointers to directory entries using malloc(3). It returns
47 * the number of entries in the array. A pointer to the array of
48 * directory entries is stored in the location referenced by namelist.
50 * The select parameter is a pointer to a user supplied subroutine
51 * which is called by scandir() to select which entries are to be
52 * included in the array. The select routine is passed a pointer to
53 * a directory entry and should return a non-zero value if the
54 * directory entry is to be included in the array. If select is null,
55 * then all the directory entries will be included.
57 * The compar parameter is a pointer to a user supplied subroutine
58 * which is passed to qsort(3) to sort the completed array. If this
59 * pointer is null, the array is not sorted.
62 scandir(const char *dirname
,
63 struct dirent
***ret_namelist
,
64 int (*select
)(const struct dirent
*),
65 int (*compar
)(const struct dirent
**, const struct dirent
**))
70 struct dirent
*ent
, *ent2
;
71 struct dirent
**namelist
= NULL
;
73 if ((dir
= opendir(dirname
)) == NULL
)
78 namelist
= malloc(allocated
* sizeof(struct dirent
*));
82 while ((ent
= readdir(dir
)) != NULL
) {
84 if (select
!= NULL
&& !select(ent
))
87 /* duplicate struct direct for this entry */
88 len
= offsetof(struct dirent
, d_name
) + strlen(ent
->d_name
) + 1;
89 if ((ent2
= malloc(len
)) == NULL
)
92 if (used
>= allocated
) {
94 namelist
= realloc(namelist
, allocated
* sizeof(struct dirent
*));
98 memcpy(ent2
, ent
, len
);
99 namelist
[used
++] = ent2
;
104 qsort(namelist
, used
, sizeof(struct dirent
*),
105 (int (*)(const void *, const void *)) compar
);
107 *ret_namelist
= namelist
;
115 for (i
= 0; i
< used
; i
++)
126 main(int argc
, char **argv
)
128 struct dirent
**namelist
;
131 n
= scandir("/etc", &namelist
, NULL
, alphasort
);
133 for (i
= 0; i
< n
; i
++)
134 printf("%s\n", namelist
[i
]->d_name
);