sharpcompress icon indicating copy to clipboard operation
sharpcompress copied to clipboard

Tar corruption when writing active files

Open lopio opened this issue 10 months ago • 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

lopio avatar Mar 28 '24 18:03 lopio

I seemingly can't use that patch file

Any chance of a PR?

adamhathcock avatar Mar 29 '24 15:03 adamhathcock

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);
     }

lopio avatar Mar 29 '24 16:03 lopio

Fixed tarCorruption.patch

lopio avatar Apr 08 '24 17:04 lopio

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

Please validate the PR

adamhathcock avatar Apr 09 '24 07:04 adamhathcock