From 237a627fdcb2228bf35e07d2d1ff52246326395f Mon Sep 17 00:00:00 2001 From: tobozo Date: Wed, 11 May 2022 09:52:56 +0200 Subject: [PATCH 1/6] documentation update --- README.md | 3 ++- library.properties | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) 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 [![arduino-library-badge](https://www.ardu-badge.com/badge/ESP32-targz.svg?)](https://www.ardu-badge.com/ESP32-targz) +[![PlatformIO Registry](https://badges.registry.platformio.org/packages/tobozo/library/ESP32-targz.svg)](https://registry.platformio.org/packages/libraries/tobozo/ESP32-targz)

ES32-targz logo @@ -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..fd3debe 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 From 8932d7a419052274cef550ef694860092eb9dc07 Mon Sep 17 00:00:00 2001 From: tobozo Date: Mon, 29 Aug 2022 12:55:39 +0200 Subject: [PATCH 2/6] Fix crash in tarUnpacker --- src/TinyUntar/untar.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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--; From 2fce64dd5cfa72e9dfb4988596853b90d3fa14d4 Mon Sep 17 00:00:00 2001 From: tobozo Date: Mon, 29 Aug 2022 14:27:51 +0200 Subject: [PATCH 3/6] Fix [-Wformat-truncation=] error --- src/ESP32-targz-lib.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ESP32-targz-lib.cpp b/src/ESP32-targz-lib.cpp index dbd0e03..3289ab2 100644 --- a/src/ESP32-targz-lib.cpp +++ b/src/ESP32-targz-lib.cpp @@ -587,8 +587,10 @@ 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] == '/' ) { - snprintf( file_path, 101, "%s", header->filename ); // TAR paths are limited to 100 chars - snprintf( header->filename, 101, "%s", &file_path[2] ); + int truncate_res = snprintf( file_path, 101, "%s", header->filename ); // TAR paths are limited to 100 chars + if( truncate_res >=0 ) { + snprintf( header->filename, 101, "%s", &file_path[2] ); + } } memset( file_path, 0, 256 ); if( strcmp( tarDestFolder, FOLDER_SEPARATOR ) != 0 ) { From 6d8d2c294f61559ef100fb99579988a9de615ce0 Mon Sep 17 00:00:00 2001 From: tobozo Date: Fri, 30 Sep 2022 17:34:28 +0200 Subject: [PATCH 4/6] Added GzUpdateClass for ESP32 --- src/ESP32-targz-lib.cpp | 107 +++++++++++++++++- ...{ESP32-targz-lib.h => ESP32-targz-lib.hpp} | 82 ++++++++++++++ src/ESP32-targz.h | 6 +- 3 files changed, 187 insertions(+), 8 deletions(-) rename src/{ESP32-targz-lib.h => ESP32-targz-lib.hpp} (86%) diff --git a/src/ESP32-targz-lib.cpp b/src/ESP32-targz-lib.cpp index 3289ab2..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,10 +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] == '/' ) { - int truncate_res = snprintf( file_path, 101, "%s", header->filename ); // TAR paths are limited to 100 chars - if( truncate_res >=0 ) { - snprintf( header->filename, 101, "%s", &file_path[2] ); - } + #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 ) { @@ -2137,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 From 81aabcfe4a7290d24d7d12d8361e936c0ff460cb Mon Sep 17 00:00:00 2001 From: tobozo Date: Fri, 30 Sep 2022 17:34:43 +0200 Subject: [PATCH 5/6] added includes entry --- library.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/library.properties b/library.properties index fd3debe..da4db85 100644 --- a/library.properties +++ b/library.properties @@ -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 From 10b1353f94a6627582cf72b2b405a91302237e08 Mon Sep 17 00:00:00 2001 From: tobozo Date: Fri, 30 Sep 2022 17:34:52 +0200 Subject: [PATCH 6/6] added linter --- .github/workflows/lint.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/workflows/lint.yml 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 +