xzlib.c revision f0709e3ca8f8947f2d91ed34e92e38a4c23eae63
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 18563588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillardstatic int 18663588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillardxz_compressed(xzFile f) { 18763588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard xz_statep state; 18863588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard 18963588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard if (f == NULL) 19063588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard return(-1); 19163588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard state = (xz_statep) f; 19263588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard if (state->init <= 0) 19363588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard return(-1); 19463588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard 19563588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard switch (state->how) { 19663588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard case COPY: 19763588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard return(0); 19863588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard case GZIP: 19963588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard case LZMA: 20063588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard return(1); 20163588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard } 20263588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard return(-1); 20363588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard} 20463588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard 205adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel VeillardxzFile 206adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard__libxml2_xzopen(const char *path, const char *mode) 2076bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 2086bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return xz_open(path, -1, mode); 2096bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 2106bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 21163588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillardint 21263588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard__libxml2_xzcompressed(xzFile f) { 21363588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard return xz_compressed(f); 21463588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard} 21563588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard 216adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel VeillardxzFile 217adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard__libxml2_xzdopen(int fd, const char *mode) 2186bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 219adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard char *path; /* identifier for error messages */ 2206bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xzFile xz; 2216bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 2229f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard if (fd == -1 || (path = xmlMalloc(7 + 3 * sizeof(int))) == NULL) 2236bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return NULL; 224adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard sprintf(path, "<fd:%d>", fd); /* for debugging */ 2256bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz = xz_open(path, fd, mode); 2269f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(path); 2276bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return xz; 2286bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 2296bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 230adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic int 23172789ef21fed132bb15bd4e858cb524f41c79ed1Daniel Veillardxz_load(xz_statep state, unsigned char *buf, unsigned int len, 23272789ef21fed132bb15bd4e858cb524f41c79ed1Daniel Veillard unsigned int *have) 2336bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 2346bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund int ret; 2356bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 2366bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund *have = 0; 2376bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund do { 2386bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund ret = read(state->fd, buf + *have, len - *have); 2396bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (ret <= 0) 2406bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund break; 2416bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund *have += ret; 2426bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } while (*have < len); 2436bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (ret < 0) { 2446bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_error(state, -1, strerror(errno)); 2456bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 2466bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 2476bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (ret == 0) 2486bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->eof = 1; 2496bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 2506bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 2516bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 252adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic int 253adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardxz_avail(xz_statep state) 2546bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 2556bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream *strm = &(state->strm); 2566bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 2576bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->err != LZMA_OK) 2586bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 2596bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->eof == 0) { 260996449273fd4a8fc656d42088779e236d456e47aMarcus Meissner /* avail_in is size_t, which is not necessary sizeof(unsigned) */ 261996449273fd4a8fc656d42088779e236d456e47aMarcus Meissner unsigned tmp = strm->avail_in; 262996449273fd4a8fc656d42088779e236d456e47aMarcus Meissner 263996449273fd4a8fc656d42088779e236d456e47aMarcus Meissner if (xz_load(state, state->in, state->size, &tmp) == -1) { 264996449273fd4a8fc656d42088779e236d456e47aMarcus Meissner strm->avail_in = tmp; 2656bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 266996449273fd4a8fc656d42088779e236d456e47aMarcus Meissner } 267996449273fd4a8fc656d42088779e236d456e47aMarcus Meissner strm->avail_in = tmp; 2686bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->next_in = state->in; 2696bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 2706bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 2716bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 2726bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 273a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander#ifdef HAVE_ZLIB_H 274a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexanderstatic int 275a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexanderxz_avail_zstrm(xz_statep state) 276a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander{ 277a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander int ret; 278a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander state->strm.avail_in = state->zstrm.avail_in; 279a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander state->strm.next_in = state->zstrm.next_in; 280a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander ret = xz_avail(state); 281a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander state->zstrm.avail_in = (uInt) state->strm.avail_in; 282a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander state->zstrm.next_in = (Bytef *) state->strm.next_in; 283a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander return ret; 284a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander} 285a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander#endif 286a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander 2876bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklundstatic int 2886bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklundis_format_xz(xz_statep state) 2896bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 2906bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream *strm = &(state->strm); 2916bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 292adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return strm->avail_in >= 6 && memcmp(state->in, "\3757zXZ", 6) == 0; 2936bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 2946bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 2956bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklundstatic int 2966bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklundis_format_lzma(xz_statep state) 2976bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 2986bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream *strm = &(state->strm); 2996bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 300adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard lzma_filter filter; 301adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard lzma_options_lzma *opt; 302adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard uint32_t dict_size; 303adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard uint64_t uncompressed_size; 304adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard size_t i; 305adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 306adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (strm->avail_in < 13) 307adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return 0; 308adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 309adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard filter.id = LZMA_FILTER_LZMA1; 310adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (lzma_properties_decode(&filter, NULL, state->in, 5) != LZMA_OK) 311adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return 0; 312adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 313adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard opt = filter.options; 314adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard dict_size = opt->dict_size; 31594431ecba6c458c56cb0f5b2a919ed4cf27107baDaniel Veillard free(opt); /* we can't use xmlFree on a string returned by zlib */ 316adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 317adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* A hack to ditch tons of false positives: We allow only dictionary 318adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * sizes that are 2^n or 2^n + 2^(n-1) or UINT32_MAX. LZMA_Alone 319adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * created only files with 2^n, but accepts any dictionary size. 320adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * If someone complains, this will be reconsidered. 321adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard */ 322adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (dict_size != UINT32_MAX) { 323adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard uint32_t d = dict_size - 1; 324adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 325adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard d |= d >> 2; 326adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard d |= d >> 3; 327adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard d |= d >> 4; 328adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard d |= d >> 8; 329adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard d |= d >> 16; 330adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard ++d; 331adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (d != dict_size || dict_size == 0) 332adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return 0; 333adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } 334adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 335adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* Another hack to ditch false positives: Assume that if the 336adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * uncompressed size is known, it must be less than 256 GiB. 337adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * Again, if someone complains, this will be reconsidered. 338adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard */ 339adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard uncompressed_size = 0; 340adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard for (i = 0; i < 8; ++i) 341adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard uncompressed_size |= (uint64_t) (state->in[5 + i]) << (i * 8); 342adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 343adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (uncompressed_size != UINT64_MAX 344adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard && uncompressed_size > (UINT64_C(1) << 38)) 345adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return 0; 346adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 347adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return 1; 3486bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 3496bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 3506bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef HAVE_ZLIB_H 351adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 3526bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund/* Get next byte from input, or -1 if end or error. */ 3536bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#define NEXT() ((strm->avail_in == 0 && xz_avail(state) == -1) ? -1 : \ 3546bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund (strm->avail_in == 0 ? -1 : \ 3556bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund (strm->avail_in--, *(strm->next_in)++))) 356a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander/* Same thing, but from zstrm */ 357a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander#define NEXTZ() ((strm->avail_in == 0 && xz_avail_zstrm(state) == -1) ? -1 : \ 358a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander (strm->avail_in == 0 ? -1 : \ 359a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander (strm->avail_in--, *(strm->next_in)++))) 3606bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 3616bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund/* Get a four-byte little-endian integer and return 0 on success and the value 3626bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund in *ret. Otherwise -1 is returned and *ret is not modified. */ 363adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic int 364adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardgz_next4(xz_statep state, unsigned long *ret) 3656bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 3666bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund int ch; 3676bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund unsigned long val; 3686bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund z_streamp strm = &(state->zstrm); 3696bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 370a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander val = NEXTZ(); 371a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander val += (unsigned) NEXTZ() << 8; 372a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander val += (unsigned long) NEXTZ() << 16; 373a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander ch = NEXTZ(); 3746bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (ch == -1) 3756bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 376adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard val += (unsigned long) ch << 24; 3776bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund *ret = val; 3786bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 3796bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 3806bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 3816bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 382adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic int 383adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardxz_head(xz_statep state) 3846bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 3856bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream *strm = &(state->strm); 3866bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream init = LZMA_STREAM_INIT; 3876bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund int flags; 3886bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund unsigned len; 3896bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 3906bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* allocate read buffers and inflate memory */ 3916bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->size == 0) { 3926bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* allocate buffers */ 3939f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard state->in = xmlMalloc(state->want); 3949f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard state->out = xmlMalloc(state->want << 1); 3956bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->in == NULL || state->out == NULL) { 3966bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->out != NULL) 3979f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->out); 3986bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->in != NULL) 3999f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->in); 4006bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_error(state, LZMA_MEM_ERROR, "out of memory"); 4016bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 4026bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 4036bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->size = state->want; 4046bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 4056bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* allocate decoder memory */ 4066bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->strm = init; 4076bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->strm.avail_in = 0; 4086bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->strm.next_in = NULL; 4096bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (lzma_auto_decoder(&state->strm, UINT64_MAX, 0) != LZMA_OK) { 4109f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->out); 4119f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->in); 4126bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->size = 0; 4136bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_error(state, LZMA_MEM_ERROR, "out of memory"); 4146bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 415adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } 4166bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef HAVE_ZLIB_H 4176bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* allocate inflate memory */ 4186bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->zstrm.zalloc = Z_NULL; 4196bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->zstrm.zfree = Z_NULL; 4206bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->zstrm.opaque = Z_NULL; 4216bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->zstrm.avail_in = 0; 4226bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->zstrm.next_in = Z_NULL; 4239f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard if (state->init == 0) { 4249f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard if (inflateInit2(&(state->zstrm), -15) != Z_OK) {/* raw inflate */ 4259f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->out); 4269f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->in); 4279f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard state->size = 0; 4289f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xz_error(state, LZMA_MEM_ERROR, "out of memory"); 4299f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard return -1; 4309f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard } 4319f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard state->init = 1; 4326bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 4336bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 4346bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 4356bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 4366bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* get some data in the input buffer */ 4376bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->avail_in == 0) { 4386bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_avail(state) == -1) 4396bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 4406bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->avail_in == 0) 4416bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 4426bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 4436bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 444adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* look for the xz magic header bytes */ 4456bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (is_format_xz(state) || is_format_lzma(state)) { 446adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->how = LZMA; 447adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->direct = 0; 448adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return 0; 4496bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 4506bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef HAVE_ZLIB_H 451adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* look for the gzip magic header bytes 31 and 139 */ 4526bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->next_in[0] == 31) { 4536bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->avail_in--; 4546bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->next_in++; 4556bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->avail_in == 0 && xz_avail(state) == -1) 4566bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 4576bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->avail_in && strm->next_in[0] == 139) { 4586bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* we have a gzip header, woo hoo! */ 4596bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->avail_in--; 4606bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->next_in++; 4616bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 4626bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* skip rest of header */ 463adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (NEXT() != 8) { /* compression method */ 464adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard xz_error(state, LZMA_DATA_ERROR, 465adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard "unknown compression method"); 4666bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 4676bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 4686bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund flags = NEXT(); 469adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (flags & 0xe0) { /* reserved flag bits */ 470adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard xz_error(state, LZMA_DATA_ERROR, 471adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard "unknown header flags set"); 4726bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 4736bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 474adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard NEXT(); /* modification time */ 4756bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund NEXT(); 4766bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund NEXT(); 4776bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund NEXT(); 478adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard NEXT(); /* extra flags */ 479adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard NEXT(); /* operating system */ 480adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (flags & 4) { /* extra field */ 481adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard len = (unsigned) NEXT(); 482adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard len += (unsigned) NEXT() << 8; 4836bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund while (len--) 4846bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (NEXT() < 0) 4856bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund break; 4866bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 487adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (flags & 8) /* file name */ 488adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard while (NEXT() > 0) ; 489adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (flags & 16) /* comment */ 490adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard while (NEXT() > 0) ; 491adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (flags & 2) { /* header crc */ 4926bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund NEXT(); 4936bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund NEXT(); 4946bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 4956bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* an unexpected end of file is not checked for here -- it will be 496adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * noticed on the first request for uncompressed data */ 4976bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 4986bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* set up for decompression */ 4996bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund inflateReset(&state->zstrm); 5006bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->zstrm.adler = crc32(0L, Z_NULL, 0); 5016bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->how = GZIP; 5026bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->direct = 0; 5036bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 504adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } else { 5056bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* not a gzip file -- save first byte (31) and fall to raw i/o */ 5066bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->out[0] = 31; 5076bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->have = 1; 5086bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 5096bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 5106bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 5116bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 5126bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* doing raw i/o, save start of raw data for seeking, copy any leftover 513adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * input to output -- this assumes that the output buffer is larger than 514adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * the input buffer, which also assures space for gzungetc() */ 5156bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->raw = state->pos; 5166bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->next = state->out; 5176bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->avail_in) { 5186bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund memcpy(state->next + state->have, strm->next_in, strm->avail_in); 5196bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->have += strm->avail_in; 5206bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->avail_in = 0; 5216bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 5226bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->how = COPY; 5236bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->direct = 1; 5246bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 5256bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 5266bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 527adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic int 528adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardxz_decomp(xz_statep state) 5296bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 5306bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund int ret; 5316bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund unsigned had; 5326bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund unsigned long crc, len; 5336bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream *strm = &(state->strm); 5346bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 5356bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_action action = LZMA_RUN; 5366bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 5376bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* fill output buffer up to end of deflate stream */ 5386bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund had = strm->avail_out; 5396bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund do { 5406bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* get more input for inflate() */ 5416bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->avail_in == 0 && xz_avail(state) == -1) 5426bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 5436bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->avail_in == 0) { 5446bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_error(state, LZMA_DATA_ERROR, "unexpected end of file"); 5456bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 5466bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 5476bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->eof) 5486bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund action = LZMA_FINISH; 549adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 5506bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* decompress and handle errors */ 5516bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef HAVE_ZLIB_H 5526bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->how == GZIP) { 553adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->zstrm.avail_in = (uInt) state->strm.avail_in; 554adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->zstrm.next_in = (Bytef *) state->strm.next_in; 555adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->zstrm.avail_out = (uInt) state->strm.avail_out; 556adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->zstrm.next_out = (Bytef *) state->strm.next_out; 557adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard ret = inflate(&state->zstrm, Z_NO_FLUSH); 558adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { 559adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard xz_error(state, Z_STREAM_ERROR, 560adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard "internal error: inflate stream corrupt"); 561adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return -1; 562adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } 563adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (ret == Z_MEM_ERROR) 564adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard ret = LZMA_MEM_ERROR; 565adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (ret == Z_DATA_ERROR) 566adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard ret = LZMA_DATA_ERROR; 567adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (ret == Z_STREAM_END) 568adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard ret = LZMA_STREAM_END; 569adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.avail_in = state->zstrm.avail_in; 570adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.next_in = state->zstrm.next_in; 571adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.avail_out = state->zstrm.avail_out; 572adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.next_out = state->zstrm.next_out; 573adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } else /* state->how == LZMA */ 5746bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 575adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard ret = lzma_code(strm, action); 5766bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (ret == LZMA_MEM_ERROR) { 5776bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_error(state, LZMA_MEM_ERROR, "out of memory"); 5786bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 5796bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 5806bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (ret == LZMA_DATA_ERROR) { 5816bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_error(state, LZMA_DATA_ERROR, "compressed data error"); 5826bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 5836bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 584f0709e3ca8f8947f2d91ed34e92e38a4c23eae63Daniel Veillard if (ret == LZMA_PROG_ERROR) { 585f0709e3ca8f8947f2d91ed34e92e38a4c23eae63Daniel Veillard xz_error(state, LZMA_PROG_ERROR, "compression error"); 586f0709e3ca8f8947f2d91ed34e92e38a4c23eae63Daniel Veillard return -1; 587f0709e3ca8f8947f2d91ed34e92e38a4c23eae63Daniel Veillard } 5886bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } while (strm->avail_out && ret != LZMA_STREAM_END); 5896bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 5906bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* update available output and crc check value */ 5916bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->have = had - strm->avail_out; 5926bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->next = strm->next_out - state->have; 5936bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef HAVE_ZLIB_H 594adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->zstrm.adler = 595adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard crc32(state->zstrm.adler, state->next, state->have); 5966bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 5976bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 5986bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (ret == LZMA_STREAM_END) { 5996bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef HAVE_ZLIB_H 6006bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->how == GZIP) { 601adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) { 602adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard xz_error(state, LZMA_DATA_ERROR, "unexpected end of file"); 603adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return -1; 604adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } 605adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (crc != state->zstrm.adler) { 606adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard xz_error(state, LZMA_DATA_ERROR, "incorrect data check"); 607adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return -1; 608adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } 609adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (len != (state->zstrm.total_out & 0xffffffffL)) { 610adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard xz_error(state, LZMA_DATA_ERROR, "incorrect length check"); 611adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return -1; 612adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } 613adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.avail_in = 0; 614adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.next_in = NULL; 615adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.avail_out = 0; 616adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.next_out = NULL; 617adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } else 6186bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 619adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (strm->avail_in != 0 || !state->eof) { 6206bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_error(state, LZMA_DATA_ERROR, "trailing garbage"); 6216bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 6226bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 6236bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->how = LOOK; /* ready for next stream, once have is 0 (leave 624adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * state->direct unchanged to remember how) */ 6256bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 6266bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 6276bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* good decompression */ 6286bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 6296bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 6306bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 631adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic int 632adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardxz_make(xz_statep state) 6336bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 6346bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream *strm = &(state->strm); 6356bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 636adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (state->how == LOOK) { /* look for lzma / gzip header */ 6376bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_head(state) == -1) 6386bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 639adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (state->have) /* got some data from xz_head() */ 6406bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 6416bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 642adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (state->how == COPY) { /* straight copy */ 643adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (xz_load(state, state->out, state->size << 1, &(state->have)) == 644adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard -1) 6456bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 6466bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->next = state->out; 647adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } else if (state->how == LZMA || state->how == GZIP) { /* decompress */ 6486bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->avail_out = state->size << 1; 6496bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->next_out = state->out; 6506bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_decomp(state) == -1) 6516bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 6526bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 6536bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 6546bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 6556bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 656adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic int 657adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardxz_skip(xz_statep state, uint64_t len) 6586bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 6596bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund unsigned n; 6606bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 6616bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* skip over len bytes or reach end-of-file, whichever comes first */ 6626bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund while (len) 6636bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* skip over whatever is in output buffer */ 6646bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->have) { 665adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard n = (uint64_t) state->have > len ? 666adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard (unsigned) len : state->have; 6676bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->have -= n; 6686bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->next += n; 6696bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->pos += n; 6706bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund len -= n; 6716bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 6726bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 673adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* output buffer empty -- return if we're at the end of the input */ 6746bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund else if (state->eof && state->strm.avail_in == 0) 6756bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund break; 6766bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 677adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* need more data to skip -- load up output buffer */ 6786bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund else { 6796bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* get more output, looking for header if required */ 6806bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_make(state) == -1) 6816bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 6826bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 6836bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 6846bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 6856bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 686adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardint 687adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard__libxml2_xzread(xzFile file, void *buf, unsigned len) 6886bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 6896bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund unsigned got, n; 6906bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_statep state; 6916bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream *strm; 6926bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 6936bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* get internal structure */ 6946bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (file == NULL) 6956bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 696adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state = (xz_statep) file; 6976bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm = &(state->strm); 6986bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 6996bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* check that we're reading and that there's no error */ 7006bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->err != LZMA_OK) 7016bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 7026bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7036bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* since an int is returned, make sure len fits in one, otherwise return 704adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * with an error (this avoids the flaw in the interface) */ 705adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if ((int) len < 0) { 706adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard xz_error(state, LZMA_BUF_ERROR, 707adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard "requested length does not fit in int"); 7086bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 7096bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 7106bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7116bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* if len is zero, avoid unnecessary operations */ 7126bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (len == 0) 7136bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 7146bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7156bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* process a skip request */ 7166bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->seek) { 7176bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->seek = 0; 7186bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_skip(state, state->skip) == -1) 7196bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 7206bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 7216bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7226bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* get len bytes to buf, or less than len if at the end */ 7236bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund got = 0; 7246bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund do { 7256bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* first just try copying data from the output buffer */ 7266bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->have) { 7276bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund n = state->have > len ? len : state->have; 7286bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund memcpy(buf, state->next, n); 7296bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->next += n; 7306bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->have -= n; 7316bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 7326bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7336bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* output buffer empty -- return if we're at the end of the input */ 7346bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund else if (state->eof && strm->avail_in == 0) 7356bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund break; 7366bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7376bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* need output data -- for small len or new stream load up our output 738adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * buffer */ 7396bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund else if (state->how == LOOK || len < (state->size << 1)) { 7406bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* get more output, looking for header if required */ 7416bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_make(state) == -1) 7426bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 743adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard continue; /* no progress yet -- go back to memcpy() above */ 7446bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* the copy above assures that we will leave with space in the 745adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * output buffer, allowing at least one gzungetc() to succeed */ 7466bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 7476bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7486bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* large len -- read directly into user buffer */ 749adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard else if (state->how == COPY) { /* read directly */ 7506bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_load(state, buf, len, &n) == -1) 7516bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 7526bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 7536bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7546bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* large len -- decompress directly into user buffer */ 755adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard else { /* state->how == LZMA */ 7566bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->avail_out = len; 7576bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->next_out = buf; 7586bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_decomp(state) == -1) 7596bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 7606bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund n = state->have; 7616bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->have = 0; 7626bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 7636bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7646bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* update progress */ 7656bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund len -= n; 766adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard buf = (char *) buf + n; 7676bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund got += n; 7686bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->pos += n; 7696bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } while (len); 7706bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7716bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* return number of bytes read into user buffer (will fit in int) */ 772adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return (int) got; 7736bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 7746bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 775adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardint 776adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard__libxml2_xzclose(xzFile file) 7776bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 7786bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund int ret; 7796bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_statep state; 7806bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7816bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* get internal structure */ 7826bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (file == NULL) 7836bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return LZMA_DATA_ERROR; 784adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state = (xz_statep) file; 7856bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7866bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* free memory and close file */ 7876bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->size) { 7886bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_end(&(state->strm)); 7899f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard#ifdef HAVE_ZLIB_H 7909f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard if (state->init == 1) 7919f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard inflateEnd(&(state->zstrm)); 7929f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard state->init = 0; 7936bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 7949f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->out); 7959f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->in); 7966bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 7979f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->path); 7986bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund ret = close(state->fd); 7999f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state); 8006bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return ret ? ret : LZMA_OK; 8016bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 802adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#endif /* HAVE_LZMA_H */ 803