unzip applet by Laurence Anderson ----------------------------------------------------------------------
No binary (build failed)
—
(log yok)
| @@ -34,6 +34,7 @@ obj-$(CONFIG_GUNZIP) += gunzip.o | |
| obj-$(CONFIG_GZIP) += gzip.o | |
| obj-$(CONFIG_RPM2CPIO) += rpm2cpio.o | |
| obj-$(CONFIG_TAR) += tar.o | |
| + | obj-$(CONFIG_UNZIP) += unzip.o |
| # Hand off to toplevel Rules.mak | |
| @@ -20,4 +20,5 @@ if [ "$CONFIG_TAR" = "y" ] ; then | |
| bool ' Enable -X and --exclude options (exclude files)' CONFIG_FEATURE_TAR_EXCLUDE | |
| bool ' Enable -z option (currently only for extracting)' CONFIG_FEATURE_TAR_GZIP | |
| fi | |
| + | bool 'unzip' CONFIG_UNZIP |
| endmenu | |
| @@ -20,7 +20,7 @@ | |
| TOPDIR :=../.. | |
| L_TARGET := libunarchive.a | |
| - | obj-y := unarchive.o seek_sub_file.o |
| + | obj-y := unarchive.o seek_sub_file.o |
| obj-n := | |
| obj- := | |
| @@ -41,13 +41,17 @@ ifeq ($(CONFIG_CPIO),y) | |
| endif | |
| ifeq ($(CONFIG_RPM2CPIO),y) | |
| - | obj-y += get_header_cpio.o |
| + | obj-y += get_header_cpio.o |
| endif | |
| ifeq ($(CONFIG_TAR),y) | |
| obj-y += get_header_tar.o | |
| endif | |
| + | ifeq ($(CONFIG_UNZIP),y) |
| + | obj-y += get_header_zip.o |
| + | endif |
| + | |
| # Hand off to toplevel Rules.mak | |
| include $(TOPDIR)/Rules.mak | |
| @@ -80,7 +80,7 @@ static const int ERROR = 1; | |
| /* | |
| * window size--must be a power of two, and | |
| - | * at least 32K for zip's deflate method |
| + | * at least 32K for zip's deflate method |
| */ | |
| static const int WSIZE = 0x8000; | |
| @@ -846,7 +846,7 @@ static int inflate_block(int *e) | |
| * | |
| * GLOBAL VARIABLES: outcnt, bk, bb, hufts, inptr | |
| */ | |
| - | static int inflate(void) |
| + | extern int inflate(FILE *in, FILE *out) |
| { | |
| int e; /* last block flag */ | |
| int r; /* result code */ | |
| @@ -857,6 +857,13 @@ static int inflate(void) | |
| bk = 0; | |
| bb = 0; | |
| + | in_file = in; |
| + | out_file = out; |
| + | |
| + | /* Allocate all global buffers (for DYN_ALLOC option) */ |
| + | window = xmalloc((size_t)(((2L*WSIZE)+1L)*sizeof(unsigned char))); |
| + | bytes_out = 0L; |
| + | |
| /* Create the crc table */ | |
| make_crc_table(); | |
| @@ -881,13 +888,15 @@ static int inflate(void) | |
| /* flush out window */ | |
| flush_window(); | |
| + | free(window); |
| + | free(crc_table); |
| /* return success */ | |
| return 0; | |
| } | |
| /* =========================================================================== | |
| - | * Unzip in to out. This routine works on both gzip and pkzip files. |
| + | * Unzip in to out. This routine works on gzip files only. |
| * | |
| * IN assertions: the buffer inbuf contains already the beginning of | |
| * the compressed data, from offsets inptr to insize-1 included. | |
| @@ -901,9 +910,6 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file) | |
| typedef void (*sig_type) (int); | |
| unsigned short i; | |
| - | in_file = l_in_file; |
| - | out_file = l_out_file; |
| - | |
| if (signal(SIGINT, SIG_IGN) != SIG_IGN) { | |
| (void) signal(SIGINT, (sig_type) abort_gzip); | |
| } | |
| @@ -918,53 +924,48 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file) | |
| } | |
| #endif | |
| - | /* Allocate all global buffers (for DYN_ALLOC option) */ |
| - | window = xmalloc((size_t)(((2L*WSIZE)+1L)*sizeof(unsigned char))); |
| - | outcnt = 0; |
| - | bytes_out = 0L; |
| - | |
| /* Magic header for gzip files, 1F 8B = \037\213 */ | |
| - | if ((fgetc(in_file) != 0x1F) || (fgetc(in_file) != 0x8b)) { |
| + | if ((fgetc(l_in_file) != 0x1F) || (fgetc(l_in_file) != 0x8b)) { |
| error_msg("Invalid gzip magic"); | |
| return EXIT_FAILURE; | |
| } | |
| /* Check the compression method */ | |
| - | if (fgetc(in_file) != 8) { |
| + | if (fgetc(l_in_file) != 8) { |
| error_msg("Unknown compression method"); | |
| return(-1); | |
| } | |
| - | flags = (unsigned char) fgetc(in_file); |
| + | flags = (unsigned char) fgetc(l_in_file); |
| /* Ignore time stamp(4), extra flags(1), OS type(1) */ | |
| for (i = 0; i < 6; i++) { | |
| - | fgetc(in_file); |
| + | fgetc(l_in_file); |
| } | |
| if (flags & 0x04) { | |
| /* bit 2 set: extra field present */ | |
| - | const unsigned short extra = fgetc(in_file) + (fgetc(in_file) << 8); |
| + | const unsigned short extra = fgetc(l_in_file) + (fgetc(l_in_file) << 8); |
| for (i = 0; i < extra; i++) { | |
| - | fgetc(in_file); |
| + | fgetc(l_in_file); |
| } | |
| } | |
| /* Discard original name if any */ | |
| if (flags & 0x08) { | |
| /* bit 3 set: original file name present */ | |
| - | while (fgetc(in_file) != 0); /* null */ |
| + | while (fgetc(l_in_file) != 0); /* null */ |
| } | |
| /* Discard file comment if any */ | |
| if (flags & 0x10) { | |
| /* bit 4 set: file comment present */ | |
| - | while (fgetc(in_file) != 0); /* null */ |
| + | while (fgetc(l_in_file) != 0); /* null */ |
| } | |
| /* Decompress */ | |
| - | if (inflate() != 0) { |
| + | if (inflate(l_in_file, l_out_file) != 0) { |
| error_msg("invalid compressed data--format violated"); | |
| } | |
| @@ -972,7 +973,7 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file) | |
| * crc32 (see algorithm.doc) | |
| * uncompressed input size modulo 2^32 | |
| */ | |
| - | fread(buf, 1, 8, in_file); |
| + | fread(buf, 1, 8, l_in_file); |
| /* Validate decompression - crc */ | |
| if ((unsigned int)((buf[0] | (buf[1] << 8)) |((buf[2] | (buf[3] << 8)) << 16)) != (crc ^ 0xffffffffL)) { | |
| @@ -983,14 +984,11 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file) | |
| error_msg("invalid compressed data--length error"); | |
| } | |
| - | free(window); |
| - | free(crc_table); |
| - | |
| return 0; | |
| } | |
| /* | |
| - | * This needs access to global variables wondow and crc_table, so its not in its own file. |
| + | * This needs access to global variables window and crc_table, so its not in its own file. |
| */ | |
| extern void gz_close(int gunzip_pid) | |
| { | |
| @@ -0,0 +1,110 @@ | |
| + | /* vi: set sw=4 ts=4: */ |
| + | /* |
| + | * get_header_zip for busybox |
| + | * |
| + | * Copyright (C) 2001 by Laurence Anderson |
| + | * |
| + | * 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 <stdio.h> |
| + | #include <stdlib.h> |
| + | #include <string.h> |
| + | #include "unarchive.h" |
| + | #include "libbb.h" |
| + | |
| + | #define ZIP_FILEHEADER_MAGIC 0x04034b50 |
| + | #define ZIP_CDS_MAGIC 0x02014b50 |
| + | #define ZIP_CDS_END_MAGIC 0x06054b50 |
| + | #define ZIP_DD_MAGIC 0x8074b50 |
| + | |
| + | file_header_t *get_header_zip(FILE *zip_stream) |
| + | { |
| + | struct { |
| + | short version __attribute__ ((packed)); |
| + | short flags __attribute__ ((packed)); |
| + | short method __attribute__ ((packed)); |
| + | short modtime __attribute__ ((packed)); |
| + | short moddate __attribute__ ((packed)); |
| + | int crc32 __attribute__ ((packed)); |
| + | int cmpsize __attribute__ ((packed)); |
| + | int ucmpsize __attribute__ ((packed)); |
| + | short filename_len __attribute__ ((packed)); |
| + | short extra_len __attribute__ ((packed)); |
| + | } zip_header; |
| + | file_header_t *zip_entry = NULL; |
| + | int magic; |
| + | static int dd_ahead = 0; // If this is true, the we didn't know how long the last extraced file was |
| + | |
| + | fread (&magic, 4, 1, zip_stream); |
| + | archive_offset += 4; |
| + | |
| + | if (feof(zip_stream)) return(NULL); |
| + | checkmagic: |
| + | switch (magic) { |
| + | case ZIP_FILEHEADER_MAGIC: |
| + | zip_entry = xcalloc(1, sizeof(file_header_t)); |
| + | fread (&zip_header, sizeof(zip_header), 1, zip_stream); |
| + | archive_offset += sizeof(zip_header); |
| + | if (!(zip_header.method == 8 || zip_header.method == 0)) { printf("Unsupported compression method %d\n", zip_header.method); return(NULL); } |
| + | zip_entry->name = calloc(zip_header.filename_len + 1, sizeof(char)); |
| + | fread (zip_entry->name, sizeof(char), zip_header.filename_len, zip_stream); |
| + | archive_offset += zip_header.filename_len; |
| + | seek_sub_file(zip_stream, zip_header.extra_len); |
| + | zip_entry->size = zip_header.cmpsize; |
| + | if (zip_header.method == 8) zip_entry->extract_func = &inflate; |
| + | zip_entry->mode = S_IFREG | 0777; |
| + | // Time/Date? |
| + | if (*(zip_entry->name + strlen(zip_entry->name) - 1) == '/') { // Files that end in a / are directories |
| + | zip_entry->mode ^= S_IFREG; |
| + | zip_entry->mode |= S_IFDIR; |
| + | *(zip_entry->name + strlen(zip_entry->name) - 1) = '\0'; // Remove trailing / so unarchive doesn't get confused |
| + | } |
| + | //printf("cmpsize: %d, ucmpsize: %d, method: %d\n", zip_header.cmpsize, zip_header.ucmpsize, zip_header.method); |
| + | if (zip_header.flags & 0x8) { // crc32, and sizes are in the data description _after_ the file |
| + | if (zip_header.cmpsize == 0) dd_ahead = 1; // As we don't know how long this file it is difficult to skip! but it is compressed, so normally its ok |
| + | if (zip_header.ucmpsize != 0) dd_ahead = 2; // Humm... we would otherwise skip this twice - not good! |
| + | } |
| + | break; |
| + | case ZIP_CDS_MAGIC: /* FALLTHRU */ |
| + | case ZIP_CDS_END_MAGIC: |
| + | return(NULL); |
| + | break; |
| + | case ZIP_DD_MAGIC: { |
| + | int cmpsize; |
| + | seek_sub_file(zip_stream, 4); // Skip crc32 |
| + | fread(&cmpsize, 4, 1, zip_stream); |
| + | archive_offset += 4; |
| + | if (dd_ahead == 1) archive_offset += cmpsize; |
| + | seek_sub_file(zip_stream, 4); // Skip uncompressed size |
| + | dd_ahead = 0; |
| + | return (get_header_zip(zip_stream)); |
| + | break; } |
| + | default: |
| + | if (!dd_ahead) error_msg("Invalid magic (%#x): Trying to skip junk", magic); |
| + | dd_ahead = 0; |
| + | while (!feof(zip_stream)) { |
| + | int tmpmagic; |
| + | tmpmagic = fgetc(zip_stream); |
| + | archive_offset++; |
| + | magic = ((magic >> 8) & 0x00ffffff) | ((tmpmagic << 24) & 0xff000000); |
| + | if (magic == ZIP_FILEHEADER_MAGIC || magic == ZIP_CDS_MAGIC || magic == ZIP_CDS_END_MAGIC) goto checkmagic; |
| + | } |
| + | error_msg("End of archive reached: Bad archive"); |
| + | return(NULL); |
| + | } |
| + | //if (archive_offset != ftell(zip_stream)) printf("Archive offset out of sync (%d,%d)\n", (int) archive_offset, (int) ftell(zip_stream)); |
| + | return(zip_entry); |
| + | } |
| @@ -120,7 +120,8 @@ char *extract_archive(FILE *src_stream, FILE *out_stream, const file_header_t *f | |
| return NULL; | |
| } | |
| archive_offset += file_entry->size; | |
| - | copy_file_chunk(src_stream, dst_stream, file_entry->size); |
| + | if (file_entry->extract_func) file_entry->extract_func(src_stream, dst_stream); |
| + | else copy_file_chunk(src_stream, dst_stream, file_entry->size); |
| fclose(dst_stream); | |
| } | |
| break; | |
| @@ -80,7 +80,7 @@ static const int ERROR = 1; | |
| /* | |
| * window size--must be a power of two, and | |
| - | * at least 32K for zip's deflate method |
| + | * at least 32K for zip's deflate method |
| */ | |
| static const int WSIZE = 0x8000; | |
| @@ -846,7 +846,7 @@ static int inflate_block(int *e) | |
| * | |
| * GLOBAL VARIABLES: outcnt, bk, bb, hufts, inptr | |
| */ | |
| - | static int inflate(void) |
| + | extern int inflate(FILE *in, FILE *out) |
| { | |
| int e; /* last block flag */ | |
| int r; /* result code */ | |
| @@ -857,6 +857,13 @@ static int inflate(void) | |
| bk = 0; | |
| bb = 0; | |
| + | in_file = in; |
| + | out_file = out; |
| + | |
| + | /* Allocate all global buffers (for DYN_ALLOC option) */ |
| + | window = xmalloc((size_t)(((2L*WSIZE)+1L)*sizeof(unsigned char))); |
| + | bytes_out = 0L; |
| + | |
| /* Create the crc table */ | |
| make_crc_table(); | |
| @@ -881,13 +888,15 @@ static int inflate(void) | |
| /* flush out window */ | |
| flush_window(); | |
| + | free(window); |
| + | free(crc_table); |
| /* return success */ | |
| return 0; | |
| } | |
| /* =========================================================================== | |
| - | * Unzip in to out. This routine works on both gzip and pkzip files. |
| + | * Unzip in to out. This routine works on gzip files only. |
| * | |
| * IN assertions: the buffer inbuf contains already the beginning of | |
| * the compressed data, from offsets inptr to insize-1 included. | |
| @@ -901,9 +910,6 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file) | |
| typedef void (*sig_type) (int); | |
| unsigned short i; | |
| - | in_file = l_in_file; |
| - | out_file = l_out_file; |
| - | |
| if (signal(SIGINT, SIG_IGN) != SIG_IGN) { | |
| (void) signal(SIGINT, (sig_type) abort_gzip); | |
| } | |
| @@ -918,53 +924,48 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file) | |
| } | |
| #endif | |
| - | /* Allocate all global buffers (for DYN_ALLOC option) */ |
| - | window = xmalloc((size_t)(((2L*WSIZE)+1L)*sizeof(unsigned char))); |
| - | outcnt = 0; |
| - | bytes_out = 0L; |
| - | |
| /* Magic header for gzip files, 1F 8B = \037\213 */ | |
| - | if ((fgetc(in_file) != 0x1F) || (fgetc(in_file) != 0x8b)) { |
| + | if ((fgetc(l_in_file) != 0x1F) || (fgetc(l_in_file) != 0x8b)) { |
| error_msg("Invalid gzip magic"); | |
| return EXIT_FAILURE; | |
| } | |
| /* Check the compression method */ | |
| - | if (fgetc(in_file) != 8) { |
| + | if (fgetc(l_in_file) != 8) { |
| error_msg("Unknown compression method"); | |
| return(-1); | |
| } | |
| - | flags = (unsigned char) fgetc(in_file); |
| + | flags = (unsigned char) fgetc(l_in_file); |
| /* Ignore time stamp(4), extra flags(1), OS type(1) */ | |
| for (i = 0; i < 6; i++) { | |
| - | fgetc(in_file); |
| + | fgetc(l_in_file); |
| } | |
| if (flags & 0x04) { | |
| /* bit 2 set: extra field present */ | |
| - | const unsigned short extra = fgetc(in_file) + (fgetc(in_file) << 8); |
| + | const unsigned short extra = fgetc(l_in_file) + (fgetc(l_in_file) << 8); |
| for (i = 0; i < extra; i++) { | |
| - | fgetc(in_file); |
| + | fgetc(l_in_file); |
| } | |
| } | |
| /* Discard original name if any */ | |
| if (flags & 0x08) { | |
| /* bit 3 set: original file name present */ | |
| - | while (fgetc(in_file) != 0); /* null */ |
| + | while (fgetc(l_in_file) != 0); /* null */ |
| } | |
| /* Discard file comment if any */ | |
| if (flags & 0x10) { | |
| /* bit 4 set: file comment present */ | |
| - | while (fgetc(in_file) != 0); /* null */ |
| + | while (fgetc(l_in_file) != 0); /* null */ |
| } | |
| /* Decompress */ | |
| - | if (inflate() != 0) { |
| + | if (inflate(l_in_file, l_out_file) != 0) { |
| error_msg("invalid compressed data--format violated"); | |
| } | |
| @@ -972,7 +973,7 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file) | |
| * crc32 (see algorithm.doc) | |
| * uncompressed input size modulo 2^32 | |
| */ | |
| - | fread(buf, 1, 8, in_file); |
| + | fread(buf, 1, 8, l_in_file); |
| /* Validate decompression - crc */ | |
| if ((unsigned int)((buf[0] | (buf[1] << 8)) |((buf[2] | (buf[3] << 8)) << 16)) != (crc ^ 0xffffffffL)) { | |
| @@ -983,14 +984,11 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file) | |
| error_msg("invalid compressed data--length error"); | |
| } | |
| - | free(window); |
| - | free(crc_table); |
| - | |
| return 0; | |
| } | |
| /* | |
| - | * This needs access to global variables wondow and crc_table, so its not in its own file. |
| + | * This needs access to global variables window and crc_table, so its not in its own file. |
| */ | |
| extern void gz_close(int gunzip_pid) | |
| { | |
| @@ -0,0 +1,94 @@ | |
| + | /* vi: set sw=4 ts=4: */ |
| + | /* |
| + | * Mini unzip implementation for busybox |
| + | * |
| + | * Copyright (C) 2001 by Laurence Anderson |
| + | * |
| + | * 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 <fcntl.h> |
| + | #include <getopt.h> |
| + | #include <stdlib.h> |
| + | #include <string.h> |
| + | #include <unistd.h> |
| + | #include "unarchive.h" |
| + | #include "busybox.h" |
| + | |
| + | extern int unzip_main(int argc, char **argv) |
| + | { |
| + | FILE *src_stream; |
| + | int extract_function = extract_all_to_fs | extract_create_leading_dirs; |
| + | char **extract_names = NULL; |
| + | char **exclude_names = NULL; |
| + | int opt = 0; |
| + | int num_of_entries = 0; |
| + | int exclude = 0; |
| + | char *outdir = "./"; |
| + | FILE *msgout = stdout; |
| + | |
| + | while ((opt = getopt(argc, argv, "lnopqxd:")) != -1) { |
| + | switch (opt) { |
| + | case 'l': |
| + | extract_function |= extract_verbose_list; |
| + | extract_function ^= extract_all_to_fs; |
| + | break; |
| + | case 'n': |
| + | break; |
| + | case 'o': |
| + | extract_function |= extract_unconditional; |
| + | break; |
| + | case 'p': |
| + | extract_function |= extract_to_stdout; |
| + | extract_function ^= extract_all_to_fs; |
| + | /* FALLTHROUGH */ |
| + | case 'q': |
| + | msgout = xfopen("/dev/null", "w"); |
| + | break; |
| + | case 'd': |
| + | outdir = xstrdup(optarg); |
| + | strcat(outdir, "/"); |
| + | break; |
| + | case 'x': |
| + | exclude = 1; |
| + | break; |
| + | } |
| + | } |
| + | |
| + | if (optind == argc) { |
| + | show_usage(); |
| + | } |
| + | |
| + | if (*argv[optind] == '-') src_stream = stdin; |
| + | else src_stream = xfopen(argv[optind++], "r"); |
| + | |
| + | while (optind < argc) { |
| + | if (exclude) { |
| + | exclude_names = xrealloc(exclude_names, sizeof(char *) * (num_of_entries + 2)); |
| + | exclude_names[num_of_entries] = xstrdup(argv[optind]); |
| + | } else { |
| + | extract_names = xrealloc(extract_names, sizeof(char *) * (num_of_entries + 2)); |
| + | extract_names[num_of_entries] = xstrdup(argv[optind]); |
| + | } |
| + | num_of_entries++; |
| + | if (exclude) exclude_names[num_of_entries] = NULL; |
| + | else extract_names[num_of_entries] = NULL; |
| + | optind++; |
| + | } |
| + | |
| + | unarchive(src_stream, msgout, &get_header_zip, extract_function, outdir, extract_names, exclude_names); |
| + | return EXIT_SUCCESS; |
| + | } |
| @@ -470,6 +470,9 @@ | |
| #ifdef CONFIG_UNIX2DOS | |
| APPLET(unix2dos, dos2unix_main, _BB_DIR_USR_BIN) | |
| #endif | |
| + | #ifdef CONFIG_UNZIP |
| + | APPLET(unzip, unzip_main, _BB_DIR_USR_BIN) |
| + | #endif |
| #ifdef CONFIG_UPDATE | |
| APPLET(update, update_main, _BB_DIR_SBIN) | |
| #endif | |
| @@ -215,6 +215,7 @@ extern long arith (const char *startbuf, int *errcode); | |
| int read_package_field(const char *package_buffer, char **field_name, char **field_value); | |
| char *fgets_str(FILE *file, const char *terminating_string); | |
| + | extern int inflate(FILE *in, FILE *out); |
| extern int unzip(FILE *l_in_file, FILE *l_out_file); | |
| extern void gz_close(int gunzip_pid); | |
| extern FILE *gz_open(FILE *compressed_file, int *pid); | |
| @@ -26,11 +26,13 @@ typedef struct file_headers_s { | |
| mode_t mode; | |
| time_t mtime; | |
| dev_t device; | |
| + | int (*extract_func)(FILE *, FILE *); |
| } file_header_t; | |
| file_header_t *get_header_ar(FILE *in_file); | |
| file_header_t *get_header_cpio(FILE *src_stream); | |
| file_header_t *get_header_tar(FILE *tar_stream); | |
| + | file_header_t *get_header_zip(FILE *zip_stream); |
| void seek_sub_file(FILE *src_stream, const int count); | |
| @@ -1851,6 +1851,19 @@ | |
| "\t-u\toutput will be in UNIX format\n" \ | |
| "\t-d\toutput will be in DOS format" | |
| + | #define unzip_trivial_usage \ |
| + | "[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d exdir]" |
| + | #define unzip_full_usage \ |
| + | "Extracts files from ZIP archives\n" \ |
| + | "Options:\n" \ |
| + | "\t-l\tlist archive contents (short form)\n" \ |
| + | "\t-n\tnever overwrite existing files (default)\n" \ |
| + | "\t-o\toverwrite files without prompting\n" \ |
| + | "\t-p\tsend output to stdout\n" \ |
| + | "\t-q\tbe quiet\n" \ |
| + | "\t-x\texclude these files\n" \ |
| + | "\t-d\textract files into this directory" |
| + | |
| #define update_trivial_usage \ | |
| "[options]" | |
| #define update_full_usage \ | |
| @@ -80,7 +80,7 @@ static const int ERROR = 1; | |
| /* | |
| * window size--must be a power of two, and | |
| - | * at least 32K for zip's deflate method |
| + | * at least 32K for zip's deflate method |
| */ | |
| static const int WSIZE = 0x8000; | |
| @@ -846,7 +846,7 @@ static int inflate_block(int *e) | |
| * | |
| * GLOBAL VARIABLES: outcnt, bk, bb, hufts, inptr | |
| */ | |
| - | static int inflate(void) |
| + | extern int inflate(FILE *in, FILE *out) |
| { | |
| int e; /* last block flag */ | |
| int r; /* result code */ | |
| @@ -857,6 +857,13 @@ static int inflate(void) | |
| bk = 0; | |
| bb = 0; | |
| + | in_file = in; |
| + | out_file = out; |
| + | |
| + | /* Allocate all global buffers (for DYN_ALLOC option) */ |
| + | window = xmalloc((size_t)(((2L*WSIZE)+1L)*sizeof(unsigned char))); |
| + | bytes_out = 0L; |
| + | |
| /* Create the crc table */ | |
| make_crc_table(); | |
| @@ -881,13 +888,15 @@ static int inflate(void) | |
| /* flush out window */ | |
| flush_window(); | |
| + | free(window); |
| + | free(crc_table); |
| /* return success */ | |
| return 0; | |
| } | |
| /* =========================================================================== | |
| - | * Unzip in to out. This routine works on both gzip and pkzip files. |
| + | * Unzip in to out. This routine works on gzip files only. |
| * | |
| * IN assertions: the buffer inbuf contains already the beginning of | |
| * the compressed data, from offsets inptr to insize-1 included. | |
| @@ -901,9 +910,6 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file) | |
| typedef void (*sig_type) (int); | |
| unsigned short i; | |
| - | in_file = l_in_file; |
| - | out_file = l_out_file; |
| - | |
| if (signal(SIGINT, SIG_IGN) != SIG_IGN) { | |
| (void) signal(SIGINT, (sig_type) abort_gzip); | |
| } | |
| @@ -918,53 +924,48 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file) | |
| } | |
| #endif | |
| - | /* Allocate all global buffers (for DYN_ALLOC option) */ |
| - | window = xmalloc((size_t)(((2L*WSIZE)+1L)*sizeof(unsigned char))); |
| - | outcnt = 0; |
| - | bytes_out = 0L; |
| - | |
| /* Magic header for gzip files, 1F 8B = \037\213 */ | |
| - | if ((fgetc(in_file) != 0x1F) || (fgetc(in_file) != 0x8b)) { |
| + | if ((fgetc(l_in_file) != 0x1F) || (fgetc(l_in_file) != 0x8b)) { |
| error_msg("Invalid gzip magic"); | |
| return EXIT_FAILURE; | |
| } | |
| /* Check the compression method */ | |
| - | if (fgetc(in_file) != 8) { |
| + | if (fgetc(l_in_file) != 8) { |
| error_msg("Unknown compression method"); | |
| return(-1); | |
| } | |
| - | flags = (unsigned char) fgetc(in_file); |
| + | flags = (unsigned char) fgetc(l_in_file); |
| /* Ignore time stamp(4), extra flags(1), OS type(1) */ | |
| for (i = 0; i < 6; i++) { | |
| - | fgetc(in_file); |
| + | fgetc(l_in_file); |
| } | |
| if (flags & 0x04) { | |
| /* bit 2 set: extra field present */ | |
| - | const unsigned short extra = fgetc(in_file) + (fgetc(in_file) << 8); |
| + | const unsigned short extra = fgetc(l_in_file) + (fgetc(l_in_file) << 8); |
| for (i = 0; i < extra; i++) { | |
| - | fgetc(in_file); |
| + | fgetc(l_in_file); |
| } | |
| } | |
| /* Discard original name if any */ | |
| if (flags & 0x08) { | |
| /* bit 3 set: original file name present */ | |
| - | while (fgetc(in_file) != 0); /* null */ |
| + | while (fgetc(l_in_file) != 0); /* null */ |
| } | |
| /* Discard file comment if any */ | |
| if (flags & 0x10) { | |
| /* bit 4 set: file comment present */ | |
| - | while (fgetc(in_file) != 0); /* null */ |
| + | while (fgetc(l_in_file) != 0); /* null */ |
| } | |
| /* Decompress */ | |
| - | if (inflate() != 0) { |
| + | if (inflate(l_in_file, l_out_file) != 0) { |
| error_msg("invalid compressed data--format violated"); | |
| } | |
| @@ -972,7 +973,7 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file) | |
| * crc32 (see algorithm.doc) | |
| * uncompressed input size modulo 2^32 | |
| */ | |
| - | fread(buf, 1, 8, in_file); |
| + | fread(buf, 1, 8, l_in_file); |
| /* Validate decompression - crc */ | |
| if ((unsigned int)((buf[0] | (buf[1] << 8)) |((buf[2] | (buf[3] << 8)) << 16)) != (crc ^ 0xffffffffL)) { | |
| @@ -983,14 +984,11 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file) | |
| error_msg("invalid compressed data--length error"); | |
| } | |
| - | free(window); |
| - | free(crc_table); |
| - | |
| return 0; | |
| } | |
| /* | |
| - | * This needs access to global variables wondow and crc_table, so its not in its own file. |
| + | * This needs access to global variables window and crc_table, so its not in its own file. |
| */ | |
| extern void gz_close(int gunzip_pid) | |
| { | |