aboutsummaryrefslogtreecommitdiff
path: root/lib/libc/gen/scandir.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/gen/scandir.c')
-rw-r--r--lib/libc/gen/scandir.c74
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 **);