home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 20 / AACD20.BIN / AACD / Programming / Jikes / Source / src / zip.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-03  |  12.9 KB  |  420 lines

  1. // $Id: zip.cpp,v 1.13 2001/01/10 16:49:45 mdejong Exp $
  2. //
  3. // This software is subject to the terms of the IBM Jikes Compiler
  4. // License Agreement available at the following URL:
  5. // http://www.ibm.com/research/jikes.
  6. // Copyright (C) 1996, 1998, International Business Machines Corporation
  7. // and others.  All Rights Reserved.
  8. // You must accept the terms of that agreement to use this software.
  9. //
  10.  
  11. #include "zip.h"
  12. #include "control.h"
  13. #include "symbol.h"
  14.  
  15. #ifdef    HAVE_JIKES_NAMESPACE
  16. namespace Jikes {    // Open namespace Jikes block
  17. #endif
  18.  
  19. //************************************************************************************************
  20. //
  21. // The ZipFile methods follow
  22. //
  23. //************************************************************************************************
  24. #if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
  25.     int (*ZipFile::uncompress_file[10]) (FILE *, char *, long) =
  26.     {
  27.         UncompressFile0,
  28.         UncompressFile1,
  29.         UncompressFile2,
  30.         UncompressFile3,
  31.         UncompressFile4,
  32.         UncompressFile5,
  33.         UncompressFile6,
  34.         UncompressFile7,
  35.         UncompressFile8,
  36.         UncompressFile9
  37.     };
  38.  
  39.     inline u1 ZipFile::GetU1()
  40.     {
  41.         return getc(zipfile);
  42.     }
  43.  
  44.     inline void ZipFile::Skip(u4 length)
  45.     {
  46.         for (u4 i = 0; i < length; i++)
  47.              getc(zipfile);
  48.     }
  49.  
  50. #elif defined(WIN32_FILE_SYSTEM)
  51.  
  52.     int (*ZipFile::uncompress_file[10]) (char *, char *, long) =
  53.     {
  54.         UncompressFile0,
  55.         UncompressFile1,
  56.         UncompressFile2,
  57.         UncompressFile3,
  58.         UncompressFile4,
  59.         UncompressFile5,
  60.         UncompressFile6,
  61.         UncompressFile7,
  62.         UncompressFile8,
  63.         UncompressFile9
  64.     };
  65.  
  66.     inline u1 ZipFile::GetU1()
  67.     {
  68.         return *file_buffer++;
  69.     }
  70.  
  71.     inline void ZipFile::Skip(u4 length)
  72.     {
  73.         file_buffer += length;
  74.     }
  75.  
  76. #endif
  77.  
  78.  
  79. inline u2 ZipFile::GetU2()
  80. {
  81.     u4 val = GetU1();
  82.     val |= (((u4) GetU1()) << 8);
  83.  
  84.     return val;
  85. }
  86.  
  87.  
  88. inline u4 ZipFile::GetU4()
  89. {
  90.     u4 val = GetU1();
  91.     val |= (((u4) GetU1()) << 8);
  92.     val |= (((u4) GetU1()) << 16);
  93.     val |= (((u4) GetU1()) << 24);
  94.  
  95.     return val;
  96. }
  97.  
  98.  
  99. ZipFile::ZipFile(FileSymbol *file_symbol) : buffer(NULL)
  100. {
  101.     Zip *zip = file_symbol -> Zipfile();
  102.  
  103.     assert(zip -> IsValid());
  104.  
  105. #if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
  106.     zipfile = zip -> zipfile;
  107.     int rc = fseek(zipfile, file_symbol -> offset, SEEK_SET);
  108.  
  109.     assert(rc == 0);
  110.  
  111. #elif defined(WIN32_FILE_SYSTEM)
  112.     file_buffer = &zip -> zipbuffer[file_symbol -> offset];
  113. #endif
  114.  
  115.     Skip(8); // u4 magic                     = GetU4();
  116.              // u2 version_needed_to_extract = GetU2();
  117.              // u2 general_purpose_bits      = GetU2();
  118.     u2 compression_method                    = GetU2();
  119.     Skip(16); // u2 time                     = GetU2();
  120.               // u2 date                     = GetU2();
  121.               // u4 crc32                    = GetU4();
  122.               // u4 compressed_size          = GetU4();
  123.               // u4 uncompressed_size        = GetU4();
  124.     u2 filename_length                       = GetU2();
  125.     u2 extra_field_length                    = GetU2();
  126.     Skip(filename_length + extra_field_length);
  127.  
  128. #if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
  129.     this -> buffer = new char[file_symbol -> uncompressed_size];
  130.     if (! uncompress_file[compression_method < 9 ? compression_method : 9](zipfile, this -> buffer, file_symbol -> uncompressed_size))
  131.     {
  132.         delete [] this -> buffer;
  133.         this -> buffer = NULL;
  134.     }
  135. #elif defined(WIN32_FILE_SYSTEM)
  136.     if (compression_method > 0)
  137.     {
  138.         this -> buffer = new char[file_symbol -> uncompressed_size];
  139.         if (! uncompress_file[compression_method < 9 ? compression_method : 9](file_buffer,
  140.                                                                                this -> buffer,
  141.                                                                                file_symbol -> uncompressed_size))
  142.         {
  143.             delete [] this -> buffer;
  144.             this -> buffer = NULL;
  145.             this -> file_buffer = NULL;
  146.         }
  147.     }
  148. #endif
  149.  
  150.     return;
  151. }
  152.  
  153.  
  154. ZipFile::~ZipFile()
  155. {
  156.     delete [] buffer;
  157. }
  158.  
  159.  
  160. //************************************************************************************************
  161. //
  162. // The Zip methods follow:
  163. //
  164. //************************************************************************************************
  165. inline u1 Zip::GetU1()
  166. {
  167.     return *buffer_ptr++;
  168. }
  169.  
  170.  
  171. inline u2 Zip::GetU2()
  172. {
  173.     u4 val = GetU1();
  174.     val |= (((u4) GetU1()) << 8);
  175.  
  176.     return val;
  177. }
  178.  
  179.  
  180. inline u4 Zip::GetU4()
  181. {
  182.     u4 val = GetU1();
  183.     val |= (((u4) GetU1()) << 8);
  184.     val |= (((u4) GetU1()) << 16);
  185.     val |= (((u4) GetU1()) << 24);
  186.  
  187.     return val;
  188. }
  189.  
  190.  
  191. inline void Zip::Skip(u4 length)
  192. {
  193.     buffer_ptr += length;
  194. }
  195.  
  196.  
  197. inline DirectorySymbol *Zip::ProcessSubdirectoryEntries(DirectorySymbol *directory_symbol, char *name, int name_length)
  198. {
  199.     wchar_t *directory_name = new wchar_t[name_length];
  200.  
  201.     for (int start = 0, end; start < name_length; start = end + 1)
  202.     {
  203.         end = start;
  204.         for (int i = 0; end < name_length && name[end] != U_SLASH; i++, end++)
  205.              directory_name[i] = name[end];
  206.         NameSymbol *name_symbol = control.FindOrInsertName(directory_name, end - start);
  207.         DirectorySymbol *subdirectory_symbol = directory_symbol -> FindDirectorySymbol(name_symbol);
  208.         if (! subdirectory_symbol)
  209.             subdirectory_symbol = directory_symbol -> InsertDirectorySymbol(name_symbol);
  210.         directory_symbol = subdirectory_symbol;
  211.     }
  212.  
  213.     delete [] directory_name;
  214.  
  215.     return directory_symbol;
  216. }
  217.  
  218.  
  219. inline NameSymbol *Zip::ProcessFilename(char *name, int name_length)
  220. {
  221.     wchar_t *input_filename = new wchar_t[name_length];
  222.     for (int i = 0; i < name_length; i++)
  223.         input_filename[i] = name[i];
  224.     NameSymbol *name_symbol = control.FindOrInsertName(input_filename, name_length);
  225.  
  226.     delete [] input_filename;
  227.  
  228.     return name_symbol;
  229. }
  230.  
  231.  
  232. inline void Zip::ProcessDirectoryEntry()
  233. {
  234.     Skip(8); // u2 version_made_by           = GetU2();
  235.              // u2 version_needed_to_extract = GetU2();
  236.              // u2 general_purpose_bits      = GetU2();
  237.              // u2 compression_method        = GetU2();
  238.     u2 last_mod_file_time                    = GetU2();
  239.     u2 last_mod_file_date                    = GetU2();
  240.     Skip(4); // u4 crc32                     = GetU4();
  241.     Skip(4); // u4 compressed_size           = GetU4();
  242.     u4 uncompressed_size                     = GetU4();
  243.     u2 file_name_length                      = GetU2();
  244.     u2 extra_field_length                    = GetU2();
  245.     u2 file_comment_length                   = GetU2();
  246.     Skip(8); // u2 disk_number_start         = GetU2();
  247.              // u2 internal_file_attributes  = GetU2();
  248.              // u4 external_file_attributes  = GetU4();
  249.     u4 relative_offset_of_local_header       = GetU4();
  250.  
  251.     u4 date_time = ((u4) last_mod_file_date) << 16 | last_mod_file_time;
  252.     char *name = buffer_ptr;
  253.  
  254.     Skip(file_name_length + extra_field_length + file_comment_length);
  255.  
  256.     //
  257.     // Note that we need to process all subdirectory entries that appear in the zip file, and not
  258.     // just the ones that contain java and class files. Recall that in java the dot notation is
  259.     // used in specifying a package. Therefore, in processing a qualified-name that represents
  260.     // a package, we need to recognize each name as a subpackage. E.g., when processing
  261.     // "java.lang", we need to recognize "java" as a package before looking for "lang"...
  262.     //
  263.     DirectorySymbol *directory_symbol = root_directory; // start at the "." directory.
  264.     if (name[file_name_length - 1] == U_SLASH)
  265.         ProcessSubdirectoryEntries(directory_symbol, name, file_name_length - 1);  // -1 to remove last '/'
  266.     else
  267.     {
  268.         bool java_file = (file_name_length >= FileSymbol::java_suffix_length &&
  269.                           FileSymbol::IsJavaSuffix(&name[file_name_length - FileSymbol::java_suffix_length])),
  270.              class_file = (file_name_length >= FileSymbol::class_suffix_length &&
  271.                            FileSymbol::IsClassSuffix(&name[file_name_length - FileSymbol::class_suffix_length]));
  272.  
  273.         if (java_file || class_file)
  274.         {
  275.             int name_length = file_name_length - (java_file ? FileSymbol::java_suffix_length : FileSymbol::class_suffix_length);
  276.             int i;
  277.             for (i = name_length - 1; i >= 0 && name[i] != U_SLASH; i--)
  278.                 ;
  279.             if (i > 0) // directory specified?
  280.                 directory_symbol = ProcessSubdirectoryEntries(directory_symbol, name, i);
  281.             NameSymbol *name_symbol = ProcessFilename(&name[i + 1], name_length - (i + 1));
  282.  
  283.             //
  284.             // Search for a file of that name in the directory. If one is not found, then insert ...
  285.             // Otherwise, either a class file of that name was previously processed and now we found
  286.             // a java file with the same name or vice-versa... In that case keep (or replace with ) the
  287.             // the file with the most recent date stamp.
  288.             //
  289.             FileSymbol *file_symbol = directory_symbol -> FindFileSymbol(name_symbol);
  290.             if (! file_symbol)
  291.             {
  292.                 file_symbol = directory_symbol -> InsertFileSymbol(name_symbol);
  293.  
  294.                 file_symbol -> directory_symbol = directory_symbol;
  295.                 if (java_file)
  296.                      file_symbol -> SetJava();
  297.                 else file_symbol -> SetClassOnly();
  298.  
  299.                 file_symbol -> uncompressed_size = uncompressed_size;
  300.                 file_symbol -> offset = relative_offset_of_local_header;
  301.                 file_symbol -> date_time = date_time;
  302.             }
  303.             else if (file_symbol -> date_time < date_time)
  304.             {
  305.                 if (java_file)
  306.                      file_symbol -> SetJava();
  307.                 else file_symbol -> SetClass();
  308.  
  309.                 file_symbol -> uncompressed_size = uncompressed_size;
  310.                 file_symbol -> offset = relative_offset_of_local_header;
  311.                 file_symbol -> date_time = date_time;
  312.             }
  313.         }
  314.     }
  315.  
  316.     return;
  317. }
  318.  
  319.  
  320. Zip::Zip(Control &control_, char *zipfile_name) : control(control_),
  321.                                                   magic(0),
  322.                                                   zipbuffer(NULL)
  323. {
  324. #if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
  325.     zipfile = SystemFopen(zipfile_name, "rb");
  326.     if (zipfile)
  327.     {
  328.         int rc = fseek(zipfile, -22, SEEK_END);
  329.         if (rc == 0)
  330.         {
  331.             zipbuffer = new char[22];
  332.             buffer_ptr = zipbuffer;
  333.             fread(buffer_ptr, sizeof(char), 22, zipfile);
  334.  
  335.             magic = GetU4();
  336.         }
  337.     }
  338. #elif defined(WIN32_FILE_SYSTEM)
  339.     zipfile = CreateFile(zipfile_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
  340.     if (zipfile != INVALID_HANDLE_VALUE)
  341.     {
  342.         mapfile = CreateFileMapping(zipfile, NULL, PAGE_READONLY, 0, 0, NULL);
  343.         zipbuffer = (mapfile == INVALID_HANDLE_VALUE ? NULL : (char *) MapViewOfFile(mapfile, FILE_MAP_READ, 0, 0, 0));
  344.         if (zipbuffer)
  345.         {
  346.             buffer_ptr = &zipbuffer[GetFileSize(zipfile, NULL) - 22];
  347.             magic = GetU4();
  348.         }
  349.     }
  350. #endif
  351.  
  352.     ReadDirectory();
  353.  
  354.     return;
  355. }
  356.  
  357.  
  358. Zip::~Zip()
  359. {
  360. #if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
  361.     delete [] zipbuffer;
  362.     if (zipfile)
  363.         fclose(zipfile);
  364. #elif defined(WIN32_FILE_SYSTEM)
  365.     if (zipfile != INVALID_HANDLE_VALUE)
  366.     {
  367.         if (mapfile != INVALID_HANDLE_VALUE)
  368.         {
  369.             if (zipbuffer)
  370.                 UnmapViewOfFile(zipbuffer);
  371.             CloseHandle(mapfile);
  372.         }
  373.         CloseHandle(zipfile);
  374.     }
  375. #endif
  376.  
  377.     delete root_directory;
  378. }
  379.  
  380.  
  381. //
  382. // Upon successful termination of this function, IsValid() should yield true.
  383. // I.e., we should be able to assert that (magic == 0x06054b50)
  384. //
  385. void Zip::ReadDirectory()
  386. {
  387.     root_directory = new DirectorySymbol(control.dot_name_symbol, NULL);
  388.  
  389.     if (IsValid())
  390.     {
  391.         Skip(8); // u2 number_of_this_disk              = GetU2();
  392.                  // u2 number_of_the_disk_with_the_star = GetU2();
  393.                  // u2 start_of_the_central_directory   = GetU2();
  394.                  // u2 total_number_of_entries_in_the_  = GetU2();
  395.         u4 central_directory_size                       = GetU4();
  396.  
  397. #if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
  398.         int rc = fseek(zipfile, -((int) central_directory_size + 22), SEEK_END);
  399.  
  400.         assert(rc == 0);
  401.  
  402.         delete [] zipbuffer;
  403.         zipbuffer = new char[central_directory_size + 22];
  404.         buffer_ptr = zipbuffer;
  405.         fread(buffer_ptr, sizeof(char), central_directory_size + 22, zipfile);
  406. #elif defined(WIN32_FILE_SYSTEM)
  407.         buffer_ptr -= (central_directory_size + 16);
  408. #endif
  409.         for (magic = GetU4(); magic == 0x02014b50; magic = GetU4())
  410.              ProcessDirectoryEntry();
  411.     }
  412.  
  413.     return;
  414. }
  415.  
  416. #ifdef    HAVE_JIKES_NAMESPACE
  417. }            // Close namespace Jikes block
  418. #endif
  419.  
  420.