Home | History | Annotate | Download | only in install
      1 /*
      2  * Copyright (C) 2019 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 #include "install/package.h"
     18 
     19 #include <string.h>
     20 #include <unistd.h>
     21 
     22 #include <android-base/file.h>
     23 #include <android-base/logging.h>
     24 #include <android-base/stringprintf.h>
     25 #include <android-base/unique_fd.h>
     26 
     27 #include "otautil/error_code.h"
     28 #include "otautil/sysutil.h"
     29 
     30 // This class wraps the package in memory, i.e. a memory mapped package, or a package loaded
     31 // to a string/vector.
     32 class MemoryPackage : public Package {
     33  public:
     34   // Constructs the class from a file. We will memory maps the file later.
     35   MemoryPackage(const std::string& path, std::unique_ptr<MemMapping> map,
     36                 const std::function<void(float)>& set_progress);
     37 
     38   // Constructs the class from the package bytes in |content|.
     39   MemoryPackage(std::vector<uint8_t> content, const std::function<void(float)>& set_progress);
     40 
     41   ~MemoryPackage() override;
     42 
     43   // Memory maps the package file if necessary. Initializes the start address and size of the
     44   // package.
     45   uint64_t GetPackageSize() const override {
     46     return package_size_;
     47   }
     48 
     49   bool ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) override;
     50 
     51   ZipArchiveHandle GetZipArchiveHandle() override;
     52 
     53   bool UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers, uint64_t start,
     54                           uint64_t length) override;
     55 
     56  private:
     57   const uint8_t* addr_;    // Start address of the package in memory.
     58   uint64_t package_size_;  // Package size in bytes.
     59 
     60   // The memory mapped package.
     61   std::unique_ptr<MemMapping> map_;
     62   // A copy of the package content, valid only if we create the class with the exact bytes of
     63   // the package.
     64   std::vector<uint8_t> package_content_;
     65   // The physical path to the package, empty if we create the class with the package content.
     66   std::string path_;
     67 
     68   // The ZipArchiveHandle of the package.
     69   ZipArchiveHandle zip_handle_;
     70 };
     71 
     72 void Package::SetProgress(float progress) {
     73   if (set_progress_) {
     74     set_progress_(progress);
     75   }
     76 }
     77 
     78 class FilePackage : public Package {
     79  public:
     80   FilePackage(android::base::unique_fd&& fd, uint64_t file_size, const std::string& path,
     81               const std::function<void(float)>& set_progress);
     82 
     83   ~FilePackage() override;
     84 
     85   uint64_t GetPackageSize() const override {
     86     return package_size_;
     87   }
     88 
     89   bool ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) override;
     90 
     91   ZipArchiveHandle GetZipArchiveHandle() override;
     92 
     93   bool UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers, uint64_t start,
     94                           uint64_t length) override;
     95 
     96  private:
     97   android::base::unique_fd fd_;  // The underlying fd to the open package.
     98   uint64_t package_size_;
     99   std::string path_;  // The physical path to the package.
    100 
    101   ZipArchiveHandle zip_handle_;
    102 };
    103 
    104 std::unique_ptr<Package> Package::CreateMemoryPackage(
    105     const std::string& path, const std::function<void(float)>& set_progress) {
    106   std::unique_ptr<MemMapping> mmap = std::make_unique<MemMapping>();
    107   if (!mmap->MapFile(path)) {
    108     LOG(ERROR) << "failed to map file";
    109     return nullptr;
    110   }
    111 
    112   return std::make_unique<MemoryPackage>(path, std::move(mmap), set_progress);
    113 }
    114 
    115 std::unique_ptr<Package> Package::CreateFilePackage(
    116     const std::string& path, const std::function<void(float)>& set_progress) {
    117   android::base::unique_fd fd(open(path.c_str(), O_RDONLY));
    118   if (fd == -1) {
    119     PLOG(ERROR) << "Failed to open " << path;
    120     return nullptr;
    121   }
    122 
    123   off64_t file_size = lseek64(fd.get(), 0, SEEK_END);
    124   if (file_size == -1) {
    125     PLOG(ERROR) << "Failed to get the package size";
    126     return nullptr;
    127   }
    128 
    129   return std::make_unique<FilePackage>(std::move(fd), file_size, path, set_progress);
    130 }
    131 
    132 std::unique_ptr<Package> Package::CreateMemoryPackage(
    133     std::vector<uint8_t> content, const std::function<void(float)>& set_progress) {
    134   return std::make_unique<MemoryPackage>(std::move(content), set_progress);
    135 }
    136 
    137 MemoryPackage::MemoryPackage(const std::string& path, std::unique_ptr<MemMapping> map,
    138                              const std::function<void(float)>& set_progress)
    139     : map_(std::move(map)), path_(path), zip_handle_(nullptr) {
    140   addr_ = map_->addr;
    141   package_size_ = map_->length;
    142   set_progress_ = set_progress;
    143 }
    144 
    145 MemoryPackage::MemoryPackage(std::vector<uint8_t> content,
    146                              const std::function<void(float)>& set_progress)
    147     : package_content_(std::move(content)), zip_handle_(nullptr) {
    148   CHECK(!package_content_.empty());
    149   addr_ = package_content_.data();
    150   package_size_ = package_content_.size();
    151   set_progress_ = set_progress;
    152 }
    153 
    154 MemoryPackage::~MemoryPackage() {
    155   if (zip_handle_) {
    156     CloseArchive(zip_handle_);
    157   }
    158 }
    159 
    160 bool MemoryPackage::ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) {
    161   if (byte_count > package_size_ || offset > package_size_ - byte_count) {
    162     LOG(ERROR) << "Out of bound read, offset: " << offset << ", size: " << byte_count
    163                << ", total package_size: " << package_size_;
    164     return false;
    165   }
    166   memcpy(buffer, addr_ + offset, byte_count);
    167   return true;
    168 }
    169 
    170 bool MemoryPackage::UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers,
    171                                        uint64_t start, uint64_t length) {
    172   if (length > package_size_ || start > package_size_ - length) {
    173     LOG(ERROR) << "Out of bound read, offset: " << start << ", size: " << length
    174                << ", total package_size: " << package_size_;
    175     return false;
    176   }
    177 
    178   for (const auto& hasher : hashers) {
    179     hasher(addr_ + start, length);
    180   }
    181   return true;
    182 }
    183 
    184 ZipArchiveHandle MemoryPackage::GetZipArchiveHandle() {
    185   if (zip_handle_) {
    186     return zip_handle_;
    187   }
    188 
    189   if (auto err = OpenArchiveFromMemory(const_cast<uint8_t*>(addr_), package_size_, path_.c_str(),
    190                                        &zip_handle_);
    191       err != 0) {
    192     LOG(ERROR) << "Can't open package" << path_ << " : " << ErrorCodeString(err);
    193     return nullptr;
    194   }
    195 
    196   return zip_handle_;
    197 }
    198 
    199 FilePackage::FilePackage(android::base::unique_fd&& fd, uint64_t file_size, const std::string& path,
    200                          const std::function<void(float)>& set_progress)
    201     : fd_(std::move(fd)), package_size_(file_size), path_(path), zip_handle_(nullptr) {
    202   set_progress_ = set_progress;
    203 }
    204 
    205 FilePackage::~FilePackage() {
    206   if (zip_handle_) {
    207     CloseArchive(zip_handle_);
    208   }
    209 }
    210 
    211 bool FilePackage::ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) {
    212   if (byte_count > package_size_ || offset > package_size_ - byte_count) {
    213     LOG(ERROR) << "Out of bound read, offset: " << offset << ", size: " << byte_count
    214                << ", total package_size: " << package_size_;
    215     return false;
    216   }
    217 
    218   if (!android::base::ReadFullyAtOffset(fd_.get(), buffer, byte_count, offset)) {
    219     PLOG(ERROR) << "Failed to read " << byte_count << " bytes data at offset " << offset;
    220     return false;
    221   }
    222 
    223   return true;
    224 }
    225 
    226 bool FilePackage::UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers,
    227                                      uint64_t start, uint64_t length) {
    228   if (length > package_size_ || start > package_size_ - length) {
    229     LOG(ERROR) << "Out of bound read, offset: " << start << ", size: " << length
    230                << ", total package_size: " << package_size_;
    231     return false;
    232   }
    233 
    234   uint64_t so_far = 0;
    235   while (so_far < length) {
    236     uint64_t read_size = std::min<uint64_t>(length - so_far, 16 * MiB);
    237     std::vector<uint8_t> buffer(read_size);
    238     if (!ReadFullyAtOffset(buffer.data(), read_size, start + so_far)) {
    239       return false;
    240     }
    241 
    242     for (const auto& hasher : hashers) {
    243       hasher(buffer.data(), read_size);
    244     }
    245     so_far += read_size;
    246   }
    247 
    248   return true;
    249 }
    250 
    251 ZipArchiveHandle FilePackage::GetZipArchiveHandle() {
    252   if (zip_handle_) {
    253     return zip_handle_;
    254   }
    255 
    256   if (auto err = OpenArchiveFd(fd_.get(), path_.c_str(), &zip_handle_); err != 0) {
    257     LOG(ERROR) << "Can't open package" << path_ << " : " << ErrorCodeString(err);
    258     return nullptr;
    259   }
    260 
    261   return zip_handle_;
    262 }
    263