• 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     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