github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/make/tools/zipalign/ZipFile.h (about)

     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  // General-purpose Zip archive access.  This class allows both reading and
    19  // writing to Zip archives, including deletion of existing entries.
    20  //
    21  #ifndef __LIBS_ZIPFILE_H
    22  #define __LIBS_ZIPFILE_H
    23  
    24  #include <utils/Vector.h>
    25  #include <utils/Errors.h>
    26  #include <stdio.h>
    27  
    28  #include "ZipEntry.h"
    29  
    30  namespace android {
    31  
    32  /*
    33   * Manipulate a Zip archive.
    34   *
    35   * Some changes will not be visible in the until until "flush" is called.
    36   *
    37   * The correct way to update a file archive is to make all changes to a
    38   * copy of the archive in a temporary file, and then unlink/rename over
    39   * the original after everything completes.  Because we're only interested
    40   * in using this for packaging, we don't worry about such things.  Crashing
    41   * after making changes and before flush() completes could leave us with
    42   * an unusable Zip archive.
    43   */
    44  class ZipFile {
    45  public:
    46      ZipFile(void)
    47        : mZipFp(NULL), mReadOnly(false), mNeedCDRewrite(false)
    48        {}
    49      ~ZipFile(void) {
    50          if (!mReadOnly)
    51              flush();
    52          if (mZipFp != NULL)
    53              fclose(mZipFp);
    54          discardEntries();
    55      }
    56  
    57      /*
    58       * Open a new or existing archive.
    59       */
    60      enum {
    61          kOpenReadOnly   = 0x01,
    62          kOpenReadWrite  = 0x02,
    63          kOpenCreate     = 0x04,     // create if it doesn't exist
    64          kOpenTruncate   = 0x08,     // if it exists, empty it
    65      };
    66      status_t open(const char* zipFileName, int flags);
    67  
    68      /*
    69       * Add a file to the end of the archive.  Specify whether you want the
    70       * library to try to store it compressed.
    71       *
    72       * If "storageName" is specified, the archive will use that instead
    73       * of "fileName".
    74       *
    75       * If there is already an entry with the same name, the call fails.
    76       * Existing entries with the same name must be removed first.
    77       *
    78       * If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
    79       */
    80      status_t add(const char* fileName, int compressionMethod,
    81          ZipEntry** ppEntry)
    82      {
    83          return add(fileName, fileName, compressionMethod, ppEntry);
    84      }
    85      status_t add(const char* fileName, const char* storageName,
    86          int compressionMethod, ZipEntry** ppEntry)
    87      {
    88          return addCommon(fileName, NULL, 0, storageName,
    89                           compressionMethod, ppEntry);
    90      }
    91  
    92      /*
    93       * Add a file from an in-memory data buffer.
    94       *
    95       * If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
    96       */
    97      status_t add(const void* data, size_t size, const char* storageName,
    98          int compressionMethod, ZipEntry** ppEntry)
    99      {
   100          return addCommon(NULL, data, size, storageName,
   101                           compressionMethod, ppEntry);
   102      }
   103  
   104      /*
   105       * Add an entry by copying it from another zip file.  If "padding" is
   106       * nonzero, the specified number of bytes will be added to the "extra"
   107       * field in the header.
   108       *
   109       * If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
   110       */
   111      status_t add(const ZipFile* pSourceZip, const ZipEntry* pSourceEntry,
   112          int padding, ZipEntry** ppEntry);
   113  
   114      /*
   115       * Add an entry by copying it from another zip file, recompressing with
   116       * Zopfli if already compressed.
   117       *
   118       * If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
   119       */
   120      status_t addRecompress(const ZipFile* pSourceZip, const ZipEntry* pSourceEntry,
   121          ZipEntry** ppEntry);
   122  
   123      /*
   124       * Mark an entry as having been removed.  It is not actually deleted
   125       * from the archive or our internal data structures until flush() is
   126       * called.
   127       */
   128      status_t remove(ZipEntry* pEntry);
   129  
   130      /*
   131       * Flush changes.  If mNeedCDRewrite is set, this writes the central dir.
   132       */
   133      status_t flush(void);
   134  
   135      /*
   136       * Expand the data into the buffer provided.  The buffer must hold
   137       * at least <uncompressed len> bytes.  Variation expands directly
   138       * to a file.
   139       *
   140       * Returns "false" if an error was encountered in the compressed data.
   141       */
   142      //bool uncompress(const ZipEntry* pEntry, void* buf) const;
   143      //bool uncompress(const ZipEntry* pEntry, FILE* fp) const;
   144      void* uncompress(const ZipEntry* pEntry) const;
   145  
   146      /*
   147       * Get an entry, by name.  Returns NULL if not found.
   148       *
   149       * Does not return entries pending deletion.
   150       */
   151      ZipEntry* getEntryByName(const char* fileName) const;
   152  
   153      /*
   154       * Get the Nth entry in the archive.
   155       *
   156       * This will return an entry that is pending deletion.
   157       */
   158      int getNumEntries(void) const { return mEntries.size(); }
   159      ZipEntry* getEntryByIndex(int idx) const;
   160  
   161  private:
   162      /* these are private and not defined */
   163      ZipFile(const ZipFile& src);
   164      ZipFile& operator=(const ZipFile& src);
   165  
   166      class EndOfCentralDir {
   167      public:
   168          EndOfCentralDir(void) :
   169              mDiskNumber(0),
   170              mDiskWithCentralDir(0),
   171              mNumEntries(0),
   172              mTotalNumEntries(0),
   173              mCentralDirSize(0),
   174              mCentralDirOffset(0),
   175              mCommentLen(0),
   176              mComment(NULL)
   177              {}
   178          virtual ~EndOfCentralDir(void) {
   179              delete[] mComment;
   180          }
   181  
   182          status_t readBuf(const uint8_t* buf, int len);
   183          status_t write(FILE* fp);
   184  
   185          //uint32_t mSignature;
   186          uint16_t mDiskNumber;
   187          uint16_t mDiskWithCentralDir;
   188          uint16_t mNumEntries;
   189          uint16_t mTotalNumEntries;
   190          uint32_t mCentralDirSize;
   191          uint32_t mCentralDirOffset;      // offset from first disk
   192          uint16_t mCommentLen;
   193          uint8_t* mComment;
   194  
   195          enum {
   196              kSignature      = 0x06054b50,
   197              kEOCDLen        = 22,       // EndOfCentralDir len, excl. comment
   198  
   199              kMaxCommentLen  = 65535,    // longest possible in ushort
   200              kMaxEOCDSearch  = kMaxCommentLen + EndOfCentralDir::kEOCDLen,
   201  
   202          };
   203  
   204          void dump(void) const;
   205      };
   206  
   207  
   208      /* read all entries in the central dir */
   209      status_t readCentralDir(void);
   210  
   211      /* crunch deleted entries out */
   212      status_t crunchArchive(void);
   213  
   214      /* clean up mEntries */
   215      void discardEntries(void);
   216  
   217      /* common handler for all "add" functions */
   218      status_t addCommon(const char* fileName, const void* data, size_t size,
   219          const char* storageName, int compressionMethod, ZipEntry** ppEntry);
   220  
   221      /* copy all of "srcFp" into "dstFp" */
   222      status_t copyFpToFp(FILE* dstFp, FILE* srcFp, uint32_t* pCRC32);
   223      /* copy all of "data" into "dstFp" */
   224      status_t copyDataToFp(FILE* dstFp,
   225          const void* data, size_t size, uint32_t* pCRC32);
   226      /* copy some of "srcFp" into "dstFp" */
   227      status_t copyPartialFpToFp(FILE* dstFp, FILE* srcFp, long length,
   228          uint32_t* pCRC32);
   229      /* like memmove(), but on parts of a single file */
   230      status_t filemove(FILE* fp, off_t dest, off_t src, size_t n);
   231      /* compress all of "srcFp" into "dstFp", using Deflate */
   232      status_t compressFpToFp(FILE* dstFp, FILE* srcFp,
   233          const void* data, size_t size, uint32_t* pCRC32);
   234  
   235      /* get modification date from a file descriptor */
   236      time_t getModTime(int fd);
   237  
   238      /*
   239       * We use stdio FILE*, which gives us buffering but makes dealing
   240       * with files >2GB awkward.  Until we support Zip64, we're fine.
   241       */
   242      FILE*           mZipFp;             // Zip file pointer
   243  
   244      /* one of these per file */
   245      EndOfCentralDir mEOCD;
   246  
   247      /* did we open this read-only? */
   248      bool            mReadOnly;
   249  
   250      /* set this when we trash the central dir */
   251      bool            mNeedCDRewrite;
   252  
   253      /*
   254       * One ZipEntry per entry in the zip file.  I'm using pointers instead
   255       * of objects because it's easier than making operator= work for the
   256       * classes and sub-classes.
   257       */
   258      Vector<ZipEntry*>   mEntries;
   259  };
   260  
   261  }; // namespace android
   262  
   263  #endif // __LIBS_ZIPFILE_H