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