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