[PATCH] Add Untar_FromChunk_Print() + Test
Gedare Bloom
gedare at rtems.org
Wed Jul 13 14:17:34 UTC 2016
It may be worth using a constant expression for the 512byte header
parameter, since this 512 reappears in a couple of math expressions,
if one ever changed it that would be a problem. Unless it is not
changeable / part of the tar "specification"
On Wed, Jul 13, 2016 at 7:59 AM, Alexander Krutwig
<alexander.krutwig at embedded-brains.de> wrote:
> From: Sebastian Huber <sebastian.huber at embedded-brains.de>
>
> ---
> cpukit/libmisc/untar/untar.c | 135 ++++++++++++++++++++++++++++++++++++
> cpukit/libmisc/untar/untar.h | 30 ++++++++
> testsuites/libtests/tar01/init.c | 44 ++++++++++++
> testsuites/libtests/tar01/tar01.doc | 1 +
> testsuites/libtests/tar01/tar01.scn | 11 +++
> 5 files changed, 221 insertions(+)
>
> diff --git a/cpukit/libmisc/untar/untar.c b/cpukit/libmisc/untar/untar.c
> index f6f4f0c..5287d5a 100644
> --- a/cpukit/libmisc/untar/untar.c
> +++ b/cpukit/libmisc/untar/untar.c
> @@ -542,6 +542,141 @@ Untar_FromFile_Print(
> }
>
> /*
> + * Function: Untar_ChunkContext_Init
> + *
> + * Description:
> + *
> + * This is a simple subroutine that initializes the Untar_ChunkContext
> + * files out of a part of a block of memory.
> + *
> + * Inputs:
> + *
> + * Untar_ChunkContext *context - Pointer to a context structure
> + *
> + * Output: None
> + */
> +void Untar_ChunkContext_Init(Untar_ChunkContext *context)
> +{
> + context->state = UNTAR_CHUNK_HEADER;
> + context->done_bytes = 0;
> + context->out_fd = -1;
> +}
> +
> +/*
> + * Function: Untar_FromChunk_Print
> + *
> + * Description:
> + *
> + * This is a simple subroutine used to rip links, directories, and
> + * files out of a part of a block of memory.
> + *
> + * Inputs:
> + *
> + * Untar_ChunkContext *context - Pointer to a context structure
> + * void *chunk - Pointer to a chunk of a TAR buffer
> + * size_t chunk_size - Length of the chunk of a TAR buffer
> + *
> + * Output:
> + *
> + * int - UNTAR_SUCCESSFUL (0) on successful completion.
> + * UNTAR_FAIL for a faulty step within the process
> + * UNTAR_INVALID_CHECKSUM for an invalid header checksum.
> + * UNTAR_INVALID_HEADER for an invalid header.
> + */
> +int Untar_FromChunk_Print(
> + Untar_ChunkContext *context,
> + void *chunk,
> + size_t chunk_size,
> + const rtems_printer* printer
> +)
> +{
> + char *buf;
> + size_t done;
> + size_t todo;
> + size_t remaining;
> + size_t consume;
> + int retval;
> + unsigned char linkflag;
> +
> + buf = chunk;
> + done = 0;
> + todo = chunk_size;
> +
> + while (todo > 0) {
> + switch (context->state) {
> + case UNTAR_CHUNK_HEADER:
> + remaining = 512 - context->done_bytes;
> + consume = MIN(remaining, todo);
> + memcpy(&context->header[context->done_bytes], &buf[done], consume);
> + context->done_bytes += consume;
> +
> + if (context->done_bytes == 512) {
> + retval = Untar_ProcessHeader(
> + &context->header[0],
> + &context->fname[0],
> + &context->todo_bytes,
> + &context->todo_blocks,
> + &linkflag,
> + printer
> + );
> +
> + if (retval != UNTAR_SUCCESSFUL) {
> + context->state = UNTAR_CHUNK_ERROR;
> + return retval;
> + }
> +
> + if (linkflag == REGTYPE) {
> + context->out_fd = creat(&context->fname[0], 0644);
> +
> + if (context->out_fd >= 0) {
> + context->state = UNTAR_CHUNK_WRITE;
> + } else {
> + context->state = UNTAR_CHUNK_SKIP;
> + context->todo_bytes = 512 * context->todo_blocks;
> + }
> + } else {
> + context->done_bytes = 0;
> + }
> + }
> +
> + break;
> + case UNTAR_CHUNK_SKIP:
> + remaining = context->todo_bytes - context->done_bytes;
> + consume = MIN(remaining, todo);
> + context->done_bytes += consume;
> +
> + if (context->done_bytes == context->todo_bytes) {
> + context->state = UNTAR_CHUNK_HEADER;
> + context->done_bytes = 0;
> + }
> +
> + break;
> + case UNTAR_CHUNK_WRITE:
> + remaining = context->todo_bytes - context->done_bytes;
> + consume = MIN(remaining, todo);
> + write(context->out_fd, &buf[done], consume);
> + context->done_bytes += consume;
> +
> + if (context->done_bytes == context->todo_bytes) {
> + close(context->out_fd);
> + context->out_fd = -1;
> + context->state = UNTAR_CHUNK_SKIP;
> + context->todo_bytes = 512 * context->todo_blocks - context->todo_bytes;
> + }
> +
> + break;
> + default:
> + return UNTAR_FAIL;
> + }
> +
> + done += consume;
> + todo -= consume;
> + }
> +
> + return UNTAR_SUCCESSFUL;
> +}
> +
> +/*
> * Function: Untar_FromFile
> *
> * Description:
> diff --git a/cpukit/libmisc/untar/untar.h b/cpukit/libmisc/untar/untar.h
> index d67c29e..5a74918 100644
> --- a/cpukit/libmisc/untar/untar.h
> +++ b/cpukit/libmisc/untar/untar.h
> @@ -44,6 +44,36 @@ int Untar_FromMemory_Print(void *tar_buf, size_t size, const rtems_printer* prin
> int Untar_FromFile(const char *tar_name);
> int Untar_FromFile_Print(const char *tar_name, const rtems_printer* printer);
>
> +typedef struct {
> + enum {
> + UNTAR_CHUNK_HEADER,
> + UNTAR_CHUNK_SKIP,
> + UNTAR_CHUNK_WRITE,
> + UNTAR_CHUNK_ERROR
> + } state;
> +
> + char header[512];
> +
> + char fname[100];
> +
> + size_t done_bytes;
> +
> + long unsigned todo_bytes;
> +
> + unsigned long todo_blocks;
> +
> + int out_fd;
> +} Untar_ChunkContext;
> +
> +void Untar_ChunkContext_Init(Untar_ChunkContext *context);
> +
> +int Untar_FromChunk_Print(
> + Untar_ChunkContext *context,
> + 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/testsuites/libtests/tar01/init.c b/testsuites/libtests/tar01/init.c
> index 54760e9..3977447 100644
> --- a/testsuites/libtests/tar01/init.c
> +++ b/testsuites/libtests/tar01/init.c
> @@ -31,6 +31,7 @@ const char rtems_test_name[] = "TAR 1";
> rtems_task Init(rtems_task_argument argument);
> void test_untar_from_memory(void);
> void test_untar_from_file(void);
> +void test_untar_chunks_from_memory(void);
>
> #define TARFILE_START initial_filesystem_tar
> #define TARFILE_SIZE initial_filesystem_tar_size
> @@ -106,6 +107,47 @@ void test_untar_from_file(void)
> test_cat( "/dest/symlink", 0, 0 );
> }
>
> +void test_untar_chunks_from_memory(void)
> +{
> + rtems_status_code sc;
> + rtems_printer printer;
> + int rv;
> + Untar_ChunkContext ctx;
> + unsigned long counter = 0;
> + char *buffer = (char *)TARFILE_START;
> + size_t buflen = TARFILE_SIZE;
> +
> + rtems_print_printer_printf(&printer);
> +
> + /* make a directory to untar it into */
> + rv = mkdir( "/dest2", 0777 );
> + rtems_test_assert( rv == 0 );
> +
> + rv = chdir( "/dest2" );
> + rtems_test_assert( rv == 0 );
> +
> + printf("Untaring chunks from memory - ");
> + Untar_ChunkContext_Init(&ctx);
> + do {
> + sc = Untar_FromChunk_Print(&ctx, &buffer[counter], (size_t)1 , &printer);
> + if (sc != RTEMS_SUCCESSFUL) {
> + printf ("error: untar failed: %s\n", rtems_status_text (sc));
> + exit(1);
> + }
> + counter ++;
> + } while (counter < buflen);
> + printf ("successful\n");
> +
> + /******************/
> + printf( "========= /home/test_file =========\n" );
> + test_cat( "/home/test_file", 0, 0 );
> +
> + /******************/
> + printf( "========= /symlink =========\n" );
> + test_cat( "/symlink", 0, 0 );
> +
> +}
> +
> rtems_task Init(
> rtems_task_argument ignored
> )
> @@ -115,6 +157,8 @@ rtems_task Init(
> test_untar_from_memory();
> puts( "" );
> test_untar_from_file();
> + puts( "" );
> + test_untar_chunks_from_memory();
>
> TEST_END();
> exit( 0 );
> diff --git a/testsuites/libtests/tar01/tar01.doc b/testsuites/libtests/tar01/tar01.doc
> index 463d6b3..1a8151c 100644
> --- a/testsuites/libtests/tar01/tar01.doc
> +++ b/testsuites/libtests/tar01/tar01.doc
> @@ -14,6 +14,7 @@ directives:
>
> + Untar_FromMemory
> + Untar_FromFile
> + + Untar_ChunksFromMemory
>
> concepts:
>
> diff --git a/testsuites/libtests/tar01/tar01.scn b/testsuites/libtests/tar01/tar01.scn
> index 2c4d6b0..ae20139 100644
> --- a/testsuites/libtests/tar01/tar01.scn
> +++ b/testsuites/libtests/tar01/tar01.scn
> @@ -19,4 +19,15 @@ initial tar image.
> (0)This is a test of loading an RTEMS filesystem from an
> initial tar image.
>
> +Untaring chunks from memory - untar: dir: home
> +untar: file: home/test_file (73)
> +successful
> +========= /home/test_file =========
> +(0)This is a test of loading an RTEMS filesystem from an
> +initial tar image.
> +
> +========= /symlink =========
> +(0)This is a test of loading an RTEMS filesystem from an
> +initial tar image.
> +
> *** END OF TAR01 TEST ***
> --
> 1.8.4.5
>
> _______________________________________________
> devel mailing list
> devel at rtems.org
> http://lists.rtems.org/mailman/listinfo/devel
More information about the devel
mailing list