Skip to content

Commit

Permalink
Feature/multirar (#43)
Browse files Browse the repository at this point in the history
* Implementation of multi-volume archive support, RAR test case
  • Loading branch information
jas88 authored Jun 29, 2023
1 parent 7fbcb2c commit 72a4536
Show file tree
Hide file tree
Showing 11 changed files with 114 additions and 35 deletions.
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
v0.1.4 - Jun 28 2023

- Add support for multi-volume archives

v0.1.3 - Dec 23 2022

- Add optional argument to LibArchiveReader to configure blocksize, default 1MiB

v0.1.2 - Oct 27 2022

- Fix memory leak on Linux in musl-libc malloc

v0.1.1 - Sep 22 2022

- First full release, supporting Linux, Windows and MacOS x64 plus MacOS ARM64
46 changes: 45 additions & 1 deletion LibArchive.Net/LibArchiveReader.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;

Expand Down Expand Up @@ -52,7 +53,20 @@ public LibArchiveReader(string filename,uint blockSize = 1<<20) : base(true)
archive_read_support_filter_all(handle);
archive_read_support_format_all(handle);
if (archive_read_open_filename(handle, uName.Ptr, (int)blockSize) != 0)
throw new ApplicationException("TODO: Archive open failed");
Throw();
}

/// <summary>
///
/// </summary>
public LibArchiveReader(string[] filenames,uint blockSize=1<<20) : base(true)
{
using var names = new DisposableStringArray(filenames);
handle = archive_read_new();
archive_read_support_filter_all(handle);
archive_read_support_format_all(handle);
if (archive_read_open_filenames(handle, names.Ptr, (int)blockSize) != 0)
Throw();
}

private void Throw()
Expand Down Expand Up @@ -147,6 +161,9 @@ public override long Position
[DllImport("archive")]
private static extern int archive_read_open_filename(IntPtr a, IntPtr filename, int blocksize);

[DllImport("archive")]
private static extern int archive_read_open_filenames(IntPtr a, IntPtr filename, int blocksize);

[DllImport("archive")]
private static extern int archive_read_data(IntPtr a, ref byte buff, int size);

Expand All @@ -162,3 +179,30 @@ public override long Position
[DllImport("archive")]
private static extern IntPtr archive_error_string(IntPtr a);
}

public class DisposableStringArray : IDisposable
{
private readonly IntPtr[] backing;
private readonly GCHandle handle;
private readonly SafeStringBuffer[] strings;

public DisposableStringArray(string[] a)
{
backing = new IntPtr[a.Length+1];
strings = a.Select(s => new SafeStringBuffer(s)).ToArray();
for (int i=0;i<strings.Length;i++)
backing[i] = strings[i].Ptr;
backing[strings.Length] = IntPtr.Zero;
handle = GCHandle.Alloc(backing, GCHandleType.Pinned);
}

public IntPtr Ptr => handle.AddrOfPinnedObject();

public void Dispose()
{
GC.SuppressFinalize(this);
handle.Free();
foreach (var s in strings)
s.Dispose();
}
}
2 changes: 1 addition & 1 deletion LibArchive.Net/SafeStringBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class SafeStringBuffer : SafeHandleZeroOrMinusOneIsInvalid
public SafeStringBuffer(string s) : base(true)
{
if (s is null)
throw new ArgumentException(nameof(s));
throw new ArgumentNullException(nameof(s));
handle = Marshal.StringToCoTaskMemUTF8(s);
}

Expand Down
32 changes: 0 additions & 32 deletions Test.LibArchive.Net/7zTests.cs

This file was deleted.

49 changes: 49 additions & 0 deletions Test.LibArchive.Net/ReaderTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System.Security.Cryptography;
using System.Text;
using LibArchive.Net;
using NUnit.Framework;

namespace Test.LibArchive.Net;

public class SevenZipTests
{
private readonly SHA256 hash = SHA256.Create();

[Test]
public void Test7z()
{
using var lar = new LibArchiveReader("7ztest.7z");
foreach (var e in lar.Entries())
{
using var s = e.Stream;
StringBuilder sb = new(e.Name,e.Name.Length+33);
sb.Append(' ');
foreach (var d in hash.ComputeHash(s))
{
sb.Append(d.ToString("x2"));
}
Console.WriteLine(sb);
}
Assert.Pass();
}

[Test]
public void TestMultiRar()
{
var files = Directory.GetFiles(TestContext.CurrentContext.TestDirectory, "rartest*.rar");
Array.Sort(files);
Assert.That(files, Has.Length.EqualTo(4), "Expected 4 RAR segments");
using var rar = new LibArchiveReader(files);
foreach (var e in rar.Entries())
{
using var s = e.Stream;
StringBuilder sb = new(e.Name, e.Name.Length + 33);
sb.Append(' ');
foreach (var d in hash.ComputeHash(s))
{
sb.Append(d.ToString("x2"));
}
Console.WriteLine(sb);
}
}
}
4 changes: 4 additions & 0 deletions Test.LibArchive.Net/Test.LibArchive.Net.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,9 @@
</ItemGroup>
<ItemGroup>
<None Update="7ztest.7z" CopyToOutputDirectory="PreserveNewest" />
<None Update="rartest.part00001.rar" CopyToOutputDirectory="PreserveNewest" />
<None Update="rartest.part00002.rar" CopyToOutputDirectory="PreserveNewest" />
<None Update="rartest.part00003.rar" CopyToOutputDirectory="PreserveNewest" />
<None Update="rartest.part00004.rar" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
</Project>
1 change: 0 additions & 1 deletion Test.LibArchive.Net/Usings.cs

This file was deleted.

Binary file added Test.LibArchive.Net/rartest.part00001.rar
Binary file not shown.
Binary file added Test.LibArchive.Net/rartest.part00002.rar
Binary file not shown.
Binary file added Test.LibArchive.Net/rartest.part00003.rar
Binary file not shown.
Binary file added Test.LibArchive.Net/rartest.part00004.rar
Binary file not shown.

0 comments on commit 72a4536

Please sign in to comment.