• 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 "image_diff.h"
17 #include <iostream>
18 #include <vector>
19 #include "diffpatch.h"
20 
21 using namespace Hpackage;
22 
23 namespace UpdatePatch {
24 #define GET_REAL_DATA_LEN(info) (info) ->packedSize + (info)->dataOffset - (info)->headerOffset
25 constexpr int32_t LZ4F_MAX_BLOCKID = 7;
26 constexpr int32_t ZIP_MAX_LEVEL = 9;
27 constexpr int32_t MAX_NEW_LENGTH = 1 << 20;
28 
29 template<class DataType>
WriteToFile(std::ofstream & patchFile,DataType data,size_t dataSize)30 static void WriteToFile(std::ofstream &patchFile, DataType data, size_t dataSize)
31 {
32     patchFile.write(reinterpret_cast<const char*>(&data), dataSize);
33 }
34 
GetHeaderSize(const ImageBlock & block)35 static size_t GetHeaderSize(const ImageBlock &block)
36 {
37     switch (block.type) {
38         case BLOCK_NORMAL:
39             return sizeof(uint32_t) + PATCH_NORMAL_MIN_HEADER_LEN;
40         case BLOCK_DEFLATE:
41             return sizeof(uint32_t) + PATCH_DEFLATE_MIN_HEADER_LEN;
42         case BLOCK_RAW:
43             return sizeof(uint32_t) + sizeof(uint32_t) + block.newInfo.length;
44         case BLOCK_LZ4:
45             return sizeof(uint32_t) + PATCH_LZ4_MIN_HEADER_LEN;
46         default:
47             return 0;
48     }
49 }
50 
MakePatch(const std::string & patchName)51 int32_t ImageDiff::MakePatch(const std::string &patchName)
52 {
53     PATCH_LOGI("ImageDiff::MakePatch %s limit_:%d", patchName.c_str(), limit_);
54     if (newParser_ == nullptr || oldParser_ == nullptr) {
55         PATCH_LOGE("Invalid parser");
56         return -1;
57     }
58     BlockBuffer newBuffer;
59     BlockBuffer olduffer;
60     int32_t ret = newParser_->GetPkgBuffer(newBuffer);
61     int32_t ret1 = oldParser_->GetPkgBuffer(olduffer);
62     if (ret != 0 || ret1 != 0) {
63         PATCH_LOGE("Failed to get pkgbuffer");
64         return -1;
65     }
66 
67     PATCH_LOGI("ImageDiff::MakePatch newBuffer %zu %zu ", newBuffer.length, olduffer.length);
68 
69     if (limit_ == 0 || newBuffer.length <= limit_) {
70         ImageBlock block = {
71             BLOCK_NORMAL,
72             { newBuffer.buffer, 0, newBuffer.length },
73             { olduffer.buffer, 0, olduffer.length },
74         };
75         updateBlocks_.push_back(std::move(block));
76     } else {
77         PatchBuffer oldInfo = { olduffer.buffer, 0, olduffer.length };
78         PatchBuffer newInfo = { newBuffer.buffer, 0, newBuffer.length };
79         ret = SplitImage(oldInfo, newInfo);
80         if (ret != 0) {
81             PATCH_LOGE("Failed to split imgage");
82             return ret;
83         }
84     }
85     return DiffImage(patchName);
86 }
87 
SplitImage(const PatchBuffer & oldInfo,const PatchBuffer & newInfo)88 int32_t ImageDiff::SplitImage(const PatchBuffer &oldInfo, const PatchBuffer &newInfo)
89 {
90     size_t blockCount = newInfo.length / limit_ + 1;
91     size_t oldBlockSize = oldInfo.length / blockCount;
92     size_t newBlockSize = newInfo.length / blockCount;
93     int32_t type = (oldInfo.length == 0) ? BLOCK_RAW : BLOCK_NORMAL;
94     size_t i = 0;
95     while (i < blockCount - 1) {
96         ImageBlock block = {
97             type,
98             { newInfo.buffer, newInfo.start + newBlockSize * i, newBlockSize },
99             { oldInfo.buffer, oldInfo.start + oldBlockSize * i, oldBlockSize },
100         };
101         updateBlocks_.push_back(std::move(block));
102         i++;
103     }
104     ImageBlock block = {
105         type,
106         { newInfo.buffer, newInfo.start + newBlockSize * i, newInfo.length - (newInfo.start + newBlockSize * i) },
107         { oldInfo.buffer, oldInfo.start + oldBlockSize * i, oldInfo.length - (oldInfo.start + oldBlockSize * i) },
108     };
109     updateBlocks_.push_back(std::move(block));
110     return 0;
111 }
112 
WriteHeader(std::ofstream & patchFile,std::fstream & blockPatchFile,size_t & dataOffset,ImageBlock & block) const113 int32_t ImageDiff::WriteHeader(std::ofstream &patchFile,
114     std::fstream &blockPatchFile, size_t &dataOffset, ImageBlock &block) const
115 {
116     int32_t ret = 0;
117     switch (block.type) {
118         case BLOCK_NORMAL: {
119             size_t patchSize = 0;
120             BlockBuffer newInfo = { block.newInfo.buffer + block.newInfo.start, block.newInfo.length };
121             BlockBuffer oldInfo = { block.oldInfo.buffer + block.oldInfo.start, block.oldInfo.length };
122             ret = MakeBlockPatch(block, blockPatchFile, newInfo, oldInfo, patchSize);
123             if (ret != 0) {
124                 PATCH_LOGE("Failed to make block patch");
125                 return -1;
126             }
127             PATCH_LOGI("WriteHeader BLOCK_NORMAL patchOffset %zu oldInfo %ld %ld newInfo:%zu %zu patch %zu %zu",
128                 static_cast<size_t>(patchFile.tellp()),
129                 block.oldInfo.start, block.oldInfo.length, block.newInfo.start, block.newInfo.length,
130                 dataOffset, patchSize);
131             WriteToFile<int64_t>(patchFile, static_cast<int64_t>(block.oldInfo.start), sizeof(int64_t));
132             WriteToFile<int64_t>(patchFile, static_cast<int64_t>(block.oldInfo.length), sizeof(int64_t));
133             WriteToFile<int64_t>(patchFile, static_cast<int64_t>(dataOffset), sizeof(int64_t));
134             dataOffset += patchSize;
135             break;
136         }
137         case BLOCK_RAW: {
138             PATCH_LOGI("WriteHeader BLOCK_ROW patchOffset %zu dataOffset:%zu newInfo:%zu",
139                 static_cast<size_t>(patchFile.tellp()), dataOffset, block.newInfo.length);
140             WriteToFile<int32_t>(patchFile, static_cast<int32_t>(block.newInfo.length), sizeof(int32_t));
141             patchFile.write(reinterpret_cast<const char*>(block.newInfo.buffer + block.newInfo.start),
142                 block.newInfo.length);
143             BlockBuffer rawData = { block.newInfo.buffer + block.newInfo.start, block.newInfo.length };
144             PATCH_LOGI("WriteHeader BLOCK_ROW hash %zu %s",
145                 block.newInfo.length, GeneraterBufferHash(rawData).c_str());
146             break;
147         }
148         default:
149             break;
150     }
151     return ret;
152 }
153 
MakeBlockPatch(ImageBlock & block,std::fstream & blockPatchFile,const BlockBuffer & newInfo,const BlockBuffer & oldInfo,size_t & patchSize) const154 int32_t ImageDiff::MakeBlockPatch(ImageBlock &block, std::fstream &blockPatchFile,
155     const BlockBuffer &newInfo, const BlockBuffer &oldInfo, size_t &patchSize) const
156 {
157     if (!usePatchFile_) {
158         std::vector<uint8_t> patchData;
159         int32_t ret = BlocksDiff::MakePatch(newInfo, oldInfo, patchData, 0, patchSize);
160         if (ret != 0) {
161             PATCH_LOGE("Failed to make block patch");
162             return -1;
163         }
164         BlockBuffer patchBuffer = {patchData.data(), patchSize};
165         PATCH_DEBUG("MakeBlockPatch hash %zu %s", patchSize, GeneraterBufferHash(patchBuffer).c_str());
166         block.patchData = std::move(patchData);
167     } else {
168         int32_t ret = BlocksDiff::MakePatch(newInfo, oldInfo, blockPatchFile, patchSize);
169         if (ret != 0) {
170             PATCH_LOGE("Failed to make block patch");
171             return -1;
172         }
173         PATCH_LOGI("MakeBlockPatch patch %zu patch %zu",
174             patchSize, static_cast<size_t>(blockPatchFile.tellp()));
175     }
176     return 0;
177 }
178 
WritePatch(std::ofstream & patchFile,std::fstream & blockPatchFile)179 int32_t ImageDiff::WritePatch(std::ofstream &patchFile, std::fstream &blockPatchFile)
180 {
181     if (usePatchFile_) { // copy to patch
182         size_t bsPatchSize = static_cast<size_t>(blockPatchFile.tellp());
183         PATCH_LOGI("WritePatch patch block patch %zu img patch offset %zu",
184             bsPatchSize, static_cast<size_t>(patchFile.tellp()));
185         blockPatchFile.seekg(0, std::ios::beg);
186         std::vector<char> buffer(IGMDIFF_LIMIT_UNIT);
187         while (bsPatchSize > 0) {
188             size_t readLen = (bsPatchSize > IGMDIFF_LIMIT_UNIT) ? IGMDIFF_LIMIT_UNIT : bsPatchSize;
189             blockPatchFile.read(buffer.data(), readLen);
190             patchFile.write(buffer.data(), readLen);
191             bsPatchSize -= readLen;
192         }
193         PATCH_LOGI("WritePatch patch %zu", static_cast<size_t>(patchFile.tellp()));
194     } else {
195         for (size_t index = 0; index < updateBlocks_.size(); index++) {
196             if (updateBlocks_[index].type == BLOCK_RAW) {
197                 continue;
198             }
199             PATCH_LOGI("WritePatch [%zu] write patch patchOffset %zu length %zu",
200                 index, static_cast<size_t>(patchFile.tellp()), updateBlocks_[index].patchData.size());
201             patchFile.write(reinterpret_cast<const char*>(updateBlocks_[index].patchData.data()),
202                 updateBlocks_[index].patchData.size());
203         }
204     }
205     return 0;
206 }
207 
DiffImage(const std::string & patchName)208 int32_t ImageDiff::DiffImage(const std::string &patchName)
209 {
210     std::fstream blockPatchFile;
211     std::ofstream patchFile(patchName, std::ios::out | std::ios::trunc | std::ios::binary);
212     if (patchFile.fail()) {
213         PATCH_LOGE("Failed to open %s", patchName.c_str());
214         return -1;
215     }
216     patchFile.write(PKGDIFF_MAGIC, std::char_traits<char>::length(PKGDIFF_MAGIC));
217     size_t dataOffset = std::char_traits<char>::length(PKGDIFF_MAGIC);
218     uint32_t size = static_cast<uint32_t>(updateBlocks_.size());
219     patchFile.write(reinterpret_cast<const char*>(&size), sizeof(uint32_t));
220     dataOffset += sizeof(uint32_t);
221 
222     for (size_t index = 0; index < updateBlocks_.size(); index++) {
223         dataOffset += GetHeaderSize(updateBlocks_[index]);
224         if (updateBlocks_[index].destOriginalLength >= MAX_NEW_LENGTH ||
225             updateBlocks_[index].newInfo.length >= MAX_NEW_LENGTH) {
226             usePatchFile_ = true;
227         }
228     }
229 
230     if (usePatchFile_) {
231         blockPatchFile.open(patchName + ".bspatch", std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary);
232         if (blockPatchFile.fail()) {
233             PATCH_LOGE("Failed to open bspatch %s", patchName.c_str());
234             return -1;
235         }
236     }
237 
238     for (size_t index = 0; index < updateBlocks_.size(); index++) {
239         PATCH_LOGI("DiffImage [%zu] write header patchOffset %zu dataOffset %zu",
240             index, static_cast<size_t>(patchFile.tellp()), dataOffset);
241         patchFile.write(reinterpret_cast<const char*>(&updateBlocks_[index].type), sizeof(uint32_t));
242         int32_t ret = WriteHeader(patchFile, blockPatchFile, dataOffset, updateBlocks_[index]);
243         if (ret != 0) {
244             PATCH_LOGE("Failed to write header");
245             return -1;
246         }
247     }
248 
249     int32_t ret = WritePatch(patchFile, blockPatchFile);
250     if (ret != 0) {
251         PATCH_LOGE("Failed to write patch");
252         return -1;
253     }
254     PATCH_LOGI("DiffImage success patchOffset %zu %s", static_cast<size_t>(patchFile.tellp()), patchName.c_str());
255     patchFile.close();
256     return 0;
257 }
258 
MakePatch(const std::string & patchName)259 int32_t CompressedImageDiff::MakePatch(const std::string &patchName)
260 {
261     PATCH_DEBUG("CompressedImageDiff::MakePatch %s limit_:%d", patchName.c_str(), limit_);
262     if (newParser_ == nullptr || oldParser_ == nullptr) {
263         PATCH_LOGE("Invalid parser");
264         return -1;
265     }
266     BlockBuffer newBuffer;
267     BlockBuffer oldBuffer;
268     int32_t ret = newParser_->GetPkgBuffer(newBuffer);
269     int32_t ret1 = oldParser_->GetPkgBuffer(oldBuffer);
270     if (ret != 0 || ret1 != 0) {
271         PATCH_LOGE("Failed to get pkgbuffer");
272         return -1;
273     }
274 
275     if (limit_ != 0 && newBuffer.length >= limit_) {
276         PatchBuffer oldInfo = { oldBuffer.buffer, 0, oldBuffer.length };
277         PatchBuffer newInfo = { newBuffer.buffer, 0, newBuffer.length };
278         ret = SplitImage(oldInfo, newInfo);
279         PATCH_CHECK(ret == 0, return -1, "Failed to split imgage");
280         return DiffImage(patchName);
281     }
282 
283     size_t oldOffset = 0;
284     size_t newOffset = 0;
285     for (size_t i = 0; i < newParser_->GetFileIds().size(); i++) {
286         PATCH_LOGI("CompressedImageDiff::DiffFile %s oldOffset:%zu newOffset:%zu",
287             newParser_->GetFileIds()[i].c_str(), oldOffset, newOffset);
288         ret = DiffFile(newParser_->GetFileIds()[i], oldOffset, newOffset);
289         PATCH_CHECK(ret == 0, break, "Failed to generate patch");
290     }
291     if (ret != 0) {
292         updateBlocks_.clear();
293         return ImageDiff::MakePatch(patchName);
294     }
295     PATCH_LOGI("MakePatch oldOffset:%zu newOffset:%zu newBuffer %zu oldBuffer: %zu",
296         oldOffset, newOffset, newBuffer.length, oldBuffer.length);
297     if (newOffset < newBuffer.length) {
298         ImageBlock block = {
299             BLOCK_RAW,
300             { newBuffer.buffer, newOffset, newBuffer.length - newOffset },
301             { oldBuffer.buffer, oldOffset, oldBuffer.length - oldOffset },
302         };
303         updateBlocks_.push_back(std::move(block));
304     }
305     return DiffImage(patchName);
306 }
307 
DiffFile(const std::string & fileName,size_t & oldOffset,size_t & newOffset)308 int32_t CompressedImageDiff::DiffFile(const std::string &fileName, size_t &oldOffset, size_t &newOffset)
309 {
310     BlockBuffer orgNewBuffer;
311     BlockBuffer orgOldBuffer;
312     int32_t ret = newParser_->GetPkgBuffer(orgNewBuffer);
313     int32_t ret1 = oldParser_->GetPkgBuffer(orgOldBuffer);
314     PATCH_CHECK((ret == 0 && ret1 == 0), return -1, "Failed to get pkgbuffer");
315 
316     std::vector<uint8_t> newBuffer;
317     std::vector<uint8_t> oldBuffer;
318     ret = newParser_->Extract(fileName, newBuffer);
319     const FileInfo *newFileInfo = newParser_->GetFileInfo(fileName);
320     PATCH_CHECK(ret == 0 && newFileInfo != nullptr, return -1, "Failed to get new data");
321     newOffset += GET_REAL_DATA_LEN(newFileInfo);
322     PATCH_CHECK(limit_ == 0 || newFileInfo->unpackedSize < limit_, return PATCH_EXCEED_LIMIT,
323         "Exceed limit, so make patch by original file");
324 
325     ret = oldParser_->Extract(fileName, oldBuffer);
326     if (ret != 0) {
327         ImageBlock block = {
328             BLOCK_RAW,
329             { orgNewBuffer.buffer, newFileInfo->headerOffset, GET_REAL_DATA_LEN(newFileInfo) },
330             { orgOldBuffer.buffer, 0, orgOldBuffer.length },
331         };
332         updateBlocks_.push_back(std::move(block));
333         return 0;
334     }
335     const FileInfo *oldFileInfo = oldParser_->GetFileInfo(fileName);
336     PATCH_CHECK(oldFileInfo != nullptr, return -1, "Failed to get file info");
337     oldOffset += GET_REAL_DATA_LEN(oldFileInfo);
338 
339     BlockBuffer newData = {newBuffer.data(), newFileInfo->unpackedSize};
340     ret = TestAndSetConfig(newData, fileName);
341     PATCH_CHECK(ret == 0, return -1, "Failed to test zip config");
342 
343     if (type_ != BLOCK_LZ4 && newFileInfo->dataOffset > newFileInfo->headerOffset) {
344         ImageBlock block = {
345             BLOCK_RAW,
346             { orgNewBuffer.buffer, newFileInfo->headerOffset, newFileInfo->dataOffset - newFileInfo->headerOffset },
347             { orgOldBuffer.buffer, oldFileInfo->headerOffset, oldFileInfo->dataOffset - oldFileInfo->headerOffset },
348         };
349         updateBlocks_.push_back(std::move(block));
350     }
351 
352     ImageBlock block = {
353         type_,
354         { orgNewBuffer.buffer, newFileInfo->dataOffset, newFileInfo->packedSize },
355         { orgOldBuffer.buffer, oldFileInfo->dataOffset, oldFileInfo->packedSize },
356     };
357     block.srcOriginalData = std::move(oldBuffer);
358     block.destOriginalData = std::move(newBuffer);
359     block.srcOriginalLength = oldFileInfo->unpackedSize;
360     block.destOriginalLength = newFileInfo->unpackedSize;
361     updateBlocks_.push_back(std::move(block));
362     return 0;
363 }
364 
WriteHeader(std::ofstream & patchFile,std::fstream & blockPatchFile,size_t & dataOffset,ImageBlock & block) const365 int32_t ZipImageDiff::WriteHeader(std::ofstream &patchFile,
366     std::fstream &blockPatchFile, size_t &dataOffset, ImageBlock &block) const
367 {
368     int32_t ret = 0;
369     if (block.type == BLOCK_DEFLATE) {
370         size_t patchSize = 0;
371         BlockBuffer oldInfo = { block.srcOriginalData.data(), block.srcOriginalLength };
372         BlockBuffer newInfo = { block.destOriginalData.data(), block.destOriginalLength };
373         ret = MakeBlockPatch(block, blockPatchFile, newInfo, oldInfo, patchSize);
374         if (ret != 0) {
375             PATCH_LOGE("Failed to make block patch");
376             return -1;
377         }
378 
379         PATCH_LOGI("WriteHeader BLOCK_DEFLATE patchoffset %zu dataOffset:%zu patchData:%zu",
380             static_cast<size_t>(patchFile.tellp()), dataOffset, patchSize);
381         PATCH_LOGI("WriteHeader oldInfo start:%zu length:%zu", block.oldInfo.start, block.oldInfo.length);
382         PATCH_LOGI("WriteHeader uncompressedLength:%zu %zu", block.srcOriginalLength, block.destOriginalLength);
383         PATCH_LOGI("WriteHeader level_:%d method_:%d windowBits_:%d memLevel_:%d strategy_:%d",
384             level_, method_, windowBits_, memLevel_, strategy_);
385 
386         WriteToFile<int64_t>(patchFile, static_cast<int64_t>(block.oldInfo.start), sizeof(int64_t));
387         WriteToFile<int64_t>(patchFile, static_cast<int64_t>(block.oldInfo.length), sizeof(int64_t));
388         WriteToFile<int64_t>(patchFile, static_cast<int64_t>(dataOffset), sizeof(int64_t));
389         WriteToFile<int64_t>(patchFile, static_cast<int64_t>(block.srcOriginalLength), sizeof(int64_t));
390         WriteToFile<int64_t>(patchFile, static_cast<int64_t>(block.destOriginalLength), sizeof(int64_t));
391 
392         WriteToFile<int32_t>(patchFile, level_, sizeof(int32_t));
393         WriteToFile<int32_t>(patchFile, method_, sizeof(int32_t));
394         WriteToFile<int32_t>(patchFile, windowBits_, sizeof(int32_t));
395         WriteToFile<int32_t>(patchFile, memLevel_, sizeof(int32_t));
396         WriteToFile<int32_t>(patchFile, strategy_, sizeof(int32_t));
397         dataOffset += patchSize;
398     } else {
399         ret = ImageDiff::WriteHeader(patchFile, blockPatchFile, dataOffset, block);
400     }
401     return ret;
402 }
403 
TestAndSetConfig(const BlockBuffer & buffer,const std::string & fileName)404 int32_t ZipImageDiff::TestAndSetConfig(const BlockBuffer &buffer, const std::string &fileName)
405 {
406     const FileInfo *fileInfo = newParser_->GetFileInfo(fileName);
407     if (fileInfo == nullptr) {
408         PATCH_LOGE("Failed to get file info");
409         return -1;
410     }
411     ZipFileInfo *info = reinterpret_cast<ZipFileInfo *>(const_cast<FileInfo *>(fileInfo));
412     method_ = info->method;
413     level_ = info->level;
414     windowBits_ = info->windowBits;
415     memLevel_ = info->memLevel;
416     strategy_ = info->strategy;
417 
418     BlockBuffer orgNewBuffer;
419     int32_t ret = newParser_->GetPkgBuffer(orgNewBuffer);
420     if (ret != 0) {
421         PATCH_LOGE("Failed to get pkgbuffer");
422         return -1;
423     }
424     ZipFileInfo zipInfo {};
425     zipInfo.fileInfo.packMethod = info->fileInfo.packMethod;
426     zipInfo.method = info->method;
427     zipInfo.level = info->level;
428     zipInfo.windowBits = info->windowBits;
429     zipInfo.memLevel = info->memLevel;
430     zipInfo.strategy = info->strategy;
431 
432     PATCH_LOGI("TestAndSetConfig new info %zu %zu %zu %zu",
433         fileInfo->unpackedSize, fileInfo->packedSize, fileInfo->dataOffset, fileInfo->headerOffset);
434     PATCH_LOGI("TestAndSetConfig level_:%d method_:%d windowBits_:%d memLevel_:%d strategy_:%d",
435         level_, method_, windowBits_, memLevel_, strategy_);
436     BlockBuffer orgData = {orgNewBuffer.buffer + fileInfo->dataOffset, fileInfo->packedSize};
437     PATCH_DEBUG("DiffFile new orignial hash %zu %s", fileInfo->packedSize, GeneraterBufferHash(orgData).c_str());
438 
439     std::vector<uint8_t> data;
440     for (int32_t i = ZIP_MAX_LEVEL; i >= 0; i--) {
441         zipInfo.level = i;
442         size_t bufferSize = 0;
443         ret = CompressData(&zipInfo.fileInfo, buffer, data, bufferSize);
444         PATCH_CHECK(ret == 0, return -1, "Can not Compress buff ");
445 
446         if ((bufferSize == fileInfo->packedSize) &&
447             memcmp(data.data(), orgNewBuffer.buffer + fileInfo->dataOffset, bufferSize) == 0) {
448             level_ = i;
449             return 0;
450         }
451     }
452     return -1;
453 }
454 
WriteHeader(std::ofstream & patchFile,std::fstream & blockPatchFile,size_t & dataOffset,ImageBlock & block) const455 int32_t Lz4ImageDiff::WriteHeader(std::ofstream &patchFile,
456     std::fstream &blockPatchFile, size_t &dataOffset, ImageBlock &block) const
457 {
458     int32_t ret = 0;
459     if (block.type == BLOCK_LZ4) {
460         size_t patchSize = 0;
461         BlockBuffer oldInfo = { block.srcOriginalData.data(), block.srcOriginalLength };
462         BlockBuffer newInfo = { block.destOriginalData.data(), block.destOriginalLength };
463         ret = MakeBlockPatch(block, blockPatchFile, newInfo, oldInfo, patchSize);
464         if (ret != 0) {
465             PATCH_LOGE("Failed to make block patch");
466             return -1;
467         }
468 
469         PATCH_LOGI("WriteHeader BLOCK_LZ4 patchoffset %zu dataOffset:%zu %zu",
470             static_cast<size_t>(patchFile.tellp()), dataOffset, patchSize);
471         PATCH_LOGI("WriteHeader oldInfo start:%zu length:%zu", block.oldInfo.start, block.oldInfo.length);
472         PATCH_LOGI("WriteHeader uncompressedLength:%zu %zu", block.srcOriginalLength, block.destOriginalLength);
473         PATCH_LOGI("WriteHeader level_:%d method_:%d blockIndependence_:%d contentChecksumFlag_:%d blockSizeID_:%d %d",
474             compressionLevel_, method_, blockIndependence_, contentChecksumFlag_, blockSizeID_, autoFlush_);
475         PATCH_LOGI("WriteHeader BLOCK_LZ4 decompressed hash %zu %s",
476             newInfo.length, GeneraterBufferHash(newInfo).c_str());
477         WriteToFile<int64_t>(patchFile, static_cast<int64_t>(block.oldInfo.start), sizeof(int64_t));
478         WriteToFile<int64_t>(patchFile, static_cast<int64_t>(block.oldInfo.length), sizeof(int64_t));
479         WriteToFile<int64_t>(patchFile, static_cast<int64_t>(dataOffset), sizeof(int64_t));
480         WriteToFile<int64_t>(patchFile, static_cast<int64_t>(block.srcOriginalLength), sizeof(int64_t));
481         WriteToFile<int64_t>(patchFile, static_cast<int64_t>(block.destOriginalLength), sizeof(int64_t));
482 
483         int32_t magic = (method_ == PKG_COMPRESS_METHOD_LZ4_BLOCK) ? LZ4B_MAGIC : LZ4S_MAGIC;
484         WriteToFile<int32_t>(patchFile, compressionLevel_, sizeof(int32_t));
485         WriteToFile<int32_t>(patchFile, magic, sizeof(int32_t));
486         WriteToFile<int32_t>(patchFile, blockIndependence_, sizeof(int32_t));
487         WriteToFile<int32_t>(patchFile, contentChecksumFlag_, sizeof(int32_t));
488         WriteToFile<int32_t>(patchFile, blockSizeID_, sizeof(int32_t));
489         WriteToFile<int32_t>(patchFile, autoFlush_, sizeof(int32_t));
490         dataOffset += patchSize;
491     } else {
492         ret = ImageDiff::WriteHeader(patchFile, blockPatchFile, dataOffset, block);
493     }
494     return ret;
495 }
496 
TestAndSetConfig(const BlockBuffer & buffer,const std::string & fileName)497 int32_t Lz4ImageDiff::TestAndSetConfig(const BlockBuffer &buffer, const std::string &fileName)
498 {
499     const FileInfo *fileInfo = newParser_->GetFileInfo(fileName);
500     PATCH_CHECK(fileInfo != nullptr, return -1, "Failed to get file info");
501     Lz4FileInfo *info = reinterpret_cast<Lz4FileInfo *>(const_cast<FileInfo *>(fileInfo));
502     method_ = static_cast<int32_t>(info->fileInfo.packMethod);
503     compressionLevel_ = info->compressionLevel;
504     blockIndependence_ = info->blockIndependence;
505     contentChecksumFlag_ = info->contentChecksumFlag;
506     blockSizeID_ = info->blockSizeID;
507     autoFlush_ = info->autoFlush;
508 
509     BlockBuffer orgNewBuffer;
510     int32_t ret = newParser_->GetPkgBuffer(orgNewBuffer);
511     PATCH_CHECK(ret == 0, return -1, "Failed to get pkgbuffer");
512     Lz4FileInfo lz4Info {};
513     lz4Info.fileInfo.packMethod = info->fileInfo.packMethod;
514     lz4Info.compressionLevel = info->compressionLevel;
515     lz4Info.blockIndependence = info->blockIndependence;
516     lz4Info.contentChecksumFlag = info->contentChecksumFlag;
517     lz4Info.blockSizeID = info->blockSizeID;
518     lz4Info.autoFlush = info->autoFlush;
519 
520     PATCH_DEBUG("TestAndSetConfig level_:%d method_:%d blockIndependence_:%d contentChecksumFlag_:%d blockSizeID_:%d",
521         compressionLevel_, method_, blockIndependence_, contentChecksumFlag_, blockSizeID_);
522     PATCH_DEBUG("DiffFile new info %zu %zu %zu %zu",
523         fileInfo->unpackedSize, fileInfo->packedSize, fileInfo->dataOffset, fileInfo->headerOffset);
524     BlockBuffer orgData = { orgNewBuffer.buffer, fileInfo->packedSize + sizeof(uint32_t) };
525     PATCH_DEBUG("DiffFile new orignial hash %zu %s",
526         fileInfo->packedSize + sizeof(uint32_t), GeneraterBufferHash(orgData).c_str());
527 
528     std::vector<uint8_t> data;
529     for (int32_t i = 0; i <= LZ4F_MAX_BLOCKID; i++) {
530         lz4Info.blockSizeID = i;
531         size_t bufferSize = 0;
532         ret = CompressData(&lz4Info.fileInfo, buffer, data, bufferSize);
533         PATCH_CHECK(ret == 0, return -1, "Can not Compress buff ");
534 
535         if ((bufferSize == fileInfo->packedSize + sizeof(uint32_t)) &&
536             memcmp(data.data(), orgNewBuffer.buffer + fileInfo->headerOffset, bufferSize) == 0) {
537             blockSizeID_ = i;
538             return 0;
539         }
540     }
541     return -1;
542 }
543 
CompressData(Hpackage::PkgManager::FileInfoPtr info,const BlockBuffer & buffer,std::vector<uint8_t> & outData,size_t & outSize) const544 int32_t CompressedImageDiff::CompressData(Hpackage::PkgManager::FileInfoPtr info,
545     const BlockBuffer &buffer, std::vector<uint8_t> &outData, size_t &outSize) const
546 {
547     Hpackage::PkgManager *pkgManager = Hpackage::PkgManager::GetPackageInstance();
548     if (pkgManager == nullptr) {
549         PATCH_LOGE("Can not get manager ");
550         return -1;
551     }
552     Hpackage::PkgManager::StreamPtr stream1 = nullptr;
553     pkgManager->CreatePkgStream(stream1, "gzip",
554         [&outData, &outSize](const PkgBuffer &data,
555             size_t size, size_t start, bool isFinish, const void *context) ->int {
556             if (isFinish) {
557                 return 0;
558             }
559             outSize += size;
560             if ((start + outSize) > outData.size()) {
561                 outData.resize(IGMDIFF_LIMIT_UNIT * ((start + outSize) / IGMDIFF_LIMIT_UNIT + 1));
562             }
563             return memcpy_s(outData.data() + start, outData.size(), data.buffer, size);
564         }, nullptr);
565     int32_t ret = pkgManager->CompressBuffer(info, {buffer.buffer, buffer.length}, stream1);
566     if (ret != 0) {
567         PATCH_LOGE("Can not Compress buff ");
568         return -1;
569     }
570     PATCH_DEBUG("UpdateDiff::MakePatch totalSize: %zu", outSize);
571     return 0;
572 }
573 } // namespace UpdatePatch
574