a ton of gzip changes, split up in compiled and

run-tested pieces. Code was rather messy.
It's not a bug fix, more like code cleanup.

This is the first part.
This commit is contained in:
Denis Vlasenko 2007-01-07 19:37:42 +00:00
parent 88e2b1cb62
commit ad403413c7

View File

@ -25,45 +25,15 @@ aa: 85.1% -- replaced with aa.gz
#define SMALL_MEM #define SMALL_MEM
#include <stdlib.h> //#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <signal.h>
#include <utime.h>
#include <ctype.h>
#include <sys/types.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#include <time.h>
#include "busybox.h" #include "busybox.h"
typedef unsigned char uch;
typedef unsigned short ush;
typedef unsigned long ulg;
/* Return codes from gzip */
#define OK 0
#define ERROR 1
#define WARNING 2
/* Compression methods (see algorithm.doc) */ /* Compression methods (see algorithm.doc) */
/* Only STORED and DEFLATED are supported by this BusyBox module */ /* Only STORED and DEFLATED are supported by this BusyBox module */
#define STORED 0 #define STORED 0
/* methods 4 to 7 reserved */ /* methods 4 to 7 reserved */
#define DEFLATED 8 #define DEFLATED 8
/* To save memory for 16 bit systems, some arrays are overlaid between
* the various modules:
* deflate: prev+head window d_buf l_buf outbuf
* unlzw: tab_prefix tab_suffix stack inbuf outbuf
* For compression, input is done in window[]. For decompression, output
* is done in window except for unlzw.
*/
#ifndef INBUFSIZ #ifndef INBUFSIZ
# ifdef SMALL_MEM # ifdef SMALL_MEM
# define INBUFSIZ 0x2000 /* input buffer size */ # define INBUFSIZ 0x2000 /* input buffer size */
@ -71,6 +41,7 @@ typedef unsigned long ulg;
# define INBUFSIZ 0x8000 /* input buffer size */ # define INBUFSIZ 0x8000 /* input buffer size */
# endif # endif
#endif #endif
#define INBUF_EXTRA 64 /* required by unlzw() */ #define INBUF_EXTRA 64 /* required by unlzw() */
#ifndef OUTBUFSIZ #ifndef OUTBUFSIZ
@ -90,21 +61,8 @@ typedef unsigned long ulg;
# endif # endif
#endif #endif
# define DECLARE(type, array, size) static type * array
# define ALLOC(type, array, size) { \
array = xzalloc((size_t)(((size)+1L)/2) * 2*sizeof(type)); \
}
# define FREE(array) {free(array), array=NULL;}
#define tab_suffix window
#define tab_prefix prev /* hash link (see deflate.c) */
#define head (prev+WSIZE) /* hash head (see deflate.c) */
static long isize; /* number of input bytes */
#define NO_FILE (-1) /* in memory compression */ #define NO_FILE (-1) /* in memory compression */
#define PACK_MAGIC "\037\036" /* Magic header for packed files */ #define PACK_MAGIC "\037\036" /* Magic header for packed files */
#define GZIP_MAGIC "\037\213" /* Magic header for gzip files, 1F 8B */ #define GZIP_MAGIC "\037\213" /* Magic header for gzip files, 1F 8B */
#define OLD_GZIP_MAGIC "\037\236" /* Magic header for gzip 0.5 = freeze 1.x */ #define OLD_GZIP_MAGIC "\037\236" /* Magic header for gzip 0.5 = freeze 1.x */
@ -142,36 +100,65 @@ static long isize; /* number of input bytes */
* distances are limited to MAX_DIST instead of WSIZE. * distances are limited to MAX_DIST instead of WSIZE.
*/ */
/* put_byte is used for the compressed output */ #ifndef MAX_PATH_LEN
#define put_byte(c) {outbuf[outcnt++]=(uch)(c); if (outcnt==OUTBUFSIZ)\ # define MAX_PATH_LEN 1024 /* max pathname length */
flush_outbuf();} #endif
#define seekable() 0 /* force sequential output */ #define seekable() 0 /* force sequential output */
#define translate_eol 0 /* no option -a yet */ #define translate_eol 0 /* no option -a yet */
#ifndef BITS
# define BITS 16
#endif
#define INIT_BITS 9 /* Initial number of bits per code */
#define BIT_MASK 0x1f /* Mask for 'number of compression bits' */
/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free.
* It's a pity that old uncompress does not check bit 0x20. That makes
* extension of the format actually undesirable because old compress
* would just crash on the new format instead of giving a meaningful
* error message. It does check the number of bits, but it's more
* helpful to say "unsupported format, get a new version" than
* "can only handle 16 bits".
*/
#ifdef MAX_EXT_CHARS
# define MAX_SUFFIX MAX_EXT_CHARS
#else
# define MAX_SUFFIX 30
#endif
#define DECLARE(type, array, size)\
static type * array
#define ALLOC(type, array, size) { \
array = xzalloc((size_t)(((size)+1L)/2) * 2*sizeof(type)); \
}
#define FREE(array) { \
free(array); \
array = NULL; \
}
/* Diagnostic functions */ /* Diagnostic functions */
#ifdef DEBUG #ifdef DEBUG
# define Assert(cond,msg) {if(!(cond)) bb_error_msg(msg);} # define Assert(cond,msg) {if(!(cond)) bb_error_msg(msg);}
# define Trace(x) fprintf x # define Trace(x) fprintf x
# define Tracev(x) {if (verbose) fprintf x ;} # define Tracev(x) {if (verbose) fprintf x ;}
# define Tracevv(x) {if (verbose>1) fprintf x ;} # define Tracevv(x) {if (verbose>1) fprintf x ;}
# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} # define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} # define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
#else #else
# define Assert(cond,msg) # define Assert(cond,msg)
# define Trace(x) # define Trace(x)
# define Tracev(x) # define Tracev(x)
# define Tracevv(x) # define Tracevv(x)
# define Tracec(c,x) # define Tracec(c,x)
# define Tracecv(c,x) # define Tracecv(c,x)
#endif #endif
#define WARN(msg) {if (!quiet) fprintf msg ; \ typedef unsigned char uch;
if (exit_code == OK) exit_code = WARNING;} typedef unsigned short ush;
typedef unsigned long ulg;
#ifndef MAX_PATH_LEN
# define MAX_PATH_LEN 1024 /* max pathname length */
#endif
/* from zip.c: */ /* from zip.c: */
@ -195,66 +182,22 @@ static void bi_windup(void);
static void copy_block(char *buf, unsigned len, int header); static void copy_block(char *buf, unsigned len, int header);
static int (*read_buf) (char *buf, unsigned size); static int (*read_buf) (char *buf, unsigned size);
/* from util.c: */
static void flush_outbuf(void); static void flush_outbuf(void);
/* lzw.h -- define the lzw functions. /* global buffers */
* Copyright (C) 1992-1993 Jean-loup Gailly.
* This is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, see the file COPYING.
*/
#ifndef BITS /* To save memory for 16 bit systems, some arrays are overlaid between
# define BITS 16 * the various modules:
#endif * deflate: prev+head window d_buf l_buf outbuf
#define INIT_BITS 9 /* Initial number of bits per code */ * unlzw: tab_prefix tab_suffix stack inbuf outbuf
* For compression, input is done in window[]. For decompression, output
#define BIT_MASK 0x1f /* Mask for 'number of compression bits' */ * is done in window except for unlzw.
/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free.
* It's a pity that old uncompress does not check bit 0x20. That makes
* extension of the format actually undesirable because old compress
* would just crash on the new format instead of giving a meaningful
* error message. It does check the number of bits, but it's more
* helpful to say "unsupported format, get a new version" than
* "can only handle 16 bits".
*/
/* tailor.h -- target dependent definitions
* Copyright (C) 1992-1993 Jean-loup Gailly.
* This is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, see the file COPYING.
*/
/* The target dependent definitions should be defined here only.
* The target dependent functions should be defined in tailor.c.
*/ */
/* Common defaults */ #define tab_suffix window
#define tab_prefix prev /* hash link (see deflate.c) */
#ifndef OS_CODE #define head (prev+WSIZE) /* hash head (see deflate.c) */
# define OS_CODE 0x03 /* assume Unix */
#endif
#ifndef PATH_SEP
# define PATH_SEP '/'
#endif
#ifndef OPTIONS_VAR
# define OPTIONS_VAR "GZIP"
#endif
#ifndef Z_SUFFIX
# define Z_SUFFIX ".gz"
#endif
#ifdef MAX_EXT_CHARS
# define MAX_SUFFIX MAX_EXT_CHARS
#else
# define MAX_SUFFIX 30
#endif
/* global buffers */
DECLARE(uch, inbuf, INBUFSIZ + INBUF_EXTRA); DECLARE(uch, inbuf, INBUFSIZ + INBUF_EXTRA);
DECLARE(uch, outbuf, OUTBUFSIZ + OUTBUF_EXTRA); DECLARE(uch, outbuf, OUTBUFSIZ + OUTBUF_EXTRA);
@ -262,10 +205,12 @@ DECLARE(ush, d_buf, DIST_BUFSIZE);
DECLARE(uch, window, 2L * WSIZE); DECLARE(uch, window, 2L * WSIZE);
DECLARE(ush, tab_prefix, 1L << BITS); DECLARE(ush, tab_prefix, 1L << BITS);
static int foreground; /* set if program run in foreground */ static long isize; /* number of input bytes */
static int foreground; /* set if program run in foreground */
static int method = DEFLATED; /* compression method */ static int method = DEFLATED; /* compression method */
static int exit_code = OK; /* program exit code */ static int exit_code; /* program exit code */
static long time_stamp; /* original time stamp (modification time) */ static long time_stamp; /* original time stamp (modification time) */
static char z_suffix[MAX_SUFFIX + 1]; /* default suffix (can be set with --suffix) */ static char z_suffix[MAX_SUFFIX + 1]; /* default suffix (can be set with --suffix) */
static int ifd; /* input file descriptor */ static int ifd; /* input file descriptor */
@ -277,24 +222,67 @@ static unsigned outcnt; /* bytes in output buffer */
static uint32_t *crc_32_tab; static uint32_t *crc_32_tab;
/* ===========================================================================
* Local data used by the "bit string" routines.
*/
static int zfile; /* output gzip file */
static unsigned short bi_buf;
/* Output buffer. bits are inserted starting at the bottom (least significant
* bits).
*/
#undef BUF_SIZE
#define BUF_SIZE (8 * sizeof(bi_buf))
/* Number of bits used within bi_buf. (bi_buf might be implemented on
* more than 16 bits on some systems.)
*/
static int bi_valid;
/* Current input function. Set to mem_read for in-memory compression */
#ifdef DEBUG
static ulg bits_sent; /* bit length of the compressed data */
#endif
/* ===========================================================================
*/
/* put_8bit is used for the compressed output */
#define put_8bit(c) \
{ \
outbuf[outcnt++] = (c); \
if (outcnt == OUTBUFSIZ) flush_outbuf(); \
}
/* Output a 16 bit value, lsb first */ /* Output a 16 bit value, lsb first */
static void put_short(ush w) static void put_16bit(ush w)
{ {
if (outcnt < OUTBUFSIZ - 2) { if (outcnt < OUTBUFSIZ - 2) {
outbuf[outcnt++] = (uch) ((w) & 0xff); outbuf[outcnt++] = w;
outbuf[outcnt++] = (uch) ((ush) (w) >> 8); outbuf[outcnt++] = w >> 8;
} else { } else {
put_byte((uch) ((w) & 0xff)); put_8bit(w);
put_byte((uch) ((ush) (w) >> 8)); put_8bit(w >> 8);
} }
} }
/* ======================================================================== static void put_32bit(ulg n)
* Signal and error handler.
*/
static void abort_gzip(int ATTRIBUTE_UNUSED ignored)
{ {
exit(ERROR); put_16bit(n);
put_16bit(n >> 16);
}
/* put_header_byte is used for the compressed output
* - for the initial 4 bytes that can't overflow the buffer.
*/
#define put_header_byte(c) \
{ \
outbuf[outcnt++] = (c); \
} }
/* =========================================================================== /* ===========================================================================
@ -318,7 +306,8 @@ static void write_buf(int fd, void *buf, unsigned cnt)
unsigned n; unsigned n;
while ((n = write(fd, buf, cnt)) != cnt) { while ((n = write(fd, buf, cnt)) != cnt) {
if (n == (unsigned) (-1)) bb_error_msg_and_die(bb_msg_write_error); if (n == (unsigned) (-1))
bb_error_msg_and_die(bb_msg_write_error);
cnt -= n; cnt -= n;
buf = (void *) ((char *) buf + n); buf = (void *) ((char *) buf + n);
} }
@ -400,31 +389,6 @@ static uint32_t updcrc(uch * s, unsigned n)
* *
*/ */
/* ===========================================================================
* Local data used by the "bit string" routines.
*/
static int zfile; /* output gzip file */
static unsigned short bi_buf;
/* Output buffer. bits are inserted starting at the bottom (least significant
* bits).
*/
#define Buf_size (8 * 2*sizeof(char))
/* Number of bits used within bi_buf. (bi_buf might be implemented on
* more than 16 bits on some systems.)
*/
static int bi_valid;
/* Current input function. Set to mem_read for in-memory compression */
#ifdef DEBUG
ulg bits_sent; /* bit length of the compressed data */
#endif
/* =========================================================================== /* ===========================================================================
* Initialize the bit string routines. * Initialize the bit string routines.
*/ */
@ -460,11 +424,11 @@ static void send_bits(int value, int length)
* (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
* unused bits in value. * unused bits in value.
*/ */
if (bi_valid > (int) Buf_size - length) { if (bi_valid > (int) BUF_SIZE - length) {
bi_buf |= (value << bi_valid); bi_buf |= (value << bi_valid);
put_short(bi_buf); put_16bit(bi_buf);
bi_buf = (ush) value >> (Buf_size - bi_valid); bi_buf = (ush) value >> (BUF_SIZE - bi_valid);
bi_valid += length - Buf_size; bi_valid += length - BUF_SIZE;
} else { } else {
bi_buf |= value << bi_valid; bi_buf |= value << bi_valid;
bi_valid += length; bi_valid += length;
@ -493,9 +457,9 @@ static unsigned bi_reverse(unsigned code, int len)
static void bi_windup(void) static void bi_windup(void)
{ {
if (bi_valid > 8) { if (bi_valid > 8) {
put_short(bi_buf); put_16bit(bi_buf);
} else if (bi_valid > 0) { } else if (bi_valid > 0) {
put_byte(bi_buf); put_8bit(bi_buf);
} }
bi_buf = 0; bi_buf = 0;
bi_valid = 0; bi_valid = 0;
@ -513,8 +477,8 @@ static void copy_block(char *buf, unsigned len, int header)
bi_windup(); /* align on byte boundary */ bi_windup(); /* align on byte boundary */
if (header) { if (header) {
put_short((ush) len); put_16bit((ush) len);
put_short((ush) ~ len); put_16bit((ush) ~ len);
#ifdef DEBUG #ifdef DEBUG
bits_sent += 2 * 16; bits_sent += 2 * 16;
#endif #endif
@ -523,7 +487,7 @@ static void copy_block(char *buf, unsigned len, int header)
bits_sent += (ulg) len << 3; bits_sent += (ulg) len << 3;
#endif #endif
while (len--) { while (len--) {
put_byte(*buf++); put_8bit(*buf++);
} }
} }
@ -1039,8 +1003,7 @@ static ulg deflate(void)
check_match(strstart - 1, prev_match, prev_length); check_match(strstart - 1, prev_match, prev_length);
flush = flush = ct_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH);
ct_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH);
/* Insert in hash table all strings up to the end of the match. /* Insert in hash table all strings up to the end of the match.
* strstart-1 and strstart are already inserted. * strstart-1 and strstart are already inserted.
@ -1122,6 +1085,11 @@ static ulg deflate(void)
typedef struct dirent dir_type; typedef struct dirent dir_type;
/* ======================================================================== */ /* ======================================================================== */
static void abort_gzip(int ATTRIBUTE_UNUSED ignored)
{
exit(1);
}
int gzip_main(int argc, char **argv) int gzip_main(int argc, char **argv)
{ {
enum { enum {
@ -1174,7 +1142,7 @@ int gzip_main(int argc, char **argv)
} }
#endif #endif
strncpy(z_suffix, Z_SUFFIX, sizeof(z_suffix) - 1); strncpy(z_suffix, ".gz", sizeof(z_suffix) - 1);
/* Allocate all global buffers (for DYN_ALLOC option) */ /* Allocate all global buffers (for DYN_ALLOC option) */
ALLOC(uch, inbuf, INBUFSIZ + INBUF_EXTRA); ALLOC(uch, inbuf, INBUFSIZ + INBUF_EXTRA);
@ -1244,7 +1212,7 @@ int gzip_main(int argc, char **argv)
close(outFileNum); close(outFileNum);
/* Delete the original file */ /* Delete the original file */
if (result == OK) if (result == 0)
delFileName = argv[i]; delFileName = argv[i];
else else
delFileName = path; delFileName = path;
@ -2375,17 +2343,6 @@ static void set_file_type(void)
static uint32_t crc; /* crc on uncompressed file data */ static uint32_t crc; /* crc on uncompressed file data */
static void put_long(ulg n)
{
put_short((n) & 0xffff);
put_short(((ulg) (n)) >> 16);
}
/* put_header_byte is used for the compressed output
* - for the initial 4 bytes that can't overflow the buffer.
*/
#define put_header_byte(c) {outbuf[outcnt++]=(uch)(c);}
/* =========================================================================== /* ===========================================================================
* Deflate in to out. * Deflate in to out.
* IN assertions: the input and output buffers are cleared. * IN assertions: the input and output buffers are cleared.
@ -2409,7 +2366,7 @@ static int zip(int in, int out)
put_header_byte(DEFLATED); /* compression method */ put_header_byte(DEFLATED); /* compression method */
put_header_byte(my_flags); /* general flags */ put_header_byte(my_flags); /* general flags */
put_long(time_stamp); put_32bit(time_stamp);
/* Write deflated file to zip file */ /* Write deflated file to zip file */
crc = updcrc(0, 0); crc = updcrc(0, 0);
@ -2418,17 +2375,17 @@ static int zip(int in, int out)
ct_init(&attr, &method); ct_init(&attr, &method);
lm_init(&deflate_flags); lm_init(&deflate_flags);
put_byte((uch) deflate_flags); /* extra flags */ put_8bit((uch) deflate_flags); /* extra flags */
put_byte(OS_CODE); /* OS identifier */ put_8bit(3); /* OS identifier = 3 (Unix) */
(void) deflate(); (void) deflate();
/* Write the crc and uncompressed size */ /* Write the crc and uncompressed size */
put_long(crc); put_32bit(crc);
put_long(isize); put_32bit(isize);
flush_outbuf(); flush_outbuf();
return OK; return 0;
} }