blob: 86fc0647d179b7378a8830806f9a5e3fc98763a0 [file] [log] [blame]
xunchangf07ed2e2019-02-25 14:14:01 -08001/*
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
xunchang24788852019-03-22 16:08:52 -070017#include "install/package.h"
xunchangf07ed2e2019-02-25 14:14:01 -080018
19#include <string.h>
xunchang37304f32019-03-12 12:40:14 -070020#include <unistd.h>
xunchangf07ed2e2019-02-25 14:14:01 -080021
xunchang37304f32019-03-12 12:40:14 -070022#include <android-base/file.h>
xunchangf07ed2e2019-02-25 14:14:01 -080023#include <android-base/logging.h>
24#include <android-base/stringprintf.h>
xunchang37304f32019-03-12 12:40:14 -070025#include <android-base/unique_fd.h>
xunchangf07ed2e2019-02-25 14:14:01 -080026
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.
32class 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
Tianjie Xu980f92e2019-06-11 15:43:43 -070043 PackageType GetType() const override {
44 return PackageType::kMemory;
45 }
46
xunchangf07ed2e2019-02-25 14:14:01 -080047 // Memory maps the package file if necessary. Initializes the start address and size of the
48 // package.
49 uint64_t GetPackageSize() const override {
50 return package_size_;
51 }
52
Tianjie Xu980f92e2019-06-11 15:43:43 -070053 std::string GetPath() const override {
54 return path_;
55 }
56
xunchangf07ed2e2019-02-25 14:14:01 -080057 bool ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) override;
58
59 ZipArchiveHandle GetZipArchiveHandle() override;
60
61 bool UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers, uint64_t start,
62 uint64_t length) override;
63
64 private:
65 const uint8_t* addr_; // Start address of the package in memory.
66 uint64_t package_size_; // Package size in bytes.
67
68 // The memory mapped package.
69 std::unique_ptr<MemMapping> map_;
70 // A copy of the package content, valid only if we create the class with the exact bytes of
71 // the package.
72 std::vector<uint8_t> package_content_;
73 // The physical path to the package, empty if we create the class with the package content.
74 std::string path_;
75
76 // The ZipArchiveHandle of the package.
77 ZipArchiveHandle zip_handle_;
78};
79
xunchangf07ed2e2019-02-25 14:14:01 -080080void Package::SetProgress(float progress) {
81 if (set_progress_) {
82 set_progress_(progress);
83 }
84}
85
xunchang37304f32019-03-12 12:40:14 -070086class FilePackage : public Package {
87 public:
88 FilePackage(android::base::unique_fd&& fd, uint64_t file_size, const std::string& path,
89 const std::function<void(float)>& set_progress);
90
91 ~FilePackage() override;
92
Tianjie Xu980f92e2019-06-11 15:43:43 -070093 PackageType GetType() const override {
94 return PackageType::kFile;
95 }
96
xunchang37304f32019-03-12 12:40:14 -070097 uint64_t GetPackageSize() const override {
98 return package_size_;
99 }
100
Tianjie Xu980f92e2019-06-11 15:43:43 -0700101 std::string GetPath() const override {
102 return path_;
103 }
104
xunchang37304f32019-03-12 12:40:14 -0700105 bool ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) override;
106
107 ZipArchiveHandle GetZipArchiveHandle() override;
108
109 bool UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers, uint64_t start,
110 uint64_t length) override;
111
112 private:
113 android::base::unique_fd fd_; // The underlying fd to the open package.
114 uint64_t package_size_;
115 std::string path_; // The physical path to the package.
116
117 ZipArchiveHandle zip_handle_;
118};
119
xunchangf07ed2e2019-02-25 14:14:01 -0800120std::unique_ptr<Package> Package::CreateMemoryPackage(
121 const std::string& path, const std::function<void(float)>& set_progress) {
122 std::unique_ptr<MemMapping> mmap = std::make_unique<MemMapping>();
123 if (!mmap->MapFile(path)) {
124 LOG(ERROR) << "failed to map file";
125 return nullptr;
126 }
127
128 return std::make_unique<MemoryPackage>(path, std::move(mmap), set_progress);
129}
130
xunchang37304f32019-03-12 12:40:14 -0700131std::unique_ptr<Package> Package::CreateFilePackage(
132 const std::string& path, const std::function<void(float)>& set_progress) {
133 android::base::unique_fd fd(open(path.c_str(), O_RDONLY));
134 if (fd == -1) {
135 PLOG(ERROR) << "Failed to open " << path;
136 return nullptr;
137 }
138
139 off64_t file_size = lseek64(fd.get(), 0, SEEK_END);
140 if (file_size == -1) {
141 PLOG(ERROR) << "Failed to get the package size";
142 return nullptr;
143 }
144
145 return std::make_unique<FilePackage>(std::move(fd), file_size, path, set_progress);
146}
147
xunchangf07ed2e2019-02-25 14:14:01 -0800148std::unique_ptr<Package> Package::CreateMemoryPackage(
149 std::vector<uint8_t> content, const std::function<void(float)>& set_progress) {
150 return std::make_unique<MemoryPackage>(std::move(content), set_progress);
151}
152
153MemoryPackage::MemoryPackage(const std::string& path, std::unique_ptr<MemMapping> map,
154 const std::function<void(float)>& set_progress)
155 : map_(std::move(map)), path_(path), zip_handle_(nullptr) {
156 addr_ = map_->addr;
157 package_size_ = map_->length;
158 set_progress_ = set_progress;
159}
160
161MemoryPackage::MemoryPackage(std::vector<uint8_t> content,
162 const std::function<void(float)>& set_progress)
163 : package_content_(std::move(content)), zip_handle_(nullptr) {
164 CHECK(!package_content_.empty());
165 addr_ = package_content_.data();
166 package_size_ = package_content_.size();
167 set_progress_ = set_progress;
168}
169
170MemoryPackage::~MemoryPackage() {
171 if (zip_handle_) {
172 CloseArchive(zip_handle_);
173 }
174}
175
176bool MemoryPackage::ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) {
177 if (byte_count > package_size_ || offset > package_size_ - byte_count) {
178 LOG(ERROR) << "Out of bound read, offset: " << offset << ", size: " << byte_count
179 << ", total package_size: " << package_size_;
180 return false;
181 }
182 memcpy(buffer, addr_ + offset, byte_count);
183 return true;
184}
185
186bool MemoryPackage::UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers,
187 uint64_t start, uint64_t length) {
188 if (length > package_size_ || start > package_size_ - length) {
189 LOG(ERROR) << "Out of bound read, offset: " << start << ", size: " << length
190 << ", total package_size: " << package_size_;
191 return false;
192 }
193
194 for (const auto& hasher : hashers) {
195 hasher(addr_ + start, length);
196 }
197 return true;
198}
199
200ZipArchiveHandle MemoryPackage::GetZipArchiveHandle() {
201 if (zip_handle_) {
202 return zip_handle_;
203 }
204
205 if (auto err = OpenArchiveFromMemory(const_cast<uint8_t*>(addr_), package_size_, path_.c_str(),
206 &zip_handle_);
207 err != 0) {
208 LOG(ERROR) << "Can't open package" << path_ << " : " << ErrorCodeString(err);
209 return nullptr;
210 }
211
212 return zip_handle_;
213}
xunchang37304f32019-03-12 12:40:14 -0700214
215FilePackage::FilePackage(android::base::unique_fd&& fd, uint64_t file_size, const std::string& path,
216 const std::function<void(float)>& set_progress)
217 : fd_(std::move(fd)), package_size_(file_size), path_(path), zip_handle_(nullptr) {
218 set_progress_ = set_progress;
219}
220
221FilePackage::~FilePackage() {
222 if (zip_handle_) {
223 CloseArchive(zip_handle_);
224 }
225}
226
227bool FilePackage::ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) {
228 if (byte_count > package_size_ || offset > package_size_ - byte_count) {
229 LOG(ERROR) << "Out of bound read, offset: " << offset << ", size: " << byte_count
230 << ", total package_size: " << package_size_;
231 return false;
232 }
233
234 if (!android::base::ReadFullyAtOffset(fd_.get(), buffer, byte_count, offset)) {
235 PLOG(ERROR) << "Failed to read " << byte_count << " bytes data at offset " << offset;
236 return false;
237 }
238
239 return true;
240}
241
242bool FilePackage::UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers,
243 uint64_t start, uint64_t length) {
244 if (length > package_size_ || start > package_size_ - length) {
245 LOG(ERROR) << "Out of bound read, offset: " << start << ", size: " << length
246 << ", total package_size: " << package_size_;
247 return false;
248 }
249
250 uint64_t so_far = 0;
251 while (so_far < length) {
252 uint64_t read_size = std::min<uint64_t>(length - so_far, 16 * MiB);
253 std::vector<uint8_t> buffer(read_size);
254 if (!ReadFullyAtOffset(buffer.data(), read_size, start + so_far)) {
255 return false;
256 }
257
258 for (const auto& hasher : hashers) {
259 hasher(buffer.data(), read_size);
260 }
261 so_far += read_size;
262 }
263
264 return true;
265}
266
267ZipArchiveHandle FilePackage::GetZipArchiveHandle() {
268 if (zip_handle_) {
269 return zip_handle_;
270 }
271
Tianjie Xu980f92e2019-06-11 15:43:43 -0700272 if (auto err = OpenArchiveFd(fd_.get(), path_.c_str(), &zip_handle_, false); err != 0) {
xunchang37304f32019-03-12 12:40:14 -0700273 LOG(ERROR) << "Can't open package" << path_ << " : " << ErrorCodeString(err);
274 return nullptr;
275 }
276
277 return zip_handle_;
278}