Latest and greatest
[oweals/busybox.git] / gzip.c
diff --git a/gzip.c b/gzip.c
index 6fd2e3971c6a594a4f9b603ac2ec70bfa2324241..983f673e15eb7c847b69590de845c3f95d8d95fd 100644 (file)
--- a/gzip.c
+++ b/gzip.c
@@ -7,11 +7,17 @@
 #include "internal.h"
 #ifdef BB_GZIP
 
-#ifndef BB_ZCAT
-error: you need zcat to have gzip support!
-#endif
+//#ifndef BB_ZCAT
+//#error you need zcat to have gzip support!
+//#endif
+
+static const char gzip_usage[] =
+    "gzip [OPTION]... FILE\n\n"
+    "Compress FILE with maximum compression.\n"
+    "When FILE is -, reads standard input.  Implies -c.\n\n"
+    "Options:\n"
+    "\t-c\tWrite output to standard output instead of FILE.gz\n";
 
-const char gzip_usage[] = "gzip\nignores all command line arguments\ncompress stdin to stdout with -9 compression\n";
 
 /* gzip.h -- common declarations for all gzip modules
  * Copyright (C) 1992-1993 Jean-loup Gailly.
@@ -210,7 +216,6 @@ extern int exit_code;      /* program exit code */
 extern int verbose;        /* be verbose (-v) */
 extern int quiet;          /* be quiet (-q) */
 extern int test;           /* check .z file integrity */
-extern int to_stdout;      /* output to stdout (-c) */
 extern int save_orig_name; /* set if original name must be saved */
 
 #define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf(0))
@@ -272,7 +277,7 @@ extern int save_orig_name; /* set if original name must be saved */
 #define WARN(msg) {if (!quiet) fprintf msg ; \
                   if (exit_code == OK) exit_code = WARNING;}
 
-local void do_exit(int exitcode);
+local void do_exit(int exitcode) __attribute__ ((noreturn));
 
        /* in zip.c: */
 extern int zip        OF((int in, int out));
@@ -380,7 +385,6 @@ extern int block_mode;   /* block compress mode -C compatible with 2.0 */
 #  undef LZW
 #endif
 
-/* $Id: gzip.c,v 1.1 1999/10/05 16:24:56 andersen Exp $ */
 /* 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
@@ -391,7 +395,6 @@ extern int block_mode;   /* block compress mode -C compatible with 2.0 */
  * The target dependent functions should be defined in tailor.c.
  */
 
-/* $Id: gzip.c,v 1.1 1999/10/05 16:24:56 andersen Exp $ */
 
 #if defined(__MSDOS__) && !defined(MSDOS)
 #  define MSDOS
@@ -766,10 +769,6 @@ extern int block_mode;   /* block compress mode -C compatible with 2.0 */
 #  include <stdio.h>
 #endif
 
-#ifdef RCSID
-static char rcsid[] = "$Id: gzip.c,v 1.1 1999/10/05 16:24:56 andersen Exp $";
-#endif
-
 /* ===========================================================================
  * Local data used by the "bit string" routines.
  */
@@ -975,10 +974,6 @@ void copy_block(buf, len, header)
 
 #include <stdio.h>
 
-#ifdef RCSID
-static char rcsid[] = "$Id: gzip.c,v 1.1 1999/10/05 16:24:56 andersen Exp $";
-#endif
-
 /* ===========================================================================
  * Configuration parameters
  */
@@ -1591,10 +1586,6 @@ ulg deflate()
  * For the meaning of all compilation flags, see comments in Makefile.in.
  */
 
-#ifdef RCSID
-static char rcsid[] = "$Id: gzip.c,v 1.1 1999/10/05 16:24:56 andersen Exp $";
-#endif
-
 #include <ctype.h>
 #include <sys/types.h>
 #include <signal.h>
@@ -1740,7 +1731,6 @@ DECLARE(uch, window, 2L*WSIZE);
                /* local variables */
 
 int ascii = 0;        /* convert end-of-lines to local OS conventions */
-int to_stdout = 0;    /* output to stdout (-c) */
 int decompress = 0;   /* decompress (-d) */
 int no_name = -1;     /* don't save or restore the original file name */
 int no_time = -1;     /* don't save or restore the original file time */
@@ -1772,17 +1762,42 @@ unsigned outcnt;           /* bytes in output buffer */
 
 /* local functions */
 
-local void treat_stdin  OF((void));
-static int (*work) OF((int infile, int outfile)) = zip; /* function to call */
-
 #define strequ(s1, s2) (strcmp((s1),(s2)) == 0)
 
 /* ======================================================================== */
 // int main (argc, argv)
 //    int argc;
 //    char **argv;
-int gzip_main(struct FileInfo * i, int argc, char * * argv)
+int gzip_main(int argc, char ** argv)
 {
+    int result;
+    int inFileNum;
+    int outFileNum;
+    struct stat statBuf;
+    char* delFileName; 
+    int tostdout = 0;
+    int fromstdin = 0;
+
+    if (argc==1)
+       usage(gzip_usage);
+
+    /* Parse any options */
+    while (--argc > 0 && **(++argv) == '-') {
+       if (*((*argv)+1) == '\0') {
+           fromstdin = 1;
+           tostdout = 1;
+       }
+       while (*(++(*argv))) {
+           switch (**argv) {
+           case 'c':
+               tostdout = 1;
+               break;
+           default:
+               usage(gzip_usage);
+           }
+       }
+    }
+
     foreground = signal(SIGINT, SIG_IGN) != SIG_IGN;
     if (foreground) {
        (void) signal (SIGINT, (sig_type)abort_gzip);
@@ -1801,8 +1816,6 @@ int gzip_main(struct FileInfo * i, int argc, char * * argv)
     strncpy(z_suffix, Z_SUFFIX, sizeof(z_suffix)-1);
     z_len = strlen(z_suffix);
 
-    to_stdout = 1;
-
     /* Allocate all global buffers (for DYN_ALLOC option) */
     ALLOC(uch, inbuf,  INBUFSIZ +INBUF_EXTRA);
     ALLOC(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
@@ -1815,33 +1828,84 @@ int gzip_main(struct FileInfo * i, int argc, char * * argv)
     ALLOC(ush, tab_prefix1, 1L<<(BITS-1));
 #endif
 
-    /* And get to work */
-       treat_stdin();
-    do_exit(exit_code);
-    return exit_code; /* just to avoid lint warning */
-}
+    if (fromstdin==1) {
+       strcpy(ofname, "stdin");
 
-/* ========================================================================
- * Compress or decompress stdin
- */
-local void treat_stdin()
-{
+       inFileNum=fileno(stdin);
+       time_stamp = 0; /* time unknown by default */
+       ifile_size = -1L; /* convention for unknown size */
+    } else {
+       /* Open up the input file */
+       if (*argv=='\0')
+           usage(gzip_usage);
+       strncpy(ifname, *argv, MAX_PATH_LEN);
+
+       /* Open input fille */
+       inFileNum=open( ifname, O_RDONLY);
+       if (inFileNum < 0) {
+           perror(ifname);
+           do_exit(WARNING);
+       }
+       /* Get the time stamp on the input file. */
+       result = stat(ifname, &statBuf);
+       if (result < 0) {
+           perror(ifname);
+           do_exit(WARNING);
+       }
+       time_stamp = statBuf.st_ctime;
+       ifile_size = statBuf.st_size;
+    }
+
+
+    if (tostdout==1) {
+       /* And get to work */
+       strcpy(ofname, "stdout");
+       outFileNum=fileno(stdout);
        SET_BINARY_MODE(fileno(stdout));
-    strcpy(ifname, "stdin");
-    strcpy(ofname, "stdout");
 
-    /* Get the time stamp on the input file. */
-    time_stamp = 0; /* time unknown by default */
+       clear_bufs(); /* clear input and output buffers */
+       part_nb = 0;
 
-    ifile_size = -1L; /* convention for unknown size */
+       /* Actually do the compression/decompression. */
+       zip(inFileNum, outFileNum);
 
-    clear_bufs(); /* clear input and output buffers */
-    to_stdout = 1;
-    part_nb = 0;
+    } else {
 
-    /* Actually do the compression/decompression. Loop over zipped members.
-     */
-       if ((*work)(fileno(stdin), fileno(stdout)) != OK) return;
+       /* And get to work */
+       strncpy(ofname, ifname, MAX_PATH_LEN-4);
+       strcat(ofname, ".gz");
+
+
+       /* Open output fille */
+       outFileNum=open( ofname, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW);
+       if (outFileNum < 0) {
+           perror(ofname);
+           do_exit(WARNING);
+       }
+       SET_BINARY_MODE(outFileNum);
+       /* Set permissions on the file */
+       fchmod(outFileNum, statBuf.st_mode);
+
+       clear_bufs(); /* clear input and output buffers */
+       part_nb = 0;
+
+       /* Actually do the compression/decompression. */
+       result=zip(inFileNum, outFileNum);
+       close( outFileNum);
+       close( inFileNum);
+       /* Delete the original file */
+       if (result == OK)
+           delFileName=ifname;
+       else
+           delFileName=ofname;
+
+       if (unlink (delFileName) < 0) {
+           perror (delFileName);
+           exit( FALSE);
+       }
+    }
+
+    do_exit(exit_code);
 }
 
 /* ========================================================================
@@ -1924,10 +1988,6 @@ local void do_exit(int exitcode)
 
 #include <ctype.h>
 
-#ifdef RCSID
-static char rcsid[] = "$Id: gzip.c,v 1.1 1999/10/05 16:24:56 andersen Exp $";
-#endif
-
 /* ===========================================================================
  * Constants
  */
@@ -2942,10 +3002,6 @@ local void set_file_type()
  * terms of the GNU General Public License, see the file COPYING.
  */
 
-#ifdef RCSID
-static char rcsid[] = "$Id: gzip.c,v 1.1 1999/10/05 16:24:56 andersen Exp $";
-#endif
-
 #include <ctype.h>
 #include <errno.h>
 #include <sys/types.h>
@@ -2963,8 +3019,6 @@ static char rcsid[] = "$Id: gzip.c,v 1.1 1999/10/05 16:24:56 andersen Exp $";
    extern int errno;
 #endif
 
-extern ulg crc_32_tab[];   /* crc table, defined below */
-
 /* ===========================================================================
  * Copy input to output unchanged: zcat == cat with --force.
  * IN assertion: insize bytes have already been read in inbuf.
@@ -3141,10 +3195,6 @@ void display_ratio(num, den, file)
  * terms of the GNU General Public License, see the file COPYING.
  */
 
-#ifdef RCSID
-static char rcsid[] = "$Id: gzip.c,v 1.1 1999/10/05 16:24:56 andersen Exp $";
-#endif
-
 #include <ctype.h>
 #include <sys/types.h>
 
@@ -3176,6 +3226,7 @@ int zip(in, out)
 
     /* Write the header to the gzip file. See algorithm.doc for the format */
 
+
     method = DEFLATED;
     put_byte(GZIP_MAGIC[0]); /* magic header */
     put_byte(GZIP_MAGIC[1]);