/* * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "bzip2_adapter.h" #include <iostream> #include "bzlib.h" using namespace Hpackage; namespace UpdatePatch { int32_t BZip2Adapter::Open() { (void)memset_s(&stream_, sizeof(bz_stream), 0, sizeof(bz_stream)); int32_t ret = BZ2_bzCompressInit(&stream_, BLOCK_SIZE_BEST, 0, 0); if (ret != BZ_OK) { PATCH_LOGE("Failed to bzcompressinit %d", ret); return ret; } init_ = true; return ret; } int32_t BZip2Adapter::Close() { if (!init_) { return PATCH_SUCCESS; } int32_t ret = BZ2_bzCompressEnd(&stream_); if (ret != BZ_OK) { PATCH_LOGE("Failed to bz_compressEnd %d", ret); return ret; } init_ = false; return ret; } int32_t BZipBuffer2Adapter::WriteData(const BlockBuffer &srcData) { stream_.next_in = reinterpret_cast<char*>(srcData.buffer); stream_.avail_in = srcData.length; char *next = reinterpret_cast<char*>(buffer_.data() + offset_ + dataSize_); stream_.avail_out = buffer_.size() - offset_ - dataSize_; stream_.next_out = next; int32_t ret = BZ_RUN_OK; do { ret = BZ2_bzCompress(&stream_, BZ_RUN); if (stream_.avail_out == 0) { dataSize_ += stream_.next_out - next; size_t bufferSize = buffer_.size(); buffer_.resize(bufferSize + IGMDIFF_LIMIT_UNIT); stream_.avail_out = IGMDIFF_LIMIT_UNIT; next = reinterpret_cast<char*>(buffer_.data() + bufferSize); stream_.next_out = next; } if (stream_.avail_in == 0) { break; } } while (ret == BZ_RUN_OK); if (ret != BZ_RUN_OK) { PATCH_LOGE("BZipBuffer2Adapter::WriteData : Failed to write data ret %d", ret); return ret; } if (stream_.avail_in != 0) { PATCH_LOGE("BZipBuffer2Adapter::WriteData : Failed to write data"); return ret; } dataSize_ += stream_.next_out - next; return PATCH_SUCCESS; } int32_t BZipBuffer2Adapter::FlushData(size_t &dataSize) { dataSize = 0; PATCH_DEBUG("FlushData dataSize_ %d ", dataSize_); stream_.next_in = nullptr; stream_.avail_in = 0; stream_.avail_out = buffer_.size() - offset_ - dataSize_; char *next = reinterpret_cast<char*>(buffer_.data() + offset_ + dataSize_); stream_.next_out = next; int ret = BZ_FINISH_OK; while (ret == BZ_FINISH_OK) { ret = BZ2_bzCompress(&stream_, BZ_FINISH); if (stream_.avail_out == 0) { dataSize_ += stream_.next_out - next; buffer_.resize(buffer_.size() + IGMDIFF_LIMIT_UNIT); stream_.avail_out = buffer_.size() - offset_ - dataSize_; next = reinterpret_cast<char*>(buffer_.data() + offset_ + dataSize_); stream_.next_out = next; } } if (ret != BZ_RUN_OK && ret != BZ_STREAM_END) { PATCH_LOGE("Failed to write data %d", ret); return ret; } dataSize_ += stream_.next_out - next; PATCH_DEBUG("FlushData offset_ %zu dataSize_ %zu ", offset_, dataSize_); dataSize = dataSize_; return 0; } int32_t BZip2StreamAdapter::Open() { buffer_.resize(IGMDIFF_LIMIT_UNIT); return BZip2Adapter::Open(); } int32_t BZip2StreamAdapter::WriteData(const BlockBuffer &srcData) { stream_.next_in = reinterpret_cast<char*>(srcData.buffer); stream_.avail_in = srcData.length; stream_.avail_out = buffer_.size(); stream_.next_out = reinterpret_cast<char*>(buffer_.data()); int32_t ret = BZ_RUN_OK; do { ret = BZ2_bzCompress(&stream_, BZ_RUN); if (stream_.avail_out == 0) { outStream_.write(buffer_.data(), buffer_.size()); dataSize_ += stream_.next_out - reinterpret_cast<char*>(buffer_.data()); stream_.avail_out = buffer_.size(); stream_.next_out = reinterpret_cast<char*>(buffer_.data()); } if (stream_.avail_in == 0) { break; } } while (ret == BZ_RUN_OK); if (ret != BZ_RUN_OK) { PATCH_LOGE("BZip2StreamAdapter::WriteData : Failed to write data ret %d", ret); return ret; } if (stream_.avail_in != 0) { PATCH_LOGE("BZip2StreamAdapter::WriteData : Failed to write data"); return ret; } if (stream_.avail_out != buffer_.size()) { outStream_.write(buffer_.data(), stream_.next_out - reinterpret_cast<char*>(buffer_.data())); } dataSize_ += stream_.next_out - reinterpret_cast<char*>(buffer_.data()); return PATCH_SUCCESS; } int32_t BZip2StreamAdapter::FlushData(size_t &dataSize) { dataSize = 0; PATCH_DEBUG("FlushData dataSize_ %d ", dataSize_); stream_.next_in = nullptr; stream_.avail_in = 0; stream_.avail_out = buffer_.size(); stream_.next_out = reinterpret_cast<char*>(buffer_.data()); int ret = BZ_FINISH_OK; while (ret == BZ_FINISH_OK) { ret = BZ2_bzCompress(&stream_, BZ_FINISH); if (stream_.avail_out == 0) { outStream_.write(buffer_.data(), stream_.next_out - reinterpret_cast<char*>(buffer_.data())); dataSize_ += stream_.next_out - reinterpret_cast<char*>(buffer_.data()); stream_.avail_out = buffer_.size(); stream_.next_out = reinterpret_cast<char*>(buffer_.data()); } } if (ret != BZ_RUN_OK && ret != BZ_STREAM_END) { PATCH_LOGE("Failed to write data %d", ret); return ret; } if (stream_.avail_out != buffer_.size()) { outStream_.write(buffer_.data(), stream_.next_out - reinterpret_cast<char*>(buffer_.data())); } dataSize_ += stream_.next_out - reinterpret_cast<char*>(buffer_.data()); PATCH_DEBUG("FlushData dataSize %zu %zu", dataSize_, static_cast<size_t>(outStream_.tellp())); dataSize = dataSize_; return 0; } int32_t BZip2BufferReadAdapter::Open() { if (init_) { PATCH_LOGE("State error %d", init_); return -1; } if (dataLength_ > buffer_.length - offset_) { PATCH_LOGE("Invalid buffer length. dataLength:%zu, buffer_.length:%zu, offset_:%zu", dataLength_, buffer_.length, offset_); return -1; } PATCH_DEBUG("BZip2BufferReadAdapter::Open %zu dataLength_ %zu", offset_, dataLength_); (void)memset_s(&stream_, sizeof(bz_stream), 0, sizeof(bz_stream)); int32_t ret = BZ2_bzDecompressInit(&stream_, 0, 0); if (ret != BZ_OK) { PATCH_LOGE("Failed to open read mem ret %d", ret); return -1; } stream_.avail_in = static_cast<unsigned int>(dataLength_); stream_.next_in = reinterpret_cast<char*>(buffer_.buffer + offset_); init_ = true; return PATCH_SUCCESS; } int32_t BZip2BufferReadAdapter::Close() { if (!init_) { return PATCH_SUCCESS; } int32_t ret = 0; ret = BZ2_bzDecompressEnd(&stream_); if (ret != BZ_OK) { PATCH_LOGE("Failed to close read mem ret %d", ret); return -1; } init_ = false; return PATCH_SUCCESS; } int32_t BZip2BufferReadAdapter::ReadData(BlockBuffer &info) { if (!init_) { PATCH_LOGE("State error %d", init_); return -1; } int32_t ret = 0; size_t readLen = 0; stream_.next_out = reinterpret_cast<char*>(info.buffer); stream_.avail_out = info.length; while (1) { ret = BZ2_bzDecompress(&stream_); if (ret == BZ_STREAM_END) { readLen = info.length - stream_.avail_out; break; } if (ret != BZ_OK) { PATCH_LOGE("Failed to decompress ret %d", ret); return -1; } if (stream_.avail_out == 0) { readLen = info.length; break; } if (stream_.avail_in == 0) { PATCH_LOGE("Not enough buffer to decompress"); return -1; } } if (readLen < info.length) { PATCH_LOGE("Failed to read mem ret %zu length %zu", readLen, info.length); return -1; } return 0; } } // namespace UpdatePatch