xzlib.c revision 9f3cdef08a5d45c82c71bf740a54e2bc5d07f3ec
1adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard/** 2adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * xzlib.c: front end for the transparent suport of lzma compression 3adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * at the I/O layer, based on an example file from lzma project 4adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * 5adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * See Copyright for the status of this software. 6adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * 7adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * Anders F Bjorklund <afb@users.sourceforge.net> 8adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard */ 9adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#define IN_LIBXML 10adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#include "libxml.h" 11adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#ifdef HAVE_LZMA_H 12adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 13adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#include <string.h> 14adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#ifdef HAVE_ERRNO_H 15adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#include <errno.h> 16adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#endif 17adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 18adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 19adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#ifdef HAVE_SYS_TYPES_H 20adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#include <sys/types.h> 21adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#endif 22adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#ifdef HAVE_SYS_STAT_H 23adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#include <sys/stat.h> 24adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#endif 25adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#ifdef HAVE_FCNTL_H 26adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#include <fcntl.h> 27adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#endif 28adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#ifdef HAVE_UNISTD_H 29adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#include <unistd.h> 30adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#endif 31adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#ifdef HAVE_STDLIB_H 32adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#include <stdlib.h> 33adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#endif 34adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#ifdef HAVE_ZLIB_H 35adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#include <zlib.h> 36adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#endif 37adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#include <lzma.h> 38adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 396bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#include "xzlib.h" 409f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard#include <libxml/xmlmemory.h> 416bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 426bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund/* values for xz_state how */ 43adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#define LOOK 0 /* look for a gzip/lzma header */ 44adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#define COPY 1 /* copy input directly */ 45adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#define GZIP 2 /* decompress a gzip stream */ 46adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#define LZMA 3 /* decompress a lzma stream */ 476bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 486bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund/* internal lzma file state data structure */ 496bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklundtypedef struct { 50adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard int mode; /* see lzma modes above */ 51adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard int fd; /* file descriptor */ 52adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard char *path; /* path or fd for error messages */ 53adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard uint64_t pos; /* current position in uncompressed data */ 5472789ef21fed132bb15bd4e858cb524f41c79ed1Daniel Veillard unsigned int size; /* buffer size, zero if not allocated yet */ 5572789ef21fed132bb15bd4e858cb524f41c79ed1Daniel Veillard unsigned int want; /* requested buffer size, default is BUFSIZ */ 56adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard unsigned char *in; /* input buffer */ 57adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard unsigned char *out; /* output buffer (double-sized when reading) */ 58adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard unsigned char *next; /* next output data to deliver or write */ 5972789ef21fed132bb15bd4e858cb524f41c79ed1Daniel Veillard unsigned int have; /* amount of output data unused at next */ 60adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard int eof; /* true if end of input file reached */ 61adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard uint64_t start; /* where the lzma data started, for rewinding */ 62adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard uint64_t raw; /* where the raw data started, for seeking */ 63adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard int how; /* 0: get header, 1: copy, 2: decompress */ 64adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard int direct; /* true if last read direct, false if lzma */ 65adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* seek request */ 66adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard uint64_t skip; /* amount to skip (already rewound if backwards) */ 67adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard int seek; /* true if seek request pending */ 68adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* error information */ 69adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard int err; /* error code */ 70adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard char *msg; /* error message */ 71adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* lzma stream */ 729f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard int init; /* is the iniflate stream initialized */ 73adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard lzma_stream strm; /* stream structure in-place (not a pointer) */ 74adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard char padding1[32]; /* padding allowing to cope with possible 75adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard extensions of above structure without 76adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard too much side effect */ 776bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef HAVE_ZLIB_H 78adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* zlib inflate or deflate stream */ 79adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard z_stream zstrm; /* stream structure in-place (not a pointer) */ 806bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 81adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard char padding2[32]; /* padding allowing to cope with possible 82adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard extensions of above structure without 83adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard too much side effect */ 846bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} xz_state, *xz_statep; 856bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 86adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic void 87adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardxz_error(xz_statep state, int err, const char *msg) 886bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 896bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* free previously allocated message and clear */ 906bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->msg != NULL) { 916bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->err != LZMA_MEM_ERROR) 929f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->msg); 936bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->msg = NULL; 946bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 956bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 966bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* set error code, and if no message, then done */ 976bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->err = err; 986bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (msg == NULL) 996bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return; 1006bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 1016bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* for an out of memory error, save as static string */ 1026bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (err == LZMA_MEM_ERROR) { 103adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->msg = (char *) msg; 1046bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return; 1056bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 1066bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 1076bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* construct error message with path */ 108adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if ((state->msg = 1099f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlMalloc(strlen(state->path) + strlen(msg) + 3)) == NULL) { 1106bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->err = LZMA_MEM_ERROR; 111adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->msg = (char *) "out of memory"; 1126bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return; 1136bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 1146bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strcpy(state->msg, state->path); 1156bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strcat(state->msg, ": "); 1166bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strcat(state->msg, msg); 1176bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return; 1186bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 1196bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 120adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic void 121adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardxz_reset(xz_statep state) 1226bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 123adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->have = 0; /* no output data available */ 124adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->eof = 0; /* not at end of file */ 125adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->how = LOOK; /* look for gzip header */ 126adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->direct = 1; /* default for empty file */ 127adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->seek = 0; /* no seek request pending */ 128adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard xz_error(state, LZMA_OK, NULL); /* clear error */ 129adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->pos = 0; /* no uncompressed data yet */ 130adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.avail_in = 0; /* no input data yet */ 1316bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef HAVE_ZLIB_H 132adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->zstrm.avail_in = 0; /* no input data yet */ 1336bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 1346bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 1356bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 136adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic xzFile 137adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardxz_open(const char *path, int fd, const char *mode ATTRIBUTE_UNUSED) 1386bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 1396bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_statep state; 1406bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 1416bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* allocate xzFile structure to return */ 1429f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard state = xmlMalloc(sizeof(xz_state)); 1436bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state == NULL) 1446bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return NULL; 1456bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->size = 0; /* no buffers allocated yet */ 1466bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->want = BUFSIZ; /* requested buffer size */ 1476bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->msg = NULL; /* no error message yet */ 1489f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard state->init = 0; /* initialization of zlib data */ 1496bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 150adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* save the path name for error messages */ 1519f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard state->path = xmlMalloc(strlen(path) + 1); 1526bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->path == NULL) { 1539f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state); 1546bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return NULL; 1556bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 1566bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strcpy(state->path, path); 1576bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 1586bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* open the file with the appropriate mode (or just use fd) */ 159adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->fd = fd != -1 ? fd : open(path, 1606bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef O_LARGEFILE 161adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard O_LARGEFILE | 1626bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 1636bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef O_BINARY 164adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard O_BINARY | 1656bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 166adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard O_RDONLY, 0666); 1676bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->fd == -1) { 1689f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->path); 1699f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state); 1706bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return NULL; 1716bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 1726bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 1736bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* save the current position for rewinding (only if reading) */ 1746bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->start = lseek(state->fd, 0, SEEK_CUR); 175adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (state->start == (uint64_t) - 1) 176adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->start = 0; 1776bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 1786bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* initialize stream */ 1796bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_reset(state); 1806bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 1816bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* return stream */ 182adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return (xzFile) state; 1836bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 1846bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 185adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel VeillardxzFile 186adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard__libxml2_xzopen(const char *path, const char *mode) 1876bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 1886bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return xz_open(path, -1, mode); 1896bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 1906bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 191adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel VeillardxzFile 192adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard__libxml2_xzdopen(int fd, const char *mode) 1936bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 194adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard char *path; /* identifier for error messages */ 1956bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xzFile xz; 1966bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 1979f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard if (fd == -1 || (path = xmlMalloc(7 + 3 * sizeof(int))) == NULL) 1986bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return NULL; 199adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard sprintf(path, "<fd:%d>", fd); /* for debugging */ 2006bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz = xz_open(path, fd, mode); 2019f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(path); 2026bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return xz; 2036bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 2046bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 205adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic int 20672789ef21fed132bb15bd4e858cb524f41c79ed1Daniel Veillardxz_load(xz_statep state, unsigned char *buf, unsigned int len, 20772789ef21fed132bb15bd4e858cb524f41c79ed1Daniel Veillard unsigned int *have) 2086bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 2096bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund int ret; 2106bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 2116bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund *have = 0; 2126bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund do { 2136bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund ret = read(state->fd, buf + *have, len - *have); 2146bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (ret <= 0) 2156bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund break; 2166bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund *have += ret; 2176bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } while (*have < len); 2186bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (ret < 0) { 2196bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_error(state, -1, strerror(errno)); 2206bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 2216bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 2226bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (ret == 0) 2236bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->eof = 1; 2246bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 2256bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 2266bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 227adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic int 228adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardxz_avail(xz_statep state) 2296bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 2306bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream *strm = &(state->strm); 2316bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 2326bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->err != LZMA_OK) 2336bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 2346bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->eof == 0) { 235996449273fd4a8fc656d42088779e236d456e47aMarcus Meissner /* avail_in is size_t, which is not necessary sizeof(unsigned) */ 236996449273fd4a8fc656d42088779e236d456e47aMarcus Meissner unsigned tmp = strm->avail_in; 237996449273fd4a8fc656d42088779e236d456e47aMarcus Meissner 238996449273fd4a8fc656d42088779e236d456e47aMarcus Meissner if (xz_load(state, state->in, state->size, &tmp) == -1) { 239996449273fd4a8fc656d42088779e236d456e47aMarcus Meissner strm->avail_in = tmp; 2406bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 241996449273fd4a8fc656d42088779e236d456e47aMarcus Meissner } 242996449273fd4a8fc656d42088779e236d456e47aMarcus Meissner strm->avail_in = tmp; 2436bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->next_in = state->in; 2446bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 2456bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 2466bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 2476bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 2486bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklundstatic int 2496bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklundis_format_xz(xz_statep state) 2506bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 2516bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream *strm = &(state->strm); 2526bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 253adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return strm->avail_in >= 6 && memcmp(state->in, "\3757zXZ", 6) == 0; 2546bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 2556bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 2566bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklundstatic int 2576bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklundis_format_lzma(xz_statep state) 2586bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 2596bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream *strm = &(state->strm); 2606bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 261adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard lzma_filter filter; 262adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard lzma_options_lzma *opt; 263adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard uint32_t dict_size; 264adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard uint64_t uncompressed_size; 265adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard size_t i; 266adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 267adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (strm->avail_in < 13) 268adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return 0; 269adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 270adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard filter.id = LZMA_FILTER_LZMA1; 271adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (lzma_properties_decode(&filter, NULL, state->in, 5) != LZMA_OK) 272adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return 0; 273adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 274adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard opt = filter.options; 275adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard dict_size = opt->dict_size; 2769f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(opt); 277adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 278adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* A hack to ditch tons of false positives: We allow only dictionary 279adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * sizes that are 2^n or 2^n + 2^(n-1) or UINT32_MAX. LZMA_Alone 280adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * created only files with 2^n, but accepts any dictionary size. 281adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * If someone complains, this will be reconsidered. 282adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard */ 283adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (dict_size != UINT32_MAX) { 284adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard uint32_t d = dict_size - 1; 285adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 286adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard d |= d >> 2; 287adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard d |= d >> 3; 288adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard d |= d >> 4; 289adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard d |= d >> 8; 290adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard d |= d >> 16; 291adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard ++d; 292adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (d != dict_size || dict_size == 0) 293adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return 0; 294adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } 295adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 296adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* Another hack to ditch false positives: Assume that if the 297adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * uncompressed size is known, it must be less than 256 GiB. 298adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * Again, if someone complains, this will be reconsidered. 299adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard */ 300adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard uncompressed_size = 0; 301adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard for (i = 0; i < 8; ++i) 302adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard uncompressed_size |= (uint64_t) (state->in[5 + i]) << (i * 8); 303adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 304adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (uncompressed_size != UINT64_MAX 305adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard && uncompressed_size > (UINT64_C(1) << 38)) 306adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return 0; 307adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 308adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return 1; 3096bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 3106bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 3116bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef HAVE_ZLIB_H 312adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 3136bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund/* Get next byte from input, or -1 if end or error. */ 3146bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#define NEXT() ((strm->avail_in == 0 && xz_avail(state) == -1) ? -1 : \ 3156bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund (strm->avail_in == 0 ? -1 : \ 3166bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund (strm->avail_in--, *(strm->next_in)++))) 3176bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 3186bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund/* Get a four-byte little-endian integer and return 0 on success and the value 3196bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund in *ret. Otherwise -1 is returned and *ret is not modified. */ 320adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic int 321adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardgz_next4(xz_statep state, unsigned long *ret) 3226bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 3236bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund int ch; 3246bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund unsigned long val; 3256bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund z_streamp strm = &(state->zstrm); 3266bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 3276bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund val = NEXT(); 328adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard val += (unsigned) NEXT() << 8; 329adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard val += (unsigned long) NEXT() << 16; 3306bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund ch = NEXT(); 3316bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (ch == -1) 3326bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 333adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard val += (unsigned long) ch << 24; 3346bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund *ret = val; 3356bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 3366bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 3376bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 3386bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 339adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic int 340adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardxz_head(xz_statep state) 3416bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 3426bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream *strm = &(state->strm); 3436bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream init = LZMA_STREAM_INIT; 3446bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund int flags; 3456bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund unsigned len; 3466bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 3476bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* allocate read buffers and inflate memory */ 3486bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->size == 0) { 3496bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* allocate buffers */ 3509f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard state->in = xmlMalloc(state->want); 3519f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard state->out = xmlMalloc(state->want << 1); 3526bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->in == NULL || state->out == NULL) { 3536bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->out != NULL) 3549f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->out); 3556bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->in != NULL) 3569f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->in); 3576bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_error(state, LZMA_MEM_ERROR, "out of memory"); 3586bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 3596bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 3606bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->size = state->want; 3616bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 3626bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* allocate decoder memory */ 3636bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->strm = init; 3646bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->strm.avail_in = 0; 3656bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->strm.next_in = NULL; 3666bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (lzma_auto_decoder(&state->strm, UINT64_MAX, 0) != LZMA_OK) { 3679f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->out); 3689f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->in); 3696bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->size = 0; 3706bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_error(state, LZMA_MEM_ERROR, "out of memory"); 3716bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 372adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } 3736bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef HAVE_ZLIB_H 3746bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* allocate inflate memory */ 3756bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->zstrm.zalloc = Z_NULL; 3766bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->zstrm.zfree = Z_NULL; 3776bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->zstrm.opaque = Z_NULL; 3786bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->zstrm.avail_in = 0; 3796bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->zstrm.next_in = Z_NULL; 3809f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard if (state->init == 0) { 3819f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard if (inflateInit2(&(state->zstrm), -15) != Z_OK) {/* raw inflate */ 3829f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->out); 3839f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->in); 3849f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard state->size = 0; 3859f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xz_error(state, LZMA_MEM_ERROR, "out of memory"); 3869f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard return -1; 3879f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard } 3889f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard state->init = 1; 3896bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 3906bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 3916bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 3926bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 3936bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* get some data in the input buffer */ 3946bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->avail_in == 0) { 3956bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_avail(state) == -1) 3966bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 3976bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->avail_in == 0) 3986bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 3996bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 4006bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 401adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* look for the xz magic header bytes */ 4026bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (is_format_xz(state) || is_format_lzma(state)) { 403adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->how = LZMA; 404adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->direct = 0; 405adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return 0; 4066bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 4076bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef HAVE_ZLIB_H 408adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* look for the gzip magic header bytes 31 and 139 */ 4096bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->next_in[0] == 31) { 4106bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->avail_in--; 4116bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->next_in++; 4126bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->avail_in == 0 && xz_avail(state) == -1) 4136bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 4146bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->avail_in && strm->next_in[0] == 139) { 4156bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* we have a gzip header, woo hoo! */ 4166bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->avail_in--; 4176bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->next_in++; 4186bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 4196bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* skip rest of header */ 420adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (NEXT() != 8) { /* compression method */ 421adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard xz_error(state, LZMA_DATA_ERROR, 422adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard "unknown compression method"); 4236bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 4246bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 4256bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund flags = NEXT(); 426adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (flags & 0xe0) { /* reserved flag bits */ 427adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard xz_error(state, LZMA_DATA_ERROR, 428adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard "unknown header flags set"); 4296bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 4306bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 431adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard NEXT(); /* modification time */ 4326bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund NEXT(); 4336bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund NEXT(); 4346bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund NEXT(); 435adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard NEXT(); /* extra flags */ 436adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard NEXT(); /* operating system */ 437adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (flags & 4) { /* extra field */ 438adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard len = (unsigned) NEXT(); 439adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard len += (unsigned) NEXT() << 8; 4406bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund while (len--) 4416bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (NEXT() < 0) 4426bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund break; 4436bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 444adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (flags & 8) /* file name */ 445adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard while (NEXT() > 0) ; 446adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (flags & 16) /* comment */ 447adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard while (NEXT() > 0) ; 448adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (flags & 2) { /* header crc */ 4496bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund NEXT(); 4506bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund NEXT(); 4516bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 4526bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* an unexpected end of file is not checked for here -- it will be 453adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * noticed on the first request for uncompressed data */ 4546bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 4556bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* set up for decompression */ 4566bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund inflateReset(&state->zstrm); 4576bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->zstrm.adler = crc32(0L, Z_NULL, 0); 4586bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->how = GZIP; 4596bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->direct = 0; 4606bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 461adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } else { 4626bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* not a gzip file -- save first byte (31) and fall to raw i/o */ 4636bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->out[0] = 31; 4646bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->have = 1; 4656bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 4666bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 4676bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 4686bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 4696bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* doing raw i/o, save start of raw data for seeking, copy any leftover 470adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * input to output -- this assumes that the output buffer is larger than 471adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * the input buffer, which also assures space for gzungetc() */ 4726bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->raw = state->pos; 4736bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->next = state->out; 4746bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->avail_in) { 4756bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund memcpy(state->next + state->have, strm->next_in, strm->avail_in); 4766bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->have += strm->avail_in; 4776bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->avail_in = 0; 4786bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 4796bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->how = COPY; 4806bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->direct = 1; 4816bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 4826bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 4836bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 484adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic int 485adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardxz_decomp(xz_statep state) 4866bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 4876bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund int ret; 4886bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund unsigned had; 4896bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund unsigned long crc, len; 4906bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream *strm = &(state->strm); 4916bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 4926bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_action action = LZMA_RUN; 4936bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 4946bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* fill output buffer up to end of deflate stream */ 4956bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund had = strm->avail_out; 4966bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund do { 4976bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* get more input for inflate() */ 4986bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->avail_in == 0 && xz_avail(state) == -1) 4996bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 5006bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->avail_in == 0) { 5016bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_error(state, LZMA_DATA_ERROR, "unexpected end of file"); 5026bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 5036bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 5046bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->eof) 5056bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund action = LZMA_FINISH; 506adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 5076bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* decompress and handle errors */ 5086bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef HAVE_ZLIB_H 5096bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->how == GZIP) { 510adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->zstrm.avail_in = (uInt) state->strm.avail_in; 511adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->zstrm.next_in = (Bytef *) state->strm.next_in; 512adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->zstrm.avail_out = (uInt) state->strm.avail_out; 513adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->zstrm.next_out = (Bytef *) state->strm.next_out; 514adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard ret = inflate(&state->zstrm, Z_NO_FLUSH); 515adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { 516adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard xz_error(state, Z_STREAM_ERROR, 517adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard "internal error: inflate stream corrupt"); 518adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return -1; 519adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } 520adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (ret == Z_MEM_ERROR) 521adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard ret = LZMA_MEM_ERROR; 522adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (ret == Z_DATA_ERROR) 523adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard ret = LZMA_DATA_ERROR; 524adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (ret == Z_STREAM_END) 525adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard ret = LZMA_STREAM_END; 526adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.avail_in = state->zstrm.avail_in; 527adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.next_in = state->zstrm.next_in; 528adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.avail_out = state->zstrm.avail_out; 529adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.next_out = state->zstrm.next_out; 530adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } else /* state->how == LZMA */ 5316bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 532adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard ret = lzma_code(strm, action); 5336bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (ret == LZMA_MEM_ERROR) { 5346bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_error(state, LZMA_MEM_ERROR, "out of memory"); 5356bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 5366bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 5376bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (ret == LZMA_DATA_ERROR) { 5386bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_error(state, LZMA_DATA_ERROR, "compressed data error"); 5396bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 5406bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 5416bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } while (strm->avail_out && ret != LZMA_STREAM_END); 5426bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 5436bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* update available output and crc check value */ 5446bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->have = had - strm->avail_out; 5456bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->next = strm->next_out - state->have; 5466bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef HAVE_ZLIB_H 547adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->zstrm.adler = 548adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard crc32(state->zstrm.adler, state->next, state->have); 5496bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 5506bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 5516bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (ret == LZMA_STREAM_END) { 5526bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef HAVE_ZLIB_H 5536bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->how == GZIP) { 554adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) { 555adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard xz_error(state, LZMA_DATA_ERROR, "unexpected end of file"); 556adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return -1; 557adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } 558adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (crc != state->zstrm.adler) { 559adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard xz_error(state, LZMA_DATA_ERROR, "incorrect data check"); 560adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return -1; 561adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } 562adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (len != (state->zstrm.total_out & 0xffffffffL)) { 563adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard xz_error(state, LZMA_DATA_ERROR, "incorrect length check"); 564adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return -1; 565adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } 566adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.avail_in = 0; 567adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.next_in = NULL; 568adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.avail_out = 0; 569adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.next_out = NULL; 570adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } else 5716bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 572adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (strm->avail_in != 0 || !state->eof) { 5736bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_error(state, LZMA_DATA_ERROR, "trailing garbage"); 5746bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 5756bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 5766bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->how = LOOK; /* ready for next stream, once have is 0 (leave 577adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * state->direct unchanged to remember how) */ 5786bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 5796bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 5806bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* good decompression */ 5816bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 5826bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 5836bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 584adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic int 585adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardxz_make(xz_statep state) 5866bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 5876bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream *strm = &(state->strm); 5886bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 589adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (state->how == LOOK) { /* look for lzma / gzip header */ 5906bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_head(state) == -1) 5916bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 592adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (state->have) /* got some data from xz_head() */ 5936bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 5946bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 595adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (state->how == COPY) { /* straight copy */ 596adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (xz_load(state, state->out, state->size << 1, &(state->have)) == 597adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard -1) 5986bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 5996bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->next = state->out; 600adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } else if (state->how == LZMA || state->how == GZIP) { /* decompress */ 6016bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->avail_out = state->size << 1; 6026bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->next_out = state->out; 6036bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_decomp(state) == -1) 6046bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 6056bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 6066bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 6076bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 6086bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 609adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic int 610adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardxz_skip(xz_statep state, uint64_t len) 6116bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 6126bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund unsigned n; 6136bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 6146bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* skip over len bytes or reach end-of-file, whichever comes first */ 6156bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund while (len) 6166bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* skip over whatever is in output buffer */ 6176bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->have) { 618adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard n = (uint64_t) state->have > len ? 619adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard (unsigned) len : state->have; 6206bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->have -= n; 6216bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->next += n; 6226bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->pos += n; 6236bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund len -= n; 6246bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 6256bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 626adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* output buffer empty -- return if we're at the end of the input */ 6276bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund else if (state->eof && state->strm.avail_in == 0) 6286bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund break; 6296bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 630adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* need more data to skip -- load up output buffer */ 6316bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund else { 6326bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* get more output, looking for header if required */ 6336bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_make(state) == -1) 6346bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 6356bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 6366bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 6376bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 6386bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 639adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardint 640adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard__libxml2_xzread(xzFile file, void *buf, unsigned len) 6416bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 6426bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund unsigned got, n; 6436bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_statep state; 6446bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream *strm; 6456bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 6466bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* get internal structure */ 6476bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (file == NULL) 6486bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 649adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state = (xz_statep) file; 6506bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm = &(state->strm); 6516bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 6526bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* check that we're reading and that there's no error */ 6536bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->err != LZMA_OK) 6546bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 6556bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 6566bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* since an int is returned, make sure len fits in one, otherwise return 657adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * with an error (this avoids the flaw in the interface) */ 658adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if ((int) len < 0) { 659adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard xz_error(state, LZMA_BUF_ERROR, 660adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard "requested length does not fit in int"); 6616bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 6626bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 6636bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 6646bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* if len is zero, avoid unnecessary operations */ 6656bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (len == 0) 6666bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 6676bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 6686bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* process a skip request */ 6696bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->seek) { 6706bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->seek = 0; 6716bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_skip(state, state->skip) == -1) 6726bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 6736bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 6746bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 6756bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* get len bytes to buf, or less than len if at the end */ 6766bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund got = 0; 6776bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund do { 6786bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* first just try copying data from the output buffer */ 6796bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->have) { 6806bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund n = state->have > len ? len : state->have; 6816bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund memcpy(buf, state->next, n); 6826bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->next += n; 6836bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->have -= n; 6846bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 6856bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 6866bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* output buffer empty -- return if we're at the end of the input */ 6876bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund else if (state->eof && strm->avail_in == 0) 6886bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund break; 6896bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 6906bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* need output data -- for small len or new stream load up our output 691adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * buffer */ 6926bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund else if (state->how == LOOK || len < (state->size << 1)) { 6936bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* get more output, looking for header if required */ 6946bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_make(state) == -1) 6956bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 696adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard continue; /* no progress yet -- go back to memcpy() above */ 6976bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* the copy above assures that we will leave with space in the 698adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * output buffer, allowing at least one gzungetc() to succeed */ 6996bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 7006bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7016bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* large len -- read directly into user buffer */ 702adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard else if (state->how == COPY) { /* read directly */ 7036bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_load(state, buf, len, &n) == -1) 7046bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 7056bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 7066bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7076bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* large len -- decompress directly into user buffer */ 708adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard else { /* state->how == LZMA */ 7096bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->avail_out = len; 7106bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->next_out = buf; 7116bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_decomp(state) == -1) 7126bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 7136bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund n = state->have; 7146bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->have = 0; 7156bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 7166bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7176bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* update progress */ 7186bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund len -= n; 719adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard buf = (char *) buf + n; 7206bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund got += n; 7216bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->pos += n; 7226bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } while (len); 7236bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7246bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* return number of bytes read into user buffer (will fit in int) */ 725adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return (int) got; 7266bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 7276bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 728adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardint 729adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard__libxml2_xzclose(xzFile file) 7306bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 7316bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund int ret; 7326bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_statep state; 7336bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7346bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* get internal structure */ 7356bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (file == NULL) 7366bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return LZMA_DATA_ERROR; 737adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state = (xz_statep) file; 7386bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7396bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* free memory and close file */ 7406bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->size) { 7416bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_end(&(state->strm)); 7429f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard#ifdef HAVE_ZLIB_H 7439f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard if (state->init == 1) 7449f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard inflateEnd(&(state->zstrm)); 7459f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard state->init = 0; 7466bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 7479f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->out); 7489f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->in); 7496bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 7509f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->path); 7516bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund ret = close(state->fd); 7529f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state); 7536bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return ret ? ret : LZMA_OK; 7546bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 755adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#endif /* HAVE_LZMA_H */ 756