[klibc] [PATCH v2 1/4] klibc: Add scandir() support.

Mike Waychison mikew at google.com
Tue Aug 2 15:46:50 PDT 2011


Add support for scandir() as defined in POSIX.1-2008.

Signed-off-by: Mike Waychison <mikew at google.com>
---
 usr/include/dirent.h |    5 ++++
 usr/klibc/Kbuild     |    2 +
 usr/klibc/scandir.c  |   71 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 77 insertions(+), 1 deletions(-)
 create mode 100644 usr/klibc/scandir.c

diff --git a/usr/include/dirent.h b/usr/include/dirent.h
index e324474..0bcf40b 100644
--- a/usr/include/dirent.h
+++ b/usr/include/dirent.h
@@ -30,4 +30,9 @@ static __inline__ int dirfd(DIR * __d)
 	return __d->__fd;
 }
 
+__extern int scandir(const char *, struct dirent ***,
+		     int (*)(const struct dirent *),
+		     int (*)(const struct dirent **,
+			     const struct dirent **));
+
 #endif				/* _DIRENT_H */
diff --git a/usr/klibc/Kbuild b/usr/klibc/Kbuild
index af40367..40e61da 100644
--- a/usr/klibc/Kbuild
+++ b/usr/klibc/Kbuild
@@ -42,7 +42,7 @@ klib-y := vsnprintf.o snprintf.o vsprintf.o sprintf.o \
 	  seteuid.o setegid.o \
 	  getenv.o setenv.o putenv.o __put_env.o unsetenv.o \
 	  clearenv.o nullenv.o \
-	  getopt.o getopt_long.o readdir.o remove.o \
+	  getopt.o getopt_long.o readdir.o scandir.o remove.o \
 	  syslog.o closelog.o pty.o getpt.o posix_openpt.o isatty.o reboot.o \
 	  time.o utime.o llseek.o nice.o getpriority.o \
 	  qsort.o bsearch.o \
diff --git a/usr/klibc/scandir.c b/usr/klibc/scandir.c
new file mode 100644
index 0000000..9b95980
--- /dev/null
+++ b/usr/klibc/scandir.c
@@ -0,0 +1,71 @@
+/*
+ * scandir.c: scandir
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <dirent.h>
+
+int scandir(const char *dirp, struct dirent ***namelist,
+	    int (*filter)(const struct dirent *),
+	    int (*compar)(const struct dirent **, const struct dirent **))
+{
+	struct dirent **nl = NULL, **next_nl;
+	struct dirent *dirent;
+	size_t count = 0;
+	size_t allocated = 0;
+	DIR *dir;
+
+	dir = opendir(dirp);
+	if (!dir)
+		return -1;
+
+	while (1) {
+		dirent = readdir(dir);
+		if (!dirent)
+			break;
+		if (!filter || filter(dirent)) {
+			struct dirent *copy;
+			copy = malloc(sizeof(*copy));
+			if (!copy)
+				goto cleanup_fail;
+			memcpy(copy, dirent, sizeof(*copy));
+
+			/* Extend the array if needed */
+			if (count == allocated) {
+				if (allocated == 0)
+					allocated = 15; /* ~1 page worth */
+				else
+					allocated *= 2;
+				next_nl = realloc(nl, allocated);
+				if (!next_nl) {
+					free(copy);
+					goto cleanup_fail;
+				}
+				nl = next_nl;
+			}
+
+			nl[count++] = copy;
+		}
+	}
+
+	qsort(nl, count, sizeof(struct dirent *),
+	      (int (*)(const void *, const void *))compar);
+
+	closedir(dir);
+
+	*namelist = nl;
+	return count;
+
+cleanup_fail:
+	while (count) {
+		dirent = nl[--count];
+		free(dirent);
+	}
+	free(nl);
+	closedir(dir);
+	errno = ENOMEM;
+	return -1;
+}



More information about the klibc mailing list