blob: d40427859a1098632f94af3cf8f5e75881728539 [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
17#include "package.h"
18
19#include <string.h>
20
21#include <android-base/logging.h>
22#include <android-base/stringprintf.h>
23#include <openssl/sha.h>
24
25#include "otautil/error_code.h"
26#include "otautil/sysutil.h"
27
28// This class wraps the package in memory, i.e. a memory mapped package, or a package loaded
29// to a string/vector.
30class MemoryPackage : public Package {
31 public:
32 // Constructs the class from a file. We will memory maps the file later.
33 MemoryPackage(const std::string& path, std::unique_ptr<MemMapping> map,
34 const std::function<void(float)>& set_progress);
35
36 // Constructs the class from the package bytes in |content|.
37 MemoryPackage(std::vector<uint8_t> content, const std::function<void(float)>& set_progress);
38
39 ~MemoryPackage() override;
40
41 // Memory maps the package file if necessary. Initializes the start address and size of the
42 // package.
43 uint64_t GetPackageSize() const override {
44 return package_size_;
45 }
46
47 bool ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) override;
48
49 ZipArchiveHandle GetZipArchiveHandle() override;
50
51 bool UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers, uint64_t start,
52 uint64_t length) override;
53
54 private:
55 const uint8_t* addr_; // Start address of the package in memory.
56 uint64_t package_size_; // Package size in bytes.
57
58 // The memory mapped package.
59 std::unique_ptr<MemMapping> map_;
60 // A copy of the package content, valid only if we create the class with the exact bytes of
61 // the package.
62 std::vector<uint8_t> package_content_;
63 // The physical path to the package, empty if we create the class with the package content.
64 std::string path_;
65
66 // The ZipArchiveHandle of the package.
67 ZipArchiveHandle zip_handle_;
68};
69
70// TODO(xunchang) Implement the PackageFromFd.
71
72void Package::SetProgress(float progress) {
73 if (set_progress_) {
74 set_progress_(progress);
75 }
76}
77
78std::unique_ptr<Package> Package::CreateMemoryPackage(
79 const std::string& path, const std::function<void(float)>& set_progress) {
80 std::unique_ptr<MemMapping> mmap = std::make_unique<MemMapping>();
81 if (!mmap->MapFile(path)) {
82 LOG(ERROR) << "failed to map file";
83 return nullptr;
84 }
85
86 return std::make_unique<MemoryPackage>(path, std::move(mmap), set_progress);
87}
88
89std::unique_ptr<Package> Package::CreateMemoryPackage(
90 std::vector<uint8_t> content, const std::function<void(float)>& set_progress) {
91 return std::make_unique<MemoryPackage>(std::move(content), set_progress);
92}
93
94MemoryPackage::MemoryPackage(const std::string& path, std::unique_ptr<MemMapping> map,
95 const std::function<void(float)>& set_progress)
96 : map_(std::move(map)), path_(path), zip_handle_(nullptr) {
97 addr_ = map_->addr;
98 package_size_ = map_->length;
99 set_progress_ = set_progress;
100}
101
102MemoryPackage::MemoryPackage(std::vector<uint8_t> content,
103 const std::function<void(float)>& set_progress)
104 : package_content_(std::move(content)), zip_handle_(nullptr) {
105 CHECK(!package_content_.empty());
106 addr_ = package_content_.data();
107 package_size_ = package_content_.size();
108 set_progress_ = set_progress;
109}
110
111MemoryPackage::~MemoryPackage() {
112 if (zip_handle_) {
113 CloseArchive(zip_handle_);
114 }
115}
116
117bool MemoryPackage::ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) {
118 if (byte_count > package_size_ || offset > package_size_ - byte_count) {
119 LOG(ERROR) << "Out of bound read, offset: " << offset << ", size: " << byte_count
120 << ", total package_size: " << package_size_;
121 return false;
122 }
123 memcpy(buffer, addr_ + offset, byte_count);
124 return true;
125}
126
127bool MemoryPackage::UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers,
128 uint64_t start, uint64_t length) {
129 if (length > package_size_ || start > package_size_ - length) {
130 LOG(ERROR) << "Out of bound read, offset: " << start << ", size: " << length
131 << ", total package_size: " << package_size_;
132 return false;
133 }
134
135 for (const auto& hasher : hashers) {
136 hasher(addr_ + start, length);
137 }
138 return true;
139}
140
141ZipArchiveHandle MemoryPackage::GetZipArchiveHandle() {
142 if (zip_handle_) {
143 return zip_handle_;
144 }
145
146 if (auto err = OpenArchiveFromMemory(const_cast<uint8_t*>(addr_), package_size_, path_.c_str(),
147 &zip_handle_);
148 err != 0) {
149 LOG(ERROR) << "Can't open package" << path_ << " : " << ErrorCodeString(err);
150 return nullptr;
151 }
152
153 return zip_handle_;
154}