summaryrefslogtreecommitdiffstats
path: root/linux
diff options
context:
space:
mode:
authorjkeil <jkeil@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-11-26 18:31:30 +0000
committerjkeil <jkeil@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-11-26 18:31:30 +0000
commit11896c376b384e5bdb77f4daf55bcf9b14e60a90 (patch)
treedc7c964c824f2249b85cf54deeea1a01ed8dcf29 /linux
parent35836a6b775514633ed0ed18e603f9afe3ef7418 (diff)
downloadmpv-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/Makefile2
-rw-r--r--linux/scandir.c134
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