diff options
Diffstat (limited to 'lib/libc/gen/scandir.c')
-rw-r--r-- | lib/libc/gen/scandir.c | 74 |
1 files changed, 59 insertions, 15 deletions
diff --git a/lib/libc/gen/scandir.c b/lib/libc/gen/scandir.c index 10cd7633dac1..f59f57047278 100644 --- a/lib/libc/gen/scandir.c +++ b/lib/libc/gen/scandir.c @@ -29,10 +29,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> -__SCCSID("@(#)scandir.c 8.3 (Berkeley) 1/2/94"); -__FBSDID("$FreeBSD$"); - /* * Scan the directory dirname calling select to make a list of selected * directory entries then sort using qsort and compare routine dcomp. @@ -42,8 +38,10 @@ __FBSDID("$FreeBSD$"); #include "namespace.h" #include <dirent.h> +#include <fcntl.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> #include "un-namespace.h" #ifdef I_AM_SCANDIR_B @@ -61,25 +59,21 @@ typedef DECLARE_BLOCK(int, select_block, const struct dirent *); typedef DECLARE_BLOCK(int, dcomp_block, const struct dirent **, const struct dirent **); #else -static int alphasort_thunk(void *thunk, const void *p1, const void *p2); +static int scandir_thunk_cmp(const void *p1, const void *p2, void *thunk); #endif -int +static int #ifdef I_AM_SCANDIR_B -scandir_b(const char *dirname, struct dirent ***namelist, select_block select, +scandir_b_dirp(DIR *dirp, struct dirent ***namelist, select_block select, dcomp_block dcomp) #else -scandir(const char *dirname, struct dirent ***namelist, +scandir_dirp(DIR *dirp, struct dirent ***namelist, int (*select)(const struct dirent *), int (*dcomp)(const struct dirent **, - const struct dirent **)) + const struct dirent **)) #endif { struct dirent *d, *p, **names = NULL; size_t arraysz, numitems; - DIR *dirp; - - if ((dirp = opendir(dirname)) == NULL) - return(-1); numitems = 0; arraysz = 32; /* initial estimate of the array size */ @@ -125,7 +119,7 @@ scandir(const char *dirname, struct dirent ***namelist, qsort_b(names, numitems, sizeof(struct dirent *), (void*)dcomp); #else qsort_r(names, numitems, sizeof(struct dirent *), - &dcomp, alphasort_thunk); + scandir_thunk_cmp, &dcomp); #endif *namelist = names; return (numitems); @@ -138,7 +132,50 @@ fail: return (-1); } +int +#ifdef I_AM_SCANDIR_B +scandir_b(const char *dirname, struct dirent ***namelist, select_block select, + dcomp_block dcomp) +#else +scandir(const char *dirname, struct dirent ***namelist, + int (*select)(const struct dirent *), int (*dcomp)(const struct dirent **, + const struct dirent **)) +#endif +{ + DIR *dirp; + + dirp = opendir(dirname); + if (dirp == NULL) + return (-1); + return ( +#ifdef I_AM_SCANDIR_B + scandir_b_dirp +#else + scandir_dirp +#endif + (dirp, namelist, select, dcomp)); +} + #ifndef I_AM_SCANDIR_B +int +scandirat(int dirfd, const char *dirname, struct dirent ***namelist, + int (*select)(const struct dirent *), int (*dcomp)(const struct dirent **, + const struct dirent **)) +{ + DIR *dirp; + int fd; + + fd = _openat(dirfd, dirname, O_RDONLY | O_DIRECTORY | O_CLOEXEC); + if (fd == -1) + return (-1); + dirp = fdopendir(fd); + if (dirp == NULL) { + _close(fd); + return (-1); + } + return (scandir_dirp(dirp, namelist, select, dcomp)); +} + /* * Alphabetic order comparison routine for those who want it. * POSIX 2008 requires that alphasort() uses strcoll(). @@ -150,8 +187,15 @@ alphasort(const struct dirent **d1, const struct dirent **d2) return (strcoll((*d1)->d_name, (*d2)->d_name)); } +int +versionsort(const struct dirent **d1, const struct dirent **d2) +{ + + return (strverscmp((*d1)->d_name, (*d2)->d_name)); +} + static int -alphasort_thunk(void *thunk, const void *p1, const void *p2) +scandir_thunk_cmp(const void *p1, const void *p2, void *thunk) { int (*dc)(const struct dirent **, const struct dirent **); |