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 #include "pkg_algo_lz4.h"
16 #include "lz4.h"
17 #include "lz4frame.h"
18 #include "lz4hc.h"
19 #include "pkg_stream.h"
20 #include "pkg_utils.h"
21 #include "securec.h"
22 
23 namespace Hpackage {
PkgAlgorithmLz4(const Lz4FileInfo & config)24 PkgAlgorithmLz4::PkgAlgorithmLz4(const Lz4FileInfo &config) : PkgAlgorithm(),
25     compressionLevel_(config.compressionLevel),
26     blockIndependence_(config.blockIndependence),
27     contentChecksumFlag_(config.contentChecksumFlag),
28     blockSizeID_(config.blockSizeID),
29     autoFlush_(config.autoFlush)
30 {
31     // blockIndependence_ 0 LZ4F_blockLinked
32     // contentChecksumFlag_ 0 disable
33     // blockSizeID_ LZ4F_default=0
34     if (compressionLevel_ < 1) {
35         compressionLevel_ = 2; // 2 : set compressionLevel_ 2
36     }
37     if (compressionLevel_ >= LZ4HC_CLEVEL_MAX) {
38         compressionLevel_ = LZ4HC_CLEVEL_MAX;
39     }
40 }
41 
AdpLz4Compress(const uint8_t * src,uint8_t * dest,uint32_t srcSize,uint32_t dstCapacity) const42 int32_t PkgAlgorithmLz4::AdpLz4Compress(const uint8_t *src, uint8_t *dest,
43     uint32_t srcSize, uint32_t dstCapacity) const
44 {
45     if (compressionLevel_ < LZ4HC_CLEVEL_MIN) { // hc 最小是3
46         return LZ4_compress_default(reinterpret_cast<const char *>(src), reinterpret_cast<char *>(dest),
47             static_cast<int32_t>(srcSize), static_cast<int32_t>(dstCapacity));
48     }
49     return LZ4_compress_HC(reinterpret_cast<const char *>(src), reinterpret_cast<char *>(dest), srcSize, dstCapacity,
50         compressionLevel_);
51 }
52 
AdpLz4Decompress(const uint8_t * src,uint8_t * dest,uint32_t srcSize,uint32_t dstCapacity) const53 int32_t PkgAlgorithmLz4::AdpLz4Decompress(const uint8_t *src, uint8_t *dest, uint32_t srcSize,
54     uint32_t dstCapacity) const
55 {
56     return LZ4_decompress_safe(reinterpret_cast<const char *>(src), reinterpret_cast<char *>(dest), srcSize,
57         dstCapacity);
58 }
59 
PackCalculate(const PkgStreamPtr inStream,const PkgStreamPtr outStream,PkgAlgorithmContext & context,PkgBuffer & inBuffer,PkgBuffer & outBuffer)60 int32_t PkgAlgorithmBlockLz4::PackCalculate(const PkgStreamPtr inStream, const PkgStreamPtr outStream,
61     PkgAlgorithmContext &context, PkgBuffer &inBuffer, PkgBuffer &outBuffer)
62 {
63     size_t srcOffset = context.srcOffset;
64     size_t destOffset = context.destOffset;
65     size_t remainSize = context.unpackedSize;
66     size_t readLen = 0;
67     /* 写包头 */
68     WriteLE32(outBuffer.buffer, LZ4B_MAGIC_NUMBER);
69     int32_t ret = outStream->Write(outBuffer, sizeof(LZ4B_MAGIC_NUMBER), destOffset);
70     if (ret != PKG_SUCCESS) {
71         PKG_LOGE("Fail write data ");
72         return ret;
73     }
74     destOffset += sizeof(LZ4B_MAGIC_NUMBER);
75 
76     while (remainSize > 0) {
77         ret = ReadData(inStream, srcOffset, inBuffer, remainSize, readLen);
78         if (ret != PKG_SUCCESS) {
79             PKG_LOGE("Fail read data ");
80             break;
81         }
82 
83         // Compress Block, reserve 4 bytes to store block size
84         int32_t outSize = AdpLz4Compress(inBuffer.buffer,
85             outBuffer.buffer + LZ4B_REVERSED_LEN, readLen, outBuffer.length - LZ4B_REVERSED_LEN);
86         if (outSize <= 0) {
87             PKG_LOGE("Fail to compress data outSize %d ", outSize);
88             break;
89         }
90 
91         // Write block to buffer.
92         // Buffer format: <block size> + <block contents>
93         WriteLE32(outBuffer.buffer, outSize);
94         ret = outStream->Write(outBuffer, outSize + LZ4B_REVERSED_LEN, destOffset);
95         if (ret != PKG_SUCCESS) {
96             PKG_LOGE("Fail write data ");
97             break;
98         }
99 
100         srcOffset += readLen;
101         destOffset += static_cast<size_t>(outSize) + LZ4B_REVERSED_LEN;
102     }
103     if (srcOffset - context.srcOffset != context.unpackedSize) {
104         PKG_LOGE("original size error %zu %zu", srcOffset, context.unpackedSize);
105         return ret;
106     }
107     context.packedSize = destOffset - context.destOffset;
108     return PKG_SUCCESS;
109 }
110 
Pack(const PkgStreamPtr inStream,const PkgStreamPtr outStream,PkgAlgorithmContext & context)111 int32_t PkgAlgorithmBlockLz4::Pack(const PkgStreamPtr inStream, const PkgStreamPtr outStream,
112     PkgAlgorithmContext &context)
113 {
114     if (inStream == nullptr || outStream == nullptr) {
115         PKG_LOGE("Param context null!");
116         return PKG_INVALID_PARAM;
117     }
118     size_t blockSize = static_cast<size_t>(GetBlockSizeFromBlockId(blockSizeID_));
119     blockSize = (blockSize > LZ4B_BLOCK_SIZE) ? LZ4B_BLOCK_SIZE : blockSize;
120     PkgBuffer inBuffer = {blockSize};
121     PkgBuffer outBuffer = {LZ4_compressBound(blockSize)};
122     if (inBuffer.buffer == nullptr || outBuffer.buffer == nullptr) {
123         PKG_LOGE("Fail to alloc buffer ");
124         return PKG_NONE_MEMORY;
125     }
126 
127     PKG_LOGI("frameInfo blockSizeID %d compressionLevel_: %d blockIndependence_:%d contentChecksumFlag_:%d %zu",
128         static_cast<int32_t>(blockSizeID_), static_cast<int32_t>(compressionLevel_),
129         static_cast<int32_t>(blockIndependence_), static_cast<int32_t>(contentChecksumFlag_), blockSize);
130 
131     return PackCalculate(inStream, outStream, context, inBuffer, outBuffer);
132 }
133 
UnpackCalculate(const PkgStreamPtr inStream,const PkgStreamPtr outStream,PkgAlgorithmContext & context,int & inBuffSize)134 int32_t PkgAlgorithmBlockLz4::UnpackCalculate(const PkgStreamPtr inStream, const PkgStreamPtr outStream,
135     PkgAlgorithmContext &context, int &inBuffSize)
136 {
137     PkgBuffer inBuffer(static_cast<size_t>(inBuffSize));
138     PkgBuffer outBuffer(LZ4B_BLOCK_SIZE);
139     if (inBuffer.buffer == nullptr || outBuffer.buffer == nullptr) {
140         PKG_LOGE("Fail to alloc buffer ");
141         return PKG_NONE_MEMORY;
142     }
143     PkgAlgorithmContext unpackText = context;
144     size_t readLen = 0;
145 
146     /* Main Loop */
147     while (1) {
148         /* Block Size */
149         inBuffer.length = sizeof(uint32_t);
150         int32_t ret = ReadData(inStream, unpackText.srcOffset, inBuffer, unpackText.packedSize, readLen);
151         if (ret != PKG_SUCCESS) {
152             PKG_LOGE("Fail read data ");
153             break;
154         }
155         if (readLen == 0) {
156             break;
157         }
158         uint32_t blockSize = ReadLE32(inBuffer.buffer);
159         if (blockSize > static_cast<uint32_t>(inBuffSize)) {
160             PKG_LOGE("Fail to get block size %u  %d", blockSize, inBuffSize);
161             break;
162         }
163         unpackText.srcOffset += sizeof(uint32_t);
164 
165         /* Read Block */
166         inBuffer.length = blockSize;
167         ret = ReadData(inStream, unpackText.srcOffset, inBuffer, unpackText.packedSize, readLen);
168         if (ret != PKG_SUCCESS) {
169             PKG_LOGE("Fail Read Block ");
170             break;
171         }
172 
173         /* Decode Block */
174         int32_t decodeSize = AdpLz4Decompress(inBuffer.buffer,
175             outBuffer.buffer, readLen, LZ4B_BLOCK_SIZE);
176         if (decodeSize <= 0) {
177             PKG_LOGE("Fail to decompress");
178             break;
179         }
180 
181         /* Write Block */
182         ret = outStream->Write(outBuffer, decodeSize, unpackText.destOffset);
183         if (ret != PKG_SUCCESS) {
184             PKG_LOGE("Fail Write Block ");
185             break;
186         }
187         unpackText.destOffset += static_cast<size_t>(decodeSize);
188         unpackText.srcOffset += readLen;
189     }
190     context.packedSize = unpackText.srcOffset - context.srcOffset;
191     context.unpackedSize = unpackText.destOffset - context.destOffset;
192     return PKG_SUCCESS;
193 }
194 
Unpack(const PkgStreamPtr inStream,const PkgStreamPtr outStream,PkgAlgorithmContext & context)195 int32_t PkgAlgorithmBlockLz4::Unpack(const PkgStreamPtr inStream, const PkgStreamPtr outStream,
196     PkgAlgorithmContext &context)
197 {
198     if (inStream == nullptr || outStream == nullptr) {
199         PKG_LOGE("Param context null!");
200         return PKG_INVALID_PARAM;
201     }
202     int inBuffSize = LZ4_compressBound(LZ4B_BLOCK_SIZE);
203     if (inBuffSize <= 0) {
204         PKG_LOGE("BufferSize must > 0");
205         return PKG_NONE_MEMORY;
206     }
207     return UnpackCalculate(inStream, outStream, context, inBuffSize);
208 }
209 
GetPackParam(LZ4F_compressionContext_t & ctx,LZ4F_preferences_t & preferences,size_t & inBuffSize,size_t & outBuffSize) const210 int32_t PkgAlgorithmLz4::GetPackParam(LZ4F_compressionContext_t &ctx, LZ4F_preferences_t &preferences,
211     size_t &inBuffSize, size_t &outBuffSize) const
212 {
213     LZ4F_errorCode_t errorCode = 0;
214     errorCode = LZ4F_createCompressionContext(&ctx, LZ4F_VERSION);
215     if (LZ4F_isError(errorCode)) {
216         PKG_LOGE("Fail to create compress context %s", LZ4F_getErrorName(errorCode));
217         return PKG_NONE_MEMORY;
218     }
219     size_t blockSize = static_cast<size_t>(GetBlockSizeFromBlockId(blockSizeID_));
220     if (memset_s(&preferences, sizeof(preferences), 0, sizeof(preferences)) != EOK) {
221         PKG_LOGE("Memset failed");
222         return PKG_NONE_MEMORY;
223     }
224     preferences.autoFlush = autoFlush_;
225     preferences.compressionLevel = compressionLevel_;
226     preferences.frameInfo.blockMode = ((blockIndependence_ == 0) ? LZ4F_blockLinked : LZ4F_blockIndependent);
227     preferences.frameInfo.blockSizeID = (LZ4F_blockSizeID_t)blockSizeID_;
228     preferences.frameInfo.contentChecksumFlag =
229         ((contentChecksumFlag_ == 0) ? LZ4F_noContentChecksum : LZ4F_contentChecksumEnabled);
230 
231     outBuffSize = LZ4F_compressBound(blockSize, &preferences);
232     if (outBuffSize <= 0) {
233         PKG_LOGE("BufferSize must > 0");
234         return PKG_NONE_MEMORY;
235     }
236     inBuffSize = blockSize;
237 
238     PKG_LOGI("frameInfo blockSizeID %d compressionLevel_: %d blockIndependence_:%d contentChecksumFlag_:%d",
239         static_cast<int32_t>(blockSizeID_), static_cast<int32_t>(compressionLevel_),
240         static_cast<int32_t>(blockIndependence_), static_cast<int32_t>(contentChecksumFlag_));
241     PKG_LOGI("blockSize %zu %zu %zu", blockSize, GetBlockSizeFromBlockId(blockSizeID_), outBuffSize);
242     return PKG_SUCCESS;
243 }
244 
PackCalculate(const PkgStreamPtr inStream,const PkgStreamPtr outStream,PkgBufferMessage & msg,size_t & dataLen,LZ4F_compressionContext_t & ctx)245 int32_t PkgAlgorithmLz4::PackCalculate(const PkgStreamPtr inStream, const PkgStreamPtr outStream,
246     PkgBufferMessage &msg, size_t &dataLen, LZ4F_compressionContext_t &ctx)
247 {
248     /* 写包头 */
249     int32_t ret = outStream->Write(msg.outBuffer, dataLen, msg.context.destOffset);
250     if (ret != PKG_SUCCESS) {
251         PKG_LOGE("Fail write data ");
252         return ret;
253     }
254 
255     msg.context.destOffset += dataLen;
256     while (msg.context.unpackedSize > 0) {
257         ret = ReadData(inStream, msg.context.srcOffset, msg.inBuffer, msg.context.unpackedSize, dataLen);
258         if (ret != PKG_SUCCESS) {
259             PKG_LOGE("Fail read data ");
260             break;
261         }
262         size_t outSize = LZ4F_compressUpdate(ctx,
263             msg.outBuffer.buffer, msg.outBuffer.length, msg.inBuffer.buffer, dataLen, nullptr);
264         if (LZ4F_isError(outSize)) {
265             ret = PKG_NONE_MEMORY;
266             PKG_LOGE("Fail to compress update %s", LZ4F_getErrorName(outSize));
267             break;
268         }
269         ret = outStream->Write(msg.outBuffer, outSize, msg.context.destOffset);
270         if (ret != PKG_SUCCESS) {
271             ret = PKG_NONE_MEMORY;
272             PKG_LOGE("Fail write data ");
273             break;
274         }
275 
276         msg.context.srcOffset += dataLen;
277         msg.context.destOffset += outSize;
278     }
279 
280     if (ret == PKG_SUCCESS) {
281         size_t headerSize = LZ4F_compressEnd(ctx, msg.outBuffer.buffer, msg.outBuffer.length, nullptr);
282         if (LZ4F_isError(headerSize)) {
283             PKG_LOGE("Fail to compress update end %s", LZ4F_getErrorName(headerSize));
284             return PKG_NONE_MEMORY;
285         }
286         ret = outStream->Write(msg.outBuffer, headerSize, msg.context.destOffset);
287         if (ret != PKG_SUCCESS) {
288             PKG_LOGE("Fail write data ");
289             return ret;
290         }
291         msg.context.destOffset += headerSize;
292     }
293     return ret;
294 }
295 
296 /* 打包数据时,会自动生成magic字 */
Pack(const PkgStreamPtr inStream,const PkgStreamPtr outStream,PkgAlgorithmContext & context)297 int32_t PkgAlgorithmLz4::Pack(const PkgStreamPtr inStream, const PkgStreamPtr outStream,
298     PkgAlgorithmContext &context)
299 {
300     if (inStream == nullptr || outStream == nullptr) {
301         PKG_LOGE("Param context null!");
302         return PKG_INVALID_PARAM;
303     }
304     LZ4F_compressionContext_t ctx;
305     LZ4F_preferences_t preferences;
306     size_t inLength = 0;
307     size_t outLength = 0;
308     if (GetPackParam(ctx, preferences, inLength, outLength) != PKG_SUCCESS) {
309         PKG_LOGE("Fail to get param for pack");
310         return PKG_NONE_MEMORY;
311     }
312 
313     PkgBuffer inBuffer(inLength);
314     PkgBuffer outBuffer(outLength);
315     if (inBuffer.buffer == nullptr || outBuffer.buffer == nullptr) {
316         (void)LZ4F_freeCompressionContext(ctx);
317         PKG_LOGE("Fail to alloc buffer ");
318         return PKG_NONE_MEMORY;
319     }
320     PkgAlgorithmContext packText = context;
321     struct PkgBufferMessage msg { packText, inBuffer, outBuffer, inLength, outLength};
322     size_t dataLen = LZ4F_compressBegin(ctx, msg.outBuffer.buffer, msg.outBuffer.length, &preferences);
323     if (LZ4F_isError(dataLen)) {
324         (void)LZ4F_freeCompressionContext(ctx);
325         PKG_LOGE("Fail to generate header %s", LZ4F_getErrorName(dataLen));
326         return PKG_NONE_MEMORY;
327     }
328     int32_t ret = PackCalculate(inStream, outStream, msg, dataLen, ctx);
329     if (ret != PKG_SUCCESS) {
330         (void)LZ4F_freeCompressionContext(ctx);
331         return ret;
332     }
333     (void)LZ4F_freeCompressionContext(ctx);
334     if (msg.context.srcOffset - context.srcOffset != context.unpackedSize) {
335         PKG_LOGE("original size error %zu %zu", msg.context.srcOffset, context.unpackedSize);
336         return PKG_INVALID_LZ4;
337     }
338     context.packedSize = msg.context.destOffset - context.destOffset;
339     return PKG_SUCCESS;
340 }
341 
GetUnpackParam(LZ4F_decompressionContext_t & ctx,const PkgStreamPtr inStream,size_t & nextToRead,size_t & srcOffset)342 int32_t PkgAlgorithmLz4::GetUnpackParam(LZ4F_decompressionContext_t &ctx, const PkgStreamPtr inStream,
343     size_t &nextToRead, size_t &srcOffset)
344 {
345     LZ4F_errorCode_t errorCode = 0;
346     LZ4F_frameInfo_t frameInfo;
347 
348     PkgBuffer pkgHeader(LZ4S_HEADER_LEN);
349     WriteLE32(pkgHeader.buffer, LZ4S_MAGIC_NUMBER);
350 
351     /* Decode stream descriptor */
352     size_t readLen = 0;
353     size_t outBuffSize = 0;
354     size_t inBuffSize = 0;
355     size_t sizeCheck = sizeof(LZ4B_MAGIC_NUMBER);
356     nextToRead = LZ4F_decompress(ctx, nullptr, &outBuffSize, pkgHeader.buffer, &sizeCheck, nullptr);
357     if (LZ4F_isError(nextToRead)) {
358         PKG_LOGE("Fail to decode frame info %s", LZ4F_getErrorName(nextToRead));
359         return PKG_INVALID_LZ4;
360     }
361     if (nextToRead > pkgHeader.length) {
362         PKG_LOGE("Invalid pkgHeader.length %d", pkgHeader.length);
363         return PKG_INVALID_LZ4;
364     }
365 
366     size_t remainSize = LZ4S_HEADER_LEN;
367     PkgBuffer inbuffer(nullptr, nextToRead);
368     if (ReadData(inStream, srcOffset, inbuffer, remainSize, readLen) != PKG_SUCCESS) {
369         PKG_LOGE("Fail read data ");
370         return PKG_INVALID_LZ4;
371     }
372     if (readLen != nextToRead) {
373         PKG_LOGE("Invalid len %zu %zu", readLen, nextToRead);
374         return PKG_INVALID_LZ4;
375     }
376     srcOffset += readLen;
377     sizeCheck = readLen;
378     nextToRead = LZ4F_decompress(ctx, nullptr, &outBuffSize, inbuffer.buffer, &sizeCheck, nullptr);
379     errorCode = LZ4F_getFrameInfo(ctx, &frameInfo, nullptr, &inBuffSize);
380     if (LZ4F_isError(errorCode)) {
381         PKG_LOGE("Fail to decode frame info %s", LZ4F_getErrorName(errorCode));
382         return PKG_INVALID_LZ4;
383     }
384     if (frameInfo.blockSizeID < 3 || frameInfo.blockSizeID > 7) { // 3,7 : Check whether block size ID is valid
385         PKG_LOGE("Invalid block size ID %d", frameInfo.blockSizeID);
386         return PKG_INVALID_LZ4;
387     }
388 
389     blockIndependence_ = frameInfo.blockMode;
390     contentChecksumFlag_ = frameInfo.contentChecksumFlag;
391     blockSizeID_ = frameInfo.blockSizeID;
392     return PKG_SUCCESS;
393 }
394 
UnpackDecode(const PkgStreamPtr inStream,const PkgStreamPtr outStream,PkgBufferMessage & msg,size_t & nextToRead,LZ4F_decompressionContext_t & ctx)395 int32_t PkgAlgorithmLz4::UnpackDecode(const PkgStreamPtr inStream, const PkgStreamPtr outStream,
396     PkgBufferMessage &msg, size_t &nextToRead, LZ4F_decompressionContext_t &ctx)
397 {
398     /* Main Loop */
399     while (nextToRead != 0) {
400         size_t readLen = 0;
401         size_t decodedBytes = msg.outBuffSize;
402         if (nextToRead > msg.inBuffSize) {
403             PKG_LOGE("Error next read %zu %zu ", nextToRead, msg.inBuffSize);
404             break;
405         }
406 
407         /* Read Block */
408         msg.inBuffer.length = nextToRead;
409         if (ReadData(inStream, msg.context.srcOffset, msg.inBuffer, msg.context.packedSize, readLen) != PKG_SUCCESS) {
410             PKG_LOGE("Fail read data ");
411             return PKG_INVALID_STREAM;
412         }
413 
414         /* Decode Block */
415         size_t sizeCheck = readLen;
416         LZ4F_errorCode_t errorCode = LZ4F_decompress(ctx, msg.outBuffer.buffer,
417             &decodedBytes, msg.inBuffer.buffer, &sizeCheck, nullptr);
418         if (LZ4F_isError(errorCode)) {
419             PKG_LOGE("Fail to decompress %s", LZ4F_getErrorName(errorCode));
420             return PKG_INVALID_LZ4;
421         }
422         if (decodedBytes == 0) {
423             msg.context.srcOffset += readLen;
424             break;
425         }
426         if (sizeCheck != nextToRead) {
427             PKG_LOGE("Error next read %zu %zu ", nextToRead, sizeCheck);
428             break;
429         }
430 
431         /* Write Block */
432         if (outStream->Write(msg.outBuffer, decodedBytes, msg.context.destOffset) != PKG_SUCCESS) {
433             PKG_LOGE("Fail write data ");
434             return PKG_INVALID_STREAM;
435         }
436         msg.context.destOffset += decodedBytes;
437         msg.context.srcOffset += readLen;
438         nextToRead = errorCode;
439     }
440     return PKG_SUCCESS;
441 }
442 
Unpack(const PkgStreamPtr inStream,const PkgStreamPtr outStream,PkgAlgorithmContext & context)443 int32_t PkgAlgorithmLz4::Unpack(const PkgStreamPtr inStream, const PkgStreamPtr outStream,
444     PkgAlgorithmContext &context)
445 {
446     if (inStream == nullptr || outStream == nullptr) {
447         PKG_LOGE("Param context null!");
448         return PKG_INVALID_PARAM;
449     }
450     LZ4F_decompressionContext_t ctx;
451     LZ4F_errorCode_t errorCode = 0;
452     size_t nextToRead = 0;
453     PkgAlgorithmContext unpackText = context;
454     errorCode = LZ4F_createDecompressionContext(&ctx, LZ4F_VERSION);
455     if (LZ4F_isError(errorCode)) {
456         PKG_LOGE("Fail to create compress context %s", LZ4F_getErrorName(errorCode));
457         return PKG_INVALID_LZ4;
458     }
459     int32_t ret = GetUnpackParam(ctx, inStream, nextToRead, unpackText.srcOffset);
460     if (ret != PKG_SUCCESS) {
461         (void)LZ4F_freeDecompressionContext(ctx);
462         PKG_LOGE("Fail to get param ");
463         return PKG_INVALID_LZ4;
464     }
465 
466     int32_t outBuffSize = GetBlockSizeFromBlockId(blockSizeID_);
467     PKG_LOGI("Block size ID %d outBuffSize:%d", blockSizeID_, outBuffSize);
468     int32_t inBuffSize = outBuffSize + static_cast<int32_t>(sizeof(uint32_t));
469     if (inBuffSize <= 0 || outBuffSize <= 0) {
470         (void)LZ4F_freeDecompressionContext(ctx);
471         PKG_LOGE("Buffer size must > 0");
472         return PKG_NONE_MEMORY;
473     }
474     size_t inLength = static_cast<size_t>(inBuffSize);
475     size_t outLength = static_cast<size_t>(outBuffSize);
476     PkgBuffer inBuffer(nullptr, inLength);
477     PkgBuffer outBuffer(outLength);
478     if (outBuffer.buffer == nullptr) {
479         (void)LZ4F_freeDecompressionContext(ctx);
480         PKG_LOGE("Fail to alloc buffer ");
481         return PKG_NONE_MEMORY;
482     }
483     struct PkgBufferMessage msg { unpackText, inBuffer, outBuffer, inLength, outLength};
484     ret = UnpackDecode(inStream, outStream, msg, nextToRead, ctx);
485 
486     errorCode = LZ4F_freeDecompressionContext(ctx);
487     if (LZ4F_isError(errorCode)) {
488         PKG_LOGE("Fail to free compress context %s", LZ4F_getErrorName(errorCode));
489         return PKG_NONE_MEMORY;
490     }
491     context.packedSize = msg.context.srcOffset - context.srcOffset;
492     context.unpackedSize = msg.context.destOffset - context.destOffset;
493     return ret;
494 }
495 
UpdateFileInfo(PkgManager::FileInfoPtr info) const496 void PkgAlgorithmLz4::UpdateFileInfo(PkgManager::FileInfoPtr info) const
497 {
498     Lz4FileInfo *lz4Info = (Lz4FileInfo *)info;
499     lz4Info->fileInfo.packMethod = PKG_COMPRESS_METHOD_LZ4;
500     lz4Info->fileInfo.digestMethod = PKG_DIGEST_TYPE_NONE;
501     lz4Info->compressionLevel = compressionLevel_;
502     lz4Info->blockIndependence = blockIndependence_;
503     lz4Info->contentChecksumFlag = contentChecksumFlag_;
504     lz4Info->blockSizeID = blockSizeID_;
505     lz4Info->autoFlush = autoFlush_;
506 }
507 } // namespace Hpackage
508