[PATCH 6/6] Handle short reads in archive_tar_file::read()

Jon TURNEY jon.turney@dronecode.org.uk
Fri Apr 8 14:44:00 GMT 2011


archive_tar_file::read() currently considers any short read an error.

These can now occur if the underlying bz2 compressed io_stream starts a
new compression stream in the middle of the read

It also transparently reads to the next 512-byte block in the parent
io_stream after reading all the data expected for a file.

Teach it to do things correctly, even if a short read occurs.

2011-04-08  Jon TURNEY  <jon.turney@dronecode.org.uk>

	* archive_tar_file.cc (read): Handle short reads

Signed-off-by: Jon TURNEY <jon.turney@dronecode.org.uk>
---
 archive_tar_file.cc |   52 +++++++++++++++++++++++++++++++++-----------------
 1 files changed, 34 insertions(+), 18 deletions(-)

diff --git a/archive_tar_file.cc b/archive_tar_file.cc
index 5ffb3a1..9a1721b 100644
--- a/archive_tar_file.cc
+++ b/archive_tar_file.cc
@@ -49,24 +49,40 @@ ssize_t archive_tar_file::read (void *buffer, size_t len)
   read_something = true;
   if (want)
     {
-      ssize_t
-	got = state.parent->read (buffer, want);
-      char
-	throwaway[512];
-      ssize_t
-	got2 = state.parent->read (throwaway, roundup);
-      if (got == want && got2 == roundup)
-	{
-	  state.file_offset += got;
-	  return got;
-	}
-      else
-	{
-	  /* unexpected EOF or read error in the tar parent stream */
-	  /* the user can query the parent for the error */
-	  state.lasterr = EIO;
-	  return -1;
-	}
+      int need = want;
+      char *p = (char *)buffer;
+      while (need > 0)
+        {
+          ssize_t got = state.parent->read (p, need);
+          if (got <= 0)
+            {
+              /* unexpected EOF or read error in the tar parent stream */
+              /* the user can query the parent for the error */
+              state.lasterr = EIO;
+              return -1;
+            }
+          p += got;
+          need -= got;
+        }
+
+      char throwaway[512];
+      p = &throwaway[0];
+      while (roundup > 0)
+        {
+          ssize_t got2 = state.parent->read (p, roundup);
+          if (got2 <= 0)
+            {
+              /* unexpected EOF or read error in the tar parent stream */
+              /* the user can query the parent for the error */
+              state.lasterr = EIO;
+              return -1;
+            }
+          p += got2;
+          roundup -= got2;
+        }
+
+      state.file_offset += want;
+      return want;
     }
   return 0;
 }
-- 
1.7.4



More information about the Cygwin-apps mailing list