19e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* gzjoin -- command to join gzip files into one gzip file
29e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
304351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes  Copyright (C) 2004, 2005, 2012 Mark Adler, all rights reserved
404351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes  version 1.2, 14 Aug 2012
59e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
69e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  This software is provided 'as-is', without any express or implied
79e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  warranty.  In no event will the author be held liable for any damages
89e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  arising from the use of this software.
99e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  Permission is granted to anyone to use this software for any purpose,
119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  including commercial applications, and to alter it and redistribute it
129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  freely, subject to the following restrictions:
139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  1. The origin of this software must not be misrepresented; you must not
159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project     claim that you wrote the original software. If you use this software
169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project     in a product, an acknowledgment in the product documentation would be
179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project     appreciated but is not required.
189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  2. Altered source versions must be plainly marked as such, and must not be
199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project     misrepresented as being the original software.
209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  3. This notice may not be removed or altered from any source distribution.
219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  Mark Adler    madler@alumni.caltech.edu
239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/*
269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * Change history:
279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *
289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * 1.0  11 Dec 2004     - First version
299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * 1.1  12 Jun 2005     - Changed ssize_t to long for portability
3004351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes * 1.2  14 Aug 2012     - Clean up for z_const usage
319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/*
349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   gzjoin takes one or more gzip files on the command line and writes out a
359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   single gzip file that will uncompress to the concatenation of the
369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   uncompressed data from the individual gzip files.  gzjoin does this without
379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   having to recompress any of the data and without having to calculate a new
389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   crc32 for the concatenated uncompressed data.  gzjoin does however have to
399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   decompress all of the input data in order to find the bits in the compressed
409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   data that need to be modified to concatenate the streams.
419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   gzjoin does not do an integrity check on the input gzip files other than
439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   checking the gzip header and decompressing the compressed data.  They are
449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   otherwise assumed to be complete and correct.
459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   Each joint between gzip files removes at least 18 bytes of previous trailer
479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   and subsequent header, and inserts an average of about three bytes to the
489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   compressed data in order to connect the streams.  The output gzip file
499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   has a minimal ten-byte gzip header with no file name or modification time.
509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   This program was written to illustrate the use of the Z_BLOCK option of
529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   inflate() and the crc32_combine() function.  gzjoin will not compile with
539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   versions of zlib earlier than 1.2.3.
549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <stdio.h>      /* fputs(), fprintf(), fwrite(), putc() */
579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <stdlib.h>     /* exit(), malloc(), free() */
589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <fcntl.h>      /* open() */
599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <unistd.h>     /* close(), read(), lseek() */
609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include "zlib.h"
619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* crc32(), crc32_combine(), inflateInit2(), inflate(), inflateEnd() */
629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define local static
649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* exit with an error (return a value to allow use in an expression) */
669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal int bail(char *why1, char *why2)
679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    fprintf(stderr, "gzjoin error: %s%s, output incomplete\n", why1, why2);
699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    exit(1);
709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return 0;
719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* -- simple buffered file input with access to the buffer -- */
749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define CHUNK 32768         /* must be a power of two and fit in unsigned */
769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* bin buffered input file type */
789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projecttypedef struct {
799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    char *name;             /* name of file for error messages */
809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int fd;                 /* file descriptor */
819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned left;          /* bytes remaining at next */
829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned char *next;    /* next byte to read */
839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned char *buf;     /* allocated buffer of length CHUNK */
849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} bin;
859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* close a buffered file and free allocated memory */
879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal void bclose(bin *in)
889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (in != NULL) {
909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (in->fd != -1)
919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            close(in->fd);
929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (in->buf != NULL)
939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            free(in->buf);
949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        free(in);
959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* open a buffered file for input, return a pointer to type bin, or NULL on
999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   failure */
1009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal bin *bopen(char *name)
1019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
1029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    bin *in;
1039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    in = malloc(sizeof(bin));
1059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (in == NULL)
1069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return NULL;
1079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    in->buf = malloc(CHUNK);
1089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    in->fd = open(name, O_RDONLY, 0);
1099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (in->buf == NULL || in->fd == -1) {
1109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        bclose(in);
1119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return NULL;
1129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
1139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    in->left = 0;
1149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    in->next = in->buf;
1159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    in->name = name;
1169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return in;
1179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
1189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* load buffer from file, return -1 on read error, 0 or 1 on success, with
1209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   1 indicating that end-of-file was reached */
1219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal int bload(bin *in)
1229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
1239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    long len;
1249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (in == NULL)
1269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return -1;
1279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (in->left != 0)
1289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return 0;
1299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    in->next = in->buf;
1309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    do {
1319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        len = (long)read(in->fd, in->buf + in->left, CHUNK - in->left);
1329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (len < 0)
1339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            return -1;
1349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        in->left += (unsigned)len;
1359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    } while (len != 0 && in->left < CHUNK);
1369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return len == 0 ? 1 : 0;
1379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
1389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* get a byte from the file, bail if end of file */
1409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define bget(in) (in->left ? 0 : bload(in), \
1419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                  in->left ? (in->left--, *(in->next)++) : \
1429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    bail("unexpected end of file on ", in->name))
1439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* get a four-byte little-endian unsigned integer from file */
1459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal unsigned long bget4(bin *in)
1469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
1479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned long val;
1489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    val = bget(in);
1509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    val += (unsigned long)(bget(in)) << 8;
1519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    val += (unsigned long)(bget(in)) << 16;
1529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    val += (unsigned long)(bget(in)) << 24;
1539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return val;
1549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
1559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* skip bytes in file */
1579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal void bskip(bin *in, unsigned skip)
1589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
1599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* check pointer */
1609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (in == NULL)
1619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return;
1629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* easy case -- skip bytes in buffer */
1649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (skip <= in->left) {
1659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        in->left -= skip;
1669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        in->next += skip;
1679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return;
1689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
1699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* skip what's in buffer, discard buffer contents */
1719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    skip -= in->left;
1729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    in->left = 0;
1739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* seek past multiples of CHUNK bytes */
1759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (skip > CHUNK) {
1769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        unsigned left;
1779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        left = skip & (CHUNK - 1);
1799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (left == 0) {
1809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* exact number of chunks: seek all the way minus one byte to check
1819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project               for end-of-file with a read */
1829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            lseek(in->fd, skip - 1, SEEK_CUR);
1839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (read(in->fd, in->buf, 1) != 1)
1849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                bail("unexpected end of file on ", in->name);
1859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            return;
1869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
1879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* skip the integral chunks, update skip with remainder */
1899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        lseek(in->fd, skip - left, SEEK_CUR);
1909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        skip = left;
1919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
1929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* read more input and skip remainder */
1949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    bload(in);
1959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (skip > in->left)
1969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        bail("unexpected end of file on ", in->name);
1979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    in->left -= skip;
1989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    in->next += skip;
1999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
2009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* -- end of buffered input functions -- */
2029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* skip the gzip header from file in */
2049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal void gzhead(bin *in)
2059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
2069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int flags;
2079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* verify gzip magic header and compression method */
2099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (bget(in) != 0x1f || bget(in) != 0x8b || bget(in) != 8)
2109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        bail(in->name, " is not a valid gzip file");
2119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* get and verify flags */
2139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    flags = bget(in);
2149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if ((flags & 0xe0) != 0)
2159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        bail("unknown reserved bits set in ", in->name);
2169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* skip modification time, extra flags, and os */
2189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    bskip(in, 6);
2199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* skip extra field if present */
2219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (flags & 4) {
2229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        unsigned len;
2239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        len = bget(in);
2259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        len += (unsigned)(bget(in)) << 8;
2269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        bskip(in, len);
2279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
2289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* skip file name if present */
2309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (flags & 8)
2319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        while (bget(in) != 0)
2329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            ;
2339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* skip comment if present */
2359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (flags & 16)
2369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        while (bget(in) != 0)
2379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            ;
2389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* skip header crc if present */
2409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (flags & 2)
2419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        bskip(in, 2);
2429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
2439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* write a four-byte little-endian unsigned integer to out */
2459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal void put4(unsigned long val, FILE *out)
2469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
2479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    putc(val & 0xff, out);
2489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    putc((val >> 8) & 0xff, out);
2499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    putc((val >> 16) & 0xff, out);
2509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    putc((val >> 24) & 0xff, out);
2519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
2529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Load up zlib stream from buffered input, bail if end of file */
2549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal void zpull(z_streamp strm, bin *in)
2559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
2569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (in->left == 0)
2579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        bload(in);
2589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (in->left == 0)
2599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        bail("unexpected end of file on ", in->name);
2609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm->avail_in = in->left;
2619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm->next_in = in->next;
2629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
2639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Write header for gzip file to out and initialize trailer. */
2659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal void gzinit(unsigned long *crc, unsigned long *tot, FILE *out)
2669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
2679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    fwrite("\x1f\x8b\x08\0\0\0\0\0\0\xff", 1, 10, out);
2689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    *crc = crc32(0L, Z_NULL, 0);
2699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    *tot = 0;
2709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
2719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Copy the compressed data from name, zeroing the last block bit of the last
2739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   block if clr is true, and adding empty blocks as needed to get to a byte
2749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   boundary.  If clr is false, then the last block becomes the last block of
2759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   the output, and the gzip trailer is written.  crc and tot maintains the
2769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   crc and length (modulo 2^32) of the output for the trailer.  The resulting
2779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   gzip file is written to out.  gzinit() must be called before the first call
2789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   of gzcopy() to write the gzip header and to initialize crc and tot. */
2799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal void gzcopy(char *name, int clr, unsigned long *crc, unsigned long *tot,
2809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                  FILE *out)
2819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
2829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int ret;                /* return value from zlib functions */
2839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int pos;                /* where the "last block" bit is in byte */
2849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int last;               /* true if processing the last block */
2859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    bin *in;                /* buffered input file */
2869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned char *start;   /* start of compressed data in buffer */
2879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned char *junk;    /* buffer for uncompressed data -- discarded */
2889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    z_off_t len;            /* length of uncompressed data (support > 4 GB) */
2899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    z_stream strm;          /* zlib inflate stream */
2909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* open gzip file and skip header */
2929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    in = bopen(name);
2939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (in == NULL)
2949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        bail("could not open ", name);
2959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    gzhead(in);
2969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* allocate buffer for uncompressed data and initialize raw inflate
2989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project       stream */
2999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    junk = malloc(CHUNK);
3009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm.zalloc = Z_NULL;
3019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm.zfree = Z_NULL;
3029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm.opaque = Z_NULL;
3039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm.avail_in = 0;
3049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm.next_in = Z_NULL;
3059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    ret = inflateInit2(&strm, -15);
3069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (junk == NULL || ret != Z_OK)
3079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        bail("out of memory", "");
3089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* inflate and copy compressed data, clear last-block bit if requested */
3109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    len = 0;
3119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    zpull(&strm, in);
31204351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    start = in->next;
3139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    last = start[0] & 1;
3149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (last && clr)
3159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        start[0] &= ~1;
3169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm.avail_out = 0;
3179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    for (;;) {
3189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* if input used and output done, write used input and get more */
3199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (strm.avail_in == 0 && strm.avail_out != 0) {
3209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            fwrite(start, 1, strm.next_in - start, out);
3219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            start = in->buf;
3229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            in->left = 0;
3239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            zpull(&strm, in);
3249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
3259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* decompress -- return early when end-of-block reached */
3279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        strm.avail_out = CHUNK;
3289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        strm.next_out = junk;
3299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        ret = inflate(&strm, Z_BLOCK);
3309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        switch (ret) {
3319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        case Z_MEM_ERROR:
3329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            bail("out of memory", "");
3339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        case Z_DATA_ERROR:
3349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            bail("invalid compressed data in ", in->name);
3359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
3369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* update length of uncompressed data */
3389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        len += CHUNK - strm.avail_out;
3399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* check for block boundary (only get this when block copied out) */
3419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (strm.data_type & 128) {
3429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* if that was the last block, then done */
3439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (last)
3449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
3459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* number of unused bits in last byte */
3479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            pos = strm.data_type & 7;
3489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* find the next last-block bit */
3509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (pos != 0) {
3519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                /* next last-block bit is in last used byte */
3529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                pos = 0x100 >> pos;
3539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                last = strm.next_in[-1] & pos;
3549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                if (last && clr)
35504351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes                    in->buf[strm.next_in - in->buf - 1] &= ~pos;
3569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
3579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            else {
3589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                /* next last-block bit is in next unused byte */
3599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                if (strm.avail_in == 0) {
3609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    /* don't have that byte yet -- get it */
3619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    fwrite(start, 1, strm.next_in - start, out);
3629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    start = in->buf;
3639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    in->left = 0;
3649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    zpull(&strm, in);
3659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                }
3669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                last = strm.next_in[0] & 1;
3679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                if (last && clr)
36804351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes                    in->buf[strm.next_in - in->buf] &= ~1;
3699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
3709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
3719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
3729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* update buffer with unused input */
3749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    in->left = strm.avail_in;
37504351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    in->next = in->buf + (strm.next_in - in->buf);
3769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* copy used input, write empty blocks to get to byte boundary */
3789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    pos = strm.data_type & 7;
3799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    fwrite(start, 1, in->next - start - 1, out);
3809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    last = in->next[-1];
3819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (pos == 0 || !clr)
3829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* already at byte boundary, or last file: write last byte */
3839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        putc(last, out);
3849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    else {
3859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* append empty blocks to last byte */
3869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        last &= ((0x100 >> pos) - 1);       /* assure unused bits are zero */
3879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (pos & 1) {
3889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* odd -- append an empty stored block */
3899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            putc(last, out);
3909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (pos == 1)
3919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                putc(0, out);               /* two more bits in block header */
3929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            fwrite("\0\0\xff\xff", 1, 4, out);
3939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
3949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        else {
3959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* even -- append 1, 2, or 3 empty fixed blocks */
3969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            switch (pos) {
3979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            case 6:
3989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                putc(last | 8, out);
3999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                last = 0;
4009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            case 4:
4019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                putc(last | 0x20, out);
4029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                last = 0;
4039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            case 2:
4049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                putc(last | 0x80, out);
4059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                putc(0, out);
4069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
4079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
4089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
4099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* update crc and tot */
4119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    *crc = crc32_combine(*crc, bget4(in), len);
4129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    *tot += (unsigned long)len;
4139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* clean up */
4159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    inflateEnd(&strm);
4169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    free(junk);
4179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    bclose(in);
4189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* write trailer if this is the last gzip file */
4209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (!clr) {
4219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        put4(*crc, out);
4229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        put4(*tot, out);
4239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
4249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
4259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* join the gzip files on the command line, write result to stdout */
4279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectint main(int argc, char **argv)
4289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
4299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned long crc, tot;     /* running crc and total uncompressed length */
4309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* skip command name */
4329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    argc--;
4339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    argv++;
4349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* show usage if no arguments */
4369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (argc == 0) {
4379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        fputs("gzjoin usage: gzjoin f1.gz [f2.gz [f3.gz ...]] > fjoin.gz\n",
4389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project              stderr);
4399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return 0;
4409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
4419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* join gzip files on command line and write to stdout */
4439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    gzinit(&crc, &tot, stdout);
4449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    while (argc--)
4459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        gzcopy(*argv++, argc, &crc, &tot, stdout);
4469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* done */
4489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return 0;
4499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
450