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 int64_t controlDataSize = 0;
63 int64_t diffDataSize = 0;
64 int32_t ret = ReadHeader(controlDataSize, diffDataSize, newSize_);
65 if (ret != 0) {
66 PATCH_LOGE("Failed to read header ");
67 return -1;
68 }
69
70 while (newOffset_ < newSize_) {
71 ControlData ctrlData {};
72 int32_t ret = ReadControlData(ctrlData);
73 if (ret != 0) {
74 PATCH_LOGE("Failed to read control data");
75 return ret;
76 }
77 if (newOffset_ + ctrlData.diffLength > newSize_) {
78 PATCH_LOGE("Failed to check new offset %ld %zu", ctrlData.diffLength, newOffset_);
79 return PATCH_INVALID_PATCH;
80 }
81
82 ret = RestoreDiffData(ctrlData);
83 if (ret != 0) {
84 PATCH_LOGE("Failed to read diff data");
85 return ret;
86 }
87 oldOffset_ += ctrlData.diffLength;
88 newOffset_ += ctrlData.diffLength;
89 if (newOffset_ + ctrlData.extraLength > newSize_) {
90 PATCH_LOGE("Failed to check new offset %ld %zu", ctrlData.diffLength, newOffset_);
91 return PATCH_INVALID_PATCH;
92 }
93
94 ret = RestoreExtraData(ctrlData);
95 if (ret != 0) {
96 PATCH_LOGE("Failed to read extra data");
97 return ret;
98 }
99
100 newOffset_ += ctrlData.extraLength;
101 oldOffset_ += ctrlData.offsetIncrement;
102 }
103 controlDataReader_->Close();
104 diffDataReader_->Close();
105 extraDataReader_->Close();
106 return 0;
107 }
108
ReadHeader(int64_t & controlDataSize,int64_t & diffDataSize,int64_t & newSize)109 int32_t BlocksPatch::ReadHeader(int64_t &controlDataSize, int64_t &diffDataSize, int64_t &newSize)
110 {
111 if (patchInfo_.buffer == nullptr || patchInfo_.length <= PATCH_MIN) {
112 PATCH_LOGE("Invalid parm");
113 return -1;
114 }
115 BlockBuffer patchData = {patchInfo_.buffer + patchInfo_.start, patchInfo_.length - patchInfo_.start};
116 PATCH_DEBUG("Restore patch hash %zu %zu %s",
117 patchInfo_.length , patchInfo_.start, GeneraterBufferHash(patchData).c_str());
118 uint8_t *header = patchInfo_.buffer + patchInfo_.start;
119 if (memcmp(header, BSDIFF_MAGIC, std::char_traits<char>::length(BSDIFF_MAGIC)) != 0) {
120 PATCH_LOGE("Corrupt patch, patch head != BSDIFF40");
121 return -1;
122 }
123 /* Read lengths from header */
124 size_t offset = std::char_traits<char>::length(BSDIFF_MAGIC);
125 controlDataSize = ReadLE64(header + offset);
126 offset += sizeof(int64_t);
127 diffDataSize = ReadLE64(header + offset);
128 offset += sizeof(int64_t);
129 newSize = ReadLE64(header + offset);
130 offset += sizeof(int64_t);
131 if (controlDataSize < 0) {
132 PATCH_LOGE("Invalid control data size");
133 return -1;
134 }
135 if (newSize < 0) {
136 PATCH_LOGE("Invalid new data size");
137 return -1;
138 }
139 if (diffDataSize < 0 || (diffDataSize + controlDataSize) > static_cast<int64_t>(patchInfo_.length)) {
140 PATCH_LOGE("Invalid patch data size");
141 return -1;
142 }
143 BlockBuffer patchBuffer = {header, patchInfo_.length - patchInfo_.start};
144 controlDataReader_.reset(new BZip2BufferReadAdapter(offset, static_cast<size_t>(controlDataSize), patchBuffer));
145 offset += static_cast<size_t>(controlDataSize);
146 diffDataReader_.reset(new BZip2BufferReadAdapter(offset, static_cast<size_t>(diffDataSize), patchBuffer));
147 offset += static_cast<size_t>(diffDataSize);
148 extraDataReader_.reset(new BZip2BufferReadAdapter(offset,
149 patchInfo_.length - patchInfo_.start - offset, patchBuffer));
150 if (controlDataReader_ == nullptr || diffDataReader_ == nullptr || extraDataReader_ == nullptr) {
151 PATCH_LOGE("Failed to create reader");
152 return -1;
153 }
154 controlDataReader_->Open();
155 diffDataReader_->Open();
156 extraDataReader_->Open();
157 return 0;
158 }
159
ReadControlData(ControlData & ctrlData)160 int32_t BlocksPatch::ReadControlData(ControlData &ctrlData)
161 {
162 std::vector<uint8_t> data(sizeof(int64_t), 0);
163 BlockBuffer info = {data.data(), sizeof(int64_t)};
164 int32_t ret = controlDataReader_->ReadData(info);
165 if (ret != 0) {
166 PATCH_LOGE("Failed to read diffLength");
167 return ret;
168 }
169 ctrlData.diffLength = ReadLE64(info.buffer);
170 ret = controlDataReader_->ReadData(info);
171 if (ret != 0) {
172 PATCH_LOGE("Failed to read extraLength");
173 return ret;
174 }
175 ctrlData.extraLength = ReadLE64(info.buffer);
176 ret = controlDataReader_->ReadData(info);
177 if (ret != 0) {
178 PATCH_LOGE("Failed to read offsetIncrement");
179 return ret;
180 }
181 ctrlData.offsetIncrement = ReadLE64(info.buffer);
182 return 0;
183 }
184
ReadHeader(int64_t & controlDataSize,int64_t & diffDataSize,int64_t & newSize)185 int32_t BlocksBufferPatch::ReadHeader(int64_t &controlDataSize, int64_t &diffDataSize, int64_t &newSize)
186 {
187 int32_t ret = BlocksPatch::ReadHeader(controlDataSize, diffDataSize, newSize);
188 if (ret != 0) {
189 PATCH_LOGE("Failed to read header");
190 return -1;
191 }
192 PATCH_LOGI("ReadHeader controlDataSize: %ld %ld %ld", controlDataSize, diffDataSize, newSize);
193 newData_.resize(newSize);
194 return 0;
195 }
196
RestoreDiffData(const ControlData & ctrlData)197 int32_t BlocksBufferPatch::RestoreDiffData(const ControlData &ctrlData)
198 {
199 if (ctrlData.diffLength <= 0) {
200 return 0;
201 }
202 BlockBuffer diffData = {newData_.data() + newOffset_, static_cast<size_t>(ctrlData.diffLength)};
203 int32_t ret = diffDataReader_->ReadData(diffData);
204 if (ret != 0) {
205 PATCH_LOGE("Failed to read diff data");
206 return ret;
207 }
208
209 for (int64_t i = 0; i < ctrlData.diffLength; i++) {
210 if (((oldOffset_ + i) >= 0) && (static_cast<size_t>(oldOffset_ + i) < oldInfo_.length)) {
211 newData_[newOffset_ + i] += oldInfo_.buffer[oldOffset_ + i];
212 }
213 }
214 return 0;
215 }
216
RestoreExtraData(const ControlData & ctrlData)217 int32_t BlocksBufferPatch::RestoreExtraData(const ControlData &ctrlData)
218 {
219 if (ctrlData.extraLength <= 0) {
220 return 0;
221 }
222 BlockBuffer extraData = {newData_.data() + newOffset_, static_cast<size_t>(ctrlData.extraLength)};
223 int32_t ret = extraDataReader_->ReadData(extraData);
224 if (ret != 0) {
225 PATCH_LOGE("Failed to read extra data");
226 return ret;
227 }
228 return 0;
229 }
230
RestoreDiffData(const ControlData & ctrlData)231 int32_t BlocksStreamPatch::RestoreDiffData(const ControlData &ctrlData)
232 {
233 if (ctrlData.diffLength <= 0) {
234 return 0;
235 }
236 std::vector<uint8_t> diffData(ctrlData.diffLength);
237 BlockBuffer diffBuffer = {diffData.data(), diffData.size()};
238 int32_t ret = diffDataReader_->ReadData(diffBuffer);
239 if (ret != 0) {
240 PATCH_LOGE("Failed to read diff data");
241 return ret;
242 }
243
244 size_t oldOffset = static_cast<size_t>(oldOffset_);
245 size_t oldLength = stream_->GetFileLength();
246 PkgBuffer buffer {};
247 if (stream_->GetStreamType() == PkgStream::PkgStreamType_MemoryMap ||
248 stream_->GetStreamType() == PkgStream::PkgStreamType_Buffer) {
249 ret = stream_->GetBuffer(buffer);
250 if (ret != 0) {
251 PATCH_LOGE("Failed to get old buffer");
252 return ret;
253 }
254 } else {
255 std::vector<uint8_t> oldData(ctrlData.diffLength);
256 size_t readLen = 0;
257 ret = stream_->Read(buffer, oldOffset_, ctrlData.diffLength, readLen);
258 if (ret != 0 || readLen != static_cast<size_t>(ctrlData.diffLength)) {
259 PATCH_LOGE("Failed to get old buffer");
260 return ret;
261 }
262 oldOffset = 0;
263 }
264 for (int64_t i = 0; i < ctrlData.diffLength; i++) {
265 if ((oldOffset_ + i >= 0) && (static_cast<size_t>(oldOffset_ + i) < oldLength)) {
266 diffData[i] += buffer.buffer[static_cast<int64_t>(oldOffset) + i];
267 }
268 }
269 // write
270 return writer_->Write(newOffset_, diffBuffer, static_cast<size_t>(ctrlData.diffLength));
271 }
272
RestoreExtraData(const ControlData & ctrlData)273 int32_t BlocksStreamPatch::RestoreExtraData(const ControlData &ctrlData)
274 {
275 if (ctrlData.extraLength <= 0) {
276 return 0;
277 }
278 std::vector<uint8_t> extraData(ctrlData.extraLength);
279 BlockBuffer extraBuffer = {extraData.data(), static_cast<size_t>(ctrlData.extraLength)};
280 int32_t ret = extraDataReader_->ReadData(extraBuffer);
281 if (ret != 0) {
282 PATCH_LOGE("Failed to read extra data");
283 return ret;
284 }
285 // write
286 return writer_->Write(newOffset_, extraBuffer, static_cast<size_t>(ctrlData.extraLength));
287 }
288 } // namespace UpdatePatch
289