X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=archival%2Fgzip.c;h=05f6cb5821fbc637255053e0989ab0d40811c740;hb=03721973851afbe02bbc1cdc56ee6002631c4df6;hp=bc4c7badd10118b6edf0162850e0f9ebcde0493a;hpb=cb81e6484d1f50ec2761f6294722407b14add525;p=oweals%2Fbusybox.git diff --git a/archival/gzip.c b/archival/gzip.c index bc4c7badd..05f6cb582 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -9,31 +9,14 @@ * only standard in to standard out with -9 compression. It also requires * the zcat module for some important functions." * - * Adjusted further by Erik Andersen to support - * files as well as stdin/stdout, and to generally behave itself wrt + * Adjusted further by Erik Andersen to support + * files as well as stdin/stdout, and to generally behave itself wrt * command line handling. * - * 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 - * + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ -/* These defines are very important for BusyBox. Without these, - * huge chunks of ram are pre-allocated making the BusyBox bss - * size Freaking Huge(tm), which is a bad thing.*/ #define SMALL_MEM -#define DYN_ALLOC #include #include @@ -51,12 +34,6 @@ #include #include "busybox.h" -#define memzero(s, n) memset ((void *)(s), 0, (n)) - -#ifndef RETSIGTYPE -# define RETSIGTYPE void -#endif - typedef unsigned char uch; typedef unsigned short ush; typedef unsigned long ulg; @@ -106,17 +83,11 @@ typedef unsigned long ulg; # endif #endif -#ifdef DYN_ALLOC # define DECLARE(type, array, size) static type * array # define ALLOC(type, array, size) { \ - array = (type*)xcalloc((size_t)(((size)+1L)/2), 2*sizeof(type)); \ + array = (type*)xzalloc((size_t)(((size)+1L)/2) * 2*sizeof(type)); \ } # define FREE(array) {free(array), array=NULL;} -#else -# define DECLARE(type, array, size) static type array[size] -# define ALLOC(type, array, size) -# define FREE(array) -#endif #define tab_suffix window #define tab_prefix prev /* hash link (see deflate.c) */ @@ -173,15 +144,6 @@ typedef int file_t; /* Do not use stdio */ #define put_byte(c) {outbuf[outcnt++]=(uch)(c); if (outcnt==OUTBUFSIZ)\ flush_outbuf();} - -/* Output a 32 bit value to the bit stream, lsb first */ -#if 0 -#define put_long(n) { \ - put_short((n) & 0xffff); \ - put_short(((ulg)(n)) >> 16); \ -} -#endif - #define seekable() 0 /* force sequential output */ #define translate_eol 0 /* no option -a yet */ @@ -214,9 +176,6 @@ typedef int file_t; /* Do not use stdio */ static int zip(int in, int out); static int file_read(char *buf, unsigned size); - /* from gzip.c */ -static RETSIGTYPE abort_gzip(void); - /* from deflate.c */ static void lm_init(ush * flags); static ulg deflate(void); @@ -243,10 +202,6 @@ static void flush_outbuf(void); * terms of the GNU General Public License, see the file COPYING. */ -#if !defined(OF) && defined(lint) -# include "gzip.h" -#endif - #ifndef BITS # define BITS 16 #endif @@ -305,22 +260,20 @@ DECLARE(ush, d_buf, DIST_BUFSIZE); DECLARE(uch, window, 2L * WSIZE); DECLARE(ush, tab_prefix, 1L << BITS); -static int crc_table_empty = 1; - static int foreground; /* set if program run in foreground */ static int method = DEFLATED; /* compression method */ static int exit_code = OK; /* program exit code */ -static int part_nb; /* number of parts in .gz file */ static long time_stamp; /* original time stamp (modification time) */ -static long ifile_size; /* input file size, -1 for devices (debug only) */ static char z_suffix[MAX_SUFFIX + 1]; /* default suffix (can be set with --suffix) */ -static int z_len; /* strlen(z_suffix) */ static int ifd; /* input file descriptor */ static int ofd; /* output file descriptor */ +#ifdef DEBUG static unsigned insize; /* valid bytes in inbuf */ +#endif static unsigned outcnt; /* bytes in output buffer */ +static uint32_t *crc_32_tab; /* Output a 16 bit value, lsb first */ static void put_short(ush w) @@ -337,7 +290,7 @@ static void put_short(ush w) /* ======================================================================== * Signal and error handler. */ -static void abort_gzip() +static void abort_gzip(int ATTRIBUTE_UNUSED ignored) { exit(ERROR); } @@ -348,17 +301,12 @@ static void abort_gzip() static void clear_bufs(void) { outcnt = 0; +#ifdef DEBUG insize = 0; +#endif bytes_in = 0L; } -static void write_bb_error_msg(void) -{ - fputc('\n', stderr); - bb_perror_nomsg(); - abort_gzip(); -} - /* =========================================================================== * Does the same as write(), but also handles partial pipe writes and checks * for error return. @@ -368,9 +316,7 @@ static void write_buf(int fd, void *buf, unsigned cnt) unsigned n; while ((n = write(fd, buf, cnt)) != cnt) { - if (n == (unsigned) (-1)) { - write_bb_error_msg(); - } + if (n == (unsigned) (-1)) bb_error_msg_and_die(bb_msg_write_error); cnt -= n; buf = (void *) ((char *) buf + n); } @@ -381,33 +327,13 @@ static void write_buf(int fd, void *buf, unsigned cnt) * pointer, then initialize the crc shift register contents instead. * Return the current crc in either case. */ -static ulg updcrc(uch * s, unsigned n) +static uint32_t updcrc(uch * s, unsigned n) { - static ulg crc = (ulg) 0xffffffffL; /* shift register contents */ - register ulg c; /* temporary variable */ - static unsigned long crc_32_tab[256]; - - if (crc_table_empty) { - unsigned long csr; /* crc shift register */ - const unsigned long e = 0xedb88320L; /* polynomial exclusive-or pattern */ - int i; /* counter for all possible eight bit values */ - int k; /* byte being shifted into crc apparatus */ - - /* Compute table of CRC's. */ - crc_32_tab[0] = 0x00000000L; - for (i = 1; i < 256; i++) { - csr = i; - /* The idea to initialize the register with the byte instead of - * zero was stolen from Haruhiko Okumura's ar002 - */ - for (k = 8; k; k--) - csr = csr & 1 ? (csr >> 1) ^ e : csr >> 1; - crc_32_tab[i] = csr; - } - } + static uint32_t crc = ~0; /* shift register contents */ + uint32_t c; /* temporary variable */ if (s == NULL) { - c = 0xffffffffL; + c = ~0; } else { c = crc; if (n) @@ -416,7 +342,7 @@ static ulg updcrc(uch * s, unsigned n) } while (--n); } crc = c; - return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */ + return ~c; } /* bits.c -- output variable-length bit strings @@ -550,7 +476,7 @@ static void send_bits(int value, int length) */ static unsigned bi_reverse(unsigned code, int len) { - register unsigned res = 0; + unsigned res = 0; do { res |= code & 1; @@ -562,7 +488,7 @@ static unsigned bi_reverse(unsigned code, int len) /* =========================================================================== * Write out any remaining bits in an incomplete byte. */ -static void bi_windup() +static void bi_windup(void) { if (bi_valid > 8) { put_short(bi_buf); @@ -635,7 +561,7 @@ static void copy_block(char *buf, unsigned len, int header) * However the F&G algorithm may be faster for some highly redundant * files if the parameter max_chain_length (described below) is too large. * - * ACKNOWLEDGEMENTS + * ACKNOWLEDGMENTS * * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and * I found it in 'freeze' written by Leonid Broukhis. @@ -770,25 +696,26 @@ static unsigned match_start; /* start of matching string */ static int eofile; /* flag set at end of input file */ static unsigned lookahead; /* number of valid bytes ahead in window */ -static const unsigned max_chain_length = 4096; +enum { + max_chain_length = 4096, /* To speed up deflation, hash chains are never searched beyond this length. * A higher limit improves compression ratio but degrades the speed. */ -static const unsigned int max_lazy_match = 258; + max_lazy_match = 258, /* Attempt to find a better match only when the current match is strictly * smaller than this value. This mechanism is used only for compression * levels >= 4. */ -#define max_insert_length max_lazy_match + max_insert_length = max_lazy_match, /* Insert new strings in the hash table only if the match length * is not greater than this length. This saves time but degrades compression. * max_insert_length is used only for compression levels <= 3. */ -static const unsigned good_match = 32; + good_match = 32, /* Use a faster search when the previous match is longer than this */ @@ -799,12 +726,13 @@ static const unsigned good_match = 32; * found for specific files. */ -static const int nice_match = 258; /* Stop searching when current match exceeds this */ + nice_match = 258 /* Stop searching when current match exceeds this */ /* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 * For deflate_fast() (levels <= 3) good is ignored and lazy has a different * meaning. */ +}; #define EQUAL 0 /* result of memcmp for equal strings */ @@ -846,10 +774,10 @@ static void check_match(IPos start, IPos match, int length); */ static void lm_init(ush * flags) { - register unsigned j; + unsigned j; /* Initialize the hash table. */ - memzero((char *) head, HASH_SIZE * sizeof(*head)); + memset(head, 0, HASH_SIZE * sizeof(*head)); /* prev will be initialized on the fly */ *flags |= SLOW; @@ -896,9 +824,9 @@ static void lm_init(ush * flags) static int longest_match(IPos cur_match) { unsigned chain_length = max_chain_length; /* max hash chain length */ - register uch *scan = window + strstart; /* current string */ - register uch *match; /* matched string */ - register int len; /* length of current match */ + uch *scan = window + strstart; /* current string */ + uch *match; /* matched string */ + int len; /* length of current match */ int best_len = prev_length; /* best match length so far */ IPos limit = strstart > (IPos) MAX_DIST ? strstart - (IPos) MAX_DIST : NIL; @@ -912,9 +840,9 @@ static int longest_match(IPos cur_match) #if HASH_BITS < 8 || MAX_MATCH != 258 # error Code too clever #endif - register uch *strend = window + strstart + MAX_MATCH; - register uch scan_end1 = scan[best_len - 1]; - register uch scan_end = scan[best_len]; + uch *strend = window + strstart + MAX_MATCH; + uch scan_end1 = scan[best_len - 1]; + uch scan_end = scan[best_len]; /* Do not waste too much time if we already have a good match: */ if (prev_length >= good_match) { @@ -999,9 +927,9 @@ static void check_match(IPos start, IPos match, int length) * file reads are performed for at least two bytes (required for the * translate_eol option). */ -static void fill_window() +static void fill_window(void) { - register unsigned n, m; + unsigned n, m; unsigned more = (unsigned) (window_size - (ulg) lookahead - (ulg) strstart); /* Amount of free space at the end of the window. */ @@ -1056,20 +984,20 @@ static void fill_window() */ #define FLUSH_BLOCK(eof) \ flush_block(block_start >= 0L ? (char*)&window[(unsigned)block_start] : \ - (char*)NULL, (long)strstart - block_start, (eof)) + (char*)NULL, (long)strstart - block_start, (eof)) /* =========================================================================== * Same as above, but achieves better compression. We use a lazy * evaluation for matches: a match is finally adopted only if there is * no better match at the next window position. */ -static ulg deflate() +static ulg deflate(void) { IPos hash_head; /* head of hash chain */ IPos prev_match; /* previous match */ int flush; /* set if current block must be flushed */ int match_available = 0; /* set if previous match exists */ - register unsigned match_length = MIN_MATCH - 1; /* length of best match */ + unsigned match_length = MIN_MATCH - 1; /* length of best match */ /* Process the input block. */ while (lookahead != 0) { @@ -1191,68 +1119,57 @@ static ulg deflate() typedef struct dirent dir_type; -typedef RETSIGTYPE(*sig_type) (int); - /* ======================================================================== */ int gzip_main(int argc, char **argv) { + enum { + OPT_tostdout = 0x1, + OPT_force = 0x2, + }; + + unsigned long opt; int result; int inFileNum; int outFileNum; struct stat statBuf; char *delFileName; - int tostdout = 0; - int force = 0; - int opt; - - while ((opt = getopt(argc, argv, "cf123456789dq")) != -1) { - switch (opt) { - case 'c': - tostdout = 1; - break; - case 'f': - force = 1; - break; - /* Ignore 1-9 (compression level) options */ - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - break; - case 'q': - break; -#ifdef CONFIG_GUNZIP - case 'd': - optind = 1; - return gunzip_main(argc, argv); -#endif - default: - bb_show_usage(); - } + + opt = bb_getopt_ulflags(argc, argv, "cf123456789q" USE_GUNZIP("d")); + //if (opt & 0x1) // -c + //if (opt & 0x2) // -f + /* Ignore 1-9 (compression level) options */ + //if (opt & 0x4) // -1 + //if (opt & 0x8) // -2 + //if (opt & 0x10) // -3 + //if (opt & 0x20) // -4 + //if (opt & 0x40) // -5 + //if (opt & 0x80) // -6 + //if (opt & 0x100) // -7 + //if (opt & 0x200) // -8 + //if (opt & 0x400) // -9 + //if (opt & 0x800) // -q + if (ENABLE_GUNZIP && (opt & 0x1000)) { // -d + /* FIXME: bb_getopt_ulflags should not depend on optind */ + optind = 1; + return gunzip_main(argc, argv); } foreground = signal(SIGINT, SIG_IGN) != SIG_IGN; if (foreground) { - (void) signal(SIGINT, (sig_type) abort_gzip); + (void) signal(SIGINT, abort_gzip); } #ifdef SIGTERM if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { - (void) signal(SIGTERM, (sig_type) abort_gzip); + (void) signal(SIGTERM, abort_gzip); } #endif #ifdef SIGHUP if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { - (void) signal(SIGHUP, (sig_type) abort_gzip); + (void) signal(SIGHUP, abort_gzip); } #endif strncpy(z_suffix, Z_SUFFIX, sizeof(z_suffix) - 1); - z_len = strlen(z_suffix); /* Allocate all global buffers (for DYN_ALLOC option) */ ALLOC(uch, inbuf, INBUFSIZ + INBUF_EXTRA); @@ -1261,12 +1178,13 @@ int gzip_main(int argc, char **argv) ALLOC(uch, window, 2L * WSIZE); ALLOC(ush, tab_prefix, 1L << BITS); + /* Initialise the CRC32 table */ + crc_32_tab = crc32_filltable(0); + clear_bufs(); - part_nb = 0; if (optind == argc) { time_stamp = 0; - ifile_size = -1L; zip(STDIN_FILENO, STDOUT_FILENO); } else { int i; @@ -1274,25 +1192,22 @@ int gzip_main(int argc, char **argv) for (i = optind; i < argc; i++) { char *path = NULL; + clear_bufs(); if (strcmp(argv[i], "-") == 0) { time_stamp = 0; - ifile_size = -1L; inFileNum = STDIN_FILENO; outFileNum = STDOUT_FILENO; } else { - inFileNum = open(argv[i], O_RDONLY); - if (inFileNum < 0 || fstat(inFileNum, &statBuf) < 0) + inFileNum = xopen(argv[i], O_RDONLY); + if (fstat(inFileNum, &statBuf) < 0) bb_perror_msg_and_die("%s", argv[i]); time_stamp = statBuf.st_ctime; - ifile_size = statBuf.st_size; - if (!tostdout) { - path = xmalloc(strlen(argv[i]) + 4); - strcpy(path, argv[i]); - strcat(path, ".gz"); + if (!(opt & OPT_tostdout)) { + path = xasprintf("%s.gz", argv[i]); /* Open output file */ -#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) +#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) && defined O_NOFOLLOW outFileNum = open(path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW); #else @@ -1310,7 +1225,7 @@ int gzip_main(int argc, char **argv) outFileNum = STDOUT_FILENO; } - if (path == NULL && isatty(outFileNum) && force == 0) { + if (path == NULL && isatty(outFileNum) && !(opt & OPT_force)) { bb_error_msg ("compressed data not written to a terminal. Use -f to force compression."); free(path); @@ -1752,7 +1667,7 @@ static void ct_init(ush * attr, int *methodp) /* =========================================================================== * Initialize a new block. */ -static void init_block() +static void init_block(void) { int n; /* iterates over tree elements */ @@ -2165,7 +2080,7 @@ static void send_tree(ct_data * tree, int max_code) * Construct the Huffman tree for the bit lengths and return the index in * bl_order of the last bit length code to send. */ -static const int build_bl_tree() +static int build_bl_tree(void) { int max_blindex; /* index of last bit length code of non zero freq */ @@ -2428,7 +2343,7 @@ static void compress_block(ct_data * ltree, ct_data * dtree) * IN assertion: the fields freq of dyn_ltree are set and the total of all * frequencies does not exceed 64K (to fit in an int on 16 bit machines). */ -static void set_file_type() +static void set_file_type(void) { int n = 0; unsigned ascii_freq = 0; @@ -2453,7 +2368,7 @@ static void set_file_type() */ -static ulg crc; /* crc on uncompressed file data */ +static uint32_t crc; /* crc on uncompressed file data */ static long header_bytes; /* number of bytes in gzip header */ static void put_long(ulg n) @@ -2541,7 +2456,7 @@ static int file_read(char *buf, unsigned size) * Write the output buffer outbuf[0..outcnt-1] and update bytes_out. * (used for the compressed data only) */ -static void flush_outbuf() +static void flush_outbuf(void) { if (outcnt == 0) return;