diff --git a/src/ESP32-targz.cpp b/src/ESP32-targz.cpp index eaa25d0..4950ca4 100644 --- a/src/ESP32-targz.cpp +++ b/src/ESP32-targz.cpp @@ -37,6 +37,23 @@ int32_t uzlib_bytesleft = 0; //int8_t uzLibLastProgress = -1; unsigned char __attribute__((aligned(4))) uzlib_read_cb_buff[GZIP_BUFF_SIZE]; +tarGzErrorCode _error = ESP32_TARGZ_OK; + +int8_t tarGzGetError() +{ + return (int8_t)_error; +} + +void tarGzClearError() +{ + _error = ESP32_TARGZ_OK; +} + +bool tarGzHasError() +{ + return _error != ESP32_TARGZ_OK; +} + uint8_t *getGzBufferUint8() { return (uint8_t *)uzlib_read_cb_buff; } @@ -145,7 +162,9 @@ static void gzUpdateWriteCallback( unsigned char* buff, size_t buffsize ) { static void gzStreamWriteCallback( unsigned char* buff, size_t buffsize ) { - tarGzStream.output->write( buff, buffsize ); + if( ! tarGzStream.output->write( buff, buffsize ) ) { + _error = ESP32_TARGZ_STREAM_ERROR; + } } @@ -156,8 +175,9 @@ static void gzProcessTarBuffer( CC_UNUSED unsigned char* buff, CC_UNUSED size_t } for( byte i=0;iavailable() ) { - log_e("gz resource doesn't exist!"); - return 1; + tgzLogger("[ERROR] in gzUncompress: gz resource doesn't exist!"); + return ESP32_TARGZ_STREAM_ERROR; } uzlib_gzip_dict = new unsigned char[GZIP_DICT_SIZE]; uzlib_bytesleft = tarGzStream.output_size; @@ -276,31 +301,35 @@ int gzUncompress( bool isupdate = false ) { uzlib_init(); uzLibDecompressor.source = NULL; uzLibDecompressor.source_limit = NULL; + // TODO: malloc() uzlib_read_cb_buff uzLibDecompressor.source_read_cb = gzStreamReadCallback; uzlib_uncompress_init(&uzLibDecompressor, uzlib_gzip_dict, GZIP_DICT_SIZE); int res = uzlib_gzip_parse_header(&uzLibDecompressor); if (res != TINF_OK) { - log_e("uzlib_gzip_parse_header failed!"); + tgzLogger("[ERROR] in gzUncompress: uzlib_gzip_parse_header failed!"); tarGzExpanderCleanup(); - return 5; // Error uncompress header read + return res; // Error uncompress header read } gzProgressCallback( 0 ); while( uzlib_bytesleft>0 ) { int res = gzProcessBlock( isupdate ); - if (res!=0) { + if (res!= TINF_OK ) { tarGzExpanderCleanup(); - return res; + return res; // Error processing block } } gzProgressCallback( 100 ); tarGzExpanderCleanup(); //uzlib_buffer = nullptr; - return 0; + return ESP32_TARGZ_OK; } + + // uncompress gz sourceFile to destFile -void gzExpander( fs::FS sourceFS, const char* sourceFile, fs::FS destFS, const char* destFile ) { +bool gzExpander( fs::FS sourceFS, const char* sourceFile, fs::FS destFS, const char* destFile ) { + tarGzClearError(); if (!tgzLogger ) { setLoggerCallback( tgzPrintLogger ); } @@ -310,12 +339,27 @@ void gzExpander( fs::FS sourceFS, const char* sourceFile, fs::FS destFS, const c setProgressCallback( defaultProgressCallback ); } if( !readGzHeaders( gz ) ) { - log_e("Not a valid gzip file"); + tgzLogger("[ERROR] in gzExpander: Not a valid gzip file"); gz.close(); - return; + _error = ESP32_TARGZ_UZLIB_INVALID_FILE; + return false; } + + //SPIFFSFS + //SDFS + //SDMMCFS + + + if( &(destFS) == &(SPIFFS) ) { + // + } + // TODO: check for available space on destination FS + //int fBytes = destFS.toalBytes() - destFS.usedBytes(); + //tgzLogger("Space available on dest vs required: %d vs %d\n", fBytes, tarGzStream.output_size ); + + if( destFS.exists( destFile ) ) { - log_d("Deleting %s as it is in the way", destFile); + tgzLogger("[INFO] Deleting %s as it is in the way", destFile); destFS.remove( destFile ); } fs::File outfile = destFS.open( destFile, FILE_WRITE ); @@ -323,24 +367,31 @@ void gzExpander( fs::FS sourceFS, const char* sourceFile, fs::FS destFS, const c tarGzStream.output = &outfile; gzWriteCallback = &gzStreamWriteCallback; // for regular unzipping int ret = gzUncompress(); - if( ret!=0 ) tgzLogger("gzUncompress returned error code %d\n", ret); outfile.close(); gz.close(); + if( ret!=0 ) { + tgzLogger("gzUncompress returned error code %d\n", ret); + _error = (tarGzErrorCode)ret; + return false; + } tgzLogger("uzLib expander finished!\n"); + return true; } // uncompress gz to flash (expected to be a valid Arduino compiled binary sketch) -void gzUpdater( fs::FS &fs, const char* gz_filename ) { +bool gzUpdater( fs::FS &fs, const char* gz_filename ) { + tarGzClearError(); if (!tgzLogger ) { setLoggerCallback( tgzPrintLogger ); } tgzLogger("uzLib SPIFFS Updater start!\n"); fs::File gz = fs.open( gz_filename, FILE_READ ); if( !readGzHeaders( gz ) ) { - log_e("Not a valid gzip file"); + tgzLogger("[ERROR] in gzUpdater: Not a valid gzip file"); gz.close(); - return; + _error = ESP32_TARGZ_UZLIB_INVALID_FILE; + return false; } if( !gzProgressCallback ) { setProgressCallback( defaultProgressCallback ); @@ -349,9 +400,14 @@ void gzUpdater( fs::FS &fs, const char* gz_filename ) { gzWriteCallback = &gzUpdateWriteCallback; // for unzipping direct to flash Update.begin( ( ( tarGzStream.output_size + SPI_FLASH_SEC_SIZE-1 ) & ~( SPI_FLASH_SEC_SIZE-1 ) ) ); int ret = gzUncompress( true ); - if( ret!=0 ) tgzLogger("gzUncompress returned error code %d\n", ret); gz.close(); + if( ret!=0 ) { + tgzLogger("gzUncompress returned error code %d\n", ret); + _error = (tarGzErrorCode)ret; + return false; + } + if ( Update.end() ) { tgzLogger( "OTA done!\n" ); if ( Update.isFinished() ) { @@ -360,11 +416,17 @@ void gzUpdater( fs::FS &fs, const char* gz_filename ) { ESP.restart(); } else { tgzLogger( "Update not finished? Something went wrong!\n" ); + _error = ESP32_TARGZ_UPDATE_INCOMPLETE; + return false; } } else { tgzLogger( "Update Error Occurred. Error #: %u\n", Update.getError() ); + _error = (tarGzErrorCode)(Update.getError()-20); // "-20" offset is Update error id to esp32-targz error id + return false; } tgzLogger("uzLib filesystem Updater finished!\n"); + _error = (tarGzErrorCode)ret; + return true; } @@ -409,36 +471,37 @@ int unTarHeaderCallBack(header_translated_t *proper, CC_UNUSED int entry_index, if( strlen( file_path ) > 32 ) { // WARNING: SPIFFS LIMIT tgzLogger("WARNING: file path is longer than 32 chars (SPIFFS limit) and may fail: %s\n", file_path); + _error = ESP32_TARGZ_TAR_ERR_FILENAME_TOOLONG; // don't break untar for that } else { tgzLogger("Creating %s\n", file_path); } untarredFile = tarFS->open(file_path, FILE_WRITE); if(!untarredFile) { - log_e("Could not open [%s] for write.\n", file_path); + tgzLogger("[ERROR] in unTarHeaderCallBack: Could not open [%s] for write.\n", file_path); delete file_path; - return -1; + return ESP32_TARGZ_FS_ERROR; } delete file_path; tarGzStream.output = &untarredFile; } else { switch( proper->type ) { - case T_HARDLINK: log_e("Ignoring hard link to %s.\n\n", proper->filename); break; - case T_SYMBOLIC: log_e("Ignoring sym link to %s.\n\n", proper->filename); break; - case T_CHARSPECIAL: log_e("Ignoring special char.\n\n"); break; - case T_BLOCKSPECIAL: log_e("Ignoring special block.\n\n"); break; - case T_DIRECTORY: log_e("Entering %s directory.\n\n", proper->filename); break; - case T_FIFO: log_e("Ignoring FIFO request.\n\n"); break; - case T_CONTIGUOUS: log_e("Ignoring contiguous data to %s.\n\n", proper->filename); break; - case T_GLOBALEXTENDED: log_e("Ignoring global extended data.\n\n"); break; - case T_EXTENDED: log_e("Ignoring extended data.\n\n"); break; - case T_OTHER: default: log_e("Ignoring unrelevant data.\n\n"); break; + case T_HARDLINK: tgzLogger("Ignoring hard link to %s.\n\n", proper->filename); break; + case T_SYMBOLIC: tgzLogger("Ignoring sym link to %s.\n\n", proper->filename); break; + case T_CHARSPECIAL: tgzLogger("Ignoring special char.\n\n"); break; + case T_BLOCKSPECIAL: tgzLogger("Ignoring special block.\n\n"); break; + case T_DIRECTORY: tgzLogger("Entering %s directory.\n\n", proper->filename); break; + case T_FIFO: tgzLogger("Ignoring FIFO request.\n\n"); break; + case T_CONTIGUOUS: tgzLogger("Ignoring contiguous data to %s.\n\n", proper->filename); break; + case T_GLOBALEXTENDED: tgzLogger("Ignoring global extended data.\n\n"); break; + case T_EXTENDED: tgzLogger("Ignoring extended data.\n\n"); break; + case T_OTHER: default: tgzLogger("Ignoring unrelevant data.\n\n"); break; } } - return 0; + return ESP32_TARGZ_OK; } @@ -460,22 +523,34 @@ int unTarStreamWriteCallback(CC_UNUSED header_translated_t *proper, CC_UNUSED in } } } - return 0; + return ESP32_TARGZ_OK; } int unTarEndCallBack( CC_UNUSED header_translated_t *proper, CC_UNUSED int entry_index, CC_UNUSED void *context_data) { + int ret = ESP32_TARGZ_OK; if(untarredFile) { tgzLogger("\n"); //log_d("Final size: %d", untarredFile.size() ); + const char* fname = untarredFile.name(); untarredFile.close(); + + untarredFile = tarFS->open(fname, FILE_READ); + + if( proper->filesize != untarredFile.size() ) { + log_e("Written file size (%d) differs from tar headers file size (%d) !!", proper->filesize, untarredFile.size() ); + ret = ESP32_TARGZ_FS_ERROR; + } + untarredFile.close(); + } - return 0; + return ret; } // unpack sourceFS://fileName.tar contents to destFS::/destFolder/ -int tarExpander( fs::FS &sourceFS, const char* fileName, fs::FS &destFS, const char* destFolder ) { +bool tarExpander( fs::FS &sourceFS, const char* fileName, fs::FS &destFS, const char* destFolder ) { + tarGzClearError(); tarFS = &destFS; tarDestFolder = destFolder; if( gzProgressCallback ) { @@ -486,7 +561,8 @@ int tarExpander( fs::FS &sourceFS, const char* fileName, fs::FS &destFS, const c } if( !sourceFS.exists( fileName ) ) { tgzLogger("Error: file %s does not exist or is not reachable\n", fileName); - return 1; + _error = ESP32_TARGZ_FS_ERROR; + return false; } if( !destFS.exists( tarDestFolder ) ) { destFS.mkdir( tarDestFolder ); @@ -500,11 +576,18 @@ int tarExpander( fs::FS &sourceFS, const char* fileName, fs::FS &destFS, const c fs::File tarFile = sourceFS.open( fileName, FILE_READ ); tarGzStream.tar = &tarFile; tinyUntarReadCallback = &unTarStreamReadCallback; - if(read_tar( &tarCallbacks, NULL ) != 0) { - printf("Read failed.\n\n"); - return -2; + + tar_error_logger = tgzLogger; + tar_debug_logger = tgzLogger; // comment this out if too verbose + + int res = read_tar( &tarCallbacks, NULL ); + if( res != TAR_OK ) { + tgzLogger("Error: tar file %s could not be read (return code #%d\n", fileName, res-30); + // res + _error = (tarGzErrorCode)(res-30); + return false; } - return 0; + return true; } @@ -533,6 +616,7 @@ int tarGzExpanderSetup() { uzlib_init(); uzLibDecompressor.source = NULL; uzLibDecompressor.source_limit = NULL; + // TODO: malloc() uzlib_read_cb_buff uzLibDecompressor.source_read_cb = gzStreamReadCallback; uzlib_uncompress_init(&uzLibDecompressor, uzlib_gzip_dict, GZIP_DICT_SIZE); tgzLogger("setup end\n"); @@ -541,13 +625,20 @@ int tarGzExpanderSetup() { // unzip sourceFS://sourceFile.tar.gz contents into destFS://destFolder -int tarGzExpander( fs::FS sourceFS, const char* sourceFile, fs::FS destFS, const char* destFolder ) { - +bool tarGzExpander( fs::FS sourceFS, const char* sourceFile, fs::FS destFS, const char* destFolder ) { + tarGzClearError(); + const char* tempFile = "/tmp/data/tar"; // tarGzStream is broken so use an intermediate file until this is fixed - gzExpander(sourceFS, sourceFile, destFS, "/tmp/data.tar"); - tarExpander(destFS, "/tmp/data.tar", destFS, destFolder); - destFS.remove( "/tmp/data.tar" ); - return 0; + if( gzExpander(sourceFS, sourceFile, destFS, tempFile) ) { + + if( tarExpander(destFS, tempFile, destFS, destFolder) ) { + // yay + } + } + delay(100); + if( destFS.exists( tempFile ) ) destFS.remove( tempFile ); + + return !tarGzHasError(); /* tgzLogger("targz expander start!\n"); @@ -555,11 +646,11 @@ int tarGzExpander( fs::FS sourceFS, const char* sourceFile, fs::FS destFS, const tarGzStream.gz = &gz; tarDestFolder = destFolder; if( !tarGzStream.gz->available() ) { - log_e("gz resource doesn't exist!"); + tgzLogger("gz resource doesn't exist!"); return 1; } if( !readGzHeaders( gz ) ) { - log_e("Not a valid gzip file"); + tgzLogger("Not a valid gzip file"); gz.close(); return 2; } @@ -570,7 +661,7 @@ int tarGzExpander( fs::FS sourceFS, const char* sourceFile, fs::FS destFS, const } int res = tarGzExpanderSetup(); if (res != TINF_OK) { - log_e("uzlib_gzip_parse_header failed!"); + tgzLogger("uzlib_gzip_parse_header failed!"); tarGzExpanderCleanup(); return 5; // Error uncompress header read } @@ -638,11 +729,11 @@ void hexDumpFile( fs::FS &fs, const char* filename ) { void tarGzListDir( fs::FS &fs, const char * dirName, uint8_t levels, bool hexDump ) { File root = fs.open( dirName, FILE_READ ); if( !root ){ - log_e( "Can't open %s dir", dirName ); + tgzLogger("[ERROR] in tarGzListDir: Can't open %s dir", dirName ); return; } if( !root.isDirectory() ){ - log_e( "%s is not a directory", dirName ); + tgzLogger("[ERROR] in tarGzListDir: %s is not a directory", dirName ); return; } File file = root.openNextFile(); @@ -670,7 +761,7 @@ void hexDumpFile( fs::FS &fs, const char* filename ) { Dir root = fs.openDir(dirname); /* if( !root.isDirectory() ){ - log_e( "%s is not a directory", dirname ); + tgzLogger( "%s is not a directory", dirname ); return; }*/ while (root.next()) { diff --git a/src/ESP32-targz.h b/src/ESP32-targz.h index 70cb5f4..1bc8175 100644 --- a/src/ESP32-targz.h +++ b/src/ESP32-targz.h @@ -57,28 +57,75 @@ // unzip sourceFS://sourceFile.tar.gz contents into destFS://destFolder -int tarGzExpander( fs::FS sourceFS, const char* sourceFile, fs::FS destFS, const char* destFolder="/tmp" ); +bool tarGzExpander( fs::FS sourceFS, const char* sourceFile, fs::FS destFS, const char* destFolder="/tmp" ); // unpack sourceFS://fileName.tar contents to destFS::/destFolder/ -int tarExpander( fs::FS &sourceFS, const char* fileName, fs::FS &destFS, const char* destFolder ); -// checks if gzFile is a valid gzip file -bool readGzHeaders(fs::File &gzFile); -// extract 4K of data from gzip -int gzProcessBlock( bool isupdate = false ); +bool tarExpander( fs::FS &sourceFS, const char* fileName, fs::FS &destFS, const char* destFolder ); // uncompresses *gzipped* sourceFile to destFile, filesystems may differ -void gzExpander( fs::FS sourceFS, const char* sourceFile, fs::FS destFS, const char* destFile ); +bool gzExpander( fs::FS sourceFS, const char* sourceFile, fs::FS destFS, const char* destFile ); // flashes the ESP with the content of a *gzipped* file -void gzUpdater( fs::FS &fs, const char* gz_filename ); +bool gzUpdater( fs::FS &fs, const char* gz_filename ); // naive ls -void tarGzListDir( fs::FS &fs, const char * dirName, uint8_t levels=1, bool hexDump = false ); +void tarGzListDir( fs::FS &fs, const char * dirName, uint8_t levels=1, bool hexDump = false ); // fs helper -char *dirname(char *path); +char *dirname(char *path); // useful to share the buffer so it's not totally wasted memory outside targz scope uint8_t *getGzBufferUint8(); -void hexDumpFile( fs::FS &fs, const char* filename); +void hexDumpFile( fs::FS &fs, const char* filename); + // callbacks for progress and misc output messages typedef void (*genericProgressCallback)( uint8_t progress ); typedef void (*genericLoggerCallback)( const char* format, ... ); -void setProgressCallback( genericProgressCallback cb ); -void setLoggerCallback( genericLoggerCallback cb ); +void setProgressCallback( genericProgressCallback cb ); +void setLoggerCallback( genericLoggerCallback cb ); + +// error handling +int8_t tarGzGetError(); +void tarGzClearError(); +bool tarGzHasError(); + +// this is only to centralize error codes and spare the +// hassle of looking up in three different library folders + +typedef enum tarGzErrorCode { + ESP32_TARGZ_OK = 0, // yay + ESP32_TARGZ_FS_ERROR = -1, // Filesystem error + // keeping error values from uzlib.h + ESP32_TARGZ_UZLIB_INVALID_FILE = -2, // Not a valid gzip file + ESP32_TARGZ_UZLIB_DATA_ERROR = -3, // TINF_DATA_ERROR + ESP32_TARGZ_UZLIB_CHKSUM_ERROR = -4, // TINF_CHKSUM_ERROR + ESP32_TARGZ_UZLIB_DICT_ERROR = -5, // TINF_DICT_ERROR + + ESP32_TARGZ_STREAM_ERROR = -6, // same a Filesystem error + + ESP32_TARGZ_UPDATE_INCOMPLETE = -7, // Update not finished? Something went wrong + // adding -20 offset to actual error values from Update.h + ESP32_TARGZ_UPDATE_ERROR_ABORT = -8, // UPDATE_ERROR_ABORT -20 // (12-20) = -8 + ESP32_TARGZ_UPDATE_ERROR_BAD_ARGUMENT = -9, // UPDATE_ERROR_BAD_ARGUMENT -20 // (11-20) = -9 + ESP32_TARGZ_UPDATE_ERROR_NO_PARTITION = -10, // UPDATE_ERROR_NO_PARTITION -20 // (10-20) = -10 + ESP32_TARGZ_UPDATE_ERROR_ACTIVATE = -11, // UPDATE_ERROR_ACTIVATE -20 // (9-20) = -11 + ESP32_TARGZ_UPDATE_ERROR_MAGIC_BYTE = -12, // UPDATE_ERROR_MAGIC_BYTE -20 // (8-20) = -12 + ESP32_TARGZ_UPDATE_ERROR_MD5 = -13, // UPDATE_ERROR_MD5 -20 // (7-20) = -13 + ESP32_TARGZ_UPDATE_ERROR_STREAM = -14, // UPDATE_ERROR_STREAM -20 // (6-20) = -14 + ESP32_TARGZ_UPDATE_ERROR_SIZE = -15, // UPDATE_ERROR_SIZE -20 // (5-20) = -15 + ESP32_TARGZ_UPDATE_ERROR_SPACE = -16, // UPDATE_ERROR_SPACE -20 // (4-20) = -16 + ESP32_TARGZ_UPDATE_ERROR_READ = -17, // UPDATE_ERROR_READ -20 // (3-20) = -17 + ESP32_TARGZ_UPDATE_ERROR_ERASE = -18, // UPDATE_ERROR_ERASE -20 // (2-20) = -18 + ESP32_TARGZ_UPDATE_ERROR_WRITE = -19, // UPDATE_ERROR_WRITE -20 // (1-20) = -19 + + ESP32_TARGZ_TAR_ERR_DATACB_FAIL = -32, // TAR_ERR_DATACB_FAIL -30 // (-2-30) = -32 + ESP32_TARGZ_TAR_ERR_HEADERCB_FAIL = -33, // TAR_ERR_HEADERCB_FAIL -30 // (-3-30) = -33 + ESP32_TARGZ_TAR_ERR_FOOTERCB_FAIL = -34, // TAR_ERR_FOOTERCB_FAIL -30 // (-4-30) = -34 + ESP32_TARGZ_TAR_ERR_READBLOCK_FAIL = -35, // TAR_ERR_READBLOCK_FAIL -30 // (-5-30) = -35 + ESP32_TARGZ_TAR_ERR_HEADERTRANS_FAIL = -36, // TAR_ERR_HEADERTRANS_FAIL -30 // (-6-30) = -36 + ESP32_TARGZ_TAR_ERR_HEADERPARSE_FAIL = -37, // TAR_ERR_HEADERPARSE_FAIL -30 // (-7-30) = -37 + + ESP32_TARGZ_TAR_ERR_GZDEFL_FAIL = -38, + ESP32_TARGZ_TAR_ERR_GZREAD_FAIL = -39, + ESP32_TARGZ_TAR_ERR_FILENAME_TOOLONG = -40, + + +} ErrorCodes ; + + #endif // #ifdef _ESP_TGZ_H diff --git a/src/TinyUntar/untar.c b/src/TinyUntar/untar.c index 3c5d04c..84b6484 100644 --- a/src/TinyUntar/untar.c +++ b/src/TinyUntar/untar.c @@ -13,6 +13,7 @@ int entry_index; int empty_count; int received_bytes; int indatablock; +int tar_error = TAR_OK; void (*tar_error_logger)(const char* subject, ...); void (*tar_debug_logger)(const char* subject, ...); @@ -28,11 +29,11 @@ static void log_debug(const char *message) { int parse_header(const unsigned char buffer[TAR_BLOCK_SIZE], header_t *header) { log_debug("Copying tar header"); memcpy(header, buffer, sizeof(header_t)); - return 0; + return TAR_OK; } unsigned long long decode_base256( __attribute__((unused)) const unsigned char *buffer) { - return 0; + return TAR_OK; } __attribute__((unused)) static void dump_hex(const char *ptr, int length) { @@ -188,7 +189,7 @@ int translate_header(header_t *raw_header, header_translated_t *parsed) { parsed->device_major = 0; parsed->device_minor = 0; } - return 0; + return TAR_OK; } static int read_block(unsigned char *buffer) { @@ -204,10 +205,11 @@ static int read_block(unsigned char *buffer) { "rather than (%d). Quitting under error.", num_read, TAR_BLOCK_SIZE ); + tar_error = TAR_ERR_READBLOCK_FAIL; log_error(message); - return -1; + return TAR_ERROR; } - return 0; + return TAR_OK; } @@ -222,12 +224,12 @@ int expand_tar_data_block() { if(read_tar_callbacks->data_cb(&header_translated, entry_index, read_context_data, read_buffer, current_data_size) != 0) { //log_error("Data callback failed."); - return -7; + return TAR_ERR_DATACB_FAIL; } num_blocks_iterator++; received_bytes += current_data_size; - return 0; + return TAR_OK; } @@ -249,6 +251,7 @@ void tar_abort( const char* msgstr, int iserror ) { void tar_setup( entry_callbacks_t *callbacks, void *context_data ) { //log_debug("entering tar setup"); + tar_error = TAR_OK; read_tar_callbacks = callbacks; read_context_data = context_data; read_buffer = (unsigned char*)malloc(TAR_BLOCK_SIZE + 1); @@ -263,59 +266,69 @@ int tar_datablock_step() { if(num_blocks_iterator < num_blocks) { if(read_block( read_buffer ) != 0) { tar_abort("Could not read block. File too short.", 1); - return -6; + tar_error = TAR_ERR_READBLOCK_FAIL; + return tar_error; } int res = expand_tar_data_block(); if( res != 0 ) { tar_abort("Data callback failed", 1); return res; } - return 1; + return TAR_CONTINUE; } else { indatablock = -1; if(read_tar_callbacks->end_cb(&header_translated, entry_index, read_context_data) != 0) { tar_abort("End callback failed.", 1); - return -5; + tar_error = TAR_ERR_FOOTERCB_FAIL; + return tar_error; } - return -1; + return TAR_ERROR; } } int tar_step() { + if( tar_error != TAR_OK ) { + tar_abort("tar expanding interrupted!", 1); + return tar_error; + } + if( indatablock == 0 ) { return tar_datablock_step(); } if(empty_count >= 2) { tar_abort("tar expanding done!", 0); - return -1; + return TAR_ERROR; } if(read_block( read_buffer ) != 0) { tar_abort("tar expanding done!", 0); - return -1; + return TAR_ERROR; } // If we haven't yet determined what format to support, read the // header of the next entry, now. This should be done only at the // top of the archive. if( parse_header(read_buffer, &header) != 0) { tar_abort("Could not understand the header of the first entry in the TAR.", 1); - return -3; + tar_error = TAR_ERR_HEADERPARSE_FAIL; + return tar_error; } else if(strlen(header.filename) == 0) { empty_count++; entry_index++; - return 0; + return TAR_OK; } else { if(translate_header(&header, &header_translated) != 0) { tar_abort("Could not translate header.", 1); - return -4; + tar_error = TAR_ERR_HEADERTRANS_FAIL; + return tar_error; } if(read_tar_callbacks->header_cb(&header_translated, entry_index, read_context_data) != 0) { tar_abort("Header callback failed.", 1); - return -5; + tar_error = TAR_ERR_HEADERCB_FAIL; + return tar_error; } num_blocks_iterator = 0; received_bytes = 0; @@ -329,7 +342,7 @@ int tar_step() { log_error(message); return res; } - return 0; + return TAR_OK; } } @@ -338,22 +351,22 @@ int tar_step() { int read_tar_step() { if( read_tar_callbacks == NULL ) { //tar_abort("No callbacks defined!", 1); - return -1; + return TAR_ERROR; } int res = tar_step(); if( res < 0 ) { char message[200]; - if( res != -1 ) { + if( res != TAR_ERROR ) { snprintf(message, 200, "read_tar return code (%d)", res ); tar_abort(message, 1); return res; } else { //tar_abort("Unpacking success!", 0); - return 0; + return TAR_OK; } } else { - return 0; + return TAR_OK; } } @@ -384,17 +397,20 @@ int read_tar( entry_callbacks_t *callbacks, void *context_data) { if(parse_header(read_buffer, &header) != 0) { tar_abort("Could not understand the header of the first entry in the TAR.", 1); - return -3; + tar_error = TAR_ERR_HEADERPARSE_FAIL; + return tar_error; } else if(strlen(header.filename) == 0) { empty_count++; } else { if(translate_header(&header, &header_translated) != 0) { tar_abort("Could not translate header.", 1); - return -4; + tar_error = TAR_ERR_HEADERTRANS_FAIL; + return tar_error; } if(callbacks->header_cb(&header_translated, entry_index, context_data) != 0) { tar_abort("Header callback failed.", 1); - return -5; + tar_error = TAR_ERR_HEADERCB_FAIL; + return tar_error; } int i = 0; int received_bytes = 0; @@ -402,7 +418,8 @@ int read_tar( entry_callbacks_t *callbacks, void *context_data) { while(i < num_blocks) { if(read_block( read_buffer ) != 0) { tar_abort("Could not read block. File too short.", 1); - return -6; + tar_error = TAR_ERR_READBLOCK_FAIL; + return tar_error; } if(i >= num_blocks - 1) @@ -414,21 +431,23 @@ int read_tar( entry_callbacks_t *callbacks, void *context_data) { if(callbacks->data_cb(&header_translated, entry_index, context_data, read_buffer, current_data_size) != 0) { tar_abort("Data callback failed.", 1); - return -7; + tar_error = TAR_ERR_DATACB_FAIL; + return tar_error; } i++; received_bytes += current_data_size; } if(callbacks->end_cb(&header_translated, entry_index, context_data) != 0) { tar_abort("End callback failed.", 1); - return -5; + tar_error = TAR_ERR_FOOTERCB_FAIL; + return tar_error; } } entry_index++; } tar_abort("tar expanding done!", 0); - return 0; + return TAR_OK; } diff --git a/src/TinyUntar/untar.h b/src/TinyUntar/untar.h index 9c21389..bd56a78 100644 --- a/src/TinyUntar/untar.h +++ b/src/TinyUntar/untar.h @@ -35,6 +35,17 @@ inline int get_last_block_portion_size(int filesize); #define TAR_T_GLOBALEXTENDED 'g' #define TAR_T_EXTENDED 'x' +#define TAR_CONTINUE 1 +#define TAR_OK 0 +#define TAR_ERROR -1 + +#define TAR_ERR_DATACB_FAIL -2 +#define TAR_ERR_HEADERCB_FAIL -3 +#define TAR_ERR_FOOTERCB_FAIL -4 +#define TAR_ERR_READBLOCK_FAIL -5 +#define TAR_ERR_HEADERTRANS_FAIL -6 +#define TAR_ERR_HEADERPARSE_FAIL -7 + #define TAR_BLOCK_SIZE 512 #define TAR_HT_PRE11988 1