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 "bzip2_adapter.h"
16 #include <iostream>
17 #include "bzlib.h"
18
19 using namespace Hpackage;
20
21 namespace UpdatePatch {
Open()22 int32_t BZip2Adapter::Open()
23 {
24 (void)memset_s(&stream_, sizeof(bz_stream), 0, sizeof(bz_stream));
25 int32_t ret = BZ2_bzCompressInit(&stream_, BLOCK_SIZE_BEST, 0, 0);
26 if (ret != BZ_OK) {
27 PATCH_LOGE("Failed to bzcompressinit %d", ret);
28 return ret;
29 }
30 init_ = true;
31 return ret;
32 }
33
Close()34 int32_t BZip2Adapter::Close()
35 {
36 if (!init_) {
37 return PATCH_SUCCESS;
38 }
39 int32_t ret = BZ2_bzCompressEnd(&stream_);
40 if (ret != BZ_OK) {
41 PATCH_LOGE("Failed to bz_compressEnd %d", ret);
42 return ret;
43 }
44 init_ = false;
45 return ret;
46 }
47
WriteData(const BlockBuffer & srcData)48 int32_t BZipBuffer2Adapter::WriteData(const BlockBuffer &srcData)
49 {
50 stream_.next_in = reinterpret_cast<char*>(srcData.buffer);
51 stream_.avail_in = srcData.length;
52
53 if (offset_ + dataSize_ + srcData.length > buffer_.size()) {
54 buffer_.resize(buffer_.size() + srcData.length);
55 }
56 char *next = reinterpret_cast<char*>(buffer_.data() + offset_ + dataSize_);
57 stream_.avail_out = buffer_.size() - offset_ - dataSize_;
58 stream_.next_out = next;
59 int32_t ret = BZ_RUN_OK;
60 do {
61 ret = BZ2_bzCompress(&stream_, BZ_RUN);
62 if (stream_.avail_in == 0) {
63 break;
64 }
65 } while (ret == BZ_RUN_OK);
66 if (ret != BZ_RUN_OK) {
67 PATCH_LOGE("BZipBuffer2Adapter::WriteData : Failed to write data ret %d", ret);
68 return ret;
69 }
70 if (stream_.avail_in != 0) {
71 PATCH_LOGE("BZipBuffer2Adapter::WriteData : Failed to write data");
72 return ret;
73 }
74 dataSize_ += stream_.next_out - next;
75 return PATCH_SUCCESS;
76 }
77
FlushData(size_t & dataSize)78 int32_t BZipBuffer2Adapter::FlushData(size_t &dataSize)
79 {
80 dataSize = 0;
81 PATCH_DEBUG("FlushData dataSize_ %d ", dataSize_);
82 stream_.next_in = 0;
83 stream_.avail_in = 0;
84 stream_.avail_out = buffer_.size() - offset_ - dataSize_;
85 char *next = reinterpret_cast<char*>(buffer_.data() + offset_ + dataSize_);
86 stream_.next_out = next;
87 int ret = BZ_FINISH_OK;
88 while (ret == BZ_FINISH_OK) {
89 ret = BZ2_bzCompress(&stream_, BZ_FINISH);
90 if (stream_.avail_out == 0) {
91 dataSize_ += stream_.next_out - next;
92 buffer_.resize(buffer_.size() + IGMDIFF_LIMIT_UNIT);
93 stream_.avail_out = buffer_.size() - offset_ - dataSize_;
94 next = reinterpret_cast<char*>(buffer_.data() + offset_ + dataSize_);
95 stream_.next_out = next;
96 }
97 }
98 if (ret != BZ_RUN_OK && ret != BZ_STREAM_END) {
99 PATCH_LOGE("Failed to write data %d", ret);
100 return ret;
101 }
102 dataSize_ += stream_.next_out - next;
103 PATCH_DEBUG("FlushData offset_ %zu dataSize_ %zu ", offset_, dataSize_);
104 dataSize = dataSize_;
105 return 0;
106 }
107
Open()108 int32_t BZip2StreamAdapter::Open()
109 {
110 buffer_.resize(IGMDIFF_LIMIT_UNIT);
111 return BZip2Adapter::Open();
112 }
113
WriteData(const BlockBuffer & srcData)114 int32_t BZip2StreamAdapter::WriteData(const BlockBuffer &srcData)
115 {
116 stream_.next_in = reinterpret_cast<char*>(srcData.buffer);
117 stream_.avail_in = srcData.length;
118
119 stream_.avail_out = buffer_.size();
120 stream_.next_out = reinterpret_cast<char*>(buffer_.data());
121 int32_t ret = BZ_RUN_OK;
122 do {
123 ret = BZ2_bzCompress(&stream_, BZ_RUN);
124 if (stream_.avail_out == 0) {
125 outStream_.write(buffer_.data(), buffer_.size());
126 dataSize_ += stream_.next_out - reinterpret_cast<char*>(buffer_.data());
127 stream_.avail_out = buffer_.size();
128 stream_.next_out = reinterpret_cast<char*>(buffer_.data());
129 }
130 if (stream_.avail_in == 0) {
131 break;
132 }
133 } while (ret == BZ_RUN_OK);
134 if (ret != BZ_RUN_OK) {
135 PATCH_LOGE("BZip2StreamAdapter::WriteData : Failed to write data ret %d", ret);
136 return ret;
137 }
138 if (stream_.avail_in != 0) {
139 PATCH_LOGE("BZip2StreamAdapter::WriteData : Failed to write data");
140 return ret;
141 }
142 if (stream_.avail_out != buffer_.size()) {
143 outStream_.write(buffer_.data(), stream_.next_out - reinterpret_cast<char*>(buffer_.data()));
144 }
145 dataSize_ += stream_.next_out - reinterpret_cast<char*>(buffer_.data());
146 return PATCH_SUCCESS;
147 }
FlushData(size_t & dataSize)148 int32_t BZip2StreamAdapter::FlushData(size_t &dataSize)
149 {
150 dataSize = 0;
151 PATCH_DEBUG("FlushData dataSize_ %d ", dataSize_);
152 stream_.next_in = 0;
153 stream_.avail_in = 0;
154 stream_.avail_out = buffer_.size();
155 stream_.next_out = reinterpret_cast<char*>(buffer_.data());
156 int ret = BZ_FINISH_OK;
157 while (ret == BZ_FINISH_OK) {
158 ret = BZ2_bzCompress(&stream_, BZ_FINISH);
159 if (stream_.avail_out == 0) {
160 outStream_.write(buffer_.data(), stream_.next_out - reinterpret_cast<char*>(buffer_.data()));
161 dataSize_ += stream_.next_out - reinterpret_cast<char*>(buffer_.data());
162 stream_.avail_out = buffer_.size();
163 stream_.next_out = reinterpret_cast<char*>(buffer_.data());
164 }
165 }
166 if (ret != BZ_RUN_OK && ret != BZ_STREAM_END) {
167 PATCH_LOGE("Failed to write data %d", ret);
168 return ret;
169 }
170 if (stream_.avail_out != buffer_.size()) {
171 outStream_.write(buffer_.data(), stream_.next_out - reinterpret_cast<char*>(buffer_.data()));
172 }
173 dataSize_ += stream_.next_out - reinterpret_cast<char*>(buffer_.data());
174 PATCH_DEBUG("FlushData dataSize %zu %zu", dataSize_, static_cast<size_t>(outStream_.tellp()));
175 dataSize = dataSize_;
176 return 0;
177 }
178
Open()179 int32_t BZip2BufferReadAdapter::Open()
180 {
181 if (init_) {
182 PATCH_LOGE("State error %d", init_);
183 return -1;
184 }
185 if (dataLength_ > buffer_.length) {
186 PATCH_LOGE("Invalid buffer length");
187 return -1;
188 }
189
190 PATCH_DEBUG("BZip2BufferReadAdapter::Open %zu dataLength_ %zu", offset_, dataLength_);
191 (void)memset_s(&stream_, sizeof(bz_stream), 0, sizeof(bz_stream));
192 int32_t ret = BZ2_bzDecompressInit(&stream_, 0, 0);
193 if (ret != BZ_OK) {
194 PATCH_LOGE("Failed to open read mem ret %d", ret);
195 return -1;
196 }
197 stream_.avail_in = static_cast<unsigned int>(dataLength_);
198 stream_.next_in = reinterpret_cast<char*>(buffer_.buffer + offset_);
199
200 init_ = true;
201 return PATCH_SUCCESS;
202 }
203
Close()204 int32_t BZip2BufferReadAdapter::Close()
205 {
206 if (!init_) {
207 return PATCH_SUCCESS;
208 }
209 int32_t ret = 0;
210 ret = BZ2_bzDecompressEnd(&stream_);
211 if (ret != BZ_OK) {
212 PATCH_LOGE("Failed to close read mem ret %d", ret);
213 return -1;
214 }
215 init_ = false;
216 return PATCH_SUCCESS;
217 }
218
ReadData(BlockBuffer & info)219 int32_t BZip2BufferReadAdapter::ReadData(BlockBuffer &info)
220 {
221 if (!init_) {
222 PATCH_LOGE("State error %d", init_);
223 return -1;
224 }
225 int32_t ret = 0;
226 size_t readLen = 0;
227 stream_.next_out = reinterpret_cast<char*>(info.buffer);
228 stream_.avail_out = info.length;
229 while (1) {
230 ret = BZ2_bzDecompress(&stream_);
231 if (ret == BZ_STREAM_END) {
232 readLen = info.length - stream_.avail_out;
233 break;
234 }
235 if (ret != BZ_OK) {
236 PATCH_LOGE("Failed to decompress ret %d", ret);
237 return -1;
238 }
239 if (stream_.avail_out == 0) {
240 readLen = info.length;
241 break;
242 }
243 if (stream_.avail_in == 0) {
244 PATCH_LOGE("Not enough buffer to decompress");
245 return -1;
246 }
247 }
248 if (readLen < info.length) {
249 PATCH_LOGE("Failed to read mem ret %zu length %zu", readLen, info.length);
250 return -1;
251 }
252 return 0;
253 }
254 } // namespace UpdatePatch
255