From d8cf534bf25038f406a044516534bc89907675b4 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 29 Mar 2002 08:20:06 +0000 Subject: [PATCH] Platform abstracted i/o, other bugfixes. --- archivers/unzip.c | 94 +++++++++++++++++++++++++++-------------------- archivers/zip.c | 63 +++++++++++++++---------------- 2 files changed, 84 insertions(+), 73 deletions(-) diff --git a/archivers/unzip.c b/archivers/unzip.c index b7860bf1..b5cb73fd 100644 --- a/archivers/unzip.c +++ b/archivers/unzip.c @@ -11,6 +11,13 @@ #include "zlib.h" #include "unzip.h" +#define __PHYSICSFS_INTERNAL__ +#include "physfs_internal.h" + +#if (!defined PHYSFS_SUPPORTS_ZIP) +#error PHYSFS_SUPPORTS_ZIP must be defined. +#endif + #ifdef STDC # include # include @@ -86,7 +93,7 @@ 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 pos_in_zipfile; /* position in byte on the zipfile, for seek*/ uLong stream_initialised; /* flag set if stream structure is initialised*/ uLong offset_local_extrafield;/* offset of the local extra field */ @@ -97,7 +104,7 @@ typedef struct 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*/ - FILE* file; /* io structore of the zipfile */ + void* file; /* io structore of the zipfile */ uLong compression_method; /* compression method (0==store) */ uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ } file_in_zip_read_info_s; @@ -107,7 +114,7 @@ typedef struct */ typedef struct { - FILE* file; /* io structore of the zipfile */ + void* file; /* 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*/ @@ -134,11 +141,11 @@ typedef struct local int unzlocal_getByte(fin,pi) - FILE *fin; + void *fin; int *pi; { - unsigned char c; - int err = fread(&c, 1, 1, fin); + PHYSFS_uint8 c; + PHYSFS_sint64 err = __PHYSFS_platformRead(fin, &c, 1, 1); if (err==1) { *pi = (int)c; @@ -154,11 +161,12 @@ local int unzlocal_getByte(fin,pi) } +/* !!! FIXME: Use PhysFS byteswap routines. */ /* =========================================================================== Reads a long in LSB order from the given gz_stream. Sets */ local int unzlocal_getShort (fin,pX) - FILE* fin; + void* fin; uLong *pX; { uLong x ; @@ -179,8 +187,9 @@ local int unzlocal_getShort (fin,pX) return err; } +/* !!! FIXME: Use PhysFS byteswap routines. */ local int unzlocal_getLong (fin,pX) - FILE* fin; + void* fin; uLong *pX; { uLong x ; @@ -275,20 +284,16 @@ extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivit the global comment) */ local uLong unzlocal_SearchCentralDir(fin) - FILE *fin; + void *fin; { unsigned char* buf; uLong uSizeFile; uLong uBackRead; uLong uMaxBack=0xffff; /* maximum size of global comment */ uLong uPosFound=0; - - if (fseek(fin,0,SEEK_END) != 0) - return 0; + uSizeFile = (uLong) __PHYSFS_platformFileLength( fin ); - uSizeFile = ftell( fin ); - if (uMaxBack>uSizeFile) uMaxBack = uSizeFile; @@ -309,19 +314,21 @@ local uLong unzlocal_SearchCentralDir(fin) uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); - if (fseek(fin,uReadPos,SEEK_SET)!=0) + if (!__PHYSFS_platformSeek(fin,uReadPos)) break; - if (fread(buf,(uInt)uReadSize,1,fin)!=1) + if (__PHYSFS_platformRead(fin,buf,(uInt)uReadSize,1)!=1) break; - for (i=(int)uReadSize-3; (i--)>0;) - if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + 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; @@ -345,7 +352,7 @@ extern unzFile ZEXPORT unzOpen (path) unz_s us; unz_s *s; uLong central_pos,uL; - FILE * fin ; + void* fin ; uLong number_disk; /* number of the current dist, used for spaning ZIP, unsupported, always 0*/ @@ -360,7 +367,7 @@ extern unzFile ZEXPORT unzOpen (path) if (unz_copyright[0]!=' ') return NULL; - fin=fopen(path,"rb"); + fin=__PHYSFS_platformOpenRead(path); if (fin==NULL) return NULL; @@ -368,7 +375,7 @@ extern unzFile ZEXPORT unzOpen (path) if (central_pos==0) err=UNZ_ERRNO; - if (fseek(fin,central_pos,SEEK_SET)!=0) + if (!__PHYSFS_platformSeek(fin,central_pos)) err=UNZ_ERRNO; /* the signature, already checked */ @@ -415,7 +422,7 @@ extern unzFile ZEXPORT unzOpen (path) if (err!=UNZ_OK) { - fclose(fin); + __PHYSFS_platformClose(fin); return NULL; } @@ -449,7 +456,7 @@ extern int ZEXPORT unzClose (file) if (s->pfile_in_zip_read!=NULL) unzCloseCurrentFile(file); - fclose(s->file); + __PHYSFS_platformClose(s->file); TRYFREE(s); return UNZ_OK; } @@ -530,7 +537,7 @@ local int unzlocal_GetCurrentFileInfoInternal (file, if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; - if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0) + if (!__PHYSFS_platformSeek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile)) err=UNZ_ERRNO; @@ -603,8 +610,10 @@ local int unzlocal_GetCurrentFileInfoInternal (file, uSizeRead = fileNameBufferSize; if ((file_info.size_filename>0) && (fileNameBufferSize>0)) - if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1) + { + if (__PHYSFS_platformRead(s->file,szFileName,(uInt)uSizeRead,1)!=1) err=UNZ_ERRNO; + } lSeek -= uSizeRead; } @@ -619,14 +628,15 @@ local int unzlocal_GetCurrentFileInfoInternal (file, if (lSeek!=0) { - if (fseek(s->file,lSeek,SEEK_CUR)==0) + PHYSFS_sint64 curpos = __PHYSFS_platformTell(s->file); + if ((curpos >= 0) && (__PHYSFS_platformSeek(s->file,lSeek+curpos))) lSeek=0; else err=UNZ_ERRNO; } if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) { - if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1) + if (__PHYSFS_platformRead(s->file,extraField,(uInt)uSizeRead,1)!=1) err=UNZ_ERRNO; } lSeek += file_info.size_file_extra - uSizeRead; @@ -648,14 +658,15 @@ local int unzlocal_GetCurrentFileInfoInternal (file, if (lSeek!=0) { - if (fseek(s->file,lSeek,SEEK_CUR)==0) + PHYSFS_sint64 curpos = __PHYSFS_platformTell(s->file); + if (__PHYSFS_platformSeek(s->file,lSeek+curpos)) lSeek=0; else err=UNZ_ERRNO; } if ((file_info.size_file_comment>0) && (commentBufferSize>0)) { - if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1) + if (__PHYSFS_platformRead(s->file,szComment,(uInt)uSizeRead,1)!=1) err=UNZ_ERRNO; } lSeek+=file_info.size_file_comment - uSizeRead; @@ -829,8 +840,9 @@ local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar, *poffset_local_extrafield = 0; *psize_local_extrafield = 0; - if (fseek(s->file,s->cur_file_info_internal.offset_curfile + - s->byte_before_the_zipfile,SEEK_SET)!=0) + if (!__PHYSFS_platformSeek(s->file, + s->cur_file_info_internal.offset_curfile + + s->byte_before_the_zipfile)) { return UNZ_ERRNO; } @@ -1047,12 +1059,13 @@ extern int ZEXPORT unzReadCurrentFile (file, buf, len) uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed; if (uReadThis == 0) return UNZ_EOF; - if (fseek(pfile_in_zip_read_info->file, + if (!__PHYSFS_platformSeek(pfile_in_zip_read_info->file, pfile_in_zip_read_info->pos_in_zipfile + - pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0) + pfile_in_zip_read_info->byte_before_the_zipfile)) return UNZ_ERRNO; - if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1, - pfile_in_zip_read_info->file)!=1) + if (__PHYSFS_platformRead(pfile_in_zip_read_info->file, + pfile_in_zip_read_info->read_buffer, + uReadThis,1)!=1) return UNZ_ERRNO; pfile_in_zip_read_info->pos_in_zipfile += uReadThis; @@ -1218,12 +1231,12 @@ extern int ZEXPORT unzGetLocalExtrafield (file,buf,len) if (read_now==0) return 0; - if (fseek(pfile_in_zip_read_info->file, + if (!__PHYSFS_platformSeek(pfile_in_zip_read_info->file, pfile_in_zip_read_info->offset_local_extrafield + - pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0) + pfile_in_zip_read_info->pos_local_extrafield)) return UNZ_ERRNO; - if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1) + if (__PHYSFS_platformRead(pfile_in_zip_read_info->file,buf,(uInt)size_to_read,1)!=1) return UNZ_ERRNO; return (int)read_now; @@ -1291,13 +1304,13 @@ extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf) if (uReadThis>s->gi.size_comment) uReadThis = s->gi.size_comment; - if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0) + if (!__PHYSFS_platformSeek(s->file,s->central_pos+22)) return UNZ_ERRNO; if (uReadThis>0) { *szComment='\0'; - if (fread(szComment,(uInt)uReadThis,1,s->file)!=1) + if (__PHYSFS_platformRead(s->file,szComment,(uInt)uReadThis,1)!=1) return UNZ_ERRNO; } @@ -1305,3 +1318,4 @@ extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf) *(szComment+s->gi.size_comment)='\0'; return (int)uReadThis; } + diff --git a/archivers/zip.c b/archivers/zip.c index 6915c277..b346c578 100644 --- a/archivers/zip.c +++ b/archivers/zip.c @@ -9,18 +9,18 @@ /* * !!! FIXME: overall design bugs. * - * Make unz_file_info.version into two fields of unsigned char. That's what - * they are in the zipfile; heavens knows why unzip.c casts it...this causes - * a byte ordering headache for me in entry_is_symlink(). - * * Maybe add a seekToStartOfCurrentFile() in unzip.c if complete seek * semantics are impossible. + * + * Could be more i/o efficient if we combined unzip.c and this file. + * (and thus lose all the unzGoToNextFile() dummy loops. */ #include #include #include #include +#include #include "physfs.h" #include "unzip.h" @@ -237,45 +237,42 @@ static void freeEntries(ZIPinfo *info, int count, const char *errmsg) } /* freeEntries */ -static char *ZIP_realpath(unzFile fh, unz_file_info *info) +/* + * !!! FIXME: Really implement this. + * !!! FIXME: symlinks in zipfiles can be relative paths, including + * !!! FIXME: "." and ".." entries. These need to be parsed out. + * !!! FIXME: For now, though, we're just copying the relative path. Oh well. + */ +static char *expand_symlink_path(const char *path, ZIPentry *entry) { - char *retval = NULL; - int size; - - BAIL_IF_MACRO(unzOpenCurrentFile(fh) != UNZ_OK, ERR_IO_ERROR, NULL); - size = info->uncompressed_size; - retval = (char *) malloc(size + 1); + char *retval = (char *) malloc(strlen(path) + 1); BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL); - if (unzReadCurrentFile(fh, retval, size) != size) - { - free(retval); - __PHYSFS_setError(ERR_IO_ERROR); - retval = NULL; - } /* if */ - retval[size] = '\0'; - unzCloseCurrentFile(fh); - + strcpy(retval, path); return(retval); -} /* ZIP_realpath */ +} /* expand_symlink_path */ -/* "uLong" is defined by zlib and/or unzip.h ... */ -typedef union +static char *ZIP_realpath(unzFile fh, unz_file_info *info, ZIPentry *entry) { - unsigned char uchar4[4]; - uLong ul; -} uchar4_uLong; + char path[MAXZIPENTRYSIZE]; + int size = info->uncompressed_size; + int rc; + + BAIL_IF_MACRO(size >= sizeof (path), ERR_IO_ERROR, NULL); + BAIL_IF_MACRO(unzOpenCurrentFile(fh) != UNZ_OK, ERR_IO_ERROR, NULL); + rc = unzReadCurrentFile(fh, path, size); + unzCloseCurrentFile(fh); + BAIL_IF_MACRO(rc != size, ERR_IO_ERROR, NULL); + path[size] = '\0'; /* null terminate it. */ + + return(expand_symlink_path(path, entry)); /* retval is malloc()'d. */ +} /* ZIP_realpath */ static int version_does_symlinks(uLong version) { int retval = 0; - unsigned char hosttype; - uchar4_uLong converter; - - converter.ul = version; - hosttype = converter.uchar4[1]; /* !!! BYTE ORDERING ALERT! */ - + unsigned char hosttype = ((version >> 8) & 0xFF); /* * These are the platforms that can build an archive with symlinks, @@ -344,7 +341,7 @@ static int loadZipEntries(ZIPinfo *info, unzFile unz) if (entry_is_symlink(d)) { - info->entries[i].symlink = ZIP_realpath(unz, d); + info->entries[i].symlink = ZIP_realpath(unz, d, &info->entries[i]); if (info->entries[i].symlink == NULL) { freeEntries(info, i + 1, NULL);