?? gzip.c
字號:
/* vi: set sw=4 ts=4: *//* * Gzip implementation for busybox * * Based on GNU gzip Copyright (C) 1992-1993 Jean-loup Gailly. * * Originally adjusted for busybox by Charles P. Wright <cpw@unix.asb.com> * "this is a stripped down version of gzip I put into busybox, it does * only standard in to standard out with -9 compression. It also requires * the zcat module for some important functions." * * Adjusted further by Erik Andersen <andersee@debian.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 * *//* 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 <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"#define memzero(s, n) memset ((void *)(s), 0, (n))#ifndef RETSIGTYPE# define RETSIGTYPE void#endiftypedef 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) *//* Only STORED and DEFLATED are supported by this BusyBox module */#define STORED 0/* methods 4 to 7 reserved */#define DEFLATED 8static int method; /* compression method *//* 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# ifdef SMALL_MEM# define INBUFSIZ 0x2000 /* input buffer size */# else# define INBUFSIZ 0x8000 /* input buffer size */# endif#endif#define INBUF_EXTRA 64 /* required by unlzw() */#ifndef OUTBUFSIZ# ifdef SMALL_MEM# define OUTBUFSIZ 8192 /* output buffer size */# else# define OUTBUFSIZ 16384 /* output buffer size */# endif#endif#define OUTBUF_EXTRA 2048 /* required by unlzw() */#ifndef DIST_BUFSIZE# ifdef SMALL_MEM# define DIST_BUFSIZE 0x2000 /* buffer for distances, see trees.c */# else# define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */# endif#endif#ifdef DYN_ALLOC# define DECLARE(type, array, size) static type * array# define ALLOC(type, array, size) { \ array = (type*)calloc((size_t)(((size)+1L)/2), 2*sizeof(type)); \ if (array == NULL) error_msg(memory_exhausted); \ }# 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 tab_suffix window#define tab_prefix prev /* hash link (see deflate.c) */#define head (prev+WSIZE) /* hash head (see deflate.c) */static long bytes_in; /* number of input bytes */#define isize bytes_in/* for compatibility with old zip sources (to be cleaned) */typedef int file_t; /* Do not use stdio */#define NO_FILE (-1) /* in memory compression */#define PACK_MAGIC "\037\036" /* Magic header for packed files */#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 LZH_MAGIC "\037\240" /* Magic header for SCO LZH Compress files */#define PKZIP_MAGIC "\120\113\003\004" /* Magic header for pkzip files *//* gzip flag byte */#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */#define ORIG_NAME 0x08 /* bit 3 set: original file name present */#define COMMENT 0x10 /* bit 4 set: file comment present */#define RESERVED 0xC0 /* bit 6,7: reserved *//* internal file attribute */#define UNKNOWN 0xffff#define BINARY 0#define ASCII 1#ifndef WSIZE# define WSIZE 0x8000 /* window size--must be a power of two, and */#endif /* at least 32K for zip's deflate method */#define MIN_MATCH 3#define MAX_MATCH 258/* The minimum and maximum match lengths */#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)/* Minimum amount of lookahead, except at the end of the input file. * See deflate.c for comments about the MIN_MATCH+1. */#define MAX_DIST (WSIZE-MIN_LOOKAHEAD)/* In order to simplify the code, particularly on 16 bit machines, match * distances are limited to MAX_DIST instead of WSIZE. *//* put_byte is used for the compressed output */#define put_byte(c) {outbuf[outcnt++]=(uch)(c); if (outcnt==OUTBUFSIZ)\ flush_outbuf();}/* Output a 16 bit value, lsb first */#define put_short(w) \{ if (outcnt < OUTBUFSIZ-2) { \ outbuf[outcnt++] = (uch) ((w) & 0xff); \ outbuf[outcnt++] = (uch) ((ush)(w) >> 8); \ } else { \ put_byte((uch)((w) & 0xff)); \ put_byte((uch)((ush)(w) >> 8)); \ } \}/* Output a 32 bit value to the bit stream, lsb first */#define put_long(n) { \ put_short((n) & 0xffff); \ put_short(((ulg)(n)) >> 16); \}#define seekable() 0 /* force sequential output */#define translate_eol 0 /* no option -a yet *//* Diagnostic functions */#ifdef DEBUG# define Assert(cond,msg) {if(!(cond)) error_msg(msg);}# define Trace(x) fprintf x# define Tracev(x) {if (verbose) fprintf x ;}# define Tracevv(x) {if (verbose>1) fprintf x ;}# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}#else# define Assert(cond,msg)# define Trace(x)# define Tracev(x)# define Tracevv(x)# define Tracec(c,x)# define Tracecv(c,x)#endif#define WARN(msg) {if (!quiet) fprintf msg ; \ if (exit_code == OK) exit_code = WARNING;}#ifndef MAX_PATH_LEN# define MAX_PATH_LEN 1024 /* max pathname length */#endif /* from zip.c: */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); /* from trees.c */static void ct_init (ush * attr, int *methodp);static int ct_tally (int dist, int lc);static ulg flush_block (char *buf, ulg stored_len, int eof); /* from bits.c */static void bi_init (file_t zipfile);static void send_bits (int value, int length);static unsigned bi_reverse (unsigned value, int length);static void bi_windup (void);static void copy_block (char *buf, unsigned len, int header);static int (*read_buf) (char *buf, unsigned size); /* from util.c: */static void flush_outbuf (void);/* lzw.h -- define the lzw functions. * 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. */#if !defined(OF) && defined(lint)# include "gzip.h"#endif#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". *//* 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 */#ifndef OS_CODE# 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, outbuf, OUTBUFSIZ + OUTBUF_EXTRA);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 char ifname[MAX_PATH_LEN]; /* input file name */static char ofname[MAX_PATH_LEN]; /* output file name */static int ifd; /* input file descriptor */static int ofd; /* output file descriptor */static unsigned insize; /* valid bytes in inbuf */static unsigned outcnt; /* bytes in output buffer *//* ======================================================================== * Signal and error handler. */static void abort_gzip(){ exit(ERROR);}/* =========================================================================== * Clear input and output buffers */static void clear_bufs(void){ outcnt = 0; insize = 0; bytes_in = 0L;}static void write_error_msg(){ fprintf(stderr, "\n"); perror(""); abort_gzip();}/* =========================================================================== * Does the same as write(), but also handles partial pipe writes and checks * for error return. */static void write_buf(int fd, void *buf, unsigned cnt){ unsigned n; while ((n = write(fd, buf, cnt)) != cnt) { if (n == (unsigned) (-1)) { write_error_msg(); } cnt -= n; buf = (void *) ((char *) buf + n); }}/* =========================================================================== * Run a set of bytes through the crc shift register. If s is a NULL * pointer, then initialize the crc shift register contents instead. * Return the current crc in either case. */static ulg 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 */ unsigned long e=0; /* polynomial exclusive-or pattern */ int i; /* counter for all possible eight bit values */ int k; /* byte being shifted into crc apparatus */ /* terms of polynomial defining this crc (except x^32): */ static const int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; /* Make exclusive-or pattern from polynomial (0xedb88320) */ for (i = 0; i < sizeof(p)/sizeof(int); i++) e |= 1L << (31 - p[i]); /* Compute and print table of CRC's, five per line */ 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; }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -