diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
new file mode 100644
index 0000000..de92b20
--- /dev/null
+++ b/.github/workflows/lint.yml
@@ -0,0 +1,31 @@
+name: Lint
+
+on:
+ push:
+ paths:
+ - '**.ino'
+ - '**.ini'
+ - '**.cpp'
+ - '**.hpp'
+ - '**.h'
+ - '**.c'
+ - '**lint.yml'
+
+ pull_request:
+ branches:
+ - main
+
+ workflow_dispatch:
+
+jobs:
+
+ lint:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: arduino/arduino-lint-action@v1
+ with:
+ project-type: library
+ library-manager: false
+ recursive: true
+
diff --git a/README.md b/README.md
index fabd46d..10c0d04 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,7 @@
## An ESP32/ESP8266 Arduino library to provide decompression support for .tar, .gz and .tar.gz files
[](https://www.ardu-badge.com/ESP32-targz)
+[](https://registry.platformio.org/packages/libraries/tobozo/ESP32-targz)
@@ -180,7 +181,7 @@ Flash the ESP with contents from `.gz` file
GZUnpacker->setGzProgressCallback( BaseUnpacker::defaultProgressCallback ); // targzNullProgressCallback or defaultProgressCallback
GZUnpacker->setLoggerCallback( BaseUnpacker::targzPrintLoggerCallback ); // gz log verbosity
- if( ! GZUnpacker->gzUpdater(tarGzFS, firmwareFile, /*don't restart after update*/false ) ) {
+ if( ! GZUnpacker->gzUpdater(tarGzFS, firmwareFile, U_FLASH,/*don't restart after update*/false ) ) {
Serial.printf("gzUpdater failed with return code #%d\n", GZUnpacker->tarGzGetError() );
}
diff --git a/library.properties b/library.properties
index 3227618..da4db85 100644
--- a/library.properties
+++ b/library.properties
@@ -1,5 +1,5 @@
name=ESP32-targz
-version=1.1.4
+version=1.1.5
author=tobozo
maintainer=tobozo
sentence=A library to unpack/uncompress tar, gz, and tar.gz files on ESP32 and ESP8266
@@ -7,3 +7,4 @@ paragraph=ESP32-targz is a wrapper for TinyUntar and uzLib to use with fs::FS. I
category=Data Processing
url=https://github.com/tobozo/ESP32-targz/
architectures=esp32,esp8266
+includes=ESP32-targz.h
diff --git a/src/ESP32-targz-lib.cpp b/src/ESP32-targz-lib.cpp
index dbd0e03..9585c7d 100644
--- a/src/ESP32-targz-lib.cpp
+++ b/src/ESP32-targz-lib.cpp
@@ -44,7 +44,7 @@
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
-#include "ESP32-targz-lib.h"
+#include "ESP32-targz-lib.hpp"
struct TarGzIO
{
@@ -587,8 +587,11 @@ int TarUnpacker::tarHeaderCallBack( TAR::header_translated_t *header, CC_UNUSED
char file_path[256] = {0};
// check that TAR path does not start with "./" and truncate if necessary
if( header->filename[0] == '.' && header->filename[1] == '/' ) {
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wformat-truncation"
snprintf( file_path, 101, "%s", header->filename ); // TAR paths are limited to 100 chars
snprintf( header->filename, 101, "%s", &file_path[2] );
+ #pragma GCC diagnostic pop
}
memset( file_path, 0, 256 );
if( strcmp( tarDestFolder, FOLDER_SEPARATOR ) != 0 ) {
@@ -2135,6 +2138,102 @@ bool TarGzUnpacker::tarGzStreamExpander( Stream *stream, fs::FS &destFS, const c
+#if defined ESP32
+
+
+/** GzUpdateClass Class implementation **/
+
+bool GzUpdateClass::begingz(size_t size, int command, int ledPin, uint8_t ledOn, const char *label)
+{
+ if( !gzProgressCallback ) {
+ log_d("Setting progress cb");
+ gzUnpacker.setGzProgressCallback( gzUnpacker.defaultProgressCallback );
+ }
+ if( !tgzLogger ) {
+ log_d("Setting logger cb");
+ gzUnpacker.setLoggerCallback( gzUnpacker.targzPrintLoggerCallback );
+ }
+ if( gzWriteCallback == nullptr ) {
+ log_d("Setting write cb");
+ gzUnpacker.setStreamWriter( gzUpdateWriteCallback );
+ //gzUnpacker.setStreamWriter( Update.write );
+ }
+
+ mode_gz = true;
+
+ bool ret = begin(size, command, ledPin, ledOn, label);
+
+ return ret;
+}
+
+
+
+bool GzUpdateClass::gzUpdateWriteCallback( unsigned char* buff, size_t buffsize )
+{
+ if( GzUpdateClass::getInstance().write( buff, buffsize ) ) {
+ log_v("Wrote %d bytes", buffsize );
+ return true;
+ }
+ log_e("Failed to write %d bytes", buffsize );
+ return false;
+}
+
+
+void GzUpdateClass::abortgz()
+{
+ abort();
+ gzUnpacker.gzExpanderCleanup();
+ mode_gz = false;
+}
+
+
+bool GzUpdateClass::endgz(bool evenIfRemaining)
+{
+ gzUnpacker.gzExpanderCleanup();
+ mode_gz = false;
+ return end(evenIfRemaining);
+}
+
+
+size_t GzUpdateClass::writeGzStream(Stream &data, size_t len)
+{
+ if (!mode_gz) {
+ log_d("Not in gz mode");
+ return writeStream(data);
+ }
+
+ size_t size = data.available();
+ if( ! size ) {
+ log_e("Bad stream, aborting");
+ //gzUnpacker.setError( ESP32_TARGZ_STREAM_ERROR );
+ return 0;
+ }
+
+ log_d("In gz mode");
+
+ tarGzIO.gz = &data;
+ // process with unzipping
+ bool show_progress = false;
+ bool use_dict = true;
+ bool isupdate = true;
+ bool stream_to_tar = false;
+ int ret = gzUnpacker.gzUncompress( isupdate, stream_to_tar, use_dict, show_progress );
+ // unzipping ended
+ if( ret!=0 ) {
+ log_e("gzHTTPUpdater returned error code %d", ret);
+ //gzUnpacker.setError( (tarGzErrorCode)ret );
+ return 0;
+ }
+
+ log_d("unpack complete (%d bytes)", tarGzIO.gz_size );
+
+ return len;
+}
+
+#endif
+
+
+
#ifdef ESP8266
#pragma GCC diagnostic pop
#endif
diff --git a/src/ESP32-targz-lib.h b/src/ESP32-targz-lib.hpp
similarity index 86%
rename from src/ESP32-targz-lib.h
rename to src/ESP32-targz-lib.hpp
index 99ca03a..0e8992e 100644
--- a/src/ESP32-targz-lib.h
+++ b/src/ESP32-targz-lib.hpp
@@ -280,6 +280,88 @@ struct TarGzUnpacker : public TarUnpacker, public GzUnpacker
};
+
+
+#if defined ESP32
+
+
+class GzUpdateClass : public UpdateClass {
+
+ GzUpdateClass(){}; // hidden c-tor
+ ~GzUpdateClass(){}; // hidden d-tor
+
+ bool mode_gz = false; // needed to keep mode state for async writez() calls
+ int command = U_FLASH; // needed to keep track of the destination partition
+ GzUnpacker gzUnpacker;
+
+ /**
+ * @brief callback for GzUnpacker
+ * writes inflated firmware chunk to flash
+ *
+ */
+ //int flash_cb(size_t index, const uint8_t* data, size_t size, bool final); //> inflate_cb_t
+
+ public:
+ // this is a singleton, no copy's
+ GzUpdateClass(const GzUpdateClass&) = delete;
+ GzUpdateClass& operator=(const GzUpdateClass &) = delete;
+ GzUpdateClass(GzUpdateClass &&) = delete;
+ GzUpdateClass & operator=(GzUpdateClass &&) = delete;
+
+ static GzUpdateClass& getInstance(){
+ static GzUpdateClass flashz;
+ return flashz;
+ }
+
+ /**
+ * @brief initilize GzUnpacker structs and UpdaterClass
+ *
+ * @return true on success
+ * @return false on GzUnpacker mem allocation error or flash free space error
+ */
+ bool begingz(size_t size=UPDATE_SIZE_UNKNOWN, int command = U_FLASH, int ledPin = -1, uint8_t ledOn = LOW, const char *label = NULL);
+
+ /**
+ * @brief Writes a buffer to the flash
+ * Returns true on success
+ *
+ * @param buff
+ * @param buffsize
+ * @return processed bytes
+ */
+ //size_t writez(const uint8_t *data, size_t len, bool final);
+ static bool gzUpdateWriteCallback( unsigned char* buff, size_t buffsize );
+
+ /**
+ * @brief Read zlib compressed data from stream, decompress and write it to flash
+ * size of the stream must be known in order to signal zlib inflator last chunk
+ *
+ * @param data Stream object, usually data from a tcp socket
+ * @param len total length of compressed data to read from stream
+ * @return size_t number of bytes processed from a stream
+ */
+ size_t writeGzStream(Stream &data, size_t len);
+
+ /**
+ * @brief abort running inflator and flash update process
+ * also releases inflator memory
+ */
+ void abortgz();
+
+ /**
+ * @brief release inflator memory and run UpdateClass.end()
+ * returns status of end() call
+ *
+ * @return true
+ * @return false
+ */
+ bool endgz(bool evenIfRemaining = true);
+
+};
+
+#endif
+
+
#ifdef ESP8266
// some ESP32 => ESP8266 syntax shim
diff --git a/src/ESP32-targz.h b/src/ESP32-targz.h
index 894aaf8..b2570f7 100644
--- a/src/ESP32-targz.h
+++ b/src/ESP32-targz.h
@@ -108,7 +108,7 @@
// required filesystem helpers are declared outside the main library
// because ESP32/ESP8266 use different abstraction flavours :)
-size_t targzFreeBytesFn() {
+__attribute__((unused)) static size_t targzFreeBytesFn() {
#if defined DEST_FS_USES_SPIFFS || defined DEST_FS_USES_SD || defined DEST_FS_USES_SD_MMC || defined DEST_FS_USES_LITTLEFS || defined DEST_FS_USES_PSRAMFS
#if defined ESP32
return tarGzFS.totalBytes() - tarGzFS.usedBytes();
@@ -129,7 +129,7 @@ size_t targzFreeBytesFn() {
#endif
}
-size_t targzTotalBytesFn() {
+__attribute__((unused)) static size_t targzTotalBytesFn() {
#if defined DEST_FS_USES_SPIFFS || defined DEST_FS_USES_SD || defined DEST_FS_USES_SD_MMC || defined DEST_FS_USES_LITTLEFS || defined DEST_FS_USES_FFAT || defined DEST_FS_USES_PSRAMFS
#if defined ESP32
return tarGzFS.totalBytes();
@@ -149,6 +149,6 @@ size_t targzTotalBytesFn() {
}
-#include "ESP32-targz-lib.h"
+#include "ESP32-targz-lib.hpp"
#endif
diff --git a/src/TinyUntar/untar.c b/src/TinyUntar/untar.c
index abbc26d..b270db5 100644
--- a/src/TinyUntar/untar.c
+++ b/src/TinyUntar/untar.c
@@ -1,6 +1,6 @@
#include "untar.h"
-char *empty_string = "";
+const char *empty_string = "";
entry_callbacks_t *read_tar_callbacks = NULL;
unsigned char *read_buffer = NULL;
header_t header;
@@ -68,7 +68,7 @@ char *trim(char *raw, int length) {
}
}
if(is_empty == 1)
- return empty_string;
+ return (char*)empty_string;
// Determine right padding.
while((raw[j] == 0 || raw[j] == ' ')) {
j--;