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