19e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* gun.c -- simple gunzip to give an example of the use of inflateBack()
204351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes * Copyright (C) 2003, 2005, 2008, 2010, 2012 Mark Adler
39e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * For conditions of distribution and use, see copyright notice in zlib.h
404351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes   Version 1.7  12 August 2012  Mark Adler */
59e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
69e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Version history:
79e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   1.0  16 Feb 2003  First version for testing of inflateBack()
89e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   1.1  21 Feb 2005  Decompress concatenated gzip streams
99e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                     Remove use of "this" variable (C++ keyword)
109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                     Fix return value for in()
119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                     Improve allocation failure checking
129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                     Add typecasting for void * structures
139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                     Add -h option for command version and usage
149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                     Add a bunch of comments
159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   1.2  20 Mar 2005  Add Unix compress (LZW) decompression
169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                     Copy file attributes from input file to output file
179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   1.3  12 Jun 2005  Add casts for error messages [Oberhumer]
18381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   1.4   8 Dec 2006  LZW decompression speed improvements
19381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   1.5   9 Feb 2008  Avoid warning in latest version of gcc
20381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   1.6  17 Jan 2010  Avoid signed/unsigned comparison warnings
2104351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes   1.7  12 Aug 2012  Update for z_const usage in zlib 1.2.8
229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/*
259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   gun [ -t ] [ name ... ]
269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   decompresses the data in the named gzip files.  If no arguments are given,
289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   gun will decompress from stdin to stdout.  The names must end in .gz, -gz,
299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   .z, -z, _z, or .Z.  The uncompressed data will be written to a file name
309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   with the suffix stripped.  On success, the original file is deleted.  On
319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   failure, the output file is deleted.  For most failures, the command will
329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   continue to process the remaining names on the command line.  A memory
339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   allocation failure will abort the command.  If -t is specified, then the
349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   listed files or stdin will be tested as gzip files for integrity (without
359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   checking for a proper suffix), no output will be written, and no files
369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   will be deleted.
379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   Like gzip, gun allows concatenated gzip streams and will decompress them,
399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   writing all of the uncompressed data to the output.  Unlike gzip, gun allows
409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   an empty file on input, and will produce no error writing an empty output
419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   file.
429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   gun will also decompress files made by Unix compress, which uses LZW
449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   compression.  These files are automatically detected by virtue of their
459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   magic header bytes.  Since the end of Unix compress stream is marked by the
469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   end-of-file, they cannot be concantenated.  If a Unix compress stream is
479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   encountered in an input file, it is the last stream in that file.
489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   Like gunzip and uncompress, the file attributes of the orignal compressed
509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   file are maintained in the final uncompressed file, to the extent that the
519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   user permissions allow it.
529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   On my Mac OS X PowerPC G4, gun is almost twice as fast as gunzip (version
549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   1.2.4) is on the same file, when gun is linked with zlib 1.2.2.  Also the
559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   LZW decompression provided by gun is about twice as fast as the standard
569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   Unix uncompress command.
579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* external functions and related types and constants */
609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <stdio.h>          /* fprintf() */
619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <stdlib.h>         /* malloc(), free() */
629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <string.h>         /* strerror(), strcmp(), strlen(), memcpy() */
639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <errno.h>          /* errno */
649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <fcntl.h>          /* open() */
659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <unistd.h>         /* read(), write(), close(), chown(), unlink() */
669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <sys/types.h>
679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <sys/stat.h>       /* stat(), chmod() */
689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <utime.h>          /* utime() */
699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include "zlib.h"           /* inflateBackInit(), inflateBack(), */
709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                            /* inflateBackEnd(), crc32() */
719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* function declaration */
739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define local static
749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* buffer constants */
769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define SIZE 32768U         /* input and output buffer sizes */
779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define PIECE 16384         /* limits i/o chunks for 16-bit int case */
789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* structure for infback() to pass to input function in() -- it maintains the
809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   input file and a buffer of size SIZE */
819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectstruct ind {
829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int infile;
839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned char *inbuf;
849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project};
859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Load input buffer, assumed to be empty, and return bytes loaded and a
879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   pointer to them.  read() is called until the buffer is full, or until it
889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   returns end-of-file or error.  Return 0 on error. */
8904351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hugheslocal unsigned in(void *in_desc, z_const unsigned char **buf)
909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int ret;
929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned len;
939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned char *next;
949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    struct ind *me = (struct ind *)in_desc;
959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    next = me->inbuf;
979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    *buf = next;
989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    len = 0;
999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    do {
1009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        ret = PIECE;
1019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if ((unsigned)ret > SIZE - len)
1029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            ret = (int)(SIZE - len);
1039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        ret = (int)read(me->infile, next, ret);
1049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (ret == -1) {
1059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            len = 0;
1069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            break;
1079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
1089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        next += ret;
1099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        len += ret;
1109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    } while (ret != 0 && len < SIZE);
1119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return len;
1129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
1139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* structure for infback() to pass to output function out() -- it maintains the
1159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   output file, a running CRC-32 check on the output and the total number of
1169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   bytes output, both for checking against the gzip trailer.  (The length in
1179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   the gzip trailer is stored modulo 2^32, so it's ok if a long is 32 bits and
1189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   the output is greater than 4 GB.) */
1199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectstruct outd {
1209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int outfile;
1219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int check;                  /* true if checking crc and total */
1229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned long crc;
1239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned long total;
1249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project};
1259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Write output buffer and update the CRC-32 and total bytes written.  write()
1279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   is called until all of the output is written or an error is encountered.
1289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   On success out() returns 0.  For a write failure, out() returns 1.  If the
1299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   output file descriptor is -1, then nothing is written.
1309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
1319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal int out(void *out_desc, unsigned char *buf, unsigned len)
1329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
1339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int ret;
1349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    struct outd *me = (struct outd *)out_desc;
1359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (me->check) {
1379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        me->crc = crc32(me->crc, buf, len);
1389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        me->total += len;
1399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
1409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (me->outfile != -1)
1419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        do {
1429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            ret = PIECE;
1439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if ((unsigned)ret > len)
1449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                ret = (int)len;
1459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            ret = (int)write(me->outfile, buf, ret);
1469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (ret == -1)
1479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                return 1;
1489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            buf += ret;
1499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            len -= ret;
1509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        } while (len != 0);
1519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return 0;
1529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
1539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* next input byte macro for use inside lunpipe() and gunpipe() */
1559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define NEXT() (have ? 0 : (have = in(indp, &next)), \
1569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                last = have ? (have--, (int)(*next++)) : -1)
1579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* memory for gunpipe() and lunpipe() --
1599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   the first 256 entries of prefix[] and suffix[] are never used, could
1609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   have offset the index, but it's faster to waste the memory */
1619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectunsigned char inbuf[SIZE];              /* input buffer */
1629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectunsigned char outbuf[SIZE];             /* output buffer */
1639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectunsigned short prefix[65536];           /* index to LZW prefix string */
1649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectunsigned char suffix[65536];            /* one-character LZW suffix */
1659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectunsigned char match[65280 + 2];         /* buffer for reversed match or gzip
1669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                                           32K sliding window */
1679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* throw out what's left in the current bits byte buffer (this is a vestigial
1699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   aspect of the compressed data format derived from an implementation that
1709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   made use of a special VAX machine instruction!) */
1719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define FLUSHCODE() \
1729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    do { \
1739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        left = 0; \
1749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        rem = 0; \
1759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (chunk > have) { \
1769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            chunk -= have; \
1779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            have = 0; \
1789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (NEXT() == -1) \
1799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break; \
1809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            chunk--; \
1819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (chunk > have) { \
1829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                chunk = have = 0; \
1839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break; \
1849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            } \
1859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        } \
1869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        have -= chunk; \
1879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        next += chunk; \
1889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        chunk = 0; \
1899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    } while (0)
1909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Decompress a compress (LZW) file from indp to outfile.  The compress magic
1929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   header (two bytes) has already been read and verified.  There are have bytes
1939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   of buffered input at next.  strm is used for passing error information back
1949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   to gunpipe().
1959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   lunpipe() will return Z_OK on success, Z_BUF_ERROR for an unexpected end of
1979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   file, read error, or write error (a write error indicated by strm->next_in
1989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   not equal to Z_NULL), or Z_DATA_ERROR for invalid input.
1999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
20004351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hugheslocal int lunpipe(unsigned have, z_const unsigned char *next, struct ind *indp,
2019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                  int outfile, z_stream *strm)
2029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
2039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int last;                   /* last byte read by NEXT(), or -1 if EOF */
204381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned chunk;             /* bytes left in current chunk */
2059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int left;                   /* bits left in rem */
2069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned rem;               /* unused bits from input */
2079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int bits;                   /* current bits per code */
2089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned code;              /* code, table traversal index */
2099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned mask;              /* mask for current bits codes */
2109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int max;                    /* maximum bits per code for this stream */
211381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned flags;             /* compress flags, then block compress flag */
2129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned end;               /* last valid entry in prefix/suffix tables */
2139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned temp;              /* current code */
2149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned prev;              /* previous code */
2159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned final;             /* last character written for previous code */
2169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned stack;             /* next position for reversed string */
2179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned outcnt;            /* bytes in output buffer */
2189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    struct outd outd;           /* output structure */
219381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned char *p;
2209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* set up output */
2229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    outd.outfile = outfile;
2239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    outd.check = 0;
2249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* process remainder of compress header -- a flags byte */
2269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    flags = NEXT();
2279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (last == -1)
2289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return Z_BUF_ERROR;
2299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (flags & 0x60) {
2309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        strm->msg = (char *)"unknown lzw flags set";
2319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return Z_DATA_ERROR;
2329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
2339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    max = flags & 0x1f;
2349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (max < 9 || max > 16) {
2359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        strm->msg = (char *)"lzw bits out of range";
2369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return Z_DATA_ERROR;
2379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
2389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (max == 9)                           /* 9 doesn't really mean 9 */
2399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        max = 10;
2409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    flags &= 0x80;                          /* true if block compress */
2419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* clear table */
2439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    bits = 9;
2449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    mask = 0x1ff;
2459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    end = flags ? 256 : 255;
2469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* set up: get first 9-bit code, which is the first decompressed byte, but
2489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project       don't create a table entry until the next code */
2499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (NEXT() == -1)                       /* no compressed data is ok */
2509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return Z_OK;
2519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    final = prev = (unsigned)last;          /* low 8 bits of code */
2529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (NEXT() == -1)                       /* missing a bit */
2539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return Z_BUF_ERROR;
2549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (last & 1) {                         /* code must be < 256 */
2559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        strm->msg = (char *)"invalid lzw code";
2569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return Z_DATA_ERROR;
2579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
2589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    rem = (unsigned)last >> 1;              /* remaining 7 bits */
2599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    left = 7;
2609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    chunk = bits - 2;                       /* 7 bytes left in this chunk */
2619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    outbuf[0] = (unsigned char)final;       /* write first decompressed byte */
2629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    outcnt = 1;
2639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* decode codes */
2659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    stack = 0;
2669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    for (;;) {
2679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* if the table will be full after this, increment the code size */
2689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (end >= mask && bits < max) {
2699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            FLUSHCODE();
2709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            bits++;
2719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            mask <<= 1;
2729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            mask++;
2739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
2749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* get a code of length bits */
2769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (chunk == 0)                     /* decrement chunk modulo bits */
2779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            chunk = bits;
2789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        code = rem;                         /* low bits of code */
2799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (NEXT() == -1) {                 /* EOF is end of compressed data */
2809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* write remaining buffered output */
2819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (outcnt && out(&outd, outbuf, outcnt)) {
2829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                strm->next_in = outbuf;     /* signal write error */
2839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                return Z_BUF_ERROR;
2849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
2859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            return Z_OK;
2869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
2879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        code += (unsigned)last << left;     /* middle (or high) bits of code */
2889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        left += 8;
2899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        chunk--;
2909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (bits > left) {                  /* need more bits */
2919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (NEXT() == -1)               /* can't end in middle of code */
2929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                return Z_BUF_ERROR;
2939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            code += (unsigned)last << left; /* high bits of code */
2949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            left += 8;
2959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            chunk--;
2969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
2979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        code &= mask;                       /* mask to current code length */
2989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        left -= bits;                       /* number of unused bits */
2999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        rem = (unsigned)last >> (8 - left); /* unused bits from last byte */
3009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* process clear code (256) */
3029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (code == 256 && flags) {
3039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            FLUSHCODE();
3049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            bits = 9;                       /* initialize bits and mask */
3059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            mask = 0x1ff;
3069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            end = 255;                      /* empty table */
3079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            continue;                       /* get next code */
3089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
3099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* special code to reuse last match */
3119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        temp = code;                        /* save the current code */
3129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (code > end) {
3139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* Be picky on the allowed code here, and make sure that the code
3149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project               we drop through (prev) will be a valid index so that random
3159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project               input does not cause an exception.  The code != end + 1 check is
3169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project               empirically derived, and not checked in the original uncompress
3179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project               code.  If this ever causes a problem, that check could be safely
3189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project               removed.  Leaving this check in greatly improves gun's ability
3199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project               to detect random or corrupted input after a compress header.
3209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project               In any case, the prev > end check must be retained. */
3219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (code != end + 1 || prev > end) {
3229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                strm->msg = (char *)"invalid lzw code";
3239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                return Z_DATA_ERROR;
3249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
3259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            match[stack++] = (unsigned char)final;
3269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            code = prev;
3279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
3289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* walk through linked list to generate output in reverse order */
330381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        p = match + stack;
3319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        while (code >= 256) {
332381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            *p++ = suffix[code];
3339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            code = prefix[code];
3349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
335381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        stack = p - match;
3369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        match[stack++] = (unsigned char)code;
3379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        final = code;
3389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* link new table entry */
3409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (end < mask) {
3419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            end++;
3429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            prefix[end] = (unsigned short)prev;
3439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            suffix[end] = (unsigned char)final;
3449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
3459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* set previous code for next iteration */
3479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        prev = temp;
3489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* write output in forward order */
3509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        while (stack > SIZE - outcnt) {
3519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            while (outcnt < SIZE)
3529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                outbuf[outcnt++] = match[--stack];
3539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (out(&outd, outbuf, outcnt)) {
3549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                strm->next_in = outbuf; /* signal write error */
3559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                return Z_BUF_ERROR;
3569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
3579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            outcnt = 0;
3589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
359381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        p = match + stack;
3609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        do {
361381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            outbuf[outcnt++] = *--p;
362381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        } while (p > match);
363381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        stack = 0;
3649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* loop for next code with final and prev as the last match, rem and
3669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project           left provide the first 0..7 bits of the next code, end is the last
3679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project           valid table entry */
3689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
3699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
3709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Decompress a gzip file from infile to outfile.  strm is assumed to have been
3729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   successfully initialized with inflateBackInit().  The input file may consist
3739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   of a series of gzip streams, in which case all of them will be decompressed
3749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   to the output file.  If outfile is -1, then the gzip stream(s) integrity is
3759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   checked and nothing is written.
3769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   The return value is a zlib error code: Z_MEM_ERROR if out of memory,
3789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   Z_DATA_ERROR if the header or the compressed data is invalid, or if the
3799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   trailer CRC-32 check or length doesn't match, Z_BUF_ERROR if the input ends
3809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   prematurely or a write error occurs, or Z_ERRNO if junk (not a another gzip
3819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   stream) follows a valid gzip stream.
3829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
3839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal int gunpipe(z_stream *strm, int infile, int outfile)
3849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
3859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int ret, first, last;
3869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned have, flags, len;
38704351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    z_const unsigned char *next = NULL;
3889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    struct ind ind, *indp;
3899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    struct outd outd;
3909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* setup input buffer */
3929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    ind.infile = infile;
3939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    ind.inbuf = inbuf;
3949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    indp = &ind;
3959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* decompress concatenated gzip streams */
3979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    have = 0;                               /* no input data read in yet */
3989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    first = 1;                              /* looking for first gzip header */
3999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm->next_in = Z_NULL;                 /* so Z_BUF_ERROR means EOF */
4009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    for (;;) {
4019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* look for the two magic header bytes for a gzip stream */
4029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (NEXT() == -1) {
4039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            ret = Z_OK;
4049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            break;                          /* empty gzip stream is ok */
4059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
4069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (last != 31 || (NEXT() != 139 && last != 157)) {
4079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            strm->msg = (char *)"incorrect header check";
4089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            ret = first ? Z_DATA_ERROR : Z_ERRNO;
4099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            break;                          /* not a gzip or compress header */
4109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
4119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        first = 0;                          /* next non-header is junk */
4129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* process a compress (LZW) file -- can't be concatenated after this */
4149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (last == 157) {
4159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            ret = lunpipe(have, next, indp, outfile, strm);
4169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            break;
4179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
4189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* process remainder of gzip header */
4209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        ret = Z_BUF_ERROR;
4219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (NEXT() != 8) {                  /* only deflate method allowed */
4229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (last == -1) break;
4239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            strm->msg = (char *)"unknown compression method";
4249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            ret = Z_DATA_ERROR;
4259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            break;
4269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
4279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        flags = NEXT();                     /* header flags */
4289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        NEXT();                             /* discard mod time, xflgs, os */
4299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        NEXT();
4309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        NEXT();
4319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        NEXT();
4329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        NEXT();
4339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        NEXT();
4349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (last == -1) break;
4359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (flags & 0xe0) {
4369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            strm->msg = (char *)"unknown header flags set";
4379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            ret = Z_DATA_ERROR;
4389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            break;
4399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
4409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (flags & 4) {                    /* extra field */
4419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            len = NEXT();
4429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            len += (unsigned)(NEXT()) << 8;
4439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (last == -1) break;
4449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            while (len > have) {
4459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                len -= have;
4469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                have = 0;
4479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                if (NEXT() == -1) break;
4489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                len--;
4499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
4509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (last == -1) break;
4519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            have -= len;
4529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            next += len;
4539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
4549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (flags & 8)                      /* file name */
4559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            while (NEXT() != 0 && last != -1)
4569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                ;
4579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (flags & 16)                     /* comment */
4589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            while (NEXT() != 0 && last != -1)
4599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                ;
4609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (flags & 2) {                    /* header crc */
4619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            NEXT();
4629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            NEXT();
4639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
4649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (last == -1) break;
4659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* set up output */
4679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        outd.outfile = outfile;
4689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        outd.check = 1;
4699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        outd.crc = crc32(0L, Z_NULL, 0);
4709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        outd.total = 0;
4719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* decompress data to output */
4739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        strm->next_in = next;
4749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        strm->avail_in = have;
4759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        ret = inflateBack(strm, in, indp, out, &outd);
4769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (ret != Z_STREAM_END) break;
4779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        next = strm->next_in;
4789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        have = strm->avail_in;
4799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        strm->next_in = Z_NULL;             /* so Z_BUF_ERROR means EOF */
4809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* check trailer */
4829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        ret = Z_BUF_ERROR;
483381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (NEXT() != (int)(outd.crc & 0xff) ||
484381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            NEXT() != (int)((outd.crc >> 8) & 0xff) ||
485381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            NEXT() != (int)((outd.crc >> 16) & 0xff) ||
486381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            NEXT() != (int)((outd.crc >> 24) & 0xff)) {
4879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* crc error */
4889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (last != -1) {
4899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                strm->msg = (char *)"incorrect data check";
4909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                ret = Z_DATA_ERROR;
4919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
4929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            break;
4939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
494381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (NEXT() != (int)(outd.total & 0xff) ||
495381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            NEXT() != (int)((outd.total >> 8) & 0xff) ||
496381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            NEXT() != (int)((outd.total >> 16) & 0xff) ||
497381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            NEXT() != (int)((outd.total >> 24) & 0xff)) {
4989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* length error */
4999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (last != -1) {
5009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                strm->msg = (char *)"incorrect length check";
5019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                ret = Z_DATA_ERROR;
5029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
5039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            break;
5049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
5059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* go back and look for another gzip stream */
5079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
5089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* clean up and return */
5109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return ret;
5119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
5129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Copy file attributes, from -> to, as best we can.  This is best effort, so
5149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   no errors are reported.  The mode bits, including suid, sgid, and the sticky
5159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   bit are copied (if allowed), the owner's user id and group id are copied
5169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   (again if allowed), and the access and modify times are copied. */
5179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal void copymeta(char *from, char *to)
5189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
5199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    struct stat was;
5209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    struct utimbuf when;
5219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* get all of from's Unix meta data, return if not a regular file */
5239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (stat(from, &was) != 0 || (was.st_mode & S_IFMT) != S_IFREG)
5249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return;
5259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* set to's mode bits, ignore errors */
5279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    (void)chmod(to, was.st_mode & 07777);
5289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* copy owner's user and group, ignore errors */
5309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    (void)chown(to, was.st_uid, was.st_gid);
5319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* copy access and modify times, ignore errors */
5339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    when.actime = was.st_atime;
5349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    when.modtime = was.st_mtime;
5359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    (void)utime(to, &when);
5369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
5379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Decompress the file inname to the file outnname, of if test is true, just
5399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   decompress without writing and check the gzip trailer for integrity.  If
5409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   inname is NULL or an empty string, read from stdin.  If outname is NULL or
5419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   an empty string, write to stdout.  strm is a pre-initialized inflateBack
5429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   structure.  When appropriate, copy the file attributes from inname to
5439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   outname.
5449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   gunzip() returns 1 if there is an out-of-memory error or an unexpected
5469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   return code from gunpipe().  Otherwise it returns 0.
5479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
5489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal int gunzip(z_stream *strm, char *inname, char *outname, int test)
5499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
5509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int ret;
5519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int infile, outfile;
5529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* open files */
5549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (inname == NULL || *inname == 0) {
5559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        inname = "-";
5569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        infile = 0;     /* stdin */
5579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
5589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    else {
5599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        infile = open(inname, O_RDONLY, 0);
5609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (infile == -1) {
5619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            fprintf(stderr, "gun cannot open %s\n", inname);
5629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            return 0;
5639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
5649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
5659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (test)
5669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        outfile = -1;
5679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    else if (outname == NULL || *outname == 0) {
5689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        outname = "-";
5699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        outfile = 1;    /* stdout */
5709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
5719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    else {
5729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        outfile = open(outname, O_CREAT | O_TRUNC | O_WRONLY, 0666);
5739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (outfile == -1) {
5749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            close(infile);
5759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            fprintf(stderr, "gun cannot create %s\n", outname);
5769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            return 0;
5779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
5789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
5799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    errno = 0;
5809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* decompress */
5829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    ret = gunpipe(strm, infile, outfile);
5839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (outfile > 2) close(outfile);
5849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (infile > 2) close(infile);
5859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* interpret result */
5879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    switch (ret) {
5889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    case Z_OK:
5899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    case Z_ERRNO:
5909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (infile > 2 && outfile > 2) {
5919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            copymeta(inname, outname);          /* copy attributes */
5929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            unlink(inname);
5939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
5949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (ret == Z_ERRNO)
5959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            fprintf(stderr, "gun warning: trailing garbage ignored in %s\n",
5969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    inname);
5979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        break;
5989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    case Z_DATA_ERROR:
5999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (outfile > 2) unlink(outname);
6009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        fprintf(stderr, "gun data error on %s: %s\n", inname, strm->msg);
6019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        break;
6029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    case Z_MEM_ERROR:
6039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (outfile > 2) unlink(outname);
6049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        fprintf(stderr, "gun out of memory error--aborting\n");
6059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return 1;
6069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    case Z_BUF_ERROR:
6079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (outfile > 2) unlink(outname);
6089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (strm->next_in != Z_NULL) {
6099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            fprintf(stderr, "gun write error on %s: %s\n",
6109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    outname, strerror(errno));
6119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
6129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        else if (errno) {
6139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            fprintf(stderr, "gun read error on %s: %s\n",
6149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    inname, strerror(errno));
6159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
6169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        else {
6179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            fprintf(stderr, "gun unexpected end of file on %s\n",
6189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    inname);
6199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
6209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        break;
6219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    default:
6229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (outfile > 2) unlink(outname);
6239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        fprintf(stderr, "gun internal error--aborting\n");
6249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return 1;
6259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
6269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return 0;
6279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
6289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
6299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Process the gun command line arguments.  See the command syntax near the
6309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   beginning of this source file. */
6319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectint main(int argc, char **argv)
6329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
6339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int ret, len, test;
6349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    char *outname;
6359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned char *window;
6369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    z_stream strm;
6379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
6389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* initialize inflateBack state for repeated use */
6399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    window = match;                         /* reuse LZW match buffer */
6409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm.zalloc = Z_NULL;
6419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm.zfree = Z_NULL;
6429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm.opaque = Z_NULL;
6439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    ret = inflateBackInit(&strm, 15, window);
6449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (ret != Z_OK) {
6459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        fprintf(stderr, "gun out of memory error--aborting\n");
6469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return 1;
6479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
6489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
6499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* decompress each file to the same name with the suffix removed */
6509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    argc--;
6519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    argv++;
6529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    test = 0;
6539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (argc && strcmp(*argv, "-h") == 0) {
654381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        fprintf(stderr, "gun 1.6 (17 Jan 2010)\n");
655381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        fprintf(stderr, "Copyright (C) 2003-2010 Mark Adler\n");
6569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        fprintf(stderr, "usage: gun [-t] [file1.gz [file2.Z ...]]\n");
6579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return 0;
6589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
6599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (argc && strcmp(*argv, "-t") == 0) {
6609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        test = 1;
6619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        argc--;
6629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        argv++;
6639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
6649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (argc)
6659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        do {
6669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (test)
6679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                outname = NULL;
6689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            else {
6699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                len = (int)strlen(*argv);
6709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                if (strcmp(*argv + len - 3, ".gz") == 0 ||
6719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    strcmp(*argv + len - 3, "-gz") == 0)
6729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    len -= 3;
6739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                else if (strcmp(*argv + len - 2, ".z") == 0 ||
6749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    strcmp(*argv + len - 2, "-z") == 0 ||
6759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    strcmp(*argv + len - 2, "_z") == 0 ||
6769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    strcmp(*argv + len - 2, ".Z") == 0)
6779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    len -= 2;
6789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                else {
6799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    fprintf(stderr, "gun error: no gz type on %s--skipping\n",
6809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                            *argv);
6819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    continue;
6829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                }
6839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                outname = malloc(len + 1);
6849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                if (outname == NULL) {
6859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    fprintf(stderr, "gun out of memory error--aborting\n");
6869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    ret = 1;
6879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    break;
6889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                }
6899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                memcpy(outname, *argv, len);
6909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                outname[len] = 0;
6919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
6929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            ret = gunzip(&strm, *argv, outname, test);
6939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (outname != NULL) free(outname);
6949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (ret) break;
6959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        } while (argv++, --argc);
6969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    else
6979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        ret = gunzip(&strm, NULL, NULL, test);
6989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
6999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* clean up */
7009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    inflateBackEnd(&strm);
7019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return ret;
7029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
703