Skip to content

Instantly share code, notes, and snippets.

@Bio2hazard
Last active May 20, 2022 18:44
Show Gist options
  • Save Bio2hazard/fd40220f3b076c8fc15e0159a83444d4 to your computer and use it in GitHub Desktop.
Save Bio2hazard/fd40220f3b076c8fc15e0159a83444d4 to your computer and use it in GitHub Desktop.
void Main()
{
var fileInfoOriginal = new FileInfo(@"C:\Development\project-dev-12345-67890-abcdefg.tar.gz"); // unmodified
var fileInfoModified = new FileInfo(@"C:\Development\project-dev-12345-67890-abcdefg-modified.tar.gz"); // modified
using var fileStreamOriginal = fileInfoOriginal.OpenRead();
using var decompresssionStreamOriginal = new GZipStream(fileStreamOriginal, CompressionMode.Decompress);
var original = InspectTarHeader(decompresssionStreamOriginal);
using var fileStreamModified = fileInfoModified.OpenRead();
using var decompresssionStreamModified = new GZipStream(fileStreamModified, CompressionMode.Decompress);
var modified = InspectTarHeader(decompresssionStreamModified);
foreach (var originalEntry in original)
{
var modifiedEntry = modified[originalEntry.Key];
originalEntry.Key.Dump();
Util.Dif(originalEntry.Value, modifiedEntry, depth: 3, true).Dump();
}
}
public static Dictionary<string, byte[]> InspectTarHeader(Stream stream)
{
var readBuffer = new byte[1024];
var readBufferSpan = readBuffer.AsMemory();
var bufferArray = new byte[512];
var buffer = bufferArray.AsMemory();
var dict = new Dictionary<string, byte[]>();
var deduper = 0;
while (true)
{
var header = buffer.Slice(0, 512);
stream.Read(header.Span);
var name = Encoding.ASCII.GetString(header.Slice(0, 100).Span).Trim('\0');
if (String.IsNullOrWhiteSpace(name))
break;
header = header.Slice(100);
header = header.Slice(8 + 8 + 8); // Skip mode, uid, gid
var size = (int)Convert.ToInt64(Encoding.UTF8.GetString(header.Slice(0, 12).Span).Trim().Trim('\0'), 8);
// Put the files 512 byte header into the output dictionary
if(!dict.TryAdd(name, bufferArray.ToArray()))
{
name = $"{name}{deduper++}";
dict.TryAdd(name, bufferArray.ToArray());
}
header = header.Slice(12);
header = header.Slice(12 + 8); // Skip mtime, chksum
var mode = (char)header.Span[0];
header = header.Slice(1);
if(mode == '5' ) // Directory
{
continue;
}
if(mode == '0' || mode == 'L') // Process it
{
var chunks = Math.DivRem(size, readBuffer.Length, out int remainder);
for (int i = 0; i <= chunks; i++)
{
stream.Read(readBufferSpan.Slice(0, i == chunks ? remainder : readBuffer.Length).Span);
}
var emptyDataCount = 512 - (remainder % 512);
if (emptyDataCount > 0 && emptyDataCount < 512)
{
stream.Read(readBufferSpan.Slice(0, emptyDataCount).Span);
}
continue;
}
return dict;
}
return dict;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment