Browse Source

QGCCLZMA: use xz-embedded lib

QGC4.4
Beat Küng 4 years ago committed by Lorenz Meier
parent
commit
1a3e01bb3f
  1. 138
      src/Compression/QGCLZMA.cc
  2. 2
      src/Vehicle/ComponentInformationManager.cc

138
src/Compression/QGCLZMA.cc

@ -13,16 +13,10 @@ @@ -13,16 +13,10 @@
#include <QDir>
#include <QtDebug>
#include "lzma.h"
#include "xz.h"
bool QGCLZMA::inflateLZMAFile(const QString& lzmaFilename, const QString& decompressedFilename)
{
bool success = true;
const int cBuffer = 1024 * 5;
unsigned char inputBuffer[cBuffer];
unsigned char outputBuffer[cBuffer];
lzma_stream lzmaStrm = LZMA_STREAM_INIT;
QFile inputFile(lzmaFilename);
if (!inputFile.open(QIODevice::ReadOnly)) {
qWarning() << "QGCLZMA::inflateLZMAFile: open input file failed" << lzmaFilename << inputFile.errorString();
@ -35,63 +29,99 @@ bool QGCLZMA::inflateLZMAFile(const QString& lzmaFilename, const QString& decomp @@ -35,63 +29,99 @@ bool QGCLZMA::inflateLZMAFile(const QString& lzmaFilename, const QString& decomp
return false;
}
// UINT64_MAX - used as much memory as needed to decode
int lzmaRetCode = lzma_alone_decoder(&lzmaStrm, UINT64_MAX);
if (lzmaRetCode != LZMA_OK) {
qWarning() << "QGCLZMA::inflateLZMAFile: lzma_alone_decoder failed:" << lzmaRetCode;
// TODO: call once during startup
xz_crc32_init();
xz_crc64_init();
xz_dec *s = xz_dec_init(XZ_DYNALLOC, (uint32_t)-1);
if (s == nullptr) {
qWarning() << "QGCLZMA::inflateLZMAFile: Memory allocation failed";
return false;
}
// When LZMA_CONCATENATED flag was used when initializing the decoder,
// we need to tell lzma_code() when there will be no more input.
// This is done by setting action to LZMA_FINISH instead of LZMA_RUN
// in the same way as it is done when encoding.
//
// When LZMA_CONCATENATED isn't used, there is no need to use
// LZMA_FINISH to tell when all the input has been read, but it
// is still OK to use it if you want. When LZMA_CONCATENATED isn't
// used, the decoder will stop after the first .xz stream. In that
// case some unused data may be left in lzmaStrm.next_in.
lzma_action action = LZMA_RUN;
lzmaStrm.next_in = nullptr;
lzmaStrm.avail_in = 0;
lzmaStrm.next_out = nullptr;
lzmaStrm.avail_out = cBuffer;
do {
lzmaStrm.avail_in = static_cast<unsigned>(inputFile.read((char*)inputBuffer, cBuffer));
if (lzmaStrm.avail_in == 0) {
break;
const int buf_size = 4 * 1024;
uint8_t in[buf_size];
uint8_t out[buf_size];
xz_buf b;
b.in = in;
b.in_pos = 0;
b.in_size = 0;
b.out = out;
b.out_pos = 0;
b.out_size = buf_size;
while (true) {
if (b.in_pos == b.in_size) {
b.in_size = static_cast<size_t>(inputFile.read((char*)in, sizeof(in)));
b.in_pos = 0;
}
lzmaStrm.next_in = inputBuffer;
do {
lzmaStrm.avail_out = cBuffer;
lzmaStrm.next_out = outputBuffer;
xz_ret ret = xz_dec_run(s, &b);
lzmaRetCode = lzma_code(&lzmaStrm, action);
if (lzmaRetCode != LZMA_OK && lzmaRetCode != LZMA_STREAM_END) {
qWarning() << "QGCLZMA::inflateLZMAFile: inflate failed:" << lzmaRetCode;
goto Error;
if (b.out_pos == sizeof(out)) {
size_t cBytesWritten = (size_t)outputFile.write((char*)out, static_cast<int>(b.out_pos));
if (cBytesWritten != b.out_pos) {
qWarning() << "QGCLZMA::inflateLZMAFile: output file write failed:" << outputFile.fileName() << outputFile.errorString();
goto error;
}
unsigned cBytesInflated = cBuffer - lzmaStrm.avail_out;
qint64 cBytesWritten = outputFile.write((char*)outputBuffer, static_cast<int>(cBytesInflated));
if (cBytesWritten != cBytesInflated) {
qWarning() << "QGCLZMA::inflateLZMAFile: output file write failed:" << outputFile.fileName() << outputFile.errorString();
goto Error;
b.out_pos = 0;
}
}
} while (lzmaStrm.avail_out == 0);
} while (lzmaRetCode != LZMA_STREAM_END);
if (ret == XZ_OK)
continue;
if (ret == XZ_UNSUPPORTED_CHECK) {
qWarning() << "QGCLZMA::inflateLZMAFile: Unsupported check; not verifying file integrity";
continue;
}
size_t cBytesWritten = (size_t)outputFile.write((char*)out, static_cast<int>(b.out_pos));
if (cBytesWritten != b.out_pos) {
qWarning() << "QGCLZMA::inflateLZMAFile: output file write failed:" << outputFile.fileName() << outputFile.errorString();
goto error;
}
switch (ret) {
case XZ_STREAM_END:
xz_dec_end(s);
return true;
case XZ_MEM_ERROR:
qWarning() << "QGCLZMA::inflateLZMAFile: Memory allocation failed";
goto error;
case XZ_MEMLIMIT_ERROR:
qWarning() << "QGCLZMA::inflateLZMAFile: Memory usage limit reached";
goto error;
case XZ_FORMAT_ERROR:
qWarning() << "QGCLZMA::inflateLZMAFile: Not a .xz file";
goto error;
case XZ_OPTIONS_ERROR:
qWarning() << "QGCLZMA::inflateLZMAFile: Unsupported options in the .xz headers";
goto error;
case XZ_DATA_ERROR:
case XZ_BUF_ERROR:
qWarning() << "QGCLZMA::inflateLZMAFile: File is corrupt";
goto error;
default:
qWarning() << "QGCLZMA::inflateLZMAFile: Bug!";
goto error;
}
}
Out:
lzma_end(&lzmaStrm);
xz_dec_end(s);
return true;
return success;
error:
xz_dec_end(s);
return false;
Error:
success = false;
goto Out;
}

2
src/Vehicle/ComponentInformationManager.cc

@ -210,7 +210,7 @@ QString RequestMetaDataTypeStateMachine::_downloadCompleteJsonWorker(const QStri @@ -210,7 +210,7 @@ QString RequestMetaDataTypeStateMachine::_downloadCompleteJsonWorker(const QStri
{
QString outputFileName = fileName;
if (fileName.endsWith(".lzma", Qt::CaseInsensitive)) {
if (fileName.endsWith(".lzma", Qt::CaseInsensitive) || fileName.endsWith(".xz", Qt::CaseInsensitive)) {
outputFileName = (QDir(QStandardPaths::writableLocation(QStandardPaths::TempLocation)).absoluteFilePath(inflatedFileName));
if (QGCLZMA::inflateLZMAFile(fileName, outputFileName)) {
QFile(fileName).remove();

Loading…
Cancel
Save