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" 1118b8988511b0954272cac4d6c3e6724f9dbf6e0aDaniel Veillard#ifdef LIBXML_LZMA_ENABLED 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 3718b8988511b0954272cac4d6c3e6724f9dbf6e0aDaniel Veillard#ifdef HAVE_LZMA_H 38adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#include <lzma.h> 3918b8988511b0954272cac4d6c3e6724f9dbf6e0aDaniel Veillard#endif 40adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 416bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#include "xzlib.h" 429f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard#include <libxml/xmlmemory.h> 436bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 446bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund/* values for xz_state how */ 45adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#define LOOK 0 /* look for a gzip/lzma header */ 46adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#define COPY 1 /* copy input directly */ 47adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#define GZIP 2 /* decompress a gzip stream */ 48adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard#define LZMA 3 /* decompress a lzma stream */ 496bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 506bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund/* internal lzma file state data structure */ 516bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklundtypedef struct { 52adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard int mode; /* see lzma modes above */ 53adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard int fd; /* file descriptor */ 54adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard char *path; /* path or fd for error messages */ 55adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard uint64_t pos; /* current position in uncompressed data */ 5672789ef21fed132bb15bd4e858cb524f41c79ed1Daniel Veillard unsigned int size; /* buffer size, zero if not allocated yet */ 5772789ef21fed132bb15bd4e858cb524f41c79ed1Daniel Veillard unsigned int want; /* requested buffer size, default is BUFSIZ */ 58adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard unsigned char *in; /* input buffer */ 59adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard unsigned char *out; /* output buffer (double-sized when reading) */ 60adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard unsigned char *next; /* next output data to deliver or write */ 6172789ef21fed132bb15bd4e858cb524f41c79ed1Daniel Veillard unsigned int have; /* amount of output data unused at next */ 62adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard int eof; /* true if end of input file reached */ 63adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard uint64_t start; /* where the lzma data started, for rewinding */ 64adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard uint64_t raw; /* where the raw data started, for seeking */ 65adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard int how; /* 0: get header, 1: copy, 2: decompress */ 66adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard int direct; /* true if last read direct, false if lzma */ 67adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* seek request */ 68adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard uint64_t skip; /* amount to skip (already rewound if backwards) */ 69adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard int seek; /* true if seek request pending */ 70adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* error information */ 71adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard int err; /* error code */ 72adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard char *msg; /* error message */ 73adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* lzma stream */ 749f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard int init; /* is the iniflate stream initialized */ 75adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard lzma_stream strm; /* stream structure in-place (not a pointer) */ 76adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard char padding1[32]; /* padding allowing to cope with possible 77adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard extensions of above structure without 78adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard too much side effect */ 796bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef HAVE_ZLIB_H 80adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* zlib inflate or deflate stream */ 81adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard z_stream zstrm; /* stream structure in-place (not a pointer) */ 826bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 83adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard char padding2[32]; /* padding allowing to cope with possible 84adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard extensions of above structure without 85adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard too much side effect */ 866bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} xz_state, *xz_statep; 876bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 88adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic void 89adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardxz_error(xz_statep state, int err, const char *msg) 906bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 916bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* free previously allocated message and clear */ 926bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->msg != NULL) { 936bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->err != LZMA_MEM_ERROR) 949f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->msg); 956bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->msg = NULL; 966bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 976bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 986bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* set error code, and if no message, then done */ 996bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->err = err; 1006bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (msg == NULL) 1016bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return; 1026bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 1036bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* for an out of memory error, save as static string */ 1046bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (err == LZMA_MEM_ERROR) { 105adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->msg = (char *) msg; 1066bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return; 1076bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 1086bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 1096bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* construct error message with path */ 110adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if ((state->msg = 1119f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlMalloc(strlen(state->path) + strlen(msg) + 3)) == NULL) { 1126bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->err = LZMA_MEM_ERROR; 113adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->msg = (char *) "out of memory"; 1146bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return; 1156bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 1166bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strcpy(state->msg, state->path); 1176bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strcat(state->msg, ": "); 1186bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strcat(state->msg, msg); 1196bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return; 1206bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 1216bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 122adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic void 123adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardxz_reset(xz_statep state) 1246bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 125adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->have = 0; /* no output data available */ 126adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->eof = 0; /* not at end of file */ 127adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->how = LOOK; /* look for gzip header */ 128adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->direct = 1; /* default for empty file */ 129adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->seek = 0; /* no seek request pending */ 130adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard xz_error(state, LZMA_OK, NULL); /* clear error */ 131adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->pos = 0; /* no uncompressed data yet */ 132adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.avail_in = 0; /* no input data yet */ 1336bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef HAVE_ZLIB_H 134adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->zstrm.avail_in = 0; /* no input data yet */ 1356bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 1366bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 1376bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 138adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic xzFile 139adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardxz_open(const char *path, int fd, const char *mode ATTRIBUTE_UNUSED) 1406bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 1416bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_statep state; 1426bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 1436bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* allocate xzFile structure to return */ 1449f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard state = xmlMalloc(sizeof(xz_state)); 1456bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state == NULL) 1466bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return NULL; 1476bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->size = 0; /* no buffers allocated yet */ 1486bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->want = BUFSIZ; /* requested buffer size */ 1496bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->msg = NULL; /* no error message yet */ 1509f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard state->init = 0; /* initialization of zlib data */ 1516bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 152adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* save the path name for error messages */ 1539f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard state->path = xmlMalloc(strlen(path) + 1); 1546bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->path == NULL) { 1559f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state); 1566bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return NULL; 1576bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 1586bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strcpy(state->path, path); 1596bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 1606bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* open the file with the appropriate mode (or just use fd) */ 161adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->fd = fd != -1 ? fd : open(path, 1626bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef O_LARGEFILE 163adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard O_LARGEFILE | 1646bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 1656bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef O_BINARY 166adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard O_BINARY | 1676bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 168adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard O_RDONLY, 0666); 1696bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->fd == -1) { 1709f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->path); 1719f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state); 1726bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return NULL; 1736bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 1746bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 1756bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* save the current position for rewinding (only if reading) */ 1766bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->start = lseek(state->fd, 0, SEEK_CUR); 177adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (state->start == (uint64_t) - 1) 178adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->start = 0; 1796bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 1806bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* initialize stream */ 1816bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_reset(state); 1826bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 1836bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* return stream */ 184adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return (xzFile) state; 1856bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 1866bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 18763588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillardstatic int 18863588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillardxz_compressed(xzFile f) { 18963588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard xz_statep state; 19063588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard 19163588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard if (f == NULL) 19263588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard return(-1); 19363588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard state = (xz_statep) f; 19463588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard if (state->init <= 0) 19563588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard return(-1); 19663588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard 19763588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard switch (state->how) { 19863588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard case COPY: 19963588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard return(0); 20063588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard case GZIP: 20163588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard case LZMA: 20263588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard return(1); 20363588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard } 20463588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard return(-1); 20563588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard} 20663588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard 207adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel VeillardxzFile 208adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard__libxml2_xzopen(const char *path, const char *mode) 2096bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 2106bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return xz_open(path, -1, mode); 2116bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 2126bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 21363588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillardint 21463588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard__libxml2_xzcompressed(xzFile f) { 21563588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard return xz_compressed(f); 21663588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard} 21763588f476f2dc89d4c6ef70a474d7230fbf4d45eDaniel Veillard 218adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel VeillardxzFile 219adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard__libxml2_xzdopen(int fd, const char *mode) 2206bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 221adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard char *path; /* identifier for error messages */ 2226bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xzFile xz; 2236bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 2249f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard if (fd == -1 || (path = xmlMalloc(7 + 3 * sizeof(int))) == NULL) 2256bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return NULL; 226adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard sprintf(path, "<fd:%d>", fd); /* for debugging */ 2276bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz = xz_open(path, fd, mode); 2289f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(path); 2296bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return xz; 2306bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 2316bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 232adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic int 23372789ef21fed132bb15bd4e858cb524f41c79ed1Daniel Veillardxz_load(xz_statep state, unsigned char *buf, unsigned int len, 23472789ef21fed132bb15bd4e858cb524f41c79ed1Daniel Veillard unsigned int *have) 2356bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 2366bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund int ret; 2376bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 2386bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund *have = 0; 2396bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund do { 2406bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund ret = read(state->fd, buf + *have, len - *have); 2416bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (ret <= 0) 2426bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund break; 2436bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund *have += ret; 2446bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } while (*have < len); 2456bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (ret < 0) { 2466bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_error(state, -1, strerror(errno)); 2476bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 2486bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 2496bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (ret == 0) 2506bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->eof = 1; 2516bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 2526bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 2536bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 254adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic int 255adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardxz_avail(xz_statep state) 2566bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 2576bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream *strm = &(state->strm); 2586bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 2596bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->err != LZMA_OK) 2606bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 2616bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->eof == 0) { 262996449273fd4a8fc656d42088779e236d456e47aMarcus Meissner /* avail_in is size_t, which is not necessary sizeof(unsigned) */ 263996449273fd4a8fc656d42088779e236d456e47aMarcus Meissner unsigned tmp = strm->avail_in; 264996449273fd4a8fc656d42088779e236d456e47aMarcus Meissner 265996449273fd4a8fc656d42088779e236d456e47aMarcus Meissner if (xz_load(state, state->in, state->size, &tmp) == -1) { 266996449273fd4a8fc656d42088779e236d456e47aMarcus Meissner strm->avail_in = tmp; 2676bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 268996449273fd4a8fc656d42088779e236d456e47aMarcus Meissner } 269996449273fd4a8fc656d42088779e236d456e47aMarcus Meissner strm->avail_in = tmp; 2706bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->next_in = state->in; 2716bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 2726bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 2736bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 2746bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 275a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander#ifdef HAVE_ZLIB_H 276a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexanderstatic int 277a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexanderxz_avail_zstrm(xz_statep state) 278a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander{ 279a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander int ret; 280a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander state->strm.avail_in = state->zstrm.avail_in; 281a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander state->strm.next_in = state->zstrm.next_in; 282a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander ret = xz_avail(state); 283a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander state->zstrm.avail_in = (uInt) state->strm.avail_in; 284a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander state->zstrm.next_in = (Bytef *) state->strm.next_in; 285a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander return ret; 286a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander} 287a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander#endif 288a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander 2896bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklundstatic int 2906bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklundis_format_xz(xz_statep state) 2916bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 2926bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream *strm = &(state->strm); 2936bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 294adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return strm->avail_in >= 6 && memcmp(state->in, "\3757zXZ", 6) == 0; 2956bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 2966bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 2976bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklundstatic int 2986bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklundis_format_lzma(xz_statep state) 2996bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 3006bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream *strm = &(state->strm); 3016bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 302adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard lzma_filter filter; 303adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard lzma_options_lzma *opt; 304adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard uint32_t dict_size; 305adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard uint64_t uncompressed_size; 306adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard size_t i; 307adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 308adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (strm->avail_in < 13) 309adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return 0; 310adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 311adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard filter.id = LZMA_FILTER_LZMA1; 312adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (lzma_properties_decode(&filter, NULL, state->in, 5) != LZMA_OK) 313adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return 0; 314adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 315adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard opt = filter.options; 316adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard dict_size = opt->dict_size; 31794431ecba6c458c56cb0f5b2a919ed4cf27107baDaniel Veillard free(opt); /* we can't use xmlFree on a string returned by zlib */ 318adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 319adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* A hack to ditch tons of false positives: We allow only dictionary 320adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * sizes that are 2^n or 2^n + 2^(n-1) or UINT32_MAX. LZMA_Alone 321adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * created only files with 2^n, but accepts any dictionary size. 322adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * If someone complains, this will be reconsidered. 323adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard */ 324adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (dict_size != UINT32_MAX) { 325adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard uint32_t d = dict_size - 1; 326adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 327adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard d |= d >> 2; 328adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard d |= d >> 3; 329adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard d |= d >> 4; 330adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard d |= d >> 8; 331adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard d |= d >> 16; 332adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard ++d; 333adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (d != dict_size || dict_size == 0) 334adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return 0; 335adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } 336adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 337adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* Another hack to ditch false positives: Assume that if the 338adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * uncompressed size is known, it must be less than 256 GiB. 339adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * Again, if someone complains, this will be reconsidered. 340adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard */ 341adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard uncompressed_size = 0; 342adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard for (i = 0; i < 8; ++i) 343adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard uncompressed_size |= (uint64_t) (state->in[5 + i]) << (i * 8); 344adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 345adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (uncompressed_size != UINT64_MAX 346adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard && uncompressed_size > (UINT64_C(1) << 38)) 347adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return 0; 348adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 349adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return 1; 3506bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 3516bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 3526bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef HAVE_ZLIB_H 353adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 3546bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund/* Get next byte from input, or -1 if end or error. */ 3556bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#define NEXT() ((strm->avail_in == 0 && xz_avail(state) == -1) ? -1 : \ 3566bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund (strm->avail_in == 0 ? -1 : \ 3576bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund (strm->avail_in--, *(strm->next_in)++))) 358a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander/* Same thing, but from zstrm */ 359a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander#define NEXTZ() ((strm->avail_in == 0 && xz_avail_zstrm(state) == -1) ? -1 : \ 360a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander (strm->avail_in == 0 ? -1 : \ 361a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander (strm->avail_in--, *(strm->next_in)++))) 3626bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 3636bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund/* Get a four-byte little-endian integer and return 0 on success and the value 3646bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund in *ret. Otherwise -1 is returned and *ret is not modified. */ 365adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic int 366adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardgz_next4(xz_statep state, unsigned long *ret) 3676bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 3686bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund int ch; 3696bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund unsigned long val; 3706bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund z_streamp strm = &(state->zstrm); 3716bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 372a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander val = NEXTZ(); 373a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander val += (unsigned) NEXTZ() << 8; 374a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander val += (unsigned long) NEXTZ() << 16; 375a1313a6f8c48cc27b02f65aca6b04e6cd59d939aMike Alexander ch = NEXTZ(); 3766bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (ch == -1) 3776bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 378adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard val += (unsigned long) ch << 24; 3796bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund *ret = val; 3806bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 3816bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 3826bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 3836bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 384adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic int 385adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardxz_head(xz_statep state) 3866bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 3876bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream *strm = &(state->strm); 3886bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream init = LZMA_STREAM_INIT; 3896bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund int flags; 3906bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund unsigned len; 3916bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 3926bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* allocate read buffers and inflate memory */ 3936bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->size == 0) { 3946bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* allocate buffers */ 3959f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard state->in = xmlMalloc(state->want); 3969f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard state->out = xmlMalloc(state->want << 1); 3976bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->in == NULL || state->out == NULL) { 3986bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->out != NULL) 3999f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->out); 4006bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->in != NULL) 4019f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->in); 4026bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_error(state, LZMA_MEM_ERROR, "out of memory"); 4036bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 4046bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 4056bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->size = state->want; 4066bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 4076bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* allocate decoder memory */ 4086bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->strm = init; 4096bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->strm.avail_in = 0; 4106bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->strm.next_in = NULL; 4116bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (lzma_auto_decoder(&state->strm, UINT64_MAX, 0) != LZMA_OK) { 4129f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->out); 4139f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->in); 4146bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->size = 0; 4156bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_error(state, LZMA_MEM_ERROR, "out of memory"); 4166bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 417adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } 4186bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef HAVE_ZLIB_H 4196bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* allocate inflate memory */ 4206bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->zstrm.zalloc = Z_NULL; 4216bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->zstrm.zfree = Z_NULL; 4226bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->zstrm.opaque = Z_NULL; 4236bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->zstrm.avail_in = 0; 4246bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->zstrm.next_in = Z_NULL; 4259f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard if (state->init == 0) { 4269f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard if (inflateInit2(&(state->zstrm), -15) != Z_OK) {/* raw inflate */ 4279f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->out); 4289f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->in); 4299f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard state->size = 0; 4309f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xz_error(state, LZMA_MEM_ERROR, "out of memory"); 4319f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard return -1; 4329f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard } 4339f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard state->init = 1; 4346bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 4356bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 4366bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 4376bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 4386bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* get some data in the input buffer */ 4396bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->avail_in == 0) { 4406bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_avail(state) == -1) 4416bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 4426bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->avail_in == 0) 4436bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 4446bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 4456bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 446adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* look for the xz magic header bytes */ 4476bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (is_format_xz(state) || is_format_lzma(state)) { 448adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->how = LZMA; 449adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->direct = 0; 450adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return 0; 4516bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 4526bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef HAVE_ZLIB_H 453adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* look for the gzip magic header bytes 31 and 139 */ 4546bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->next_in[0] == 31) { 4556bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->avail_in--; 4566bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->next_in++; 4576bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->avail_in == 0 && xz_avail(state) == -1) 4586bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 4596bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->avail_in && strm->next_in[0] == 139) { 4606bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* we have a gzip header, woo hoo! */ 4616bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->avail_in--; 4626bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->next_in++; 4636bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 4646bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* skip rest of header */ 465adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (NEXT() != 8) { /* compression method */ 466adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard xz_error(state, LZMA_DATA_ERROR, 467adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard "unknown compression method"); 4686bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 4696bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 4706bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund flags = NEXT(); 471adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (flags & 0xe0) { /* reserved flag bits */ 472adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard xz_error(state, LZMA_DATA_ERROR, 473adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard "unknown header flags set"); 4746bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 4756bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 476adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard NEXT(); /* modification time */ 4776bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund NEXT(); 4786bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund NEXT(); 4796bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund NEXT(); 480adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard NEXT(); /* extra flags */ 481adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard NEXT(); /* operating system */ 482adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (flags & 4) { /* extra field */ 483adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard len = (unsigned) NEXT(); 484adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard len += (unsigned) NEXT() << 8; 4856bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund while (len--) 4866bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (NEXT() < 0) 4876bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund break; 4886bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 489adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (flags & 8) /* file name */ 490adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard while (NEXT() > 0) ; 491adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (flags & 16) /* comment */ 492adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard while (NEXT() > 0) ; 493adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (flags & 2) { /* header crc */ 4946bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund NEXT(); 4956bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund NEXT(); 4966bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 4976bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* an unexpected end of file is not checked for here -- it will be 498adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * noticed on the first request for uncompressed data */ 4996bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 5006bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* set up for decompression */ 5016bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund inflateReset(&state->zstrm); 5026bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->zstrm.adler = crc32(0L, Z_NULL, 0); 5036bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->how = GZIP; 5046bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->direct = 0; 5056bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 506adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } else { 5076bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* not a gzip file -- save first byte (31) and fall to raw i/o */ 5086bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->out[0] = 31; 5096bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->have = 1; 5106bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 5116bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 5126bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 5136bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 5146bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* doing raw i/o, save start of raw data for seeking, copy any leftover 515adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * input to output -- this assumes that the output buffer is larger than 516adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * the input buffer, which also assures space for gzungetc() */ 5176bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->raw = state->pos; 5186bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->next = state->out; 5196bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->avail_in) { 5206bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund memcpy(state->next + state->have, strm->next_in, strm->avail_in); 5216bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->have += strm->avail_in; 5226bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->avail_in = 0; 5236bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 5246bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->how = COPY; 5256bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->direct = 1; 5266bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 5276bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 5286bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 529adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic int 530adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardxz_decomp(xz_statep state) 5316bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 5326bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund int ret; 5336bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund unsigned had; 5346bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund unsigned long crc, len; 5356bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream *strm = &(state->strm); 5366bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 5376bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_action action = LZMA_RUN; 5386bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 5396bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* fill output buffer up to end of deflate stream */ 5406bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund had = strm->avail_out; 5416bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund do { 5426bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* get more input for inflate() */ 5436bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->avail_in == 0 && xz_avail(state) == -1) 5446bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 5456bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (strm->avail_in == 0) { 5466bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_error(state, LZMA_DATA_ERROR, "unexpected end of file"); 5476bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 5486bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 5496bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->eof) 5506bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund action = LZMA_FINISH; 551adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard 5526bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* decompress and handle errors */ 5536bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef HAVE_ZLIB_H 5546bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->how == GZIP) { 555adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->zstrm.avail_in = (uInt) state->strm.avail_in; 556adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->zstrm.next_in = (Bytef *) state->strm.next_in; 557adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->zstrm.avail_out = (uInt) state->strm.avail_out; 558adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->zstrm.next_out = (Bytef *) state->strm.next_out; 559adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard ret = inflate(&state->zstrm, Z_NO_FLUSH); 560adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { 561adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard xz_error(state, Z_STREAM_ERROR, 562adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard "internal error: inflate stream corrupt"); 563adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return -1; 564adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } 565adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (ret == Z_MEM_ERROR) 566adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard ret = LZMA_MEM_ERROR; 567adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (ret == Z_DATA_ERROR) 568adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard ret = LZMA_DATA_ERROR; 569adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (ret == Z_STREAM_END) 570adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard ret = LZMA_STREAM_END; 571adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.avail_in = state->zstrm.avail_in; 572adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.next_in = state->zstrm.next_in; 573adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.avail_out = state->zstrm.avail_out; 574adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.next_out = state->zstrm.next_out; 575adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } else /* state->how == LZMA */ 5766bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 577adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard ret = lzma_code(strm, action); 5786bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (ret == LZMA_MEM_ERROR) { 5796bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_error(state, LZMA_MEM_ERROR, "out of memory"); 5806bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 5816bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 5826bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (ret == LZMA_DATA_ERROR) { 5836bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_error(state, LZMA_DATA_ERROR, "compressed data error"); 5846bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 5856bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 586f0709e3ca8f8947f2d91ed34e92e38a4c23eae63Daniel Veillard if (ret == LZMA_PROG_ERROR) { 587f0709e3ca8f8947f2d91ed34e92e38a4c23eae63Daniel Veillard xz_error(state, LZMA_PROG_ERROR, "compression error"); 588f0709e3ca8f8947f2d91ed34e92e38a4c23eae63Daniel Veillard return -1; 589f0709e3ca8f8947f2d91ed34e92e38a4c23eae63Daniel Veillard } 5906bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } while (strm->avail_out && ret != LZMA_STREAM_END); 5916bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 5926bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* update available output and crc check value */ 5936bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->have = had - strm->avail_out; 5946bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->next = strm->next_out - state->have; 5956bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef HAVE_ZLIB_H 596adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->zstrm.adler = 597adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard crc32(state->zstrm.adler, state->next, state->have); 5986bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 5996bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 6006bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (ret == LZMA_STREAM_END) { 6016bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#ifdef HAVE_ZLIB_H 6026bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->how == GZIP) { 603adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) { 604adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard xz_error(state, LZMA_DATA_ERROR, "unexpected end of file"); 605adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return -1; 606adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } 607adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (crc != state->zstrm.adler) { 608adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard xz_error(state, LZMA_DATA_ERROR, "incorrect data check"); 609adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return -1; 610adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } 611adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (len != (state->zstrm.total_out & 0xffffffffL)) { 612adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard xz_error(state, LZMA_DATA_ERROR, "incorrect length check"); 613adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return -1; 614adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } 615adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.avail_in = 0; 616adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.next_in = NULL; 617adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.avail_out = 0; 618adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state->strm.next_out = NULL; 619adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } else 6206bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 621adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (strm->avail_in != 0 || !state->eof) { 6226bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_error(state, LZMA_DATA_ERROR, "trailing garbage"); 6236bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 6246bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 6256bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->how = LOOK; /* ready for next stream, once have is 0 (leave 626adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * state->direct unchanged to remember how) */ 6276bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 6286bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 6296bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* good decompression */ 6306bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 6316bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 6326bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 633adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic int 634adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardxz_make(xz_statep state) 6356bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 6366bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream *strm = &(state->strm); 6376bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 638adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (state->how == LOOK) { /* look for lzma / gzip header */ 6396bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_head(state) == -1) 6406bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 641adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (state->have) /* got some data from xz_head() */ 6426bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 6436bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 644adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (state->how == COPY) { /* straight copy */ 645adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if (xz_load(state, state->out, state->size << 1, &(state->have)) == 646adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard -1) 6476bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 6486bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->next = state->out; 649adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard } else if (state->how == LZMA || state->how == GZIP) { /* decompress */ 6506bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->avail_out = state->size << 1; 6516bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->next_out = state->out; 6526bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_decomp(state) == -1) 6536bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 6546bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 6556bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 6566bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 6576bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 658adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardstatic int 659adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardxz_skip(xz_statep state, uint64_t len) 6606bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 6616bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund unsigned n; 6626bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 6636bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* skip over len bytes or reach end-of-file, whichever comes first */ 6646bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund while (len) 6656bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* skip over whatever is in output buffer */ 6666bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->have) { 667adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard n = (uint64_t) state->have > len ? 668adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard (unsigned) len : state->have; 6696bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->have -= n; 6706bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->next += n; 6716bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->pos += n; 6726bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund len -= n; 6736bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 6746bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 675adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* output buffer empty -- return if we're at the end of the input */ 6766bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund else if (state->eof && state->strm.avail_in == 0) 6776bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund break; 6786bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 679adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard /* need more data to skip -- load up output buffer */ 6806bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund else { 6816bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* get more output, looking for header if required */ 6826bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_make(state) == -1) 6836bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 6846bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 6856bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 6866bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 6876bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 688adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardint 689adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard__libxml2_xzread(xzFile file, void *buf, unsigned len) 6906bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 6916bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund unsigned got, n; 6926bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_statep state; 6936bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_stream *strm; 6946bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 6956bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* get internal structure */ 6966bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (file == NULL) 6976bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 698adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state = (xz_statep) file; 6996bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm = &(state->strm); 7006bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7016bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* check that we're reading and that there's no error */ 7026bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->err != LZMA_OK) 7036bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 7046bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7056bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* since an int is returned, make sure len fits in one, otherwise return 706adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * with an error (this avoids the flaw in the interface) */ 707adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard if ((int) len < 0) { 708adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard xz_error(state, LZMA_BUF_ERROR, 709adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard "requested length does not fit in int"); 7106bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 7116bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 7126bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7136bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* if len is zero, avoid unnecessary operations */ 7146bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (len == 0) 7156bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return 0; 7166bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7176bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* process a skip request */ 7186bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->seek) { 7196bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->seek = 0; 7206bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_skip(state, state->skip) == -1) 7216bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 7226bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 7236bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7246bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* get len bytes to buf, or less than len if at the end */ 7256bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund got = 0; 7266bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund do { 7276bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* first just try copying data from the output buffer */ 7286bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->have) { 7296bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund n = state->have > len ? len : state->have; 7306bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund memcpy(buf, state->next, n); 7316bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->next += n; 7326bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->have -= n; 7336bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 7346bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7356bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* output buffer empty -- return if we're at the end of the input */ 7366bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund else if (state->eof && strm->avail_in == 0) 7376bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund break; 7386bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7396bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* need output data -- for small len or new stream load up our output 740adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * buffer */ 7416bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund else if (state->how == LOOK || len < (state->size << 1)) { 7426bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* get more output, looking for header if required */ 7436bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_make(state) == -1) 7446bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 745adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard continue; /* no progress yet -- go back to memcpy() above */ 7466bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* the copy above assures that we will leave with space in the 747adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard * output buffer, allowing at least one gzungetc() to succeed */ 7486bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 7496bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7506bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* large len -- read directly into user buffer */ 751adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard else if (state->how == COPY) { /* read directly */ 7526bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_load(state, buf, len, &n) == -1) 7536bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 7546bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 7556bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7566bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* large len -- decompress directly into user buffer */ 757adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard else { /* state->how == LZMA */ 7586bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->avail_out = len; 7596bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund strm->next_out = buf; 7606bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (xz_decomp(state) == -1) 7616bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return -1; 7626bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund n = state->have; 7636bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->have = 0; 7646bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 7656bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7666bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* update progress */ 7676bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund len -= n; 768adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard buf = (char *) buf + n; 7696bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund got += n; 7706bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund state->pos += n; 7716bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } while (len); 7726bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7736bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* return number of bytes read into user buffer (will fit in int) */ 774adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard return (int) got; 7756bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 7766bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 777adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillardint 778adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard__libxml2_xzclose(xzFile file) 7796bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund{ 7806bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund int ret; 7816bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund xz_statep state; 7826bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7836bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* get internal structure */ 7846bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (file == NULL) 7856bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return LZMA_DATA_ERROR; 786adf5ec9496828b18e683fb23bd1e670824cfb6d0Daniel Veillard state = (xz_statep) file; 7876bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund 7886bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund /* free memory and close file */ 7896bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund if (state->size) { 7906bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund lzma_end(&(state->strm)); 7919f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard#ifdef HAVE_ZLIB_H 7929f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard if (state->init == 1) 7939f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard inflateEnd(&(state->zstrm)); 7949f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard state->init = 0; 7956bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund#endif 7969f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->out); 7979f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->in); 7986bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund } 7999f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state->path); 8006bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund ret = close(state->fd); 8019f3cdef08a5d45c82c71bf740a54e2bc5d07f3ecDaniel Veillard xmlFree(state); 8026bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund return ret ? ret : LZMA_OK; 8036bdc774350d11117849a53f7baf2bb7e26b00009Anders F Bjorklund} 80418b8988511b0954272cac4d6c3e6724f9dbf6e0aDaniel Veillard#endif /* LIBXML_LZMA_ENABLED */ 805