• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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