X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=pxzcat.c;fp=pxzcat.c;h=18cc751d56b4c285fb231194735f4edf10a6d4d8;hb=b2de587a183f620ff350e76d7e3fac1697e4b09b;hp=befc2c00a3e2319ded8753231913b387815510b0;hpb=806ddddc063eacdd8b4a8f989ab9caffea350ce8;p=pxzcat.git diff --git a/pxzcat.c b/pxzcat.c index befc2c0..18cc751 100644 --- a/pxzcat.c +++ b/pxzcat.c @@ -325,6 +325,26 @@ parse_indexes (const char *filename, int fd) return combined_index; } +#define BUFFER_SIZE (64*1024) + +/* Return true iff the buffer is all zero bytes. + * + * Note that gcc is smart enough to optimize this properly: + * http://stackoverflow.com/questions/1493936/faster-means-of-checking-for-an-empty-buffer-in-c/1493989#1493989 + */ +static inline int +is_zero (const char *buffer, size_t size) +{ + size_t i; + + for (i = 0; i < size; ++i) { + if (buffer[i] != 0) + return 0; + } + + return 1; +} + /* Iterate over the blocks and uncompress. */ static void iter_blocks (lzma_index *idx, @@ -337,7 +357,7 @@ iter_blocks (lzma_index *idx, lzma_filter filters[LZMA_FILTERS_MAX + 1]; lzma_ret r; lzma_stream strm = LZMA_STREAM_INIT; - char outbuf[BUFSIZ]; + char outbuf[BUFFER_SIZE]; size_t i; lzma_index_iter_init (&iter, idx); @@ -400,7 +420,7 @@ iter_blocks (lzma_index *idx, strm.avail_out = sizeof outbuf; for (;;) { - uint8_t buf[BUFSIZ]; + uint8_t buf[BUFFER_SIZE]; lzma_action action = LZMA_RUN; if (strm.avail_in == 0) { @@ -417,9 +437,16 @@ iter_blocks (lzma_index *idx, if (strm.avail_out == 0 || r == LZMA_STREAM_END) { size_t wsz = sizeof outbuf - strm.avail_out; - if (write (ofd, outbuf, wsz) != wsz) - /* XXX Handle short writes. */ - error (EXIT_FAILURE, errno, "%s: write", filename); + + if (is_zero (outbuf, wsz)) { /* Seek to preserve sparseness. */ + if (lseek (ofd, wsz, SEEK_CUR) == (off_t) -1) + error (EXIT_FAILURE, errno, "%s: seek", filename); + } else { + if (write (ofd, outbuf, wsz) != wsz) + /* XXX Handle short writes. */ + error (EXIT_FAILURE, errno, "%s: write", filename); + } + strm.next_out = outbuf; strm.avail_out = sizeof outbuf; }