* src/vm/suck.c: Moved to .cpp.
[cacao.git] / src / vm / zip.c
index ecb0226a2155bb41a193b1870dae028fee6c03a4..109156079fab28f0eb31d453ba7124ea34b55564 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/zip.c - ZIP file handling for bootstrap classloader
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   Changes:
-
-   $Id: zip.c 4357 2006-01-22 23:33:38Z twisti $
-
 */
 
 
 #include "config.h"
 
 #include <assert.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <zlib.h>
 
 #include "vm/types.h"
 
+#include "vm/descriptor.h" /* needed to prevent circular dependency */
+#include "toolbox/hashtable.h"
+
 #include "mm/memory.h"
+
 #include "vm/global.h"
-#include "vm/hashtable.h"
-#include "vm/suck.h"
+#include "vm/suck.hpp"
 #include "vm/utf8.h"
+#include "vm/vm.hpp"
 #include "vm/zip.h"
 
 
 
 #define SIGNATURE_LENGTH    4
 
-
-/* Local file header ***********************************************************
-
-   local file header signature     4 bytes  (0x04034b50)
-   version needed to extract       2 bytes
-   general purpose bit flag        2 bytes
-   compression method              2 bytes
-   last mod file time              2 bytes
-   last mod file date              2 bytes
-   crc-32                          4 bytes
-   compressed size                 4 bytes
-   uncompressed size               4 bytes
-   file name length                2 bytes
-   extra field length              2 bytes
-
-   file name (variable size)
-   extra field (variable size)
-
-*******************************************************************************/
-
-#define LFH_HEADER_SIZE              30
-
-#define LFH_SIGNATURE                0x04034b50
-#define LFH_FILE_NAME_LENGTH         26
-#define LFH_EXTRA_FIELD_LENGTH       28
-
-typedef struct lfh lfh;
-
-struct lfh {
-       u2 compressionmethod;
-       u4 compressedsize;
-       u4 uncompressedsize;
-       u2 filenamelength;
-       u2 extrafieldlength;
-};
-
-
 /* Central directory structure *************************************************
 
    [file header 1]
@@ -290,34 +248,38 @@ hashtable *zip_open(char *path)
                filename = (const char *) (p + CDSFH_FILENAME);
                classext = filename + cdsfh.filenamelength - strlen(".class");
 
-               if (strncmp(classext, ".class", strlen(".class")) == 0)
-                       u = utf_new(filename, cdsfh.filenamelength - strlen(".class"));
-               else
-                       u = utf_new(filename, cdsfh.filenamelength);
+               /* skip directory entries */
+
+               if (filename[cdsfh.filenamelength - 1] != '/') {
+                       if (strncmp(classext, ".class", strlen(".class")) == 0)
+                               u = utf_new(filename, cdsfh.filenamelength - strlen(".class"));
+                       else
+                               u = utf_new(filename, cdsfh.filenamelength);
 
-               /* insert class into hashtable */
+                       /* insert class into hashtable */
 
-               htzfe = NEW(hashtable_zipfile_entry);
+                       htzfe = NEW(hashtable_zipfile_entry);
 
-               htzfe->filename          = u;
-               htzfe->compressionmethod = cdsfh.compressionmethod;
-               htzfe->compressedsize    = cdsfh.compressedsize;
-               htzfe->uncompressedsize  = cdsfh.uncompressedsize;
-               htzfe->data              = filep + cdsfh.relativeoffset;
+                       htzfe->filename          = u;
+                       htzfe->compressionmethod = cdsfh.compressionmethod;
+                       htzfe->compressedsize    = cdsfh.compressedsize;
+                       htzfe->uncompressedsize  = cdsfh.uncompressedsize;
+                       htzfe->data              = filep + cdsfh.relativeoffset;
 
-               /* get hashtable slot */
+                       /* get hashtable slot */
 
-               key  = utf_hashkey(u->text, u->blength);
-               slot = key & (ht->size - 1);
+                       key  = utf_hashkey(u->text, u->blength);
+                       slot = key & (ht->size - 1);
 
-               /* insert into external chain */
+                       /* insert into external chain */
 
-               htzfe->hashlink = ht->ptr[slot];
+                       htzfe->hashlink = ht->ptr[slot];
 
-               /* insert hashtable zipfile entry */
+                       /* insert hashtable zipfile entry */
 
-               ht->ptr[slot] = htzfe;
-               ht->entries++;
+                       ht->ptr[slot] = htzfe;
+                       ht->entries++;
+               }
 
                /* move to next central directory structure file header */
 
@@ -336,7 +298,20 @@ hashtable *zip_open(char *path)
 
 /* zip_find ********************************************************************
 
-   XXX
+   Search for the given filename in the classpath entries of a zip file.
+
+   NOTE: The '.class' extension is stripped when reading a zip file, so if
+   you want to find a .class file, you must search for its name _without_
+   the '.class' extension. 
+   XXX I dont like that, it makes foo and foo.class ambiguous. -Edwin
+
+   IN:
+      lce..........the classpath entries for the zip file
+         u............the filename to look for
+
+   RETURN VALUE:
+      hashtable_zipfile_entry * of the entry if found, or
+         NULL if not found
 
 *******************************************************************************/
 
@@ -392,7 +367,9 @@ classbuffer *zip_get(list_classpath_entry *lce, classinfo *c)
 
        /* try to find the class in the current archive */
 
-       if ((htzfe = zip_find(lce, c->name)) == NULL)
+       htzfe = zip_find(lce, c->name);
+
+       if (htzfe == NULL)
                return NULL;
 
        /* read stuff from local file header */
@@ -427,19 +404,19 @@ classbuffer *zip_get(list_classpath_entry *lce, classinfo *c)
                /* initialize this inflate run */
 
                if (inflateInit2(&zs, -MAX_WBITS) != Z_OK)
-                       assert(0);
+                       vm_abort("zip_get: inflateInit2 failed: %s", strerror(errno));
 
                /* decompress the file into buffer */
 
                err = inflate(&zs, Z_SYNC_FLUSH);
 
                if ((err != Z_STREAM_END) && (err != Z_OK))
-                       assert(0);
+                       vm_abort("zip_get: inflate failed: %s", strerror(errno));
 
                /* finish this inflate run */
 
                if (inflateEnd(&zs) != Z_OK)
-                       assert(0);
+                       vm_abort("zip_get: inflateEnd failed: %s", strerror(errno));
                break;
 
        case 0:
@@ -448,14 +425,15 @@ classbuffer *zip_get(list_classpath_entry *lce, classinfo *c)
                break;
 
        default:
-               assert(0);
+               vm_abort("zip_get: unknown compression method %d",
+                                htzfe->compressionmethod);
        }
        
        /* allocate classbuffer */
 
        cb = NEW(classbuffer);
 
-       cb->class = c;
+       cb->clazz = c;
        cb->size  = htzfe->uncompressedsize;
        cb->data  = outdata;
        cb->pos   = outdata;
@@ -478,4 +456,5 @@ classbuffer *zip_get(list_classpath_entry *lce, classinfo *c)
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */