diff --git a/filesystem/android.c b/filesystem/android.c index a724f9b4..c6967436 100644 --- a/filesystem/android.c +++ b/filesystem/android.c @@ -227,6 +227,7 @@ static file_t *FS_OpenFile_AndroidAssets( searchpath_t *search, const char *file file->position = 0; file->ungetc = EOF; + file->searchpath = search; AAsset_close( assets ); diff --git a/filesystem/dir.c b/filesystem/dir.c index 19de4660..881f1d80 100644 --- a/filesystem/dir.c +++ b/filesystem/dir.c @@ -457,10 +457,14 @@ static int FS_FileTime_DIR( searchpath_t *search, const char *filename ) static file_t *FS_OpenFile_DIR( searchpath_t *search, const char *filename, const char *mode, int pack_ind ) { + file_t *f; char path[MAX_SYSPATH]; Q_snprintf( path, sizeof( path ), "%s%s", search->filename, filename ); - return FS_SysOpen( path, mode ); + f = FS_SysOpen( path, mode ); + f->searchpath = search; + + return f; } void FS_InitDirectorySearchpath( searchpath_t *search, const char *path, int flags ) diff --git a/filesystem/filesystem.c b/filesystem/filesystem.c index e226d78b..29095f50 100644 --- a/filesystem/filesystem.c +++ b/filesystem/filesystem.c @@ -1162,13 +1162,13 @@ void FS_AddGameHierarchy( const char *dir, uint flags ) if( COM_CheckStringEmpty( fs_rodir ) ) { // append new flags to rodir, except FS_GAMEDIR_PATH and FS_CUSTOM_PATH - uint newFlags = FS_NOWRITE_PATH | (flags & (~FS_GAMEDIR_PATH|FS_CUSTOM_PATH)); + uint new_flags = FS_NOWRITE_PATH | (flags & (~FS_GAMEDIR_PATH|FS_CUSTOM_PATH)); if( isGameDir ) - newFlags |= FS_GAMERODIR_PATH; + SetBits( new_flags, FS_GAMERODIR_PATH ); FS_AllowDirectPaths( true ); Q_snprintf( buf, sizeof( buf ), "%s/%s/", fs_rodir, dir ); - FS_AddGameDirectory( buf, newFlags ); + FS_AddGameDirectory( buf, new_flags ); FS_AllowDirectPaths( false ); } @@ -1226,7 +1226,7 @@ void FS_LoadGameInfo( const char *rootfolder ) int i; // lock uplevel of gamedir for read\write - fs_ext_path = false; + FS_AllowDirectPaths( false ); if( rootfolder ) Q_strncpy( fs_gamedir, rootfolder, sizeof( fs_gamedir )); Con_Reportf( "%s( %s )\n", __func__, fs_gamedir ); @@ -1312,7 +1312,7 @@ static qboolean FS_FindLibrary( const char *dllname, qboolean directpath, fs_dll if( !COM_CheckString( dllname )) return false; - fs_ext_path = directpath; + FS_AllowDirectPaths( directpath ); // HACKHACK remove relative path to game folder if( !Q_strnicmp( dllname, "..", 2 )) @@ -1344,7 +1344,7 @@ static qboolean FS_FindLibrary( const char *dllname, qboolean directpath, fs_dll } else if( !directpath ) { - fs_ext_path = false; + FS_AllowDirectPaths( false ); // trying check also 'bin' folder for indirect paths search = FS_FindFile( dllname, &index, fixedname, sizeof( fixedname ), false ); @@ -1389,7 +1389,7 @@ static qboolean FS_FindLibrary( const char *dllname, qboolean directpath, fs_dll dllInfo->custom_loader = false; } } - fs_ext_path = false; // always reset direct paths + FS_AllowDirectPaths( false ); // always reset direct paths return true; } @@ -1704,7 +1704,7 @@ file_t *FS_SysOpen( const char *filepath, const char *mode ) return NULL; } - + file->searchpath = NULL; file->real_length = lseek( file->handle, 0, SEEK_END ); // uncomment do disable write @@ -1730,16 +1730,23 @@ static int FS_DuplicateHandle( const char *filename, int handle, fs_offset_t pos } */ -file_t *FS_OpenHandle( const char *syspath, int handle, fs_offset_t offset, fs_offset_t len ) +file_t *FS_OpenHandle( searchpath_t *searchpath, 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 ); + file->handle = open( searchpath->filename, O_RDONLY|O_BINARY ); #endif + if( file->handle < 0 ) + { + Con_Printf( S_ERROR "%s: couldn't create fd for %s:0x%lx: %s\n", __func__, searchpath->filename, (long)offset, strerror( errno )); + Mem_Free( file ); + return NULL; + } + if( lseek( file->handle, offset, SEEK_SET ) == -1 ) { Mem_Free( file ); @@ -1757,6 +1764,7 @@ file_t *FS_OpenHandle( const char *syspath, int handle, fs_offset_t offset, fs_o file->offset = offset; file->position = 0; file->ungetc = EOF; + file->searchpath = searchpath; return file; } @@ -2333,6 +2341,8 @@ int FS_Gets( file_t *file, char *string, size_t bufsize ) FS_Seek Move the position index in a file +NOTE: when porting code, check return value! +NOTE: it's not compatible with lseek! ==================== */ int FS_Seek( file_t *file, fs_offset_t offset, int whence ) @@ -2913,6 +2923,14 @@ search_t *FS_Search( const char *pattern, int caseinsensitive, int gamedironly ) return search; } +static const char *FS_ArchivePath( file_t *f ) +{ + if( f->searchpath ) + return f->searchpath->filename; + + return "plain"; +} + void FS_InitMemory( void ) { fs_mempool = Mem_AllocPool( "FileSystem Pool" ); diff --git a/filesystem/filesystem.h b/filesystem/filesystem.h index f6d3e85d..6ebe6f0d 100644 --- a/filesystem/filesystem.h +++ b/filesystem/filesystem.h @@ -191,9 +191,8 @@ typedef struct fs_api_t qboolean (*SysFileExists)( const char *path ); const char *(*GetDiskPath)( const char *name, qboolean gamedironly ); - // reserved - void (*Unused0)( void ); - void *(*MountArchive_Fullpath)( const char *path, int flags ); + const char *(*ArchivePath)( file_t *f ); // returns path to archive from which file was opened or "plain" + void *(*MountArchive_Fullpath)( const char *path, int flags ); // mounts the archive by path, if supported qboolean (*GetFullDiskPath)( char *buffer, size_t size, const char *name, qboolean gamedironly ); diff --git a/filesystem/filesystem_internal.h b/filesystem/filesystem_internal.h index d262eec9..e2531177 100644 --- a/filesystem/filesystem_internal.h +++ b/filesystem/filesystem_internal.h @@ -31,28 +31,30 @@ extern "C" { #endif +typedef struct searchpath_s searchpath_t; typedef struct dir_s dir_t; typedef struct zip_s zip_t; typedef struct pack_s pack_t; typedef struct wfile_s wfile_t; -#if XASH_ANDROID typedef struct android_assets_s android_assets_t; -// typedef struct android_saf_s android_saf_t; -#endif -#define FILE_BUFF_SIZE (2048) +#define FILE_BUFF_SIZE (2048) struct file_s { - int handle; // file descriptor - int ungetc; // single stored character from ungetc, cleared to EOF when read - fs_offset_t real_length; // uncompressed file size (for files opened in "read" mode) - fs_offset_t position; // current position in the file - fs_offset_t offset; // offset into the package (0 if external file) - time_t filetime; // pak, wad or real filetime - // contents buffer - fs_offset_t buff_ind, buff_len; // buffer current index and length - byte buff[FILE_BUFF_SIZE]; // intermediate buffer + int handle; // file descriptor + int ungetc; // single stored character from ungetc, cleared to EOF when read + time_t filetime; // pak, wad or real filetime + searchpath_t *searchpath; + fs_offset_t real_length; // uncompressed file size (for files opened in "read" mode) + fs_offset_t position; // current position in the file + fs_offset_t offset; // offset into the package (0 if external file) + + // contents buffer + fs_offset_t buff_ind; // buffer current index + fs_offset_t buff_len; // buffer current length + byte buff[FILE_BUFF_SIZE]; // intermediate buffer + #ifdef XASH_REDUCE_FD const char *backup_path; fs_offset_t backup_position; @@ -80,9 +82,9 @@ typedef struct stringlist_s typedef struct searchpath_s { - string filename; - searchpathtype_t type; - int flags; + string filename; + searchpathtype_t type; + int flags; union { @@ -90,9 +92,7 @@ typedef struct searchpath_s pack_t *pack; wfile_t *wad; zip_t *zip; -#if XASH_ANDROID android_assets_t *assets; -#endif }; struct searchpath_s *next; @@ -211,7 +211,7 @@ qboolean FS_SysFileOrFolderExists( const char *path ); file_t *FS_OpenReadFile( const char *filename, const char *mode, qboolean gamedironly ); int FS_SysFileTime( const char *filename ); -file_t *FS_OpenHandle( const char *syspath, int handle, fs_offset_t offset, fs_offset_t len ); +file_t *FS_OpenHandle( searchpath_t *search, int handle, fs_offset_t offset, fs_offset_t len ); file_t *FS_SysOpen( const char *filepath, const char *mode ); searchpath_t *FS_FindFile( const char *name, int *index, char *fixedname, size_t len, qboolean gamedironly ); qboolean FS_FullPathToRelativePath( char *dst, const char *src, size_t size ); diff --git a/filesystem/pak.c b/filesystem/pak.c index 9510a968..8ca8b415 100644 --- a/filesystem/pak.c +++ b/filesystem/pak.c @@ -67,9 +67,8 @@ typedef struct struct pack_s { - int handle; + file_t *handle; int numfiles; - time_t filetime; // common for all packed files dpackfile_t files[1]; // flexible }; @@ -99,27 +98,29 @@ of the list so they override previous pack files. static pack_t *FS_LoadPackPAK( const char *packfile, int *error ) { dpackheader_t header; - int packhandle; + file_t *packhandle; int numpackfiles; pack_t *pack; fs_size_t c; - packhandle = open( packfile, O_RDONLY|O_BINARY ); + // TODO: use FS_Open to allow PK3 to be included into other archives + // Currently, it doesn't work with rodir due to FS_FindFile logic + packhandle = FS_SysOpen( packfile, "rb" ); - if( packhandle < 0 ) + if( packhandle == NULL ) { Con_Reportf( "%s couldn't open: %s\n", packfile, strerror( errno )); if( error ) *error = PAK_LOAD_COULDNT_OPEN; return NULL; } - c = read( packhandle, (void *)&header, sizeof( header )); + c = FS_Read( packhandle, (void *)&header, sizeof( header )); if( c != sizeof( header ) || header.ident != IDPACKV1HEADER ) { Con_Reportf( "%s is not a packfile. Ignored.\n", packfile ); if( error ) *error = PAK_LOAD_BAD_HEADER; - close( packhandle ); + FS_Close( packhandle ); return NULL; } @@ -127,7 +128,7 @@ static pack_t *FS_LoadPackPAK( const char *packfile, int *error ) { Con_Reportf( S_ERROR "%s has an invalid directory size. Ignored.\n", packfile ); if( error ) *error = PAK_LOAD_BAD_FOLDERS; - close( packhandle ); + FS_Close( packhandle ); return NULL; } @@ -137,7 +138,7 @@ static pack_t *FS_LoadPackPAK( const char *packfile, int *error ) { Con_Reportf( S_ERROR "%s has too many files ( %i ). Ignored.\n", packfile, numpackfiles ); if( error ) *error = PAK_LOAD_TOO_MANY_FILES; - close( packhandle ); + FS_Close( packhandle ); return NULL; } @@ -145,26 +146,25 @@ static pack_t *FS_LoadPackPAK( const char *packfile, int *error ) { Con_Reportf( "%s has no files. Ignored.\n", packfile ); if( error ) *error = PAK_LOAD_NO_FILES; - close( packhandle ); + FS_Close( packhandle ); return NULL; } pack = (pack_t *)Mem_Calloc( fs_mempool, sizeof( pack_t ) + sizeof( dpackfile_t ) * ( numpackfiles - 1 )); - lseek( packhandle, header.dirofs, SEEK_SET ); + FS_Seek( packhandle, header.dirofs, SEEK_SET ); - if( header.dirlen != read( packhandle, (void *)pack->files, header.dirlen )) + if( header.dirlen != FS_Read( packhandle, (void *)pack->files, header.dirlen )) { Con_Reportf( "%s is an incomplete PAK, not loading\n", packfile ); if( error ) *error = PAK_LOAD_CORRUPTED; - close( packhandle ); + FS_Close( packhandle ); Mem_Free( pack ); return NULL; } // TODO: validate directory? - pack->filetime = FS_SysFileTime( packfile ); pack->handle = packhandle; pack->numfiles = numpackfiles; qsort( pack->files, pack->numfiles, sizeof( pack->files[0] ), FS_SortPak ); @@ -194,7 +194,7 @@ static file_t *FS_OpenFile_PAK( searchpath_t *search, const char *filename, cons pfile = &search->pack->files[pack_ind]; - return FS_OpenHandle( search->filename, search->pack->handle, pfile->filepos, pfile->filelen ); + return FS_OpenHandle( search, search->pack->handle->handle, pfile->filepos, pfile->filelen ); } /* @@ -288,7 +288,7 @@ FS_FileTime_PAK */ static int FS_FileTime_PAK( searchpath_t *search, const char *filename ) { - return search->pack->filetime; + return search->pack->handle->filetime; } /* @@ -299,7 +299,9 @@ FS_PrintInfo_PAK */ static void FS_PrintInfo_PAK( searchpath_t *search, char *dst, size_t size ) { - Q_snprintf( dst, size, "%s (%i files)", search->filename, search->pack->numfiles ); + if( search->pack->handle->searchpath ) + Q_snprintf( dst, size, "%s (%i files)" S_CYAN " from %s" S_DEFAULT, search->filename, search->pack->numfiles, search->pack->handle->searchpath->filename ); + else Q_snprintf( dst, size, "%s (%i files)", search->filename, search->pack->numfiles ); } /* @@ -310,8 +312,8 @@ FS_Close_PAK */ static void FS_Close_PAK( searchpath_t *search ) { - if( search->pack->handle >= 0 ) - close( search->pack->handle ); + if( search->pack->handle != NULL ) + FS_Close( search->pack->handle ); Mem_Free( search->pack ); } diff --git a/filesystem/wad.c b/filesystem/wad.c index 10070985..14f25dc4 100644 --- a/filesystem/wad.c +++ b/filesystem/wad.c @@ -415,7 +415,9 @@ FS_PrintInfo_WAD */ static void FS_PrintInfo_WAD( searchpath_t *search, char *dst, size_t size ) { - Q_snprintf( dst, size, "%s (%i files)", search->filename, search->wad->numlumps ); + if( search->wad->handle->searchpath ) + Q_snprintf( dst, size, "%s (%i files)" S_CYAN " from %s" S_DEFAULT, search->filename, search->wad->numlumps, search->wad->handle->searchpath->filename ); + else Q_snprintf( dst, size, "%s (%i files)", search->filename, search->wad->numlumps ); } /* diff --git a/filesystem/zip.c b/filesystem/zip.c index 4f27ffb2..ed6eff87 100644 --- a/filesystem/zip.c +++ b/filesystem/zip.c @@ -123,33 +123,13 @@ typedef struct zipfile_s struct zip_s { - int handle; + file_t *handle; int numfiles; - time_t filetime; - zipfile_t *files; + zipfile_t files[1]; // flexible }; // #define ENABLE_CRC_CHECK // known to be buggy because of possible libpublic crc32 bug, disabled -#ifdef XASH_REDUCE_FD -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 ); -} -#else -static void FS_EnsureOpenZip( zip_t *zip ) {} -#endif - /* ============ FS_CloseZIP @@ -157,13 +137,8 @@ FS_CloseZIP */ static void FS_CloseZIP( zip_t *zip ) { - if( zip->files ) - Mem_Free( zip->files ); - - FS_EnsureOpenZip( NULL ); - - if( zip->handle >= 0 ) - close( zip->handle ); + if( zip->handle != NULL ) + FS_Close( zip->handle ); Mem_Free( zip ); } @@ -185,7 +160,7 @@ FS_SortZip */ static int FS_SortZip( const void *a, const void *b ) { - return Q_stricmp( ( ( zipfile_t* )a )->name, ( ( zipfile_t* )b )->name ); + return Q_stricmp(((zipfile_t *)a )->name, ((zipfile_t *)b )->name ); } /* @@ -199,15 +174,17 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error ) zip_cdf_header_t header_cdf; zip_header_eocd_t header_eocd; uint32_t signature; - fs_offset_t filepos = 0, length; + fs_offset_t filepos = 0; zipfile_t *info = NULL; char filename_buffer[MAX_SYSPATH]; zip_t *zip = (zip_t *)Mem_Calloc( fs_mempool, sizeof( *zip )); fs_size_t c; - zip->handle = open( zipfile, O_RDONLY|O_BINARY ); + // TODO: use FS_Open to allow PK3 to be included into other archives + // Currently, it doesn't work with rodir due to FS_FindFile logic + zip->handle = FS_SysOpen( zipfile, "rb" ); - if( zip->handle < 0 ) + if( zip->handle == NULL ) { Con_Reportf( S_ERROR "%s couldn't open\n", zipfile ); @@ -218,9 +195,7 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error ) return NULL; } - length = lseek( zip->handle, 0, SEEK_END ); - - if( length > UINT_MAX ) + if( zip->handle->real_length > UINT32_MAX ) { Con_Reportf( S_ERROR "%s bigger than 4GB.\n", zipfile ); @@ -231,9 +206,9 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error ) return NULL; } - lseek( zip->handle, 0, SEEK_SET ); + FS_Seek( zip->handle, 0, SEEK_SET ); - c = read( zip->handle, &signature, sizeof( signature ) ); + c = FS_Read( zip->handle, &signature, sizeof( signature )); if( c != sizeof( signature ) || signature == ZIP_HEADER_EOCD ) { @@ -258,13 +233,12 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error ) } // Find oecd - lseek( zip->handle, 0, SEEK_SET ); - filepos = length; + filepos = zip->handle->real_length; - while ( filepos > 0 ) + while( filepos > 0 ) { - lseek( zip->handle, filepos, SEEK_SET ); - c = read( zip->handle, &signature, sizeof( signature ) ); + FS_Seek( zip->handle, filepos, SEEK_SET ); + c = FS_Read( zip->handle, &signature, sizeof( signature )); if( c == sizeof( signature ) && signature == ZIP_HEADER_EOCD ) break; @@ -283,7 +257,7 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error ) return NULL; } - c = read( zip->handle, &header_eocd, sizeof( header_eocd ) ); + c = FS_Read( zip->handle, &header_eocd, sizeof( header_eocd )); if( c != sizeof( header_eocd )) { @@ -296,15 +270,27 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error ) return NULL; } + if( header_eocd.total_central_directory_record == 0 ) // refuse to load empty ZIP archives + { + Con_Reportf( S_WARN "%s has no files (total records is zero). Ignored.\n", zipfile ); + + if( error ) + *error = ZIP_LOAD_NO_FILES; + + FS_CloseZIP( zip ); + return NULL; + } + // Move to CDF start - lseek( zip->handle, header_eocd.central_directory_offset, SEEK_SET ); + FS_Seek( zip->handle, header_eocd.central_directory_offset, SEEK_SET ); // Calc count of files in archive - info = (zipfile_t *)Mem_Calloc( fs_mempool, sizeof( *info ) * header_eocd.total_central_directory_record ); + zip = (zip_t *)Mem_Realloc( fs_mempool, zip, sizeof( *zip ) + sizeof( *info ) * ( header_eocd.total_central_directory_record - 1 )); + info = zip->files; for( i = 0; i < header_eocd.total_central_directory_record; i++ ) { - c = read( zip->handle, &header_cdf, sizeof( header_cdf ) ); + c = FS_Read( zip->handle, &header_cdf, sizeof( header_cdf )); if( c != sizeof( header_cdf ) || header_cdf.signature != ZIP_HEADER_CDF ) { @@ -318,10 +304,10 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error ) return NULL; } - if( header_cdf.uncompressed_size && header_cdf.filename_len && ( header_cdf.filename_len < MAX_SYSPATH ) ) + if( header_cdf.uncompressed_size && header_cdf.filename_len && header_cdf.filename_len < sizeof( filename_buffer )) { - memset( &filename_buffer, '\0', MAX_SYSPATH ); - c = read( zip->handle, &filename_buffer, header_cdf.filename_len ); + memset( &filename_buffer, '\0', sizeof( filename_buffer )); + c = FS_Read( zip->handle, &filename_buffer, header_cdf.filename_len ); if( c != header_cdf.filename_len ) { @@ -335,21 +321,32 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error ) return NULL; } - Q_strncpy( info[numpackfiles].name, filename_buffer, MAX_SYSPATH ); - + Q_strncpy( info[numpackfiles].name, filename_buffer, sizeof( info[numpackfiles].name )); info[numpackfiles].size = header_cdf.uncompressed_size; info[numpackfiles].compressed_size = header_cdf.compressed_size; info[numpackfiles].offset = header_cdf.local_header_offset; numpackfiles++; } else - lseek( zip->handle, header_cdf.filename_len, SEEK_CUR ); + FS_Seek( zip->handle, header_cdf.filename_len, SEEK_CUR ); if( header_cdf.extrafield_len ) - lseek( zip->handle, header_cdf.extrafield_len, SEEK_CUR ); + FS_Seek( zip->handle, header_cdf.extrafield_len, SEEK_CUR ); if( header_cdf.file_commentary_len ) - lseek( zip->handle, header_cdf.file_commentary_len, SEEK_CUR ); + FS_Seek( zip->handle, header_cdf.file_commentary_len, SEEK_CUR ); + } + + // refuse to load empty files again + if( numpackfiles == 0 ) + { + Con_Reportf( S_WARN "%s has no files (recalculated). Ignored.\n", zipfile ); + + if( error ) + *error = ZIP_LOAD_NO_FILES; + + FS_CloseZIP( zip ); + return NULL; } // recalculate offsets @@ -357,8 +354,8 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error ) { zip_header_t header; - lseek( zip->handle, info[i].offset, SEEK_SET ); - c = read( zip->handle, &header, sizeof( header ) ); + FS_Seek( zip->handle, info[i].offset, SEEK_SET ); + c = FS_Read( zip->handle, &header, sizeof( header ) ); if( c != sizeof( header )) { @@ -376,18 +373,9 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error ) info[i].offset = info[i].offset + header.filename_len + header.extrafield_len + sizeof( header ); } - zip->filetime = FS_SysFileTime( zipfile ); zip->numfiles = numpackfiles; - zip->files = info; - qsort( zip->files, zip->numfiles, sizeof( *zip->files ), FS_SortZip ); -#ifdef XASH_REDUCE_FD - // will reopen when needed - close(zip->handle); - zip->handle = -1; -#endif - if( error ) *error = ZIP_LOAD_OK; @@ -403,8 +391,7 @@ Open a packed file using its package file descriptor */ static file_t *FS_OpenFile_ZIP( searchpath_t *search, const char *filename, const char *mode, int pack_ind ) { - zipfile_t *pfile; - pfile = &search->zip->files[pack_ind]; + zipfile_t *pfile = &search->zip->files[pack_ind]; // compressed files handled in Zip_LoadFile if( pfile->flags != ZIP_COMPRESSION_NO_COMPRESSION ) @@ -413,7 +400,7 @@ static file_t *FS_OpenFile_ZIP( searchpath_t *search, const char *filename, cons return NULL; } - return FS_OpenHandle( search->filename, search->zip->handle, pfile->offset, pfile->size ); + return FS_OpenHandle( search, search->zip->handle->handle, pfile->offset, pfile->size ); } /* @@ -437,12 +424,10 @@ static byte *FS_LoadZIPFile( searchpath_t *search, const char *path, int pack_in file = &search->zip->files[pack_ind]; - FS_EnsureOpenZip( search->zip ); - - if( lseek( search->zip->handle, file->offset, SEEK_SET ) == -1 ) + if( FS_Seek( search->zip->handle, file->offset, SEEK_SET ) == -1 ) return NULL; - /*if( read( search->zip->handle, &header, sizeof( header ) ) < 0 ) + /*if( FS_Read( search->zip->handle, &header, sizeof( header )) < 0 ) return NULL; if( header.signature != ZIP_HEADER_LF ) @@ -451,7 +436,7 @@ static byte *FS_LoadZIPFile( searchpath_t *search, const char *path, int pack_in return NULL; }*/ - decompressed_buffer = pfnAlloc( file->size + 1 ); + decompressed_buffer = (byte *)pfnAlloc( file->size + 1 ); if( unlikely( !decompressed_buffer )) { Con_Reportf( S_ERROR "%s: can't alloc %li bytes, no free memory\n", __func__, (long)file->size + 1 ); @@ -461,7 +446,7 @@ static byte *FS_LoadZIPFile( searchpath_t *search, const char *path, int pack_in if( file->flags == ZIP_COMPRESSION_NO_COMPRESSION ) { - c = read( search->zip->handle, decompressed_buffer, file->size ); + c = FS_Read( search->zip->handle, decompressed_buffer, file->size ); if( c != file->size ) { Con_Reportf( S_ERROR "%s: %s size doesn't match\n", __func__, file->name ); @@ -484,14 +469,13 @@ static byte *FS_LoadZIPFile( searchpath_t *search, const char *path, int pack_in if( sizeptr ) *sizeptr = file->size; - FS_EnsureOpenZip( NULL ); return decompressed_buffer; } else if( file->flags == ZIP_COMPRESSION_DEFLATED ) { - compressed_buffer = Mem_Malloc( fs_mempool, file->compressed_size + 1 ); + compressed_buffer = (byte *)Mem_Malloc( fs_mempool, file->compressed_size + 1 ); - c = read( search->zip->handle, compressed_buffer, file->compressed_size ); + c = FS_Read( search->zip->handle, compressed_buffer, file->compressed_size ); if( c != file->compressed_size ) { Con_Reportf( S_ERROR "%s: %s compressed size doesn't match\n", __func__, file->name ); @@ -538,7 +522,6 @@ static byte *FS_LoadZIPFile( searchpath_t *search, const char *path, int pack_in #endif if( sizeptr ) *sizeptr = file->size; - FS_EnsureOpenZip( NULL ); return decompressed_buffer; } else @@ -557,7 +540,6 @@ static byte *FS_LoadZIPFile( searchpath_t *search, const char *path, int pack_in return NULL; } - FS_EnsureOpenZip( NULL ); return NULL; } @@ -569,7 +551,7 @@ FS_FileTime_ZIP */ static int FS_FileTime_ZIP( searchpath_t *search, const char *filename ) { - return search->zip->filetime; + return search->zip->handle->filetime; } /* @@ -580,7 +562,9 @@ FS_PrintInfo_ZIP */ static void FS_PrintInfo_ZIP( searchpath_t *search, char *dst, size_t size ) { - Q_snprintf( dst, size, "%s (%i files)", search->filename, search->zip->numfiles ); + if( search->zip->handle->searchpath ) + Q_snprintf( dst, size, "%s (%i files)" S_CYAN " from %s" S_DEFAULT, search->filename, search->zip->numfiles, search->zip->handle->searchpath->filename ); + else Q_snprintf( dst, size, "%s (%i files)", search->filename, search->zip->numfiles ); } /*