diff options
author | Alexander Krutwig <alexander.krutwig@embedded-brains.de> | 2016-07-13 09:22:35 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-07-26 10:00:04 +0200 |
commit | 1a8fe67acf5903caacc6da2854a074ed0c4b2743 (patch) | |
tree | f7f781ee2f2e847f7f5ea12e386ef27d3be09aef /cpukit/libmisc/untar/untar.c | |
parent | sptests/spextensions01: Avoid NULL pointer access (diff) | |
download | rtems-1a8fe67acf5903caacc6da2854a074ed0c4b2743.tar.bz2 |
Add Untar_FromChunk_Print() + Test
Diffstat (limited to '')
-rw-r--r-- | cpukit/libmisc/untar/untar.c | 105 |
1 files changed, 104 insertions, 1 deletions
diff --git a/cpukit/libmisc/untar/untar.c b/cpukit/libmisc/untar/untar.c index f6f4f0c837..9a14f67e4e 100644 --- a/cpukit/libmisc/untar/untar.c +++ b/cpukit/libmisc/untar/untar.c @@ -37,7 +37,6 @@ #include <rtems/untar.h> #include <rtems/bspIo.h> - /* * TAR file format: @@ -541,6 +540,110 @@ Untar_FromFile_Print( return retval; } + +void Untar_ChunkContext_Init(Untar_ChunkContext *context) +{ + context->state = UNTAR_CHUNK_HEADER; + context->done_bytes = 0; + context->out_fd = -1; +} + +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; + context->done_bytes = 0; + } else { + context->state = UNTAR_CHUNK_SKIP; + context->todo_bytes = 512 * context->todo_blocks; + context->done_bytes = 0; + } + } 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; + context->done_bytes = 0; + } + + break; + default: + return UNTAR_FAIL; + } + + done += consume; + todo -= consume; + } + + return UNTAR_SUCCESSFUL; +} + /* * Function: Untar_FromFile * |