On 2024-10-31 10:21, Sergey Poznyakoff wrote:
I have pushed commit 647cafff96.

I installed the attached further patch in this area (along with a bunch of other patches I had been putting off...).
From 15d35a0f61a516bdf946158daa8a6990a2191ce1 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Sat, 2 Nov 2024 09:54:10 -0700
Subject: [PATCH] Count short read slop when seeking
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* src/buffer.c (short_read_slop): New static var.
(get_archive_status): Treat anything other than fifos and sockets
as potentially seekable; they’ll tell us if they aren’t, whereas
fifos and sockets cannot be seekable.  Check named files for
initial offset too, to deal with names like /dev/stdin.
Do not worry about start_offset’s value if !seekable_archive,
as it won’t be used.  Use short_read_slop.
(short_read, try_new_volume, simple_flush_read, _gnu_flush_read):
Set short_read_slop.
---
 src/buffer.c | 34 ++++++++++++++++++++--------------
 1 file changed, 20 insertions(+), 14 deletions(-)

diff --git a/src/buffer.c b/src/buffer.c
index 7b006445..6b55af26 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -47,6 +47,7 @@ static tarlong prev_written;    /* bytes written on previous volumes */
 static tarlong bytes_written;   /* bytes written on this volume */
 static void *record_buffer[2];  /* allocated memory */
 static bool record_index;
+static idx_t short_read_slop;	/* excess bytes at end of short read */
 
 /* FIXME: The following variables should ideally be static to this
    module.  However, this cannot be done yet.  The cleanup continues!  */
@@ -703,22 +704,20 @@ get_archive_status (enum access_mode wanted_access, bool backed_up_flag)
     = (! (multi_volume_option || use_compress_program_option)
        && (seek_option < 0
 	   ? (_isrmt (archive)
-	      || S_ISREG (archive_stat.st_mode)
-	      || S_ISBLK (archive_stat.st_mode))
-	   : seek_option));
+	      || ! (S_ISFIFO (archive_stat.st_mode)
+		    || S_ISSOCK (archive_stat.st_mode)))
+	   : seek_option != 0));
 
   if (wanted_access == ACCESS_READ)
     {
-      if (archive == STDIN_FILENO && seekable_archive)
+      if (seekable_archive)
 	{
-	  start_offset = lseek (archive, 0, SEEK_CUR);
-	  if (start_offset == -1)
+	  start_offset = (lseek (archive, 0, SEEK_CUR)
+			  - (record_end - record_start) * BLOCKSIZE
+			  - short_read_slop);
+	  if (start_offset < 0)
 	    seekable_archive = false;
-	  else
-	    start_offset -= (record_end - record_start) * BLOCKSIZE;
 	}
-      else
-	start_offset = 0;
     }
   else
     sys_detect_dev_null_output ();
@@ -999,7 +998,7 @@ short_read (idx_t status)
 
 	  paxfatal (0, ngettext ("Unaligned block (%td byte) in archive",
 				 "Unaligned block (%td bytes) in archive",
-                                  rest),
+				 rest),
 		    rest);
         }
 
@@ -1008,6 +1007,7 @@ short_read (idx_t status)
     }
 
   record_end = record_start + (record_size - left) / BLOCKSIZE;
+  short_read_slop = (record_size - left) % BLOCKSIZE;
   records_read++;
 }
 
@@ -1451,6 +1451,7 @@ try_new_volume (void)
          < 0)
     archive_read_error ();
 
+  short_read_slop = 0;
   if (status != record_size)
     short_read (status);
 
@@ -1813,6 +1814,7 @@ simple_flush_read (void)
   ptrdiff_t nread;
   while ((nread = rmtread (archive, record_start->buffer, record_size)) < 0)
     archive_read_error ();
+  short_read_slop = 0;
   if (nread == record_size)
     records_read++;
   else
@@ -1873,10 +1875,14 @@ _gnu_flush_read (void)
 	/* Necessary for blocking_factor == 1 */
 	flush_archive ();
     }
-  else if (nread == record_size)
-    records_read++;
   else
-    short_read (nread);
+    {
+      short_read_slop = 0;
+      if (nread == record_size)
+	records_read++;
+      else
+	short_read (nread);
+    }
 }
 
 static void
-- 
2.43.0

Reply via email to