Browse Source

filesystem: apply caseinsensitivity to file creation

Replace fs_writedir with fs_writepath, exposing current writeable searchpath.
Fix caseinsensitive FS_Search
Remove unused argument from listdirectory()
Minor optimizations and refactoring
pull/2/head
Alibek Omarov 2 years ago
parent
commit
fe1aba3561
  1. 4
      filesystem/VFileSystem009.cpp
  2. 291
      filesystem/dir.c
  3. 79
      filesystem/filesystem.c
  4. 7
      filesystem/filesystem_internal.h

4
filesystem/VFileSystem009.cpp

@ -42,14 +42,14 @@ static inline qboolean IsIdGamedir( const char *id )
!Q_strcmp( id, "GAMEDOWNLOAD" ); !Q_strcmp( id, "GAMEDOWNLOAD" );
} }
static inline const char* IdToDir( const char *id ) static inline const char *IdToDir( const char *id )
{ {
if( !Q_strcmp( id, "GAME" )) if( !Q_strcmp( id, "GAME" ))
return GI->gamefolder; return GI->gamefolder;
else if( !Q_strcmp( id, "GAMEDOWNLOAD" )) else if( !Q_strcmp( id, "GAMEDOWNLOAD" ))
return va( "%s/downloaded", GI->gamefolder ); return va( "%s/downloaded", GI->gamefolder );
else if( !Q_strcmp( id, "GAMECONFIG" )) else if( !Q_strcmp( id, "GAMECONFIG" ))
return fs_writedir; // full path here so it's totally our write allowed directory return fs_writepath->filename; // full path here so it's totally our write allowed directory
else if( !Q_strcmp( id, "PLATFORM" )) else if( !Q_strcmp( id, "PLATFORM" ))
return "platform"; // stub return "platform"; // stub
else if( !Q_strcmp( id, "CONFIG" )) else if( !Q_strcmp( id, "CONFIG" ))

291
filesystem/dir.c

@ -41,7 +41,7 @@ typedef struct dir_s
struct dir_s *entries; // sorted struct dir_s *entries; // sorted
} dir_t; } dir_t;
static int FS_SortDir( const void *_a, const void *_b ) static int FS_SortDirEntries( const void *_a, const void *_b )
{ {
const dir_t *a = _a; const dir_t *a = _a;
const dir_t *b = _b; const dir_t *b = _b;
@ -65,25 +65,19 @@ static void FS_InitDirEntries( dir_t *dir, const stringlist_t *list )
{ {
int i; int i;
if( !list->numstrings )
{
dir->numentries = DIRENTRY_EMPTY_DIRECTORY;
dir->entries = NULL;
return;
}
dir->numentries = list->numstrings; dir->numentries = list->numstrings;
dir->entries = Mem_Malloc( fs_mempool, sizeof( dir_t ) * dir->numentries ); dir->entries = Mem_Malloc( fs_mempool, sizeof( dir_t ) * dir->numentries );
for( i = 0; i < list->numstrings; i++ ) for( i = 0; i < list->numstrings; i++ )
{ {
dir_t *entry = &dir->entries[i]; dir_t *entry = &dir->entries[i];
Q_strncpy( entry->name, list->strings[i], sizeof( entry->name )); Q_strncpy( entry->name, list->strings[i], sizeof( entry->name ));
entry->numentries = DIRENTRY_NOT_SCANNED; entry->numentries = DIRENTRY_NOT_SCANNED;
entry->entries = NULL; entry->entries = NULL;
} }
qsort( dir->entries, dir->numentries, sizeof( dir->entries[0] ), FS_SortDir ); qsort( dir->entries, dir->numentries, sizeof( dir->entries[0] ), FS_SortDirEntries );
} }
static void FS_PopulateDirEntries( dir_t *dir, const char *path ) static void FS_PopulateDirEntries( dir_t *dir, const char *path )
@ -102,8 +96,16 @@ static void FS_PopulateDirEntries( dir_t *dir, const char *path )
} }
stringlistinit( &list ); stringlistinit( &list );
listdirectory( &list, path, false ); listdirectory( &list, path );
FS_InitDirEntries( dir, &list ); if( !list.numstrings )
{
dir->numentries = DIRENTRY_EMPTY_DIRECTORY;
dir->entries = NULL;
}
else
{
FS_InitDirEntries( dir, &list );
}
stringlistfreecontents( &list ); stringlistfreecontents( &list );
#endif #endif
} }
@ -112,12 +114,10 @@ static int FS_FindDirEntry( dir_t *dir, const char *name )
{ {
int left, right; int left, right;
if( dir->numentries < 0 )
return -1;
// look for the file (binary search) // look for the file (binary search)
left = 0; left = 0;
right = dir->numentries - 1; right = dir->numentries - 1;
while( left <= right ) while( left <= right )
{ {
int middle = (left + right) / 2; int middle = (left + right) / 2;
@ -142,30 +142,37 @@ static void FS_MergeDirEntries( dir_t *dir, const stringlist_t *list )
int i; int i;
dir_t temp; dir_t temp;
// glorified realloc for sorted dir entries
// make new array and copy old entries with same name and subentries
// everything else get freed
FS_InitDirEntries( &temp, list ); FS_InitDirEntries( &temp, list );
// copy all entries that has the same name and has subentries
for( i = 0; i < dir->numentries; i++ ) for( i = 0; i < dir->numentries; i++ )
{ {
dir_t *oldentry = &dir->entries[i];
dir_t *newentry;
int j; int j;
// don't care about directories without subentries // don't care about directories without subentries
if( dir->entries == NULL ) if( oldentry->entries == NULL )
continue; continue;
// try to find this directory in new tree // try to find this directory in new tree
j = FS_FindDirEntry( &temp, dir->entries[i].name ); j = FS_FindDirEntry( &temp, oldentry->name );
// not found, free memory // not found, free memory
if( j < 0 ) if( j < 0 )
{ {
FS_FreeDirEntries( &dir->entries[i] ); FS_FreeDirEntries( oldentry );
continue; continue;
} }
// found directory, move all entries // found directory, move all entries
temp.entries[j].numentries = dir->entries[i].numentries; newentry = &temp.entries[j];
temp.entries[j].entries = dir->entries[i].entries;
newentry->numentries = oldentry->numentries;
newentry->entries = oldentry->entries;
} }
// now we can free old tree and replace it with temporary // now we can free old tree and replace it with temporary
@ -177,216 +184,141 @@ static void FS_MergeDirEntries( dir_t *dir, const stringlist_t *list )
static int FS_MaybeUpdateDirEntries( dir_t *dir, const char *path, const char *entryname ) static int FS_MaybeUpdateDirEntries( dir_t *dir, const char *path, const char *entryname )
{ {
stringlist_t list; stringlist_t list;
qboolean update = false; int ret;
int idx;
stringlistinit( &list ); stringlistinit( &list );
listdirectory( &list, path, false ); listdirectory( &list, path );
// find the reason to update entries list if( list.numstrings == 0 ) // empty directory
if( list.numstrings != dir->numentries )
{ {
// small optimization to not search string in the list FS_FreeDirEntries( dir );
// and directly go updating entries dir->numentries = DIRENTRY_EMPTY_DIRECTORY;
update = true; ret = -1;
}
else if( dir->numentries < 0 ) // not initialized or was empty
{
FS_InitDirEntries( dir, &list );
ret = FS_FindDirEntry( dir, entryname );
}
else if( list.numstrings != dir->numentries ) // quick update
{
FS_MergeDirEntries( dir, &list );
ret = FS_FindDirEntry( dir, entryname );
} }
else else
{ {
for( idx = 0; idx < list.numstrings; idx++ ) // do heavy compare if directory now have an entry we need
int i;
for( i = 0; i < list.numstrings; i++ )
{ {
if( !Q_stricmp( list.strings[idx], entryname )) if( !Q_stricmp( list.strings[i], entryname ))
{
update = true;
break; break;
}
} }
}
if( !update ) if( i != list.numstrings )
{ {
stringlistfreecontents( &list ); FS_MergeDirEntries( dir, &list );
return -1; ret = FS_FindDirEntry( dir, entryname );
}
else ret = -1;
} }
FS_MergeDirEntries( dir, &list );
stringlistfreecontents( &list ); stringlistfreecontents( &list );
return FS_FindDirEntry( dir, entryname ); return ret;
} }
#if 1 static inline qboolean FS_AppendToPath( char *dst, size_t *pi, const size_t len, const char *src, const char *path, const char *err )
qboolean FS_FixFileCase( dir_t *dir, const char *path, char *dst, size_t len, qboolean createpath )
{ {
const char *prev = path; size_t i = *pi;
const char *next = Q_strchrnul( prev, PATH_SEPARATOR );
size_t i = Q_strlen( dst ); // dst is expected to have searchpath filename
while( true ) i += Q_strncpy( &dst[i], src, len - i );
*pi = i;
if( i >= len )
{ {
Con_Printf( S_ERROR "FS_FixFileCase: overflow while searching %s (%s)\n", path, err );
return false;
}
return true;
}
qboolean FS_FixFileCase( dir_t *dir, const char *path, char *dst, const size_t len, qboolean createpath )
{
const char *prev, *next;
size_t i = 0;
if( !FS_AppendToPath( dst, &i, len, dir->name, path, "init" ))
return false;
for( prev = path, next = Q_strchrnul( prev, PATH_SEPARATOR );
;
prev = next + 1, next = Q_strchrnul( prev, PATH_SEPARATOR ))
{
qboolean uptodate = false; // do not run second scan if we're just updated our directory list
size_t temp;
char entryname[MAX_SYSPATH]; char entryname[MAX_SYSPATH];
int ret; int ret;
// this subdirectory is case insensitive, just slam everything that's left // this subdirectory is case insensitive, just slam everything that's left
if( dir->numentries == DIRENTRY_CASEINSENSITIVE ) if( dir->numentries == DIRENTRY_CASEINSENSITIVE )
{ {
i += Q_strncpy( &dst[i], prev, len - i ); if( !FS_AppendToPath( dst, &i, len, prev, path, "caseinsensitive entry" ))
if( i >= len )
{
Con_Printf( "%s: overflow while searching %s (caseinsensitive entry)\n", __FUNCTION__, path );
return false; return false;
}
break; break;
} }
// populate cache if needed
if( dir->numentries == DIRENTRY_NOT_SCANNED ) if( dir->numentries == DIRENTRY_NOT_SCANNED )
{
// read directory first time
FS_PopulateDirEntries( dir, dst ); FS_PopulateDirEntries( dir, dst );
uptodate = true;
}
// get our entry name // get our entry name
Q_strncpy( entryname, prev, next - prev + 1 ); Q_strncpy( entryname, prev, next - prev + 1 );
ret = FS_FindDirEntry( dir, entryname );
// didn't found, but does it exists in FS? // didn't found, but does it exists in FS?
if( ret < 0 ) if(( ret = FS_FindDirEntry( dir, entryname )) < 0 )
{ {
ret = FS_MaybeUpdateDirEntries( dir, dst, entryname ); // if we're creating files or folders, we don't care if path doesn't exist
// so copy everything that's left and exit without an error
if( uptodate || ( ret = FS_MaybeUpdateDirEntries( dir, dst, entryname )) < 0 )
return createpath ? FS_AppendToPath( dst, &i, len, prev, path, "create path" ) : false;
if( ret < 0 ) uptodate = true;
{
// if we're creating files or folders, we don't care if path doesn't exist
// so copy everything that's left and exit without an error
if( createpath )
{
i += Q_strncpy( &dst[i], prev, len - i );
if( i >= len )
{
Con_Printf( "%s: overflow while searching %s (create path)\n", __FUNCTION__, path );
return false;
}
return true;
}
return false;
}
} }
dir = &dir->entries[ret]; dir = &dir->entries[ret];
ret = Q_strncpy( &dst[i], dir->name, len - i ); temp = i;
if( !FS_AppendToPath( dst, &temp, len, dir->name, path, "case fix" ))
// file not found, rescan...
if( !FS_SysFileOrFolderExists( dst ))
{
// strip failed part
dst[i] = 0;
ret = FS_MaybeUpdateDirEntries( dir, dst, entryname );
// file not found, exit... =/
if( ret < 0 )
{
// if we're creating files or folders, we don't care if path doesn't exist
// so copy everything that's left and exit without an error
if( createpath )
{
i += Q_strncpy( &dst[i], prev, len - i );
if( i >= len )
{
Con_Printf( "%s: overflow while searching %s (create path 2)\n", __FUNCTION__, path );
return false;
}
return true;
}
return false;
}
dir = &dir->entries[ret];
ret = Q_strncpy( &dst[i], dir->name, len - i );
}
i += ret;
if( i >= len ) // overflow!
{
Con_Printf( "%s: overflow while searching %s (appending fixed file name)\n", __FUNCTION__, path );
return false; return false;
}
// end of string, found file, return
if( next[0] == '\0' )
break;
// move pointer one character forward, find next path split character if( !uptodate && !FS_SysFileOrFolderExists( dst )) // file not found, rescan...
prev = next + 1;
next = Q_strchrnul( prev, PATH_SEPARATOR );
i += Q_strncpy( &dst[i], PATH_SEPARATOR_STR, len - i );
if( i >= len ) // overflow!
{ {
Con_Printf( "%s: overflow while searching %s (path separator)\n", __FUNCTION__, path ); dst[i] = 0; // strip failed part
return false;
}
}
return true;
}
#else
qboolean FS_FixFileCase( dir_t *dir, const char *path, char *dst, size_t len, qboolean createpath )
{
const char *prev = path;
const char *next = Q_strchrnul( prev, PATH_SEPARATOR );
size_t i = Q_strlen( dst ); // dst is expected to have searchpath filename
while( true )
{
stringlist_t list;
char entryname[MAX_SYSPATH];
int idx;
// get our entry name
Q_strncpy( entryname, prev, next - prev + 1 );
stringlistinit( &list ); // if we're creating files or folders, we don't care if path doesn't exist
listdirectory( &list, dst, false ); // so copy everything that's left and exit without an error
if(( ret = FS_MaybeUpdateDirEntries( dir, dst, entryname )) < 0 )
return createpath ? FS_AppendToPath( dst, &i, len, prev, path, "create path rescan" ) : false;
for( idx = 0; idx < list.numstrings; idx++ ) dir = &dir->entries[ret];
{ if( !FS_AppendToPath( dst, &temp, len, dir->name, path, "case fix rescan" ))
if( !Q_stricmp( list.strings[idx], entryname ))
break;
}
if( idx != list.numstrings )
{
i += Q_strncpy( &dst[i], list.strings[idx], len - i );
if( i >= len ) // overflow!
{
Con_Printf( "%s: overflow while searching %s (appending fixed file name)\n", __FUNCTION__, path );
return false; return false;
}
}
else
{
stringlistfreecontents( &list );
return false;
} }
i = temp;
stringlistfreecontents( &list );
// end of string, found file, return // end of string, found file, return
if( next[0] == '\0' ) if( next[0] == '\0' || ( next[0] == PATH_SEPARATOR && next[1] == '\0' ))
break; break;
// move pointer one character forward, find next path split character if( !FS_AppendToPath( dst, &i, len, PATH_SEPARATOR_STR, path, "path separator" ))
prev = next + 1;
next = Q_strchrnul( prev, PATH_SEPARATOR );
i += Q_strncpy( &dst[i], PATH_SEPARATOR_STR, len - i );
if( i >= len ) // overflow!
{
Con_Printf( "%s: overflow while searching %s (path separator)\n", __FUNCTION__, path );
return false; return false;
}
} }
return true; return true;
} }
#endif
static void FS_Close_DIR( searchpath_t *search ) static void FS_Close_DIR( searchpath_t *search )
{ {
@ -403,7 +335,6 @@ static int FS_FindFile_DIR( searchpath_t *search, const char *path, char *fixedn
{ {
char netpath[MAX_SYSPATH]; char netpath[MAX_SYSPATH];
Q_strncpy( netpath, search->filename, sizeof( netpath ));
if( !FS_FixFileCase( search->dir, path, netpath, sizeof( netpath ), false )) if( !FS_FixFileCase( search->dir, path, netpath, sizeof( netpath ), false ))
return -1; return -1;
@ -438,12 +369,16 @@ static void FS_Search_DIR( searchpath_t *search, stringlist_t *list, const char
if( basepathlength ) memcpy( basepath, pattern, basepathlength ); if( basepathlength ) memcpy( basepath, pattern, basepathlength );
basepath[basepathlength] = '\0'; basepath[basepathlength] = '\0';
Q_snprintf( netpath, sizeof( netpath ), "%s%s", search->filename, basepath ); if( !FS_FixFileCase( search->dir, basepath, netpath, sizeof( netpath ), false ))
{
Mem_Free( basepath );
return;
}
stringlistinit( &dirlist ); stringlistinit( &dirlist );
listdirectory( &dirlist, netpath, caseinsensitive ); listdirectory( &dirlist, netpath );
Q_strncpy( temp, basepath, sizeof( temp ) ); Q_strncpy( temp, basepath, sizeof( temp ));
for( dirlistindex = 0; dirlistindex < dirlist.numstrings; dirlistindex++ ) for( dirlistindex = 0; dirlistindex < dirlist.numstrings; dirlistindex++ )
{ {
@ -500,7 +435,7 @@ void FS_InitDirectorySearchpath( searchpath_t *search, const char *path, int fla
// create cache root // create cache root
search->dir = Mem_Malloc( fs_mempool, sizeof( dir_t )); search->dir = Mem_Malloc( fs_mempool, sizeof( dir_t ));
search->dir->name[0] = 0; // root has no filename, unused Q_strncpy( search->dir->name, search->filename, sizeof( search->dir->name ));
FS_PopulateDirEntries( search->dir, path ); FS_PopulateDirEntries( search->dir, path );
} }

79
filesystem/filesystem.c

@ -50,7 +50,6 @@ poolhandle_t fs_mempool;
searchpath_t *fs_searchpaths = NULL; // chain searchpath_t *fs_searchpaths = NULL; // chain
char fs_rodir[MAX_SYSPATH]; char fs_rodir[MAX_SYSPATH];
char fs_rootdir[MAX_SYSPATH]; char fs_rootdir[MAX_SYSPATH];
char fs_writedir[MAX_SYSPATH]; // path that game allows to overwrite, delete and rename files (and create new of course)
searchpath_t *fs_writepath; searchpath_t *fs_writepath;
static char fs_basedir[MAX_SYSPATH]; // base game directory static char fs_basedir[MAX_SYSPATH]; // base game directory
@ -193,10 +192,8 @@ static void listlowercase( stringlist_t *list )
} }
} }
void listdirectory( stringlist_t *list, const char *path, qboolean lowercase ) void listdirectory( stringlist_t *list, const char *path )
{ {
int i;
signed char *c;
#if XASH_WIN32 #if XASH_WIN32
char pattern[4096]; char pattern[4096];
struct _finddata_t n_file; struct _finddata_t n_file;
@ -307,7 +304,7 @@ static qboolean FS_AddArchive_Fullpath( const char *file, qboolean *already_load
================ ================
FS_AddGameDirectory FS_AddGameDirectory
Sets fs_writedir, adds the directory to the head of the path, Sets fs_writepath, adds the directory to the head of the path,
then loads and adds pak1.pak pak2.pak ... then loads and adds pak1.pak pak2.pak ...
================ ================
*/ */
@ -319,7 +316,7 @@ void FS_AddGameDirectory( const char *dir, uint flags )
int i; int i;
stringlistinit( &list ); stringlistinit( &list );
listdirectory( &list, dir, false ); listdirectory( &list, dir );
stringlistsort( &list ); stringlistsort( &list );
// add any PAK package in the directory // add any PAK package in the directory
@ -351,10 +348,7 @@ void FS_AddGameDirectory( const char *dir, uint flags )
// (unpacked files have the priority over packed files) // (unpacked files have the priority over packed files)
search = FS_AddDir_Fullpath( dir, NULL, flags ); search = FS_AddDir_Fullpath( dir, NULL, flags );
if( !FBitSet( flags, FS_NOWRITE_PATH )) if( !FBitSet( flags, FS_NOWRITE_PATH ))
{
Q_strncpy( fs_writedir, dir, sizeof( fs_writedir ));
fs_writepath = search; fs_writepath = search;
}
} }
/* /*
@ -1318,7 +1312,7 @@ qboolean FS_InitStdio( qboolean caseinsensitive, const char *rootdir, const char
} }
stringlistinit( &dirs ); stringlistinit( &dirs );
listdirectory( &dirs, fs_rodir, false ); listdirectory( &dirs, fs_rodir );
stringlistsort( &dirs ); stringlistsort( &dirs );
for( i = 0; i < dirs.numstrings; i++ ) for( i = 0; i < dirs.numstrings; i++ )
@ -1342,7 +1336,7 @@ qboolean FS_InitStdio( qboolean caseinsensitive, const char *rootdir, const char
// validate directories // validate directories
stringlistinit( &dirs ); stringlistinit( &dirs );
listdirectory( &dirs, "./", false ); listdirectory( &dirs, "./" );
stringlistsort( &dirs ); stringlistsort( &dirs );
for( i = 0; i < dirs.numstrings; i++ ) for( i = 0; i < dirs.numstrings; i++ )
@ -1794,8 +1788,11 @@ file_t *FS_Open( const char *filepath, const char *mode, qboolean gamedironly )
char real_path[MAX_SYSPATH]; char real_path[MAX_SYSPATH];
// open the file on disk directly // open the file on disk directly
Q_sprintf( real_path, "%s/%s", fs_writedir, filepath ); if( !FS_FixFileCase( fs_writepath->dir, filepath, real_path, sizeof( real_path ), true ))
return NULL;
FS_CreatePath( real_path ); // Create directories up to the file FS_CreatePath( real_path ); // Create directories up to the file
return FS_SysOpen( real_path, mode ); return FS_SysOpen( real_path, mode );
} }
@ -2455,25 +2452,40 @@ rename specified file from gamefolder
*/ */
qboolean FS_Rename( const char *oldname, const char *newname ) qboolean FS_Rename( const char *oldname, const char *newname )
{ {
char oldpath[MAX_SYSPATH], newpath[MAX_SYSPATH]; char oldname2[MAX_SYSPATH], newname2[MAX_SYSPATH], oldpath[MAX_SYSPATH], newpath[MAX_SYSPATH];
qboolean iRet; int ret;
if( !oldname || !newname || !*oldname || !*newname ) if( !COM_CheckString( oldname ) || !COM_CheckString( newname ))
return false; return false;
// no work done // no work done
if( !Q_stricmp( oldname, newname )) if( !Q_stricmp( oldname, newname ))
return true; return true;
Q_snprintf( oldpath, sizeof( oldpath ), "%s%s", fs_writedir, oldname ); // fix up slashes
Q_snprintf( newpath, sizeof( newpath ), "%s%s", fs_writedir, newname ); Q_strncpy( oldname2, oldname, sizeof( oldname2 ));
Q_strncpy( newname2, newname, sizeof( newname2 ));
COM_FixSlashes( oldpath ); COM_FixSlashes( oldname2 );
COM_FixSlashes( newpath ); COM_FixSlashes( newname2 );
iRet = rename( oldpath, newpath ); // file does not exist
if( !FS_FixFileCase( fs_writepath->dir, oldname2, oldpath, sizeof( oldpath ), false ))
return false;
// exit if overflowed
if( !FS_FixFileCase( fs_writepath->dir, newname2, newpath, sizeof( newpath ), true ))
return false;
ret = rename( oldpath, newpath );
if( ret < 0 )
{
Con_Printf( "%s: failed to rename file %s (%s) to %s (%s): %s\n",
__FUNCTION__, oldpath, oldname2, newpath, newname2, strerror( errno ));
return false;
}
return (iRet == 0); return true;
} }
/* /*
@ -2485,17 +2497,26 @@ delete specified file from gamefolder
*/ */
qboolean GAME_EXPORT FS_Delete( const char *path ) qboolean GAME_EXPORT FS_Delete( const char *path )
{ {
char real_path[MAX_SYSPATH]; char path2[MAX_SYSPATH], real_path[MAX_SYSPATH];
qboolean iRet; int ret;
if( !path || !*path ) if( !COM_CheckString( path ))
return false; return false;
Q_snprintf( real_path, sizeof( real_path ), "%s%s", fs_writedir, path ); Q_strncpy( path2, path, sizeof( path2 ));
COM_FixSlashes( real_path ); COM_FixSlashes( path2 );
iRet = remove( real_path );
return (iRet == 0); if( !FS_FixFileCase( fs_writepath->dir, path2, real_path, sizeof( real_path ), true ))
return true;
ret = remove( real_path );
if( ret < 0 )
{
Con_Printf( "%s: failed to delete file %s (%s): %s\n", __FUNCTION__, real_path, path, strerror( errno ));
return false;
}
return true;
} }
/* /*
@ -2556,7 +2577,7 @@ search_t *FS_Search( const char *pattern, int caseinsensitive, int gamedironly )
{ {
if( gamedironly && !FBitSet( searchpath->flags, FS_GAMEDIRONLY_SEARCH_FLAGS )) if( gamedironly && !FBitSet( searchpath->flags, FS_GAMEDIRONLY_SEARCH_FLAGS ))
continue; continue;
searchpath->pfnSearch( searchpath, &resultlist, pattern, caseinsensitive ); searchpath->pfnSearch( searchpath, &resultlist, pattern, caseinsensitive );
} }

7
filesystem/filesystem_internal.h

@ -70,7 +70,7 @@ typedef struct searchpath_s
string filename; string filename;
int type; int type;
int flags; int flags;
union union
{ {
dir_t *dir; dir_t *dir;
@ -91,12 +91,12 @@ typedef struct searchpath_s
extern fs_globals_t FI; extern fs_globals_t FI;
extern searchpath_t *fs_searchpaths; extern searchpath_t *fs_searchpaths;
extern searchpath_t *fs_writepath;
extern poolhandle_t fs_mempool; extern poolhandle_t fs_mempool;
extern fs_interface_t g_engfuncs; extern fs_interface_t g_engfuncs;
extern qboolean fs_ext_path; extern qboolean fs_ext_path;
extern char fs_rodir[MAX_SYSPATH]; extern char fs_rodir[MAX_SYSPATH];
extern char fs_rootdir[MAX_SYSPATH]; extern char fs_rootdir[MAX_SYSPATH];
extern char fs_writedir[MAX_SYSPATH];
extern fs_api_t g_api; extern fs_api_t g_api;
#define GI FI.GameInfo #define GI FI.GameInfo
@ -164,7 +164,7 @@ void stringlistinit( stringlist_t *list );
void stringlistfreecontents( stringlist_t *list ); void stringlistfreecontents( stringlist_t *list );
void stringlistappend( stringlist_t *list, char *text ); void stringlistappend( stringlist_t *list, char *text );
void stringlistsort( stringlist_t *list ); void stringlistsort( stringlist_t *list );
void listdirectory( stringlist_t *list, const char *path, qboolean lowercase ); void listdirectory( stringlist_t *list, const char *path );
// filesystem ops // filesystem ops
int FS_FileExists( const char *filename, int gamedironly ); int FS_FileExists( const char *filename, int gamedironly );
@ -212,6 +212,7 @@ qboolean FS_AddZip_Fullpath( const char *zipfile, qboolean *already_loaded, int
// dir.c // dir.c
// //
searchpath_t *FS_AddDir_Fullpath( const char *path, qboolean *already_loaded, int flags ); searchpath_t *FS_AddDir_Fullpath( const char *path, qboolean *already_loaded, int flags );
qboolean FS_FixFileCase( dir_t *dir, const char *path, char *dst, const size_t len, qboolean createpath );
void FS_InitDirectorySearchpath( searchpath_t *search, const char *path, int flags ); void FS_InitDirectorySearchpath( searchpath_t *search, const char *path, int flags );
#ifdef __cplusplus #ifdef __cplusplus

Loading…
Cancel
Save