diff options
-rw-r--r-- | build/common.mk | 1 | ||||
-rw-r--r-- | source/files.c | 1065 | ||||
-rw-r--r-- | source/ioapi.c | 178 | ||||
-rw-r--r-- | source/ioapi.h | 64 | ||||
-rw-r--r-- | source/unzip.c | 1436 | ||||
-rw-r--r-- | source/unzip.h | 306 |
6 files changed, 712 insertions, 2338 deletions
diff --git a/build/common.mk b/build/common.mk index 6940ba2..f73df83 100644 --- a/build/common.mk +++ b/build/common.mk @@ -33,7 +33,6 @@ SRCFILES+=cmd.c \ io_sleep.c ifdef USE_ZLIB -SRCFILES+=ioapi.c unzip.c LDFLAGS+=$(ZLIB_LDFLAGS) CFLAGS+=$(ZLIB_CFLAGS) endif diff --git a/source/files.c b/source/files.c index e2e34f9..4623d39 100644 --- a/source/files.c +++ b/source/files.c @@ -25,7 +25,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "d_pak.h" #if USE_ZLIB #include <zlib.h> -#include "unzip.h" #endif /* @@ -42,7 +41,6 @@ QUAKE FILESYSTEM ============================================================================= */ -#define MAX_FILES_IN_PK2 0x4000 #define MAX_FILE_HANDLES 8 // macros for dealing portably with files at OS level @@ -54,8 +52,22 @@ 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 + +#if USE_ZLIB +#define ZIP_MAXFILES 0x4000 // 16k files, rather arbitrary +#define ZIP_BUFSIZE 0x10000 // inflate in blocks of 64k + +#define ZIP_BUFREADCOMMENT 1024 +#define ZIP_SIZELOCALHEADER 30 +#define ZIP_SIZECENTRALHEADER 20 +#define ZIP_SIZECENTRALDIRITEM 46 + +#define ZIP_LOCALHEADERMAGIC 0x04034b50 +#define ZIP_CENTRALHEADERMAGIC 0x02014b50 +#define ZIP_ENDHEADERMAGIC 0x06054b50 +#endif #ifdef _DEBUG #define FS_DPrintf(...) \ @@ -69,76 +81,89 @@ QUAKE FILESYSTEM // in memory // +typedef enum { + FS_FREE, + FS_REAL, + FS_PAK, +#if USE_ZLIB + FS_ZIP, + FS_GZ, +#endif + FS_BAD +} filetype_t; + +#if USE_ZLIB +typedef struct { + z_stream stream; + size_t rest_in; + size_t rest_out; + byte buffer[ZIP_BUFSIZE]; +} zipstream_t; +#endif + typedef struct packfile_s { - char *name; - size_t filepos; - size_t filelen; + char *name; + size_t filepos; + size_t filelen; +#if USE_ZLIB + size_t complen; + unsigned compmtd; // compression method, 0 (stored) or Z_DEFLATED + qboolean coherent; // true if local file header has been checked +#endif - struct packfile_s *hashNext; + struct packfile_s *hash_next; } packfile_t; typedef struct { -#if USE_ZLIB - unzFile zFile; -#endif - FILE *fp; - int numfiles; + filetype_t type; // FS_PAK or FS_ZIP + unsigned refcount; // for tracking pack users + FILE *fp; + unsigned numfiles; packfile_t *files; - packfile_t **fileHash; - int hashSize; - char filename[1]; + packfile_t **file_hash; + unsigned hash_size; + char *names; + char filename[1]; } pack_t; typedef struct searchpath_s { struct searchpath_s *next; - int mode; - pack_t *pack; // only one of filename / pack will be used - char filename[1]; + unsigned mode; + pack_t *pack; // only one of filename / pack will be used + char filename[1]; } searchpath_t; typedef struct { - enum { - FS_FREE, - FS_REAL, - FS_PAK, -#if USE_ZLIB - FS_PK2, - FS_GZIP, -#endif - FS_BAD - } type; - unsigned mode; - FILE *fp; + filetype_t type; + unsigned mode; + FILE *fp; #if USE_ZLIB - void *zfp; + void *zfp; // gzFile for FS_GZ or zipstream_t for FS_ZIP #endif - packfile_t *pak; - qboolean unique; - size_t length; + packfile_t *entry; // pack entry this handle is tied to + pack_t *pack; // points to the pack entry is from + qboolean unique; + size_t length; } file_t; typedef struct symlink_s { struct symlink_s *next; - size_t targlen; - size_t namelen; - char *target; - char name[1]; + size_t targlen; + size_t namelen; + char *target; + char name[1]; } symlink_t; // these point to user home directory -char fs_gamedir[MAX_OSPATH]; -//static char fs_basedir[MAX_OSPATH]; +char fs_gamedir[MAX_OSPATH]; +//static char fs_basedir[MAX_OSPATH]; -#ifdef _DEBUG -static cvar_t *fs_debug; -#endif - -static searchpath_t *fs_searchpaths; -static searchpath_t *fs_base_searchpaths; +static searchpath_t *fs_searchpaths; +static searchpath_t *fs_base_searchpaths; -static symlink_t *fs_links; +static symlink_t *fs_links; -static file_t fs_files[MAX_FILE_HANDLES]; +static file_t fs_files[MAX_FILE_HANDLES]; static qboolean fs_fileFromPak; @@ -146,7 +171,26 @@ static qboolean fs_fileFromPak; static int fs_count_read, fs_count_strcmp, fs_count_open; #endif -cvar_t *fs_game; +#ifdef _DEBUG +static cvar_t *fs_debug; +#endif + +cvar_t *fs_game; + +#if USE_ZLIB +// local stream used for all file loads +static zipstream_t fs_zipstream; + +static void open_zip_file( file_t *file ); +static void close_zip_file( file_t *file ); +static size_t tell_zip_file( file_t *file ); +static size_t read_zip_file( file_t *file, void *buf, size_t len ); +#endif + +// for tracking users of pack_t instance +// allows FS to be restarted while reading something from pack +static pack_t *pack_get( pack_t *pack ); +static void pack_put( pack_t *pack ); /* @@ -227,16 +271,12 @@ static file_t *FS_AllocHandle( fileHandle_t *f ) { for( i = 0, file = fs_files; i < MAX_FILE_HANDLES; i++, file++ ) { if( file->type == FS_FREE ) { - break; + *f = i + 1; + return file; } } - if( i == MAX_FILE_HANDLES ) { - Com_Error( ERR_FATAL, "%s: none free", __func__ ); - } - - *f = i + 1; - return file; + return NULL; } /* @@ -248,12 +288,12 @@ static file_t *FS_FileForHandle( fileHandle_t f ) { file_t *file; if( f <= 0 || f >= MAX_FILE_HANDLES + 1 ) { - Com_Error( ERR_FATAL, "%s: invalid handle: %i", __func__, f ); + Com_Error( ERR_FATAL, "%s: bad handle", __func__ ); } file = &fs_files[f - 1]; if( file->type <= FS_FREE || file->type >= FS_BAD ) { - Com_Error( ERR_FATAL, "%s: invalid file type: %i", __func__, file->type ); + Com_Error( ERR_FATAL, "%s: bad file type", __func__ ); } return file; @@ -348,11 +388,11 @@ size_t FS_GetFileLength( fileHandle_t f ) { return info.size; case FS_PAK: #if USE_ZLIB - case FS_PK2: + case FS_ZIP: #endif return file->length; #if USE_ZLIB - case FS_GZIP: + case FS_GZ: return INVALID_LENGTH; #endif default: @@ -369,27 +409,35 @@ FS_Tell */ size_t FS_Tell( fileHandle_t f ) { file_t *file = FS_FileForHandle( f ); - int length; + size_t pos = INVALID_LENGTH; + long ret; switch( file->type ) { case FS_REAL: - length = ftell( file->fp ); + ret = ftell( file->fp ); + if( ret != -1 ) { + pos = (size_t)ret; + } break; case FS_PAK: - length = ftell( file->fp ) - file->pak->filepos; + ret = ftell( file->fp ); + if( ret != -1 && ret >= file->entry->filepos ) { + pos = (size_t)ret; + } break; #if USE_ZLIB - case FS_PK2: - length = unztell( file->zfp ); + case FS_ZIP: + pos = tell_zip_file( file ); + break; + case FS_GZ: + pos = INVALID_LENGTH; break; - case FS_GZIP: - return INVALID_LENGTH; #endif default: Com_Error( ERR_FATAL, "%s: bad file type", __func__ ); } - return length; + return pos; } /* @@ -408,17 +456,16 @@ qboolean FS_Seek( fileHandle_t f, size_t offset ) { } break; #if USE_ZLIB - case FS_GZIP: + case FS_ZIP: + return qfalse; + case FS_GZ: if( gzseek( file->zfp, offset, SEEK_CUR ) == -1 ) { return qfalse; } break; - //case FS_PK2: - // length = unztell( file->zfp ); - // break; #endif default: - return qfalse; + Com_Error( ERR_FATAL, "%s: bad file type", __func__ ); } return qtrue; @@ -458,7 +505,7 @@ qboolean FS_FilterFile( fileHandle_t f ) { void *zfp; switch( file->type ) { - case FS_GZIP: + case FS_GZ: return qtrue; case FS_REAL: break; @@ -485,7 +532,7 @@ qboolean FS_FilterFile( fileHandle_t f ) { } file->zfp = zfp; - file->type = FS_GZIP; + file->type = FS_GZ; return qtrue; #else return qfalse; @@ -510,16 +557,17 @@ void FS_FCloseFile( fileHandle_t f ) { case FS_PAK: if( file->unique ) { fclose( file->fp ); + pack_put( file->pack ); } break; #if USE_ZLIB - case FS_GZIP: + case FS_GZ: gzclose( file->zfp ); break; - case FS_PK2: - unzCloseCurrentFile( file->zfp ); + case FS_ZIP: if( file->unique ) { - unzClose( file->zfp ); + close_zip_file( file ); + pack_put( file->pack ); } break; #endif @@ -618,66 +666,245 @@ static size_t FS_FOpenFileWrite( file_t *file, const char *name ) { return ( size_t )ftell( fp ); } -static size_t FS_FOpenFromPak( file_t *file, pack_t *pak, packfile_t *entry, qboolean unique ) { - fs_fileFromPak = qtrue; - - // 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 ); - } + +static size_t check_header_coherency( FILE *fp, packfile_t *entry ) { + unsigned flags, comp_mtd; + size_t comp_len, file_len; + size_t name_size, xtra_size; + byte header[ZIP_SIZELOCALHEADER]; + + if( fseek( fp, entry->filepos, SEEK_SET ) == -1 ) + return 0; + if( fread( header, 1, sizeof( header ), fp ) != sizeof( header ) ) + return 0; + + // check the magic + if( LittleLongMem( &header[0] ) != ZIP_LOCALHEADERMAGIC ) + return 0; + + flags = LittleShortMem( &header[6] ); + comp_mtd = LittleShortMem( &header[8] ); + comp_len = LittleLongMem( &header[18] ); + file_len = LittleLongMem( &header[22] ); + name_size = LittleShortMem( &header[26] ); + xtra_size = LittleShortMem( &header[28] ); + + if( comp_mtd != entry->compmtd ) + return 0; + + // bit 3 tells that file lengths were not known + // at the time local header was written, so don't check them + if( ( flags & 8 ) == 0 ) { + if( comp_len != entry->complen ) + return 0; + if( file_len != entry->filelen ) + return 0; + } + + return ZIP_SIZELOCALHEADER + name_size + xtra_size; +} + +static voidpf FS_zalloc OF(( voidpf opaque, uInt items, uInt size )) { + return FS_Malloc( items * size ); +} + +static void FS_zfree OF(( voidpf opaque, voidpf address )) { + Z_Free( address ); +} + +static void open_zip_file( file_t *file ) { + packfile_t *entry = file->entry; + zipstream_t *s; + + if( file->unique ) { + s = FS_Malloc( sizeof( *s ) ); + memset( &s->stream, 0, sizeof( s->stream ) ); + } else { + s = &fs_zipstream; + } + + if( entry->compmtd ) { + z_streamp z = &s->stream; + + if( z->state ) { + // already initialized, just reset + inflateReset( z ); } else { - zfp = pak->zFile; + z->zalloc = FS_zalloc; + z->zfree = FS_zfree; + if( inflateInit2( z, -MAX_WBITS ) != Z_OK ) { + Com_Error( ERR_FATAL, "%s: inflateInit2() failed", __func__ ); + } } - if( unzSetCurrentFileInfoPosition( zfp, entry->filepos ) == -1 ) { - Com_Error( ERR_FATAL, "%s: couldn't seek into %s", - __func__, pak->filename ); + + z->avail_in = z->avail_out = 0; + z->total_in = z->total_out = 0; + z->next_in = z->next_out = NULL; + } + + s->rest_in = entry->complen; + s->rest_out = entry->filelen; + + file->zfp = s; +} + +// only called for unique handles +static void close_zip_file( file_t *file ) { + zipstream_t *s = file->zfp; + + inflateEnd( &s->stream ); + Z_Free( s ); + + fclose( file->fp ); +} + +static size_t tell_zip_file( file_t *file ) { + zipstream_t *s = file->zfp; + + if( !file->entry->compmtd ) { + return file->entry->filelen - s->rest_in; + } + return s->stream.total_out; +} + +static size_t read_zip_file( file_t *file, void *buf, size_t len ) { + zipstream_t *s = file->zfp; + z_streamp z = &s->stream; + size_t block, result; + int ret; + + if( len > s->rest_out ) { + len = s->rest_out; + } + + if( !file->entry->compmtd ) { + if( len > s->rest_in ) { + len = s->rest_in; } - if( unzOpenCurrentFile( zfp ) != UNZ_OK ) { - Com_Error( ERR_FATAL, "%s: couldn't open curfile from %s", - __func__, pak->filename ); + + result = fread( buf, 1, len, file->fp ); + if( result != len ) { + Com_EPrintf( "%s: fread() failed\n", __func__ ); } - file->zfp = zfp; - file->type = FS_PK2; - } else -#endif - { - FILE *fp; + s->rest_in -= result; + s->rest_out -= result; + return len; + } - if( unique ) { - fp = fopen( pak->filename, "rb" ); - if( !fp ) { - Com_Error( ERR_FATAL, "%s: couldn't reopen %s", - __func__, pak->filename ); + z->next_out = buf; + z->avail_out = (uInt)len; + + while( z->avail_out ) { + if( !z->avail_in ) { + if( !s->rest_in ) { + break; } - } else { - fp = pak->fp; + + // fill in the temp buffer + block = ZIP_BUFSIZE; + if( block > s->rest_in ) { + block = s->rest_in; + } + + result = fread( s->buffer, 1, block, file->fp ); + if( result != block ) { + Com_EPrintf( "%s: fread() failed\n", __func__ ); + } + if( !result ) { + break; + } + + s->rest_in -= result; + z->next_in = s->buffer; + z->avail_in = result; } - if( fseek( fp, entry->filepos, SEEK_SET ) == -1 ) { - Com_Error( ERR_FATAL, "%s: couldn't seek into %s", - __func__, pak->filename ); + ret = inflate( z, Z_SYNC_FLUSH ); + if( ret == Z_STREAM_END ) { + break; } + if( ret != Z_OK ) { + Com_EPrintf( "%s: inflate() failed: %s\n", __func__, z->msg ); + break; + } + } + + len -= z->avail_out; + s->rest_out -= len; + + return len; +} + +#endif - file->fp = fp; - file->type = FS_PAK; +// open a new file on the pakfile +static size_t FS_FOpenFromPak( file_t *file, pack_t *pack, packfile_t *entry, qboolean unique ) { + FILE *fp; + + if( unique ) { + fp = fopen( pack->filename, "rb" ); + if( !fp ) { + Com_EPrintf( "%s: couldn't reopen %s\n", + __func__, pack->filename ); + return INVALID_LENGTH; + } + } else { + fp = pack->fp; } - file->pak = entry; +#if USE_ZLIB + if( pack->type == FS_ZIP && !entry->coherent ) { + size_t ofs = check_header_coherency( fp, entry ); + + if( !ofs ) { + Com_EPrintf( "%s: coherency check failed on %s\n", + __func__, pack->filename ); + goto fail; + } + + entry->filepos += ofs; + entry->coherent = qtrue; + } +#endif + + if( fseek( fp, entry->filepos, SEEK_SET ) == -1 ) { + Com_EPrintf( "%s: couldn't seek into %s\n", + __func__, pack->filename ); + goto fail; + } + + file->fp = fp; + file->type = pack->type; + file->entry = entry; + file->pack = pack; file->length = entry->filelen; file->unique = unique; +#if USE_ZLIB + if( pack->type == FS_ZIP ) { + open_zip_file( file ); + } +#endif + + if( unique ) { + // reference source pak + pack_get( pack ); + } + FS_DPrintf( "%s: %s/%s: succeeded\n", - __func__, pak->filename, entry->name ); + __func__, pack->filename, entry->name ); + + fs_fileFromPak = qtrue; return file->length; + +fail: + if( unique ) { + fclose( fp ); + } + return INVALID_LENGTH; } /* @@ -698,7 +925,7 @@ static size_t FS_FOpenFileRead( file_t *file, const char *name, qboolean unique unsigned hash; packfile_t *entry; FILE *fp; - file_info_t info; + file_info_t info; int valid = -1; size_t len; @@ -726,14 +953,19 @@ static size_t FS_FOpenFileRead( file_t *file, const char *name, qboolean unique } // look through all the pak file elements pak = search->pack; - entry = pak->fileHash[ hash & ( pak->hashSize - 1 ) ]; - for( ; entry; entry = entry->hashNext ) { + entry = pak->file_hash[ hash & ( pak->hash_size - 1 ) ]; + for( ; entry; entry = entry->hash_next ) { #ifdef _DEBUG fs_count_strcmp++; #endif if( !FS_pathcmp( entry->name, name ) ) { // found it! - return FS_FOpenFromPak( file, pak, entry, unique ); + len = FS_FOpenFromPak( file, pak, entry, unique ); + if( len == INVALID_LENGTH ) { + // failed to open pak, continue to search + break; + } + return len; } } } else { @@ -807,10 +1039,10 @@ FS_ReadFile 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; - file_t *file = FS_FileForHandle( hFile ); +size_t FS_Read( void *buffer, size_t len, fileHandle_t f ) { + size_t block, remaining = len, read = 0; + byte *buf = (byte *)buffer; + file_t *file = FS_FileForHandle( f ); // read in chunks for progress bar while( remaining ) { @@ -823,11 +1055,11 @@ size_t FS_Read( void *buffer, size_t len, fileHandle_t hFile ) { read = fread( buf, 1, block, file->fp ); break; #if USE_ZLIB - case FS_GZIP: + case FS_GZ: read = gzread( file->zfp, buf, block ); break; - case FS_PK2: - read = unzReadCurrentFile( file->zfp, buf, block ); + case FS_ZIP: + read = read_zip_file( file, buf, block ); break; #endif default: @@ -875,7 +1107,7 @@ void FS_Flush( fileHandle_t f ) { fflush( file->fp ); break; #if USE_ZLIB - case FS_GZIP: + case FS_GZ: gzflush( file->zfp, Z_SYNC_FLUSH ); break; #endif @@ -891,10 +1123,10 @@ FS_Write 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; - file_t *file = FS_FileForHandle( hFile ); +size_t FS_Write( const void *buffer, size_t len, fileHandle_t f ) { + size_t block, remaining = len, write = 0; + byte *buf = (byte *)buffer; + file_t *file = FS_FileForHandle( f ); // read in chunks for progress bar while( remaining ) { @@ -906,12 +1138,12 @@ size_t FS_Write( const void *buffer, size_t len, fileHandle_t hFile ) { write = fwrite( buf, 1, block, file->fp ); break; #if USE_ZLIB - case FS_GZIP: + case FS_GZ: write = gzwrite( file->zfp, buf, block ); break; #endif default: - Com_Error( ERR_FATAL, "FS_Write: illegal file type" ); + Com_Error( ERR_FATAL, "%s: bad file type", __func__ ); break; } if( write == 0 ) { @@ -931,7 +1163,7 @@ size_t FS_Write( const void *buffer, size_t len, fileHandle_t hFile ) { fflush( file->fp ); break; #if USE_ZLIB - case FS_GZIP: + case FS_GZ: gzflush( file->zfp, Z_SYNC_FLUSH ); break; #endif @@ -975,9 +1207,9 @@ FS_FOpenFile ============ */ size_t FS_FOpenFile( const char *name, fileHandle_t *f, int mode ) { - file_t *file; - fileHandle_t hFile; - size_t ret = INVALID_LENGTH; + file_t *file; + fileHandle_t handle; + size_t ret = INVALID_LENGTH; if( !name || !f ) { Com_Error( ERR_FATAL, "%s: NULL", __func__ ); @@ -998,7 +1230,11 @@ size_t FS_FOpenFile( const char *name, fileHandle_t *f, int mode ) { } // allocate new file handle - file = FS_AllocHandle( &hFile ); + file = FS_AllocHandle( &handle ); + if( !file ) { + Com_EPrintf( "%s: no free file handles\n", __func__ ); + return ret; + } file->mode = mode; mode &= FS_MODE_MASK; @@ -1018,7 +1254,7 @@ size_t FS_FOpenFile( const char *name, fileHandle_t *f, int mode ) { // if succeeded, store file handle if( ret != -1 ) { - *f = hFile; + *f = handle; } return ret; @@ -1053,8 +1289,8 @@ 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 ) { file_t *file; fileHandle_t f; - byte *buf; - size_t len; + byte *buf; + size_t len; if( !path ) { Com_Error( ERR_FATAL, "%s: NULL", __func__ ); @@ -1076,6 +1312,10 @@ size_t FS_LoadFileEx( const char *path, void **buffer, int flags, memtag_t tag ) // allocate new file handle file = FS_AllocHandle( &f ); + if( !file ) { + Com_EPrintf( "%s: no free file handles\n", __func__ ); + return INVALID_LENGTH; + } flags &= ~FS_MODE_MASK; file->mode = flags | FS_MODE_READ; @@ -1087,7 +1327,7 @@ size_t FS_LoadFileEx( const char *path, void **buffer, int flags, memtag_t tag ) if( buffer ) { #if USE_ZLIB - if( file->type == FS_GZIP ) { + if( file->type == FS_GZ ) { len = INVALID_LENGTH; // unknown length } else #endif @@ -1237,6 +1477,60 @@ void FS_FPrintf( fileHandle_t f, const char *format, ... ) { FS_Write( string, len, f ); } +// references pack_t instance +static pack_t *pack_get( pack_t *pack ) { + pack->refcount++; + return pack; +} + +// dereferences pack_t instance +static void pack_put( pack_t *pack ) { + if( !pack ) { + return; + } + if( !pack->refcount ) { + Com_Error( ERR_FATAL, "%s: refcount already zero", __func__ ); + } + if( !--pack->refcount ) { + FS_DPrintf( "Freeing packfile %s\n", pack->filename ); + fclose( pack->fp ); + Z_Free( pack ); + } +} + +// allocates pack_t instance along with filenames and hashes in one chunk of memory +static pack_t *pack_alloc( FILE *fp, filetype_t type, const char *name, + unsigned num_files, size_t names_len ) +{ + pack_t *pack; + unsigned hash_size; + size_t len; + + hash_size = Q_CeilPowerOfTwo( num_files ); + if( hash_size > 32 ) { + hash_size >>= 1; + } + + len = strlen( name ); + len = ( len + 3 ) & ~3; + pack = FS_Malloc( sizeof( pack_t ) + + num_files * sizeof( packfile_t ) + + hash_size * sizeof( packfile_t * ) + + names_len + len ); + strcpy( pack->filename, name ); + pack->type = type; + pack->refcount = 0; + pack->fp = fp; + pack->numfiles = num_files; + pack->hash_size = hash_size; + pack->files = ( packfile_t * )( ( byte * )pack + sizeof( pack_t ) + len ); + pack->file_hash = ( packfile_t ** )( pack->files + num_files ); + pack->names = ( char * )( pack->file_hash + hash_size ); + memset( pack->file_hash, 0, hash_size * sizeof( packfile_t * ) ); + + return pack; +} + /* ================= FS_LoadPakFile @@ -1252,109 +1546,89 @@ static pack_t *FS_LoadPakFile( const char *packfile ) { int i; packfile_t *file; dpackfile_t *dfile; - int numpackfiles; - char *names; - size_t namesLength; + unsigned num_files; + char *name; + size_t names_len; pack_t *pack; - FILE *packhandle; + FILE *fp; 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 ); + fp = fopen( packfile, "rb" ); + if( !fp ) { + Com_Printf( "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 ); + if( fread( &header, 1, sizeof( header ), fp ) != sizeof( header ) ) { + Com_Printf( "Reading header failed on %s\n", packfile ); goto fail; } if( LittleLong( header.ident ) != IDPAKHEADER ) { - Com_WPrintf( "%s is not a 'PACK' file\n", packfile ); + Com_Printf( "%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 ); + Com_Printf( "%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 ); + num_files = header.dirlen / sizeof( dpackfile_t ); + if( num_files < 1 ) { + Com_Printf( "%s has no files\n", packfile ); goto fail; } - if( numpackfiles > MAX_FILES_IN_PACK ) { - Com_WPrintf( "%s has too many files: %i > %i\n", packfile, numpackfiles, MAX_FILES_IN_PACK ); + if( num_files > MAX_FILES_IN_PACK ) { + Com_Printf( "%s has too many files: %u > %u\n", packfile, num_files, 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 ); + if( fseek( fp, header.dirofs, SEEK_SET ) ) { + Com_Printf( "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 ); + if( fread( info, 1, header.dirlen, fp ) != header.dirlen ) { + Com_Printf( "Reading directory failed on %s\n", packfile ); goto fail; } - namesLength = 0; - for( i = 0, dfile = info; i < numpackfiles; i++, dfile++ ) { + names_len = 0; + for( i = 0, dfile = info; i < num_files; i++, dfile++ ) { dfile->name[sizeof( dfile->name ) - 1] = 0; - namesLength += strlen( dfile->name ) + 1; + names_len += 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; -#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 * ) ); +// allocate the pack + pack = pack_alloc( fp, FS_PAK, packfile, num_files, names_len ); // parse the directory + name = pack->names; 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( name, dfile->name, len ); + name += len; 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, pack->hash_size ); + file->hash_next = pack->file_hash[hash]; + pack->file_hash[hash] = file; } - FS_DPrintf( "%s: %d files, %d hash table entries\n", - packfile, numpackfiles, hashSize ); + FS_DPrintf( "%s: %u files, %u hash\n", + packfile, num_files, pack->hash_size ); return pack; fail: - fclose( packhandle ); + fclose( fp ); return NULL; } @@ -1364,114 +1638,253 @@ fail: FS_LoadZipFile ================= */ + +// Locate the central directory of a zipfile (at the end, just before the global comment) +static size_t search_central_header( FILE *fp ) { + size_t file_size, back_read; + size_t max_back = 0xffff; // maximum size of global comment + byte buf[ZIP_BUFREADCOMMENT + 4]; + long ret; + + if( fseek( fp, 0, SEEK_END ) == -1 ) + return 0; + + ret = ftell( fp ); + if( ret == -1 ) + return 0; + file_size = (size_t)ret; + if( max_back > file_size ) + max_back = file_size; + + back_read = 4; + while( back_read < max_back ) { + size_t i, read_size, read_pos; + + if( back_read + ZIP_BUFREADCOMMENT > max_back ) + back_read = max_back; + else + back_read += ZIP_BUFREADCOMMENT; + + read_pos = file_size - back_read; + + read_size = back_read; + if( read_size > ZIP_BUFREADCOMMENT + 4 ) + read_size = ZIP_BUFREADCOMMENT + 4; + + if( fseek( fp, read_pos, SEEK_SET ) == -1 ) + break; + if( fread( buf, 1, read_size, fp ) != read_size ) + break; + + i = read_size - 4; + do { + // check the magic + if( LittleLongMem( buf + i ) == ZIP_ENDHEADERMAGIC ) + return read_pos + i; + } while( i-- ); + } + + return 0; +} + +// Get Info about the current file in the zipfile, with internal only info +static size_t get_file_info( FILE *fp, size_t pos, packfile_t *file, size_t *len ) { + size_t name_size, xtra_size, comm_size; + size_t comp_len, file_len, file_pos; + unsigned comp_mtd; + byte header[ZIP_SIZECENTRALDIRITEM]; // we can't use a struct here because of packing + + *len = 0; + + if( fseek( fp, pos, SEEK_SET ) == -1 ) + return 0; + if( fread( header, 1, sizeof( header ), fp ) != sizeof( header ) ) + return 0; + + // check the magic + if( LittleLongMem( &header[0] ) != ZIP_CENTRALHEADERMAGIC ) + return 0; + + comp_mtd = LittleShortMem( &header[10] ); + //if( crc ) + // *crc = LittleLongMem( &header[16] ); + comp_len = LittleLongMem( &header[20] ); + file_len = LittleLongMem( &header[24] ); + name_size = LittleShortMem( &header[28] ); + xtra_size = LittleShortMem( &header[30] ); + comm_size = LittleShortMem( &header[32] ); + file_pos = LittleLongMem( &header[42] ); + + if( !file_len || !comp_len ) { + goto skip; // skip directories and empty files + } + if( !comp_mtd ) { + if( file_len != comp_len ) { + FS_DPrintf( "%s: skipping file stored with file_len != comp_len\n", __func__ ); + goto skip; + } + } else if( comp_mtd != Z_DEFLATED ) { + FS_DPrintf( "%s: skipping file compressed with unknown method\n", __func__ ); + goto skip; + } + if( !name_size ) { + FS_DPrintf( "%s: skipping file with empty name\n", __func__ ); + goto skip; + } + if( name_size >= MAX_QPATH ) { + FS_DPrintf( "%s: skipping file with oversize name\n", __func__ ); + goto skip; + } + + // fill in the info + if( file ) { + file->compmtd = comp_mtd; + file->complen = comp_len; + file->filelen = file_len; + file->filepos = file_pos; + if( fread( file->name, 1, name_size, fp ) != name_size ) + return 0; + file->name[name_size] = 0; + } + + *len = name_size + 1; + +skip: + return ZIP_SIZECENTRALDIRITEM + name_size + xtra_size + comm_size; +} + static pack_t *FS_LoadZipFile( const char *packfile ) { int i; packfile_t *file; - char *names; - int numFiles; + char *name; + size_t names_len; + unsigned num_disk, num_disk_cd, num_files, num_files_cd; + size_t header_pos, central_ofs, central_size, central_end; + size_t extra_bytes, ofs; pack_t *pack; - unzFile zFile; - unz_global_info zGlobalInfo; - unz_file_info zInfo; - char name[MAX_QPATH]; - size_t namesLength; - int hashSize; + FILE *fp; + byte header[ZIP_SIZECENTRALHEADER]; unsigned hash; size_t len; - zFile = unzOpen( packfile ); - if( !zFile ) { - Com_WPrintf( "unzOpen() failed on %s\n", packfile ); + fp = fopen( packfile, "rb" ); + if( !fp ) { + Com_Printf( "Couldn't open %s\n", packfile ); return NULL; } - if( unzGetGlobalInfo( zFile, &zGlobalInfo ) != UNZ_OK ) { - Com_WPrintf( "unzGetGlobalInfo() failed on %s\n", packfile ); - goto fail; + header_pos = search_central_header( fp ); + if( !header_pos ) { + Com_Printf( "No central header found in %s\n", packfile ); + goto fail2; + } + if( fseek( fp, header_pos, SEEK_SET ) == -1 ) { + Com_Printf( "Couldn't seek to central header in %s\n", packfile ); + goto fail2; + } + if( fread( header, 1, sizeof( header ), fp ) != sizeof( header ) ) { + Com_Printf( "Reading central header failed on %s\n", packfile ); + goto fail2; } - 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; + num_disk = LittleShortMem( &header[4] ); + num_disk_cd = LittleShortMem( &header[6] ); + num_files = LittleShortMem( &header[8] ); + num_files_cd = LittleShortMem( &header[10] ); + if( num_files_cd != num_files || num_disk_cd != 0 || num_disk != 0 ) { + Com_Printf( "%s is an unsupported multi-part archive\n", packfile ); + goto fail2; + } + if( num_files < 1 ) { + Com_Printf( "%s has no files\n", packfile ); + goto fail2; + } + if( num_files > ZIP_MAXFILES ) { + Com_Printf( "%s has too many files: %u > %u\n", packfile, num_files, ZIP_MAXFILES ); + goto fail2; } - if( unzGoToFirstFile( zFile ) != UNZ_OK ) { - Com_WPrintf( "unzGoToFirstFile() failed on %s\n", packfile ); - goto fail; + central_size = LittleLongMem( &header[12] ); + central_ofs = LittleLongMem( &header[16] ); + central_end = central_ofs + central_size; + if( central_end > header_pos || central_end < central_ofs ) { + Com_Printf( "%s has bad central directory offset\n", packfile ); + goto fail2; } - 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; - } +// non-zero for sfx? + extra_bytes = header_pos - central_end; + if( extra_bytes ) { + Com_Printf( "%s has %"PRIz" extra bytes at the beginning, funny sfx archive?\n", + packfile, extra_bytes ); + } - // skip directories and empty files - if( zInfo.uncompressed_size ) { - namesLength += strlen( name ) + 1; +// parse the directory + num_files = 0; + names_len = 0; + header_pos = central_ofs + extra_bytes; + for( i = 0; i < num_files_cd; i++ ) { + ofs = get_file_info( fp, header_pos, NULL, &len ); + if( !ofs ) { + Com_Printf( "%s has bad central directory structure\n", packfile ); + goto fail2; } + header_pos += ofs; - if( i != numFiles - 1 && unzGoToNextFile( zFile ) != UNZ_OK ) { - Com_WPrintf( "unzGoToNextFile() failed on %s\n", packfile ); + if( len ) { + names_len += len; + num_files++; } } - hashSize = Q_CeilPowerOfTwo( numFiles ); - if( hashSize > 32 ) { - hashSize >>= 1; + if( !num_files ) { + Com_Printf( "%s has no valid files\n", packfile ); + goto fail2; } - 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 * ) ); +// allocate the pack + pack = pack_alloc( fp, FS_ZIP, packfile, num_files, names_len ); // parse the directory - unzGoToFirstFile( zFile ); - - for( i = 0, file = pack->files; i < numFiles; i++, file++ ) { - unzGetCurrentFileInfo( zFile, &zInfo, name, sizeof( name ), NULL, 0, NULL, 0 ); - - if( zInfo.uncompressed_size ) { - len = strlen( name ) + 1; - file->name = names; - - 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; - - names += len; - } - - if( i != numFiles - 1 ) { - unzGoToNextFile( zFile ); + name = pack->names; + file = pack->files; + num_files = 0; + header_pos = central_ofs + extra_bytes; + for( i = 0; i < num_files_cd; i++ ) { + file->name = name; + ofs = get_file_info( fp, header_pos, file, &len ); + if( !ofs ) { + Com_EPrintf( "Error re-reading central directory in %s\n", packfile ); + goto fail1; + } + header_pos += ofs; + + if( len ) { + // fix absolute position + file->filepos += extra_bytes; + file->coherent = qfalse; + + hash = Com_HashPath( file->name, pack->hash_size ); + file->hash_next = pack->file_hash[hash]; + pack->file_hash[hash] = file; + + file++; + name += len; + if( ++num_files == pack->numfiles ) { + break; + } } } - FS_DPrintf( "%s: %d files, %d hash table entries\n", - packfile, numFiles, hashSize ); + FS_DPrintf( "%s: %u files, %u skipped, %u hash\n", + packfile, num_files, num_files_cd - num_files, pack->hash_size ); return pack; -fail: - unzClose( zFile ); +fail1: + Z_Free( pack ); +fail2: + fclose( fp ); return NULL; } #endif @@ -1508,7 +1921,7 @@ alphacmp: static void FS_LoadPackFiles( int mode, const char *extension, pack_t *(loadfunc)( const char * ) ) { int i; searchpath_t *search; - pack_t *pak; + pack_t *pack; void **list; int numFiles; char path[MAX_OSPATH]; @@ -1520,13 +1933,13 @@ static void FS_LoadPackFiles( int mode, const char *extension, pack_t *(loadfunc 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 ) + pack = (*loadfunc)( path ); + if( !pack ) continue; search = FS_Malloc( sizeof( searchpath_t ) ); search->mode = mode; search->filename[0] = 0; - search->pack = pak; + search->pack = pack_get( pack ); search->next = fs_searchpaths; fs_searchpaths = search; } @@ -2090,8 +2503,8 @@ static void FS_WhereIs_f( void ) { 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 ) { + entry = pak->file_hash[ hash & ( pak->hash_size - 1 ) ]; + for( ; entry; entry = entry->hash_next ) { if( !FS_pathcmp( entry->name, path ) ) { Com_Printf( "%s/%s (%"PRIz" bytes)\n", pak->filename, path, entry->filelen ); @@ -2135,15 +2548,15 @@ void FS_Path_f( void ) { searchpath_t *s; int numFilesInPAK = 0; #if USE_ZLIB - int numFilesInPK2 = 0; + int numFilesInZIP = 0; #endif 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; + if( s->pack->type == FS_ZIP ) + numFilesInZIP += s->pack->numfiles; else #endif numFilesInPAK += s->pack->numfiles; @@ -2158,8 +2571,8 @@ void FS_Path_f( void ) { } #if USE_ZLIB - if( numFilesInPK2 ) { - Com_Printf( "%i files in PKZ files\n", numFilesInPK2 ); + if( numFilesInZIP ) { + Com_Printf( "%i files in PKZ files\n", numFilesInZIP ); } #endif } @@ -2182,23 +2595,23 @@ static void FS_Stats_f( void ) { if( !( pack = path->pack ) ) { continue; } - for( i = 0; i < pack->hashSize; i++ ) { - if( !( file = pack->fileHash[i] ) ) { + for( i = 0; i < pack->hash_size; i++ ) { + if( !( file = pack->file_hash[i] ) ) { continue; } len = 0; - for( ; file ; file = file->hashNext ) { + for( ; file ; file = file->hash_next ) { len++; } if( maxLen < len ) { - max = pack->fileHash[i]; + max = pack->file_hash[i]; maxpack = pack; maxLen = len; } totalLen += len; totalHashSize++; } - //totalHashSize += pack->hashSize; + //totalHashSize += pack->hash_size; } #ifdef _DEBUG @@ -2218,7 +2631,7 @@ static void FS_Stats_f( void ) { 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 ) { + for( file = max; file ; file = file->hash_next ) { Com_Printf( "%s\n", file->name ); } } @@ -2347,18 +2760,7 @@ update: } static void FS_FreeSearchPath( searchpath_t *path ) { - pack_t *pak; - - if( ( pak = path->pack ) != NULL ) { -#if USE_ZLIB - if( pak->zFile ) - unzClose( pak->zFile ); - else -#endif - fclose( pak->fp ); - Z_Free( pak ); - } - + pack_put( path->pack ); Z_Free( path ); } @@ -2416,23 +2818,6 @@ static void setup_gamedir( void ) { Cvar_FullSet( "fs_gamedir", fs_gamedir, CVAR_ROM, FROM_CODE ); } -static qboolean safe_to_restart( void ) { - file_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 ) { - return qfalse; - } - } - - return qtrue; -} - /* ================ FS_Restart @@ -2441,30 +2826,8 @@ Unless total is true, reloads paks only up to base dir ================ */ void FS_Restart( qboolean total ) { - file_t *file; - int i; - fileHandle_t temp; - Com_Printf( "---------- FS_Restart ----------\n" ); - // temporary disable logfile - temp = com_logFile; - com_logFile = 0; - - // make sure no files from paks are opened - for( i = 0, file = fs_files; i < MAX_FILE_HANDLES; i++, file++ ) { - switch( file->type ) { - case FS_FREE: - case FS_REAL: -#if USE_ZLIB - case FS_GZIP: -#endif - break; - default: - Com_Error( ERR_FATAL, "%s: closing handle %d", __func__, i + 1 ); - } - } - if( total ) { // perform full reset free_all_paths(); @@ -2478,9 +2841,6 @@ void FS_Restart( qboolean total ) { FS_Path_f(); - // re-enable logfile - com_logFile = temp; - Com_Printf( "--------------------------------\n" ); } @@ -2492,11 +2852,6 @@ Console command to fully re-start the file system. ============ */ static void FS_Restart_f( void ) { - if( !safe_to_restart() ) { - Com_Printf( "Can't \"%s\", there are some open file handles.\n", Cmd_Argv( 0 ) ); - return; - } - #if USE_CLIENT CL_RestartFilesystem( qtrue ); #else @@ -2544,6 +2899,10 @@ void FS_Shutdown( void ) { // free search paths free_all_paths(); +#if USE_ZLIB + inflateEnd( &fs_zipstream.stream ); +#endif + Z_LeakTest( TAG_FILESYSTEM ); Cmd_Deregister( c_fs ); diff --git a/source/ioapi.c b/source/ioapi.c deleted file mode 100644 index d66025b..0000000 --- a/source/ioapi.c +++ /dev/null @@ -1,178 +0,0 @@ -/* ioapi.c -- IO base function header for compress/uncompress .zip - files using zlib + zip or unzip API - - Version 0.18 beta, Feb 26th, 2002 - - Copyright (C) 1998-2002 Gilles Vollant -*/ -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "zlib.h" -#include "ioapi.h" - - - -/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ - -#ifndef SEEK_CUR -#define SEEK_CUR 1 -#endif - -#ifndef SEEK_END -#define SEEK_END 2 -#endif - -#ifndef SEEK_SET -#define SEEK_SET 0 -#endif - -voidpf ZCALLBACK fopen_file_func OF(( - voidpf opaque, - const char* filename, - int mode)); - -uLong ZCALLBACK fread_file_func OF(( - voidpf opaque, - voidpf stream, - void* buf, - uLong size)); - -uLong ZCALLBACK fwrite_file_func OF(( - voidpf opaque, - voidpf stream, - const void* buf, - uLong size)); - -long ZCALLBACK ftell_file_func OF(( - voidpf opaque, - voidpf stream)); - -long ZCALLBACK fseek_file_func OF(( - voidpf opaque, - voidpf stream, - uLong offset, - int origin)); - -long ZCALLBACK fclose_file_func OF(( - voidpf opaque, - voidpf stream)); - -int ZCALLBACK ferror_file_func OF(( - voidpf opaque, - voidpf stream)); - - -voidpf ZCALLBACK fopen_file_func (opaque, filename, mode) - voidpf opaque; - const char* filename; - int mode; -{ - FILE* file = NULL; - const char* mode_fopen = NULL; - if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) - mode_fopen = "rb"; - else - if (mode & ZLIB_FILEFUNC_MODE_EXISTING) - mode_fopen = "r+b"; - else - if (mode & ZLIB_FILEFUNC_MODE_CREATE) - mode_fopen = "wb"; - - if ((filename!=NULL) && (mode_fopen != NULL)) - file = fopen(filename, mode_fopen); - return file; -} - - -uLong ZCALLBACK fread_file_func (opaque, stream, buf, size) - voidpf opaque; - voidpf stream; - void* buf; - uLong size; -{ - uLong ret; - ret = fread(buf, 1, (size_t)size, (FILE *)stream); - return ret; -} - - -uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size) - voidpf opaque; - voidpf stream; - const void* buf; - uLong size; -{ - uLong ret; - ret = fwrite(buf, 1, (size_t)size, (FILE *)stream); - return ret; -} - -long ZCALLBACK ftell_file_func (opaque, stream) - voidpf opaque; - voidpf stream; -{ - long ret; - ret = ftell((FILE *)stream); - return ret; -} - -long ZCALLBACK fseek_file_func (opaque, stream, offset, origin) - voidpf opaque; - voidpf stream; - uLong offset; - int origin; -{ - int fseek_origin=0; - long ret; - switch (origin) - { - case ZLIB_FILEFUNC_SEEK_CUR : - fseek_origin = SEEK_CUR; - break; - case ZLIB_FILEFUNC_SEEK_END : - fseek_origin = SEEK_END; - break; - case ZLIB_FILEFUNC_SEEK_SET : - fseek_origin = SEEK_SET; - break; - default: return -1; - } - ret = 0; - fseek((FILE *)stream, offset, fseek_origin); - return ret; -} - -long ZCALLBACK fclose_file_func (opaque, stream) - voidpf opaque; - voidpf stream; -{ - long ret; - ret = fclose((FILE *)stream); - return ret; -} - -int ZCALLBACK ferror_file_func (opaque, stream) - voidpf opaque; - voidpf stream; -{ - int ret; - ret = ferror((FILE *)stream); - return ret; -} - -void fill_fopen_filefunc (pzlib_filefunc_def) - zlib_filefunc_def* pzlib_filefunc_def; -{ - pzlib_filefunc_def->zopen_file = fopen_file_func; - pzlib_filefunc_def->zread_file = fread_file_func; - pzlib_filefunc_def->zwrite_file = fwrite_file_func; - pzlib_filefunc_def->ztell_file = ftell_file_func; - pzlib_filefunc_def->zseek_file = fseek_file_func; - pzlib_filefunc_def->zclose_file = fclose_file_func; - pzlib_filefunc_def->zerror_file = ferror_file_func; - pzlib_filefunc_def->opaque = NULL; -} diff --git a/source/ioapi.h b/source/ioapi.h deleted file mode 100644 index 19b3010..0000000 --- a/source/ioapi.h +++ /dev/null @@ -1,64 +0,0 @@ -/* ioapi.h -- IO base function header for compress/uncompress .zip - files using zlib + zip or unzip API - - Version 0.18 beta, Feb 26th, 2002 - - Copyright (C) 1998-2002 Gilles Vollant -*/ - -#ifndef _ZLIBIOAPI_H -#define _ZLIBIOAPI_H - - -#define ZLIB_FILEFUNC_SEEK_CUR (1) -#define ZLIB_FILEFUNC_SEEK_END (2) -#define ZLIB_FILEFUNC_SEEK_SET (0) - -#define ZLIB_FILEFUNC_MODE_READ (1) -#define ZLIB_FILEFUNC_MODE_WRITE (2) -#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) - -#define ZLIB_FILEFUNC_MODE_EXISTING (4) -#define ZLIB_FILEFUNC_MODE_CREATE (8) - - -#ifndef ZCALLBACK - -#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) -#define ZCALLBACK CALLBACK -#else -#define ZCALLBACK -#endif -#endif - -typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); -typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); -typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); -typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); -typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); -typedef long (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); -typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); - -typedef struct zlib_filefunc_def_s -{ - open_file_func zopen_file; - read_file_func zread_file; - write_file_func zwrite_file; - tell_file_func ztell_file; - seek_file_func zseek_file; - close_file_func zclose_file; - testerror_file_func zerror_file; - voidpf opaque; -} zlib_filefunc_def; - - - -void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); - -#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size)) -#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size)) -#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream)) -#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode)) -#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream)) -#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream)) -#endif diff --git a/source/unzip.c b/source/unzip.c deleted file mode 100644 index a14de70..0000000 --- a/source/unzip.c +++ /dev/null @@ -1,1436 +0,0 @@ -/* unzip.c -- IO for uncompress .zip files using zlib - Version 0.18 beta, Feb 26th, 2002 - - Copyright (C) 1998-2002 Gilles Vollant - - Read unzip.h for more info -*/ -#include "config.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "zlib.h" -#include "unzip.h" - -#ifdef STDC -# include <stddef.h> -# include <string.h> -# include <stdlib.h> -#endif -#ifdef NO_ERRNO_H - extern int errno; -#else -# include <errno.h> -#endif - - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - - - -#if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && !defined(CASESENSITIVITYDEFAULT_NO) -#define CASESENSITIVITYDEFAULT_NO -#endif - - -#ifndef UNZ_BUFSIZE -#define UNZ_BUFSIZE (16384) -#endif - -#ifndef UNZ_MAXFILENAMEINZIP -#define UNZ_MAXFILENAMEINZIP (256) -#endif - -#ifndef ALLOC -# define ALLOC(size) (malloc(size)) -#endif -#ifndef TRYFREE -# define TRYFREE(p) {if (p) free(p);} -#endif - -#define SIZECENTRALDIRITEM (0x2e) -#define SIZEZIPLOCALHEADER (0x1e) - - - - -const char unz_copyright[] = - " unzip 0.18 Copyright 1998-2002 Gilles Vollant - http://www.winimage.com/zLibDll"; - -/* unz_file_info_interntal contain internal info about a file in zipfile*/ -typedef struct unz_file_info_internal_s -{ - uLong offset_curfile;/* relative offset of local header 4 bytes */ -} unz_file_info_internal; - - -/* file_in_zip_read_info_s contain internal information about a file in zipfile, - when reading and decompress it */ -typedef struct -{ - char *read_buffer; /* internal buffer for compressed data */ - z_stream stream; /* zLib stream structure for inflate */ - - uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ - uLong stream_initialised; /* flag set if stream structure is initialised*/ - - uLong offset_local_extrafield;/* offset of the local extra field */ - uInt size_local_extrafield;/* size of the local extra field */ - uLong pos_local_extrafield; /* position in the local extra field in read*/ - - uLong crc32; /* crc32 of all data uncompressed */ - uLong crc32_wait; /* crc32 we must obtain after decompress all */ - uLong rest_read_compressed; /* number of byte to be decompressed */ - uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/ - zlib_filefunc_def z_filefunc; - voidpf filestream; /* io structore of the zipfile */ - uLong compression_method; /* compression method (0==store) */ - uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ - int raw; -} file_in_zip_read_info_s; - - -/* unz_s contain internal information about the zipfile -*/ -typedef struct -{ - zlib_filefunc_def z_filefunc; - voidpf filestream; /* io structore of the zipfile */ - unz_global_info gi; /* public global information */ - uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ - uLong num_file; /* number of the current file in the zipfile*/ - uLong pos_in_central_dir; /* pos of the current file in the central dir*/ - uLong current_file_ok; /* flag about the usability of the current file*/ - uLong central_pos; /* position of the beginning of the central dir*/ - - uLong size_central_dir; /* size of the central directory */ - uLong offset_central_dir; /* offset of start of central directory with - respect to the starting disk number */ - - unz_file_info cur_file_info; /* public info about the current file in zip*/ - unz_file_info_internal cur_file_info_internal; /* private info about it*/ - file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current - file if we are decompressing it */ -} unz_s; - - -/* =========================================================================== - Read a byte from a gz_stream; update next_in and avail_in. Return EOF - for end of file. - IN assertion: the stream s has been sucessfully opened for reading. -*/ - - -local int unzlocal_getByte OF(( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream, - int *pi)); - -local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; - int *pi; -{ - unsigned char c; - int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1); - if (err==1) - { - *pi = (int)c; - return UNZ_OK; - } - else - { - if (ZERROR(*pzlib_filefunc_def,filestream)) - return UNZ_ERRNO; - else - return UNZ_EOF; - } -} - - -/* =========================================================================== - Reads a long in LSB order from the given gz_stream. Sets -*/ -local int unzlocal_getShort OF(( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX)); - -local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; - uLong *pX; -{ - uLong x ; - int i; - int err; - - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<8; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int unzlocal_getLong OF(( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX)); - -local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; - uLong *pX; -{ - uLong x ; - int i; - int err; - - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<8; - - if (err==UNZ_OK) - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<16; - - if (err==UNZ_OK) - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<24; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - - -/* My own strcmpi / strcasecmp */ -local int strcmpcasenosensitive_internal( - const char* fileName1, - const char* fileName2) -{ - for (;;) - { - char c1=*(fileName1++); - char c2=*(fileName2++); - if ((c1>='a') && (c1<='z')) - c1 -= 0x20; - if ((c2>='a') && (c2<='z')) - c2 -= 0x20; - if (c1=='\0') - return ((c2=='\0') ? 0 : -1); - if (c2=='\0') - return 1; - if (c1<c2) - return -1; - if (c1>c2) - return 1; - } -} - - -#ifdef CASESENSITIVITYDEFAULT_NO -#define CASESENSITIVITYDEFAULTVALUE 2 -#else -#define CASESENSITIVITYDEFAULTVALUE 1 -#endif - -#ifndef STRCMPCASENOSENTIVEFUNCTION -#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal -#endif - -/* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi - or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system - (like 1 on Unix, 2 on Windows) - -*/ -extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity) - const char* fileName1; - const char* fileName2; - int iCaseSensitivity; -{ - if (iCaseSensitivity==0) - iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; - - if (iCaseSensitivity==1) - return strcmp(fileName1,fileName2); - - return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); -} - -#define BUFREADCOMMENT (0x400) - -/* - Locate the Central directory of a zipfile (at the end, just before - the global comment) -*/ -local uLong unzlocal_SearchCentralDir OF(( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream)); - -local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; -{ - unsigned char* buf; - uLong uSizeFile; - uLong uBackRead; - uLong uMaxBack=0xffff; /* maximum size of global comment */ - uLong uPosFound=0; - - if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) - return 0; - - - uSizeFile = ZTELL(*pzlib_filefunc_def,filestream); - - if (uMaxBack>uSizeFile) - uMaxBack = uSizeFile; - - buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); - if (buf==NULL) - return 0; - - uBackRead = 4; - while (uBackRead<uMaxBack) - { - uLong uReadSize,uReadPos ; - int i; - if (uBackRead+BUFREADCOMMENT>uMaxBack) - uBackRead = uMaxBack; - else - uBackRead+=BUFREADCOMMENT; - uReadPos = uSizeFile-uBackRead ; - - uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? - (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); - if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) - break; - - if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) - break; - - for (i=(int)uReadSize-3; (i--)>0;) - if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && - ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) - { - uPosFound = uReadPos+i; - break; - } - - if (uPosFound!=0) - break; - } - TRYFREE(buf); - return uPosFound; -} - -/* - Open a Zip file. path contain the full pathname (by example, - on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer - "zlib/zlib109.zip". - If the zipfile cannot be opened (file don't exist or in not valid), the - return value is NULL. - Else, the return value is a unzFile Handle, usable with other function - of this unzip package. -*/ -extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def) - const char *path; - zlib_filefunc_def* pzlib_filefunc_def; -{ - unz_s us; - unz_s *s; - uLong central_pos,uL; - - uLong number_disk; /* number of the current dist, used for - spaning ZIP, unsupported, always 0*/ - uLong number_disk_with_CD; /* number the the disk with central dir, used - for spaning ZIP, unsupported, always 0*/ - uLong number_entry_CD; /* total number of entries in - the central dir - (same than number_entry on nospan) */ - - int err=UNZ_OK; - - if (unz_copyright[0]!=' ') - return NULL; - - if (pzlib_filefunc_def==NULL) - fill_fopen_filefunc(&us.z_filefunc); - else - us.z_filefunc = *pzlib_filefunc_def; - - us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque, - path, - ZLIB_FILEFUNC_MODE_READ | - ZLIB_FILEFUNC_MODE_EXISTING); - if (us.filestream==NULL) - return NULL; - - central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream); - if (central_pos==0) - err=UNZ_ERRNO; - - if (ZSEEK(us.z_filefunc, us.filestream, - central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) - err=UNZ_ERRNO; - - /* the signature, already checked */ - if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of this disk */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of the disk with the start of the central directory */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central dir on this disk */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central dir */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - if ((number_entry_CD!=us.gi.number_entry) || - (number_disk_with_CD!=0) || - (number_disk!=0)) - err=UNZ_BADZIPFILE; - - /* size of the central directory */ - if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) - err=UNZ_ERRNO; - - /* offset of start of central directory with respect to the - starting disk number */ - if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) - err=UNZ_ERRNO; - - /* zipfile comment length */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) - err=UNZ_ERRNO; - - if ((central_pos<us.offset_central_dir+us.size_central_dir) && - (err==UNZ_OK)) - err=UNZ_BADZIPFILE; - - if (err!=UNZ_OK) - { - ZCLOSE(us.z_filefunc, us.filestream); - return NULL; - } - - us.byte_before_the_zipfile = central_pos - - (us.offset_central_dir+us.size_central_dir); - us.central_pos = central_pos; - us.pfile_in_zip_read = NULL; - - - s=(unz_s*)ALLOC(sizeof(unz_s)); - *s=us; - unzGoToFirstFile((unzFile)s); - return (unzFile)s; -} - - -extern unzFile ZEXPORT unzOpen (path) - const char *path; -{ - return unzOpen2(path, NULL); -} - -/* - Close a ZipFile opened with unzipOpen. - If there is files inside the .Zip opened with unzipOpenCurrentFile (see later), - these files MUST be closed with unzipCloseCurrentFile before call unzipClose. - return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzClose (file) - unzFile file; -{ - unz_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - - if (s->pfile_in_zip_read!=NULL) - unzCloseCurrentFile(file); - - ZCLOSE(s->z_filefunc, s->filestream); - TRYFREE(s); - return UNZ_OK; -} - - -/* - Write info about the ZipFile in the *pglobal_info structuref. - No preparation of the structure is needed - return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info) - unzFile file; - unz_global_info *pglobal_info; -{ - unz_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - *pglobal_info=s->gi; - return UNZ_OK; -} - - -/* - Translate date/time from Dos format to tm_unz (readable more easilty) -*/ -local void unzlocal_DosDateToTmuDate ( - uLong ulDosDate, - tm_unz* ptm) -{ - uLong uDate; - uDate = (uLong)(ulDosDate>>16); - ptm->tm_mday = (uInt)(uDate&0x1f) ; - ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; - ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; - - ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); - ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; - ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; -} - -/* - Get Info about the current file in the zipfile, with internal only info -*/ -local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file, - unz_file_info *pfile_info, - unz_file_info_internal - *pfile_info_internal, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize)); - -local int unzlocal_GetCurrentFileInfoInternal (file, - pfile_info, - pfile_info_internal, - szFileName, fileNameBufferSize, - extraField, extraFieldBufferSize, - szComment, commentBufferSize) - unzFile file; - unz_file_info *pfile_info; - unz_file_info_internal *pfile_info_internal; - char *szFileName; - uLong fileNameBufferSize; - void *extraField; - uLong extraFieldBufferSize; - char *szComment; - uLong commentBufferSize; -{ - unz_s* s; - unz_file_info file_info; - unz_file_info_internal file_info_internal; - int err=UNZ_OK; - uLong uMagic; - long lSeek=0; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (ZSEEK(s->z_filefunc, s->filestream, - s->pos_in_central_dir+s->byte_before_the_zipfile, - ZLIB_FILEFUNC_SEEK_SET)!=0) - err=UNZ_ERRNO; - - - /* we check the magic */ - if (err==UNZ_OK) { - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x02014b50) - err=UNZ_BADZIPFILE; - } - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) - err=UNZ_ERRNO; - - unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) - err=UNZ_ERRNO; - - lSeek+=file_info.size_filename; - if ((err==UNZ_OK) && (szFileName!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_filename<fileNameBufferSize) - { - *(szFileName+file_info.size_filename)='\0'; - uSizeRead = file_info.size_filename; - } - else - uSizeRead = fileNameBufferSize; - - if ((file_info.size_filename>0) && (fileNameBufferSize>0)) - if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) - err=UNZ_ERRNO; - lSeek -= uSizeRead; - } - - - if ((err==UNZ_OK) && (extraField!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_file_extra<extraFieldBufferSize) - uSizeRead = file_info.size_file_extra; - else - uSizeRead = extraFieldBufferSize; - - if (lSeek!=0) { - if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - } - if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) - if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead) - err=UNZ_ERRNO; - lSeek += file_info.size_file_extra - uSizeRead; - } - else - lSeek+=file_info.size_file_extra; - - - if ((err==UNZ_OK) && (szComment!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_file_comment<commentBufferSize) - { - *(szComment+file_info.size_file_comment)='\0'; - uSizeRead = file_info.size_file_comment; - } - else - uSizeRead = commentBufferSize; - - if (lSeek!=0) { - if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - } - if ((file_info.size_file_comment>0) && (commentBufferSize>0)) - if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) - err=UNZ_ERRNO; - lSeek+=file_info.size_file_comment - uSizeRead; - } - else - lSeek+=file_info.size_file_comment; - - if ((err==UNZ_OK) && (pfile_info!=NULL)) - *pfile_info=file_info; - - if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) - *pfile_info_internal=file_info_internal; - - return err; -} - - - -/* - Write info about the ZipFile in the *pglobal_info structuref. - No preparation of the structure is needed - return UNZ_OK if there is no problem. -*/ -extern int ZEXPORT unzGetCurrentFileInfo (file, - pfile_info, - szFileName, fileNameBufferSize, - extraField, extraFieldBufferSize, - szComment, commentBufferSize) - unzFile file; - unz_file_info *pfile_info; - char *szFileName; - uLong fileNameBufferSize; - void *extraField; - uLong extraFieldBufferSize; - char *szComment; - uLong commentBufferSize; -{ - return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL, - szFileName,fileNameBufferSize, - extraField,extraFieldBufferSize, - szComment,commentBufferSize); -} - -/* - Set the current file of the zipfile to the first file. - return UNZ_OK if there is no problem -*/ -extern int ZEXPORT unzGoToFirstFile (file) - unzFile file; -{ - int err=UNZ_OK; - unz_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - s->pos_in_central_dir=s->offset_central_dir; - s->num_file=0; - err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - - -/* - Set the current file of the zipfile to the next file. - return UNZ_OK if there is no problem - return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. -*/ -extern int ZEXPORT unzGoToNextFile (file) - unzFile file; -{ - unz_s* s; - int err; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - if (s->num_file+1==s->gi.number_entry) - return UNZ_END_OF_LIST_OF_FILE; - - s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + - s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; - s->num_file++; - err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - - -/* - Try locate the file szFileName in the zipfile. - For the iCaseSensitivity signification, see unzipStringFileNameCompare - - return value : - UNZ_OK if the file is found. It becomes the current file. - UNZ_END_OF_LIST_OF_FILE if the file is not found -*/ -extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity) - unzFile file; - const char *szFileName; - int iCaseSensitivity; -{ - unz_s* s; - int err; - - - uLong num_fileSaved; - uLong pos_in_central_dirSaved; - - - if (file==NULL) - return UNZ_PARAMERROR; - - if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) - return UNZ_PARAMERROR; - - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - - num_fileSaved = s->num_file; - pos_in_central_dirSaved = s->pos_in_central_dir; - - err = unzGoToFirstFile(file); - - while (err == UNZ_OK) - { - char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; - unzGetCurrentFileInfo(file,NULL, - szCurrentFileName,sizeof(szCurrentFileName)-1, - NULL,0,NULL,0); - if (unzStringFileNameCompare(szCurrentFileName, - szFileName,iCaseSensitivity)==0) - return UNZ_OK; - err = unzGoToNextFile(file); - } - - s->num_file = num_fileSaved ; - s->pos_in_central_dir = pos_in_central_dirSaved ; - return err; -} - - -/* - Read the local header of the current zipfile - Check the coherency of the local header and info in the end of central - directory about this file - store in *piSizeVar the size of extra info in local header - (filename and size of extra field data) -*/ -local int unzlocal_CheckCurrentFileCoherencyHeader ( - unz_s* s, - uInt* piSizeVar, - uLong *poffset_local_extrafield, - uInt *psize_local_extrafield) -{ - uLong uMagic,uData,uFlags; - uLong size_filename; - uLong size_extra_field; - int err=UNZ_OK; - - *piSizeVar = 0; - *poffset_local_extrafield = 0; - *psize_local_extrafield = 0; - - if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + - s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - - if (err==UNZ_OK) { - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x04034b50) - err=UNZ_BADZIPFILE; - } - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) - err=UNZ_ERRNO; -/* - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) - err=UNZ_BADZIPFILE; -*/ - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) - err=UNZ_BADZIPFILE; - - if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && - (s->cur_file_info.compression_method!=Z_DEFLATED)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) - err=UNZ_BADZIPFILE; - - *piSizeVar += (uInt)size_filename; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) - err=UNZ_ERRNO; - *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + - SIZEZIPLOCALHEADER + size_filename; - *psize_local_extrafield = (uInt)size_extra_field; - - *piSizeVar += (uInt)size_extra_field; - - return err; -} - -/* - Open for reading data the current file in the zipfile. - If there is no error and the file is opened, the return value is UNZ_OK. -*/ -extern int ZEXPORT unzOpenCurrentFile2 (file, method, level, raw) - unzFile file; - int* method; - int* level; - int raw; - -{ - int err=UNZ_OK; - uInt iSizeVar; - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - uLong offset_local_extrafield; /* offset of the local extra field */ - uInt size_local_extrafield; /* size of the local extra field */ - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_PARAMERROR; - - if (s->pfile_in_zip_read != NULL) - unzCloseCurrentFile(file); - - if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, - &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) - return UNZ_BADZIPFILE; - - pfile_in_zip_read_info = (file_in_zip_read_info_s*) - ALLOC(sizeof(file_in_zip_read_info_s)); - if (pfile_in_zip_read_info==NULL) - return UNZ_INTERNALERROR; - - pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); - pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; - pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; - pfile_in_zip_read_info->pos_local_extrafield=0; - pfile_in_zip_read_info->raw=raw; - - if (pfile_in_zip_read_info->read_buffer==NULL) - { - TRYFREE(pfile_in_zip_read_info); - return UNZ_INTERNALERROR; - } - - pfile_in_zip_read_info->stream_initialised=0; - - if (method!=NULL) - *method = (int)s->cur_file_info.compression_method; - - if (level!=NULL) - { - *level = 6; - switch (s->cur_file_info.flag & 0x06) - { - case 6 : *level = 1; break; - case 4 : *level = 2; break; - case 2 : *level = 9; break; - } - } - - if ((s->cur_file_info.compression_method!=0) && - (s->cur_file_info.compression_method!=Z_DEFLATED)) - err=UNZ_BADZIPFILE; - - pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; - pfile_in_zip_read_info->crc32=0; - pfile_in_zip_read_info->compression_method = - s->cur_file_info.compression_method; - pfile_in_zip_read_info->filestream=s->filestream; - pfile_in_zip_read_info->z_filefunc=s->z_filefunc; - pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; - - pfile_in_zip_read_info->stream.total_out = 0; - - if ((s->cur_file_info.compression_method==Z_DEFLATED) && - (!raw)) - { - pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; - pfile_in_zip_read_info->stream.zfree = (free_func)0; - pfile_in_zip_read_info->stream.opaque = (voidpf)0; - - err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); - if (err == Z_OK) - pfile_in_zip_read_info->stream_initialised=1; - /* windowBits is passed < 0 to tell that there is no zlib header. - * Note that in this case inflate *requires* an extra "dummy" byte - * after the compressed stream in order to complete decompression and - * return Z_STREAM_END. - * In unzip, i don't wait absolutely Z_STREAM_END because I known the - * size of both compressed and uncompressed data - */ - } - pfile_in_zip_read_info->rest_read_compressed = - s->cur_file_info.compressed_size ; - pfile_in_zip_read_info->rest_read_uncompressed = - s->cur_file_info.uncompressed_size ; - - - pfile_in_zip_read_info->pos_in_zipfile = - s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + - iSizeVar; - - pfile_in_zip_read_info->stream.avail_in = (uInt)0; - - - s->pfile_in_zip_read = pfile_in_zip_read_info; - return UNZ_OK; -} - -extern int ZEXPORT unzOpenCurrentFile (file) - unzFile file; -{ - return unzOpenCurrentFile2(file, NULL, NULL, 0); -} -/* - Read bytes from the current file. - buf contain buffer where data must be copied - len the size of buf. - - return the number of byte copied if somes bytes are copied - return 0 if the end of file was reached - return <0 with error code if there is an error - (UNZ_ERRNO for IO error, or zLib error for uncompress error) -*/ -extern int ZEXPORT unzReadCurrentFile (file, buf, len) - unzFile file; - voidp buf; - unsigned len; -{ - int err=UNZ_OK; - uInt iRead = 0; - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - - if ((pfile_in_zip_read_info->read_buffer == NULL)) - return UNZ_END_OF_LIST_OF_FILE; - if (len==0) - return 0; - - pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; - - pfile_in_zip_read_info->stream.avail_out = (uInt)len; - - if (len>pfile_in_zip_read_info->rest_read_uncompressed) - pfile_in_zip_read_info->stream.avail_out = - (uInt)pfile_in_zip_read_info->rest_read_uncompressed; - - while (pfile_in_zip_read_info->stream.avail_out>0) - { - if ((pfile_in_zip_read_info->stream.avail_in==0) && - (pfile_in_zip_read_info->rest_read_compressed>0)) - { - uInt uReadThis = UNZ_BUFSIZE; - if (pfile_in_zip_read_info->rest_read_compressed<uReadThis) - uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed; - if (uReadThis == 0) - return UNZ_EOF; - if (ZSEEK(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->pos_in_zipfile + - pfile_in_zip_read_info->byte_before_the_zipfile, - ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - if (ZREAD(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->read_buffer, - uReadThis)!=uReadThis) - return UNZ_ERRNO; - pfile_in_zip_read_info->pos_in_zipfile += uReadThis; - - pfile_in_zip_read_info->rest_read_compressed-=uReadThis; - - pfile_in_zip_read_info->stream.next_in = - (Bytef*)pfile_in_zip_read_info->read_buffer; - pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; - } - - if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) - { - uInt uDoCopy,i ; - - if ((pfile_in_zip_read_info->stream.avail_in == 0) && - (pfile_in_zip_read_info->rest_read_compressed == 0)) - return (iRead==0) ? UNZ_EOF : iRead; - - if (pfile_in_zip_read_info->stream.avail_out < - pfile_in_zip_read_info->stream.avail_in) - uDoCopy = pfile_in_zip_read_info->stream.avail_out ; - else - uDoCopy = pfile_in_zip_read_info->stream.avail_in ; - - for (i=0;i<uDoCopy;i++) - *(pfile_in_zip_read_info->stream.next_out+i) = - *(pfile_in_zip_read_info->stream.next_in+i); - - pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, - pfile_in_zip_read_info->stream.next_out, - uDoCopy); - pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; - pfile_in_zip_read_info->stream.avail_in -= uDoCopy; - pfile_in_zip_read_info->stream.avail_out -= uDoCopy; - pfile_in_zip_read_info->stream.next_out += uDoCopy; - pfile_in_zip_read_info->stream.next_in += uDoCopy; - pfile_in_zip_read_info->stream.total_out += uDoCopy; - iRead += uDoCopy; - } - else - { - uLong uTotalOutBefore,uTotalOutAfter; - const Bytef *bufBefore; - uLong uOutThis; - int flush=Z_SYNC_FLUSH; - - uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; - bufBefore = pfile_in_zip_read_info->stream.next_out; - - /* - if ((pfile_in_zip_read_info->rest_read_uncompressed == - pfile_in_zip_read_info->stream.avail_out) && - (pfile_in_zip_read_info->rest_read_compressed == 0)) - flush = Z_FINISH; - */ - err=inflate(&pfile_in_zip_read_info->stream,flush); - - uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; - uOutThis = uTotalOutAfter-uTotalOutBefore; - - pfile_in_zip_read_info->crc32 = - crc32(pfile_in_zip_read_info->crc32,bufBefore, - (uInt)(uOutThis)); - - pfile_in_zip_read_info->rest_read_uncompressed -= - uOutThis; - - iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); - - if (err==Z_STREAM_END) - return (iRead==0) ? UNZ_EOF : iRead; - if (err!=Z_OK) - break; - } - } - - if (err==Z_OK) - return iRead; - return err; -} - - -/* - Give the current position in uncompressed data -*/ -extern z_off_t ZEXPORT unztell (file) - unzFile file; -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - return (z_off_t)pfile_in_zip_read_info->stream.total_out; -} - - -/* - return 1 if the end of file was reached, 0 elsewhere -*/ -extern int ZEXPORT unzeof (file) - unzFile file; -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - if (pfile_in_zip_read_info->rest_read_uncompressed == 0) - return 1; - else - return 0; -} - - - -/* - Read extra field from the current file (opened by unzOpenCurrentFile) - This is the local-header version of the extra field (sometimes, there is - more info in the local-header version than in the central-header) - - if buf==NULL, it return the size of the local extra field that can be read - - if buf!=NULL, len is the size of the buffer, the extra header is copied in - buf. - the return value is the number of bytes copied in buf, or (if <0) - the error code -*/ -extern int ZEXPORT unzGetLocalExtrafield (file,buf,len) - unzFile file; - voidp buf; - unsigned len; -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - uInt read_now; - uLong size_to_read; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - size_to_read = (pfile_in_zip_read_info->size_local_extrafield - - pfile_in_zip_read_info->pos_local_extrafield); - - if (buf==NULL) - return (int)size_to_read; - - if (len>size_to_read) - read_now = (uInt)size_to_read; - else - read_now = (uInt)len ; - - if (read_now==0) - return 0; - - if (ZSEEK(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->offset_local_extrafield + - pfile_in_zip_read_info->pos_local_extrafield, - ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - if (ZREAD(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - buf,size_to_read)!=size_to_read) - return UNZ_ERRNO; - - return (int)read_now; -} - -/* - Close the file in zip opened with unzipOpenCurrentFile - Return UNZ_CRCERROR if all the file was read but the CRC is not good -*/ -extern int ZEXPORT unzCloseCurrentFile (file) - unzFile file; -{ - int err=UNZ_OK; - - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - - if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && - (!pfile_in_zip_read_info->raw)) - { - if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) - err=UNZ_CRCERROR; - } - - - TRYFREE(pfile_in_zip_read_info->read_buffer); - pfile_in_zip_read_info->read_buffer = NULL; - if (pfile_in_zip_read_info->stream_initialised) - inflateEnd(&pfile_in_zip_read_info->stream); - - pfile_in_zip_read_info->stream_initialised = 0; - TRYFREE(pfile_in_zip_read_info); - - s->pfile_in_zip_read=NULL; - - return err; -} - - -/* - Get the global comment string of the ZipFile, in the szComment buffer. - uSizeBuf is the size of the szComment buffer. - return the number of byte copied or an error code <0 -*/ -extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf) - unzFile file; - char *szComment; - uLong uSizeBuf; -{ - unz_s* s; - uLong uReadThis ; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - - uReadThis = uSizeBuf; - if (uReadThis>s->gi.size_comment) - uReadThis = s->gi.size_comment; - - if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - if (uReadThis>0) - { - *szComment='\0'; - if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) - return UNZ_ERRNO; - } - - if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) - *(szComment+s->gi.size_comment)='\0'; - return (int)uReadThis; -} - - -/*********************************** - -[SkulleR] - start of modifications - -************************************/ - -/* -===================== -unzReOpen -===================== -*/ -extern unzFile ZEXPORT unzReOpen( const char *path, unzFile zFile ) { - unz_s *s; - zlib_filefunc_def z_filefunc; - voidpf filestream; - - fill_fopen_filefunc( &z_filefunc ); - - filestream = (*z_filefunc.zopen_file)( z_filefunc.opaque, - path, - ZLIB_FILEFUNC_MODE_READ| - ZLIB_FILEFUNC_MODE_EXISTING ); - if( filestream == NULL ) { - return NULL; - } - - s = (unz_s *)ALLOC( sizeof( unz_s ) ); - memcpy( s, zFile, sizeof( unz_s ) ); - s->filestream = filestream; - - return (unzFile)s; -} - -/* -===================== -unzSetCurrentFileInfoPosition -===================== -*/ -extern int ZEXPORT unzSetCurrentFileInfoPosition( unzFile zFile, int offset ) { - unz_s *s = (unz_s *)zFile; - int err; - - s->pos_in_central_dir = offset; - err = unzlocal_GetCurrentFileInfoInternal( zFile, - &s->cur_file_info, - &s->cur_file_info_internal, - NULL, 0, NULL, 0, NULL, 0 ); - if( err != UNZ_OK ) { - s->current_file_ok = 0; - return -1; - } - - s->current_file_ok = 1; - return s->cur_file_info.uncompressed_size; -} - -/* -===================== -unzGetCurrentFileInfoPosition -===================== -*/ -extern int ZEXPORT unzGetCurrentFileInfoPosition( unzFile zFile ) { - return ((unz_s *)zFile)->pos_in_central_dir; -} - -/*********************************** - -[SkulleR] - end of modifications - -************************************/ - diff --git a/source/unzip.h b/source/unzip.h deleted file mode 100644 index e6f564c..0000000 --- a/source/unzip.h +++ /dev/null @@ -1,306 +0,0 @@ -/* unzip.h -- IO for uncompress .zip files using zlib - Version 0.18 beta, Feb 26th, 2002 - - Copyright (C) 1998-2002 Gilles Vollant - - This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g - WinZip, InfoZip tools and compatible. - Encryption and multi volume ZipFile (span) are not supported. - Old compressions used by old PKZip 1.x are not supported - - THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE - CAN CHANGE IN FUTURE VERSION !! - I WAIT FEEDBACK at mail info@winimage.com - Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution - - Condition of use and distribution are the same than zlib : - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this softwaref. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original softwaref. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original softwaref. - 3. This notice may not be removed or altered from any source distribution. - - -*/ - -/* for more info about .ZIP format, see - http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip - http://www.info-zip.org/pub/infozip/doc/ - PkWare has also a specification at : - ftp://ftp.pkwaref.com/probdesc.zip -*/ - -#ifndef _unz_H -#define _unz_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _ZLIB_H -#include "zlib.h" -#endif - -#ifndef _ZLIBIOAPI_H -#include "ioapi.h" -#endif - -#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) -/* like the STRICT of WIN32, we define a pointer that cannot be converted - from (void*) without cast */ -typedef struct TagunzFile__ { int unused; } unzFile__; -typedef unzFile__ *unzFile; -#else -typedef voidp unzFile; -#endif - - -#define UNZ_OK (0) -#define UNZ_END_OF_LIST_OF_FILE (-100) -#define UNZ_ERRNO (Z_ERRNO) -#define UNZ_EOF (0) -#define UNZ_PARAMERROR (-102) -#define UNZ_BADZIPFILE (-103) -#define UNZ_INTERNALERROR (-104) -#define UNZ_CRCERROR (-105) - -/* tm_unz contain date/time info */ -typedef struct tm_unz_s -{ - uInt tm_sec; /* seconds after the minute - [0,59] */ - uInt tm_min; /* minutes after the hour - [0,59] */ - uInt tm_hour; /* hours since midnight - [0,23] */ - uInt tm_mday; /* day of the month - [1,31] */ - uInt tm_mon; /* months since January - [0,11] */ - uInt tm_year; /* years - [1980..2044] */ -} tm_unz; - -/* unz_global_info structure contain global data about the ZIPfile - These data comes from the end of central dir */ -typedef struct unz_global_info_s -{ - uLong number_entry; /* total number of entries in - the central dir on this disk */ - uLong size_comment; /* size of the global comment of the zipfile */ -} unz_global_info; - - -/* unz_file_info contain information about a file in the zipfile */ -typedef struct unz_file_info_s -{ - uLong version; /* version made by 2 bytes */ - uLong version_needed; /* version needed to extract 2 bytes */ - uLong flag; /* general purpose bit flag 2 bytes */ - uLong compression_method; /* compression method 2 bytes */ - uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ - uLong crc; /* crc-32 4 bytes */ - uLong compressed_size; /* compressed size 4 bytes */ - uLong uncompressed_size; /* uncompressed size 4 bytes */ - uLong size_filename; /* filename length 2 bytes */ - uLong size_file_extra; /* extra field length 2 bytes */ - uLong size_file_comment; /* file comment length 2 bytes */ - - uLong disk_num_start; /* disk number start 2 bytes */ - uLong internal_fa; /* internal file attributes 2 bytes */ - uLong external_fa; /* external file attributes 4 bytes */ - - tm_unz tmu_date; -} unz_file_info; - -extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, - const char* fileName2, - int iCaseSensitivity)); -/* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi - or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system - (like 1 on Unix, 2 on Windows) -*/ - - -extern unzFile ZEXPORT unzOpen OF((const char *path)); -/* - Open a Zip file. path contain the full pathname (by example, - on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer - "zlib/zlib113.zip". - If the zipfile cannot be opened (file don't exist or in not valid), the - return value is NULL. - Else, the return value is a unzFile Handle, usable with other function - of this unzip package. -*/ - -extern unzFile ZEXPORT unzOpen2 OF((const char *path, - zlib_filefunc_def* pzlib_filefunc_def)); -/* - Open a Zip file, like unzOpen, but provide a set of file low level API - for read/write the zip file (see ioapi.h) -*/ - -extern int ZEXPORT unzClose OF((unzFile file)); -/* - Close a ZipFile opened with unzipOpen. - If there is files inside the .Zip opened with unzOpenCurrentFile (see later), - these files MUST be closed with unzipCloseCurrentFile before call unzipClose. - return UNZ_OK if there is no problem. */ - -extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, - unz_global_info *pglobal_info)); -/* - Write info about the ZipFile in the *pglobal_info structuref. - No preparation of the structure is needed - return UNZ_OK if there is no problem. */ - - -extern int ZEXPORT unzGetGlobalComment OF((unzFile file, - char *szComment, - uLong uSizeBuf)); -/* - Get the global comment string of the ZipFile, in the szComment buffer. - uSizeBuf is the size of the szComment buffer. - return the number of byte copied or an error code <0 -*/ - - -/***************************************************************************/ -/* Unzip package allow you browse the directory of the zipfile */ - -extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); -/* - Set the current file of the zipfile to the first file. - return UNZ_OK if there is no problem -*/ - -extern int ZEXPORT unzGoToNextFile OF((unzFile file)); -/* - Set the current file of the zipfile to the next file. - return UNZ_OK if there is no problem - return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. -*/ - -extern int ZEXPORT unzLocateFile OF((unzFile file, - const char *szFileName, - int iCaseSensitivity)); -/* - Try locate the file szFileName in the zipfile. - For the iCaseSensitivity signification, see unzStringFileNameCompare - - return value : - UNZ_OK if the file is found. It becomes the current file. - UNZ_END_OF_LIST_OF_FILE if the file is not found -*/ - - -extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, - unz_file_info *pfile_info, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize)); -/* - Get Info about the current file - if pfile_info!=NULL, the *pfile_info structure will contain somes info about - the current file - if szFileName!=NULL, the filemane string will be copied in szFileName - (fileNameBufferSize is the size of the buffer) - if extraField!=NULL, the extra field information will be copied in extraField - (extraFieldBufferSize is the size of the buffer). - This is the Central-header version of the extra field - if szComment!=NULL, the comment string of the file will be copied in szComment - (commentBufferSize is the size of the buffer) -*/ - -/***************************************************************************/ -/* for reading the content of the current zipfile, you can open it, read data - from it, and close it (you can close it before reading all the file) - */ - -extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); -/* - Open for reading data the current file in the zipfile. - If there is no error, the return value is UNZ_OK. -*/ - -extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, - int* method, - int* level, - int raw)); -/* - Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) - *method will receive method of compression, *level will receive level of - compression - note : you can set level parameter as NULL (if you did not want known level, - but you CANNOT set method parameter as NULL -*/ - -extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); -/* - Close the file in zip opened with unzOpenCurrentFile - Return UNZ_CRCERROR if all the file was read but the CRC is not good -*/ - -extern int ZEXPORT unzReadCurrentFile OF((unzFile file, - voidp buf, - unsigned len)); -/* - Read bytes from the current file (opened by unzOpenCurrentFile) - buf contain buffer where data must be copied - len the size of buf. - - return the number of byte copied if somes bytes are copied - return 0 if the end of file was reached - return <0 with error code if there is an error - (UNZ_ERRNO for IO error, or zLib error for uncompress error) -*/ - -extern z_off_t ZEXPORT unztell OF((unzFile file)); -/* - Give the current position in uncompressed data -*/ - -extern int ZEXPORT unzeof OF((unzFile file)); -/* - return 1 if the end of file was reached, 0 elsewhere -*/ - -extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, - voidp buf, - unsigned len)); -/* - Read extra field from the current file (opened by unzOpenCurrentFile) - This is the local-header version of the extra field (sometimes, there is - more info in the local-header version than in the central-header) - - if buf==NULL, it return the size of the local extra field - - if buf!=NULL, len is the size of the buffer, the extra header is copied in - buf. - the return value is the number of bytes copied in buf, or (if <0) - the error code -*/ - -// [SkulleR] - start -extern unzFile ZEXPORT unzReOpen OF( (const char *path, unzFile zFile) ); -extern int ZEXPORT unzSetCurrentFileInfoPosition OF( (unzFile zFile, int offset) ); -extern int ZEXPORT unzGetCurrentFileInfoPosition OF( (unzFile zFile) ); -// [SkulleR] - end - -#ifdef __cplusplus -} -#endif - -#endif /* _unz_H */ |