diff options
author | Chris Johns <chrisj@rtems.org> | 2016-10-12 09:15:23 +1100 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2016-10-13 13:11:40 +1100 |
commit | 826f3afaf3e4682c3ab7110648327217b0cd9e44 (patch) | |
tree | b378ea695ba466a14220a6274ec5570a66e9457d /cpukit/libmisc/untar | |
parent | score: More robust linker sets (diff) | |
download | rtems-826f3afaf3e4682c3ab7110648327217b0cd9e44.tar.bz2 |
libmisc/xz: Add xz decompression.
Add support to untar XZ compressed files.
Diffstat (limited to '')
-rw-r--r-- | cpukit/libmisc/untar/untar.h | 63 | ||||
-rw-r--r-- | cpukit/libmisc/untar/untar_txz.c | 109 |
2 files changed, 172 insertions, 0 deletions
diff --git a/cpukit/libmisc/untar/untar.h b/cpukit/libmisc/untar/untar.h index 3c8bb74130..b97d1d5154 100644 --- a/cpukit/libmisc/untar/untar.h +++ b/cpukit/libmisc/untar/untar.h @@ -21,6 +21,7 @@ #include <stddef.h> #include <tar.h> #include <zlib.h> +#include <xz.h> #include <rtems/print.h> @@ -117,6 +118,34 @@ typedef struct { } Untar_GzChunkContext; +typedef struct { + /** + * @brief Instance of Chunk Context needed for tar decompression. + */ + Untar_ChunkContext base; + + /** + * @brief Xz context. + */ + struct xz_dec* strm; + + /** + * @brief Xz buffer. + */ + struct xz_buf buf; + + /** + * @brief Buffer that contains the inflated data. + */ + void *inflateBuffer; + + /** + * @brief Size of buffer that contains the inflated data. + */ + size_t inflateBufferSize; + +} Untar_XzChunkContext; + /** * @brief Initializes the Untar_ChunkContext files out of a part of a block of * memory. @@ -175,6 +204,40 @@ int Untar_FromGzChunk_Print( const rtems_printer* printer ); +/** + * @brief Initializes the Untar_ChunkXzContext. + * + * @param Untar_ChunkXzContext *context [in] Pointer to a context structure. + * @param enum xz_mode mode [in] Dictionary mode. + * @param uint32_t dict_max [in] Maximum size of dictionary. + * @param void *inflateBuffer [in] Pointer to a context structure. + * @param size_t inflateBufferSize [in] Size of inflateBuffer. + */ +int Untar_XzChunkContext_Init( + Untar_XzChunkContext *ctx, + enum xz_mode mode, + uint32_t dict_max, + void *inflateBuffer, + size_t inflateBufferSize +); + +/* + * @brief Untars a XZ compressed POSIX TAR file. + * + * This is a subroutine used to rip links, directories, and + * files out of a tar.gz/tgz file. + * + * @param Untar_ChunkContext *context [in] Pointer to a context structure. + * @param ssize buflen [in] Size of valid bytes in input buffer. + * @param z_stream *strm [in] Pointer to the current zlib context. + */ +int Untar_FromXzChunk_Print( + Untar_XzChunkContext *ctx, + void *chunk, + size_t chunk_size, + const rtems_printer* printer +); + /************************************************************************** * This converts octal ASCII number representations into an * unsigned long. Only support 32-bit numbers for now. diff --git a/cpukit/libmisc/untar/untar_txz.c b/cpukit/libmisc/untar/untar_txz.c new file mode 100644 index 0000000000..89c7a06e85 --- /dev/null +++ b/cpukit/libmisc/untar/untar_txz.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2016 Chris Johns <chrisj.rtems.org>. All rights reserved. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/untar.h> + +int Untar_XzChunkContext_Init( + Untar_XzChunkContext *ctx, + enum xz_mode mode, + uint32_t dict_max, + void *inflateBuffer, + size_t inflateBufferSize +) +{ + int status = UNTAR_SUCCESSFUL; + + xz_crc32_init(); + + Untar_ChunkContext_Init(&ctx->base); + ctx->inflateBuffer = inflateBuffer; + ctx->inflateBufferSize = inflateBufferSize; + ctx->strm = xz_dec_init(mode, dict_max); + if (ctx->strm == NULL) { + status = UNTAR_FAIL; + } + + return status; +} + +int Untar_FromXzChunk_Print( + Untar_XzChunkContext *ctx, + void *chunk, + size_t chunk_size, + const rtems_printer *printer +) +{ + int untar_status = UNTAR_SUCCESSFUL; + enum xz_ret status = XZ_OK; + + if (ctx->strm == NULL) + return UNTAR_FAIL; + + ctx->buf.in = (const uint8_t*) chunk; + ctx->buf.in_pos = 0; + ctx->buf.in_size = chunk_size; + ctx->buf.out = (uint8_t *) ctx->inflateBuffer; + + /* Inflate until output buffer is not full */ + do { + ctx->buf.out_pos = 0; + ctx->buf.out_size = ctx->inflateBufferSize; + status = xz_dec_run(ctx->strm, &ctx->buf); + if (status == XZ_OPTIONS_ERROR) + status = XZ_OK; + if (status == XZ_OK && ctx->buf.out_pos != 0) { + untar_status = Untar_FromChunk_Print(&ctx->base, + ctx->inflateBuffer, + ctx->buf.out_pos, + NULL); + if (untar_status != UNTAR_SUCCESSFUL) { + break; + } + } + } while (ctx->buf.in_pos != ctx->buf.in_size && status == XZ_OK); + + if (status != XZ_OK) { + xz_dec_end(ctx->strm); + ctx->strm = NULL; + if (untar_status == UNTAR_SUCCESSFUL) { + switch (status) { + case XZ_OK: + case XZ_STREAM_END: + break; + case XZ_UNSUPPORTED_CHECK: + rtems_printf(printer, "XZ unsupported check\n"); + break; + case XZ_MEM_ERROR: + rtems_printf(printer, "XZ memory allocation error\n"); + break; + case XZ_MEMLIMIT_ERROR: + rtems_printf(printer, "XZ memory usage limit reached\n"); + break; + case XZ_FORMAT_ERROR: + rtems_printf(printer, "Not a XZ file\n"); + break; + case XZ_OPTIONS_ERROR: + rtems_printf(printer, "Unsupported options in XZ header\n"); + break; + case XZ_DATA_ERROR: + rtems_printf(printer, "XZ file is corrupt (data)\n"); + break; + case XZ_BUF_ERROR: + rtems_printf(printer, "XZ file is corrupt (buffer)\n"); + break; + } + untar_status = UNTAR_FAIL; + } + } + + return untar_status; +} |