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,
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);
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) {
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;
}