Changeset View
Changeset View
Standalone View
Standalone View
lib/libc/gen/scandir.c
Show All 36 Lines | |||||
* Scan the directory dirname calling select to make a list of selected | * Scan the directory dirname calling select to make a list of selected | ||||
* directory entries then sort using qsort and compare routine dcomp. | * directory entries then sort using qsort and compare routine dcomp. | ||||
* Returns the number of entries and a pointer to a list of pointers to | * 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. | * struct dirent (through namelist). Returns -1 if there were any errors. | ||||
*/ | */ | ||||
#include "namespace.h" | #include "namespace.h" | ||||
#include <dirent.h> | #include <dirent.h> | ||||
#include <fcntl.h> | |||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <unistd.h> | |||||
#include "un-namespace.h" | #include "un-namespace.h" | ||||
#ifdef I_AM_SCANDIR_B | #ifdef I_AM_SCANDIR_B | ||||
#include "block_abi.h" | #include "block_abi.h" | ||||
#define SELECT(x) CALL_BLOCK(select, x) | #define SELECT(x) CALL_BLOCK(select, x) | ||||
#ifndef __BLOCKS__ | #ifndef __BLOCKS__ | ||||
void qsort_b(void *, size_t, size_t, void *); | void qsort_b(void *, size_t, size_t, void *); | ||||
#endif | #endif | ||||
#else | #else | ||||
#define SELECT(x) select(x) | #define SELECT(x) select(x) | ||||
#endif | #endif | ||||
#ifdef I_AM_SCANDIR_B | #ifdef I_AM_SCANDIR_B | ||||
typedef DECLARE_BLOCK(int, select_block, const struct dirent *); | typedef DECLARE_BLOCK(int, select_block, const struct dirent *); | ||||
typedef DECLARE_BLOCK(int, dcomp_block, const struct dirent **, | typedef DECLARE_BLOCK(int, dcomp_block, const struct dirent **, | ||||
const struct dirent **); | const struct dirent **); | ||||
#else | #else | ||||
static int alphasort_thunk(void *thunk, const void *p1, const void *p2); | static int alphasort_thunk(void *thunk, const void *p1, const void *p2); | ||||
#endif | #endif | ||||
int | static int | ||||
#ifdef I_AM_SCANDIR_B | #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) | dcomp_block dcomp) | ||||
#else | #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 **, | int (*select)(const struct dirent *), int (*dcomp)(const struct dirent **, | ||||
const struct dirent **)) | const struct dirent **)) | ||||
#endif | #endif | ||||
{ | { | ||||
struct dirent *d, *p, **names = NULL; | struct dirent *d, *p, **names = NULL; | ||||
size_t arraysz, numitems; | size_t arraysz, numitems; | ||||
DIR *dirp; | |||||
if ((dirp = opendir(dirname)) == NULL) | |||||
return(-1); | |||||
numitems = 0; | numitems = 0; | ||||
arraysz = 32; /* initial estimate of the array size */ | arraysz = 32; /* initial estimate of the array size */ | ||||
names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *)); | names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *)); | ||||
if (names == NULL) | if (names == NULL) | ||||
goto fail; | goto fail; | ||||
while ((d = readdir(dirp)) != NULL) { | while ((d = readdir(dirp)) != NULL) { | ||||
if (select != NULL && !SELECT(d)) | if (select != NULL && !SELECT(d)) | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | |||||
fail: | fail: | ||||
while (numitems > 0) | while (numitems > 0) | ||||
free(names[--numitems]); | free(names[--numitems]); | ||||
free(names); | free(names); | ||||
closedir(dirp); | closedir(dirp); | ||||
return (-1); | 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 | #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. | * Alphabetic order comparison routine for those who want it. | ||||
* POSIX 2008 requires that alphasort() uses strcoll(). | * POSIX 2008 requires that alphasort() uses strcoll(). | ||||
*/ | */ | ||||
int | int | ||||
alphasort(const struct dirent **d1, const struct dirent **d2) | alphasort(const struct dirent **d1, const struct dirent **d2) | ||||
{ | { | ||||
Show All 12 Lines |