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.krut...@embedded-brains.de> wrote: > From: Sebastian Huber <sebastian.hu...@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@rtems.org > http://lists.rtems.org/mailman/listinfo/devel _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel