* only standard in to standard out with -9 compression. It also requires
* the zcat module for some important functions."
*
- * Adjusted further by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
- * to support files as well as stdin/stdout, and to generally behave itself wrt
+ * Adjusted further by Erik Andersen <andersen@codepoet.org> 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 <stdlib.h>
#include <stdio.h>
#include <time.h>
#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;
#define STORED 0
/* methods 4 to 7 reserved */
#define DEFLATED 8
-static int method; /* compression method */
/* To save memory for 16 bit systems, some arrays are overlaid between
* the various modules:
# 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) {if (array != NULL) free(array), array=NULL;}
-#else
-# define DECLARE(type, array, size) static type array[size]
-# define ALLOC(type, array, size)
-# define FREE(array)
-#endif
+# define FREE(array) {free(array), array=NULL;}
#define tab_suffix window
#define tab_prefix prev /* hash link (see deflate.c) */
/* Diagnostic functions */
#ifdef DEBUG
-# define Assert(cond,msg) {if(!(cond)) error_msg(msg);}
+# define Assert(cond,msg) {if(!(cond)) bb_error_msg(msg);}
# define Trace(x) fprintf x
# define Tracev(x) {if (verbose) fprintf x ;}
# define Tracevv(x) {if (verbose>1) fprintf x ;}
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);
* 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
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 unsigned insize; /* valid bytes in inbuf */
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)
/* ========================================================================
* Signal and error handler.
*/
-static void abort_gzip()
+static void abort_gzip(int ATTRIBUTE_UNUSED ignored)
{
exit(ERROR);
}
bytes_in = 0L;
}
-static void write_error_msg(void)
-{
- fprintf(stderr, "\n");
- perror("");
- abort_gzip();
-}
-
/* ===========================================================================
* Does the same as write(), but also handles partial pipe writes and checks
* for error return.
unsigned n;
while ((n = write(fd, buf, cnt)) != cnt) {
- if (n == (unsigned) (-1)) {
- write_error_msg();
- }
+ if (n == (unsigned) (-1)) bb_error_msg_and_die(bb_msg_write_error);
cnt -= n;
buf = (void *) ((char *) buf + n);
}
* 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)
} while (--n);
}
crc = c;
- return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */
+ return ~c;
}
/* bits.c -- output variable-length bit strings
/* ===========================================================================
* 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);
* 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.
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 */
* 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 */
register 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;
/* check that the match is indeed a match */
if (memcmp((char *) window + match,
(char *) window + start, length) != EQUAL) {
- fprintf(stderr,
- " start %d, match %d, length %d\n", start, match, length);
- error_msg("invalid match");
+ bb_error_msg(" start %d, match %d, length %d", start, match, length);
+ bb_error_msg("invalid match");
}
if (verbose > 1) {
- fprintf(stderr, "\\[%d,%d]", start - match, length);
+ bb_error_msg("\\[%d,%d]", start - match, length);
do {
putc(window[start++], stderr);
} while (--length != 0);
* 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 more =
*/
#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 */
typedef struct dirent dir_type;
-typedef RETSIGTYPE(*sig_type) (int);
-
/* ======================================================================== */
int gzip_main(int argc, char **argv)
{
return gunzip_main(argc, argv);
#endif
default:
- show_usage();
+ bb_show_usage();
}
}
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
ALLOC(uch, window, 2L * WSIZE);
ALLOC(ush, tab_prefix, 1L << BITS);
+ /* Initialise the CRC32 table */
+ crc_32_tab = bb_crc32_filltable(0);
+
clear_bufs();
part_nb = 0;
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)
- perror_msg_and_die("%s", argv[i]);
+ inFileNum = bb_xopen3(argv[i], O_RDONLY, 0);
+ if (fstat(inFileNum, &statBuf) < 0)
+ bb_perror_msg_and_die("%s", argv[i]);
time_stamp = statBuf.st_ctime;
ifile_size = statBuf.st_size;
strcat(path, ".gz");
/* 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
outFileNum = open(path, O_RDWR | O_CREAT | O_EXCL);
#endif
if (outFileNum < 0) {
- perror_msg("%s", path);
+ bb_perror_msg("%s", path);
free(path);
continue;
}
}
if (path == NULL && isatty(outFileNum) && force == 0) {
- error_msg
+ bb_error_msg
("compressed data not written to a terminal. Use -f to force compression.");
free(path);
continue;
delFileName = path;
if (unlink(delFileName) < 0)
- perror_msg("%s", delFileName);
+ bb_perror_msg("%s", delFileName);
}
free(path);
#else /* DEBUG */
# define send_code(c, tree) \
- { if (verbose>1) fprintf(stderr,"\ncd %3d ",(c)); \
+ { if (verbose>1) bb_error_msg("\ncd %3d ",(c)); \
send_bits(tree[c].Code, tree[c].Len); }
#endif
/* ===========================================================================
* Initialize a new block.
*/
-static void init_block()
+static void init_block(void)
{
int n; /* iterates over tree elements */
tree[n].Dad = tree[m].Dad = (ush) node;
#ifdef DUMP_BL_TREE
if (tree == bl_tree) {
- fprintf(stderr, "\nnode %d(%d), sons %d(%d) %d(%d)",
+ bb_error_msg("\nnode %d(%d), sons %d(%d) %d(%d)",
node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
}
#endif
* 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 */
if (stored_len <= opt_lenb && eof && compressed_len == 0L && seekable()) {
/* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */
if (buf == (char *) 0)
- error_msg("block vanished");
+ bb_error_msg("block vanished");
copy_block(buf, (unsigned) stored_len, 0); /* without header */
compressed_len = stored_len << 3;
* 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;
bin_freq += dyn_ltree[n++].Freq;
*file_type = bin_freq > (ascii_freq >> 2) ? BINARY : ASCII;
if (*file_type == BINARY && translate_eol) {
- error_msg("-l used on binary file");
+ bb_error_msg("-l used on binary file");
}
}
*/
-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)
* 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;