• 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 #include "pkg_algo_deflate.h"
16 #include "pkg_stream.h"
17 #include "pkg_utils.h"
18 #include "securec.h"
19 #include "zlib.h"
20 
21 namespace Hpackage {
22 constexpr uint32_t DEFLATE_IN_BUFFER_SIZE = 1024 * 64;
23 constexpr uint32_t DEFLATE_OUT_BUFFER_SIZE = 1024 * 32;
24 constexpr uint32_t INFLATE_IN_BUFFER_SIZE = 1024 * 1024 * 1024;
25 constexpr uint32_t INFLATE_OUT_BUFFER_SIZE = 1024 * 1024;
26 
DeflateData(const PkgStreamPtr outStream,z_stream & zstream,int32_t flush,PkgBuffer & outBuffer,size_t & destOffset) const27 int32_t PkgAlgoDeflate::DeflateData(const PkgStreamPtr outStream, z_stream &zstream, int32_t flush,
28     PkgBuffer &outBuffer, size_t &destOffset) const
29 {
30     int32_t ret = Z_OK;
31     do {
32         size_t deflateLen = 0;
33         ret = deflate(&zstream, flush);
34         if (ret < Z_OK) {
35             PKG_LOGE("deflate finish error ret1 %d", ret);
36             return PKG_NOT_EXIST_ALGORITHM;
37         }
38         deflateLen += outBuffer.length - zstream.avail_out;
39         if (deflateLen > 0) {
40             int32_t ret1 = outStream->Write(outBuffer, deflateLen, destOffset);
41             if (ret1 != PKG_SUCCESS) {
42                 PKG_LOGE("error write data deflateLen: %zu", deflateLen);
43                 break;
44             }
45             destOffset += deflateLen;
46             zstream.next_out = outBuffer.buffer;
47             zstream.avail_out = outBuffer.length;
48         }
49         if (flush == Z_NO_FLUSH) {
50             break;
51         }
52     } while (ret == Z_OK && flush == Z_FINISH);
53     return PKG_SUCCESS;
54 }
55 
PackCalculate(PkgAlgorithmContext & context,const PkgStreamPtr inStream,const PkgStreamPtr outStream,const DigestAlgorithm::DigestAlgorithmPtr algorithm)56 int32_t PkgAlgoDeflate::PackCalculate(PkgAlgorithmContext &context, const PkgStreamPtr inStream,
57     const PkgStreamPtr outStream, const DigestAlgorithm::DigestAlgorithmPtr algorithm)
58 {
59     PkgBuffer inBuffer = {};
60     PkgBuffer outBuffer = {};
61     z_stream zstream;
62     int32_t ret = InitStream(zstream, true, inBuffer, outBuffer);
63     if (ret != PKG_SUCCESS) {
64         PKG_LOGE("fail InitStream");
65         return ret;
66     }
67     size_t remainSize = context.unpackedSize;
68     uint32_t crc = 0;
69     size_t srcOffset = context.srcOffset;
70     size_t destOffset = context.destOffset;
71     PkgBuffer crcResult((uint8_t *)&crc, sizeof(crc));
72 
73     while ((remainSize > 0) || (zstream.avail_in > 0)) {
74         size_t readLen = 0;
75         if (zstream.avail_in == 0) {
76             ret = ReadData(inStream, srcOffset, inBuffer, remainSize, readLen);
77             if (ret != PKG_SUCCESS) {
78                 PKG_LOGE("Read data fail!");
79                 break;
80             }
81             zstream.next_in = reinterpret_cast<unsigned char *>(inBuffer.buffer);
82             zstream.avail_in = readLen;
83             srcOffset += readLen;
84             // Calculate CRC of original file
85             algorithm->Calculate(crcResult, inBuffer, readLen);
86         }
87         ret = DeflateData(outStream, zstream, ((remainSize == 0) ? Z_FINISH : Z_NO_FLUSH), outBuffer, destOffset);
88         if (ret != PKG_SUCCESS) {
89             PKG_LOGE("error write data deflateLen: %zu", destOffset);
90             break;
91         }
92     }
93     ReleaseStream(zstream, true);
94     if (ret != PKG_SUCCESS) {
95         PKG_LOGE("error write data");
96         return ret;
97     }
98     if (srcOffset != context.unpackedSize) {
99         PKG_LOGE("original size error %zu %zu", srcOffset, context.unpackedSize);
100         return PKG_INVALID_PKG_FORMAT;
101     }
102     context.crc = crc;
103     context.packedSize = destOffset - context.destOffset;
104     return ret;
105 }
106 
Pack(const PkgStreamPtr inStream,const PkgStreamPtr outStream,PkgAlgorithmContext & context)107 int32_t PkgAlgoDeflate::Pack(const PkgStreamPtr inStream, const PkgStreamPtr outStream,
108     PkgAlgorithmContext &context)
109 {
110     if (inStream == nullptr || outStream == nullptr) {
111         PKG_LOGE("Param context null!");
112         return PKG_INVALID_PARAM;
113     }
114     DigestAlgorithm::DigestAlgorithmPtr algorithm = PkgAlgorithmFactory::GetDigestAlgorithm(context.digestMethod);
115     if (algorithm == nullptr) {
116         PKG_LOGE("Can not get digest algor");
117         return PKG_NOT_EXIST_ALGORITHM;
118     }
119     return PackCalculate(context, inStream, outStream, algorithm);
120 }
121 
ReadUnpackData(const PkgStreamPtr inStream,PkgBuffer & inBuffer,z_stream & zstream,PkgAlgorithmContext & context,size_t & readLen)122 int32_t PkgAlgoDeflate::ReadUnpackData(const PkgStreamPtr inStream, PkgBuffer &inBuffer,
123     z_stream &zstream, PkgAlgorithmContext &context, size_t &readLen)
124 {
125     if (zstream.avail_in == 0) {
126         int32_t ret = ReadData(inStream, context.srcOffset, inBuffer, context.packedSize, readLen);
127         if (ret != PKG_SUCCESS) {
128             PKG_LOGE("Read data fail!");
129             return ret;
130         }
131         zstream.next_in = reinterpret_cast<uint8_t *>(inBuffer.buffer);
132         zstream.avail_in = readLen;
133         context.srcOffset += readLen;
134     }
135     return PKG_SUCCESS;
136 }
137 
CalculateUnpackData(z_stream & zstream,uint32_t & crc,int32_t & ret,PkgAlgorithmContext & context,PkgAlgorithmContext & unpackContext)138 int32_t PkgAlgoDeflate::CalculateUnpackData(z_stream &zstream, uint32_t &crc, int32_t &ret,
139     PkgAlgorithmContext &context, PkgAlgorithmContext &unpackContext)
140 {
141     ReleaseStream(zstream, false);
142     context.packedSize = context.packedSize - zstream.avail_in - unpackContext.packedSize;
143     context.unpackedSize = unpackContext.destOffset - context.destOffset;
144     if (context.crc != 0 && context.crc != crc) {
145         PKG_LOGE("crc fail %u %u!", crc, context.crc);
146         return PKG_VERIFY_FAIL;
147     }
148     context.crc = crc;
149     return (ret == Z_STREAM_END) ? PKG_SUCCESS : ret;
150 }
151 
UnpackCalculate(PkgAlgorithmContext & context,const PkgStreamPtr inStream,const PkgStreamPtr outStream,DigestAlgorithm::DigestAlgorithmPtr algorithm)152 int32_t PkgAlgoDeflate::UnpackCalculate(PkgAlgorithmContext &context, const PkgStreamPtr inStream,
153     const PkgStreamPtr outStream, DigestAlgorithm::DigestAlgorithmPtr algorithm)
154 {
155     z_stream zstream;
156     PkgBuffer inBuffer = {};
157     PkgBuffer outBuffer = {};
158     int32_t ret = InitStream(zstream, false, inBuffer, outBuffer);
159     if (ret != PKG_SUCCESS) {
160         PKG_LOGE("fail InitStream ");
161         return ret;
162     }
163     size_t inflateLen = 0;
164     uint32_t crc = 0;
165 
166     PkgBuffer crcResult((uint8_t *)&crc, sizeof(crc));
167     PkgAlgorithmContext unpackContext = context;
168     size_t readLen = 0;
169     int32_t unpack_ret = Z_OK;
170     while ((unpackContext.packedSize > 0) || (unpack_ret != Z_STREAM_END)) {
171         if (ReadUnpackData(inStream, inBuffer, zstream, unpackContext, readLen) != PKG_SUCCESS) {
172             break;
173         }
174         unpack_ret = inflate(&zstream, Z_SYNC_FLUSH);
175         if (unpack_ret < Z_OK) {
176             PKG_LOGE("fail inflate ret:%d", unpack_ret);
177             break;
178         }
179 
180         if (zstream.avail_out == 0 || (unpack_ret == Z_STREAM_END && zstream.avail_out != INFLATE_OUT_BUFFER_SIZE)) {
181             inflateLen = outBuffer.length - zstream.avail_out;
182             ret = outStream->Write(outBuffer, inflateLen, unpackContext.destOffset);
183             if (ret != PKG_SUCCESS) {
184                 PKG_LOGE("write data is fail!");
185                 break;
186             }
187             unpackContext.destOffset += inflateLen;
188             zstream.next_out = outBuffer.buffer;
189             zstream.avail_out = outBuffer.length;
190 
191             algorithm->Calculate(crcResult, outBuffer, inflateLen);
192         }
193     }
194     return CalculateUnpackData(zstream, crc, unpack_ret, context, unpackContext);
195 }
196 
Unpack(const PkgStreamPtr inStream,const PkgStreamPtr outStream,PkgAlgorithmContext & context)197 int32_t PkgAlgoDeflate::Unpack(const PkgStreamPtr inStream, const PkgStreamPtr outStream,
198     PkgAlgorithmContext &context)
199 {
200     DigestAlgorithm::DigestAlgorithmPtr algorithm = PkgAlgorithmFactory::GetDigestAlgorithm(context.digestMethod);
201     if (algorithm == nullptr) {
202         PKG_LOGE("Can not get digest algor");
203         return PKG_NOT_EXIST_ALGORITHM;
204     }
205     if (inStream == nullptr || outStream == nullptr) {
206         PKG_LOGE("Param context null!");
207         return PKG_INVALID_PARAM;
208     }
209 
210     return UnpackCalculate(context, inStream, outStream, algorithm);
211 }
212 
InitStream(z_stream & zstream,bool zip,PkgBuffer & inBuffer,PkgBuffer & outBuffer)213 int32_t PkgAlgoDeflate::InitStream(z_stream &zstream, bool zip, PkgBuffer &inBuffer, PkgBuffer &outBuffer)
214 {
215     int32_t ret = PKG_SUCCESS;
216     // init zlib stream
217     if (memset_s(&zstream, sizeof(z_stream), 0, sizeof(z_stream)) != EOK) {
218         PKG_LOGE("memset fail");
219         return PKG_NONE_MEMORY;
220     }
221     if (zip) {
222         PKG_LOGI("InitStream level_:%d method_:%d windowBits_:%d memLevel_:%d strategy_:%d",
223             level_, method_, windowBits_, memLevel_, strategy_);
224         ret = deflateInit2(&zstream, level_, method_, windowBits_, memLevel_, strategy_);
225         if (ret != Z_OK) {
226             PKG_LOGE("fail deflateInit2 ret %d", ret);
227             return PKG_NOT_EXIST_ALGORITHM;
228         }
229         inBuffer.length = DEFLATE_IN_BUFFER_SIZE;
230         outBuffer.length = DEFLATE_OUT_BUFFER_SIZE;
231     } else {
232         ret = inflateInit2(&zstream, windowBits_);
233         if (ret != Z_OK) {
234             PKG_LOGE("fail deflateInit2");
235             return PKG_NOT_EXIST_ALGORITHM;
236         }
237         inBuffer.length = INFLATE_IN_BUFFER_SIZE;
238         outBuffer.length = INFLATE_OUT_BUFFER_SIZE;
239     }
240 
241     outBuffer.data.resize(outBuffer.length);
242     outBuffer.buffer = reinterpret_cast<uint8_t *>(outBuffer.data.data());
243     zstream.next_out = outBuffer.buffer;
244     zstream.avail_out = outBuffer.length;
245     return PKG_SUCCESS;
246 }
247 
ReleaseStream(z_stream & zstream,bool zip) const248 void PkgAlgoDeflate::ReleaseStream(z_stream &zstream, bool zip) const
249 {
250     int32_t ret = Z_OK;
251     if (zip) {
252         ret = deflateEnd(&zstream);
253         if (ret != Z_OK) {
254             PKG_LOGE("fail deflateEnd %d", ret);
255             return;
256         }
257     } else {
258         ret = inflateEnd(&zstream);
259         if (ret != Z_OK) {
260             PKG_LOGE("fail inflateEnd %d", ret);
261             return;
262         }
263     }
264 }
265 } // namespace Hpackage
266