OSDN Git Service

* boehm.c (set_bit): Improve type safety wrt unsignedness.
[pf3gnuchains/gcc-fork.git] / gcc / java / zextract.c
index 59fe486..eeea944 100644 (file)
@@ -1,21 +1,23 @@
 /* Handle a .class file embedded in a .zip archive.
    This extracts a member from a .zip file, but does not handle
    uncompression (since that is not needed for classes.zip).
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004
+   Free Software Foundation, Inc.
 
-   Copyright (C) 1996, 97-98, 1999  Free Software Foundation, Inc.
+This file is part of GCC.
 
-This program is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
-This program is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
+along with GCC; see the file COPYING.  If not, write to
 the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  
 
@@ -27,6 +29,8 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "zipfile.h"
 
 /* This stuff is partly based on the 28 August 1994 public release of the
@@ -210,15 +214,15 @@ typedef unsigned long     ulg;  /*  predefined on some systems) & match zip  */
 /* Prototypes          */
 /***********************/
 
-static ush makeword PROTO ((const uch *));
-static ulg makelong PROTO ((const uch *));
+static ush makeword (const uch *);
+static ulg makelong (const uch *);
+static long find_zip_file_start (int fd, long offset);
 
 /***********************/
 /* Function makeword() */
 /***********************/
 
