xz: Fix input file position when --single-stream is used.
authorLasse Collin <lasse.collin@tukaani.org>
Sun, 1 May 2011 09:24:23 +0000 (12:24 +0300)
committerLasse Collin <lasse.collin@tukaani.org>
Sun, 1 May 2011 09:24:23 +0000 (12:24 +0300)
Now the following works as you would expect:

    echo foo | xz > foo.xz
    echo bar | xz >> foo.xz
    ( xz -dc --single-stream ; xz -dc --single-stream ) < foo.xz

Note that it doesn't work if the input is not seekable
or if there is Stream Padding between the concatenated
.xz Streams.

src/xz/coder.c
src/xz/file_io.c
src/xz/file_io.h

index 316f560..b470e58 100644 (file)
@@ -594,6 +594,7 @@ coder_normal(file_pair *pair)
 
                        if (ret == LZMA_STREAM_END) {
                                if (opt_single_stream) {
+                                       io_fix_src_pos(pair, strm.avail_in);
                                        success = true;
                                        break;
                                }
index 370b61b..f9807a6 100644 (file)
@@ -840,6 +840,21 @@ io_close(file_pair *pair, bool success)
 }
 
 
+extern void
+io_fix_src_pos(file_pair *pair, size_t rewind_size)
+{
+       assert(rewind_size <= IO_BUFFER_SIZE);
+
+       if (rewind_size > 0) {
+               // This doesn't need to work on unseekable file descriptors,
+               // so just ignore possible errors.
+               (void)lseek(pair->src_fd, -(off_t)(rewind_size), SEEK_CUR);
+       }
+
+       return;
+}
+
+
 extern size_t
 io_read(file_pair *pair, io_buf *buf_union, size_t size)
 {
index 967da86..ef63932 100644 (file)
@@ -102,6 +102,19 @@ extern void io_close(file_pair *pair, bool success);
 extern size_t io_read(file_pair *pair, io_buf *buf, size_t size);
 
 
+/// \brief      Fix the position in src_fd
+///
+/// This is used when --single-thream has been specified and decompression
+/// is successful. If the input file descriptor supports seeking, this
+/// function fixes the input position to point to the next byte after the
+/// decompressed stream.
+///
+/// \param      pair        File pair having the source file open for reading
+/// \param      rewind_size How many bytes of extra have been read i.e.
+///                         how much to seek backwards.
+extern void io_fix_src_pos(file_pair *pair, size_t rewind_size);
+
+
 /// \brief      Read from source file from given offset to a buffer
 ///
 /// This is remotely similar to standard pread(). This uses lseek() though,