diff options
-rw-r--r-- | archival/gzip.c | 346 |
1 files changed, 168 insertions, 178 deletions
diff --git a/archival/gzip.c b/archival/gzip.c index 7683695..2c8f69d 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -311,11 +311,6 @@ static void check_match(IPos start, IPos match, int length); #endif - -/* from zip.c: */ -static int zip(int in, int out); -static unsigned file_read(void *buf, unsigned size); - /* from deflate.c */ static void lm_init(ush * flags); static ulg deflate(void); @@ -605,22 +600,8 @@ static void copy_block(char *buf, unsigned len, int header) * input characters, so that a running hash key can be computed from the * previous key instead of complete recalculation each time. */ -#define UPDATE_HASH(h,c) (h = (((h)<<H_SHIFT) ^ (c)) & HASH_MASK) +#define UPDATE_HASH(h, c) (h = (((h)<<H_SHIFT) ^ (c)) & HASH_MASK) -/* =========================================================================== - * Insert string s in the dictionary and set match_head to the previous head - * of the hash chain (the most recent string with same hash key). Return - * the previous length of the hash chain. - * IN assertion: all calls to to INSERT_STRING are made with consecutive - * input characters and the first MIN_MATCH bytes of s are valid - * (except for the last MIN_MATCH-1 bytes of the input file). - */ -#define INSERT_STRING(s, match_head) \ -{ \ - UPDATE_HASH(ins_h, window[(s) + MIN_MATCH-1]); \ - prev[(s) & WMASK] = match_head = head[ins_h]; \ - head[ins_h] = (s); \ -} /* =========================================================================== * Initialize the "longest match" routines for a new file @@ -834,9 +815,17 @@ static void fill_window(void) /* =========================================================================== - * Flush the current block, with given end-of-file flag. - * IN assertion: strstart is set to the end of the current match. + * 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. + * + * Processes a new input file and return its compressed length. Sets + * the compressed length, crc, deflate flags and internal file + * attributes. */ + +/* Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. */ #define FLUSH_BLOCK(eof) \ flush_block( \ block_start >= 0L \ @@ -846,16 +835,19 @@ static void fill_window(void) (eof) \ ) +/* Insert string s in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of s are valid + * (except for the last MIN_MATCH-1 bytes of the input file). */ +#define INSERT_STRING(s, match_head) \ +{ \ + UPDATE_HASH(ins_h, window[(s) + MIN_MATCH-1]); \ + prev[(s) & WMASK] = match_head = head[ins_h]; \ + head[ins_h] = (s); \ +} -/* =========================================================================== - * 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. - * - * Processes a new input file and return its compressed length. Sets - * the compressed length, crc, deflate flags and internal file - * attributes. - */ static ulg deflate(void) { IPos hash_head; /* head of hash chain */ @@ -959,152 +951,6 @@ static ulg deflate(void) return FLUSH_BLOCK(1); /* eof */ } - - -/* ======================================================================== */ -static void abort_gzip(int ATTRIBUTE_UNUSED ignored) -{ - exit(1); -} - -int gzip_main(int argc, char **argv) -{ - enum { - OPT_tostdout = 0x1, - OPT_force = 0x2, - }; - - unsigned opt; - int result; - int inFileNum; - int outFileNum; - struct stat statBuf; - char *delFileName; - - opt = getopt32(argc, argv, "cf123456789qv" 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 (opt & 0x1000) // -v -#if ENABLE_GUNZIP /* gunzip_main may not be visible... */ - if (opt & 0x2000) { // -d - /* FIXME: getopt32 should not depend on optind */ - optind = 1; - return gunzip_main(argc, argv); - } -#endif - - foreground = signal(SIGINT, SIG_IGN) != SIG_IGN; - if (foreground) { - (void) signal(SIGINT, abort_gzip); - } -#ifdef SIGTERM - if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { - (void) signal(SIGTERM, abort_gzip); - } -#endif -#ifdef SIGHUP - if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { - (void) signal(SIGHUP, abort_gzip); - } -#endif - - strncpy(z_suffix, ".gz", sizeof(z_suffix) - 1); - - /* Allocate all global buffers (for DYN_ALLOC option) */ - ALLOC(uch, inbuf, INBUFSIZ + INBUF_EXTRA); - ALLOC(uch, outbuf, OUTBUFSIZ + OUTBUF_EXTRA); - ALLOC(ush, d_buf, DIST_BUFSIZE); - ALLOC(uch, window, 2L * WSIZE); - ALLOC(ush, tab_prefix, 1L << BITS); - - /* Initialise the CRC32 table */ - crc_32_tab = crc32_filltable(0); - - clear_bufs(); - - if (optind == argc) { - time_stamp = 0; - zip(STDIN_FILENO, STDOUT_FILENO); - } else { - int i; - - for (i = optind; i < argc; i++) { - char *path = NULL; - - clear_bufs(); - if (LONE_DASH(argv[i])) { - time_stamp = 0; - inFileNum = STDIN_FILENO; - outFileNum = STDOUT_FILENO; - } else { - inFileNum = xopen(argv[i], O_RDONLY); - if (fstat(inFileNum, &statBuf) < 0) - bb_perror_msg_and_die("%s", argv[i]); - time_stamp = statBuf.st_ctime; - - if (!(opt & OPT_tostdout)) { - path = xasprintf("%s.gz", argv[i]); - - /* Open output file */ -#if defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1 && defined(O_NOFOLLOW) - outFileNum = - open(path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW); -#else - outFileNum = open(path, O_RDWR | O_CREAT | O_EXCL); -#endif - if (outFileNum < 0) { - bb_perror_msg("%s", path); - free(path); - continue; - } - - /* Set permissions on the file */ - fchmod(outFileNum, statBuf.st_mode); - } else - outFileNum = STDOUT_FILENO; - } - - 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); - continue; - } - - result = zip(inFileNum, outFileNum); - - if (path != NULL) { - close(inFileNum); - close(outFileNum); - - /* Delete the original file */ - if (result == 0) - delFileName = argv[i]; - else - delFileName = path; - - if (unlink(delFileName) < 0) - bb_perror_msg("%s", delFileName); - } - - free(path); - } - } - - return exit_code; -} - /* trees.c -- output deflated data using Huffman coding * Copyright (C) 1992-1993 Jean-loup Gailly * This is free software; you can redistribute it and/or modify it under the @@ -2109,7 +1955,7 @@ static ulg flush_block(char *buf, ulg stored_len, int eof) */ static int ct_tally(int dist, int lc) { - l_buf[last_lit++] = (uch) lc; + l_buf[last_lit++] = lc; if (dist == 0) { /* lc is the unmatched char */ dyn_ltree[lc].Freq++; @@ -2278,3 +2124,147 @@ static int zip(int in, int out) flush_outbuf(); return 0; } + + +/* ======================================================================== */ +static void abort_gzip(int ATTRIBUTE_UNUSED ignored) +{ + exit(1); +} + +int gzip_main(int argc, char **argv) +{ + enum { + OPT_tostdout = 0x1, + OPT_force = 0x2, + }; + + unsigned opt; + int result; + int inFileNum; + int outFileNum; + int i; + struct stat statBuf; + char *delFileName; + + opt = getopt32(argc, argv, "cf123456789qv" 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 (opt & 0x1000) // -v +#if ENABLE_GUNZIP /* gunzip_main may not be visible... */ + if (opt & 0x2000) { // -d + /* FIXME: getopt32 should not depend on optind */ + optind = 1; + return gunzip_main(argc, argv); + } +#endif + + foreground = signal(SIGINT, SIG_IGN) != SIG_IGN; + if (foreground) { + signal(SIGINT, abort_gzip); + } +#ifdef SIGTERM + if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { + signal(SIGTERM, abort_gzip); + } +#endif +#ifdef SIGHUP + if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { + signal(SIGHUP, abort_gzip); + } +#endif + + strncpy(z_suffix, ".gz", sizeof(z_suffix) - 1); + + /* Allocate all global buffers (for DYN_ALLOC option) */ + ALLOC(uch, inbuf, INBUFSIZ + INBUF_EXTRA); + ALLOC(uch, outbuf, OUTBUFSIZ + OUTBUF_EXTRA); + ALLOC(ush, d_buf, DIST_BUFSIZE); + ALLOC(uch, window, 2L * WSIZE); + ALLOC(ush, tab_prefix, 1L << BITS); + + /* Initialise the CRC32 table */ + crc_32_tab = crc32_filltable(0); + + clear_bufs(); + + if (optind == argc) { + time_stamp = 0; + zip(STDIN_FILENO, STDOUT_FILENO); + return exit_code; + } + + for (i = optind; i < argc; i++) { + char *path = NULL; + + clear_bufs(); + if (LONE_DASH(argv[i])) { + time_stamp = 0; + inFileNum = STDIN_FILENO; + outFileNum = STDOUT_FILENO; + } else { + inFileNum = xopen(argv[i], O_RDONLY); + if (fstat(inFileNum, &statBuf) < 0) + bb_perror_msg_and_die("%s", argv[i]); + time_stamp = statBuf.st_ctime; + + if (!(opt & OPT_tostdout)) { + path = xasprintf("%s.gz", argv[i]); + + /* Open output file */ +#if defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1 && defined(O_NOFOLLOW) + outFileNum = open(path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW); +#else + outFileNum = open(path, O_RDWR | O_CREAT | O_EXCL); +#endif + if (outFileNum < 0) { + bb_perror_msg("%s", path); + free(path); + continue; + } + + /* Set permissions on the file */ + fchmod(outFileNum, statBuf.st_mode); + } else + outFileNum = STDOUT_FILENO; + } + + 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); + continue; + } + + result = zip(inFileNum, outFileNum); + + if (path != NULL) { + close(inFileNum); + close(outFileNum); + + /* Delete the original file */ + if (result == 0) + delFileName = argv[i]; + else + delFileName = path; + + if (unlink(delFileName) < 0) + bb_perror_msg("%s", delFileName); + } + + free(path); + } + + return exit_code; +} |