You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
87 lines
2.5 KiB
87 lines
2.5 KiB
// Copyright 2017 The Chromium OS Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "bsdiff/bz2_decompressor.h"
|
|
|
|
#include <algorithm>
|
|
#include <limits>
|
|
|
|
#include <bzlib.h>
|
|
|
|
#include "bsdiff/logging.h"
|
|
|
|
namespace bsdiff {
|
|
|
|
BZ2Decompressor::~BZ2Decompressor() {
|
|
// Release the memory on destruction if needed.
|
|
if (stream_initialized_)
|
|
BZ2_bzDecompressEnd(&stream_);
|
|
}
|
|
|
|
bool BZ2Decompressor::SetInputData(const uint8_t* input_data, size_t size) {
|
|
// TODO(xunchang) update the avail_in for size > 2GB.
|
|
if (size > std::numeric_limits<unsigned int>::max()) {
|
|
LOG(ERROR) << "Oversized input data" << size;
|
|
return false;
|
|
}
|
|
|
|
stream_.next_in = reinterpret_cast<char*>(const_cast<uint8_t*>(input_data));
|
|
stream_.avail_in = size;
|
|
stream_.bzalloc = nullptr;
|
|
stream_.bzfree = nullptr;
|
|
stream_.opaque = nullptr;
|
|
int bz2err = BZ2_bzDecompressInit(&stream_, 0, 0);
|
|
if (bz2err != BZ_OK) {
|
|
LOG(ERROR) << "Failed to bzinit control stream: " << bz2err;
|
|
return false;
|
|
}
|
|
stream_initialized_ = true;
|
|
return true;
|
|
}
|
|
|
|
bool BZ2Decompressor::Read(uint8_t* output_data, size_t bytes_to_output) {
|
|
if (!stream_initialized_) {
|
|
LOG(ERROR) << "BZ2Decompressor not initialized";
|
|
return false;
|
|
}
|
|
stream_.next_out = reinterpret_cast<char*>(output_data);
|
|
while (bytes_to_output > 0) {
|
|
size_t output_size = std::min<size_t>(
|
|
std::numeric_limits<unsigned int>::max(), bytes_to_output);
|
|
stream_.avail_out = output_size;
|
|
|
|
size_t prev_avail_in = stream_.avail_in;
|
|
int bz2err = BZ2_bzDecompress(&stream_);
|
|
if (bz2err != BZ_OK && bz2err != BZ_STREAM_END) {
|
|
LOG(ERROR) << "Failed to decompress " << output_size
|
|
<< " bytes of data, error: " << bz2err;
|
|
return false;
|
|
}
|
|
bytes_to_output -= (output_size - stream_.avail_out);
|
|
if (bytes_to_output && prev_avail_in == stream_.avail_in &&
|
|
output_size == stream_.avail_out) {
|
|
LOG(ERROR) << "BZ2Decompressor made no progress, pending "
|
|
<< bytes_to_output << " bytes to decompress";
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool BZ2Decompressor::Close() {
|
|
if (!stream_initialized_) {
|
|
LOG(ERROR) << "BZ2Decompressor not initialized";
|
|
return false;
|
|
}
|
|
int bz2err = BZ2_bzDecompressEnd(&stream_);
|
|
if (bz2err != BZ_OK) {
|
|
LOG(ERROR) << "BZ2_bzDecompressEnd returns with " << bz2err;
|
|
return false;
|
|
}
|
|
stream_initialized_ = false;
|
|
return true;
|
|
}
|
|
|
|
} // namespace bsdiff
|