diff options
author | Glenn L McGrath <bug1@ihug.co.nz> | 2002-11-03 14:05:15 +0000 |
---|---|---|
committer | Glenn L McGrath <bug1@ihug.co.nz> | 2002-11-03 14:05:15 +0000 |
commit | 237ae42fc96ede945d28d9054f045b73e419d089 (patch) | |
tree | 3fb6a9c10150303aca3c218b47aaf327a186382a /archival | |
parent | 2fc54a9258c3aa5dad2ce9807ba85cf29af2668e (diff) | |
download | busybox-237ae42fc96ede945d28d9054f045b73e419d089.tar.gz |
Abstract read and seek in unarchiving code, convert bunzip to file descriptors, support tar -j
Diffstat (limited to 'archival')
25 files changed, 442 insertions, 306 deletions
diff --git a/archival/ar.c b/archival/ar.c index 997927346..71cde4ebe 100644 --- a/archival/ar.c +++ b/archival/ar.c @@ -50,7 +50,7 @@ static void header_verbose_list_ar(const file_header_t *file_header) printf("%s %d/%d%7d %s %s\n", &mode[1], file_header->uid, file_header->gid, (int) file_header->size, &mtime[4], file_header->name); } -#if defined CONFIG_TAR | defined CONFIG_DPKG_DEB | defined CONFIG_CPIO +#if !defined CONFIG_TAR && !defined CONFIG_DPKG_DEB && !defined CONFIG_CPIO /* This is simpler than data_extract_all */ static void data_extract_regular_file(archive_handle_t *archive_handle) { @@ -59,7 +59,7 @@ static void data_extract_regular_file(archive_handle_t *archive_handle) file_header = archive_handle->file_header; dst_fd = xopen(file_header->name, O_WRONLY | O_CREAT); - copy_file_chunk_fd(archive_handle->src_fd, dst_fd, file_header->size); + archive_copy_file(archive_handle, dst_fd); close(dst_fd); chmod(file_header->name, file_header->mode); @@ -80,18 +80,10 @@ extern int ar_main(int argc, char **argv) archive_handle_t *archive_handle; int opt; -#ifndef CONFIG_DPKG_DEB +#if !defined CONFIG_DPKG_DEB && !defined CONFIG_DPKG char magic[8]; #endif -#if defined CONFIG_TAR | defined CONFIG_DPKG_DEB | defined CONFIG_CPIO archive_handle = init_handle(); -#else - archive_handle = xcalloc(1, sizeof(archive_handle_t)); - archive_handle->filter = filter_accept_all; - archive_handle->action_data = data_skip; - archive_handle->action_header = header_skip; - archive_handle->file_header =xmalloc(sizeof(file_header_t)); -#endif while ((opt = getopt(argc, argv, "covtpxX")) != -1) { switch (opt) { @@ -104,7 +96,7 @@ extern int ar_main(int argc, char **argv) case 'X': archive_handle->action_header = header_verbose_list_ar; case 'x': /* extract */ -#if defined CONFIG_TAR | defined CONFIG_DPKG_DEB | defined CONFIG_CPIO +#if defined CONFIG_TAR || defined CONFIG_DPKG_DEB || defined CONFIG_CPIO archive_handle->action_data = data_extract_all; #else archive_handle->action_data = data_extract_regular_file; @@ -136,10 +128,10 @@ extern int ar_main(int argc, char **argv) optind++; } -#if defined CONFIG_DPKG_DEB +#if defined CONFIG_DPKG_DEB || defined CONFIG_DPKG unpack_ar_archive(archive_handle); #else - xread_all(archive_handle->src_fd, magic, 7); + archive_xread_all(archive_handle, magic, 7); if (strncmp(magic, "!<arch>", 7) != 0) { error_msg_and_die("Invalid ar magic"); } diff --git a/archival/bunzip2.c b/archival/bunzip2.c index 9f346f266..d5c06f4fd 100644 --- a/archival/bunzip2.c +++ b/archival/bunzip2.c @@ -17,9 +17,11 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include <fcntl.h> #include <getopt.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <unistd.h> #include "busybox.h" @@ -33,8 +35,8 @@ int bunzip2_main(int argc, char **argv) int opt = 0; int status; - FILE *src_stream; - FILE *dst_stream; + int src_fd; + int dst_fd; char *save_name = NULL; char *delete_name = NULL; @@ -59,10 +61,10 @@ int bunzip2_main(int argc, char **argv) /* Set input filename and number */ if (argv[optind] == NULL || strcmp(argv[optind], "-") == 0) { flags |= bunzip_to_stdout; - src_stream = stdin; + src_fd = fileno(stdin); } else { /* Open input file */ - src_stream = xfopen(argv[optind], "r"); + src_fd = xopen(argv[optind], O_RDONLY); save_name = xstrdup(argv[optind]); if (strcmp(save_name + strlen(save_name) - 4, ".bz2") != 0) @@ -71,29 +73,30 @@ int bunzip2_main(int argc, char **argv) } /* Check that the input is sane. */ - if (isatty(fileno(src_stream)) && (flags & bunzip_force) == 0) + if (isatty(src_fd) && (flags & bunzip_force) == 0) { error_msg_and_die("compressed data not read from terminal. Use -f to force it."); + } if (flags & bunzip_to_stdout) { - dst_stream = stdout; + dst_fd = fileno(stdout); } else { - dst_stream = xfopen(save_name, "w"); + dst_fd = xopen(save_name, O_WRONLY | O_CREAT); } - if (uncompressStream(src_stream, dst_stream)) { - if (!(flags & bunzip_to_stdout)) + if (uncompressStream(src_fd, dst_fd)) { + if (!(flags & bunzip_to_stdout)) { delete_name = argv[optind]; + } status = EXIT_SUCCESS; } else { - if (!(flags & bunzip_to_stdout)) + if (!(flags & bunzip_to_stdout)) { delete_name = save_name; + } status = EXIT_FAILURE; } - if (delete_name) { - if (unlink(delete_name) < 0) { - error_msg_and_die("Couldn't remove %s", delete_name); - } + if ((delete_name) && (unlink(delete_name) < 0)) { + error_msg_and_die("Couldn't remove %s", delete_name); } return status; diff --git a/archival/config.in b/archival/config.in index 689561b8e..3ec03fd8c 100644 --- a/archival/config.in +++ b/archival/config.in @@ -26,6 +26,7 @@ bool 'rpm2cpio' CONFIG_RPM2CPIO bool 'tar' CONFIG_TAR if [ "$CONFIG_TAR" = "y" ] ; then bool ' Enable archive creation' CONFIG_FEATURE_TAR_CREATE + bool ' Enable -j option to handle .tar.bz2 files' CONFIG_FEATURE_TAR_BZIP2 bool ' Enable -X and --exclude options (exclude files)' CONFIG_FEATURE_TAR_EXCLUDE bool ' Enable -z option' CONFIG_FEATURE_TAR_GZIP bool ' Enable support for old tar header format' CONFIG_FEATURE_TAR_OLD_FORMAT diff --git a/archival/cpio.c b/archival/cpio.c index 761517516..0d0614932 100644 --- a/archival/cpio.c +++ b/archival/cpio.c @@ -45,6 +45,7 @@ extern int cpio_main(int argc, char **argv) /* Initialise */ archive_handle = init_handle(); archive_handle->src_fd = fileno(stdin); + archive_handle->seek = seek_by_char; archive_handle->action_header = header_list; while ((opt = getopt(argc, argv, "idmuvtF:")) != -1) { @@ -69,6 +70,7 @@ extern int cpio_main(int argc, char **argv) break; case 'F': archive_handle->src_fd = xopen(optarg, O_RDONLY); + archive_handle->seek = seek_by_jump; break; default: show_usage(); @@ -117,9 +119,9 @@ extern int cpio_main(int argc, char **argv) } /* There can be padding before archive header */ - archive_handle->offset += data_align(archive_handle->src_fd, archive_handle->offset, 4); + data_align(archive_handle, 4); - if (xread_all_eof(archive_handle->src_fd, cpio_header, 110) == 0) { + if (archive_xread_all_eof(archive_handle, cpio_header, 110) == 0) { return(EXIT_FAILURE); } archive_handle->offset += 110; @@ -145,12 +147,12 @@ extern int cpio_main(int argc, char **argv) dummy, &major, &minor, &namesize, dummy); file_header->name = (char *) xmalloc(namesize + 1); - xread(archive_handle->src_fd, file_header->name, namesize); /* Read in filename */ + archive_xread_all(archive_handle, file_header->name, namesize); /* Read in filename */ file_header->name[namesize] = '\0'; archive_handle->offset += namesize; /* Update offset amount and skip padding before file contents */ - archive_handle->offset += data_align(archive_handle->src_fd, archive_handle->offset, 4); + data_align(archive_handle, 4); if (strcmp(file_header->name, "TRAILER!!!") == 0) { printf("%d blocks\n", (int) (archive_handle->offset % 512 ? (archive_handle->offset / 512) + 1 : archive_handle->offset / 512)); /* Always round up */ @@ -173,7 +175,7 @@ extern int cpio_main(int argc, char **argv) if (S_ISLNK(file_header->mode)) { file_header->link_name = (char *) xmalloc(file_header->size + 1); - xread(archive_handle->src_fd, file_header->link_name, file_header->size); + archive_xread_all(archive_handle, file_header->link_name, file_header->size); file_header->link_name[file_header->size] = '\0'; archive_handle->offset += file_header->size; file_header->size = 0; /* Stop possible seeks in future */ diff --git a/archival/libunarchive/Makefile.in b/archival/libunarchive/Makefile.in index 432077721..e406f750e 100644 --- a/archival/libunarchive/Makefile.in +++ b/archival/libunarchive/Makefile.in @@ -41,15 +41,23 @@ LIBUNARCHIVE-y:= \ header_list.o \ header_verbose_list.o \ \ + archive_xread.o \ + archive_xread_all.o \ + archive_xread_all_eof.o \ + archive_xread_char.o \ +\ + seek_by_char.o \ + seek_by_jump.o \ +\ + archive_copy_file.o \ +\ add_to_list.o \ check_header_gzip.o \ check_trailer_gzip.o \ - copy_file_chunk_fd.o \ data_align.o \ decompress_bunzip2.o \ find_list_entry.o \ init_handle.o \ - seek_sub_file.o \ uncompress.o \ unpack_ar_archive.o \ unzip.o diff --git a/archival/libunarchive/archive_copy_file.c b/archival/libunarchive/archive_copy_file.c new file mode 100644 index 000000000..22355ccd5 --- /dev/null +++ b/archival/libunarchive/archive_copy_file.c @@ -0,0 +1,48 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <unistd.h> + +#include "libbb.h" +#include "unarchive.h" + +/* Copy CHUNKSIZE bytes (or untill EOF if chunksize == -1) + * from SRC_FILE to DST_FILE. */ +extern void archive_copy_file(const archive_handle_t *archive_handle, const int dst_fd) +{ + size_t size; + char buffer[BUFSIZ]; + off_t chunksize = archive_handle->file_header->size; + + while (chunksize != 0) { + if (chunksize > BUFSIZ) { + size = BUFSIZ; + } else { + size = chunksize; + } + archive_xread_all(archive_handle, buffer, size); + + if (write(dst_fd, buffer, size) != size) { + error_msg_and_die ("Short write"); + } + + if (chunksize != -1) { + chunksize -= size; + } + } + + return; +} diff --git a/archival/libunarchive/archive_xread.c b/archival/libunarchive/archive_xread.c new file mode 100644 index 000000000..7fde4c0b1 --- /dev/null +++ b/archival/libunarchive/archive_xread.c @@ -0,0 +1,33 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "unarchive.h" +#include "libbb.h" + +extern ssize_t archive_xread(const archive_handle_t *archive_handle, unsigned char *buf, const size_t count) +{ + ssize_t size; + + size = archive_handle->read(archive_handle->src_fd, buf, count); + if (size == -1) { + perror_msg_and_die("Read error"); + } + + return(size); +} diff --git a/archival/libunarchive/seek_sub_file.c b/archival/libunarchive/archive_xread_all.c index 733bb36a9..ef8cc0141 100644 --- a/archival/libunarchive/seek_sub_file.c +++ b/archival/libunarchive/archive_xread_all.c @@ -14,19 +14,19 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <sys/types.h> -#include <errno.h> -#include <unistd.h> +#include <stdio.h> #include <stdlib.h> +#include <string.h> #include "unarchive.h" #include "libbb.h" -extern void seek_sub_file(const int src_fd, const unsigned int amount) +extern void archive_xread_all(const archive_handle_t *archive_handle, void *buf, const size_t count) { - if ((lseek(src_fd, amount, SEEK_CUR) == -1) && (errno == ESPIPE)) { - unsigned int i; - for (i = 0; i < amount; i++) { - xread_char(src_fd); - } + ssize_t size; + + size = archive_xread(archive_handle, buf, count); + if (size != count) { + error_msg_and_die("Short read"); } + return; } diff --git a/archival/libunarchive/archive_xread_all_eof.c b/archival/libunarchive/archive_xread_all_eof.c new file mode 100644 index 000000000..3cfbbd8d1 --- /dev/null +++ b/archival/libunarchive/archive_xread_all_eof.c @@ -0,0 +1,32 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "unarchive.h" +#include "libbb.h" + +extern ssize_t archive_xread_all_eof(archive_handle_t *archive_handle, unsigned char *buf, size_t count) +{ + ssize_t size; + + size = archive_xread(archive_handle, buf, count); + if ((size != 0) && (size != count)) { + perror_msg_and_die("Short read, read %d of %d", size, count); + } + return(size); +} diff --git a/archival/libunarchive/archive_xread_char.c b/archival/libunarchive/archive_xread_char.c new file mode 100644 index 000000000..4c665e159 --- /dev/null +++ b/archival/libunarchive/archive_xread_char.c @@ -0,0 +1,30 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "unarchive.h" +#include "libbb.h" + +extern unsigned char archive_xread_char(const archive_handle_t *archive_handle) +{ + unsigned char tmp; + + archive_xread(archive_handle, &tmp, 1); + + return(tmp); +} diff --git a/archival/libunarchive/copy_file_chunk_fd.c b/archival/libunarchive/copy_file_chunk_fd.c deleted file mode 100644 index fb513e6d5..000000000 --- a/archival/libunarchive/copy_file_chunk_fd.c +++ /dev/null @@ -1,33 +0,0 @@ -#include <unistd.h> -#include <sys/types.h> -#include "libbb.h" - -/* Copy CHUNKSIZE bytes (or untill EOF if chunksize == -1) - * from SRC_FILE to DST_FILE. */ -extern int copy_file_chunk_fd(int src_fd, int dst_fd, off_t chunksize) -{ - size_t nread, size; - char buffer[BUFSIZ]; - - while (chunksize != 0) { - if (chunksize > BUFSIZ) { - size = BUFSIZ; - } else { - size = chunksize; - } - nread = xread(src_fd, buffer, size); - if (nread == 0) { - return 1; - } - - if (write (dst_fd, buffer, nread) != nread) { - error_msg_and_die ("Short write"); - } - - if (chunksize != -1) { - chunksize -= nread; - } - } - - return 0; -} diff --git a/archival/libunarchive/data_align.c b/archival/libunarchive/data_align.c index d6243bc19..037242f25 100644 --- a/archival/libunarchive/data_align.c +++ b/archival/libunarchive/data_align.c @@ -1,13 +1,34 @@ -#include <errno.h> +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + #include <sys/types.h> + +#include <errno.h> #include <unistd.h> -#include "unarchive.h" + #include "libbb.h" +#include "unarchive.h" -extern const unsigned short data_align(const int src_fd, const unsigned int offset, const unsigned short align_to) +extern void data_align(archive_handle_t *archive_handle, const unsigned short boundary) { - const unsigned short skip_amount = (align_to - (offset % align_to)) % align_to; - seek_sub_file(src_fd, skip_amount); + const unsigned short skip_amount = (boundary - (archive_handle->offset % boundary)) % boundary; + + archive_handle->seek(archive_handle, skip_amount); + + archive_handle->offset += skip_amount; - return(skip_amount); + return; } diff --git a/archival/libunarchive/data_extract_all.c b/archival/libunarchive/data_extract_all.c index f839be35e..dda514771 100644 --- a/archival/libunarchive/data_extract_all.c +++ b/archival/libunarchive/data_extract_all.c @@ -1,4 +1,21 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + #include <sys/types.h> + #include <errno.h> #include <fcntl.h> #include <stdlib.h> @@ -6,6 +23,7 @@ #include <utime.h> #include <unistd.h> #include <stdlib.h> + #include "libbb.h" #include "unarchive.h" @@ -21,7 +39,7 @@ extern void data_extract_all(archive_handle_t *archive_handle) free(name); } - /* Create the file */ + /* Create the filesystem entry */ switch(file_header->mode & S_IFMT) { case S_IFREG: { #ifdef CONFIG_CPIO @@ -36,7 +54,7 @@ extern void data_extract_all(archive_handle_t *archive_handle) { /* Regular file */ dst_fd = xopen(file_header->name, O_WRONLY | O_CREAT); - copy_file_chunk_fd(archive_handle->src_fd, dst_fd, file_header->size); + archive_copy_file(archive_handle, dst_fd); close(dst_fd); } break; diff --git a/archival/libunarchive/data_extract_to_buffer.c b/archival/libunarchive/data_extract_to_buffer.c index 02ee4b362..3fcab6d02 100644 --- a/archival/libunarchive/data_extract_to_buffer.c +++ b/archival/libunarchive/data_extract_to_buffer.c @@ -1,11 +1,26 @@ -#include <stdlib.h> -#include <stdio.h> -#include "unarchive.h" +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + #include "libbb.h" +#include "unarchive.h" extern void data_extract_to_buffer(archive_handle_t *archive_handle) { archive_handle->buffer = xmalloc(archive_handle->file_header->size + 1); - xread_all(archive_handle->src_fd, archive_handle->buffer, archive_handle->file_header->size); + archive_xread_all(archive_handle, archive_handle->buffer, archive_handle->file_header->size); + } diff --git a/archival/libunarchive/data_extract_to_stdout.c b/archival/libunarchive/data_extract_to_stdout.c index 00687b315..8be2fa2e9 100644 --- a/archival/libunarchive/data_extract_to_stdout.c +++ b/archival/libunarchive/data_extract_to_stdout.c @@ -1,8 +1,22 @@ -#include <stdlib.h> -#include <stdio.h> +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + #include "unarchive.h" extern void data_extract_to_stdout(archive_handle_t *archive_handle) { - copy_file_chunk_fd(archive_handle->src_fd, fileno(stdout), archive_handle->file_header->size); + archive_copy_file(archive_handle, fileno(stdout)); } diff --git a/archival/libunarchive/data_skip.c b/archival/libunarchive/data_skip.c index 4e63d4304..b82c9065b 100644 --- a/archival/libunarchive/data_skip.c +++ b/archival/libunarchive/data_skip.c @@ -23,5 +23,5 @@ extern void data_skip(archive_handle_t *archive_handle) { - seek_sub_file(archive_handle->src_fd, archive_handle->file_header->size); + archive_handle->seek(archive_handle, archive_handle->file_header->size); } diff --git a/archival/libunarchive/decompress_bunzip2.c b/archival/libunarchive/decompress_bunzip2.c index dd15b819f..00ae5a494 100644 --- a/archival/libunarchive/decompress_bunzip2.c +++ b/archival/libunarchive/decompress_bunzip2.c @@ -57,10 +57,8 @@ #include <string.h> #include <getopt.h> #include <unistd.h> -#include <busybox.h> -//#define TRUE 1 -//#define FALSE 0 +#include "busybox.h" #define MTFA_SIZE 4096 #define MTFL_SIZE 16 @@ -142,9 +140,10 @@ typedef struct { } bz_stream; +#define BZ_MAX_UNUSED 5000 typedef struct { bz_stream strm; - FILE *handle; + int fd; unsigned char initialisedOk; char buf[BZ_MAX_UNUSED]; int lastErr; @@ -237,18 +236,11 @@ typedef struct { int *save_gPerm; } DState; -int BZ2_rNums[512]; -char inName[FILE_NAME_LEN]; -char outName[FILE_NAME_LEN]; -int srcMode; -int opMode; -unsigned char deleteOutputOnInterrupt; -FILE *outputHandleJustInCase; -int numFileNames; -int numFilesProcessed; -int exitValue; +static int BZ2_rNums[512]; +static bzFile *bzf; +static int bzerr = BZ_OK; -const unsigned int BZ2_crc32Table[256] = { +static const unsigned int BZ2_crc32Table[256] = { /*-- Ugly, innit? --*/ @@ -330,16 +322,6 @@ static void bz_rand_udp_mask(DState *s) s->rNToGo--; } -static unsigned char myfeof(FILE *f) -{ - int c = fgetc(f); - if (c == EOF) { - return(TRUE); - } - ungetc(c, f); - return(FALSE); -} - static void BZ2_hbCreateDecodeTables(int *limit, int *base, int *perm, unsigned char *length, int minLen, int maxLen, int alphaSize ) { int pp, i, j, vec; @@ -1292,43 +1274,8 @@ save_state_and_return: return retVal; } -//int BZ2_bzDecompressInit(bz_stream* strm, int verbosity_level, int small) -static inline int BZ2_bzDecompressInit(bz_stream* strm) -{ - DState* s; - -// if (verbosity_level < 0 || verbosity_level > 4) { -// return BZ_PARAM_ERROR; -// } - s = xmalloc(sizeof(DState)); - s->strm = strm; - strm->state = s; - s->state = BZ_X_MAGIC_1; - s->bsLive = 0; - s->bsBuff = 0; - s->calculatedCombinedCRC = 0; - s->tt = NULL; - s->currBlockNo = 0; - - return BZ_OK; -} - -static void bz_seterr(int eee, int *bzerror, bzFile **bzf) +static void BZ2_bzReadClose(void) { - if (bzerror != NULL) { - *bzerror = eee; - } - if (*bzf != NULL) { - (*bzf)->lastErr = eee; - } -} - -static void BZ2_bzReadClose(int *bzerror, void *b) -{ - bzFile* bzf = (bzFile*)b; - - bz_seterr(BZ_OK, bzerror, &bzf); - if (bzf->initialisedOk) { bz_stream *strm = &(bzf->strm); DState *s; @@ -1588,31 +1535,22 @@ int BZ2_bzDecompress(bz_stream *strm) return(0); /*NOTREACHED*/ } -static inline int BZ2_bzRead(int *bzerror, void *b, void *buf, int len) +extern ssize_t read_bz2(int fd, void *buf, size_t count) { int n, ret; - bzFile *bzf = (bzFile*)b; - - bz_seterr(BZ_OK, bzerror, &bzf); - if (len == 0) { - bz_seterr(BZ_OK, bzerror, &bzf); - return 0; + bzerr = BZ_OK; + if (count == 0) { + return(0); } - - bzf->strm.avail_out = len; + bzf->strm.avail_out = count; bzf->strm.next_out = buf; while (1) { - if (ferror(bzf->handle)) { - bz_seterr(BZ_IO_ERROR, bzerror, &bzf); - return 0; - } - if ((bzf->strm.avail_in == 0) && !myfeof(bzf->handle)) { - n = fread(bzf->buf, sizeof(unsigned char), BZ_MAX_UNUSED, bzf->handle); - if (ferror(bzf->handle)) { - bz_seterr(BZ_IO_ERROR, bzerror, &bzf); - return 0; + if (bzf->strm.avail_in == 0) { + n = xread(bzf->fd, bzf->buf, BZ_MAX_UNUSED); + if (n == 0) { + break; } bzf->bufN = n; bzf->strm.avail_in = bzf->bufN; @@ -1622,48 +1560,43 @@ static inline int BZ2_bzRead(int *bzerror, void *b, void *buf, int len) ret = BZ2_bzDecompress(&(bzf->strm)); if ((ret != BZ_OK) && (ret != BZ_STREAM_END)) { - bz_seterr(ret, bzerror, &bzf); - return 0; - } - - if ((ret == BZ_OK) && myfeof(bzf->handle) && - (bzf->strm.avail_in == 0) && (bzf->strm.avail_out > 0)) { - bz_seterr(BZ_UNEXPECTED_EOF, bzerror, &bzf); - return(0); + error_msg_and_die("Error decompressing"); } if (ret == BZ_STREAM_END) { - bz_seterr(BZ_STREAM_END, bzerror, &bzf); - return(len - bzf->strm.avail_out); + bzerr = BZ_STREAM_END; + return(count - bzf->strm.avail_out); } if (bzf->strm.avail_out == 0) { - bz_seterr(BZ_OK, bzerror, &bzf); - return(len); + bzerr = BZ_OK; + return(count); } } - return(0); /*not reached*/ + return(0); } -static inline void *BZ2_bzReadOpen(int *bzerror, FILE *f, void *unused, int nUnused) +extern void BZ2_bzReadOpen(int fd, void *unused, int nUnused) { - bzFile *bzf = xmalloc(sizeof(bzFile)); - int ret; - - bz_seterr(BZ_OK, bzerror, &bzf); + DState *s; + bzf = xmalloc(sizeof(bzFile)); bzf->initialisedOk = FALSE; - bzf->handle = f; - bzf->bufN = 0; - - ret = BZ2_bzDecompressInit(&(bzf->strm)); - if (ret != BZ_OK) { - bz_seterr(ret, bzerror, &bzf); - free(bzf); - return NULL; - } + bzf->fd = fd; + bzf->bufN = 0; + + s = xmalloc(sizeof(DState)); + s->strm = &bzf->strm; + s->state = BZ_X_MAGIC_1; + s->bsLive = 0; + s->bsBuff = 0; + s->calculatedCombinedCRC = 0; + s->tt = NULL; + s->currBlockNo = 0; + bzf->strm.state = s; while (nUnused > 0) { - bzf->buf[bzf->bufN] = *((unsigned char *)(unused)); bzf->bufN++; + bzf->buf[bzf->bufN] = *((unsigned char *)(unused)); + bzf->bufN++; unused = ((void *)( 1 + ((unsigned char *)(unused)) )); nUnused--; } @@ -1671,119 +1604,55 @@ static inline void *BZ2_bzReadOpen(int *bzerror, FILE *f, void *unused, int nUnu bzf->strm.next_in = bzf->buf; bzf->initialisedOk = TRUE; - return bzf; + + return; } -extern unsigned char uncompressStream(FILE *zStream, FILE *stream) +extern unsigned char uncompressStream(int src_fd, int dst_fd) { unsigned char unused[BZ_MAX_UNUSED]; unsigned char *unusedTmp; unsigned char obuf[5000]; - bzFile *bzf = NULL; - int bzerr_dummy; - int bzerr; int nread; int nUnused; int streamNo; - int ret; int i; nUnused = 0; streamNo = 0; - if (ferror(stream)) { - goto errhandler_io; - } - if (ferror(zStream)) { - goto errhandler_io; - } - while(1) { - bzf = BZ2_bzReadOpen(&bzerr, zStream, unused, nUnused); - if (bzf == NULL || bzerr != BZ_OK) { - goto errhandler; - } + BZ2_bzReadOpen(src_fd, unused, nUnused); streamNo++; while (bzerr == BZ_OK) { - nread = BZ2_bzRead(&bzerr, bzf, obuf, 5000); + nread = read_bz2(src_fd, obuf, 5000); if (bzerr == BZ_DATA_ERROR_MAGIC) { - goto errhandler; - } - if ((bzerr == BZ_OK || bzerr == BZ_STREAM_END) && nread > 0) { - fwrite(obuf, sizeof(unsigned char), nread, stream); + error_msg_and_die("invalid magic"); } - if (ferror(stream)) { - goto errhandler_io; + if (((bzerr == BZ_OK) || (bzerr == BZ_STREAM_END)) && (nread > 0)) { + if (write(dst_fd, obuf, nread) != nread) { + BZ2_bzReadClose(); + perror_msg_and_die("Couldnt write to file"); + } } } - if (bzerr != BZ_STREAM_END) { - goto errhandler; - } nUnused = bzf->strm.avail_in; unusedTmp = bzf->strm.next_in; - bz_seterr(BZ_OK, &bzerr, &bzf); + for (i = 0; i < nUnused; i++) { unused[i] = unusedTmp[i]; } - BZ2_bzReadClose(&bzerr, bzf); - if ((nUnused == 0) && myfeof(zStream)) { + BZ2_bzReadClose(); + if (nUnused == 0) { break; } } - if (ferror(zStream)) { - goto errhandler_io; - } - ret = fclose(zStream); - if (ret == EOF) { - goto errhandler_io; - } - if (ferror(stream)) { - goto errhandler_io; - } - ret = fflush(stream); - if (ret != 0) { - goto errhandler_io; - } - if (stream != stdout) { - ret = fclose(stream); - if (ret == EOF) { - goto errhandler_io; - } + close(src_fd); + if (dst_fd != fileno(stdout)) { + close(dst_fd); } return TRUE; - -errhandler: - BZ2_bzReadClose ( &bzerr_dummy, bzf ); - switch (bzerr) { - case BZ_IO_ERROR: -errhandler_io: - error_msg("\n%s: I/O or other error, bailing out. " - "Possible reason follows.\n", applet_name); - perror(applet_name); - exit(1); - case BZ_DATA_ERROR: - error_msg("\n%s: Data integrity error when decompressing.\n", applet_name); - exit(2); - case BZ_UNEXPECTED_EOF: - error_msg("\n%s: Compressed file ends unexpectedly;\n\t" - "perhaps it is corrupted? *Possible* reason follows.\n", applet_name); - perror(applet_name); - exit(2); - case BZ_DATA_ERROR_MAGIC: - if (zStream != stdin) { - fclose(zStream); - } - if (stream != stdout) { - fclose(stream); - } - if (streamNo == 1) { - return FALSE; - } else { - return TRUE; - } - } - - return(TRUE); /*notreached*/ } + diff --git a/archival/libunarchive/get_header_tar.c b/archival/libunarchive/get_header_tar.c index e87eb77b8..b2b9e0b03 100644 --- a/archival/libunarchive/get_header_tar.c +++ b/archival/libunarchive/get_header_tar.c @@ -50,9 +50,9 @@ extern char get_header_tar(archive_handle_t *archive_handle) char *tmp; /* Align header */ - archive_handle->offset += data_align(archive_handle->src_fd, archive_handle->offset, 512); + data_align(archive_handle, 512); - if (xread_all_eof(archive_handle->src_fd, tar.raw, 512) == 0) { + if (archive_xread_all_eof(archive_handle, tar.raw, 512) == 0) { /* End of file */ return(EXIT_FAILURE); } @@ -72,7 +72,6 @@ extern char get_header_tar(archive_handle_t *archive_handle) #endif error_msg_and_die("Invalid tar magic"); } - /* Do checksum on headers */ for (i = 0; i < 148 ; i++) { sum += tar.raw[i]; @@ -138,7 +137,7 @@ extern char get_header_tar(archive_handle_t *archive_handle) char *longname; longname = xmalloc(file_header->size + 1); - xread_all(archive_handle->src_fd, longname, file_header->size); + archive_xread_all(archive_handle, longname, file_header->size); longname[file_header->size] = '\0'; archive_handle->offset += file_header->size; @@ -150,7 +149,7 @@ extern char get_header_tar(archive_handle_t *archive_handle) char *linkname; linkname = xmalloc(file_header->size + 1); - xread_all(archive_handle->src_fd, linkname, file_header->size); + archive_xread_all(archive_handle, linkname, file_header->size); linkname[file_header->size] = '\0'; archive_handle->offset += file_header->size; diff --git a/archival/libunarchive/get_header_tar_gz.c b/archival/libunarchive/get_header_tar_gz.c index 24d19fbfd..f0d4b1359 100644 --- a/archival/libunarchive/get_header_tar_gz.c +++ b/archival/libunarchive/get_header_tar_gz.c @@ -29,7 +29,10 @@ extern char get_header_tar_gz(archive_handle_t *archive_handle) int pid; unsigned char magic[2]; - xread_all(archive_handle->src_fd, &magic, 2); + /* Cant lseek over pipe's */ + archive_handle->seek = seek_by_char; + + archive_xread_all(archive_handle, &magic, 2); if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) { error_msg_and_die("Invalid gzip magic"); } diff --git a/archival/libunarchive/init_handle.c b/archival/libunarchive/init_handle.c index 12d9e7183..4b0103491 100644 --- a/archival/libunarchive/init_handle.c +++ b/archival/libunarchive/init_handle.c @@ -1,3 +1,20 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <unistd.h> #include <string.h> #include "libbb.h" #include "unarchive.h" @@ -13,6 +30,8 @@ archive_handle_t *init_handle(void) archive_handle->action_header = header_skip; archive_handle->action_data = data_skip; archive_handle->filter = filter_accept_all; + archive_handle->read = read; + archive_handle->seek = seek_by_jump; return(archive_handle); } diff --git a/archival/libunarchive/seek_by_char.c b/archival/libunarchive/seek_by_char.c new file mode 100644 index 000000000..f33935cb5 --- /dev/null +++ b/archival/libunarchive/seek_by_char.c @@ -0,0 +1,25 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "unarchive.h" + +extern void seek_by_char(const archive_handle_t *archive_handle, const unsigned int amount) +{ + unsigned int i; + for (i = 0; i < amount; i++) { + archive_xread_char(archive_handle); + } +} diff --git a/archival/libunarchive/seek_by_jump.c b/archival/libunarchive/seek_by_jump.c new file mode 100644 index 000000000..efad97fc4 --- /dev/null +++ b/archival/libunarchive/seek_by_jump.c @@ -0,0 +1,35 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <sys/types.h> +#include <errno.h> +#include <unistd.h> +#include <stdlib.h> + +#include "libbb.h" +#include "unarchive.h" + +extern void seek_by_jump(const archive_handle_t *archive_handle, const unsigned int amount) +{ + if (lseek(archive_handle->src_fd, (off_t) amount, SEEK_CUR) == (off_t) -1) { +#if CONFIG_FEATURE_UNARCHIVE_TAPE + if (errno == ESPIPE) { + seek_by_char(archive_handle, amount); + } else +#endif + perror_msg_and_die("Seek failure"); + } +} diff --git a/archival/libunarchive/unpack_ar_archive.c b/archival/libunarchive/unpack_ar_archive.c index 923b8a068..afa3672ad 100644 --- a/archival/libunarchive/unpack_ar_archive.c +++ b/archival/libunarchive/unpack_ar_archive.c @@ -24,7 +24,7 @@ extern void unpack_ar_archive(archive_handle_t *ar_archive) { char magic[7]; - xread_all(ar_archive->src_fd, magic, 7); + archive_xread_all(ar_archive, magic, 7); if (strncmp(magic, "!<arch>", 7) != 0) { error_msg_and_die("Invalid ar magic"); } diff --git a/archival/tar.c b/archival/tar.c index 48d6ce22e..e1e121a09 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -627,7 +627,7 @@ int tar_main(int argc, char **argv) tar_handle = init_handle(); tar_handle->flags = ARCHIVE_CREATE_LEADING_DIRS; - while ((opt = getopt(argc, argv, "ctxT:X:C:f:Opvz")) != -1) { + while ((opt = getopt(argc, argv, "cjtxT:X:C:f:Opvz")) != -1) { switch (opt) { /* One and only one of these is required */ #ifdef CONFIG_FEATURE_TAR_CREATE @@ -684,9 +684,8 @@ int tar_main(int argc, char **argv) break; #endif #ifdef CONFIG_FEATURE_TAR_BZIP2 - /* Not enabled yet */ case 'j': - archive_handle->archive_action = bunzip2; + tar_handle->read = read_bz2; break; #endif default: @@ -703,14 +702,8 @@ int tar_main(int argc, char **argv) /* Setup an array of filenames to work with */ /* TODO: This is the same as in ar, seperate function ? */ while (optind < argc) { -#if 0 - char absolute_path[PATH_MAX]; - realpath(argv[optind], absolute_path); - tar_handle->accept = add_to_list(tar_handle->accept, absolute_path); -#endif tar_handle->accept = add_to_list(tar_handle->accept, argv[optind]); optind++; - } if ((tar_handle->accept) || (tar_handle->reject)) { @@ -744,13 +737,21 @@ int tar_main(int argc, char **argv) if ((tar_filename[0] == '-') && (tar_filename[1] == '\0')) { tar_handle->src_fd = fileno(stdin); } else { + tar_handle->seek = seek_by_jump; tar_handle->src_fd = xopen(tar_filename, O_RDONLY); } #ifdef CONFIG_FEATURE_TAR_GZIP if (get_header_ptr == get_header_tar_gz) { + tar_handle->seek = seek_by_char; get_header_tar_gz(tar_handle); } else -#endif /* CONFIG_FEATURE_TAR_CREATE */ +#endif /* CONFIG_FEATURE_TAR_GZIP */ +#ifdef CONFIG_FEATURE_TAR_BZIP2 + if (tar_handle->read == read_bz2) { + BZ2_bzReadOpen(tar_handle->src_fd, NULL, 0); + while (get_header_tar(tar_handle) == EXIT_SUCCESS); + } else +#endif /* CONFIG_FEATURE_TAR_BZIP2 */ while (get_header_tar(tar_handle) == EXIT_SUCCESS); diff --git a/archival/unzip.c b/archival/unzip.c index 5a22d242a..4c1e5ce40 100644 --- a/archival/unzip.c +++ b/archival/unzip.c @@ -136,13 +136,14 @@ extern int unzip_main(int argc, char **argv) if (*argv[optind] == '-') { archive_handle->src_fd = fileno(stdin); - } else { + archive_handle->seek = seek_by_char; + } else { archive_handle->src_fd = xopen(argv[optind++], O_RDONLY); - } + } if ((base_dir) && (chdir(base_dir))) { perror_msg_and_die("Couldnt chdir"); - } + } while (optind < argc) { archive_handle->filter = filter_accept_list; @@ -155,7 +156,7 @@ extern int unzip_main(int argc, char **argv) int dst_fd; /* TODO Endian issues */ - xread_all(archive_handle->src_fd, &magic, 4); + archive_xread_all(archive_handle, &magic, 4); archive_handle->offset += 4; if (magic == ZIP_CDS_MAGIC) { @@ -166,7 +167,7 @@ extern int unzip_main(int argc, char **argv) } /* Read the file header */ - xread_all(archive_handle->src_fd, zip_header.raw, 26); + archive_xread_all(archive_handle, zip_header.raw, 26); archive_handle->offset += 26; archive_handle->file_header->mode = S_IFREG | 0777; @@ -176,7 +177,7 @@ extern int unzip_main(int argc, char **argv) /* Read filename */ archive_handle->file_header->name = xmalloc(zip_header.formated.filename_len + 1); - xread_all(archive_handle->src_fd, archive_handle->file_header->name, zip_header.formated.filename_len); + archive_xread_all(archive_handle, archive_handle->file_header->name, zip_header.formated.filename_len); archive_handle->offset += zip_header.formated.filename_len; archive_handle->file_header->name[zip_header.formated.filename_len] = '\0'; @@ -228,7 +229,7 @@ extern int unzip_main(int argc, char **argv) /* skip over duplicate crc, compressed size and uncompressed size */ unsigned short i; for (i = 0; i != 12; i++) { - xread_char(archive_handle->src_fd); + archive_xread_char(archive_handle); } archive_handle->offset += 12; } |