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