archivers/zip.c
changeset 143 337505f94c10
parent 132 b53fa5093749
child 144 819455c581e5
--- 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);