blob: 8ff952baab2dc28450d3e94b1a3eaffedfea655b [file] [log] [blame]
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ART_RUNTIME_ZIP_ARCHIVE_H_
#define ART_RUNTIME_ZIP_ARCHIVE_H_
#include <stdint.h>
#include <zlib.h>
#include <string>
#include "base/logging.h"
#include "base/stringpiece.h"
#include "base/unix_file/random_access_file.h"
#include "globals.h"
#include "mem_map.h"
#include "os.h"
#include "safe_map.h"
#include "UniquePtr.h"
namespace art {
class ZipArchive;
class MemMap;
class ZipEntry {
public:
bool ExtractToFile(File& file, std::string* error_msg);
bool ExtractToMemory(uint8_t* begin, size_t size, std::string* error_msg);
MemMap* ExtractToMemMap(const char* entry_filename, std::string* error_msg);
uint32_t GetUncompressedLength();
uint32_t GetCrc32();
private:
ZipEntry(const ZipArchive* zip_archive, const byte* ptr) : zip_archive_(zip_archive), ptr_(ptr) {}
// Zip compression methods
enum {
kCompressStored = 0, // no compression
kCompressDeflated = 8, // standard deflate
};
// kCompressStored, kCompressDeflated, ...
uint16_t GetCompressionMethod();
uint32_t GetCompressedLength();
// returns -1 on error
off64_t GetDataOffset();
const ZipArchive* zip_archive_;
// pointer to zip entry within central directory
const byte* ptr_;
friend class ZipArchive;
DISALLOW_COPY_AND_ASSIGN(ZipEntry);
};
class ZipArchive {
public:
// Zip file constants.
static const uint32_t kEOCDSignature = 0x06054b50;
static const int32_t kEOCDLen = 22;
static const int32_t kEOCDDiskNumber = 4; // number of the current disk
static const int32_t kEOCDDiskNumberForCD = 6; // disk number with the Central Directory
static const int32_t kEOCDNumEntries = 8; // offset to #of entries in file
static const int32_t kEOCDTotalNumEntries = 10; // offset to total #of entries in spanned archives
static const int32_t kEOCDSize = 12; // size of the central directory
static const int32_t kEOCDFileOffset = 16; // offset to central directory
static const int32_t kEOCDCommentSize = 20; // offset to the length of the file comment
static const int32_t kMaxCommentLen = 65535; // longest possible in uint16_t
static const int32_t kMaxEOCDSearch = (kMaxCommentLen + kEOCDLen);
static const uint32_t kLFHSignature = 0x04034b50;
static const int32_t kLFHLen = 30; // excluding variable-len fields
static const int32_t kLFHGPBFlags = 6; // offset to GPB flags
static const int32_t kLFHNameLen = 26; // offset to filename length
static const int32_t kLFHExtraLen = 28; // offset to extra length
static const uint32_t kCDESignature = 0x02014b50;
static const int32_t kCDELen = 46; // excluding variable-len fields
static const int32_t kCDEGPBFlags = 8; // offset to GPB flags
static const int32_t kCDEMethod = 10; // offset to compression method
static const int32_t kCDEModWhen = 12; // offset to modification timestamp
static const int32_t kCDECRC = 16; // offset to entry CRC
static const int32_t kCDECompLen = 20; // offset to compressed length
static const int32_t kCDEUncompLen = 24; // offset to uncompressed length
static const int32_t kCDENameLen = 28; // offset to filename length
static const int32_t kCDEExtraLen = 30; // offset to extra length
static const int32_t kCDECommentLen = 32; // offset to comment length
static const int32_t kCDELocalOffset = 42; // offset to local hdr
// General Purpose Bit Flag
static const int32_t kGPFEncryptedFlag = (1 << 0);
static const int32_t kGPFUnsupportedMask = (kGPFEncryptedFlag);
// return new ZipArchive instance on success, NULL on error.
static ZipArchive* Open(const char* filename, std::string* error_msg);
static ZipArchive* OpenFromFd(int fd, const char* filename, std::string* error_msg);
ZipEntry* Find(const char* name) const;
~ZipArchive() {
Close();
}
private:
explicit ZipArchive(int fd, const char* filename)
: fd_(fd), num_entries_(0), dir_offset_(0), filename_(filename) {}
bool MapCentralDirectory(std::string* error_msg);
bool Parse(std::string* error_msg);
void Close();
std::string ErrorStringPrintf(const char* fmt, ...)
__attribute__((__format__(__printf__, 2, 3))) COLD_ATTR;
int fd_;
uint16_t num_entries_;
off64_t dir_offset_;
UniquePtr<MemMap> dir_map_;
typedef SafeMap<StringPiece, const byte*> DirEntries;
DirEntries dir_entries_;
// Containing file for error reporting.
const std::string filename_;
friend class ZipEntry;
DISALLOW_COPY_AND_ASSIGN(ZipArchive);
};
} // namespace art
#endif // ART_RUNTIME_ZIP_ARCHIVE_H_