-static ush makeword(b)
-    const uch *b;
+static ush makeword(const uch *b)
 {
     /*
      * Convert Intel style 'short' integer to non-Intel non-16-bit
@@ -232,8 +236,8 @@ static ush makeword(b)
 /* Function makelong() */
 /***********************/
 
-static ulg makelong(sig)
-    const uch *sig;
+static ulg
+makelong (const uch *sig)
 {
     /*
      * Convert intel style 'long' variable to non-Intel non-16-bit
@@ -245,9 +249,32 @@ static ulg makelong(sig)
         + ((ulg)sig[0]);
 }
 
+/* Examine file's header in zip file and return the offset of the
+   start of the actual data.  Return -1 on error.  OFFSET is the
+   offset from the beginning of the zip file of the file's header.  */
+static long
+find_zip_file_start (int fd, long offset)
+{
+  int filename_length, extra_field_length;
+  unsigned char buffer[LREC_SIZE + 4];
+
+  if (lseek (fd, offset, SEEK_SET) < 0)
+    return -1;
+
+  if (read (fd, buffer, LREC_SIZE + 4) != LREC_SIZE + 4)
+    return -1;
+
+  if (buffer[0] != 'P' || strncmp ((const char *) &buffer[1], LOCAL_HDR_SIG, 3))
+    return -1;
+
+  filename_length = makeword (&buffer[4 + L_FILENAME_LENGTH]);
+  extra_field_length = makeword (&buffer[4 + L_EXTRA_FIELD_LENGTH]);
+
+  return offset + (4 + LREC_SIZE) + filename_length + extra_field_length;
+}
+
 int
-read_zip_archive (zipf)
-     register ZipFile *zipf;
+read_zip_archive (ZipFile *zipf)
 {
   int i;
   int dir_last_pad;
@@ -260,9 +287,9 @@ read_zip_archive (zipf)
     return -1;
   if (read (zipf->fd, buffer, ECREC_SIZE+4) != ECREC_SIZE+4)
     return -2;
-  zipf->count = makeword(&buffer[TOTAL_ENTRIES_CENTRAL_DIR]);
-  zipf->dir_size = makelong(&buffer[SIZE_CENTRAL_DIRECTORY]);
-#define ALLOC malloc
+  zipf->count = makeword((const uch *) &buffer[TOTAL_ENTRIES_CENTRAL_DIR]);
+  zipf->dir_size = makelong((const uch *) &buffer[SIZE_CENTRAL_DIRECTORY]);
+#define ALLOC xmalloc
   /* Allocate 1 more to allow appending '\0' to last filename. */
   zipf->central_directory = ALLOC (zipf->dir_size+1);
   if (lseek (zipf->fd, -(zipf->dir_size+ECREC_SIZE+4), SEEK_CUR) < 0)
@@ -279,9 +306,9 @@ read_zip_archive (zipf)
   printf ("total_entries_central_dir = %d\n",
         makeword(&buffer[TOTAL_ENTRIES_CENTRAL_DIR]));
   printf ("size_central_directory = %d\n",
-        makelong(&buffer[SIZE_CENTRAL_DIRECTORY]));
+        makelong((const uch *) &buffer[SIZE_CENTRAL_DIRECTORY]));
   printf ("offset_start_central_directory = %d\n",
-        makelong(&buffer[OFFSET_START_CENTRAL_DIRECTORY]));
+        makelong((const uch *) &buffer[OFFSET_START_CENTRAL_DIRECTORY]));
   printf ("zipfile_comment_length = %d\n",
         makeword(&buffer[ZIPFILE_COMMENT_LENGTH]));
 #endif
@@ -291,27 +318,27 @@ read_zip_archive (zipf)
   for (i = 0; i < zipf->count; i++)
     {
       ZipDirectory *zipd = (ZipDirectory*)(dir_ptr + dir_last_pad);
-      long uncompressed_size = makelong (&dir_ptr[4+C_UNCOMPRESSED_SIZE]);
-      long filename_length = makeword (&dir_ptr[4+C_FILENAME_LENGTH]);
-      long extra_field_length = makeword (&dir_ptr[4+C_EXTRA_FIELD_LENGTH]);
-      long file_comment_length = makeword (&dir_ptr[4+C_FILE_COMMENT_LENGTH]);
+      int compression_method = (int) dir_ptr[4+C_COMPRESSION_METHOD];
+      long size = makelong ((const uch *) &dir_ptr[4+C_COMPRESSED_SIZE]);
+      long uncompressed_size = makelong ((const uch *) &dir_ptr[4+C_UNCOMPRESSED_SIZE]);
+      long filename_length = makeword ((const uch *) &dir_ptr[4+C_FILENAME_LENGTH]);
+      long extra_field_length = makeword ((const uch *) &dir_ptr[4+C_EXTRA_FIELD_LENGTH]);
+      long file_offset = makelong ((const uch *) &dir_ptr[4+C_RELATIVE_OFFSET_LOCAL_HEADER]);
       int unpadded_direntry_length;
       if ((dir_ptr-zipf->central_directory)+filename_length+CREC_SIZE+4>zipf->dir_size)
        return -1;
 
       zipd->filename_length = filename_length;
-      zipd->size = uncompressed_size;
+      zipd->compression_method = compression_method;
+      zipd->size = size;
+      zipd->uncompressed_size = uncompressed_size;
+      zipd->zipf = zipf;
 #ifdef __GNUC__
 #define DIR_ALIGN __alignof__(ZipDirectory)
 #else
 #define DIR_ALIGN sizeof(long)
 #endif
-      zipd->filestart = makelong (&dir_ptr[4+C_RELATIVE_OFFSET_LOCAL_HEADER])
-         + (LREC_SIZE+4) + filename_length + file_comment_length +
-         + (extra_field_length ? extra_field_length+4 : 0);
-      /* About the last term of the expression above. Should the same
-        apply if file_comment_length is not zero ?  I've never seen
-        the comment field uses so far. FIXME.  */
+      zipd->filestart = find_zip_file_start (zipf->fd, file_offset);
       zipd->filename_offset = CREC_SIZE+4 - dir_last_pad;
       unpadded_direntry_length 
          = zipd->filename_offset + zipd->filename_length + extra_field_length;
@@ -325,7 +352,7 @@ read_zip_archive (zipf)
 }
 
 #ifdef TEST
-main ()
+main (void)
 {
   ZipFile zipf[1];
   ZipDirectory *zipd;