Home | History | Annotate | Download | only in libdex
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 /*
     17  * Read-only access to Zip archives, with minimal heap allocation.
     18  */
     19 #ifndef _LIBDEX_ZIPARCHIVE
     20 #define _LIBDEX_ZIPARCHIVE
     21 
     22 #include "SysUtil.h"
     23 #include "DexFile.h"            // need DEX_INLINE
     24 
     25 
     26 /*
     27  * Trivial typedef to ensure that ZipEntry is not treated as a simple
     28  * integer.  We use NULL to indicate an invalid value.
     29  */
     30 typedef void* ZipEntry;
     31 
     32 /*
     33  * One entry in the hash table.
     34  */
     35 typedef struct ZipHashEntry {
     36     const char*     name;
     37     unsigned short  nameLen;
     38     //unsigned int    hash;
     39 } ZipHashEntry;
     40 
     41 /*
     42  * Read-only Zip archive.
     43  *
     44  * We want "open" and "find entry by name" to be fast operations, and we
     45  * want to use as little memory as possible.  We memory-map the file,
     46  * and load a hash table with pointers to the filenames (which aren't
     47  * null-terminated).  The other fields are at a fixed offset from the
     48  * filename, so we don't need to extract those (but we do need to byte-read
     49  * and endian-swap them every time we want them).
     50  *
     51  * To speed comparisons when doing a lookup by name, we could make the mapping
     52  * "private" (copy-on-write) and null-terminate the filenames after verifying
     53  * the record structure.  However, this requires a private mapping of
     54  * every page that the Central Directory touches.  Easier to tuck a copy
     55  * of the string length into the hash table entry.
     56  */
     57 typedef struct ZipArchive {
     58     /* open Zip archive */
     59     int         mFd;
     60 
     61     /* mapped file */
     62     MemMapping  mMap;
     63 
     64     /* number of entries in the Zip archive */
     65     int         mNumEntries;
     66 
     67     /*
     68      * We know how many entries are in the Zip archive, so we can have a
     69      * fixed-size hash table.  We probe on collisions.
     70      */
     71     int         mHashTableSize;
     72     ZipHashEntry* mHashTable;
     73 } ZipArchive;
     74 
     75 /* Zip compression methods we support */
     76 enum {
     77     kCompressStored     = 0,        // no compression
     78     kCompressDeflated   = 8,        // standard deflate
     79 };
     80 
     81 
     82 /*
     83  * Open a Zip archive.
     84  *
     85  * On success, returns 0 and populates "pArchive".  Returns nonzero errno
     86  * value on failure.
     87  */
     88 int dexZipOpenArchive(const char* fileName, ZipArchive* pArchive);
     89 
     90 /*
     91  * Like dexZipOpenArchive, but takes a file descriptor open for reading
     92  * at the start of the file.  The descriptor must be mappable (this does
     93  * not allow access to a stream).
     94  *
     95  * "debugFileName" will appear in error messages, but is not otherwise used.
     96  */
     97 int dexZipPrepArchive(int fd, const char* debugFileName, ZipArchive* pArchive);
     98 
     99 /*
    100  * Close archive, releasing resources associated with it.
    101  *
    102  * Depending on the implementation this could unmap pages used by classes
    103  * stored in a Jar.  This should only be done after unloading classes.
    104  */
    105 void dexZipCloseArchive(ZipArchive* pArchive);
    106 
    107 /*
    108  * Return the archive's file descriptor.
    109  */
    110 DEX_INLINE int dexZipGetArchiveFd(const ZipArchive* pArchive) {
    111     return pArchive->mFd;
    112 }
    113 
    114 /*
    115  * Find an entry in the Zip archive, by name.  Returns NULL if the entry
    116  * was not found.
    117  */
    118 ZipEntry dexZipFindEntry(const ZipArchive* pArchive,
    119     const char* entryName);
    120 
    121 /*
    122  * Retrieve one or more of the "interesting" fields.  Non-NULL pointers
    123  * are filled in.
    124  */
    125 bool dexZipGetEntryInfo(const ZipArchive* pArchive, ZipEntry entry,
    126     int* pMethod, long* pUncompLen, long* pCompLen, off_t* pOffset,
    127     long* pModWhen, long* pCrc32);
    128 
    129 /*
    130  * Simple accessors.
    131  */
    132 DEX_INLINE long dexGetZipEntryOffset(const ZipArchive* pArchive,
    133     const ZipEntry entry)
    134 {
    135     off_t val = 0;
    136     dexZipGetEntryInfo(pArchive, entry, NULL, NULL, NULL, &val, NULL, NULL);
    137     return (long) val;
    138 }
    139 DEX_INLINE long dexGetZipEntryUncompLen(const ZipArchive* pArchive,
    140     const ZipEntry entry)
    141 {
    142     long val = 0;
    143     dexZipGetEntryInfo(pArchive, entry, NULL, &val, NULL, NULL, NULL, NULL);
    144     return val;
    145 }
    146 DEX_INLINE long dexGetZipEntryModTime(const ZipArchive* pArchive,
    147     const ZipEntry entry)
    148 {
    149     long val = 0;
    150     dexZipGetEntryInfo(pArchive, entry, NULL, NULL, NULL, NULL, &val, NULL);
    151     return val;
    152 }
    153 DEX_INLINE long dexGetZipEntryCrc32(const ZipArchive* pArchive,
    154     const ZipEntry entry)
    155 {
    156     long val = 0;
    157     dexZipGetEntryInfo(pArchive, entry, NULL, NULL, NULL, NULL, NULL, &val);
    158     return val;
    159 }
    160 
    161 /*
    162  * Uncompress and write an entry to a file descriptor.
    163  */
    164 bool dexZipExtractEntryToFile(const ZipArchive* pArchive,
    165     const ZipEntry entry, int fd);
    166 
    167 /*
    168  * Utility function to compute a CRC-32.
    169  */
    170 u4 dexInitCrc32(void);
    171 u4 dexComputeCrc32(u4 crc, const void* buf, size_t len);
    172 
    173 #endif /*_LIBDEX_ZIPARCHIVE*/
    174