Platform abstracted i/o, other bugfixes.
authorRyan C. Gordon <icculus@icculus.org>
Fri, 29 Mar 2002 08:20:06 +0000
changeset 143 337505f94c10
parent 142 e3eb45e37874
child 144 819455c581e5
Platform abstracted i/o, other bugfixes.
archivers/unzip.c
archivers/zip.c
--- a/archivers/unzip.c	Fri Mar 29 08:19:39 2002 +0000
+++ b/archivers/unzip.c	Fri Mar 29 08:20:06 2002 +0000
@@ -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 <stddef.h>
 #  include <string.h>
@@ -86,7 +93,7 @@
 	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 @@
 	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
 {
-	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 @@
 
 
 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 @@
 }
 
 
+/* !!! 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 @@
     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 @@
     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 @@
 		
 		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 @@
 	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 @@
     if (unz_copyright[0]!=' ')
         return NULL;
 
-    fin=fopen(path,"rb");
+    fin=__PHYSFS_platformOpenRead(path);
 	if (fin==NULL)
 		return NULL;
 
@@ -368,7 +375,7 @@
 	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 @@
 
 	if (err!=UNZ_OK)
 	{
-		fclose(fin);
+		__PHYSFS_platformClose(fin);
 		return NULL;
 	}
 
@@ -449,7 +456,7 @@
     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 @@
 	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 @@
 			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 @@
 
 		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 @@
 
 		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 @@
 	*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 @@
 				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 @@
 	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 @@
 	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 @@
 		*(szComment+s->gi.size_comment)='\0';
 	return (int)uReadThis;
 }
+
--- a/archivers/zip.c	Fri Mar 29 08:19:39 2002 +0000
+++ b/archivers/zip.c	Fri Mar 29 08:20:06 2002 +0000
@@ -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 <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <assert.h>
 #include "physfs.h"
 #include "unzip.h"
 
@@ -237,45 +237,42 @@
 } /* 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 @@
 
         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);