]> git.ipfire.org Git - thirdparty/tar.git/commitdiff
Don't assume archive read from stdin starts at offset 0
authorSergey Poznyakoff <gray@gnu.org>
Thu, 31 Oct 2024 17:09:28 +0000 (19:09 +0200)
committerSergey Poznyakoff <gray@gnu.org>
Thu, 31 Oct 2024 17:17:05 +0000 (19:17 +0200)
* src/buffer.c (start_offset): New variable.
(get_archive_status): If reading from seekable stdin, store the
position in the stream corresponding to record_start in start_offset.
(seek_archive): Compute current offset relative to start_offset.

src/buffer.c

index 570c8666bc24d202abff70e6516c44913d397117..6550e7989d79c3c9beb81359f9dfd4ba8cc8b9f3 100644 (file)
@@ -65,6 +65,7 @@ union block *current_block;     /* current block of archive */
 enum access_mode access_mode;   /* how do we handle the archive */
 off_t records_read;             /* number of records read from this archive */
 off_t records_written;          /* likewise, for records written */
+off_t start_offset;             /* start offset in the archive */
 
 /* When file status was last computed.  */
 static struct timespec last_stat_time;
@@ -710,7 +711,20 @@ get_archive_status (enum access_mode wanted_access, bool backed_up_flag)
              || S_ISBLK (archive_stat.st_mode))
           : seek_option));
 
-  if (wanted_access != ACCESS_READ)
+  if (wanted_access == ACCESS_READ)
+    {
+      if (archive == STDIN_FILENO && seekable_archive)
+       {
+         start_offset = lseek (archive, 0, SEEK_CUR);
+         if (start_offset == -1)
+           seekable_archive = false;
+         else
+           start_offset -= (record_end - record_start) * BLOCKSIZE;
+       }
+      else
+       start_offset = 0;
+    }
+  else
     sys_detect_dev_null_output ();
 
   SET_BINARY_MODE (archive);
@@ -1096,6 +1110,8 @@ seek_archive (off_t size)
   if (offset < 0)
     return offset;
 
+  offset -= start_offset;
+
   if (offset % record_size)
     paxfatal (0, _("rmtlseek not stopped at a record boundary"));