Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions src/ICSharpCode.SharpZipLib/Tar/TarInputStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -390,10 +390,21 @@ public TarEntry GetNextEntry()

byte[] headerBuf = tarBuffer.ReadBlock();

if (headerBuf == null) {
if (headerBuf == null)
{
hasHitEOF = true;
}
else if (TarBuffer.IsEndOfArchiveBlock(headerBuf))
{
hasHitEOF = true;
} else
hasHitEOF |= TarBuffer.IsEndOfArchiveBlock(headerBuf);

// Read the second zero-filled block
tarBuffer.ReadBlock();
}
else
{
hasHitEOF = false;
}

if (hasHitEOF) {
currentEntry = null;
Expand Down
41 changes: 41 additions & 0 deletions test/ICSharpCode.SharpZipLib.Tests/Tar/TarTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,47 @@ public void InputStreamOwnership()
Assert.IsFalse(memStream.IsDisposed, "Should not be disposed after parent owner close");
}

[Test]
[Category("Tar")]
public void EndBlockHandling()
{
int dummySize = 70145;

long outCount, inCount;

using (var ms = new MemoryStream())
{
using (var tarOut = TarArchive.CreateOutputTarArchive(ms))
using (var dummyFile = Utils.GetDummyFile(dummySize))
{
tarOut.IsStreamOwner = false;
tarOut.WriteEntry(TarEntry.CreateEntryFromFile(dummyFile.Filename), false);
}

outCount = ms.Position;
ms.Seek(0, SeekOrigin.Begin);

using (var tarIn = TarArchive.CreateInputTarArchive(ms))
using (var tempDir = new Utils.TempDir())
{
tarIn.IsStreamOwner = false;
tarIn.ExtractContents(tempDir.Fullpath);

foreach (var file in Directory.GetFiles(tempDir.Fullpath, "*", SearchOption.AllDirectories))
{
Console.WriteLine($"Extracted \"{file}\"");
}
}

inCount = ms.Position;

Console.WriteLine($"Output count: {outCount}");
Console.WriteLine($"Input count: {inCount}");

Assert.AreEqual(inCount, outCount, "Bytes read and bytes written should be equal");
}
}

[Test]
[Category("Tar")]
[Category("Performance")]
Expand Down
94 changes: 94 additions & 0 deletions test/ICSharpCode.SharpZipLib.Tests/TestSupport/Utils.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.IO;
using NUnit.Framework;

namespace ICSharpCode.SharpZipLib.Tests.TestSupport
Expand All @@ -8,6 +9,7 @@ namespace ICSharpCode.SharpZipLib.Tests.TestSupport
/// </summary>
public static class Utils
{
static Random random = new Random();

static void Compare(byte[] a, byte[] b)
{
Expand All @@ -25,5 +27,97 @@ static void Compare(byte[] a, byte[] b)
}
}

public static TempFile GetDummyFile(int size = -1)
{
var tempFile = new TempFile();
if (size < 0)
{
File.WriteAllText(tempFile.Filename, DateTime.UtcNow.Ticks.ToString("x16"));
}
else if (size > 0)
{
var bytes = Array.CreateInstance(typeof(byte), size) as byte[];
random.NextBytes(bytes);
File.WriteAllBytes(tempFile.Filename, bytes);
}
return tempFile;
}

public class TempFile : IDisposable
{
public string Filename { get; internal set; }

public TempFile()
{
Filename = Path.GetTempFileName();
}

#region IDisposable Support
private bool disposed = false; // To detect redundant calls


protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing && File.Exists(Filename))
{
try
{
File.Delete(Filename);
}
catch { }
}

disposed = true;
}
}

public void Dispose()
=> Dispose(true);

#endregion

}

public class TempDir : IDisposable
{
public string Fullpath { get; internal set; }

public TempDir()
{
Fullpath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Directory.CreateDirectory(Fullpath);
}

#region IDisposable Support
private bool disposed = false; // To detect redundant calls


protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing && Directory.Exists(Fullpath))
{
try
{
Directory.Delete(Fullpath, true);
}
catch { }
}

disposed = true;
}
}

public void Dispose()
=> Dispose(true);

#endregion

}
}


}