diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 3552bb7..df4d819 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -644,6 +644,7 @@ HEADERS += \ src/QGCQGeoCoordinate.h \ src/QGCTemporaryFile.h \ src/QGCToolbox.h \ + src/QGCZlib.h \ src/QmlControls/AppMessages.h \ src/QmlControls/EditPositionDialogController.h \ src/QmlControls/FlightPathSegment.h \ @@ -859,6 +860,7 @@ SOURCES += \ src/QGCQGeoCoordinate.cc \ src/QGCTemporaryFile.cc \ src/QGCToolbox.cc \ + src/QGCZlib.cc \ src/QmlControls/AppMessages.cc \ src/QmlControls/EditPositionDialogController.cc \ src/QmlControls/FlightPathSegment.cc \ diff --git a/src/QGCZlib.cc b/src/QGCZlib.cc new file mode 100644 index 0000000..77ad1e9 --- /dev/null +++ b/src/QGCZlib.cc @@ -0,0 +1,85 @@ +/**************************************************************************** + * + * (c) 2009-2020 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#include "QGCZlib.h" + +#include +#include +#include + +#include "zlib.h" + +bool QGCZlib::inflateGzipFile(const QString& gzippedFileName, const QString& decompressedFilename) +{ + bool success = true; + int ret; + const int cBuffer = 1024 * 5; + unsigned char inputBuffer[cBuffer]; + unsigned char outputBuffer[cBuffer]; + z_stream strm; + + QFile inputFile(gzippedFileName); + if (!inputFile.open(QIODevice::ReadOnly)) { + qWarning() << "QGCZlib::inflateGzipFile: open input file failed" << gzippedFileName << inputFile.errorString(); + return false; + } + + QFile outputFile(decompressedFilename); + if (!outputFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + qWarning() << "QGCZlib::inflateGzipFile: open input file failed" << outputFile.fileName() << outputFile.errorString(); + return false; + } + + strm.zalloc = nullptr; + strm.zfree = nullptr; + strm.opaque = nullptr; + strm.avail_in = 0; + strm.next_in = nullptr; + + ret = inflateInit2(&strm, 16+MAX_WBITS); + if (ret != Z_OK) { + qWarning() << "QGCZlib::inflateGzipFile: inflateInit2 failed:" << ret; + goto Error; + } + + do { + strm.avail_in = static_cast(inputFile.read((char*)inputBuffer, cBuffer)); + if (strm.avail_in == 0) { + break; + } + strm.next_in = inputBuffer; + + do { + strm.avail_out = cBuffer; + strm.next_out = outputBuffer; + + ret = inflate(&strm, Z_NO_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) { + qWarning() << "QGCZlib::inflateGzipFile: inflate failed:" << ret; + goto Error; + } + + unsigned cBytesInflated = cBuffer - strm.avail_out; + qint64 cBytesWritten = outputFile.write((char*)outputBuffer, static_cast(cBytesInflated)); + if (cBytesWritten != cBytesInflated) { + qWarning() << "QGCZlib::inflateGzipFile: output file write failed:" << outputFile.fileName() << outputFile.errorString(); + goto Error; + + } + } while (strm.avail_out == 0); + } while (ret != Z_STREAM_END); + +Out: + inflateEnd(&strm); + return success; + +Error: + success = false; + goto Out; +} diff --git a/src/QGCZlib.h b/src/QGCZlib.h new file mode 100644 index 0000000..e5fce05 --- /dev/null +++ b/src/QGCZlib.h @@ -0,0 +1,21 @@ +/**************************************************************************** + * + * (c) 2009-2020 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#pragma once + +#include + +class QGCZlib +{ +public: + /// Decompresses the specified file to the specified directory + /// @param gzipFilename Fully qualified path to gzip file + /// @param decompressedFilename Fully qualified path to for file to decompress to + static bool inflateGzipFile(const QString& gzippedFileName, const QString& decompressedFilename); +};