1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "blocks_patch.h"
17 #include <cstdio>
18 #include <iostream>
19 #include <vector>
20 #include "diffpatch.h"
21
22 using namespace Hpackage;
23 using namespace std;
24
25 namespace UpdatePatch {
26 #define PATCH_MIN std::char_traits<char>::length(BSDIFF_MAGIC) + sizeof(int64_t) * 3
27 #define GET_BYTE_FROM_BUFFER(v, index, buffer) (y) = (y) * 256; (y) += buffer[index]
28 constexpr uint8_t BUFFER_MASK = 0x80;
29
ReadLE64(const uint8_t * buffer)30 static int64_t ReadLE64(const uint8_t *buffer)
31 {
32 if (buffer == nullptr) {
33 return 0;
34 }
35 int64_t y = 0;
36 int32_t index = static_cast<int32_t>(sizeof(int64_t)) - 1;
37 y = buffer[index] & static_cast<uint8_t>(~BUFFER_MASK);
38 index--;
39 GET_BYTE_FROM_BUFFER(y, index, buffer);
40 index--;
41 GET_BYTE_FROM_BUFFER(y, index, buffer);
42 index--;
43 GET_BYTE_FROM_BUFFER(y, index, buffer);
44 index--;
45 GET_BYTE_FROM_BUFFER(y, index, buffer);
46 index--;
47 GET_BYTE_FROM_BUFFER(y, index, buffer);
48 index--;
49 GET_BYTE_FROM_BUFFER(y, index, buffer);
50 index--;
51 GET_BYTE_FROM_BUFFER(y, index, buffer);
52
53 index = static_cast<int32_t>(sizeof(int64_t));
54 if (buffer[index - 1] & BUFFER_MASK) {
55 y = -y;
56 }
57 return y;
58 }
59
ApplyPatch()60 int32_t BlocksPatch::ApplyPatch()
61 {
62 PATCH_LOGI("BlocksPatch::ApplyPatch");
63 int64_t controlDataSize = 0;
64 int64_t diffDataSize = 0;
65 int32_t ret = ReadHeader(controlDataSize, diffDataSize, newSize_);
66 if (ret != 0) {
67 PATCH_LOGE("Failed to read header ");
68 return -1;
69 }
70
71 while (newOffset_ < newSize_) {
72 ControlData ctrlData {};
73 ret = ReadControlData(ctrlData);
74 if (ret != 0) {
75 PATCH_LOGE("Failed to read control data");
76 return ret;
77 }
78 if (newOffset_ + ctrlData.diffLength > newSize_) {
79 PATCH_LOGE("Failed to check new offset %ld %zu", ctrlData.diffLength, newOffset_);
80 return PATCH_INVALID_PATCH;
81 }
82
83 ret = RestoreDiffData(ctrlData);
84 if (ret != 0) {
85 PATCH_LOGE("Failed to read diff data");
86 return ret;
87 }
88 oldOffset_ += ctrlData.diffLength;
89 newOffset_ += ctrlData.diffLength;
90 if (newOffset_ + ctrlData.extraLength > newSize_) {
91 PATCH_LOGE("Failed to check new offset %ld %zu", ctrlData.diffLength, newOffset_);
92 return PATCH_INVALID_PATCH;
93 }
94
95 ret = RestoreExtraData(ctrlData);
96 if (ret != 0) {
97 PATCH_LOGE("Failed to read extra data");
98 return ret;
99 }
100
101 newOffset_ += ctrlData.extraLength;
102 oldOffset_ += ctrlData.offsetIncrement;
103 }
104 controlDataReader_->Close();
105 diffDataReader_->Close();
106 extraDataReader_->Close();
107 PATCH_LOGI("BlocksPatch::ApplyPatch %zu newSize: %zu", newOffset_, newSize_);
108 return 0;
109 }
110
ReadHeader(int64_t & controlDataSize,int64_t & diffDataSize,int64_t & newSize)111 int32_t BlocksPatch::ReadHeader(int64_t &controlDataSize, int64_t &diffDataSize, int64_t &newSize)
112 {
113 PATCH_LOGI("BlocksPatch::ApplyPatch %zu %zu", patchInfo_.start, patchInfo_.length);
114 if (patchInfo_.buffer == nullptr || patchInfo_.length <= PATCH_MIN) {
115 PATCH_LOGE("Invalid parm");
116 return -1;
117 }
118 BlockBuffer patchData = {patchInfo_.buffer + patchInfo_.start, patchInfo_.length - patchInfo_.start};
119 PATCH_LOGI("Restore patch hash %zu %s",
120 patchInfo_.length - patchInfo_.start, GeneraterBufferHash(patchData).c_str());
121 uint8_t *header = patchInfo_.buffer + patchInfo_.start;
122 // Compare header
123 if (memcmp(header, BSDIFF_MAGIC, std::char_traits<char>::length(BSDIFF_MAGIC)) != 0) {
124 PATCH_LOGE("Corrupt patch, patch head != BSDIFF40");
125 return -1;
126 }
127
128 /* Read lengths from header */
129 size_t offset = std::char_traits<char>::length(BSDIFF_MAGIC);
130 controlDataSize = ReadLE64(header + offset);
131 offset += sizeof(int64_t);
132 diffDataSize = ReadLE64(header + offset);
133 offset += sizeof(int64_t);
134 newSize = ReadLE64(header + offset);
135 offset += sizeof(int64_t);
136
137 if (controlDataSize < 0) {
138 PATCH_LOGE("Invalid control data size");
139 return -1;
140 }
141 if (newSize < 0) {
142 PATCH_LOGE("Invalid new data size");
143 return -1;
144 }
145 PATCH_CHECK(diffDataSize >= 0 && (diffDataSize + controlDataSize) <= static_cast<int64_t>(patchInfo_.length),
146 return -1, "Invalid patch data size");
147
148 BlockBuffer patchBuffer = {header, patchInfo_.length - patchInfo_.start};
149 controlDataReader_.reset(new BZip2BufferReadAdapter(offset, static_cast<size_t>(controlDataSize), patchBuffer));
150 offset += static_cast<size_t>(controlDataSize);
151 diffDataReader_.reset(new BZip2BufferReadAdapter(offset, static_cast<size_t>(diffDataSize), patchBuffer));
152 offset += static_cast<size_t>(diffDataSize);
153 extraDataReader_.reset(new BZip2BufferReadAdapter(offset,
154 patchInfo_.length - patchInfo_.start - offset, patchBuffer));
155 PATCH_CHECK(controlDataReader_ != nullptr && diffDataReader_ != nullptr && extraDataReader_ != nullptr,
156 return -1, "Failed to create reader");
157 controlDataReader_->Open();
158 diffDataReader_->Open();
159 extraDataReader_->Open();
160 return 0;
161 }
162
ReadControlData(ControlData & ctrlData)163 int32_t BlocksPatch::ReadControlData(ControlData &ctrlData)
164 {
165 std::vector<uint8_t> data(sizeof(int64_t), 0);
166 BlockBuffer info = {data.data(), sizeof(int64_t)};
167 int32_t ret = controlDataReader_->ReadData(info);
168 if (ret != 0) {
169 PATCH_LOGE("Failed to read diffLength");
170 return ret;
171 }
172 ctrlData.diffLength = ReadLE64(info.buffer);
173 ret = controlDataReader_->ReadData(info);
174 if (ret != 0) {
175 PATCH_LOGE("Failed to read extraLength");
176 return ret;
177 }
178 ctrlData.extraLength = ReadLE64(info.buffer);
179 ret = controlDataReader_->ReadData(info);
180 if (ret != 0) {
181 PATCH_LOGE("Failed to read offsetIncrement");
182 return ret;
183 }
184 ctrlData.offsetIncrement = ReadLE64(info.buffer);
185 return 0;
186 }
187
ReadHeader(int64_t & controlDataSize,int64_t & diffDataSize,int64_t & newSize)188 int32_t BlocksBufferPatch::ReadHeader(int64_t &controlDataSize, int64_t &diffDataSize, int64_t &newSize)
189 {
190 int32_t ret = BlocksPatch::ReadHeader(controlDataSize, diffDataSize, newSize);
191 if (ret != 0) {
192 PATCH_LOGE("Failed to read header");
193 return -1;
194 }
195 PATCH_LOGI("ReadHeader controlDataSize: %ld %ld %ld", controlDataSize, diffDataSize, newSize);
196 newData_.resize(newSize);
197 return 0;
198 }
199
RestoreDiffData(const ControlData & ctrlData)200 int32_t BlocksBufferPatch::RestoreDiffData(const ControlData &ctrlData)
201 {
202 if (ctrlData.diffLength <= 0) {
203 return 0;
204 }
205 BlockBuffer diffData = {newData_.data() + newOffset_, static_cast<size_t>(ctrlData.diffLength)};
206 int32_t ret = diffDataReader_->ReadData(diffData);
207 if (ret != 0) {
208 PATCH_LOGE("Failed to read diff data");
209 return ret;
210 }
211
212 for (int64_t i = 0; i < ctrlData.diffLength; i++) {
213 if (((oldOffset_ + i) >= 0) && (static_cast<size_t>(oldOffset_ + i) < oldInfo_.length)) {
214 newData_[newOffset_ + i] += oldInfo_.buffer[oldOffset_ + i];
215 }
216 }
217 return 0;
218 }
219
RestoreExtraData(const ControlData & ctrlData)220 int32_t BlocksBufferPatch::RestoreExtraData(const ControlData &ctrlData)
221 {
222 if (ctrlData.extraLength <= 0) {
223 return 0;
224 }
225 BlockBuffer extraData = {newData_.data() + newOffset_, static_cast<size_t>(ctrlData.extraLength)};
226 int32_t ret = extraDataReader_->ReadData(extraData);
227 if (ret != 0) {
228 PATCH_LOGE("Failed to read extra data");
229 return ret;
230 }
231 return 0;
232 }
233
RestoreDiffData(const ControlData & ctrlData)234 int32_t BlocksStreamPatch::RestoreDiffData(const ControlData &ctrlData)
235 {
236 if (ctrlData.diffLength <= 0) {
237 return 0;
238 }
239 std::vector<uint8_t> diffData(ctrlData.diffLength);
240 BlockBuffer diffBuffer = {diffData.data(), diffData.size()};
241 int32_t ret = diffDataReader_->ReadData(diffBuffer);
242 if (ret != 0) {
243 PATCH_LOGE("Failed to read diff data");
244 return ret;
245 }
246
247 size_t oldOffset = static_cast<size_t>(oldOffset_);
248 size_t oldLength = stream_->GetFileLength();
249 PkgBuffer buffer {};
250 if (stream_->GetStreamType() == PkgStream::PkgStreamType_MemoryMap ||
251 stream_->GetStreamType() == PkgStream::PkgStreamType_Buffer) {
252 ret = stream_->GetBuffer(buffer);
253 if (ret != 0) {
254 PATCH_LOGE("Failed to get old buffer");
255 return ret;
256 }
257 } else {
258 std::vector<uint8_t> oldData(ctrlData.diffLength);
259 size_t readLen = 0;
260 ret = stream_->Read(buffer, oldOffset_, ctrlData.diffLength, readLen);
261 if (ret != 0 || readLen != static_cast<size_t>(ctrlData.diffLength)) {
262 PATCH_LOGE("Failed to get old buffer");
263 return ret;
264 }
265 oldOffset = 0;
266 }
267 for (int64_t i = 0; i < ctrlData.diffLength; i++) {
268 if ((oldOffset_ + i >= 0) && (static_cast<size_t>(oldOffset_ + i) < oldLength)) {
269 diffData[i] += buffer.buffer[static_cast<int64_t>(oldOffset) + i];
270 }
271 }
272 // write
273 return writer_->Write(newOffset_, diffBuffer, static_cast<size_t>(ctrlData.diffLength));
274 }
275
RestoreExtraData(const ControlData & ctrlData)276 int32_t BlocksStreamPatch::RestoreExtraData(const ControlData &ctrlData)
277 {
278 if (ctrlData.extraLength <= 0) {
279 return 0;
280 }
281 std::vector<uint8_t> extraData(ctrlData.extraLength);
282 BlockBuffer extraBuffer = {extraData.data(), static_cast<size_t>(ctrlData.extraLength)};
283 int32_t ret = extraDataReader_->ReadData(extraBuffer);
284 if (ret != 0) {
285 PATCH_LOGE("Failed to read extra data");
286 return ret;
287 }
288 // write
289 return writer_->Write(newOffset_, extraBuffer, static_cast<size_t>(ctrlData.extraLength));
290 }
291 } // namespace UpdatePatch
292