19e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* gzappend -- command to append to a gzip file 29e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 304351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes Copyright (C) 2003, 2012 Mark Adler, all rights reserved 404351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes version 1.2, 11 Oct 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 19 Oct 2003 - First version 299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * 1.1 4 Nov 2003 - Expand and clarify some comments and notes 309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * - Add version and copyright to help 319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * - Send help to stdout instead of stderr 329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * - Add some preemptive typecasts 339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * - Add L to constants in lseek() calls 349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * - Remove some debugging information in error messages 359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * - Use new data_type definition for zlib 1.2.1 369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * - Simplfy and unify file operations 379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * - Finish off gzip file in gztack() 389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * - Use deflatePrime() instead of adding empty blocks 399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * - Keep gzip file clean on appended file read errors 409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * - Use in-place rotate instead of auxiliary buffer 419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * (Why you ask? Because it was fun to write!) 4204351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes * 1.2 11 Oct 2012 - Fix for proper z_const usage 4304351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes * - Check for input buffer malloc failure 449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */ 459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* 479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project gzappend takes a gzip file and appends to it, compressing files from the 489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project command line or data from stdin. The gzip file is written to directly, to 499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project avoid copying that file, in case it's large. Note that this results in the 509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unfriendly behavior that if gzappend fails, the gzip file is corrupted. 519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project This program was written to illustrate the use of the new Z_BLOCK option of 539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project zlib 1.2.x's inflate() function. This option returns from inflate() at each 549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project block boundary to facilitate locating and modifying the last block bit at 559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project the start of the final deflate block. Also whether using Z_BLOCK or not, 569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project another required feature of zlib 1.2.x is that inflate() now provides the 579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project number of unusued bits in the last input byte used. gzappend will not work 589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project with versions of zlib earlier than 1.2.1. 599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project gzappend first decompresses the gzip file internally, discarding all but 619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project the last 32K of uncompressed data, and noting the location of the last block 629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project bit and the number of unused bits in the last byte of the compressed data. 639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project The gzip trailer containing the CRC-32 and length of the uncompressed data 649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project is verified. This trailer will be later overwritten. 659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project Then the last block bit is cleared by seeking back in the file and rewriting 679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project the byte that contains it. Seeking forward, the last byte of the compressed 689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project data is saved along with the number of unused bits to initialize deflate. 699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project A deflate process is initialized, using the last 32K of the uncompressed 719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project data from the gzip file to initialize the dictionary. If the total 729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project uncompressed data was less than 32K, then all of it is used to initialize 739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project the dictionary. The deflate output bit buffer is also initialized with the 749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project last bits from the original deflate stream. From here on, the data to 759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project append is simply compressed using deflate, and written to the gzip file. 769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project When that is complete, the new CRC-32 and uncompressed length are written 779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project as the trailer of the gzip file. 789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */ 799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <stdio.h> 819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <stdlib.h> 829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <string.h> 839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <fcntl.h> 849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <unistd.h> 859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include "zlib.h" 869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define local static 889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define LGCHUNK 14 899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define CHUNK (1U << LGCHUNK) 909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define DSIZE 32768U 919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* print an error message and terminate with extreme prejudice */ 939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal void bye(char *msg1, char *msg2) 949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{ 959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project fprintf(stderr, "gzappend error: %s%s\n", msg1, msg2); 969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project exit(1); 979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} 989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* return the greatest common divisor of a and b using Euclid's algorithm, 1009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project modified to be fast when one argument much greater than the other, and 1019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project coded to avoid unnecessary swapping */ 1029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal unsigned gcd(unsigned a, unsigned b) 1039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{ 1049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned c; 1059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project while (a && b) 1079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (a > b) { 1089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project c = b; 1099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project while (a - c >= c) 1109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project c <<= 1; 1119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project a -= c; 1129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 1139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project else { 1149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project c = a; 1159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project while (b - c >= c) 1169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project c <<= 1; 1179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project b -= c; 1189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 1199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return a + b; 1209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} 1219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* rotate list[0..len-1] left by rot positions, in place */ 1239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal void rotate(unsigned char *list, unsigned len, unsigned rot) 1249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{ 1259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned char tmp; 1269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned cycles; 1279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned char *start, *last, *to, *from; 1289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* normalize rot and handle degenerate cases */ 1309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (len < 2) return; 1319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (rot >= len) rot %= len; 1329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (rot == 0) return; 1339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* pointer to last entry in list */ 1359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project last = list + (len - 1); 1369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* do simple left shift by one */ 1389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (rot == 1) { 1399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project tmp = *list; 1409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project memcpy(list, list + 1, len - 1); 1419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *last = tmp; 1429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return; 1439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 1449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* do simple right shift by one */ 1469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (rot == len - 1) { 1479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project tmp = *last; 1489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project memmove(list + 1, list, len - 1); 1499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *list = tmp; 1509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return; 1519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 1529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* otherwise do rotate as a set of cycles in place */ 1549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project cycles = gcd(len, rot); /* number of cycles */ 1559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project do { 1569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project start = from = list + cycles; /* start index is arbitrary */ 1579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project tmp = *from; /* save entry to be overwritten */ 1589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project for (;;) { 1599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project to = from; /* next step in cycle */ 1609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project from += rot; /* go right rot positions */ 1619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (from > last) from -= len; /* (pointer better not wrap) */ 1629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (from == start) break; /* all but one shifted */ 1639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *to = *from; /* shift left */ 1649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 1659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *to = tmp; /* complete the circle */ 1669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } while (--cycles); 1679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} 1689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* structure for gzip file read operations */ 1709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projecttypedef struct { 1719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project int fd; /* file descriptor */ 1729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project int size; /* 1 << size is bytes in buf */ 1739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned left; /* bytes available at next */ 1749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned char *buf; /* buffer */ 17504351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes z_const unsigned char *next; /* next byte in buffer */ 1769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project char *name; /* file name for error messages */ 1779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} file; 1789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* reload buffer */ 1809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal int readin(file *in) 1819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{ 1829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project int len; 1839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project len = read(in->fd, in->buf, 1 << in->size); 1859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (len == -1) bye("error reading ", in->name); 1869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project in->left = (unsigned)len; 1879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project in->next = in->buf; 1889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return len; 1899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} 1909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* read from file in, exit if end-of-file */ 1929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal int readmore(file *in) 1939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{ 1949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (readin(in) == 0) bye("unexpected end of ", in->name); 1959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return 0; 1969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} 1979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define read1(in) (in->left == 0 ? readmore(in) : 0, \ 1999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project in->left--, *(in->next)++) 2009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 2019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* skip over n bytes of in */ 2029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal void skip(file *in, unsigned n) 2039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{ 2049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned bypass; 2059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 2069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (n > in->left) { 2079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project n -= in->left; 2089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project bypass = n & ~((1U << in->size) - 1); 2099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (bypass) { 2109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (lseek(in->fd, (off_t)bypass, SEEK_CUR) == -1) 2119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project bye("seeking ", in->name); 2129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project n -= bypass; 2139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 2149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project readmore(in); 2159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (n > in->left) 2169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project bye("unexpected end of ", in->name); 2179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 2189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project in->left -= n; 2199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project in->next += n; 2209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} 2219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 2229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* read a four-byte unsigned integer, little-endian, from in */ 2239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectunsigned long read4(file *in) 2249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{ 2259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned long val; 2269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 2279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project val = read1(in); 2289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project val += (unsigned)read1(in) << 8; 2299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project val += (unsigned long)read1(in) << 16; 2309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project val += (unsigned long)read1(in) << 24; 2319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return val; 2329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} 2339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 2349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* skip over gzip header */ 2359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal void gzheader(file *in) 2369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{ 2379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project int flags; 2389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned n; 2399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 2409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (read1(in) != 31 || read1(in) != 139) bye(in->name, " not a gzip file"); 2419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (read1(in) != 8) bye("unknown compression method in", in->name); 2429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project flags = read1(in); 2439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (flags & 0xe0) bye("unknown header flags set in", in->name); 2449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project skip(in, 6); 2459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (flags & 4) { 2469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project n = read1(in); 2479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project n += (unsigned)(read1(in)) << 8; 2489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project skip(in, n); 2499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 2509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (flags & 8) while (read1(in) != 0) ; 2519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (flags & 16) while (read1(in) != 0) ; 2529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (flags & 2) skip(in, 2); 2539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} 2549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 2559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* decompress gzip file "name", return strm with a deflate stream ready to 2569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project continue compression of the data in the gzip file, and return a file 2579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project descriptor pointing to where to write the compressed data -- the deflate 2589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project stream is initialized to compress using level "level" */ 2599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal int gzscan(char *name, z_stream *strm, int level) 2609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{ 2619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project int ret, lastbit, left, full; 2629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned have; 2639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned long crc, tot; 2649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned char *window; 2659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project off_t lastoff, end; 2669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project file gz; 2679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 2689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* open gzip file */ 2699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project gz.name = name; 2709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project gz.fd = open(name, O_RDWR, 0); 2719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (gz.fd == -1) bye("cannot open ", name); 2729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project gz.buf = malloc(CHUNK); 2739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (gz.buf == NULL) bye("out of memory", ""); 2749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project gz.size = LGCHUNK; 2759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project gz.left = 0; 2769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 2779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* skip gzip header */ 2789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project gzheader(&gz); 2799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 2809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* prepare to decompress */ 2819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project window = malloc(DSIZE); 2829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (window == NULL) bye("out of memory", ""); 2839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->zalloc = Z_NULL; 2849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->zfree = Z_NULL; 2859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->opaque = Z_NULL; 2869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ret = inflateInit2(strm, -15); 2879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (ret != Z_OK) bye("out of memory", " or library mismatch"); 2889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 2899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* decompress the deflate stream, saving append information */ 2909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project lastbit = 0; 2919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project lastoff = lseek(gz.fd, 0L, SEEK_CUR) - gz.left; 2929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project left = 0; 2939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->avail_in = gz.left; 2949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->next_in = gz.next; 2959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project crc = crc32(0L, Z_NULL, 0); 2969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project have = full = 0; 2979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project do { 2989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* if needed, get more input */ 2999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (strm->avail_in == 0) { 3009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project readmore(&gz); 3019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->avail_in = gz.left; 3029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->next_in = gz.next; 3039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 3049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 3059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* set up output to next available section of sliding window */ 3069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->avail_out = DSIZE - have; 3079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->next_out = window + have; 3089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 3099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* inflate and check for errors */ 3109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ret = inflate(strm, Z_BLOCK); 3119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (ret == Z_STREAM_ERROR) bye("internal stream error!", ""); 3129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (ret == Z_MEM_ERROR) bye("out of memory", ""); 3139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (ret == Z_DATA_ERROR) 3149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project bye("invalid compressed data--format violated in", name); 3159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 3169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* update crc and sliding window pointer */ 3179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project crc = crc32(crc, window + have, DSIZE - have - strm->avail_out); 3189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (strm->avail_out) 3199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project have = DSIZE - strm->avail_out; 3209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project else { 3219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project have = 0; 3229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project full = 1; 3239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 3249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 3259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* process end of block */ 3269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (strm->data_type & 128) { 3279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (strm->data_type & 64) 3289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project left = strm->data_type & 0x1f; 3299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project else { 3309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project lastbit = strm->data_type & 0x1f; 3319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project lastoff = lseek(gz.fd, 0L, SEEK_CUR) - strm->avail_in; 3329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 3339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 3349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } while (ret != Z_STREAM_END); 3359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project inflateEnd(strm); 3369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project gz.left = strm->avail_in; 3379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project gz.next = strm->next_in; 3389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 3399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* save the location of the end of the compressed data */ 3409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project end = lseek(gz.fd, 0L, SEEK_CUR) - gz.left; 3419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 3429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* check gzip trailer and save total for deflate */ 3439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (crc != read4(&gz)) 3449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project bye("invalid compressed data--crc mismatch in ", name); 3459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project tot = strm->total_out; 3469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if ((tot & 0xffffffffUL) != read4(&gz)) 3479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project bye("invalid compressed data--length mismatch in", name); 3489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 3499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* if not at end of file, warn */ 3509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (gz.left || readin(&gz)) 3519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project fprintf(stderr, 3529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project "gzappend warning: junk at end of gzip file overwritten\n"); 3539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 3549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* clear last block bit */ 3559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project lseek(gz.fd, lastoff - (lastbit != 0), SEEK_SET); 3569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (read(gz.fd, gz.buf, 1) != 1) bye("reading after seek on ", name); 3579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *gz.buf = (unsigned char)(*gz.buf ^ (1 << ((8 - lastbit) & 7))); 3589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project lseek(gz.fd, -1L, SEEK_CUR); 3599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (write(gz.fd, gz.buf, 1) != 1) bye("writing after seek to ", name); 3609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 3619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* if window wrapped, build dictionary from window by rotating */ 3629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (full) { 3639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project rotate(window, DSIZE, have); 3649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project have = DSIZE; 3659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 3669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 3679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* set up deflate stream with window, crc, total_in, and leftover bits */ 3689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ret = deflateInit2(strm, level, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); 3699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (ret != Z_OK) bye("out of memory", ""); 3709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project deflateSetDictionary(strm, window, have); 3719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->adler = crc; 3729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->total_in = tot; 3739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (left) { 3749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project lseek(gz.fd, --end, SEEK_SET); 3759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (read(gz.fd, gz.buf, 1) != 1) bye("reading after seek on ", name); 3769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project deflatePrime(strm, 8 - left, *gz.buf); 3779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 3789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project lseek(gz.fd, end, SEEK_SET); 3799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 3809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* clean up and return */ 3819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project free(window); 3829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project free(gz.buf); 3839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return gz.fd; 3849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} 3859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 3869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* append file "name" to gzip file gd using deflate stream strm -- if last 3879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project is true, then finish off the deflate stream at the end */ 3889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal void gztack(char *name, int gd, z_stream *strm, int last) 3899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{ 3909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project int fd, len, ret; 3919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned left; 3929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned char *in, *out; 3939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 3949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* open file to compress and append */ 3959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project fd = 0; 3969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (name != NULL) { 3979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project fd = open(name, O_RDONLY, 0); 3989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (fd == -1) 3999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project fprintf(stderr, "gzappend warning: %s not found, skipping ...\n", 4009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project name); 4019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 4029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 4039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* allocate buffers */ 40404351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes in = malloc(CHUNK); 4059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project out = malloc(CHUNK); 40604351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes if (in == NULL || out == NULL) bye("out of memory", ""); 4079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 4089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* compress input file and append to gzip file */ 4099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project do { 4109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* get more input */ 41104351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes len = read(fd, in, CHUNK); 4129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (len == -1) { 4139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project fprintf(stderr, 4149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project "gzappend warning: error reading %s, skipping rest ...\n", 4159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project name); 4169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project len = 0; 4179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 4189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->avail_in = (unsigned)len; 4199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->next_in = in; 4209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (len) strm->adler = crc32(strm->adler, in, (unsigned)len); 4219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 4229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* compress and write all available output */ 4239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project do { 4249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->avail_out = CHUNK; 4259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->next_out = out; 4269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ret = deflate(strm, last && len == 0 ? Z_FINISH : Z_NO_FLUSH); 4279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project left = CHUNK - strm->avail_out; 4289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project while (left) { 4299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project len = write(gd, out + CHUNK - strm->avail_out - left, left); 4309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (len == -1) bye("writing gzip file", ""); 4319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project left -= (unsigned)len; 4329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 4339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } while (strm->avail_out == 0 && ret != Z_STREAM_END); 4349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } while (len != 0); 4359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 4369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* write trailer after last entry */ 4379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (last) { 4389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project deflateEnd(strm); 4399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project out[0] = (unsigned char)(strm->adler); 4409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project out[1] = (unsigned char)(strm->adler >> 8); 4419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project out[2] = (unsigned char)(strm->adler >> 16); 4429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project out[3] = (unsigned char)(strm->adler >> 24); 4439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project out[4] = (unsigned char)(strm->total_in); 4449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project out[5] = (unsigned char)(strm->total_in >> 8); 4459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project out[6] = (unsigned char)(strm->total_in >> 16); 4469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project out[7] = (unsigned char)(strm->total_in >> 24); 4479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project len = 8; 4489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project do { 4499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ret = write(gd, out + 8 - len, len); 4509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (ret == -1) bye("writing gzip file", ""); 4519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project len -= ret; 4529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } while (len); 4539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project close(gd); 4549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 4559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 4569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* clean up and return */ 4579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project free(out); 45804351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes free(in); 4599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (fd > 0) close(fd); 4609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} 4619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 4629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* process the compression level option if present, scan the gzip file, and 4639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project append the specified files, or append the data from stdin if no other file 4649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project names are provided on the command line -- the gzip file must be writable 4659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project and seekable */ 4669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectint main(int argc, char **argv) 4679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{ 4689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project int gd, level; 4699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project z_stream strm; 4709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 4719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* ignore command name */ 47204351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes argc--; argv++; 4739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 4749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* provide usage if no arguments */ 4759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (*argv == NULL) { 47604351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes printf( 47704351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes "gzappend 1.2 (11 Oct 2012) Copyright (C) 2003, 2012 Mark Adler\n" 47804351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes ); 4799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project printf( 4809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project "usage: gzappend [-level] file.gz [ addthis [ andthis ... ]]\n"); 4819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return 0; 4829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 4839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 4849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* set compression level */ 4859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project level = Z_DEFAULT_COMPRESSION; 4869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (argv[0][0] == '-') { 4879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (argv[0][1] < '0' || argv[0][1] > '9' || argv[0][2] != 0) 4889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project bye("invalid compression level", ""); 4899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project level = argv[0][1] - '0'; 4909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (*++argv == NULL) bye("no gzip file name after options", ""); 4919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 4929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 4939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* prepare to append to gzip file */ 4949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project gd = gzscan(*argv++, &strm, level); 4959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 4969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* append files on command line, or from stdin if none */ 4979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (*argv == NULL) 4989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project gztack(NULL, gd, &strm, 1); 4999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project else 5009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project do { 5019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project gztack(*argv, gd, &strm, argv[1] == NULL); 5029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } while (*++argv != NULL); 5039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return 0; 5049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} 505