aboutsummaryrefslogtreecommitdiffstats
path: root/android/utils/dirscanner.c
diff options
context:
space:
mode:
Diffstat (limited to 'android/utils/dirscanner.c')
-rw-r--r--android/utils/dirscanner.c203
1 files changed, 203 insertions, 0 deletions
diff --git a/android/utils/dirscanner.c b/android/utils/dirscanner.c
new file mode 100644
index 0000000..fc63ef0
--- /dev/null
+++ b/android/utils/dirscanner.c
@@ -0,0 +1,203 @@
+/* Copyright (C) 2007-2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#include "android/utils/dirscanner.h"
+#include "android/utils/bufprint.h"
+#include "qemu-common.h"
+#include <stddef.h>
+
+#define DIRSCANNER_BASE \
+ char root[PATH_MAX]; \
+ int rootLen; \
+ char full[PATH_MAX]; \
+
+
+#if _WIN32
+
+#include <io.h>
+
+struct DirScanner {
+ DIRSCANNER_BASE
+ intptr_t findIndex1;
+ struct _finddata_t findData;
+};
+
+/* note: findIndex1 contains the find index + 1
+ * so a value of 0 means 'invalid'
+ */
+
+static int
+_dirScannerInit( DirScanner* s )
+{
+ char* p = s->root + s->rootLen;
+ char* end = s->root + sizeof s->root;
+ int ret;
+
+ /* create file spec by appending \* to root */
+ p = bufprint(p, end, "\\*");
+ if (p >= end)
+ return -1;
+
+ ret = _findfirst(s->root, &s->findData);
+
+ s->findIndex1 = ret+1;
+ return ret;
+}
+
+static void
+_dirScanner_done( DirScanner* s )
+{
+ if (s->findIndex1 > 0) {
+ _findclose(s->findIndex1-1);
+ s->findIndex1 = 0;
+ }
+}
+
+const char*
+dirScanner_next( DirScanner* s )
+{
+ char* ret = NULL;
+
+ if (!s || s->findIndex1 <= 0)
+ return NULL;
+
+ while (ret == NULL) {
+ ret = s->findData.name;
+
+ /* ignore special directories */
+ if (!strcmp(ret, ".") || !strcmp(ret, "..")) {
+ ret = NULL;
+ }
+ /* find next one */
+ if (_findnext(s->findIndex1-1, &s->findData) < 0) {
+ _dirScanner_done(s);
+ break;
+ }
+ }
+ return ret;
+}
+
+#else /* !_WIN32 */
+
+#include <dirent.h>
+struct DirScanner {
+ DIRSCANNER_BASE
+ DIR* dir;
+ struct dirent* entry;
+};
+
+static int
+_dirScannerInit( DirScanner* s )
+{
+ s->dir = opendir(s->root);
+
+ if (s->dir == NULL)
+ return -1;
+
+ s->entry = NULL;
+ return 0;
+}
+
+static void
+_dirScanner_done( DirScanner* s )
+{
+ if (s->dir) {
+ closedir(s->dir);
+ s->dir = NULL;
+ }
+}
+
+const char*
+dirScanner_next( DirScanner* s )
+{
+ char* ret = NULL;
+
+ if (!s || s->dir == NULL)
+ return NULL;
+
+ for (;;)
+ {
+ /* read new entry if needed */
+ s->entry = readdir(s->dir);
+ if (s->entry == NULL) {
+ _dirScanner_done(s);
+ break;
+ }
+
+ /* ignore special directories */
+ ret = s->entry->d_name;
+
+ if (!strcmp(ret,".") || !strcmp(ret,"..")) {
+ ret = NULL;
+ continue;
+ }
+ break;
+ }
+ return ret;
+}
+
+#endif /* !_WIN32 */
+
+DirScanner*
+dirScanner_new ( const char* rootPath )
+{
+ DirScanner* s = qemu_mallocz(sizeof *s);
+ char* p = s->root;
+ char* end = p + sizeof s->root;
+
+ p = bufprint(p, end, "%s", rootPath);
+ if (p >= end)
+ goto FAIL;
+
+ s->rootLen = (p - s->root);
+
+ if (_dirScannerInit(s) < 0)
+ goto FAIL;
+
+ return s;
+
+FAIL:
+ dirScanner_free(s);
+ return NULL;
+}
+
+
+void
+dirScanner_free( DirScanner* s )
+{
+ if (!s)
+ return;
+
+ _dirScanner_done(s);
+ qemu_free(s);
+}
+
+
+const char*
+dirScanner_nextFull( DirScanner* s )
+{
+ const char* name = dirScanner_next(s);
+ char* p;
+ char* end;
+
+ if (name == NULL)
+ return NULL;
+
+ p = s->full;
+ end = p + sizeof s->full;
+
+ p = bufprint(p, end, "%.*s/%s", s->rootLen, s->root, name);
+ if (p >= end) {
+ /* ignore if the full name is too long */
+ return dirScanner_nextFull(s);
+ }
+ return s->full;
+}