@ -20,6 +20,9 @@ GNU General Public License for more details.
@@ -20,6 +20,9 @@ GNU General Public License for more details.
# if XASH_WIN32
# include <direct.h>
# include <io.h>
# elif XASH_DOS4GW
# include <direct.h>
# include <errno.h>
# else
# include <dirent.h>
# include <errno.h>
@ -61,6 +64,8 @@ GNU General Public License for more details.
@@ -61,6 +64,8 @@ GNU General Public License for more details.
# define ZIP_LOAD_NO_FILES 5
# define ZIP_LOAD_CORRUPTED 6
# define XASH_REDUCE_FD
typedef struct stringlist_s
{
// maxstrings changes as needed, causing reallocation of strings[] array
@ -86,6 +91,11 @@ struct file_s
@@ -86,6 +91,11 @@ struct file_s
// contents buffer
fs_offset_t buff_ind , buff_len ; // buffer current index and length
byte buff [ FILE_BUFF_SIZE ] ; // intermediate buffer
# ifdef XASH_REDUCE_FD
const char * backup_path ;
fs_offset_t * backup_position ;
uint backup_options ;
# endif
} ;
struct wfile_s
@ -114,13 +124,13 @@ typedef struct zipfile_s
@@ -114,13 +124,13 @@ typedef struct zipfile_s
fs_offset_t offset ; // offset of local file header
fs_offset_t size ; //original file size
fs_offset_t compressed_size ; // compressed file size
unsigned short flags ;
} zipfile_t ;
typedef struct zip_s
{
string filename ;
byte * mempool ;
file_t * handle ;
int handle ;
int numfiles ;
time_t filetime ;
zipfile_t * files ;
@ -136,18 +146,82 @@ typedef struct searchpath_s
@@ -136,18 +146,82 @@ typedef struct searchpath_s
struct searchpath_s * next ;
} searchpath_t ;
byte * fs_mempool ;
searchpath_t * fs_searchpaths = NULL ; // chain
searchpath_t fs_directpath ; // static direct path
char fs_basedir [ MAX_SYSPATH ] ; // base game directory
char fs_gamedir [ MAX_SYSPATH ] ; // game current directory
char fs_writedir [ MAX_SYSPATH ] ; // path that game allows to overwrite, delete and rename files (and create new of course)
static byte * fs_mempool ;
static searchpath_t * fs_searchpaths = NULL ; // chain
static searchpath_t fs_directpath ; // static direct path
static char fs_basedir [ MAX_SYSPATH ] ; // base game directory
static char fs_gamedir [ MAX_SYSPATH ] ; // game current directory
static char fs_writedir [ MAX_SYSPATH ] ; // path that game allows to overwrite, delete and rename files (and create new of course)
qboolean fs_ext_path = false ; // attempt to read\write from ./ or ../ pathes
static qboolean fs_ext_path = false ; // attempt to read\write from ./ or ../ pathes
# if !XASH_WIN32
qboolean fs_caseinsensitive = true ; // try to search missing files
static qboolean fs_caseinsensitive = true ; // try to search missing files
# endif
# ifdef XASH_REDUCE_FD
static file_t * fs_last_readfile ;
static zip_t * fs_last_zip ;
static pack_t * fs_last_pak ;
static void FS_EnsureOpenFile ( file_t * file )
{
if ( fs_last_readfile = = file )
return ;
if ( ! file - > backup_path )
return ;
if ( fs_last_readfile & & ( fs_last_readfile - > handle ! = - 1 ) )
{
fs_last_readfile - > backup_position = lseek ( fs_last_readfile - > handle , 0 , SEEK_CUR ) ;
close ( fs_last_readfile - > handle ) ;
fs_last_readfile - > handle = - 1 ;
}
fs_last_readfile = file ;
if ( file & & ( file - > handle = = - 1 ) )
{
file - > handle = open ( file - > backup_path , file - > backup_options ) ;
lseek ( file - > handle , file - > backup_position , SEEK_SET ) ;
}
}
static void FS_EnsureOpenZip ( zip_t * zip )
{
if ( fs_last_zip = = zip )
return ;
if ( fs_last_zip & & ( fs_last_zip - > handle ! = - 1 ) )
{
close ( fs_last_zip - > handle ) ;
fs_last_zip - > handle = - 1 ;
}
fs_last_zip = zip ;
if ( zip & & ( zip - > handle = = - 1 ) )
zip - > handle = open ( zip - > filename , O_RDONLY | O_BINARY ) ;
}
static void FS_BackupFileName ( file_t * file , const char * path , uint options )
{
if ( path = = NULL )
{
if ( file - > backup_path )
Mem_Free ( file - > backup_path ) ;
if ( file = = fs_last_readfile )
FS_EnsureOpenFile ( NULL ) ;
}
else if ( options = = O_RDONLY | | options = = ( O_RDONLY | O_BINARY ) )
{
file - > backup_path = copystring ( path ) ;
file - > backup_options = options ;
}
}
# else
static void FS_EnsureOpenFile ( file_t * file ) { }
static void FS_EnsureOpenZip ( zip_t * zip ) { }
static void FS_BackupFileName ( file_t * file , const char * path , uint options ) { }
# endif
static void FS_InitMemory ( void ) ;
static searchpath_t * FS_FindFile ( const char * name , int * index , qboolean gamedironly ) ;
@ -281,10 +355,8 @@ static void listdirectory( stringlist_t *list, const char *path, qboolean lowerc
@@ -281,10 +355,8 @@ static void listdirectory( stringlist_t *list, const char *path, qboolean lowerc
closedir ( dir ) ;
# endif
// seems not needed anymore
#if 0
// convert names to lowercase because windows doesn't care, but pattern matching code often does
if ( lowercase )
# if XASH_DOS4GW
// convert names to lowercase because 8.3 always in CAPS
listlowercase ( list ) ;
# endif
}
@ -296,6 +368,7 @@ OTHER PRIVATE FUNCTIONS
@@ -296,6 +368,7 @@ OTHER PRIVATE FUNCTIONS
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = =
FS_FixFileCase
@ -305,7 +378,36 @@ emulate WIN32 FS behaviour when opening local file
@@ -305,7 +378,36 @@ emulate WIN32 FS behaviour when opening local file
*/
static const char * FS_FixFileCase ( const char * path )
{
# if !XASH_WIN32 && !XASH_IOS // assume case insensitive
# if defined __DOS__ & !defined __WATCOM_LFN__
// not fix, but convert to 8.3 CAPS and rotate slashes
// it is still recommended to package game data
static char out [ PATH_MAX ] ;
int i = 0 ;
int last = 0 ;
while ( * path )
{
char c = * path + + ;
if ( c = = ' / ' ) c = ' \\ ' ;
else c = toupper ( c ) ;
out [ i + + ] = c ;
if ( c = = ' \\ ' | | c = = ' . ' )
{
if ( i - last > 8 )
{
char * l = & out [ last ] ;
l [ 6 ] = ' ~ ' ;
l [ 7 ] = ' 1 ' ;
l [ 8 ] = c ;
i = last + 9 ;
}
last = i ;
}
}
out [ i ] = 0 ;
return out ;
# elif !XASH_WIN32 && !XASH_IOS // assume case insensitive
DIR * dir ; struct dirent * entry ;
char path2 [ PATH_MAX ] , * fname ;
@ -567,52 +669,41 @@ pack_t *FS_LoadPackPAK( const char *packfile, int *error )
@@ -567,52 +669,41 @@ pack_t *FS_LoadPackPAK( const char *packfile, int *error )
for ( i = 0 ; i < numpackfiles ; i + + )
FS_AddFileToPack ( info [ i ] . name , pack , info [ i ] . filepos , info [ i ] . filelen ) ;
# ifdef XASH_REDUCE_FD
// will reopen when needed
close ( pack - > handle ) ;
pack - > handle = - 1 ;
# endif
if ( error ) * error = PAK_LOAD_OK ;
Mem_Free ( info ) ;
return pack ;
}
static zipfile_t * FS_AddFileToZip ( const char * name , zip_t * zip , fs_offset_t offset , fs_offset_t size , fs_offset_t compressed_size )
{
zipfile_t * zipfile = NULL ;
zipfile = & zip - > files [ zip - > numfiles ] ;
Q_strncpy ( zipfile - > name , name , MAX_SYSPATH ) ;
zipfile - > size = size ;
zipfile - > offset = offset ;
zipfile - > compressed_size = compressed_size ;
zip - > numfiles + + ;
return zipfile ;
}
static zip_t * FS_LoadZip ( const char * zipfile , int * error )
{
int numpackfiles = 0 , i ;
zip_cdf_header_t header_cdf ;
zip_header_eocd_t header_eocd ;
uint signature ;
fs_offset_t filepos = 0 ;
fs_offset_t filepos = 0 , length ;
zipfile_t * info = NULL ;
char filename_buffer [ MAX_SYSPATH ] ;
zip_t * zip = ( zip_t * ) Mem_Calloc ( fs_mempool , sizeof ( zip_t ) ) ;
zip - > handle = FS_O pen( zipfile , " rb " , true ) ;
zip - > handle = open ( zipfile , O_RDONLY | O_BINARY ) ;
# if !XASH_WIN32
if ( ! zip - > handle )
if ( zip - > handle < 0 )
{
const char * fzipfile = FS_FixFileCase ( zipfile ) ;
if ( fzipfile ! = zipfile )
zip - > handle = FS_O pen( fzipfile , " rb " , true ) ;
zip - > handle = o pen( fzipfile , O_RDONLY | O_BINARY ) ;
}
# endif
if ( ! zip - > handle )
if ( zip - > handle < 0 )
{
Con_Reportf ( S_ERROR " %s couldn't open \n " , zipfile ) ;
@ -623,7 +714,9 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
@@ -623,7 +714,9 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
return NULL ;
}
if ( FS_FileLength ( zip - > handle ) > UINT_MAX )
length = lseek ( zip - > handle , 0 , SEEK_END ) ;
if ( length > UINT_MAX )
{
Con_Reportf ( S_ERROR " %s bigger than 4GB. \n " , zipfile ) ;
@ -634,7 +727,9 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
@@ -634,7 +727,9 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
return NULL ;
}
FS_Read ( zip - > handle , ( void * ) & signature , sizeof ( uint ) ) ;
lseek ( zip - > handle , 0 , SEEK_SET ) ;
read ( zip - > handle , & signature , sizeof ( signature ) ) ;
if ( signature = = ZIP_HEADER_EOCD )
{
@ -659,13 +754,13 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
@@ -659,13 +754,13 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
}
// Find oecd
FS_S eek( zip - > handle , 0 , SEEK_SET ) ;
filepos = zip - > handle - > real_ length;
ls eek( zip - > handle , 0 , SEEK_SET ) ;
filepos = length ;
while ( filepos > 0 )
{
FS_S eek( zip - > handle , filepos , SEEK_SET ) ;
FS_R ead( zip - > handle , ( void * ) & signature , sizeof ( signature ) ) ;
ls eek( zip - > handle , filepos , SEEK_SET ) ;
r ead( zip - > handle , & signature , sizeof ( signature ) ) ;
if ( signature = = ZIP_HEADER_EOCD )
break ;
@ -675,7 +770,7 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
@@ -675,7 +770,7 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
if ( ZIP_HEADER_EOCD ! = signature )
{
Con_Reportf ( S_ERROR " C annot find EOCD in %s. Zip file corrupted.\n " , zipfile ) ;
Con_Reportf ( S_ERROR " c annot find EOCD in %s. Zip file corrupted.\n " , zipfile ) ;
if ( error )
* error = ZIP_LOAD_BAD_HEADER ;
@ -684,19 +779,17 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
@@ -684,19 +779,17 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
return NULL ;
}
FS_R ead( zip - > handle , ( void * ) & header_eocd , sizeof ( zip_header_eocd_t ) ) ;
r ead( zip - > handle , & header_eocd , sizeof ( zip_header_eocd_t ) ) ;
// Move to CDF start
FS_Seek ( zip - > handle , header_eocd . central_directory_offset , SEEK_SET ) ;
lseek ( zip - > handle , header_eocd . central_directory_offset , SEEK_SET ) ;
// Calc count of files in archive
info = ( zipfile_t * ) Mem_Calloc ( fs_mempool , sizeof ( zipfile_t ) * header_eocd . total_central_directory_record ) ;
for ( i = 0 ; i < header_eocd . total_central_directory_record ; i + + )
{
FS_R ead( zip - > handle , ( void * ) & header_cdf , sizeof ( header_cdf ) ) ;
r ead( zip - > handle , & header_cdf , sizeof ( header_cdf ) ) ;
if ( header_cdf . signature ! = ZIP_HEADER_CDF )
{
@ -710,16 +803,10 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
@@ -710,16 +803,10 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
return NULL ;
}
if ( header_cdf . uncompressed_size & & header_cdf . filename_len )
{
if ( header_cdf . filename_len > MAX_SYSPATH ) // ignore files with bigger than 1024 bytes
if ( header_cdf . uncompressed_size & & header_cdf . filename_len & & ( header_cdf . filename_len < MAX_SYSPATH ) )
{
Con_Reportf ( S_WARN " File name bigger than buffer. Ignored. \n " ) ;
continue ;
}
memset ( & filename_buffer , ' \0 ' , MAX_SYSPATH ) ;
FS_R ead( zip - > handle , & filename_buffer , header_cdf . filename_len ) ;
read ( zip - > handle , & filename_buffer , header_cdf . filename_len ) ;
Q_strncpy ( info [ numpackfiles ] . name , filename_buffer , MAX_SYSPATH ) ;
info [ numpackfiles ] . size = header_cdf . uncompressed_size ;
@ -728,29 +815,40 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
@@ -728,29 +815,40 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
numpackfiles + + ;
}
else
FS_S eek( zip - > handle , header_cdf . filename_len , SEEK_CUR ) ;
ls eek( zip - > handle , header_cdf . filename_len , SEEK_CUR ) ;
if ( header_cdf . extrafield_len )
FS_S eek( zip - > handle , header_cdf . extrafield_len , SEEK_CUR ) ;
ls eek( zip - > handle , header_cdf . extrafield_len , SEEK_CUR ) ;
if ( header_cdf . file_commentary_len )
FS_Seek ( zip - > handle , header_cdf . file_commentary_len , SEEK_CUR ) ;
lseek ( zip - > handle , header_cdf . file_commentary_len , SEEK_CUR ) ;
}
// recalculate offsets
for ( i = 0 ; i < numpackfiles ; i + + )
{
zip_header_t header ;
lseek ( zip - > handle , info [ i ] . offset , SEEK_SET ) ;
read ( zip - > handle , & header , sizeof ( header ) ) ;
info [ i ] . flags = header . compression_flags ;
info [ i ] . offset = info [ i ] . offset + header . filename_len + header . extrafield_len + sizeof ( header ) ;
}
Q_strncpy ( zip - > filename , zipfile , sizeof ( zip - > filename ) ) ;
zip - > mempool = Mem_AllocPool ( zipfile ) ;
zip - > filetime = FS_SysFileTime ( zipfile ) ;
zip - > numfiles = 0 ;
zip - > files = ( zipfile_t * ) Mem_Calloc ( fs_mempool , sizeof ( zipfile_t ) * numpackfiles ) ;
zip - > numfiles = numpackfiles ;
zip - > files = in fo ;
for ( i = 0 ; i < numpackfiles ; i + + )
FS_AddFileToZip ( info [ i ] . name , zip , info [ i ] . offset , info [ i ] . size , info [ i ] . compressed_size ) ;
# ifdef XASH_REDUCE_FD
// will reopen when needed
close ( zip - > handle ) ;
zip - > handle = - 1 ;
# endif
if ( error )
* error = ZIP_LOAD_OK ;
Mem_Free ( info ) ;
return zip ;
}
@ -759,10 +857,12 @@ void Zip_Close( zip_t *zip )
@@ -759,10 +857,12 @@ void Zip_Close( zip_t *zip )
if ( ! zip )
return ;
Mem_FreePool ( & zip - > mempool ) ;
Mem_Free ( zip - > files ) ;
FS_EnsureOpenZip ( NULL ) ;
if ( zip - > handle ! = NULL )
FS_C lose( zip - > handle ) ;
if ( zip - > handle > = 0 )
c lose( zip - > handle ) ;
Mem_Free ( zip ) ;
}
@ -771,7 +871,6 @@ static byte *Zip_LoadFile( const char *path, fs_offset_t *sizeptr, qboolean game
@@ -771,7 +871,6 @@ static byte *Zip_LoadFile( const char *path, fs_offset_t *sizeptr, qboolean game
{
searchpath_t * search ;
int index ;
zip_header_t header ;
zipfile_t * file = NULL ;
byte * compressed_buffer = NULL , * decompressed_buffer = NULL ;
int zlib_result = 0 ;
@ -787,57 +886,51 @@ static byte *Zip_LoadFile( const char *path, fs_offset_t *sizeptr, qboolean game
@@ -787,57 +886,51 @@ static byte *Zip_LoadFile( const char *path, fs_offset_t *sizeptr, qboolean game
file = & search - > zip - > files [ index ] ;
FS_Seek ( search - > zip - > handle , file - > offset , SEEK_SET ) ;
FS_Read ( search - > zip - > handle , ( void * ) & header , sizeof ( header ) ) ;
FS_EnsureOpenZip ( search - > zip ) ;
if ( lseek ( search - > zip - > handle , file - > offset , SEEK_SET ) = = - 1 )
return NULL ;
/*if( read( search->zip->handle, &header, sizeof( header ) ) < 0 )
return NULL ;
if ( header . signature ! = ZIP_HEADER_LF )
{
Con_Reportf ( S_ERROR " Zip_LoadFile: %s signature error \n " , file - > name ) ;
return NULL ;
}
} */
if ( header . compression_ flags = = ZIP_COMPRESSION_NO_COMPRESSION )
if ( file - > flags = = ZIP_COMPRESSION_NO_COMPRESSION )
{
if ( header . filename_len )
FS_Seek ( search - > zip - > handle , header . filename_len , SEEK_CUR ) ;
if ( header . extrafield_len )
FS_Seek ( search - > zip - > handle , header . extrafield_len , SEEK_CUR ) ;
decompressed_buffer = Mem_Malloc ( search - > zip - > mempool , file - > size + 1 ) ;
decompressed_buffer = Mem_Malloc ( fs_mempool , file - > size + 1 ) ;
decompressed_buffer [ file - > size ] = ' \0 ' ;
FS_R ead( search - > zip - > handle , decompressed_buffer , file - > size ) ;
read ( search - > zip - > handle , decompressed_buffer , file - > size ) ;
#if 0
CRC32_Init ( & test_crc ) ;
CRC32_ProcessBuffer ( & test_crc , decompressed_buffer , file - > size ) ;
final_crc = CRC32_Final ( test_crc ) ;
if ( final_crc ! = header . crc32 )
if ( final_crc ! = file - > crc32 )
{
Con_Reportf ( S_ERROR " Zip_LoadFile: %s file crc32 mismatch \n " , file - > name ) ;
Mem_Free ( decompressed_buffer ) ;
return NULL ;
}
# endif
if ( sizeptr ) * sizeptr = file - > size ;
FS_EnsureOpenZip ( NULL ) ;
return decompressed_buffer ;
}
else if ( header . compression_ flags = = ZIP_COMPRESSION_DEFLATED )
else if ( file - > flags = = ZIP_COMPRESSION_DEFLATED )
{
if ( header . filename_len )
FS_Seek ( search - > zip - > handle , header . filename_len , SEEK_CUR ) ;
if ( header . extrafield_len )
FS_Seek ( search - > zip - > handle , header . extrafield_len , SEEK_CUR ) ;
compressed_buffer = Mem_Malloc ( search - > zip - > mempool , file - > compressed_size + 1 ) ;
decompressed_buffer = Mem_Malloc ( search - > zip - > mempool , file - > size + 1 ) ;
compressed_buffer = Mem_Malloc ( fs_mempool , file - > compressed_size + 1 ) ;
decompressed_buffer = Mem_Malloc ( fs_mempool , file - > size + 1 ) ;
decompressed_buffer [ file - > size ] = ' \0 ' ;
FS_R ead( search - > zip - > handle , compressed_buffer , file - > compressed_size ) ;
read ( search - > zip - > handle , compressed_buffer , file - > compressed_size ) ;
memset ( & decompress_stream , 0 , sizeof ( decompress_stream ) ) ;
@ -864,21 +957,22 @@ static byte *Zip_LoadFile( const char *path, fs_offset_t *sizeptr, qboolean game
@@ -864,21 +957,22 @@ static byte *Zip_LoadFile( const char *path, fs_offset_t *sizeptr, qboolean game
if ( zlib_result = = Z_OK | | zlib_result = = Z_STREAM_END )
{
Mem_Free ( compressed_buffer ) ; // finaly free compressed buffer
#if 0
CRC32_Init ( & test_crc ) ;
CRC32_ProcessBuffer ( & test_crc , decompressed_buffer , file - > size ) ;
final_crc = CRC32_Final ( test_crc ) ;
if ( final_crc ! = header . crc32 )
if ( final_crc ! = file - > crc32 )
{
Con_Reportf ( S_ERROR " Zip_LoadFile: %s file crc32 mismatch \n " , file - > name ) ;
Mem_Free ( decompressed_buffer ) ;
return NULL ;
}
# endif
if ( sizeptr ) * sizeptr = file - > size ;
FS_EnsureOpenZip ( NULL ) ;
return decompressed_buffer ;
}
else
@ -896,6 +990,7 @@ static byte *Zip_LoadFile( const char *path, fs_offset_t *sizeptr, qboolean game
@@ -896,6 +990,7 @@ static byte *Zip_LoadFile( const char *path, fs_offset_t *sizeptr, qboolean game
return NULL ;
}
FS_EnsureOpenZip ( NULL ) ;
return NULL ;
}
@ -998,7 +1093,7 @@ static qboolean FS_AddPak_Fullpath( const char *pakfile, qboolean *already_loade
@@ -998,7 +1093,7 @@ static qboolean FS_AddPak_Fullpath( const char *pakfile, qboolean *already_loade
{
if ( ! Q_stricmp ( COM_FileExtension ( pak - > files [ i ] . name ) , " wad " ) )
{
Q_sprintf ( fullpath , " %s/%s " , pakfile , pak - > files [ i ] . name ) ;
Q_sn printf ( fullpath , MAX_STRING , " %s/%s " , pakfile , pak - > files [ i ] . name ) ;
FS_AddWad_Fullpath ( fullpath , NULL , flags ) ;
}
}
@ -1036,6 +1131,9 @@ qboolean FS_AddZip_Fullpath( const char *zipfile, qboolean *already_loaded, int
@@ -1036,6 +1131,9 @@ qboolean FS_AddZip_Fullpath( const char *zipfile, qboolean *already_loaded, int
if ( zip )
{
string fullpath ;
int i ;
search = ( searchpath_t * ) Mem_Calloc ( fs_mempool , sizeof ( searchpath_t ) ) ;
search - > zip = zip ;
search - > next = fs_searchpaths ;
@ -1043,6 +1141,16 @@ qboolean FS_AddZip_Fullpath( const char *zipfile, qboolean *already_loaded, int
@@ -1043,6 +1141,16 @@ qboolean FS_AddZip_Fullpath( const char *zipfile, qboolean *already_loaded, int
fs_searchpaths = search ;
Con_Reportf ( " Adding zipfile: %s (%i files) \n " , zipfile , zip - > numfiles ) ;
// time to add in search list all the wads that contains in current pakfile (if do)
for ( i = 0 ; i < zip - > numfiles ; i + + )
{
if ( ! Q_stricmp ( COM_FileExtension ( zip - > files [ i ] . name ) , " wad " ) )
{
Q_snprintf ( fullpath , MAX_STRING , " %s/%s " , zipfile , zip - > files [ i ] . name ) ;
FS_AddWad_Fullpath ( fullpath , NULL , flags ) ;
}
}
return true ;
}
else
@ -1070,7 +1178,6 @@ void FS_AddGameDirectory( const char *dir, uint flags )
@@ -1070,7 +1178,6 @@ void FS_AddGameDirectory( const char *dir, uint flags )
if ( ! FBitSet ( flags , FS_NOWRITE_PATH ) )
Q_strncpy ( fs_writedir , dir , sizeof ( fs_writedir ) ) ;
stringlistinit ( & list ) ;
listdirectory ( & list , dir , false ) ;
stringlistsort ( & list ) ;
@ -1085,25 +1192,25 @@ void FS_AddGameDirectory( const char *dir, uint flags )
@@ -1085,25 +1192,25 @@ void FS_AddGameDirectory( const char *dir, uint flags )
}
}
FS_AllowDirectPaths ( true ) ;
// add any WAD package in the directory
// add any Zip package in the directory
for ( i = 0 ; i < list . numstrings ; i + + )
{
if ( ! Q_stricmp ( COM_FileExtension ( list . strings [ i ] ) , " wad " ) )
if ( ! Q_stricmp ( COM_FileExtension ( list . strings [ i ] ) , " zip " ) | | ! Q_stricmp ( COM_FileExtension ( list . strings [ i ] ) , " pk3 " ) )
{
Q_sprintf ( fullpath , " %s%s " , dir , list . strings [ i ] ) ;
FS_AddWad _Fullpath ( fullpath , NULL , flags ) ;
FS_AddZip _Fullpath ( fullpath , NULL , flags ) ;
}
}
// add any Zip package in the directory
FS_AllowDirectPaths ( true ) ;
// add any WAD package in the directory
for ( i = 0 ; i < list . numstrings ; i + + )
{
if ( ! Q_stricmp ( COM_FileExtension ( list . strings [ i ] ) , " zip " ) | | ! Q_stricmp ( COM_FileExtension ( list . strings [ i ] ) , " pk3 " ) )
if ( ! Q_stricmp ( COM_FileExtension ( list . strings [ i ] ) , " wad " ) )
{
Q_sprintf ( fullpath , " %s%s " , dir , list . strings [ i ] ) ;
FS_AddZip _Fullpath ( fullpath , NULL , flags ) ;
FS_AddWad _Fullpath ( fullpath , NULL , flags ) ;
}
}
@ -1197,6 +1304,8 @@ void FS_ClearSearchPath( void )
@@ -1197,6 +1304,8 @@ void FS_ClearSearchPath( void )
{
if ( search - > pack - > files )
Mem_Free ( search - > pack - > files ) ;
if ( search - > pack - > handle > = 0 )
close ( search - > pack - > handle ) ;
Mem_Free ( search - > pack ) ;
}
@ -2118,7 +2227,11 @@ static file_t *FS_SysOpen( const char *filepath, const char *mode )
@@ -2118,7 +2227,11 @@ static file_t *FS_SysOpen( const char *filepath, const char *mode )
const char * ffilepath = FS_FixFileCase ( filepath ) ;
if ( ffilepath ! = filepath )
file - > handle = open ( ffilepath , mod | opt , 0666 ) ;
if ( file - > handle > = 0 )
FS_BackupFileName ( file , ffilepath , mod | opt ) ;
}
else
FS_BackupFileName ( file , filepath , mod | opt ) ;
# endif
if ( file - > handle < 0 )
@ -2127,14 +2240,62 @@ static file_t *FS_SysOpen( const char *filepath, const char *mode )
@@ -2127,14 +2240,62 @@ static file_t *FS_SysOpen( const char *filepath, const char *mode )
return NULL ;
}
file - > real_length = lseek ( file - > handle , 0 , SEEK_END ) ;
// uncomment do disable write
//if( opt & O_CREAT )
// return NULL;
// For files opened in append mode, we start at the end of the file
if ( mod & O_APPEND ) file - > position = file - > real_length ;
if ( opt & O_APPEND ) file - > position = file - > real_length ;
else lseek ( file - > handle , 0 , SEEK_SET ) ;
return file ;
}
/*
static int FS_DuplicateHandle ( const char * filename , int handle , fs_offset_t pos )
{
# ifdef HAVE_DUP
return dup ( handle ) ;
# else
int newhandle = open ( filename , O_RDONLY | O_BINARY ) ;
lseek ( newhandle , pos , SEEK_SET ) ;
return newhandle ;
# endif
}
*/
static int FS_OpenHandle ( const char * syspath , int handle , fs_offset_t offset , fs_offset_t len )
{
file_t * file = ( file_t * ) Mem_Calloc ( fs_mempool , sizeof ( file_t ) ) ;
# ifndef XASH_REDUCE_FD
# ifdef HAVE_DUP
file - > handle = dup ( handle ) ;
# else
file - > handle = open ( syspath , O_RDONLY | O_BINARY ) ;
# endif
if ( lseek ( file - > handle , offset , SEEK_SET ) = = - 1 )
{
Mem_Free ( file ) ;
return NULL ;
}
# else
file - > backup_position = offset ;
file - > backup_path = copystring ( syspath ) ;
file - > backup_options = O_RDONLY | O_BINARY ;
file - > handle = - 1 ;
# endif
file - > real_length = len ;
file - > offset = offset ;
file - > position = 0 ;
file - > ungetc = EOF ;
return file ;
}
/*
= = = = = = = = = = =
@ -2146,27 +2307,29 @@ Open a packed file using its package file descriptor
@@ -2146,27 +2307,29 @@ Open a packed file using its package file descriptor
file_t * FS_OpenPackedFile ( pack_t * pack , int pack_ind )
{
dpackfile_t * pfile ;
int dup_handle ;
file_t * file ;
pfile = & pack - > files [ pack_ind ] ;
if ( lseek ( pack - > handle , pfile - > filepos , SEEK_SET ) = = - 1 )
return NULL ;
return FS_OpenHandle ( pack - > filename , pack - > handle , pfile - > filepos , pfile - > filelen ) ;
}
dup_handle = dup ( pack - > handle ) ;
/*
= = = = = = = = = = =
FS_OpenZipFile
if ( dup_handle < 0 )
return NULL ;
Open a packed file using its package file descriptor
= = = = = = = = = = =
*/
file_t * FS_OpenZipFile ( zip_t * zip , int pack_ind )
{
zipfile_t * pfile ;
pfile = & zip - > files [ pack_ind ] ;
file = ( file_t * ) Mem_Calloc ( fs_mempool , sizeof ( * file ) ) ;
file - > handle = dup_handle ;
file - > real_length = pfile - > filelen ;
file - > offset = pfile - > filepos ;
file - > position = 0 ;
file - > ungetc = EOF ;
// compressed files handled in Zip_LoadFile
if ( pfile - > flags ! = ZIP_COMPRESSION_NO_COMPRESSION )
return NULL ;
return file ;
return FS_OpenHandle ( zip - > filename , zip - > handle , pfile - > offset , pfile - > size ) ;
}
/*
@ -2431,6 +2594,8 @@ file_t *FS_OpenReadFile( const char *filename, const char *mode, qboolean gamedi
@@ -2431,6 +2594,8 @@ file_t *FS_OpenReadFile( const char *filename, const char *mode, qboolean gamedi
return FS_OpenPackedFile ( search - > pack , pack_ind ) ;
else if ( search - > wad )
return NULL ; // let W_LoadFile get lump correctly
else if ( search - > zip )
return FS_OpenZipFile ( search - > zip , pack_ind ) ;
else if ( pack_ind < 0 )
{
char path [ MAX_SYSPATH ] ;
@ -2495,6 +2660,9 @@ int FS_Close( file_t *file )
@@ -2495,6 +2660,9 @@ int FS_Close( file_t *file )
{
if ( ! file ) return 0 ;
FS_BackupFileName ( file , NULL , 0 ) ;
if ( file - > handle > = 0 )
if ( close ( file - > handle ) )
return EOF ;
@ -2575,6 +2743,7 @@ fs_offset_t FS_Read( file_t *file, void *buffer, size_t buffersize )
@@ -2575,6 +2743,7 @@ fs_offset_t FS_Read( file_t *file, void *buffer, size_t buffersize )
// NOTE: at this point, the read buffer is always empty
FS_EnsureOpenFile ( file ) ;
// we must take care to not read after the end of the file
count = file - > real_length - file - > position ;
@ -2784,6 +2953,7 @@ int FS_Seek( file_t *file, fs_offset_t offset, int whence )
@@ -2784,6 +2953,7 @@ int FS_Seek( file_t *file, fs_offset_t offset, int whence )
return 0 ;
}
FS_EnsureOpenFile ( file ) ;
// Purge cached data
FS_Purge ( file ) ;
@ -2853,6 +3023,7 @@ byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamediro
@@ -2853,6 +3023,7 @@ byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamediro
if ( file )
{
filesize = file - > real_length ;
buf = ( byte * ) Mem_Malloc ( fs_mempool , filesize + 1 ) ;
buf [ filesize ] = ' \0 ' ;
FS_Read ( file , buf , filesize ) ;