adamhathcock/sharpcompress

Tar corruption when writing active files

lopio opened this issue · 4 comments

I use the library to compress logs in a streaming manner, without saving a temporary file or storing to memory (RAM and diskspace restriction).

When I use the tar writer to archive active files (logs) the size of the tar header doesn't match the file in the tar, because the file has increased in size between the time the header was created and the file was fully read.

This result in the tar entry being corrupted, and sometime it can also result in the file in question not being recoverable.

Repro steps: Create a tar archive with a file that is being written in actively.

The fix is to stop reading the file at the size set by the tar header. Attached is the proposed fix as a git patch
tarCorruption.patch

I seemingly can't use that patch file

Any chance of a PR?

I can't find a way to create a branch for the PR. I do have my complete git diff here:

PS C:\git\sharpcompress> git diff
diff --git a/src/SharpCompress/Utility.cs b/src/SharpCompress/Utility.cs
index 9471c3e..0493e84 100644
--- a/src/SharpCompress/Utility.cs
+++ b/src/SharpCompress/Utility.cs
@@ -270,16 +270,27 @@ public static class Utility
         return sTime.AddSeconds(unixtime);
     }

-    public static long TransferTo(this Stream source, Stream destination)
+    public static long TransferTo(this Stream source, Stream destination, Int64? size = null)
     {
+        Int64 realSize = size ?? source.Length;
         var array = GetTransferByteArray();
         try
         {
             long total = 0;
             while (ReadTransferBlock(source, array, out var count))
             {
-                total += count;
-                destination.Write(array, 0, count);
+                if (total + count > realSize)
+                {
+                    int bytesToWrite = (int) (realSize - total);
+                    destination.Write(array, 0, (int) bytesToWrite);
+                    total = realSize;
+                    break;
+                }
+                else
+                {
+                    total += count;
+                    destination.Write(array, 0, count);
+                }
             }
             return total;
         }
diff --git a/src/SharpCompress/Writers/Tar/TarWriter.cs b/src/SharpCompress/Writers/Tar/TarWriter.cs
index 2427db3..53ce0ea 100644
--- a/src/SharpCompress/Writers/Tar/TarWriter.cs
+++ b/src/SharpCompress/Writers/Tar/TarWriter.cs
@@ -91,7 +91,7 @@ public class TarWriter : AbstractWriter
         header.Size = realSize;
         header.Write(OutputStream);

-        size = source.TransferTo(OutputStream);
+        size = source.TransferTo(OutputStream, realSize);
         PadTo512(size.Value);
     }

modified the patch a little as my client corrupted it I think

Please validate the PR