diff options
author | jkeil <jkeil@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2002-11-26 18:31:30 +0000 |
---|---|---|
committer | jkeil <jkeil@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2002-11-26 18:31:30 +0000 |
commit | 11896c376b384e5bdb77f4daf55bcf9b14e60a90 (patch) | |
tree | dc7c964c824f2249b85cf54deeea1a01ed8dcf29 /linux | |
parent | 35836a6b775514633ed0ed18e603f9afe3ef7418 (diff) | |
download | mpv-11896c376b384e5bdb77f4daf55bcf9b14e60a90.tar.bz2 mpv-11896c376b384e5bdb77f4daf55bcf9b14e60a90.tar.xz |
Add a scandir() implementation for systems that do not have it in libc.
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@8289 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'linux')
-rw-r--r-- | linux/Makefile | 2 | ||||
-rw-r--r-- | linux/scandir.c | 134 |
2 files changed, 135 insertions, 1 deletions
diff --git a/linux/Makefile b/linux/Makefile index 0519e08efd..342445004c 100644 --- a/linux/Makefile +++ b/linux/Makefile @@ -3,7 +3,7 @@ include ../config.mak LIBNAME = libosdep.a -SRCS=getch2.c timer-lx.c shmem.c strsep.c # timer.c +SRCS=getch2.c timer-lx.c shmem.c strsep.c scandir.c # timer.c OBJS=$(SRCS:.c=.o) ifeq ($(TARGET_ARCH_X86),yes) diff --git a/linux/scandir.c b/linux/scandir.c new file mode 100644 index 0000000000..868dd7cb57 --- /dev/null +++ b/linux/scandir.c @@ -0,0 +1,134 @@ +/* + * scandir, alphasort - scan a directory + * + * implementation for systems that do not have it in libc + */ + +#include "../config.h" + +#ifndef HAVE_SCANDIR + +#include <sys/types.h> +#include <dirent.h> +#include <stdlib.h> +#include <stddef.h> +#include <string.h> + +/* + * convenience helper function for scandir's |compar()| function: + * sort directory entries using strcoll(3) + */ +int +alphasort(const void *_a, const void *_b) +{ + struct dirent **a = (struct dirent **)_a; + struct dirent **b = (struct dirent **)_b; + return strcoll((*a)->d_name, (*b)->d_name); +} + + +#define strverscmp(a,b) strcoll(a,b) /* for now */ + +/* + * convenience helper function for scandir's |compar()| function: + * sort directory entries using GNU |strverscmp()| + */ +int +versionsort(const void *_a, const void *_b) +{ + struct dirent **a = (struct dirent **)_a; + struct dirent **b = (struct dirent **)_b; + return strverscmp((*a)->d_name, (*b)->d_name); +} + +/* + * The scandir() function reads the directory dirname and builds an + * array of pointers to directory entries using malloc(3). It returns + * the number of entries in the array. A pointer to the array of + * directory entries is stored in the location referenced by namelist. + * + * The select parameter is a pointer to a user supplied subroutine + * which is called by scandir() to select which entries are to be + * included in the array. The select routine is passed a pointer to + * a directory entry and should return a non-zero value if the + * directory entry is to be included in the array. If select is null, + * then all the directory entries will be included. + * + * The compar parameter is a pointer to a user supplied subroutine + * which is passed to qsort(3) to sort the completed array. If this + * pointer is null, the array is not sorted. + */ +int +scandir(const char *dirname, + struct dirent ***ret_namelist, + int (*select)(const struct dirent *), + int (*compar)(const struct dirent **, const struct dirent **)) +{ + int i, len; + int used, allocated; + DIR *dir; + struct dirent *ent, *ent2; + struct dirent **namelist = NULL; + + if ((dir = opendir(dirname)) == NULL) + return -1; + + used = 0; + allocated = 2; + namelist = malloc(allocated * sizeof(struct dirent *)); + if (!namelist) + goto error; + + while ((ent = readdir(dir)) != NULL) { + + if (select != NULL && !select(ent)) + continue; + + /* duplicate struct direct for this entry */ + len = offsetof(struct dirent, d_name) + strlen(ent->d_name) + 1; + if ((ent2 = malloc(len)) == NULL) + return -1; + + if (used >= allocated) { + allocated *= 2; + namelist = realloc(namelist, allocated * sizeof(struct dirent *)); + if (!namelist) + goto error; + } + memcpy(ent2, ent, len); + namelist[used++] = ent2; + } + closedir(dir); + + if (compar) + qsort(namelist, used, sizeof(struct dirent *), + (int (*)(const void *, const void *)) compar); + + *ret_namelist = namelist; + return used; + + +error: + if (namelist) { + for (i = 0; i < used; i++) + free(namelist[i]); + free(namelist); + } + return -1; +} +#endif + + +#if STANDALONE_MAIN +int +main(int argc, char **argv) +{ + struct dirent **namelist; + int i, n; + + n = scandir("/etc", &namelist, NULL, alphasort); + + for (i = 0; i < n; i++) + printf("%s\n", namelist[i]->d_name); +} +#endif |