diff options
Diffstat (limited to 'android/utils/dirscanner.c')
-rw-r--r-- | android/utils/dirscanner.c | 203 |
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; +} |