char *FS_BuildOSPath( const char *base, const char *game, const char *qpath ) { char temp[MAX_OSPATH]; static char ospath[4][MAX_OSPATH]; static int toggle; toggle = (++toggle)&3; // allows four returns without clash (increased from 2 during fs_copyfiles 2 enhancement) Com_sprintf( temp, sizeof(temp), "/%s/%s", game, qpath ); FS_ReplaceSeparators( temp ); Com_sprintf( ospath[toggle], sizeof( ospath[0] ), "%s%s", base, temp ); return ospath[toggle]; }
char *FS_BuildOSPath( const char *qpath ) { char temp[MAX_OSPATH]; static char ospath[2][MAX_OSPATH]; static int toggle; toggle ^= 1; // flip-flop to allow two returns without clash Com_sprintf( temp, sizeof(temp), "/%s/%s", fs_gamedirvar->string, qpath ); FS_ReplaceSeparators( temp ); Com_sprintf( ospath[toggle], sizeof( ospath[0] ), "%s%s", fs_basepath->string, temp ); return ospath[toggle]; }
char *FS_BuildOSPath( const char *base, const char *game, const char *qpath ) { char temp[MAX_OSPATH]; static char ospath[4][MAX_OSPATH]; static int toggle; //pre-fs_cf2 //toggle ^= 1; // flip-flop to allow two returns without clash //post-fs_cf2 toggle = (++toggle)&3; // allows four returns without clash (increased from 2 during fs_copyfiles 2 enhancement) if( !game || !game[0] ) { game = fs_gamedir; } Com_sprintf( temp, sizeof(temp), "/%s/%s", game, qpath ); FS_ReplaceSeparators( temp ); Com_sprintf( ospath[toggle], sizeof( ospath[0] ), "%s%s", base, temp ); return ospath[toggle]; }
char *FS_BuildOSPath( const char *qpath ) { char temp[MAX_OSPATH]; static char ospath[2][MAX_OSPATH]; static int toggle; toggle ^= 1; // flip-flop to allow two returns without clash // Fix for filenames that are given to FS with a leading "/" (/botfiles/Foo) if (qpath[0] == '\\' || qpath[0] == '/') qpath++; Com_sprintf( temp, sizeof(temp), "/%s/%s", fs_gamedirvar->string, qpath ); FS_ReplaceSeparators( temp ); Com_sprintf( ospath[toggle], sizeof( ospath[0] ), "%s%s", fs_basepath->string, temp ); return ospath[toggle]; }
/* =================== FS_BuildGOBPath Qpath may have either forward or backwards slashes =================== */ static char *FS_BuildGOBPath(const char *qpath ) { static char path[2][MAX_OSPATH]; static int toggle; toggle ^= 1; // flip-flop to allow two returns without clash if (qpath[0] == '\\' || qpath[0] == '/') { Com_sprintf( path[toggle], sizeof( path[0] ), ".%s", qpath ); } else { Com_sprintf( path[toggle], sizeof( path[0] ), ".\\%s", qpath ); } // FS_ReplaceSeparators( path[toggle], '\\' ); FS_ReplaceSeparators( path[toggle] ); return path[toggle]; }
/* ================= Sys_ListFiles_r Internal function to filesystem. Conventions apply: - files should hold at least MAX_LISTED_FILES - *count_p must be initialized in range [0, MAX_LISTED_FILES - 1] - depth must be 0 on the first call ================= */ void Sys_ListFiles_r(const char *path, const char *filter, unsigned flags, size_t baselen, int *count_p, void **files, int depth) { WIN32_FIND_DATAA data; HANDLE handle; char fullpath[MAX_OSPATH], *name; size_t pathlen, len; unsigned mask; void *info; // optimize single extension search if (!(flags & FS_SEARCH_BYFILTER) && filter && !strchr(filter, ';')) { if (*filter == '.') { filter++; } len = Q_concat(fullpath, sizeof(fullpath), path, "\\*.", filter, NULL); filter = NULL; // do not check it later } else { len = Q_concat(fullpath, sizeof(fullpath), path, "\\*", NULL); } if (len >= sizeof(fullpath)) { return; } // format path to windows style // done on the first run only if (!depth) { FS_ReplaceSeparators(fullpath, '\\'); } handle = FindFirstFileA(fullpath, &data); if (handle == INVALID_HANDLE_VALUE) { return; } // make it point right after the slash pathlen = strlen(path) + 1; do { if (!strcmp(data.cFileName, ".") || !strcmp(data.cFileName, "..")) { continue; // ignore special entries } // construct full path len = strlen(data.cFileName); if (pathlen + len >= sizeof(fullpath)) { continue; } memcpy(fullpath + pathlen, data.cFileName, len + 1); if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { mask = FS_SEARCH_DIRSONLY; } else { mask = 0; } // pattern search implies recursive search if ((flags & FS_SEARCH_BYFILTER) && mask && depth < MAX_LISTED_DEPTH) { Sys_ListFiles_r(fullpath, filter, flags, baselen, count_p, files, depth + 1); // re-check count if (*count_p >= MAX_LISTED_FILES) { break; } } // check type if ((flags & FS_SEARCH_DIRSONLY) != mask) { continue; } // check filter if (filter) { if (flags & FS_SEARCH_BYFILTER) { if (!FS_WildCmp(filter, fullpath + baselen)) { continue; } } else { if (!FS_ExtCmp(filter, data.cFileName)) { continue; } } } // strip path if (flags & FS_SEARCH_SAVEPATH) { name = fullpath + baselen; } else { name = data.cFileName; } // reformat it back to quake filesystem style FS_ReplaceSeparators(name, '/'); // strip extension if (flags & FS_SEARCH_STRIPEXT) { *COM_FileExtension(name) = 0; if (!*name) { continue; } } // copy info off if (flags & FS_SEARCH_EXTRAINFO) { info = copy_info(name, &data); } else { info = FS_CopyString(name); } files[(*count_p)++] = info; } while (*count_p < MAX_LISTED_FILES && FindNextFileA(handle, &data) != FALSE); FindClose(handle); }