mirror of
https://github.com/FWGS/xash3d-fwgs
synced 2024-11-25 11:19:59 +01:00
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
This commit is contained in:
parent
41aa867a21
commit
fe1aba3561
@ -49,7 +49,7 @@ static inline const char* IdToDir( const char *id )
|
||||
else if( !Q_strcmp( id, "GAMEDOWNLOAD" ))
|
||||
return va( "%s/downloaded", GI->gamefolder );
|
||||
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" ))
|
||||
return "platform"; // stub
|
||||
else if( !Q_strcmp( id, "CONFIG" ))
|
||||
|
283
filesystem/dir.c
283
filesystem/dir.c
@ -41,7 +41,7 @@ typedef struct dir_s
|
||||
struct dir_s *entries; // sorted
|
||||
} 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 *b = _b;
|
||||
@ -65,25 +65,19 @@ static void FS_InitDirEntries( dir_t *dir, const stringlist_t *list )
|
||||
{
|
||||
int i;
|
||||
|
||||
if( !list->numstrings )
|
||||
{
|
||||
dir->numentries = DIRENTRY_EMPTY_DIRECTORY;
|
||||
dir->entries = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
dir->numentries = list->numstrings;
|
||||
dir->entries = Mem_Malloc( fs_mempool, sizeof( dir_t ) * dir->numentries );
|
||||
|
||||
for( i = 0; i < list->numstrings; i++ )
|
||||
{
|
||||
dir_t *entry = &dir->entries[i];
|
||||
|
||||
Q_strncpy( entry->name, list->strings[i], sizeof( entry->name ));
|
||||
entry->numentries = DIRENTRY_NOT_SCANNED;
|
||||
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 )
|
||||
@ -102,8 +96,16 @@ static void FS_PopulateDirEntries( dir_t *dir, const char *path )
|
||||
}
|
||||
|
||||
stringlistinit( &list );
|
||||
listdirectory( &list, path, false );
|
||||
listdirectory( &list, path );
|
||||
if( !list.numstrings )
|
||||
{
|
||||
dir->numentries = DIRENTRY_EMPTY_DIRECTORY;
|
||||
dir->entries = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
FS_InitDirEntries( dir, &list );
|
||||
}
|
||||
stringlistfreecontents( &list );
|
||||
#endif
|
||||
}
|
||||
@ -112,12 +114,10 @@ static int FS_FindDirEntry( dir_t *dir, const char *name )
|
||||
{
|
||||
int left, right;
|
||||
|
||||
if( dir->numentries < 0 )
|
||||
return -1;
|
||||
|
||||
// look for the file (binary search)
|
||||
left = 0;
|
||||
right = dir->numentries - 1;
|
||||
|
||||
while( left <= right )
|
||||
{
|
||||
int middle = (left + right) / 2;
|
||||
@ -142,30 +142,37 @@ static void FS_MergeDirEntries( dir_t *dir, const stringlist_t *list )
|
||||
int i;
|
||||
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 );
|
||||
|
||||
// copy all entries that has the same name and has subentries
|
||||
for( i = 0; i < dir->numentries; i++ )
|
||||
{
|
||||
dir_t *oldentry = &dir->entries[i];
|
||||
dir_t *newentry;
|
||||
int j;
|
||||
|
||||
// don't care about directories without subentries
|
||||
if( dir->entries == NULL )
|
||||
if( oldentry->entries == NULL )
|
||||
continue;
|
||||
|
||||
// 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
|
||||
if( j < 0 )
|
||||
{
|
||||
FS_FreeDirEntries( &dir->entries[i] );
|
||||
FS_FreeDirEntries( oldentry );
|
||||
continue;
|
||||
}
|
||||
|
||||
// found directory, move all entries
|
||||
temp.entries[j].numentries = dir->entries[i].numentries;
|
||||
temp.entries[j].entries = dir->entries[i].entries;
|
||||
newentry = &temp.entries[j];
|
||||
|
||||
newentry->numentries = oldentry->numentries;
|
||||
newentry->entries = oldentry->entries;
|
||||
}
|
||||
|
||||
// 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 )
|
||||
{
|
||||
stringlist_t list;
|
||||
qboolean update = false;
|
||||
int idx;
|
||||
int ret;
|
||||
|
||||
stringlistinit( &list );
|
||||
listdirectory( &list, path, false );
|
||||
listdirectory( &list, path );
|
||||
|
||||
// find the reason to update entries list
|
||||
if( list.numstrings != dir->numentries )
|
||||
if( list.numstrings == 0 ) // empty directory
|
||||
{
|
||||
// small optimization to not search string in the list
|
||||
// and directly go updating entries
|
||||
update = true;
|
||||
FS_FreeDirEntries( dir );
|
||||
dir->numentries = DIRENTRY_EMPTY_DIRECTORY;
|
||||
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
|
||||
{
|
||||
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 ))
|
||||
{
|
||||
update = true;
|
||||
if( !Q_stricmp( list.strings[i], entryname ))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !update )
|
||||
if( i != list.numstrings )
|
||||
{
|
||||
stringlistfreecontents( &list );
|
||||
return -1;
|
||||
}
|
||||
|
||||
FS_MergeDirEntries( dir, &list );
|
||||
stringlistfreecontents( &list );
|
||||
return FS_FindDirEntry( dir, entryname );
|
||||
ret = FS_FindDirEntry( dir, entryname );
|
||||
}
|
||||
else ret = -1;
|
||||
}
|
||||
|
||||
#if 1
|
||||
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
|
||||
stringlistfreecontents( &list );
|
||||
return ret;
|
||||
}
|
||||
|
||||
while( true )
|
||||
static inline qboolean FS_AppendToPath( char *dst, size_t *pi, const size_t len, const char *src, const char *path, const char *err )
|
||||
{
|
||||
size_t i = *pi;
|
||||
|
||||
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];
|
||||
int ret;
|
||||
|
||||
// this subdirectory is case insensitive, just slam everything that's left
|
||||
if( dir->numentries == DIRENTRY_CASEINSENSITIVE )
|
||||
{
|
||||
i += Q_strncpy( &dst[i], prev, len - i );
|
||||
if( i >= len )
|
||||
{
|
||||
Con_Printf( "%s: overflow while searching %s (caseinsensitive entry)\n", __FUNCTION__, path );
|
||||
if( !FS_AppendToPath( dst, &i, len, prev, path, "caseinsensitive entry" ))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// populate cache if needed
|
||||
if( dir->numentries == DIRENTRY_NOT_SCANNED )
|
||||
{
|
||||
// read directory first time
|
||||
FS_PopulateDirEntries( dir, dst );
|
||||
uptodate = true;
|
||||
}
|
||||
|
||||
// get our entry name
|
||||
Q_strncpy( entryname, prev, next - prev + 1 );
|
||||
ret = FS_FindDirEntry( dir, entryname );
|
||||
|
||||
// didn't found, but does it exists in FS?
|
||||
if( ret < 0 )
|
||||
{
|
||||
ret = FS_MaybeUpdateDirEntries( dir, dst, entryname );
|
||||
|
||||
if( ret < 0 )
|
||||
if(( ret = FS_FindDirEntry( dir, entryname )) < 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)\n", __FUNCTION__, path );
|
||||
return false;
|
||||
}
|
||||
if( uptodate || ( ret = FS_MaybeUpdateDirEntries( dir, dst, entryname )) < 0 )
|
||||
return createpath ? FS_AppendToPath( dst, &i, len, prev, path, "create path" ) : false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
uptodate = true;
|
||||
}
|
||||
|
||||
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" ))
|
||||
return false;
|
||||
|
||||
// file not found, rescan...
|
||||
if( !FS_SysFileOrFolderExists( dst ))
|
||||
if( !uptodate && !FS_SysFileOrFolderExists( dst )) // file not found, rescan...
|
||||
{
|
||||
// strip failed part
|
||||
dst[i] = 0;
|
||||
dst[i] = 0; // strip failed part
|
||||
|
||||
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;
|
||||
}
|
||||
if(( ret = FS_MaybeUpdateDirEntries( dir, dst, entryname )) < 0 )
|
||||
return createpath ? FS_AppendToPath( dst, &i, len, prev, path, "create path rescan" ) : 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 );
|
||||
if( !FS_AppendToPath( dst, &temp, len, dir->name, path, "case fix rescan" ))
|
||||
return false;
|
||||
}
|
||||
i = temp;
|
||||
|
||||
// end of string, found file, return
|
||||
if( next[0] == '\0' )
|
||||
if( next[0] == '\0' || ( next[0] == PATH_SEPARATOR && next[1] == '\0' ))
|
||||
break;
|
||||
|
||||
// move pointer one character forward, find next path split character
|
||||
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 );
|
||||
if( !FS_AppendToPath( dst, &i, len, PATH_SEPARATOR_STR, path, "path separator" ))
|
||||
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 );
|
||||
listdirectory( &list, dst, false );
|
||||
|
||||
for( idx = 0; idx < list.numstrings; idx++ )
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stringlistfreecontents( &list );
|
||||
return false;
|
||||
}
|
||||
|
||||
stringlistfreecontents( &list );
|
||||
|
||||
// end of string, found file, return
|
||||
if( next[0] == '\0' )
|
||||
break;
|
||||
|
||||
// move pointer one character forward, find next path split character
|
||||
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 true;
|
||||
}
|
||||
#endif
|
||||
|
||||
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];
|
||||
|
||||
Q_strncpy( netpath, search->filename, sizeof( netpath ));
|
||||
if( !FS_FixFileCase( search->dir, path, netpath, sizeof( netpath ), false ))
|
||||
return -1;
|
||||
|
||||
@ -438,10 +369,14 @@ static void FS_Search_DIR( searchpath_t *search, stringlist_t *list, const char
|
||||
if( basepathlength ) memcpy( basepath, pattern, basepathlength );
|
||||
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 );
|
||||
listdirectory( &dirlist, netpath, caseinsensitive );
|
||||
listdirectory( &dirlist, netpath );
|
||||
|
||||
Q_strncpy( temp, basepath, sizeof( temp ));
|
||||
|
||||
@ -500,7 +435,7 @@ void FS_InitDirectorySearchpath( searchpath_t *search, const char *path, int fla
|
||||
|
||||
// create cache root
|
||||
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 );
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,6 @@ poolhandle_t fs_mempool;
|
||||
searchpath_t *fs_searchpaths = NULL; // chain
|
||||
char fs_rodir[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;
|
||||
|
||||
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
|
||||
char pattern[4096];
|
||||
struct _finddata_t n_file;
|
||||
@ -307,7 +304,7 @@ static qboolean FS_AddArchive_Fullpath( const char *file, qboolean *already_load
|
||||
================
|
||||
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 ...
|
||||
================
|
||||
*/
|
||||
@ -319,7 +316,7 @@ void FS_AddGameDirectory( const char *dir, uint flags )
|
||||
int i;
|
||||
|
||||
stringlistinit( &list );
|
||||
listdirectory( &list, dir, false );
|
||||
listdirectory( &list, dir );
|
||||
stringlistsort( &list );
|
||||
|
||||
// add any PAK package in the directory
|
||||
@ -351,11 +348,8 @@ void FS_AddGameDirectory( const char *dir, uint flags )
|
||||
// (unpacked files have the priority over packed files)
|
||||
search = FS_AddDir_Fullpath( dir, NULL, flags );
|
||||
if( !FBitSet( flags, FS_NOWRITE_PATH ))
|
||||
{
|
||||
Q_strncpy( fs_writedir, dir, sizeof( fs_writedir ));
|
||||
fs_writepath = search;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
@ -1318,7 +1312,7 @@ qboolean FS_InitStdio( qboolean caseinsensitive, const char *rootdir, const char
|
||||
}
|
||||
|
||||
stringlistinit( &dirs );
|
||||
listdirectory( &dirs, fs_rodir, false );
|
||||
listdirectory( &dirs, fs_rodir );
|
||||
stringlistsort( &dirs );
|
||||
|
||||
for( i = 0; i < dirs.numstrings; i++ )
|
||||
@ -1342,7 +1336,7 @@ qboolean FS_InitStdio( qboolean caseinsensitive, const char *rootdir, const char
|
||||
|
||||
// validate directories
|
||||
stringlistinit( &dirs );
|
||||
listdirectory( &dirs, "./", false );
|
||||
listdirectory( &dirs, "./" );
|
||||
stringlistsort( &dirs );
|
||||
|
||||
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];
|
||||
|
||||
// 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
|
||||
|
||||
return FS_SysOpen( real_path, mode );
|
||||
}
|
||||
|
||||
@ -2455,25 +2452,40 @@ rename specified file from gamefolder
|
||||
*/
|
||||
qboolean FS_Rename( const char *oldname, const char *newname )
|
||||
{
|
||||
char oldpath[MAX_SYSPATH], newpath[MAX_SYSPATH];
|
||||
qboolean iRet;
|
||||
char oldname2[MAX_SYSPATH], newname2[MAX_SYSPATH], oldpath[MAX_SYSPATH], newpath[MAX_SYSPATH];
|
||||
int ret;
|
||||
|
||||
if( !oldname || !newname || !*oldname || !*newname )
|
||||
if( !COM_CheckString( oldname ) || !COM_CheckString( newname ))
|
||||
return false;
|
||||
|
||||
// no work done
|
||||
if( !Q_stricmp( oldname, newname ))
|
||||
return true;
|
||||
|
||||
Q_snprintf( oldpath, sizeof( oldpath ), "%s%s", fs_writedir, oldname );
|
||||
Q_snprintf( newpath, sizeof( newpath ), "%s%s", fs_writedir, newname );
|
||||
// fix up slashes
|
||||
Q_strncpy( oldname2, oldname, sizeof( oldname2 ));
|
||||
Q_strncpy( newname2, newname, sizeof( newname2 ));
|
||||
|
||||
COM_FixSlashes( oldpath );
|
||||
COM_FixSlashes( newpath );
|
||||
COM_FixSlashes( oldname2 );
|
||||
COM_FixSlashes( newname2 );
|
||||
|
||||
iRet = rename( oldpath, newpath );
|
||||
// file does not exist
|
||||
if( !FS_FixFileCase( fs_writepath->dir, oldname2, oldpath, sizeof( oldpath ), false ))
|
||||
return false;
|
||||
|
||||
return (iRet == 0);
|
||||
// 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 true;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2485,17 +2497,26 @@ delete specified file from gamefolder
|
||||
*/
|
||||
qboolean GAME_EXPORT FS_Delete( const char *path )
|
||||
{
|
||||
char real_path[MAX_SYSPATH];
|
||||
qboolean iRet;
|
||||
char path2[MAX_SYSPATH], real_path[MAX_SYSPATH];
|
||||
int ret;
|
||||
|
||||
if( !path || !*path )
|
||||
if( !COM_CheckString( path ))
|
||||
return false;
|
||||
|
||||
Q_snprintf( real_path, sizeof( real_path ), "%s%s", fs_writedir, path );
|
||||
COM_FixSlashes( real_path );
|
||||
iRet = remove( real_path );
|
||||
Q_strncpy( path2, path, sizeof( path2 ));
|
||||
COM_FixSlashes( path2 );
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -91,12 +91,12 @@ typedef struct searchpath_s
|
||||
|
||||
extern fs_globals_t FI;
|
||||
extern searchpath_t *fs_searchpaths;
|
||||
extern searchpath_t *fs_writepath;
|
||||
extern poolhandle_t fs_mempool;
|
||||
extern fs_interface_t g_engfuncs;
|
||||
extern qboolean fs_ext_path;
|
||||
extern char fs_rodir[MAX_SYSPATH];
|
||||
extern char fs_rootdir[MAX_SYSPATH];
|
||||
extern char fs_writedir[MAX_SYSPATH];
|
||||
extern fs_api_t g_api;
|
||||
|
||||
#define GI FI.GameInfo
|
||||
@ -164,7 +164,7 @@ void stringlistinit( stringlist_t *list );
|
||||
void stringlistfreecontents( stringlist_t *list );
|
||||
void stringlistappend( stringlist_t *list, char *text );
|
||||
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
|
||||
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
|
||||
//
|
||||
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 );
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
Loading…
Reference in New Issue
Block a user