diff options
author | Andrey Nazarov <skuller@skuller.net> | 2013-04-05 18:53:14 +0400 |
---|---|---|
committer | Andrey Nazarov <skuller@skuller.net> | 2013-04-06 00:56:58 +0400 |
commit | fe95b438f4a7b00c4aa41063531f66c4436d107e (patch) | |
tree | 1bcfcf711a9c88a1e20d653cd4acdb2effec4937 | |
parent | 2e377ff12d90e1b4d6d6505abea44f8429763332 (diff) |
Improve FS_ListFiles when operating on pack files.
Fix searching in the root directory of pack files: NULL path finds all
files, empty path excludes subdirectories. Add basic support for listing
directories inside pack files.
-rw-r--r-- | inc/common/files.h | 1 | ||||
-rw-r--r-- | src/common/cmd.c | 2 | ||||
-rw-r--r-- | src/common/files.c | 67 |
3 files changed, 48 insertions, 22 deletions
diff --git a/inc/common/files.h b/inc/common/files.h index b86ee6e..c2ab66a 100644 --- a/inc/common/files.h +++ b/inc/common/files.h @@ -66,6 +66,7 @@ typedef struct file_info_s { #define FS_SEARCH_EXTRAINFO 0x00000400 #define FS_SEARCH_STRIPEXT 0x00000800 #define FS_SEARCH_DIRSONLY 0x00001000 +#define FS_SEARCH_MASK 0x00001f00 // bits 8 - 11, flag #define FS_FLAG_GZIP 0x00000100 diff --git a/src/common/cmd.c b/src/common/cmd.c index 9e1fce4..65cfb43 100644 --- a/src/common/cmd.c +++ b/src/common/cmd.c @@ -1766,7 +1766,7 @@ static void Cmd_Exec_f(void) void Cmd_Config_g(genctx_t *ctx) { - FS_File_g("", "*.cfg", FS_SEARCH_SAVEPATH | FS_SEARCH_BYFILTER | FS_SEARCH_STRIPEXT, ctx); + FS_File_g(NULL, "*.cfg", FS_SEARCH_SAVEPATH | FS_SEARCH_BYFILTER | FS_SEARCH_STRIPEXT, ctx); } static void Cmd_Exec_c(genctx_t *ctx, int argnum) diff --git a/src/common/files.c b/src/common/files.c index fe3680d..b166bd3 100644 --- a/src/common/files.c +++ b/src/common/files.c @@ -2657,15 +2657,15 @@ void **FS_ListFiles(const char *path, unsigned flags, int *count_p) { - searchpath_t *search; - packfile_t *file; - void *files[MAX_LISTED_FILES], *info; - int i, count, total; - char normalized[MAX_OSPATH], buffer[MAX_OSPATH]; - void **list; - size_t len, pathlen; - char *s, *p; - int valid; + searchpath_t *search; + packfile_t *file; + void *files[MAX_LISTED_FILES], *info; + int i, j, count, total; + char normalized[MAX_OSPATH], buffer[MAX_OSPATH]; + void **list; + size_t len, pathlen; + char *s, *p; + int valid; count = 0; valid = PATH_NOT_CHECKED; @@ -2683,6 +2683,11 @@ void **FS_ListFiles(const char *path, path = normalized; } + // can't mix directory search with other flags + if ((flags & FS_SEARCH_DIRSONLY) && (flags & FS_SEARCH_MASK & ~FS_SEARCH_DIRSONLY)) { + goto fail; + } + for (search = fs_searchpaths; search; search = search->next) { if (flags & FS_PATH_MASK) { if ((flags & search->mode & FS_PATH_MASK) == 0) { @@ -2694,11 +2699,6 @@ void **FS_ListFiles(const char *path, continue; // don't search in paks } - // TODO: add directory search support for pak files - if (flags & FS_SEARCH_DIRSONLY) { - continue; - } - for (i = 0; i < search->pack->num_files; i++) { file = &search->pack->files[i]; s = file->name; @@ -2712,11 +2712,15 @@ void **FS_ListFiles(const char *path, continue; } if (s[pathlen] != '/') { - continue; // matched prefix must be a directory + continue; // matched prefix must be a directory } if (flags & FS_SEARCH_BYFILTER) { s += pathlen + 1; } + } else if (path == normalized) { + if (!(flags & FS_SEARCH_DIRSONLY) && strchr(s, '/')) { + continue; // must be a file in the root directory + } } // check filter @@ -2732,6 +2736,32 @@ void **FS_ListFiles(const char *path, } } + // copy name off + if (flags & (FS_SEARCH_DIRSONLY | FS_SEARCH_STRIPEXT)) { + s = strcpy(buffer, s); + } + + // hacky directory search support for pak files + if (flags & FS_SEARCH_DIRSONLY) { + p = s; + if (pathlen) { + p += pathlen + 1; + } + p = strchr(p, '/'); + if (!p) { + continue; // does not have directory component + } + *p = 0; + for (j = 0; j < count; j++) { + if (!FS_pathcmp(files[j], s)) { + break; + } + } + if (j != count) { + continue; // already listed this directory + } + } + // strip path if (!(flags & FS_SEARCH_SAVEPATH)) { s = COM_SkipPath(s); @@ -2739,12 +2769,7 @@ void **FS_ListFiles(const char *path, // strip extension if (flags & FS_SEARCH_STRIPEXT) { - p = COM_FileExtension(s); - if (*p) { - len = p - s; - s = memcpy(buffer, s, len); - s[len] = 0; - } + *COM_FileExtension(s) = 0; } if (!*s) { |