diff options
author | Andrey Nazarov <skuller@skuller.net> | 2010-06-13 21:09:26 +0000 |
---|---|---|
committer | Andrey Nazarov <skuller@skuller.net> | 2010-06-13 21:09:26 +0000 |
commit | 8d7da794826bd2371b41146525ed66eae26c3c0c (patch) | |
tree | 839cb015dca51f6bc7ac1502f6c9b7eb4e6e7680 | |
parent | 23b0669bc0c2e24a5b637f080e45553ed853d941 (diff) |
Read ZIP packs directly using custom loader.
Removed PKZIP library (bye bye 1600+ lines of unmaintained code).
Don't fatal crash when packfile fails to read or we run out of free file handles, just print an error message.
Allow filesystem to be restarted even if there are file handles reading from packfiles (packfile will be freed once file handle is closed).
-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 */ |