diff options
Diffstat (limited to 'cpukit/libmisc/untar/untar.c')
-rw-r--r-- | cpukit/libmisc/untar/untar.c | 78 |
1 files changed, 55 insertions, 23 deletions
diff --git a/cpukit/libmisc/untar/untar.c b/cpukit/libmisc/untar/untar.c index 8888ab2c57..fff737db68 100644 --- a/cpukit/libmisc/untar/untar.c +++ b/cpukit/libmisc/untar/untar.c @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + /** * @file * @@ -11,9 +13,26 @@ * * Copyright 2016 Chris Johns <chrisj@rtems.org> * - * 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. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H @@ -65,6 +84,14 @@ #define MAX_NAME_FIELD_SIZE 99 +#define TAR_BLOCK_SIZE 512 +#define TAR_BLOCK_SIZE_MASK (TAR_BLOCK_SIZE - 1) + +/* + * Number of blocks read or written + */ +#define TAR_WORK_BLOCKS 16 + static int _rtems_tar_header_checksum(const char *bufr); /* @@ -221,7 +248,8 @@ Untar_ProcessHeader( } else if (ctx->linkflag == REGTYPE) { rtems_printf(ctx->printer, "untar: file: %s (s:%lu,m:%04lo)\n", ctx->file_path, ctx->file_size, ctx->mode); - ctx->nblocks = (((ctx->file_size) + 511) & ~511) / 512; + ctx->nblocks = + (((ctx->file_size) + TAR_BLOCK_SIZE_MASK) & ~TAR_BLOCK_SIZE_MASK) / TAR_BLOCK_SIZE; } else if (ctx->linkflag == DIRTYPE) { rtems_printf(ctx->printer, "untar: dir: %s\n", ctx->file_path); r = mkdir(ctx->file_path, ctx->mode); @@ -292,14 +320,14 @@ Untar_FromMemory_Print( ptr = 0; while (true) { - if (ptr + 512 > size) { + if (ptr + TAR_BLOCK_SIZE > size) { retval = UNTAR_SUCCESSFUL; break; } /* Read the header */ bufr = &tar_ptr[ptr]; - ptr += 512; + ptr += TAR_BLOCK_SIZE; retval = Untar_ProcessHeader(&ctx, bufr); @@ -310,27 +338,26 @@ Untar_FromMemory_Print( if ((fd = open(ctx.file_path, O_TRUNC | O_CREAT | O_WRONLY, ctx.mode)) == -1) { Print_Error(printer, "open", ctx.file_path); - ptr += 512 * ctx.nblocks; + ptr += TAR_BLOCK_SIZE * ctx.nblocks; } else { - unsigned long sizeToGo = ctx.file_size; - ssize_t len; - ssize_t i; - ssize_t n; - /* * Read out the data. There are nblocks of data where nblocks is the * file_size rounded to the nearest 512-byte boundary. */ - for (i = 0; i < ctx.nblocks; i++) { - len = ((sizeToGo < 512L) ? (sizeToGo) : (512L)); - n = write(fd, &tar_ptr[ptr], len); + ssize_t file_size = ctx.file_size; + size_t blocks = ctx.nblocks; + while (blocks > 0) { + size_t blks = blocks > TAR_WORK_BLOCKS ? TAR_WORK_BLOCKS : blocks; + ssize_t len = MIN(blks * TAR_BLOCK_SIZE, file_size); + ssize_t n = write(fd, &tar_ptr[ptr], len); if (n != len) { Print_Error(printer, "write", ctx.file_path); retval = UNTAR_FAIL; break; } - ptr += 512; - sizeToGo -= n; + ptr += blks * TAR_BLOCK_SIZE; + file_size -= n; + blocks -= blks; } close(fd); } @@ -400,7 +427,6 @@ Untar_FromFile_Print( char *bufr; ssize_t n; int retval; - unsigned long i; char buf[UNTAR_FILE_NAME_SIZE]; Untar_HeaderContext ctx; @@ -410,7 +436,7 @@ Untar_FromFile_Print( return UNTAR_FAIL; } - bufr = (char *)malloc(512); + bufr = (char *)malloc(TAR_WORK_BLOCKS * TAR_BLOCK_SIZE); if (bufr == NULL) { close(fd); return(UNTAR_FAIL); @@ -423,7 +449,7 @@ Untar_FromFile_Print( while (1) { /* Read the header */ /* If the header read fails, we just consider it the end of the tarfile. */ - if ((n = read(fd, bufr, 512)) != 512) { + if ((n = read(fd, bufr, TAR_BLOCK_SIZE)) != TAR_BLOCK_SIZE) { break; } @@ -445,10 +471,16 @@ Untar_FromFile_Print( retval = UNTAR_FAIL; break; } else { - for (i = 0; i < ctx.nblocks; i++) { - n = read(fd, bufr, 512); - n = MIN(n, ctx.file_size - (i * 512UL)); + ssize_t file_size = ctx.file_size; + size_t blocks = ctx.nblocks; + while (blocks > 0) { + size_t blks = blocks > TAR_WORK_BLOCKS ? TAR_WORK_BLOCKS : blocks; + size_t bytes = blks * TAR_BLOCK_SIZE; + n = read(fd, bufr, bytes); + n = MIN(n, file_size); (void) write(out_fd, bufr, n); + file_size -= n; + blocks -= blks; } close(out_fd); } |