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 19using namespace Hpackage; 20 21namespace UpdatePatch { 22int32_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 34int32_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 48int32_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 83int32_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 113int32_t BZip2StreamAdapter::Open() 114{ 115 buffer_.resize(IGMDIFF_LIMIT_UNIT); 116 return BZip2Adapter::Open(); 117} 118 119int32_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} 153int32_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 184int32_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"); 192 return -1; 193 } 194 195 PATCH_DEBUG("BZip2BufferReadAdapter::Open %zu dataLength_ %zu", offset_, dataLength_); 196 (void)memset_s(&stream_, sizeof(bz_stream), 0, sizeof(bz_stream)); 197 int32_t ret = BZ2_bzDecompressInit(&stream_, 0, 0); 198 if (ret != BZ_OK) { 199 PATCH_LOGE("Failed to open read mem ret %d", ret); 200 return -1; 201 } 202 stream_.avail_in = static_cast<unsigned int>(dataLength_); 203 stream_.next_in = reinterpret_cast<char*>(buffer_.buffer + offset_); 204 205 init_ = true; 206 return PATCH_SUCCESS; 207} 208 209int32_t BZip2BufferReadAdapter::Close() 210{ 211 if (!init_) { 212 return PATCH_SUCCESS; 213 } 214 int32_t ret = 0; 215 ret = BZ2_bzDecompressEnd(&stream_); 216 if (ret != BZ_OK) { 217 PATCH_LOGE("Failed to close read mem ret %d", ret); 218 return -1; 219 } 220 init_ = false; 221 return PATCH_SUCCESS; 222} 223 224int32_t BZip2BufferReadAdapter::ReadData(BlockBuffer &info) 225{ 226 if (!init_) { 227 PATCH_LOGE("State error %d", init_); 228 return -1; 229 } 230 int32_t ret = 0; 231 size_t readLen = 0; 232 stream_.next_out = reinterpret_cast<char*>(info.buffer); 233 stream_.avail_out = info.length; 234 while (1) { 235 ret = BZ2_bzDecompress(&stream_); 236 if (ret == BZ_STREAM_END) { 237 readLen = info.length - stream_.avail_out; 238 break; 239 } 240 if (ret != BZ_OK) { 241 PATCH_LOGE("Failed to decompress ret %d", ret); 242 return -1; 243 } 244 if (stream_.avail_out == 0) { 245 readLen = info.length; 246 break; 247 } 248 if (stream_.avail_in == 0) { 249 PATCH_LOGE("Not enough buffer to decompress"); 250 return -1; 251 } 252 } 253 if (readLen < info.length) { 254 PATCH_LOGE("Failed to read mem ret %zu length %zu", readLen, info.length); 255 return -1; 256 } 257 return 0; 258} 259} // namespace UpdatePatch 260