/* * Copyright (C) 2019 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. */ #pragma once #include #include #include #include #include "fastdeploy/proto/ApkEntry.pb.h" class ApkArchiveTester; // Manipulates an APK archive. Process it by mmaping it in order to minimize // I/Os. class ApkArchive { public: friend ApkArchiveTester; // A convenience struct to store the result of search operation when // locating the EoCDr, CDr, and Signature Block. struct Location { off_t offset = 0; off_t size = 0; bool valid = false; }; ApkArchive(const std::string& path); ~ApkArchive(); com::android::fastdeploy::APKDump ExtractMetadata(); // Parses the CDr starting from |input| and returns number of bytes consumed. // Extracts local file header offset, data size and calculates MD5 hash of the record. // 0 indicates invalid CDr. static size_t ParseCentralDirectoryRecord(const char* input, size_t size, std::string* md5Hash, int64_t* localFileHeaderOffset, int64_t* dataSize); // Calculates Local File Entry size including header using offset and data size from CDr. // 0 indicates invalid Local File Entry. size_t CalculateLocalFileEntrySize(int64_t localFileHeaderOffset, int64_t dataSize) const; private: std::string ReadMetadata(Location loc) const; // Retrieve the location of the Central Directory Record. Location GetCDLocation(); // Retrieve the location of the signature block starting from Central // Directory Record Location GetSignatureLocation(off_t cdRecordOffset); // Find the End of Central Directory Record, starting from the end of the // file. off_t FindEndOfCDRecord() const; // Find Central Directory Record, starting from the end of the file. Location FindCDRecord(const char* cursor); // Checks if the archive can be used. bool ready() const { return fd_ >= 0; } std::string path_; off_t size_; unique_fd fd_; };