diff options
| author | 2017-11-03 10:14:22 +0000 | |
|---|---|---|
| committer | 2017-11-03 10:14:22 +0000 | |
| commit | 1bed4d48801bc9d4ee4317bc838e6bccaea51c7d (patch) | |
| tree | 92f4f919ee67568426662ad4b894f3b49b1d826e | |
| parent | 55f259d322290ddd86378374389083cff2668961 (diff) | |
| parent | f941215d5695690e804de0c7e3828346781c7e99 (diff) | |
Merge "ZipUtils: Rewrite in terms of zip_archive::Inflate."
am: f941215d56
Change-Id: I8aa710cb6df1ba5b2079c5e3d9a70b365815d04e
| -rw-r--r-- | libs/androidfw/ZipUtils.cpp | 235 | ||||
| -rw-r--r-- | libs/androidfw/include/androidfw/ZipUtils.h | 2 | 
2 files changed, 74 insertions, 163 deletions
diff --git a/libs/androidfw/ZipUtils.cpp b/libs/androidfw/ZipUtils.cpp index 5abfc8ee917e..5d243da2097c 100644 --- a/libs/androidfw/ZipUtils.cpp +++ b/libs/androidfw/ZipUtils.cpp @@ -20,10 +20,11 @@  #define LOG_TAG "ziputil" +#include "android-base/file.h"  #include <androidfw/ZipUtils.h> -#include <androidfw/ZipFileRO.h>  #include <utils/Log.h>  #include <utils/Compat.h> +#include <ziparchive/zip_archive.h>  #include <stdlib.h>  #include <string.h> @@ -33,211 +34,121 @@  using namespace android; -static inline unsigned long get4LE(const unsigned char* buf) { -    return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); -} - - -static const unsigned long kReadBufSize = 32768; - -/* - * Utility function that expands zip/gzip "deflate" compressed data - * into a buffer. - * - * (This is a clone of the previous function, but it takes a FILE* instead - * of an fd.  We could pass fileno(fd) to the above, but we can run into - * trouble when "fp" has a different notion of what fd's file position is.) - * - * "fp" is an open file positioned at the start of the "deflate" data - * "buf" must hold at least "uncompressedLen" bytes. - */ -/*static*/ template<typename T> bool inflateToBuffer(T& reader, void* buf, -    long uncompressedLen, long compressedLen) -{ -    bool result = false; - -    z_stream zstream; -    int zerr; -    unsigned long compRemaining; - -    assert(uncompressedLen >= 0); -    assert(compressedLen >= 0); - -    compRemaining = compressedLen; - -    /* -     * Initialize the zlib stream. -     */ -    memset(&zstream, 0, sizeof(zstream)); -    zstream.zalloc = Z_NULL; -    zstream.zfree = Z_NULL; -    zstream.opaque = Z_NULL; -    zstream.next_in = NULL; -    zstream.avail_in = 0; -    zstream.next_out = (Bytef*) buf; -    zstream.avail_out = uncompressedLen; -    zstream.data_type = Z_UNKNOWN; - -    /* -     * Use the undocumented "negative window bits" feature to tell zlib -     * that there's no zlib header waiting for it. -     */ -    zerr = inflateInit2(&zstream, -MAX_WBITS); -    if (zerr != Z_OK) { -        if (zerr == Z_VERSION_ERROR) { -            ALOGE("Installed zlib is not compatible with linked version (%s)\n", -                ZLIB_VERSION); -        } else { -            ALOGE("Call to inflateInit2 failed (zerr=%d)\n", zerr); -        } -        goto bail; +// TODO: This can go away once the only remaining usage in aapt goes away. +class FileReader : public zip_archive::Reader { +  public: +    FileReader(FILE* fp) : Reader(), mFp(fp), mCurrentOffset(0) {      } -    /* -     * Loop while we have data. -     */ -    do { -        unsigned long getSize; - -        /* read as much as we can */ -        if (zstream.avail_in == 0) { -            getSize = (compRemaining > kReadBufSize) ? -                        kReadBufSize : compRemaining; -            ALOGV("+++ reading %ld bytes (%ld left)\n", -                getSize, compRemaining); - -            unsigned char* nextBuffer = NULL; -            const unsigned long nextSize = reader.read(&nextBuffer, getSize); - -            if (nextSize < getSize || nextBuffer == NULL) { -                ALOGD("inflate read failed (%ld vs %ld)\n", nextSize, getSize); -                goto z_bail; +    bool ReadAtOffset(uint8_t* buf, size_t len, uint32_t offset) const { +        // Data is usually requested sequentially, so this helps avoid pointless +        // fseeks every time we perform a read. There's an impedence mismatch +        // here because the original API was designed around pread and pwrite. +        if (offset != mCurrentOffset) { +            if (fseek(mFp, offset, SEEK_SET) != 0) { +                return false;              } -            compRemaining -= nextSize; - -            zstream.next_in = nextBuffer; -            zstream.avail_in = nextSize; +            mCurrentOffset = offset;          } -        /* uncompress the data */ -        zerr = inflate(&zstream, Z_NO_FLUSH); -        if (zerr != Z_OK && zerr != Z_STREAM_END) { -            ALOGD("zlib inflate call failed (zerr=%d)\n", zerr); -            goto z_bail; +        size_t read = fread(buf, 1, len, mFp); +        if (read != len) { +            return false;          } -        /* output buffer holds all, so no need to write the output */ -    } while (zerr == Z_OK); - -    assert(zerr == Z_STREAM_END);       /* other errors should've been caught */ - -    if ((long) zstream.total_out != uncompressedLen) { -        ALOGW("Size mismatch on inflated file (%ld vs %ld)\n", -            zstream.total_out, uncompressedLen); -        goto z_bail; +        mCurrentOffset += read; +        return true;      } -    // success! -    result = true; - -z_bail: -    inflateEnd(&zstream);        /* free up any allocated structures */ - -bail: -    return result; -} - -class FileReader { -public: -   explicit FileReader(FILE* fp) : -       mFp(fp), mReadBuf(new unsigned char[kReadBufSize]) -   { -   } +  private: +    FILE* mFp; +    mutable uint32_t mCurrentOffset; +}; -   ~FileReader() { -       delete[] mReadBuf; -   } +class FdReader : public zip_archive::Reader { +  public: +    explicit FdReader(int fd) : mFd(fd) { +    } -   long read(unsigned char** nextBuffer, long readSize) const { -       *nextBuffer = mReadBuf; -       return fread(mReadBuf, 1, readSize, mFp); -   } +    bool ReadAtOffset(uint8_t* buf, size_t len, uint32_t offset) const { +      return android::base::ReadFullyAtOffset(mFd, buf, len, static_cast<off_t>(offset)); +    } -   FILE* mFp; -   unsigned char* mReadBuf; +  private: +    const int mFd;  }; -class FdReader { -public: -   explicit FdReader(int fd) : -       mFd(fd), mReadBuf(new unsigned char[kReadBufSize]) -   { -   } +class BufferReader : public zip_archive::Reader { +  public: +    BufferReader(const void* input, size_t inputSize) : Reader(), +        mInput(reinterpret_cast<const uint8_t*>(input)), +        mInputSize(inputSize) { +    } -   ~FdReader() { -       delete[] mReadBuf; -   } +    bool ReadAtOffset(uint8_t* buf, size_t len, uint32_t offset) const { +        if (offset + len > mInputSize) { +            return false; +        } -   long read(unsigned char** nextBuffer, long readSize) const { -       *nextBuffer = mReadBuf; -       return TEMP_FAILURE_RETRY(::read(mFd, mReadBuf, readSize)); -   } +        memcpy(buf, mInput + offset, len); +        return true; +    } -   int mFd; -   unsigned char* mReadBuf; +  private: +    const uint8_t* mInput; +    const size_t mInputSize;  }; -class BufferReader { -public: -    BufferReader(void* input, size_t inputSize) : -        mInput(reinterpret_cast<unsigned char*>(input)), -        mInputSize(inputSize), -        mBufferReturned(false) -    { +class BufferWriter : public zip_archive::Writer { +  public: +    BufferWriter(void* output, size_t outputSize) : Writer(), +        mOutput(reinterpret_cast<uint8_t*>(output)), mOutputSize(outputSize), mBytesWritten(0) {      } -    long read(unsigned char** nextBuffer, long /*readSize*/) { -        if (!mBufferReturned) { -            mBufferReturned = true; -            *nextBuffer = mInput; -            return mInputSize; +    bool Append(uint8_t* buf, size_t bufSize) override { +        if (mBytesWritten + bufSize > mOutputSize) { +            return false;          } -        *nextBuffer = NULL; -        return 0; +        memcpy(mOutput + mBytesWritten, buf, bufSize); +        mBytesWritten += bufSize; +        return true;      } -    unsigned char* mInput; -    const size_t mInputSize; -    bool mBufferReturned; +  private: +    uint8_t* const mOutput; +    const size_t mOutputSize; +    size_t mBytesWritten;  };  /*static*/ bool ZipUtils::inflateToBuffer(FILE* fp, void* buf,      long uncompressedLen, long compressedLen)  {      FileReader reader(fp); -    return ::inflateToBuffer<FileReader>(reader, buf, -        uncompressedLen, compressedLen); +    BufferWriter writer(buf, uncompressedLen); +    return (zip_archive::Inflate(reader, compressedLen, uncompressedLen, &writer, nullptr) == 0);  }  /*static*/ bool ZipUtils::inflateToBuffer(int fd, void* buf,      long uncompressedLen, long compressedLen)  {      FdReader reader(fd); -    return ::inflateToBuffer<FdReader>(reader, buf, -        uncompressedLen, compressedLen); +    BufferWriter writer(buf, uncompressedLen); +    return (zip_archive::Inflate(reader, compressedLen, uncompressedLen, &writer, nullptr) == 0);  } -/*static*/ bool ZipUtils::inflateToBuffer(void* in, void* buf, +/*static*/ bool ZipUtils::inflateToBuffer(const void* in, void* buf,      long uncompressedLen, long compressedLen)  {      BufferReader reader(in, compressedLen); -    return ::inflateToBuffer<BufferReader>(reader, buf, -        uncompressedLen, compressedLen); +    BufferWriter writer(buf, uncompressedLen); +    return (zip_archive::Inflate(reader, compressedLen, uncompressedLen, &writer, nullptr) == 0);  } - +static inline unsigned long get4LE(const unsigned char* buf) { +    return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); +}  /*   * Look at the contents of a gzip archive.  We want to know where the @@ -275,7 +186,7 @@ public:      /* quick sanity checks */      if (method == EOF || flags == EOF)          return false; -    if (method != ZipFileRO::kCompressDeflated) +    if (method != kCompressDeflated)          return false;      /* skip over 4 bytes of mod time, 1 byte XFL, 1 byte OS */ diff --git a/libs/androidfw/include/androidfw/ZipUtils.h b/libs/androidfw/include/androidfw/ZipUtils.h index 55575d774522..4d35e992cc89 100644 --- a/libs/androidfw/include/androidfw/ZipUtils.h +++ b/libs/androidfw/include/androidfw/ZipUtils.h @@ -40,7 +40,7 @@ public:          long compressedLen);      static bool inflateToBuffer(int fd, void* buf, long uncompressedLen,          long compressedLen); -    static bool inflateToBuffer(void *in, void* buf, long uncompressedLen, +    static bool inflateToBuffer(const void *in, void* buf, long uncompressedLen,          long compressedLen);      /*  |