summaryrefslogtreecommitdiff
path: root/source/files.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/files.c')
-rw-r--r--source/files.c2533
1 files changed, 1307 insertions, 1226 deletions
diff --git a/source/files.c b/source/files.c
index b6a8871..120d564 100644
--- a/source/files.c
+++ b/source/files.c
@@ -39,8 +39,8 @@ QUAKE FILESYSTEM
=============================================================================
*/
-#define MAX_FILES_IN_PK2 0x4000
-#define MAX_FILE_HANDLES 8
+#define MAX_FILES_IN_PK2 0x4000
+#define MAX_FILE_HANDLES 8
// macros for dealing portably with files at OS level
#ifdef _WIN32
@@ -51,8 +51,8 @@ QUAKE FILESYSTEM
#define FS_strncmp strncmp
#endif
-#define MAX_READ 0x40000 // read in blocks of 256k
-#define MAX_WRITE 0x40000 // write in blocks of 256k
+#define MAX_READ 0x40000 // read in blocks of 256k
+#define MAX_WRITE 0x40000 // write in blocks of 256k
//
@@ -60,54 +60,54 @@ QUAKE FILESYSTEM
//
typedef struct packfile_s {
- char *name;
- size_t filepos;
- size_t filelen;
+ char *name;
+ size_t filepos;
+ size_t filelen;
- struct packfile_s *hashNext;
+ struct packfile_s *hashNext;
} packfile_t;
typedef struct pack_s {
#if USE_ZLIB
- unzFile zFile;
+ unzFile zFile;
#endif
- FILE *fp;
- int numfiles;
- packfile_t *files;
- packfile_t **fileHash;
- int hashSize;
- char filename[1];
+ FILE *fp;
+ int numfiles;
+ packfile_t *files;
+ packfile_t **fileHash;
+ int hashSize;
+ char filename[1];
} pack_t;
typedef struct searchpath_s {
- struct searchpath_s *next;
+ struct searchpath_s *next;
int mode;
- struct pack_s *pack; // only one of filename / pack will be used
- char filename[1];
+ struct pack_s *pack; // only one of filename / pack will be used
+ char filename[1];
} searchpath_t;
typedef enum fsFileType_e {
- FS_FREE,
- FS_REAL,
- FS_PAK,
+ FS_FREE,
+ FS_REAL,
+ FS_PAK,
#if USE_ZLIB
- FS_PK2,
- FS_GZIP,
+ FS_PK2,
+ FS_GZIP,
#endif
- FS_BAD
+ FS_BAD
} fsFileType_t;
typedef struct fsFile_s {
- char fullpath[MAX_OSPATH];
- fsFileType_t type;
- unsigned mode;
- FILE *fp;
+ char fullpath[MAX_OSPATH];
+ fsFileType_t type;
+ unsigned mode;
+ FILE *fp;
#if USE_ZLIB
- void *zfp;
+ void *zfp;
#endif
- packfile_t *pak;
- qboolean unique;
- size_t length;
+ packfile_t *pak;
+ qboolean unique;
+ size_t length;
} fsFile_t;
typedef struct fsLink_s {
@@ -118,26 +118,26 @@ typedef struct fsLink_s {
} fsLink_t;
// these point to user home directory
-static char fs_gamedir[MAX_OSPATH];
-//static char fs_basedir[MAX_OSPATH];
+static char fs_gamedir[MAX_OSPATH];
+//static char fs_basedir[MAX_OSPATH];
-static cvar_t *fs_debug;
-static cvar_t *fs_restrict_mask;
+static cvar_t *fs_debug;
+static cvar_t *fs_restrict_mask;
-static searchpath_t *fs_searchpaths;
-static searchpath_t *fs_base_searchpaths;
+static searchpath_t *fs_searchpaths;
+static searchpath_t *fs_base_searchpaths;
static fsLink_t *fs_links;
-static fsFile_t fs_files[MAX_FILE_HANDLES];
+static fsFile_t fs_files[MAX_FILE_HANDLES];
-static qboolean fs_fileFromPak;
+static qboolean fs_fileFromPak;
static int fs_count_read, fs_count_strcmp, fs_count_open;
-cvar_t *fs_game;
+cvar_t *fs_game;
-fsAPI_t fs;
+fsAPI_t fs;
/*
@@ -159,22 +159,72 @@ This is a precacution against having a malicious server instruct clients to writ
/*
================
+FS_pathcmp
+
+Portably compares quake paths
+================
+*/
+static int FS_pathcmp( const char *s1, const char *s2 ) {
+ int c1, c2;
+
+ do {
+ c1 = *s1++;
+ c2 = *s2++;
+
+ if( c1 != c2 ) {
+ c1 = c1 == '\\' ? '/' : Q_tolower( c1 );
+ c2 = c2 == '\\' ? '/' : Q_tolower( c2 );
+ if( c1 < c2 )
+ return -1;
+ if( c1 > c2 )
+ return 1; /* strings not equal */
+ }
+ } while( c1 );
+
+ return 0; /* strings are equal */
+}
+
+static int FS_pathcmpn( const char *s1, const char *s2, size_t n ) {
+ int c1, c2;
+
+ do {
+ c1 = *s1++;
+ c2 = *s2++;
+
+ if( !n-- )
+ return 0; /* strings are equal until end point */
+
+ if( c1 != c2 ) {
+ c1 = c1 == '\\' ? '/' : Q_tolower( c1 );
+ c2 = c2 == '\\' ? '/' : Q_tolower( c2 );
+ if( c1 < c2 )
+ return -1;
+ if( c1 > c2 )
+ return 1; /* strings not equal */
+ }
+ } while( c1 );
+
+ return 0; /* strings are equal */
+}
+
+/*
+================
FS_DPrintf
================
*/
static void FS_DPrintf( char *format, ... ) {
- va_list argptr;
- char string[MAXPRINTMSG];
+ va_list argptr;
+ char string[MAXPRINTMSG];
- if( !fs_debug || !fs_debug->integer ) {
- return;
- }
+ if( !fs_debug || !fs_debug->integer ) {
+ return;
+ }
- va_start( argptr, format );
- Q_vsnprintf( string, sizeof( string ), format, argptr );
- va_end( argptr );
+ va_start( argptr, format );
+ Q_vsnprintf( string, sizeof( string ), format, argptr );
+ va_end( argptr );
- Com_Printf( S_COLOR_CYAN "%s", string );
+ Com_Printf( S_COLOR_CYAN "%s", string );
}
/*
@@ -183,21 +233,21 @@ FS_AllocHandle
================
*/
static fsFile_t *FS_AllocHandle( fileHandle_t *f ) {
- fsFile_t *file;
- int i;
+ fsFile_t *file;
+ int i;
- for( i = 0, file = fs_files; i < MAX_FILE_HANDLES; i++, file++ ) {
- if( file->type == FS_FREE ) {
- break;
- }
- }
+ for( i = 0, file = fs_files; i < MAX_FILE_HANDLES; i++, file++ ) {
+ if( file->type == FS_FREE ) {
+ break;
+ }
+ }
- if( i == MAX_FILE_HANDLES ) {
- Com_Error( ERR_FATAL, "%s: none free", __func__ );
- }
+ if( i == MAX_FILE_HANDLES ) {
+ Com_Error( ERR_FATAL, "%s: none free", __func__ );
+ }
- *f = i + 1;
- return file;
+ *f = i + 1;
+ return file;
}
/*
@@ -206,22 +256,22 @@ FS_FileForHandle
================
*/
static fsFile_t *FS_FileForHandle( fileHandle_t f ) {
- fsFile_t *file;
+ fsFile_t *file;
- if( f <= 0 || f >= MAX_FILE_HANDLES + 1 ) {
- Com_Error( ERR_FATAL, "%s: invalid handle: %i", __func__, f );
- }
+ if( f <= 0 || f >= MAX_FILE_HANDLES + 1 ) {
+ Com_Error( ERR_FATAL, "%s: invalid handle: %i", __func__, f );
+ }
- file = &fs_files[f - 1];
- if( file->type == FS_FREE ) {
- Com_Error( ERR_FATAL, "%s: free handle: %i", __func__, f );
- }
+ file = &fs_files[f - 1];
+ if( file->type == FS_FREE ) {
+ Com_Error( ERR_FATAL, "%s: free handle: %i", __func__, f );
+ }
- if( file->type < FS_FREE || file->type >= FS_BAD ) {
- Com_Error( ERR_FATAL, "%s: invalid file type: %i", __func__, file->type );
- }
+ if( file->type < FS_FREE || file->type >= FS_BAD ) {
+ Com_Error( ERR_FATAL, "%s: invalid file type: %i", __func__, file->type );
+ }
- return file;
+ return file;
}
/*
@@ -230,42 +280,42 @@ FS_ValidatePath
================
*/
static qboolean FS_ValidatePath( const char *s ) {
- const char *start;
-
- // check for leading slash
- // check for empty path
- if( *s == '/' || *s == '\\' /*|| *s == 0*/ ) {
- return qfalse;
- }
-
- start = s;
- while( *s ) {
- // check for ".."
- if( *s == '.' && s[1] == '.' ) {
- return qfalse;
- }
- if( *s == '/' || *s == '\\' ) {
- // check for two slashes in a row
- // check for trailing slash
- if( ( s[1] == '/' || s[1] == '\\' || s[1] == 0 ) ) {
- return qfalse;
- }
- }
- if( *s == ':' ) {
- // check for "X:\"
- if( s[1] == '\\' || s[1] == '/' ) {
- return qfalse;
- }
- }
- s++;
- }
+ const char *start;
+
+ // check for leading slash
+ // check for empty path
+ if( *s == '/' || *s == '\\' /*|| *s == 0*/ ) {
+ return qfalse;
+ }
+
+ start = s;
+ while( *s ) {
+ // check for ".."
+ if( *s == '.' && s[1] == '.' ) {
+ return qfalse;
+ }
+ if( *s == '/' || *s == '\\' ) {
+ // check for two slashes in a row
+ // check for trailing slash
+ if( ( s[1] == '/' || s[1] == '\\' || s[1] == 0 ) ) {
+ return qfalse;
+ }
+ }
+ if( *s == ':' ) {
+ // check for "X:\"
+ if( s[1] == '\\' || s[1] == '/' ) {
+ return qfalse;
+ }
+ }
+ s++;
+ }
// check length
- if( s - start > MAX_OSPATH ) {
- return qfalse;
- }
+ if( s - start > MAX_OSPATH ) {
+ return qfalse;
+ }
- return qtrue;
+ return qtrue;
}
/*
@@ -274,17 +324,17 @@ FS_ReplaceSeparators
================
*/
char *FS_ReplaceSeparators( char *s, int separator ) {
- char *p;
+ char *p;
- p = s;
- while( *p ) {
- if( *p == '/' || *p == '\\' ) {
- *p = separator;
- }
- p++;
- }
+ p = s;
+ while( *p ) {
+ if( *p == '/' || *p == '\\' ) {
+ *p = separator;
+ }
+ p++;
+ }
- return s;
+ return s;
}
@@ -298,32 +348,32 @@ Returns compressed length for GZIP files.
================
*/
size_t FS_GetFileLength( fileHandle_t f ) {
- fsFile_t *file = FS_FileForHandle( f );
+ fsFile_t *file = FS_FileForHandle( f );
fsFileInfo_t info;
- switch( file->type ) {
- case FS_REAL:
+ switch( file->type ) {
+ case FS_REAL:
if( !Sys_GetFileInfo( file->fp, &info ) ) {
return INVALID_LENGTH;
}
- return info.size;
- case FS_PAK:
- return file->length;
+ return info.size;
+ case FS_PAK:
+ return file->length;
#if USE_ZLIB
- case FS_PK2:
- return file->length;
- case FS_GZIP:
+ case FS_PK2:
+ return file->length;
+ case FS_GZIP:
return INVALID_LENGTH;
#endif
default:
- Com_Error( ERR_FATAL, "%s: bad file type", __func__ );
- }
+ Com_Error( ERR_FATAL, "%s: bad file type", __func__ );
+ }
return INVALID_LENGTH;
}
const char *FS_GetFileFullPath( fileHandle_t f ) {
- return ( FS_FileForHandle( f ) )->fullpath;
+ return ( FS_FileForHandle( f ) )->fullpath;
}
/*
@@ -335,29 +385,29 @@ Expects a fully qualified quake path (i.e. with / separators).
============
*/
void FS_CreatePath( const char *path ) {
- char buffer[MAX_OSPATH];
- char *ofs;
+ char buffer[MAX_OSPATH];
+ char *ofs;
- Q_strncpyz( buffer, path, sizeof( buffer ) );
+ Q_strncpyz( buffer, path, sizeof( buffer ) );
- FS_DPrintf( "%s: %s\n", __func__, buffer );
-
- for( ofs = buffer + 1; *ofs; ofs++ ) {
- if( *ofs == '/' ) {
- // create the directory
- *ofs = 0;
- Sys_Mkdir( buffer );
- *ofs = '/';
- }
- }
+ FS_DPrintf( "%s: %s\n", __func__, buffer );
+
+ for( ofs = buffer + 1; *ofs; ofs++ ) {
+ if( *ofs == '/' ) {
+ // create the directory
+ *ofs = 0;
+ Q_mkdir( buffer );
+ *ofs = '/';
+ }
+ }
}
qboolean FS_FilterFile( fileHandle_t f ) {
#if USE_ZLIB
- fsFile_t *file = FS_FileForHandle( f );
+ fsFile_t *file = FS_FileForHandle( f );
int mode;
char *modeStr;
- void *zfp;
+ void *zfp;
switch( file->type ) {
case FS_GZIP:
@@ -368,17 +418,17 @@ qboolean FS_FilterFile( fileHandle_t f ) {
return qfalse;
}
- mode = file->mode & FS_MODE_MASK;
- switch( mode ) {
- case FS_MODE_READ:
+ mode = file->mode & FS_MODE_MASK;
+ switch( mode ) {
+ case FS_MODE_READ:
modeStr = "rb";
break;
- case FS_MODE_WRITE:
- modeStr = "wb";
- break;
- default:
+ case FS_MODE_WRITE:
+ modeStr = "wb";
+ break;
+ default:
return qfalse;
- }
+ }
fseek( file->fp, 0, SEEK_SET );
zfp = gzdopen( fileno( file->fp ), modeStr );
@@ -401,43 +451,43 @@ FS_FCloseFile
==============
*/
void FS_FCloseFile( fileHandle_t f ) {
- fsFile_t *file = FS_FileForHandle( f );
-
- FS_DPrintf( "%s: %s\n", __func__, file->fullpath );
-
- switch( file->type ) {
- case FS_REAL:
- fclose( file->fp );
- break;
- case FS_PAK:
- if( file->unique ) {
- fclose( file->fp );
- }
- break;
+ fsFile_t *file = FS_FileForHandle( f );
+
+ FS_DPrintf( "%s: %s\n", __func__, file->fullpath );
+
+ switch( file->type ) {
+ case FS_REAL:
+ fclose( file->fp );
+ break;
+ case FS_PAK:
+ if( file->unique ) {
+ fclose( file->fp );
+ }
+ break;
#if USE_ZLIB
- case FS_GZIP:
- gzclose( file->zfp );
- break;
- case FS_PK2:
- unzCloseCurrentFile( file->zfp );
- if( file->unique ) {
- unzClose( file->zfp );
- }
- break;
+ case FS_GZIP:
+ gzclose( file->zfp );
+ break;
+ case FS_PK2:
+ unzCloseCurrentFile( file->zfp );
+ if( file->unique ) {
+ unzClose( file->zfp );
+ }
+ break;
#endif
- default:
- break;
- }
+ default:
+ break;
+ }
- // don't clear name and mode, in case
+ // don't clear name and mode, in case
// this handle will be reopened later
- file->type = FS_FREE;
- file->fp = NULL;
+ file->type = FS_FREE;
+ file->fp = NULL;
#if USE_ZLIB
- file->zfp = NULL;
+ file->zfp = NULL;
#endif
- file->pak = NULL;
- file->unique = qfalse;
+ file->pak = NULL;
+ file->unique = qfalse;
}
/*
@@ -446,49 +496,54 @@ FS_FOpenFileWrite
============
*/
static size_t FS_FOpenFileWrite( fsFile_t *file, const char *name ) {
- FILE *fp;
- char *modeStr;
- unsigned mode;
+ FILE *fp;
+ char *modeStr;
+ unsigned mode;
- if( ( file->mode & FS_PATH_MASK ) == FS_PATH_BASE ) {
+ if( !FS_ValidatePath( name ) ) {
+ FS_DPrintf( "%s: refusing invalid path: %s\n", __func__, name );
+ return INVALID_LENGTH;
+ }
+
+ if( ( file->mode & FS_PATH_MASK ) == FS_PATH_BASE ) {
if( sys_homedir->string[0] ) {
- Q_concat( file->fullpath, sizeof( file->fullpath ),
- sys_homedir->string, "/" BASEGAME "/", name, NULL );
+ Q_concat( file->fullpath, sizeof( file->fullpath ),
+ sys_homedir->string, "/" BASEGAME "/", name, NULL );
} else {
- Q_concat( file->fullpath, sizeof( file->fullpath ),
- sys_basedir->string, "/" BASEGAME "/", name, NULL );
- }
- } else {
- Q_concat( file->fullpath, sizeof( file->fullpath ),
- fs_gamedir, "/", name, NULL );
- }
-
- mode = file->mode & FS_MODE_MASK;
- switch( mode ) {
- case FS_MODE_APPEND:
- modeStr = "ab";
- break;
- case FS_MODE_WRITE:
- modeStr = "wb";
- break;
- case FS_MODE_RDWR:
- modeStr = "r+b";
- break;
- default:
- Com_Error( ERR_FATAL, "%s: %s: invalid mode mask",
+ Q_concat( file->fullpath, sizeof( file->fullpath ),
+ sys_basedir->string, "/" BASEGAME "/", name, NULL );
+ }
+ } else {
+ Q_concat( file->fullpath, sizeof( file->fullpath ),
+ fs_gamedir, "/", name, NULL );
+ }
+
+ mode = file->mode & FS_MODE_MASK;
+ switch( mode ) {
+ case FS_MODE_APPEND:
+ modeStr = "ab";
+ break;
+ case FS_MODE_WRITE:
+ modeStr = "wb";
+ break;
+ case FS_MODE_RDWR:
+ modeStr = "r+b";
+ break;
+ default:
+ Com_Error( ERR_FATAL, "%s: %s: invalid mode mask",
__func__, file->fullpath );
- modeStr = NULL;
- break;
- }
+ modeStr = NULL;
+ break;
+ }
- FS_CreatePath( file->fullpath );
+ FS_CreatePath( file->fullpath );
- fp = fopen( file->fullpath, modeStr );
- if( !fp ) {
- FS_DPrintf( "%s: %s: fopen(%s): %s\n",
- __func__, file->fullpath, modeStr, strerror( errno ) );
- return INVALID_LENGTH;
- }
+ fp = fopen( file->fullpath, modeStr );
+ if( !fp ) {
+ FS_DPrintf( "%s: %s: fopen(%s): %s\n",
+ __func__, file->fullpath, modeStr, strerror( errno ) );
+ return INVALID_LENGTH;
+ }
#ifdef __unix__
if( !Sys_GetFileInfo( fp, NULL ) ) {
@@ -499,22 +554,88 @@ static size_t FS_FOpenFileWrite( fsFile_t *file, const char *name ) {
}
#endif
- FS_DPrintf( "%s: %s: succeeded\n", __func__, file->fullpath );
+ FS_DPrintf( "%s: %s: succeeded\n", __func__, file->fullpath );
+
+ file->fp = fp;
+ file->type = FS_REAL;
+ file->length = 0;
+ file->unique = qtrue;
+
+ if( mode == FS_MODE_WRITE ) {
+ return 0;
+ }
+
+ if( mode == FS_MODE_RDWR ) {
+ fseek( fp, 0, SEEK_END );
+ }
+
+ return ( size_t )ftell( fp );
+}
+
+static size_t FS_FOpenFromPak( fsFile_t *file, pack_t *pak, packfile_t *entry, qboolean unique ) {
+ // found it!
+ fs_fileFromPak = qtrue;
+
+ Q_concat( file->fullpath, sizeof( file->fullpath ),
+ pak->filename, "/", entry->name, NULL );
+
+ // open a new file on the pakfile
+#if USE_ZLIB
+ if( pak->zFile ) {
+ void *zfp;
+
+ if( unique ) {
+ zfp = unzReOpen( pak->filename, pak->zFile );
+ if( !zfp ) {
+ Com_Error( ERR_FATAL, "%s: couldn't reopen %s",
+ __func__, pak->filename );
+ }
+ } else {
+ zfp = pak->zFile;
+ }
+ if( unzSetCurrentFileInfoPosition( zfp, entry->filepos ) == -1 ) {
+ Com_Error( ERR_FATAL, "%s: couldn't seek into %s",
+ __func__, pak->filename );
+ }
+ if( unzOpenCurrentFile( zfp ) != UNZ_OK ) {
+ Com_Error( ERR_FATAL, "%s: couldn't open curfile from %s",
+ __func__, pak->filename );
+ }
+
+ file->zfp = zfp;
+ file->type = FS_PK2;
+ } else
+#endif
+ {
+ FILE *fp;
+
+ if( unique ) {
+ fp = fopen( pak->filename, "rb" );
+ if( !fp ) {
+ Com_Error( ERR_FATAL, "%s: couldn't reopen %s",
+ __func__, pak->filename );
+ }
+ } else {
+ fp = pak->fp;
+ }
+
+ if( fseek( fp, entry->filepos, SEEK_SET ) == -1 ) {
+ Com_Error( ERR_FATAL, "%s: couldn't seek into %s",
+ __func__, pak->filename );
+ }
+
+ file->fp = fp;
+ file->type = FS_PAK;
+ }
- file->fp = fp;
- file->type = FS_REAL;
- file->length = 0;
- file->unique = qtrue;
+ file->pak = entry;
+ file->length = entry->filelen;
+ file->unique = unique;
- if( mode == FS_MODE_WRITE ) {
- return 0;
- }
+ FS_DPrintf( "%s: %s/%s: succeeded\n",
+ __func__, pak->filename, entry->name );
- if( mode == FS_MODE_RDWR ) {
- fseek( fp, 0, SEEK_END );
- }
-
- return ( size_t )ftell( fp );
+ return file->length;
}
/*
@@ -530,105 +651,65 @@ a seperate file.
*/
static size_t FS_FOpenFileRead( fsFile_t *file, const char *name, qboolean unique ) {
searchpath_t *search;
- pack_t *pak;
- unsigned hash;
- packfile_t *entry;
- FILE *fp;
+ pack_t *pak;
+ unsigned hash;
+ packfile_t *entry;
+ FILE *fp;
fsFileInfo_t info;
+ int valid = -1;
- fs_fileFromPak = qfalse;
+ fs_fileFromPak = qfalse;
fs_count_read++;
//
// search through the path, one element at a time
//
- hash = Com_HashPath( name, 0 );
-
- for( search = fs_searchpaths; search; search = search->next ) {
- if( file->mode & FS_PATH_MASK ) {
- if( ( file->mode & search->mode & FS_PATH_MASK ) == 0 ) {
- continue;
- }
- }
-
- // is the element a pak file?
- if( search->pack ) {
- if( ( file->mode & FS_TYPE_MASK ) == FS_TYPE_REAL ) {
- continue;
- }
- // look through all the pak file elements
- pak = search->pack;
- entry = pak->fileHash[ hash & ( pak->hashSize - 1 ) ];
- for( ; entry; entry = entry->hashNext ) {
- fs_count_strcmp++;
- if( !Q_stricmp( entry->name, name ) ) {
- // found it!
- fs_fileFromPak = qtrue;
-
- Q_concat( file->fullpath, sizeof( file->fullpath ), pak->filename, "/", entry->name, NULL );
+ hash = Com_HashPath( name, 0 );
- // open a new file on the pakfile
-#if USE_ZLIB
- if( pak->zFile ) {
- void *zfp;
-
- if( unique ) {
- zfp = unzReOpen( pak->filename, pak->zFile );
- if( !zfp ) {
- Com_Error( ERR_FATAL, "%s: %s: unzReOpen failed", __func__, pak->filename );
- }
- } else {
- zfp = pak->zFile;
- }
- if( unzSetCurrentFileInfoPosition( zfp, entry->filepos ) == -1 ) {
- Com_Error( ERR_FATAL, "%s: %s/%s: unzSetCurrentFileInfoPosition failed", __func__, pak->filename, entry->name );
- }
- if( unzOpenCurrentFile( zfp ) != UNZ_OK ) {
- Com_Error( ERR_FATAL, "%s: %s/%s: unzReOpen failed", __func__, pak->filename, entry->name );
- }
-
- file->zfp = zfp;
- file->type = FS_PK2;
- } else
-#endif
- {
- if( unique ) {
- fp = fopen( pak->filename, "rb" );
- if( !fp ) {
- Com_Error( ERR_FATAL, "%s: couldn't reopen %s", __func__, pak->filename );
- }
- } else {
- fp = pak->fp;
- }
-
- fseek( fp, entry->filepos, SEEK_SET );
-
- file->fp = fp;
- file->type = FS_PAK;
- }
-
- file->pak = entry;
- file->length = entry->filelen;
- file->unique = unique;
-
- FS_DPrintf( "%s: %s/%s: succeeded\n", __func__, pak->filename, entry->name );
-
- return file->length;
- }
- }
- } else {
- if( ( file->mode & FS_TYPE_MASK ) == FS_TYPE_PAK ) {
- continue;
- }
- // check a file in the directory tree
- Q_concat( file->fullpath, sizeof( file->fullpath ),
- search->filename, "/", name, NULL );
+ for( search = fs_searchpaths; search; search = search->next ) {
+ if( file->mode & FS_PATH_MASK ) {
+ if( ( file->mode & search->mode & FS_PATH_MASK ) == 0 ) {
+ continue;
+ }
+ }
+
+ // is the element a pak file?
+ if( search->pack ) {
+ if( ( file->mode & FS_TYPE_MASK ) == FS_TYPE_REAL ) {
+ continue;
+ }
+ // look through all the pak file elements
+ pak = search->pack;
+ entry = pak->fileHash[ hash & ( pak->hashSize - 1 ) ];
+ for( ; entry; entry = entry->hashNext ) {
+ fs_count_strcmp++;
+ if( !FS_pathcmp( entry->name, name ) ) {
+ return FS_FOpenFromPak( file, pak, entry, unique );
+ }
+ }
+ } else {
+ if( ( file->mode & FS_TYPE_MASK ) == FS_TYPE_PAK ) {
+ continue;
+ }
+ if( valid == -1 ) {
+ if( !FS_ValidatePath( name ) ) {
+ FS_DPrintf( "%s: refusing invalid path: %s\n",
+ __func__, name );
+ valid = 0;
+ }
+ }
+ if( valid == 0 ) {
+ continue;
+ }
+ // check a file in the directory tree
+ Q_concat( file->fullpath, sizeof( file->fullpath ),
+ search->filename, "/", name, NULL );
fs_count_open++;
- fp = fopen( file->fullpath, "rb" );
- if( !fp ) {
- continue;
- }
+ fp = fopen( file->fullpath, "rb" );
+ if( !fp ) {
+ continue;
+ }
if( !Sys_GetFileInfo( fp, &info ) ) {
FS_DPrintf( "%s: %s: couldn't get info\n",
@@ -637,20 +718,20 @@ static size_t FS_FOpenFileRead( fsFile_t *file, const char *name, qboolean uniqu
continue;
}
- file->fp = fp;
- file->type = FS_REAL;
- file->unique = qtrue;
- file->length = info.size;
+ file->fp = fp;
+ file->type = FS_REAL;
+ file->unique = qtrue;
+ file->length = info.size;
- FS_DPrintf( "%s: %s: succeeded\n", __func__, file->fullpath );
+ FS_DPrintf( "%s: %s: succeeded\n", __func__, file->fullpath );
- return file->length;
- }
- }
-
- FS_DPrintf( "%s: %s: not found\n", __func__, name );
-
- return INVALID_LENGTH;
+ return file->length;
+ }
+ }
+
+ FS_DPrintf( "%s: %s: not found\n", __func__, name );
+
+ return INVALID_LENGTH;
}
/*
@@ -659,7 +740,7 @@ FS_LastFileFromPak
=================
*/
qboolean FS_LastFileFromPak( void ) {
- return fs_fileFromPak;
+ return fs_fileFromPak;
}
@@ -671,51 +752,51 @@ Properly handles partial reads
=================
*/
size_t FS_Read( void *buffer, size_t len, fileHandle_t hFile ) {
- size_t block, remaining = len, read = 0;
- byte *buf = (byte *)buffer;
- fsFile_t *file = FS_FileForHandle( hFile );
-
- // read in chunks for progress bar
- while( remaining ) {
- block = remaining;
- if( block > MAX_READ )
- block = MAX_READ;
- switch( file->type ) {
- case FS_REAL:
- case FS_PAK:
- read = fread( buf, 1, block, file->fp );
- break;
+ size_t block, remaining = len, read = 0;
+ byte *buf = (byte *)buffer;
+ fsFile_t *file = FS_FileForHandle( hFile );
+
+ // read in chunks for progress bar
+ while( remaining ) {
+ block = remaining;
+ if( block > MAX_READ )
+ block = MAX_READ;
+ switch( file->type ) {
+ case FS_REAL:
+ case FS_PAK:
+ read = fread( buf, 1, block, file->fp );
+ break;
#if USE_ZLIB
- case FS_GZIP:
- read = gzread( file->zfp, buf, block );
- break;
- case FS_PK2:
- read = unzReadCurrentFile( file->zfp, buf, block );
- break;
+ case FS_GZIP:
+ read = gzread( file->zfp, buf, block );
+ break;
+ case FS_PK2:
+ read = unzReadCurrentFile( file->zfp, buf, block );
+ break;
#endif
- default:
- break;
- }
- if( read == 0 ) {
- return len - remaining;
- }
- if( read > block ) {
- Com_Error( ERR_FATAL, "FS_Read: %"PRIz" bytes read", read );
+ default:
+ break;
+ }
+ if( read == 0 ) {
+ return len - remaining;
+ }
+ if( read > block ) {
+ Com_Error( ERR_FATAL, "FS_Read: %"PRIz" bytes read", read );
}
- remaining -= read;
- buf += read;
- }
+ remaining -= read;
+ buf += read;
+ }
- return len;
+ return len;
}
size_t FS_ReadLine( fileHandle_t f, char *buffer, int size ) {
- fsFile_t *file = FS_FileForHandle( f );
+ fsFile_t *file = FS_FileForHandle( f );
char *s;
size_t len;
- if( file->type != FS_REAL ) {
+ if( file->type != FS_REAL ) {
return 0;
}
do {
@@ -731,7 +812,7 @@ size_t FS_ReadLine( fileHandle_t f, char *buffer, int size ) {
}
void FS_Flush( fileHandle_t f ) {
- fsFile_t *file = FS_FileForHandle( f );
+ fsFile_t *file = FS_FileForHandle( f );
switch( file->type ) {
case FS_REAL:
@@ -755,55 +836,55 @@ Properly handles partial writes
=================
*/
size_t FS_Write( const void *buffer, size_t len, fileHandle_t hFile ) {
- size_t block, remaining = len, write = 0;
- byte *buf = (byte *)buffer;
- fsFile_t *file = FS_FileForHandle( hFile );
-
- // read in chunks for progress bar
- while( remaining ) {
- block = remaining;
- if( block > MAX_WRITE )
- block = MAX_WRITE;
- switch( file->type ) {
- case FS_REAL:
- write = fwrite( buf, 1, block, file->fp );
- break;
+ size_t block, remaining = len, write = 0;
+ byte *buf = (byte *)buffer;
+ fsFile_t *file = FS_FileForHandle( hFile );
+
+ // read in chunks for progress bar
+ while( remaining ) {
+ block = remaining;
+ if( block > MAX_WRITE )
+ block = MAX_WRITE;
+ switch( file->type ) {
+ case FS_REAL:
+ write = fwrite( buf, 1, block, file->fp );
+ break;
#if USE_ZLIB
- case FS_GZIP:
- write = gzwrite( file->zfp, buf, block );
- break;
+ case FS_GZIP:
+ write = gzwrite( file->zfp, buf, block );
+ break;
#endif
- default:
- Com_Error( ERR_FATAL, "FS_Write: illegal file type" );
- break;
- }
- if( write == 0 ) {
- return len - remaining;
- }
- if( write > block ) {
- Com_Error( ERR_FATAL, "FS_Write: %"PRIz" bytes written", write );
- }
-
- remaining -= write;
- buf += write;
- }
-
- if( ( file->mode & FS_FLUSH_MASK ) == FS_FLUSH_SYNC ) {
- switch( file->type ) {
- case FS_REAL:
- fflush( file->fp );
- break;
+ default:
+ Com_Error( ERR_FATAL, "FS_Write: illegal file type" );
+ break;
+ }
+ if( write == 0 ) {
+ return len - remaining;
+ }
+ if( write > block ) {
+ Com_Error( ERR_FATAL, "FS_Write: %"PRIz" bytes written", write );
+ }
+
+ remaining -= write;
+ buf += write;
+ }
+
+ if( ( file->mode & FS_FLUSH_MASK ) == FS_FLUSH_SYNC ) {
+ switch( file->type ) {
+ case FS_REAL:
+ fflush( file->fp );
+ break;
#if USE_ZLIB
- case FS_GZIP:
- gzflush( file->zfp, Z_SYNC_FLUSH );
- break;
+ case FS_GZIP:
+ gzflush( file->zfp, Z_SYNC_FLUSH );
+ break;
#endif
- default:
- break;
- }
- }
+ default:
+ break;
+ }
+ }
- return len;
+ return len;
}
static char *FS_ExpandLinks( const char *filename ) {
@@ -816,7 +897,7 @@ static char *FS_ExpandLinks( const char *filename ) {
if( l->namelen > length ) {
continue;
}
- if( !Q_stricmpn( l->name, filename, l->namelen ) ) {
+ if( !FS_pathcmpn( l->name, filename, l->namelen ) ) {
if( l->targlen + length - l->namelen >= MAX_OSPATH ) {
FS_DPrintf( "%s: %s: MAX_OSPATH exceeded\n", __func__, filename );
return ( char * )filename;
@@ -838,19 +919,19 @@ FS_FOpenFile
============
*/
size_t FS_FOpenFile( const char *name, fileHandle_t *f, int mode ) {
- fsFile_t *file;
- fileHandle_t hFile;
- size_t ret = INVALID_LENGTH;
+ fsFile_t *file;
+ fileHandle_t hFile;
+ size_t ret = INVALID_LENGTH;
- if( !name || !f ) {
- Com_Error( ERR_FATAL, "FS_FOpenFile: NULL" );
- }
+ if( !name || !f ) {
+ Com_Error( ERR_FATAL, "%s: NULL", __func__ );
+ }
- *f = 0;
+ *f = 0;
- if( !fs_searchpaths ) {
- return ret; // not yet initialized
- }
+ if( !fs_searchpaths ) {
+ return ret; // not yet initialized
+ }
if( *name == '/' ) {
name++;
@@ -860,36 +941,31 @@ size_t FS_FOpenFile( const char *name, fileHandle_t *f, int mode ) {
name = FS_ExpandLinks( name );
}
- if( !FS_ValidatePath( name ) ) {
- FS_DPrintf( "FS_FOpenFile: refusing invalid path: %s\n", name );
- return ret;
- }
+ // allocate new file handle
+ file = FS_AllocHandle( &hFile );
+ file->mode = mode;
- // allocate new file handle
- file = FS_AllocHandle( &hFile );
- file->mode = mode;
-
- mode &= FS_MODE_MASK;
- switch( mode ) {
- case FS_MODE_READ:
- ret = FS_FOpenFileRead( file, name, qtrue );
- break;
- case FS_MODE_WRITE:
- case FS_MODE_APPEND:
- case FS_MODE_RDWR:
- ret = FS_FOpenFileWrite( file, name );
- break;
- default:
- Com_Error( ERR_FATAL, "FS_FOpenFile: illegal mode: %u", mode );
- break;
- }
+ mode &= FS_MODE_MASK;
+ switch( mode ) {
+ case FS_MODE_READ:
+ ret = FS_FOpenFileRead( file, name, qtrue );
+ break;
+ case FS_MODE_WRITE:
+ case FS_MODE_APPEND:
+ case FS_MODE_RDWR:
+ ret = FS_FOpenFileWrite( file, name );
+ break;
+ default:
+ Com_Error( ERR_FATAL, "%s: illegal mode: %u", __func__, mode );
+ break;
+ }
- // if succeeded, store file handle
- if( ret != -1 ) {
- *f = hFile;
- }
+ // if succeeded, store file handle
+ if( ret != -1 ) {
+ *f = hFile;
+ }
- return ret;
+ return ret;
}
@@ -899,30 +975,30 @@ FS_Tell
============
*/
int FS_Tell( fileHandle_t f ) {
- fsFile_t *file = FS_FileForHandle( f );
- int length;
-
- switch( file->type ) {
- case FS_REAL:
- length = ftell( file->fp );
- break;
- case FS_PAK:
- length = ftell( file->fp ) - file->pak->filepos;
- break;
+ fsFile_t *file = FS_FileForHandle( f );
+ int length;
+
+ switch( file->type ) {
+ case FS_REAL:
+ length = ftell( file->fp );
+ break;
+ case FS_PAK:
+ length = ftell( file->fp ) - file->pak->filepos;
+ break;
#if USE_ZLIB
- case FS_GZIP:
- length = gztell( file->zfp );
- break;
- case FS_PK2:
- length = unztell( file->zfp );
- break;
+ case FS_GZIP:
+ length = gztell( file->zfp );
+ break;
+ case FS_PK2:
+ length = unztell( file->zfp );
+ break;
#endif
- default:
- length = -1;
- break;
- }
+ default:
+ length = -1;
+ break;
+ }
- return length;
+ return length;
}
/*
@@ -931,33 +1007,33 @@ FS_RawTell
============
*/
int FS_RawTell( fileHandle_t f ) {
- fsFile_t *file = FS_FileForHandle( f );
- int length;
-
- switch( file->type ) {
- case FS_REAL:
- length = ftell( file->fp );
- break;
- case FS_PAK:
- length = ftell( file->fp ) - file->pak->filepos;
- break;
+ fsFile_t *file = FS_FileForHandle( f );
+ int length;
+
+ switch( file->type ) {
+ case FS_REAL:
+ length = ftell( file->fp );
+ break;
+ case FS_PAK:
+ length = ftell( file->fp ) - file->pak->filepos;
+ break;
#if USE_ZLIB
- case FS_GZIP:
- length = ftell( file->fp );
- break;
- case FS_PK2:
- length = unztell( file->zfp );
- break;
+ case FS_GZIP:
+ length = ftell( file->fp );
+ break;
+ case FS_PK2:
+ length = unztell( file->zfp );
+ break;
#endif
- default:
- length = -1;
- break;
- }
+ default:
+ length = -1;
+ break;
+ }
- return length;
+ return length;
}
-#define MAX_LOAD_BUFFER 0x100000 // 1 MiB
+#define MAX_LOAD_BUFFER 0x100000 // 1 MiB
// static buffer for small, stacked file loads and temp allocations
// the last allocation may be easily undone
@@ -980,22 +1056,22 @@ a null buffer will just return the file length without loading
============
*/
size_t FS_LoadFileEx( const char *path, void **buffer, int flags, memtag_t tag ) {
- fsFile_t *file;
- fileHandle_t f;
- byte *buf;
- size_t len;
+ fsFile_t *file;
+ fileHandle_t f;
+ byte *buf;
+ size_t len;
- if( !path ) {
- Com_Error( ERR_FATAL, "FS_LoadFile: NULL" );
- }
+ if( !path ) {
+ Com_Error( ERR_FATAL, "%s: NULL", __func__ );
+ }
- if( buffer ) {
- *buffer = NULL;
- }
+ if( buffer ) {
+ *buffer = NULL;
+ }
- if( !fs_searchpaths ) {
- return INVALID_LENGTH; // not yet initialized
- }
+ if( !fs_searchpaths ) {
+ return INVALID_LENGTH; // not yet initialized
+ }
if( *path == '/' ) {
path++;
@@ -1003,23 +1079,18 @@ size_t FS_LoadFileEx( const char *path, void **buffer, int flags, memtag_t tag )
path = FS_ExpandLinks( path );
- if( !FS_ValidatePath( path ) ) {
- FS_DPrintf( "FS_LoadFile: refusing invalid path: %s\n", path );
- return INVALID_LENGTH;
- }
+ // allocate new file handle
+ file = FS_AllocHandle( &f );
+ flags &= ~FS_MODE_MASK;
+ file->mode = flags | FS_MODE_READ;
- // allocate new file handle
- file = FS_AllocHandle( &f );
- flags &= ~FS_MODE_MASK;
- file->mode = flags | FS_MODE_READ;
-
- // look for it in the filesystem or pack files
- len = FS_FOpenFileRead( file, path, qfalse );
- if( len == INVALID_LENGTH ) {
- return len;
- }
+ // look for it in the filesystem or pack files
+ len = FS_FOpenFileRead( file, path, qfalse );
+ if( len == INVALID_LENGTH ) {
+ return len;
+ }
- if( buffer ) {
+ if( buffer ) {
#if USE_ZLIB
if( file->type == FS_GZIP ) {
len = INVALID_LENGTH; // unknown length
@@ -1035,7 +1106,7 @@ size_t FS_LoadFileEx( const char *path, void **buffer, int flags, memtag_t tag )
*buffer = buf;
buf[len] = 0;
} else {
- Com_EPrintf( "FS_LoadFile: error reading file: %s\n", path );
+ Com_EPrintf( "%s: error reading file: %s\n", __func__, path );
if( tag == TAG_FREE ) {
FS_FreeFile( buf );
} else {
@@ -1044,15 +1115,15 @@ size_t FS_LoadFileEx( const char *path, void **buffer, int flags, memtag_t tag )
len = INVALID_LENGTH;
}
}
- }
+ }
- FS_FCloseFile( f );
+ FS_FCloseFile( f );
- return len;
+ return len;
}
size_t FS_LoadFile( const char *path, void **buffer ) {
- return FS_LoadFileEx( path, buffer, 0, TAG_FREE );
+ return FS_LoadFileEx( path, buffer, 0, TAG_FREE );
}
void *FS_AllocTempMem( size_t length ) {
@@ -1069,7 +1140,7 @@ void *FS_AllocTempMem( size_t length ) {
} else {
// Com_Printf(S_COLOR_MAGENTA"alloc %d\n",length);
buf = FS_Malloc( length );
- loadCount++;
+ loadCount++;
}
return buf;
}
@@ -1080,24 +1151,24 @@ FS_FreeFile
=============
*/
void FS_FreeFile( void *buffer ) {
- if( !buffer ) {
- Com_Error( ERR_FATAL, "FS_FreeFile: NULL" );
- }
- if( ( byte * )buffer >= loadBuffer && ( byte * )buffer < loadBuffer + MAX_LOAD_BUFFER ) {
- if( loadStack == 0 ) {
- Com_Error( ERR_FATAL, "FS_FreeFile: loadStack is zero" );
- }
- loadStack--;
- if( loadStack == 0 ) {
- loadInuse = 0;
+ if( !buffer ) {
+ Com_Error( ERR_FATAL, "%s: NULL", __func__ );
+ }
+ if( ( byte * )buffer >= loadBuffer && ( byte * )buffer < loadBuffer + MAX_LOAD_BUFFER ) {
+ if( loadStack == 0 ) {
+ Com_Error( ERR_FATAL, "%s: empty load stack", __func__ );
+ }
+ loadStack--;
+ if( loadStack == 0 ) {
+ loadInuse = 0;
// Com_Printf(S_COLOR_MAGENTA"clear\n");
- } else if( buffer == loadLast ) {
+ } else if( buffer == loadLast ) {
loadInuse = loadSaved;
// Com_Printf(S_COLOR_MAGENTA"partial\n");
}
- } else {
- Z_Free( buffer );
- }
+ } else {
+ Z_Free( buffer );
+ }
}
/*
@@ -1106,43 +1177,41 @@ FS_CopyFile
=============
*/
qboolean FS_CopyFile( const char *src, const char *dst ) {
- fileHandle_t hSrc, hDst;
- byte buffer[MAX_READ];
- size_t len, size;
+ fileHandle_t hSrc, hDst;
+ byte buffer[MAX_READ];
+ size_t len, size;
- FS_DPrintf( "FS_CopyFile( '%s', '%s' )\n", src, dst );
-
- size = FS_FOpenFile( src, &hSrc, FS_MODE_READ );
- if( !hSrc ) {
- return qfalse;
- }
+ size = FS_FOpenFile( src, &hSrc, FS_MODE_READ );
+ if( !hSrc ) {
+ return qfalse;
+ }
- FS_FOpenFile( dst, &hDst, FS_MODE_WRITE );
- if( !hDst ) {
- FS_FCloseFile( hSrc );
- return qfalse;
- }
+ FS_FOpenFile( dst, &hDst, FS_MODE_WRITE );
+ if( !hDst ) {
+ FS_FCloseFile( hSrc );
+ return qfalse;
+ }
- while( size ) {
- len = size;
- if( len > sizeof( buffer ) ) {
- len = sizeof( buffer );
- }
- if( !( len = FS_Read( buffer, len, hSrc ) ) ) {
- break;
- }
- FS_Write( buffer, len, hDst );
- size -= len;
- }
+ while( size ) {
+ len = size;
+ if( len > sizeof( buffer ) ) {
+ len = sizeof( buffer );
+ }
+ if( !( len = FS_Read( buffer, len, hSrc ) ) ) {
+ break;
+ }
+ FS_Write( buffer, len, hDst );
+ size -= len;
+ }
- FS_FCloseFile( hSrc );
- FS_FCloseFile( hDst );
+ FS_FCloseFile( hSrc );
+ FS_FCloseFile( hDst );
- if( size ) {
- return qfalse;
- }
+ if( size ) {
+ return qfalse;
+ }
- return qtrue;
+ return qtrue;
}
/*
@@ -1151,25 +1220,25 @@ FS_RemoveFile
================
*/
qboolean FS_RemoveFile( const char *filename ) {
- char path[MAX_OSPATH];
+ char path[MAX_OSPATH];
if( *filename == '/' ) {
filename++;
}
- if( !FS_ValidatePath( filename ) ) {
- FS_DPrintf( "FS_RemoveFile: refusing invalid path: %s\n", filename );
- return qfalse;
- }
+ if( !FS_ValidatePath( filename ) ) {
+ FS_DPrintf( "%s: refusing invalid path: %s\n", __func__, filename );
+ return qfalse;
+ }
- Q_concat( path, sizeof( path ), fs_gamedir, "/", filename, NULL );
- //FS_ConvertToSysPath( path );
+ Q_concat( path, sizeof( path ), fs_gamedir, "/", filename, NULL );
+ //FS_ConvertToSysPath( path );
- if( !Sys_RemoveFile( path ) ) {
- return qfalse;
- }
+ if( Q_unlink( path ) ) {
+ return qfalse;
+ }
- return qtrue;
+ return qtrue;
}
/*
@@ -1178,8 +1247,8 @@ FS_RemoveFile
================
*/
qboolean FS_RenameFile( const char *from, const char *to ) {
- char frompath[MAX_OSPATH];
- char topath[MAX_OSPATH];
+ char frompath[MAX_OSPATH];
+ char topath[MAX_OSPATH];
if( *from == '/' ) {
from++;
@@ -1188,20 +1257,22 @@ qboolean FS_RenameFile( const char *from, const char *to ) {
to++;
}
- if( !FS_ValidatePath( from ) || !FS_ValidatePath( to ) ) {
- FS_DPrintf( "FS_RenameFile: refusing invalid path: %s to %s\n", from, to );
- return qfalse;
- }
+ if( !FS_ValidatePath( from ) || !FS_ValidatePath( to ) ) {
+ FS_DPrintf( "%s: refusing invalid path: %s to %s\n",
+ __func__, from, to );
+ return qfalse;
+ }
- Q_concat( frompath, sizeof( frompath ), fs_gamedir, "/", from, NULL );
- Q_concat( topath, sizeof( topath ), fs_gamedir, "/", to, NULL );
+ Q_concat( frompath, sizeof( frompath ), fs_gamedir, "/", from, NULL );
+ Q_concat( topath, sizeof( topath ), fs_gamedir, "/", to, NULL );
- if( !Sys_RenameFile( frompath, topath ) ) {
- FS_DPrintf( "FS_RenameFile: rename failed: %s to %s\n", frompath, topath );
- return qfalse;
- }
+ if( rename( frompath, topath ) ) {
+ FS_DPrintf( "%s: rename failed: %s to %s\n",
+ __func__, frompath, topath );
+ return qfalse;
+ }
- return qtrue;
+ return qtrue;
}
/*
@@ -1210,15 +1281,15 @@ FS_FPrintf
================
*/
void FS_FPrintf( fileHandle_t f, const char *format, ... ) {
- va_list argptr;
- char string[MAXPRINTMSG];
- size_t len;
+ va_list argptr;
+ char string[MAXPRINTMSG];
+ size_t len;
- va_start( argptr, format );
- len = Q_vsnprintf( string, sizeof( string ), format, argptr );
- va_end( argptr );
+ va_start( argptr, format );
+ len = Q_vsnprintf( string, sizeof( string ), format, argptr );
+ va_end( argptr );
- FS_Write( string, len, f );
+ FS_Write( string, len, f );
}
/*
@@ -1232,114 +1303,114 @@ of the list so they override previous pack files.
=================
*/
static pack_t *FS_LoadPakFile( const char *packfile ) {
- dpackheader_t header;
- int i;
- packfile_t *file;
- dpackfile_t *dfile;
- int numpackfiles;
- char *names;
- size_t namesLength;
- pack_t *pack;
- FILE *packhandle;
- dpackfile_t info[MAX_FILES_IN_PACK];
- int hashSize;
- unsigned hash;
- size_t len;
-
- packhandle = fopen( packfile, "rb" );
- if( !packhandle ) {
- Com_WPrintf( "Couldn't open %s\n", packfile );
- return NULL;
- }
-
- if( fread( &header, 1, sizeof( header ), packhandle ) != sizeof( header ) ) {
- Com_WPrintf( "Reading header failed on %s\n", packfile );
- goto fail;
- }
-
- if( LittleLong( header.ident ) != IDPAKHEADER ) {
- Com_WPrintf( "%s is not a 'PACK' file\n", packfile );
- goto fail;
- }
-
- header.dirlen = LittleLong( header.dirlen );
- if( header.dirlen % sizeof( dpackfile_t ) ) {
- Com_WPrintf( "%s has bad directory length\n", packfile );
- goto fail;
- }
-
- numpackfiles = header.dirlen / sizeof( dpackfile_t );
- if( numpackfiles < 1 ) {
- Com_WPrintf( "%s has bad number of files: %i\n", packfile, numpackfiles );
- goto fail;
- }
- if( numpackfiles > MAX_FILES_IN_PACK ) {
- Com_WPrintf( "%s has too many files: %i > %i\n", packfile, numpackfiles, MAX_FILES_IN_PACK );
- goto fail;
- }
-
- header.dirofs = LittleLong( header.dirofs );
- if( fseek( packhandle, header.dirofs, SEEK_SET ) ) {
- Com_WPrintf( "Seeking to directory failed on %s\n", packfile );
- goto fail;
- }
- if( fread( info, 1, header.dirlen, packhandle ) != header.dirlen ) {
- Com_WPrintf( "Reading directory failed on %s\n", packfile );
- goto fail;
- }
-
- namesLength = 0;
- for( i = 0, dfile = info; i < numpackfiles; i++, dfile++ ) {
- dfile->name[sizeof( dfile->name ) - 1] = 0;
- namesLength += strlen( dfile->name ) + 1;
- }
-
- hashSize = Q_CeilPowerOfTwo( numpackfiles );
- if( hashSize > 32 ) {
- hashSize >>= 1;
- }
-
- len = strlen( packfile );
- len = ( len + 3 ) & ~3;
- pack = FS_Malloc( sizeof( pack_t ) +
- numpackfiles * sizeof( packfile_t ) +
- hashSize * sizeof( packfile_t * ) +
- namesLength + len );
- strcpy( pack->filename, packfile );
- pack->fp = packhandle;
+ dpackheader_t header;
+ int i;
+ packfile_t *file;
+ dpackfile_t *dfile;
+ int numpackfiles;
+ char *names;
+ size_t namesLength;
+ pack_t *pack;
+ FILE *packhandle;
+ dpackfile_t info[MAX_FILES_IN_PACK];
+ int hashSize;
+ unsigned hash;
+ size_t len;
+
+ packhandle = fopen( packfile, "rb" );
+ if( !packhandle ) {
+ Com_WPrintf( "Couldn't open %s\n", packfile );
+ return NULL;
+ }
+
+ if( fread( &header, 1, sizeof( header ), packhandle ) != sizeof( header ) ) {
+ Com_WPrintf( "Reading header failed on %s\n", packfile );
+ goto fail;
+ }
+
+ if( LittleLong( header.ident ) != IDPAKHEADER ) {
+ Com_WPrintf( "%s is not a 'PACK' file\n", packfile );
+ goto fail;
+ }
+
+ header.dirlen = LittleLong( header.dirlen );
+ if( header.dirlen % sizeof( dpackfile_t ) ) {
+ Com_WPrintf( "%s has bad directory length\n", packfile );
+ goto fail;
+ }
+
+ numpackfiles = header.dirlen / sizeof( dpackfile_t );
+ if( numpackfiles < 1 ) {
+ Com_WPrintf( "%s has bad number of files: %i\n", packfile, numpackfiles );
+ goto fail;
+ }
+ if( numpackfiles > MAX_FILES_IN_PACK ) {
+ Com_WPrintf( "%s has too many files: %i > %i\n", packfile, numpackfiles, MAX_FILES_IN_PACK );
+ goto fail;
+ }
+
+ header.dirofs = LittleLong( header.dirofs );
+ if( fseek( packhandle, header.dirofs, SEEK_SET ) ) {
+ Com_WPrintf( "Seeking to directory failed on %s\n", packfile );
+ goto fail;
+ }
+ if( fread( info, 1, header.dirlen, packhandle ) != header.dirlen ) {
+ Com_WPrintf( "Reading directory failed on %s\n", packfile );
+ goto fail;
+ }
+
+ namesLength = 0;
+ for( i = 0, dfile = info; i < numpackfiles; i++, dfile++ ) {
+ dfile->name[sizeof( dfile->name ) - 1] = 0;
+ namesLength += strlen( dfile->name ) + 1;
+ }
+
+ hashSize = Q_CeilPowerOfTwo( numpackfiles );
+ if( hashSize > 32 ) {
+ hashSize >>= 1;
+ }
+
+ len = strlen( packfile );
+ len = ( len + 3 ) & ~3;
+ pack = FS_Malloc( sizeof( pack_t ) +
+ numpackfiles * sizeof( packfile_t ) +
+ hashSize * sizeof( packfile_t * ) +
+ namesLength + len );
+ strcpy( pack->filename, packfile );
+ pack->fp = packhandle;
#if USE_ZLIB
- pack->zFile = NULL;
+ pack->zFile = NULL;
#endif
- pack->numfiles = numpackfiles;
- pack->hashSize = hashSize;
- pack->files = ( packfile_t * )( ( byte * )pack + sizeof( pack_t ) + len );
- pack->fileHash = ( packfile_t ** )( pack->files + numpackfiles );
- names = ( char * )( pack->fileHash + hashSize );
- memset( pack->fileHash, 0, hashSize * sizeof( packfile_t * ) );
+ pack->numfiles = numpackfiles;
+ pack->hashSize = hashSize;
+ pack->files = ( packfile_t * )( ( byte * )pack + sizeof( pack_t ) + len );
+ pack->fileHash = ( packfile_t ** )( pack->files + numpackfiles );
+ names = ( char * )( pack->fileHash + hashSize );
+ memset( pack->fileHash, 0, hashSize * sizeof( packfile_t * ) );
// parse the directory
- for( i = 0, file = pack->files, dfile = info; i < pack->numfiles; i++, file++, dfile++ ) {
- len = strlen( dfile->name ) + 1;
+ for( i = 0, file = pack->files, dfile = info; i < pack->numfiles; i++, file++, dfile++ ) {
+ len = strlen( dfile->name ) + 1;
- file->name = memcpy( names, dfile->name, len );
- names += len;
+ file->name = memcpy( names, dfile->name, len );
+ names += len;
- file->filepos = LittleLong( dfile->filepos );
- file->filelen = LittleLong( dfile->filelen );
+ file->filepos = LittleLong( dfile->filepos );
+ file->filelen = LittleLong( dfile->filelen );
- hash = Com_HashPath( file->name, hashSize );
- file->hashNext = pack->fileHash[hash];
- pack->fileHash[hash] = file;
- }
+ hash = Com_HashPath( file->name, hashSize );
+ file->hashNext = pack->fileHash[hash];
+ pack->fileHash[hash] = file;
+ }
- FS_DPrintf( "%s: %d files, %d hash table entries\n",
- packfile, numpackfiles, hashSize );
+ FS_DPrintf( "%s: %d files, %d hash table entries\n",
+ packfile, numpackfiles, hashSize );
- return pack;
+ return pack;
fail:
- fclose( packhandle );
- return NULL;
+ fclose( packhandle );
+ return NULL;
}
#if USE_ZLIB
@@ -1349,110 +1420,110 @@ FS_LoadZipFile
=================
*/
static pack_t *FS_LoadZipFile( const char *packfile ) {
- int i;
- packfile_t *file;
- char *names;
- int numFiles;
- pack_t *pack;
- unzFile zFile;
- unz_global_info zGlobalInfo;
- unz_file_info zInfo;
- char name[MAX_QPATH];
- size_t namesLength;
- int hashSize;
- unsigned hash;
- size_t len;
-
- zFile = unzOpen( packfile );
- if( !zFile ) {
- Com_WPrintf( "unzOpen() failed on %s\n", packfile );
- return NULL;
- }
-
- if( unzGetGlobalInfo( zFile, &zGlobalInfo ) != UNZ_OK ) {
- Com_WPrintf( "unzGetGlobalInfo() failed on %s\n", packfile );
- goto fail;
- }
-
- numFiles = zGlobalInfo.number_entry;
- if( numFiles > MAX_FILES_IN_PK2 ) {
- Com_WPrintf( "%s has too many files, %i > %i\n", packfile, numFiles, MAX_FILES_IN_PK2 );
- goto fail;
- }
-
- if( unzGoToFirstFile( zFile ) != UNZ_OK ) {
- Com_WPrintf( "unzGoToFirstFile() failed on %s\n", packfile );
- goto fail;
- }
-
- namesLength = 0;
- for( i = 0; i < numFiles; i++ ) {
- if( unzGetCurrentFileInfo( zFile, &zInfo, name, sizeof( name ), NULL, 0, NULL, 0 ) != UNZ_OK ) {
- Com_WPrintf( "unzGetCurrentFileInfo() failed on %s\n", packfile );
- goto fail;
- }
-
- namesLength += strlen( name ) + 1;
-
- if( i != numFiles - 1 && unzGoToNextFile( zFile ) != UNZ_OK ) {
- Com_WPrintf( "unzGoToNextFile() failed on %s\n", packfile );
-
- }
- }
-
- hashSize = Q_CeilPowerOfTwo( numFiles );
- if( hashSize > 32 ) {
- hashSize >>= 1;
- }
-
- len = strlen( packfile );
- len = ( len + 3 ) & ~3;
- pack = FS_Malloc( sizeof( pack_t ) +
- numFiles * sizeof( packfile_t ) +
- hashSize * sizeof( packfile_t * ) +
- namesLength + len );
- strcpy( pack->filename, packfile );
- pack->zFile = zFile;
- pack->fp = NULL;
- pack->numfiles = numFiles;
- pack->hashSize = hashSize;
- pack->files = ( packfile_t * )( ( byte * )pack + sizeof( pack_t ) + len );
- pack->fileHash = ( packfile_t ** )( pack->files + numFiles );
- names = ( char * )( pack->fileHash + hashSize );
- memset( pack->fileHash, 0, hashSize * sizeof( packfile_t * ) );
+ int i;
+ packfile_t *file;
+ char *names;
+ int numFiles;
+ pack_t *pack;
+ unzFile zFile;
+ unz_global_info zGlobalInfo;
+ unz_file_info zInfo;
+ char name[MAX_QPATH];
+ size_t namesLength;
+ int hashSize;
+ unsigned hash;
+ size_t len;
+
+ zFile = unzOpen( packfile );
+ if( !zFile ) {
+ Com_WPrintf( "unzOpen() failed on %s\n", packfile );
+ return NULL;
+ }
+
+ if( unzGetGlobalInfo( zFile, &zGlobalInfo ) != UNZ_OK ) {
+ Com_WPrintf( "unzGetGlobalInfo() failed on %s\n", packfile );
+ goto fail;
+ }
+
+ numFiles = zGlobalInfo.number_entry;
+ if( numFiles > MAX_FILES_IN_PK2 ) {
+ Com_WPrintf( "%s has too many files, %i > %i\n", packfile, numFiles, MAX_FILES_IN_PK2 );
+ goto fail;
+ }
+
+ if( unzGoToFirstFile( zFile ) != UNZ_OK ) {
+ Com_WPrintf( "unzGoToFirstFile() failed on %s\n", packfile );
+ goto fail;
+ }
+
+ namesLength = 0;
+ for( i = 0; i < numFiles; i++ ) {
+ if( unzGetCurrentFileInfo( zFile, &zInfo, name, sizeof( name ), NULL, 0, NULL, 0 ) != UNZ_OK ) {
+ Com_WPrintf( "unzGetCurrentFileInfo() failed on %s\n", packfile );
+ goto fail;
+ }
+
+ namesLength += strlen( name ) + 1;
+
+ if( i != numFiles - 1 && unzGoToNextFile( zFile ) != UNZ_OK ) {
+ Com_WPrintf( "unzGoToNextFile() failed on %s\n", packfile );
+
+ }
+ }
+
+ hashSize = Q_CeilPowerOfTwo( numFiles );
+ if( hashSize > 32 ) {
+ hashSize >>= 1;
+ }
+
+ len = strlen( packfile );
+ len = ( len + 3 ) & ~3;
+ pack = FS_Malloc( sizeof( pack_t ) +
+ numFiles * sizeof( packfile_t ) +
+ hashSize * sizeof( packfile_t * ) +
+ namesLength + len );
+ strcpy( pack->filename, packfile );
+ pack->zFile = zFile;
+ pack->fp = NULL;
+ pack->numfiles = numFiles;
+ pack->hashSize = hashSize;
+ pack->files = ( packfile_t * )( ( byte * )pack + sizeof( pack_t ) + len );
+ pack->fileHash = ( packfile_t ** )( pack->files + numFiles );
+ names = ( char * )( pack->fileHash + hashSize );
+ memset( pack->fileHash, 0, hashSize * sizeof( packfile_t * ) );
// parse the directory
- unzGoToFirstFile( zFile );
+ unzGoToFirstFile( zFile );
- for( i = 0, file = pack->files; i < numFiles; i++, file++ ) {
- unzGetCurrentFileInfo( zFile, &zInfo, name, sizeof( name ), NULL, 0, NULL, 0 );
+ for( i = 0, file = pack->files; i < numFiles; i++, file++ ) {
+ unzGetCurrentFileInfo( zFile, &zInfo, name, sizeof( name ), NULL, 0, NULL, 0 );
- len = strlen( name ) + 1;
- file->name = names;
+ len = strlen( name ) + 1;
+ file->name = names;
- strcpy( file->name, name );
- file->filepos = unzGetCurrentFileInfoPosition( zFile );
- file->filelen = zInfo.uncompressed_size;
+ strcpy( file->name, name );
+ file->filepos = unzGetCurrentFileInfoPosition( zFile );
+ file->filelen = zInfo.uncompressed_size;
- hash = Com_HashPath( file->name, hashSize );
- file->hashNext = pack->fileHash[hash];
- pack->fileHash[hash] = file;
+ hash = Com_HashPath( file->name, hashSize );
+ file->hashNext = pack->fileHash[hash];
+ pack->fileHash[hash] = file;
- names += len;
-
- if( i != numFiles - 1 ) {
- unzGoToNextFile( zFile );
- }
- }
+ names += len;
+
+ if( i != numFiles - 1 ) {
+ unzGoToNextFile( zFile );
+ }
+ }
- FS_DPrintf( "%s: %d files, %d hash table entries\n",
- packfile, numFiles, hashSize );
+ FS_DPrintf( "%s: %d files, %d hash table entries\n",
+ packfile, numFiles, hashSize );
- return pack;
+ return pack;
fail:
- unzClose( zFile );
- return NULL;
+ unzClose( zFile );
+ return NULL;
}
#endif
@@ -1460,8 +1531,8 @@ fail:
// sorted in numerical order, then the rest of the paks in
// alphabetical order, e.g. pak0.pak, pak2.pak, pak17.pak, abc.pak...
static int QDECL pakcmp( const void *p1, const void *p2 ) {
- char *s1 = *( char ** )p1;
- char *s2 = *( char ** )p2;
+ char *s1 = *( char ** )p1;
+ char *s2 = *( char ** )p2;
if( !FS_strncmp( s1, "pak", 3 ) ) {
if( !FS_strncmp( s2, "pak", 3 ) ) {
@@ -1482,36 +1553,36 @@ static int QDECL pakcmp( const void *p1, const void *p2 ) {
}
alphacmp:
- return FS_strcmp( s1, s2 );
+ return FS_strcmp( s1, s2 );
}
static void FS_LoadPackFiles( int mode, const char *extension, pack_t *(loadfunc)( const char * ) ) {
- int i;
- searchpath_t *search;
- pack_t *pak;
- void **list;
- int numFiles;
+ int i;
+ searchpath_t *search;
+ pack_t *pak;
+ void **list;
+ int numFiles;
char path[MAX_OSPATH];
- list = Sys_ListFiles( fs_gamedir, extension, FS_SEARCH_NOSORT, 0, &numFiles );
- if( !list ) {
- return;
- }
- qsort( list, numFiles, sizeof( list[0] ), pakcmp );
- for( i = 0; i < numFiles; i++ ) {
+ list = Sys_ListFiles( fs_gamedir, extension, FS_SEARCH_NOSORT, 0, &numFiles );
+ if( !list ) {
+ return;
+ }
+ qsort( list, numFiles, sizeof( list[0] ), pakcmp );
+ for( i = 0; i < numFiles; i++ ) {
Q_concat( path, sizeof( path ), fs_gamedir, "/", list[i], NULL );
- pak = (*loadfunc)( path );
- if( !pak )
- continue;
- search = FS_Malloc( sizeof( searchpath_t ) );
+ pak = (*loadfunc)( path );
+ if( !pak )
+ continue;
+ search = FS_Malloc( sizeof( searchpath_t ) );
search->mode = mode;
- search->filename[0] = 0;
- search->pack = pak;
- search->next = fs_searchpaths;
- fs_searchpaths = search;
- }
+ search->filename[0] = 0;
+ search->pack = pak;
+ search->next = fs_searchpaths;
+ fs_searchpaths = search;
+ }
- FS_FreeList( list );
+ FS_FreeList( list );
}
/*
@@ -1524,43 +1595,43 @@ then loads and adds pak*.pak, then anything else in alphabethical order.
*/
static void q_printf( 2, 3 ) FS_AddGameDirectory( int mode, const char *fmt, ... ) {
va_list argptr;
- searchpath_t *search;
- size_t len;
+ searchpath_t *search;
+ size_t len;
va_start( argptr, fmt );
- len = Q_vsnprintf( fs_gamedir, sizeof( fs_gamedir ), fmt, argptr );
+ len = Q_vsnprintf( fs_gamedir, sizeof( fs_gamedir ), fmt, argptr );
va_end( argptr );
#ifdef _WIN32
- FS_ReplaceSeparators( fs_gamedir, '/' );
+ FS_ReplaceSeparators( fs_gamedir, '/' );
#endif
- //
- // add the directory to the search path
- //
- if( !( fs_restrict_mask->integer & 1 ) ) {
- search = FS_Malloc( sizeof( searchpath_t ) + len );
+ //
+ // add the directory to the search path
+ //
+ if( !( fs_restrict_mask->integer & 1 ) ) {
+ search = FS_Malloc( sizeof( searchpath_t ) + len );
search->mode = mode;
- search->pack = NULL;
- memcpy( search->filename, fs_gamedir, len + 1 );
- search->next = fs_searchpaths;
- fs_searchpaths = search;
- }
-
- //
- // add any pak files in the format *.pak
- //
- if( !( fs_restrict_mask->integer & 2 ) ) {
- FS_LoadPackFiles( mode, ".pak", FS_LoadPakFile );
- }
+ search->pack = NULL;
+ memcpy( search->filename, fs_gamedir, len + 1 );
+ search->next = fs_searchpaths;
+ fs_searchpaths = search;
+ }
+
+ //
+ // add any pak files in the format *.pak
+ //
+ if( !( fs_restrict_mask->integer & 2 ) ) {
+ FS_LoadPackFiles( mode, ".pak", FS_LoadPakFile );
+ }
#if USE_ZLIB
- //
- // add any zip files in the format *.pkz
- //
- if( !( fs_restrict_mask->integer & 4 ) ) {
- FS_LoadPackFiles( mode, ".pkz", FS_LoadZipFile );
- }
+ //
+ // add any zip files in the format *.pkz
+ //
+ if( !( fs_restrict_mask->integer & 4 ) ) {
+ FS_LoadPackFiles( mode, ".pkz", FS_LoadZipFile );
+ }
#endif
}
@@ -1570,32 +1641,32 @@ FS_CopyInfo
=================
*/
fsFileInfo_t *FS_CopyInfo( const char *name, size_t size, time_t ctime, time_t mtime ) {
- fsFileInfo_t *out;
- size_t len;
+ fsFileInfo_t *out;
+ size_t len;
- if( !name ) {
- return NULL;
- }
+ if( !name ) {
+ return NULL;
+ }
- len = strlen( name );
- out = FS_Mallocz( sizeof( *out ) + len );
+ len = strlen( name );
+ out = FS_Mallocz( sizeof( *out ) + len );
out->size = size;
out->ctime = ctime;
out->mtime = mtime;
- memcpy( out->name, name, len + 1 );
+ memcpy( out->name, name, len + 1 );
- return out;
+ return out;
}
void **FS_CopyList( void **list, int count ) {
void **out;
int i;
- out = FS_Malloc( sizeof( void * ) * ( count + 1 ) );
- for( i = 0; i < count; i++ ) {
- out[i] = list[i];
- }
- out[i] = NULL;
+ out = FS_Malloc( sizeof( void * ) * ( count + 1 ) );
+ for( i = 0; i < count; i++ ) {
+ out[i] = list[i];
+ }
+ out[i] = NULL;
return out;
}
@@ -1615,48 +1686,48 @@ static qboolean FS_WildCmp_r( const char *filter, const char *string ) {
continue;
}
- if( *filter != '?' && Q_toupper( *filter ) != Q_toupper( *string ) ) {
+ if( *filter != '?' && Q_toupper( *filter ) != Q_toupper( *string ) ) {
return qfalse;
}
filter++;
string++;
}
- return !*string;
+ return !*string;
}
#endif
static int FS_WildCmp_r( const char *filter, const char *string ) {
- switch( *filter ) {
- case '\0':
- case ';':
- return !*string;
+ switch( *filter ) {
+ case '\0':
+ case ';':
+ return !*string;
- case '*':
- return FS_WildCmp_r( filter + 1, string ) || (*string && FS_WildCmp_r( filter, string + 1 ));
+ case '*':
+ return FS_WildCmp_r( filter + 1, string ) || (*string && FS_WildCmp_r( filter, string + 1 ));
- case '?':
- return *string && FS_WildCmp_r( filter + 1, string + 1 );
+ case '?':
+ return *string && FS_WildCmp_r( filter + 1, string + 1 );
- default:
- return ((*filter == *string) || (Q_toupper( *filter ) == Q_toupper( *string ))) && FS_WildCmp_r( filter + 1, string + 1 );
- }
+ default:
+ return ((*filter == *string) || (Q_toupper( *filter ) == Q_toupper( *string ))) && FS_WildCmp_r( filter + 1, string + 1 );
+ }
}
qboolean FS_WildCmp( const char *filter, const char *string ) {
- do {
- if( FS_WildCmp_r( filter, string ) ) {
- return qtrue;
- }
- filter = strchr( filter, ';' );
- if( filter ) filter++;
- } while( filter );
+ do {
+ if( FS_WildCmp_r( filter, string ) ) {
+ return qtrue;
+ }
+ filter = strchr( filter, ';' );
+ if( filter ) filter++;
+ } while( filter );
- return qfalse;
+ return qfalse;
}
qboolean FS_ExtCmp( const char *ext, const char *name ) {
- int c1, c2;
+ int c1, c2;
const char *e, *n, *l;
if( !name[0] || !ext[0] ) {
@@ -1704,14 +1775,14 @@ static int infocmp( const void *p1, const void *p2 ) {
fsFileInfo_t *n1 = *( fsFileInfo_t ** )p1;
fsFileInfo_t *n2 = *( fsFileInfo_t ** )p2;
- return Q_stricmp( n1->name, n2->name );
+ return FS_pathcmp( n1->name, n2->name );
}
static int alphacmp( const void *p1, const void *p2 ) {
char *s1 = *( char ** )p1;
char *s2 = *( char ** )p2;
- return Q_stricmp( s1, s2 );
+ return FS_pathcmp( s1, s2 );
}
/*
@@ -1724,49 +1795,46 @@ void **FS_ListFiles( const char *path,
int flags,
int *numFiles )
{
- searchpath_t *search;
- void *listedFiles[MAX_LISTED_FILES];
- int count, total;
- char buffer[MAX_OSPATH];
- void **dirlist;
- int dircount;
- void **list;
- int i;
- size_t len, pathlen;
- char *s;
-
- if( flags & FS_SEARCH_BYFILTER ) {
- if( !extension ) {
- Com_Error( ERR_FATAL, "FS_ListFiles: NULL filter" );
- }
- }
-
- count = 0;
-
- if( numFiles ) {
- *numFiles = 0;
- }
-
- if( !path ) {
- path = "";
+ searchpath_t *search;
+ void *listedFiles[MAX_LISTED_FILES];
+ int count, total;
+ char buffer[MAX_OSPATH];
+ void **dirlist;
+ int dircount;
+ void **list;
+ int i;
+ size_t len, pathlen;
+ char *s;
+ int valid = -1;
+
+ if( flags & FS_SEARCH_BYFILTER ) {
+ if( !extension ) {
+ Com_Error( ERR_FATAL, "FS_ListFiles: NULL filter" );
+ }
+ }
+
+ count = 0;
+
+ if( numFiles ) {
+ *numFiles = 0;
+ }
+
+ if( !path ) {
+ path = "";
pathlen = 0;
- } else {
+ } else {
if( *path == '/' ) {
path++;
}
- if( !FS_ValidatePath( path ) ) {
- FS_DPrintf( "%s: refusing invalid path: %s\n", __func__, path );
- return NULL;
- }
pathlen = strlen( path );
}
for( search = fs_searchpaths; search; search = search->next ) {
- if( flags & FS_PATH_MASK ) {
- if( ( flags & search->mode & FS_PATH_MASK ) == 0 ) {
- continue;
- }
- }
+ if( flags & FS_PATH_MASK ) {
+ if( ( flags & search->mode & FS_PATH_MASK ) == 0 ) {
+ continue;
+ }
+ }
if( search->pack ) {
if( ( flags & FS_TYPE_MASK ) == FS_TYPE_REAL ) {
// don't search in paks
@@ -1784,7 +1852,7 @@ void **FS_ListFiles( const char *path,
// check path
if( pathlen ) {
- if( Q_stricmpn( s, path, pathlen ) ) {
+ if( FS_pathcmpn( s, path, pathlen ) ) {
continue;
}
s += pathlen + 1;
@@ -1815,7 +1883,7 @@ void **FS_ListFiles( const char *path,
s = search->pack->files[i].name;
// check path
- if( pathlen && Q_stricmpn( s, path, pathlen ) ) {
+ if( pathlen && FS_pathcmpn( s, path, pathlen ) ) {
continue;
}
@@ -1851,6 +1919,16 @@ void **FS_ListFiles( const char *path,
if( len + pathlen + 1 >= MAX_OSPATH ) {
continue;
}
+ if( valid == -1 ) {
+ if( !FS_ValidatePath( path ) ) {
+ FS_DPrintf( "%s: refusing invalid path: %s\n",
+ __func__, path );
+ valid = 0;
+ }
+ }
+ if( valid == 0 ) {
+ continue;
+ }
memcpy( buffer, search->filename, len );
buffer[len++] = '/';
memcpy( buffer + len, path, pathlen + 1 );
@@ -1884,9 +1962,9 @@ void **FS_ListFiles( const char *path,
}
}
- if( !count ) {
- return NULL;
- }
+ if( !count ) {
+ return NULL;
+ }
if( flags & FS_SEARCH_EXTRAINFO ) {
// TODO
@@ -1899,8 +1977,7 @@ void **FS_ListFiles( const char *path,
// remove duplicates
total = 1;
for( i = 1; i < count; i++ ) {
- // FIXME: use Q_stricmp instead of FS_strcmp here?
- if( !Q_stricmp( listedFiles[ i - 1 ], listedFiles[i] ) ) {
+ if( !FS_pathcmp( listedFiles[ i - 1 ], listedFiles[i] ) ) {
Z_Free( listedFiles[ i - 1 ] );
listedFiles[i-1] = NULL;
} else {
@@ -1909,21 +1986,21 @@ void **FS_ListFiles( const char *path,
}
}
- list = FS_Malloc( sizeof( void * ) * ( total + 1 ) );
+ list = FS_Malloc( sizeof( void * ) * ( total + 1 ) );
- total = 0;
- for( i = 0; i < count; i++ ) {
- if( listedFiles[i] ) {
- list[total++] = listedFiles[i];
- }
- }
- list[total] = NULL;
+ total = 0;
+ for( i = 0; i < count; i++ ) {
+ if( listedFiles[i] ) {
+ list[total++] = listedFiles[i];
+ }
+ }
+ list[total] = NULL;
- if( numFiles ) {
- *numFiles = total;
- }
+ if( numFiles ) {
+ *numFiles = total;
+ }
- return list;
+ return list;
}
/*
@@ -1932,13 +2009,13 @@ FS_FreeList
=================
*/
void FS_FreeList( void **list ) {
- void **p = list;
+ void **p = list;
- while( *p ) {
- Z_Free( *p++ );
- }
+ while( *p ) {
+ Z_Free( *p++ );
+ }
- Z_Free( list );
+ Z_Free( list );
}
void FS_File_g( const char *path, const char *ext, int flags, genctx_t *ctx ) {
@@ -1953,10 +2030,10 @@ void FS_File_g( const char *path, const char *ext, int flags, genctx_t *ctx ) {
for( i = 0; i < numFiles; i++ ) {
s = list[i];
- if( flags & 0x80000000 ) {
- p = COM_FileExtension( s );
- *p = 0;
- }
+ if( flags & 0x80000000 ) {
+ p = COM_FileExtension( s );
+ *p = 0;
+ }
if( ctx->count < ctx->size && !strncmp( s, ctx->partial, ctx->length ) ) {
ctx->matches[ctx->count++] = s;
} else {
@@ -1976,16 +2053,16 @@ extract file from *.pak, *.pk2 or *.gz
=================
*/
static void FS_CopyFile_f( void ) {
- if( Cmd_Argc() < 2 ) {
- Com_Printf( "Usage: %s <sourcePath> <destPath>\n", Cmd_Argv( 0 ) );
- return;
- }
+ if( Cmd_Argc() < 2 ) {
+ Com_Printf( "Usage: %s <sourcePath> <destPath>\n", Cmd_Argv( 0 ) );
+ return;
+ }
- if( FS_CopyFile( Cmd_Argv( 1 ), Cmd_Argv( 2 ) ) ) {
- Com_Printf( "File copied successfully\n" );
- } else {
- Com_Printf( "Failed to copy file\n" );
- }
+ if( FS_CopyFile( Cmd_Argv( 1 ), Cmd_Argv( 2 ) ) ) {
+ Com_Printf( "File copied successfully\n" );
+ } else {
+ Com_Printf( "Failed to copy file\n" );
+ }
}
/*
@@ -1994,30 +2071,30 @@ FS_FDir_f
============
*/
static void FS_FDir_f( void ) {
- void **list;
- int ndirs = 0;
- int i;
+ void **list;
+ int ndirs = 0;
+ int i;
char *filter;
- if( Cmd_Argc() < 2 ) {
- Com_Printf( "Usage: %s <filter> [fullPath]\n", Cmd_Argv( 0 ) );
- return;
- }
+ if( Cmd_Argc() < 2 ) {
+ Com_Printf( "Usage: %s <filter> [fullPath]\n", Cmd_Argv( 0 ) );
+ return;
+ }
filter = Cmd_Argv( 1 );
- i = FS_SEARCH_BYFILTER;
- if( Cmd_Argc() > 2 ) {
- i |= FS_SEARCH_SAVEPATH;
- }
+ i = FS_SEARCH_BYFILTER;
+ if( Cmd_Argc() > 2 ) {
+ i |= FS_SEARCH_SAVEPATH;
+ }
- if( ( list = FS_ListFiles( NULL, filter, i, &ndirs ) ) != NULL ) {
- for( i = 0; i < ndirs; i++ ) {
- Com_Printf( "%s\n", ( char * )list[i] );
- }
- FS_FreeList( list );
- }
- Com_Printf( "%i files listed\n", ndirs );
+ if( ( list = FS_ListFiles( NULL, filter, i, &ndirs ) ) != NULL ) {
+ for( i = 0; i < ndirs; i++ ) {
+ Com_Printf( "%s\n", ( char * )list[i] );
+ }
+ FS_FreeList( list );
+ }
+ Com_Printf( "%i files listed\n", ndirs );
}
/*
@@ -2026,28 +2103,28 @@ FS_Dir_f
============
*/
static void FS_Dir_f( void ) {
- void **list;
- int ndirs = 0;
- int i;
+ void **list;
+ int ndirs = 0;
+ int i;
char *ext;
- if( Cmd_Argc() < 2 ) {
- Com_Printf( "Usage: %s <directory> [.extension]\n", Cmd_Argv( 0 ) );
- return;
- }
+ if( Cmd_Argc() < 2 ) {
+ Com_Printf( "Usage: %s <directory> [.extension]\n", Cmd_Argv( 0 ) );
+ return;
+ }
if( Cmd_Argc() > 2 ) {
ext = Cmd_Argv( 2 );
} else {
ext = NULL;
}
list = FS_ListFiles( Cmd_Argv( 1 ), ext, 0, &ndirs );
- if( list ) {
- for( i = 0; i < ndirs; i++ ) {
- Com_Printf( "%s\n", ( char * )list[i] );
- }
- FS_FreeList( list );
- }
- Com_Printf( "%i files listed\n", ndirs );
+ if( list ) {
+ for( i = 0; i < ndirs; i++ ) {
+ Com_Printf( "%s\n", ( char * )list[i] );
+ }
+ FS_FreeList( list );
+ }
+ Com_Printf( "%i files listed\n", ndirs );
}
/*
@@ -2066,10 +2143,10 @@ static void FS_WhereIs_f( void ) {
fsFileInfo_t info;
int total;
- if( Cmd_Argc() < 2 ) {
- Com_Printf( "Usage: %s <path> [all]\n", Cmd_Argv( 0 ) );
- return;
- }
+ if( Cmd_Argc() < 2 ) {
+ Com_Printf( "Usage: %s <path> [all]\n", Cmd_Argv( 0 ) );
+ return;
+ }
Cmd_ArgvBuffer( 1, filename, sizeof( filename ) );
@@ -2082,16 +2159,16 @@ static void FS_WhereIs_f( void ) {
total = 0;
for( search = fs_searchpaths; search; search = search->next ) {
- // is the element a pak file?
- if( search->pack ) {
- // look through all the pak file elements
- pak = search->pack;
- entry = pak->fileHash[ hash & ( pak->hashSize - 1 ) ];
- for( ; entry; entry = entry->hashNext ) {
- if( !Q_stricmp( entry->name, path ) ) {
+ // is the element a pak file?
+ if( search->pack ) {
+ // look through all the pak file elements
+ pak = search->pack;
+ entry = pak->fileHash[ hash & ( pak->hashSize - 1 ) ];
+ for( ; entry; entry = entry->hashNext ) {
+ if( !FS_pathcmp( entry->name, path ) ) {
Com_Printf( "%s/%s (%"PRIz" bytes)\n", pak->filename,
path, entry->filelen );
- if( Cmd_Argc() < 3 ) {
+ if( Cmd_Argc() < 3 ) {
return;
}
total++;
@@ -2100,7 +2177,7 @@ static void FS_WhereIs_f( void ) {
} else {
Q_concat( fullpath, sizeof( fullpath ),
search->filename, "/", path, NULL );
- //FS_ConvertToSysPath( fullpath );
+ //FS_ConvertToSysPath( fullpath );
if( Sys_GetPathInfo( fullpath, &info ) ) {
Com_Printf( "%s/%s (%"PRIz" bytes)\n", search->filename, filename, info.size );
if( Cmd_Argc() < 3 ) {
@@ -2125,39 +2202,39 @@ FS_Path_f
============
*/
void FS_Path_f( void ) {
- searchpath_t *s;
- int numFilesInPAK = 0;
+ searchpath_t *s;
+ int numFilesInPAK = 0;
#if USE_ZLIB
- int numFilesInPK2 = 0;
+ int numFilesInPK2 = 0;
#endif
- Com_Printf( "Current search path:\n" );
- for( s = fs_searchpaths; s; s = s->next ) {
- if( s->pack ) {
+ Com_Printf( "Current search path:\n" );
+ for( s = fs_searchpaths; s; s = s->next ) {
+ if( s->pack ) {
#if USE_ZLIB
- if( s->pack->zFile ) {
- numFilesInPK2 += s->pack->numfiles;
- } else
+ if( s->pack->zFile ) {
+ numFilesInPK2 += s->pack->numfiles;
+ } else
#endif
{
- numFilesInPAK += s->pack->numfiles;
- }
- }
+ numFilesInPAK += s->pack->numfiles;
+ }
+ }
- if( s->pack )
- Com_Printf( "%s (%i files)\n", s->pack->filename, s->pack->numfiles );
- else
- Com_Printf( "%s\n", s->filename );
- }
+ if( s->pack )
+ Com_Printf( "%s (%i files)\n", s->pack->filename, s->pack->numfiles );
+ else
+ Com_Printf( "%s\n", s->filename );
+ }
- if( !( fs_restrict_mask->integer & 2 ) ) {
- Com_Printf( "%i files in PAK files\n", numFilesInPAK );
- }
+ if( numFilesInPAK ) {
+ Com_Printf( "%i files in PAK files\n", numFilesInPAK );
+ }
#if USE_ZLIB
- if( !( fs_restrict_mask->integer & 4 ) ) {
- Com_Printf( "%i files in PKZ files\n", numFilesInPK2 );
- }
+ if( numFilesInPK2 ) {
+ Com_Printf( "%i files in PKZ files\n", numFilesInPK2 );
+ }
#endif
}
@@ -2167,55 +2244,55 @@ FS_Stats_f
================
*/
static void FS_Stats_f( void ) {
- searchpath_t *path;
- pack_t *pack, *maxpack = NULL;
- packfile_t *file, *max = NULL;
- int i;
- int len, maxLen = 0;
- int totalHashSize, totalLen;
-
- totalHashSize = totalLen = 0;
- for( path = fs_searchpaths; path; path = path->next ) {
- if( !( pack = path->pack ) ) {
- continue;
- }
- for( i = 0; i < pack->hashSize; i++ ) {
- if( !( file = pack->fileHash[i] ) ) {
- continue;
- }
- len = 0;
- for( ; file ; file = file->hashNext ) {
- len++;
- }
- if( maxLen < len ) {
- max = pack->fileHash[i];
- maxpack = pack;
- maxLen = len;
- }
- totalLen += len;
- totalHashSize++;
- }
- //totalHashSize += pack->hashSize;
- }
-
- Com_Printf( "LoadFile counter: %d\n", loadCount );
- Com_Printf( "Static LoadFile counter: %d\n", loadCountStatic );
- Com_Printf( "Total calls to OpenFileRead: %d\n", fs_count_read );
- Com_Printf( "Total path comparsions: %d\n", fs_count_strcmp );
- Com_Printf( "Total calls to fopen: %d\n", fs_count_open );
-
- if( !totalHashSize ) {
- Com_Printf( "No stats to display\n" );
- return;
- }
-
- Com_Printf( "Maximum hash bucket length is %d, average is %.2f\n", maxLen, ( float )totalLen / totalHashSize );
- if( max ) {
- Com_Printf( "Dumping longest bucket (%s):\n", maxpack->filename );
- for( file = max; file ; file = file->hashNext ) {
- Com_Printf( "%s\n", file->name );
- }
- }
+ searchpath_t *path;
+ pack_t *pack, *maxpack = NULL;
+ packfile_t *file, *max = NULL;
+ int i;
+ int len, maxLen = 0;
+ int totalHashSize, totalLen;
+
+ totalHashSize = totalLen = 0;
+ for( path = fs_searchpaths; path; path = path->next ) {
+ if( !( pack = path->pack ) ) {
+ continue;
+ }
+ for( i = 0; i < pack->hashSize; i++ ) {
+ if( !( file = pack->fileHash[i] ) ) {
+ continue;
+ }
+ len = 0;
+ for( ; file ; file = file->hashNext ) {
+ len++;
+ }
+ if( maxLen < len ) {
+ max = pack->fileHash[i];
+ maxpack = pack;
+ maxLen = len;
+ }
+ totalLen += len;
+ totalHashSize++;
+ }
+ //totalHashSize += pack->hashSize;
+ }
+
+ Com_Printf( "LoadFile counter: %d\n", loadCount );
+ Com_Printf( "Static LoadFile counter: %d\n", loadCountStatic );
+ Com_Printf( "Total calls to OpenFileRead: %d\n", fs_count_read );
+ Com_Printf( "Total path comparsions: %d\n", fs_count_strcmp );
+ Com_Printf( "Total calls to fopen: %d\n", fs_count_open );
+
+ if( !totalHashSize ) {
+ Com_Printf( "No stats to display\n" );
+ return;
+ }
+
+ Com_Printf( "Maximum hash bucket length is %d, average is %.2f\n", maxLen, ( float )totalLen / totalHashSize );
+ if( max ) {
+ Com_Printf( "Dumping longest bucket (%s):\n", maxpack->filename );
+ for( file = max; file ; file = file->hashNext ) {
+ Com_Printf( "%s\n", file->name );
+ }
+ }
}
static void FS_Link_g( genctx_t *ctx ) {
@@ -2273,7 +2350,7 @@ static void FS_UnLink_f( void ) {
}
for( l = fs_links, back = &fs_links; l; l = l->next ) {
- if( !Q_stricmp( l->name, name ) ) {
+ if( !FS_pathcmp( l->name, name ) ) {
break;
}
back = &l->next;
@@ -2290,7 +2367,7 @@ static void FS_UnLink_f( void ) {
static void FS_Link_f( void ) {
int argc, count;
- size_t length;
+ size_t length;
fsLink_t *l;
char *name, *target;
@@ -2314,7 +2391,7 @@ static void FS_Link_f( void ) {
name = Cmd_Argv( 1 );
for( l = fs_links; l; l = l->next ) {
- if( !Q_stricmp( l->name, name ) ) {
+ if( !FS_pathcmp( l->name, name ) ) {
break;
}
}
@@ -2336,21 +2413,21 @@ static void FS_Link_f( void ) {
}
static void FS_FreeSearchPath( searchpath_t *path ) {
- pack_t *pak;
+ pack_t *pak;
- if( ( pak = path->pack ) != NULL ) {
+ if( ( pak = path->pack ) != NULL ) {
#if USE_ZLIB
- if( pak->zFile ) {
- unzClose( pak->zFile );
- } else
+ if( pak->zFile ) {
+ unzClose( pak->zFile );
+ } else
#endif
{
- fclose( pak->fp );
- }
- Z_Free( pak );
- }
+ fclose( pak->fp );
+ }
+ Z_Free( pak );
+ }
- Z_Free( path );
+ Z_Free( path );
}
/*
@@ -2359,24 +2436,24 @@ FS_Shutdown
================
*/
void FS_Shutdown( qboolean total ) {
- searchpath_t *path, *next;
+ searchpath_t *path, *next;
fsLink_t *l, *nextLink;
- fsFile_t *file;
- int i;
-
- if( !fs_searchpaths ) {
- return;
- }
-
- if( total ) {
- // close file handles
- for( i = 0, file = fs_files; i < MAX_FILE_HANDLES; i++, file++ ) {
- if( file->type != FS_FREE ) {
- Com_WPrintf( "FS_Shutdown: closing handle %i: %s\n",
+ fsFile_t *file;
+ int i;
+
+ if( !fs_searchpaths ) {
+ return;
+ }
+
+ if( total ) {
+ // close file handles
+ for( i = 0, file = fs_files; i < MAX_FILE_HANDLES; i++, file++ ) {
+ if( file->type != FS_FREE ) {
+ Com_WPrintf( "FS_Shutdown: closing handle %i: %s\n",
i + 1, file->fullpath );
- FS_FCloseFile( i + 1 );
- }
- }
+ FS_FCloseFile( i + 1 );
+ }
+ }
// free symbolic links
for( l = fs_links; l; l = nextLink ) {
@@ -2386,27 +2463,27 @@ void FS_Shutdown( qboolean total ) {
}
fs_links = NULL;
- }
+ }
- // free search paths
- for( path = fs_searchpaths; path; path = next ) {
- next = path->next;
- FS_FreeSearchPath( path );
- }
+ // free search paths
+ for( path = fs_searchpaths; path; path = next ) {
+ next = path->next;
+ FS_FreeSearchPath( path );
+ }
- fs_searchpaths = NULL;
+ fs_searchpaths = NULL;
if( total ) {
- Z_LeakTest( TAG_FILESYSTEM );
+ Z_LeakTest( TAG_FILESYSTEM );
}
- Cmd_RemoveCommand( "path" );
- Cmd_RemoveCommand( "fdir" );
- Cmd_RemoveCommand( "dir" );
- Cmd_RemoveCommand( "copyfile" );
- Cmd_RemoveCommand( "fs_stats" );
- Cmd_RemoveCommand( "link" );
- Cmd_RemoveCommand( "unlink" );
+ Cmd_RemoveCommand( "path" );
+ Cmd_RemoveCommand( "fdir" );
+ Cmd_RemoveCommand( "dir" );
+ Cmd_RemoveCommand( "copyfile" );
+ Cmd_RemoveCommand( "fs_stats" );
+ Cmd_RemoveCommand( "link" );
+ Cmd_RemoveCommand( "unlink" );
}
/*
@@ -2416,14 +2493,14 @@ FS_DefaultGamedir
*/
static void FS_DefaultGamedir( void ) {
if( sys_homedir->string[0] ) {
- FS_AddGameDirectory( FS_PATH_BASE|FS_PATH_GAME,
+ FS_AddGameDirectory( FS_PATH_BASE|FS_PATH_GAME,
"%s/"BASEGAME, sys_homedir->string );
}
- Cvar_Set( "game", "" );
- Cvar_Set( "gamedir", "" );
+ Cvar_Set( "game", "" );
+ Cvar_Set( "gamedir", "" );
- Sys_Setenv( "QUAKE2_HOME", fs_gamedir );
+ Q_setenv( "QUAKE2_GAME_PATH", fs_gamedir );
}
@@ -2435,27 +2512,29 @@ Sets the gamedir and path to a different directory.
================
*/
static void FS_SetupGamedir( void ) {
- fs_game = Cvar_Get( "game", "", CVAR_LATCHED|CVAR_SERVERINFO );
+ fs_game = Cvar_Get( "game", "", CVAR_FILES|CVAR_LATCH|CVAR_SERVERINFO );
- if( !fs_game->string[0] || !FS_strcmp( fs_game->string, BASEGAME ) ) {
- FS_DefaultGamedir();
- return;
- }
+ cvar_modified &= ~CVAR_FILES;
- if( !FS_ValidatePath( fs_game->string ) ||
+ if( !fs_game->string[0] || !FS_strcmp( fs_game->string, BASEGAME ) ) {
+ FS_DefaultGamedir();
+ return;
+ }
+
+ if( !FS_ValidatePath( fs_game->string ) ||
strchr( fs_game->string, '/' ) ||
- strchr( fs_game->string, '\\' ) )
- {
- Com_WPrintf( "Gamedir should be a single filename, not a path.\n" );
- FS_DefaultGamedir();
- return;
- }
-
- // this one is left for compatibility with server browsers, etc
- Cvar_FullSet( "gamedir", fs_game->string, CVAR_ROM|CVAR_SERVERINFO,
+ strchr( fs_game->string, '\\' ) )
+ {
+ Com_WPrintf( "Gamedir should be a single filename, not a path.\n" );
+ FS_DefaultGamedir();
+ return;
+ }
+
+ // this one is left for compatibility with server browsers, etc
+ Cvar_FullSet( "gamedir", fs_game->string, CVAR_ROM|CVAR_SERVERINFO,
CVAR_SET_DIRECT );
- FS_AddGameDirectory( FS_PATH_GAME, "%s/%s", sys_basedir->string, fs_game->string );
+ FS_AddGameDirectory( FS_PATH_GAME, "%s/%s", sys_basedir->string, fs_game->string );
// home paths override system paths
if( sys_homedir->string[0] ) {
@@ -2463,21 +2542,21 @@ static void FS_SetupGamedir( void ) {
FS_AddGameDirectory( FS_PATH_GAME, "%s/%s", sys_homedir->string, fs_game->string );
}
- Sys_Setenv( "QUAKE2_HOME", fs_gamedir );
+ Q_setenv( "QUAKE2_GAME_PATH", fs_gamedir );
}
qboolean FS_SafeToRestart( void ) {
- fsFile_t *file;
- int i;
+ fsFile_t *file;
+ int i;
- // make sure no files are opened for reading
- for( i = 0, file = fs_files; i < MAX_FILE_HANDLES; i++, file++ ) {
- if( file->type == FS_FREE ) {
- continue;
- }
- if( file->mode == FS_MODE_READ ) {
+ // make sure no files are opened for reading
+ for( i = 0, file = fs_files; i < MAX_FILE_HANDLES; i++, file++ ) {
+ if( file->type == FS_FREE ) {
+ continue;
+ }
+ if( file->mode == FS_MODE_READ ) {
return qfalse;
- }
+ }
}
return qtrue;
@@ -2489,49 +2568,49 @@ FS_Restart
================
*/
void FS_Restart( void ) {
- fsFile_t *file;
- int i;
- fileHandle_t temp;
- searchpath_t *path, *next;
-
- Com_Printf( "---------- FS_Restart ----------\n" );
-
- // temporary disable logfile
- temp = com_logFile;
- com_logFile = 0;
-
- // make sure no files are opened for reading
- for( i = 0, file = fs_files; i < MAX_FILE_HANDLES; i++, file++ ) {
- if( file->type == FS_FREE ) {
- continue;
- }
- if( file->mode == FS_MODE_READ ) {
- Com_Error( ERR_FATAL, "FS_Restart: closing handle %i: %s",
+ fsFile_t *file;
+ int i;
+ fileHandle_t temp;
+ searchpath_t *path, *next;
+
+ Com_Printf( "---------- FS_Restart ----------\n" );
+
+ // temporary disable logfile
+ temp = com_logFile;
+ com_logFile = 0;
+
+ // make sure no files are opened for reading
+ for( i = 0, file = fs_files; i < MAX_FILE_HANDLES; i++, file++ ) {
+ if( file->type == FS_FREE ) {
+ continue;
+ }
+ if( file->mode == FS_MODE_READ ) {
+ Com_Error( ERR_FATAL, "FS_Restart: closing handle %i: %s",
i + 1, file->fullpath );
- }
- }
-
- if( fs_restrict_mask->latched_string ) {
- // perform full reset
- FS_Shutdown( qfalse );
- FS_Init();
- } else {
- // just change gamedir
- for( path = fs_searchpaths; path != fs_base_searchpaths; path = next ) {
- next = path->next;
- FS_FreeSearchPath( path );
- }
-
- fs_searchpaths = fs_base_searchpaths;
-
- FS_SetupGamedir();
- FS_Path_f();
- }
-
- // re-enable logfile
- com_logFile = temp;
-
- Com_Printf( "--------------------------------\n" );
+ }
+ }
+
+ if( fs_restrict_mask->latched_string ) {
+ // perform full reset
+ FS_Shutdown( qfalse );
+ FS_Init();
+ } else {
+ // just change gamedir
+ for( path = fs_searchpaths; path != fs_base_searchpaths; path = next ) {
+ next = path->next;
+ FS_FreeSearchPath( path );
+ }
+
+ fs_searchpaths = fs_base_searchpaths;
+
+ FS_SetupGamedir();
+ FS_Path_f();
+ }
+
+ // re-enable logfile
+ com_logFile = temp;
+
+ Com_Printf( "--------------------------------\n" );
}
/*
@@ -2556,18 +2635,18 @@ FS_FillAPI
================
*/
void FS_FillAPI( fsAPI_t *api ) {
- api->LoadFile = FS_LoadFile;
- api->LoadFileEx = FS_LoadFileEx;
+ api->LoadFile = FS_LoadFile;
+ api->LoadFileEx = FS_LoadFileEx;
api->AllocTempMem = FS_AllocTempMem;
- api->FreeFile = FS_FreeFile;
- api->FOpenFile = FS_FOpenFile;
- api->FCloseFile = FS_FCloseFile;
- api->Tell = FS_Tell;
- api->RawTell = FS_RawTell;
- api->Read = FS_Read;
- api->Write = FS_Write;
- api->ListFiles = FS_ListFiles;
- api->FreeList = FS_FreeList;
+ api->FreeFile = FS_FreeFile;
+ api->FOpenFile = FS_FOpenFile;
+ api->FCloseFile = FS_FCloseFile;
+ api->Tell = FS_Tell;
+ api->RawTell = FS_RawTell;
+ api->Read = FS_Read;
+ api->Write = FS_Write;
+ api->ListFiles = FS_ListFiles;
+ api->FreeList = FS_FreeList;
api->FPrintf = FS_FPrintf;
api->ReadLine = FS_ReadLine;
}
@@ -2581,7 +2660,7 @@ static const cmdreg_t c_fs[] = {
{ "whereis", FS_WhereIs_f },
{ "link", FS_Link_f, FS_Link_c },
{ "unlink", FS_UnLink_f, FS_Link_c },
- { "fs_restart", FS_Restart_f },
+ { "fs_restart", FS_Restart_f },
{ NULL }
};
@@ -2592,39 +2671,39 @@ FS_Init
================
*/
void FS_Init( void ) {
- unsigned start, end;
+ unsigned start, end;
- start = Sys_Milliseconds();
+ start = Sys_Milliseconds();
- Com_Printf( "---------- FS_Init ----------\n" );
+ Com_Printf( "---------- FS_Init ----------\n" );
Cmd_Register( c_fs );
- fs_debug = Cvar_Get( "fs_debug", "0", 0 );
- fs_restrict_mask = Cvar_Get( "fs_restrict_mask", "0", CVAR_NOSET );
+ fs_debug = Cvar_Get( "fs_debug", "0", 0 );
+ fs_restrict_mask = Cvar_Get( "fs_restrict_mask", "0", CVAR_NOSET );
- if( ( fs_restrict_mask->integer & 7 ) == 7 ) {
- Com_WPrintf( "Invalid fs_restrict_mask value %d. "
+ if( ( fs_restrict_mask->integer & 7 ) == 7 ) {
+ Com_WPrintf( "Invalid fs_restrict_mask value %d. "
"Falling back to default.\n",
- fs_restrict_mask->integer );
- Cvar_Set( "fs_restrict_mask", "0" );
- }
+ fs_restrict_mask->integer );
+ Cvar_Set( "fs_restrict_mask", "0" );
+ }
- // start up with baseq2 by default
- FS_AddGameDirectory( FS_PATH_BASE|FS_PATH_GAME, "%s/"BASEGAME, sys_basedir->string );
+ // start up with baseq2 by default
+ FS_AddGameDirectory( FS_PATH_BASE|FS_PATH_GAME, "%s/"BASEGAME, sys_basedir->string );
- fs_base_searchpaths = fs_searchpaths;
+ fs_base_searchpaths = fs_searchpaths;
- // check for game override
- FS_SetupGamedir();
+ // check for game override
+ FS_SetupGamedir();
- FS_Path_f();
+ FS_Path_f();
- FS_FillAPI( &fs );
-
+ FS_FillAPI( &fs );
+
end = Sys_Milliseconds();
- Com_DPrintf( "%i msec to init filesystem\n", end - start );
- Com_Printf( "-----------------------------\n" );
+ Com_DPrintf( "%i msec to init filesystem\n", end - start );
+ Com_Printf( "-----------------------------\n" );
}
/*
@@ -2633,10 +2712,12 @@ FS_NeedRestart
================
*/
qboolean FS_NeedRestart( void ) {
- if( fs_game->latched_string || fs_restrict_mask->latched_string ) {
- return qtrue;
- }
-
- return qfalse;
+ if( cvar_modified & CVAR_FILES ) {
+ return qtrue;
+ }
+ if( fs_game->latched_string || fs_restrict_mask->latched_string ) {
+ return qtrue;
+ }
+ return qfalse;
}