Home | History | Annotate | Download | only in zipalign
      1 /*
      2  * Copyright (C) 2006 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 //
     18 // Zip archive entries.
     19 //
     20 // The ZipEntry class is tightly meshed with the ZipFile class.
     21 //
     22 #ifndef __LIBS_ZIPENTRY_H
     23 #define __LIBS_ZIPENTRY_H
     24 
     25 #include <utils/Errors.h>
     26 
     27 #include <stdlib.h>
     28 #include <stdint.h>
     29 #include <stdio.h>
     30 #include <time.h>
     31 
     32 namespace android {
     33 
     34 class ZipFile;
     35 
     36 /*
     37  * ZipEntry objects represent a single entry in a Zip archive.
     38  *
     39  * You can use one of these to get or set information about an entry, but
     40  * there are no functions here for accessing the data itself.  (We could
     41  * tuck a pointer to the ZipFile in here for convenience, but that raises
     42  * the likelihood of using ZipEntry objects after discarding the ZipFile.)
     43  *
     44  * File information is stored in two places: next to the file data (the Local
     45  * File Header, and possibly a Data Descriptor), and at the end of the file
     46  * (the Central Directory Entry).  The two must be kept in sync.
     47  */
     48 class ZipEntry {
     49 public:
     50     friend class ZipFile;
     51 
     52     ZipEntry(void)
     53         : mDeleted(false), mMarked(false)
     54         {}
     55     ~ZipEntry(void) {}
     56 
     57     /*
     58      * Returns "true" if the data is compressed.
     59      */
     60     bool isCompressed(void) const {
     61         return mCDE.mCompressionMethod != kCompressStored;
     62     }
     63     int getCompressionMethod(void) const { return mCDE.mCompressionMethod; }
     64 
     65     /*
     66      * Return the uncompressed length.
     67      */
     68     off_t getUncompressedLen(void) const { return mCDE.mUncompressedSize; }
     69 
     70     /*
     71      * Return the compressed length.  For uncompressed data, this returns
     72      * the same thing as getUncompresesdLen().
     73      */
     74     off_t getCompressedLen(void) const { return mCDE.mCompressedSize; }
     75 
     76     /*
     77      * Return the absolute file offset of the start of the compressed or
     78      * uncompressed data.
     79      */
     80     off_t getFileOffset(void) const {
     81         return mCDE.mLocalHeaderRelOffset +
     82                 LocalFileHeader::kLFHLen +
     83                 mLFH.mFileNameLength +
     84                 mLFH.mExtraFieldLength;
     85     }
     86 
     87     /*
     88      * Return the data CRC.
     89      */
     90     uint32_t getCRC32(void) const { return mCDE.mCRC32; }
     91 
     92     /*
     93      * Return file modification time in UNIX seconds-since-epoch.
     94      */
     95     time_t getModWhen(void) const;
     96 
     97     /*
     98      * Return the archived file name.
     99      */
    100     const char* getFileName(void) const { return (const char*) mCDE.mFileName; }
    101 
    102     /*
    103      * Application-defined "mark".  Can be useful when synchronizing the
    104      * contents of an archive with contents on disk.
    105      */
    106     bool getMarked(void) const { return mMarked; }
    107     void setMarked(bool val) { mMarked = val; }
    108 
    109     /*
    110      * Some basic functions for raw data manipulation.  "LE" means
    111      * Little Endian.
    112      */
    113     static inline uint16_t getShortLE(const uint8_t* buf) {
    114         return buf[0] | (buf[1] << 8);
    115     }
    116     static inline uint32_t getLongLE(const uint8_t* buf) {
    117         return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
    118     }
    119     static inline void putShortLE(uint8_t* buf, uint16_t val) {
    120         buf[0] = (uint8_t) val;
    121         buf[1] = (uint8_t) (val >> 8);
    122     }
    123     static inline void putLongLE(uint8_t* buf, uint32_t val) {
    124         buf[0] = (uint8_t) val;
    125         buf[1] = (uint8_t) (val >> 8);
    126         buf[2] = (uint8_t) (val >> 16);
    127         buf[3] = (uint8_t) (val >> 24);
    128     }
    129 
    130     /* defined for Zip archives */
    131     enum {
    132         kCompressStored     = 0,        // no compression
    133         // shrunk           = 1,
    134         // reduced 1        = 2,
    135         // reduced 2        = 3,
    136         // reduced 3        = 4,
    137         // reduced 4        = 5,
    138         // imploded         = 6,
    139         // tokenized        = 7,
    140         kCompressDeflated   = 8,        // standard deflate
    141         // Deflate64        = 9,
    142         // lib imploded     = 10,
    143         // reserved         = 11,
    144         // bzip2            = 12,
    145     };
    146 
    147     /*
    148      * Deletion flag.  If set, the entry will be removed on the next
    149      * call to "flush".
    150      */
    151     bool getDeleted(void) const { return mDeleted; }
    152 
    153 protected:
    154     /*
    155      * Initialize the structure from the file, which is pointing at
    156      * our Central Directory entry.
    157      */
    158     status_t initFromCDE(FILE* fp);
    159 
    160     /*
    161      * Initialize the structure for a new file.  We need the filename
    162      * and comment so that we can properly size the LFH area.  The
    163      * filename is mandatory, the comment is optional.
    164      */
    165     void initNew(const char* fileName, const char* comment);
    166 
    167     /*
    168      * Initialize the structure with the contents of a ZipEntry from
    169      * another file.
    170      */
    171     status_t initFromExternal(const ZipEntry* pEntry);
    172 
    173     /*
    174      * Add some pad bytes to the LFH.  We do this by adding or resizing
    175      * the "extra" field.
    176      */
    177     status_t addPadding(int padding);
    178 
    179     /*
    180      * Set information about the data for this entry.
    181      */
    182     void setDataInfo(long uncompLen, long compLen, uint32_t crc32,
    183         int compressionMethod);
    184 
    185     /*
    186      * Set the modification date.
    187      */
    188     void setModWhen(time_t when);
    189 
    190     /*
    191      * Return the offset of the local file header.
    192      */
    193     off_t getLFHOffset(void) const { return mCDE.mLocalHeaderRelOffset; }
    194 
    195     /*
    196      * Set the offset of the local file header, relative to the start of
    197      * the current file.
    198      */
    199     void setLFHOffset(off_t offset) {
    200         mCDE.mLocalHeaderRelOffset = (uint32_t) offset;
    201     }
    202 
    203     /* mark for deletion; used by ZipFile::remove() */
    204     void setDeleted(void) { mDeleted = true; }
    205 
    206 private:
    207     /* these are private and not defined */
    208     ZipEntry(const ZipEntry& src);
    209     ZipEntry& operator=(const ZipEntry& src);
    210 
    211     /* returns "true" if the CDE and the LFH agree */
    212     bool compareHeaders(void) const;
    213     void copyCDEtoLFH(void);
    214 
    215     bool        mDeleted;       // set if entry is pending deletion
    216     bool        mMarked;        // app-defined marker
    217 
    218     /*
    219      * Every entry in the Zip archive starts off with one of these.
    220      */
    221     class LocalFileHeader {
    222     public:
    223         LocalFileHeader(void) :
    224             mVersionToExtract(0),
    225             mGPBitFlag(0),
    226             mCompressionMethod(0),
    227             mLastModFileTime(0),
    228             mLastModFileDate(0),
    229             mCRC32(0),
    230             mCompressedSize(0),
    231             mUncompressedSize(0),
    232             mFileNameLength(0),
    233             mExtraFieldLength(0),
    234             mFileName(NULL),
    235             mExtraField(NULL)
    236         {}
    237         virtual ~LocalFileHeader(void) {
    238             delete[] mFileName;
    239             delete[] mExtraField;
    240         }
    241 
    242         status_t read(FILE* fp);
    243         status_t write(FILE* fp);
    244 
    245         // uint32_t mSignature;
    246         uint16_t mVersionToExtract;
    247         uint16_t mGPBitFlag;
    248         uint16_t mCompressionMethod;
    249         uint16_t mLastModFileTime;
    250         uint16_t mLastModFileDate;
    251         uint32_t mCRC32;
    252         uint32_t mCompressedSize;
    253         uint32_t mUncompressedSize;
    254         uint16_t mFileNameLength;
    255         uint16_t mExtraFieldLength;
    256         uint8_t* mFileName;
    257         uint8_t* mExtraField;
    258 
    259         enum {
    260             kSignature      = 0x04034b50,
    261             kLFHLen         = 30,       // LocalFileHdr len, excl. var fields
    262         };
    263 
    264         void dump(void) const;
    265     };
    266 
    267     /*
    268      * Every entry in the Zip archive has one of these in the "central
    269      * directory" at the end of the file.
    270      */
    271     class CentralDirEntry {
    272     public:
    273         CentralDirEntry(void) :
    274             mVersionMadeBy(0),
    275             mVersionToExtract(0),
    276             mGPBitFlag(0),
    277             mCompressionMethod(0),
    278             mLastModFileTime(0),
    279             mLastModFileDate(0),
    280             mCRC32(0),
    281             mCompressedSize(0),
    282             mUncompressedSize(0),
    283             mFileNameLength(0),
    284             mExtraFieldLength(0),
    285             mFileCommentLength(0),
    286             mDiskNumberStart(0),
    287             mInternalAttrs(0),
    288             mExternalAttrs(0),
    289             mLocalHeaderRelOffset(0),
    290             mFileName(NULL),
    291             mExtraField(NULL),
    292             mFileComment(NULL)
    293         {}
    294         ~CentralDirEntry(void) {
    295             delete[] mFileName;
    296             delete[] mExtraField;
    297             delete[] mFileComment;
    298         }
    299 
    300         status_t read(FILE* fp);
    301         status_t write(FILE* fp);
    302 
    303         // uint32_t mSignature;
    304         uint16_t mVersionMadeBy;
    305         uint16_t mVersionToExtract;
    306         uint16_t mGPBitFlag;
    307         uint16_t mCompressionMethod;
    308         uint16_t mLastModFileTime;
    309         uint16_t mLastModFileDate;
    310         uint32_t mCRC32;
    311         uint32_t mCompressedSize;
    312         uint32_t mUncompressedSize;
    313         uint16_t mFileNameLength;
    314         uint16_t mExtraFieldLength;
    315         uint16_t mFileCommentLength;
    316         uint16_t mDiskNumberStart;
    317         uint16_t mInternalAttrs;
    318         uint32_t mExternalAttrs;
    319         uint32_t mLocalHeaderRelOffset;
    320         uint8_t* mFileName;
    321         uint8_t* mExtraField;
    322         uint8_t* mFileComment;
    323 
    324         void dump(void) const;
    325 
    326         enum {
    327             kSignature      = 0x02014b50,
    328             kCDELen         = 46,       // CentralDirEnt len, excl. var fields
    329         };
    330     };
    331 
    332     enum {
    333         //kDataDescriptorSignature  = 0x08074b50,   // currently unused
    334         kDataDescriptorLen  = 16,           // four 32-bit fields
    335 
    336         kDefaultVersion     = 20,           // need deflate, nothing much else
    337         kDefaultMadeBy      = 0x0317,       // 03=UNIX, 17=spec v2.3
    338         kUsesDataDescr      = 0x0008,       // GPBitFlag bit 3
    339     };
    340 
    341     LocalFileHeader     mLFH;
    342     CentralDirEntry     mCDE;
    343 };
    344 
    345 }; // namespace android
    346 
    347 #endif // __LIBS_ZIPENTRY_H
    348