mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-04 05:25:00 +00:00
Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d17d09455 | ||
|
|
05208ccd9b | ||
|
|
a1e7c0068d | ||
|
|
e6bec19946 | ||
|
|
ec2be2869f | ||
|
|
ce5432ed73 | ||
|
|
b6e0ad89ce | ||
|
|
2745bfa19b | ||
|
|
3cdc4b38a6 | ||
|
|
fc1ca808d7 | ||
|
|
6983e66037 | ||
|
|
01f7336d09 | ||
|
|
1561bba538 | ||
|
|
3ecf8a5e0c | ||
|
|
e2095fc416 | ||
|
|
8398d40106 | ||
|
|
134fa8892f | ||
|
|
ea5c8dc063 | ||
|
|
0209d00164 | ||
|
|
a8d065dc9e | ||
|
|
7bd9711ade | ||
|
|
61802eadb4 | ||
|
|
b425659058 | ||
|
|
3e32e3d7b1 | ||
|
|
1b661c9df1 | ||
|
|
54fc26b93d | ||
|
|
161f99bbad | ||
|
|
c012db0776 | ||
|
|
8ee257d299 | ||
|
|
f9522107c3 | ||
|
|
e07046a37a | ||
|
|
ad6d0d9ae8 | ||
|
|
fdc33e91bd | ||
|
|
e6dded826b |
6
.github/workflows/dotnetcore.yml
vendored
6
.github/workflows/dotnetcore.yml
vendored
@@ -12,13 +12,9 @@ jobs:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 5.0.101
|
||||
dotnet-version: 5.0.401
|
||||
- run: dotnet run -p build/build.csproj
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ matrix.os }}-sharpcompress.nupkg
|
||||
path: artifacts/*
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ matrix.os }}-sharpcompress.snupkg
|
||||
path: artifacts/*
|
||||
|
||||
@@ -49,20 +49,20 @@ class Program
|
||||
Target(Build, DependsOn(Format),
|
||||
framework =>
|
||||
{
|
||||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && framework == "net46")
|
||||
{
|
||||
return;
|
||||
}
|
||||
Run("dotnet", "build src/SharpCompress/SharpCompress.csproj -c Release");
|
||||
});
|
||||
|
||||
Target(Test, DependsOn(Build), ForEach("net5.0"),
|
||||
Target(Test, DependsOn(Build), ForEach("net5.0", "net461"),
|
||||
framework =>
|
||||
{
|
||||
IEnumerable<string> GetFiles(string d)
|
||||
{
|
||||
return Glob.Files(".", d);
|
||||
}
|
||||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && framework == "net461")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var file in GetFiles("**/*.Test.csproj"))
|
||||
{
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Bullseye" Version="3.6.0" />
|
||||
<PackageReference Include="Bullseye" Version="3.8.0" />
|
||||
<PackageReference Include="Glob" Version="1.1.8" />
|
||||
<PackageReference Include="SimpleExec" Version="6.4.0" />
|
||||
<PackageReference Include="SimpleExec" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "5.0.101"
|
||||
"version": "5.0.300",
|
||||
"rollForward": "latestFeature"
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
#if !NETSTANDARD2_0 && !NETSTANDARD2_1
|
||||
#if !NETSTANDARD2_0 && !NETSTANDARD2_1 && !NETFRAMEWORK
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
#endif
|
||||
@@ -22,7 +22,7 @@ namespace SharpCompress.Algorithms
|
||||
/// </summary>
|
||||
public const uint SeedValue = 1U;
|
||||
|
||||
#if !NETSTANDARD2_0 && !NETSTANDARD2_1
|
||||
#if !NETSTANDARD2_0 && !NETSTANDARD2_1 && !NETFRAMEWORK
|
||||
private const int MinBufferSize = 64;
|
||||
#endif
|
||||
|
||||
@@ -51,12 +51,7 @@ namespace SharpCompress.Algorithms
|
||||
/// <returns>The <see cref="uint"/>.</returns>
|
||||
public static uint Calculate(uint adler, ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
if (buffer.IsEmpty)
|
||||
{
|
||||
return SeedValue;
|
||||
}
|
||||
|
||||
#if !NETSTANDARD2_0 && !NETSTANDARD2_1
|
||||
#if !NETSTANDARD2_0 && !NETSTANDARD2_1 && !NETFRAMEWORK
|
||||
if (Sse3.IsSupported && buffer.Length >= MinBufferSize)
|
||||
{
|
||||
return CalculateSse(adler, buffer);
|
||||
@@ -69,7 +64,7 @@ namespace SharpCompress.Algorithms
|
||||
}
|
||||
|
||||
// Based on https://github.com/chromium/chromium/blob/master/third_party/zlib/adler32_simd.c
|
||||
#if !NETSTANDARD2_0 && !NETSTANDARD2_1
|
||||
#if !NETSTANDARD2_0 && !NETSTANDARD2_1 && !NETFRAMEWORK
|
||||
private static unsafe uint CalculateSse(uint adler, ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
uint s1 = adler & 0xFFFF;
|
||||
@@ -282,4 +277,4 @@ namespace SharpCompress.Algorithms
|
||||
return (s2 << 16) | s1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ using SharpCompress.Readers.Rar;
|
||||
|
||||
namespace SharpCompress.Archives.Rar
|
||||
{
|
||||
public class
|
||||
public class
|
||||
RarArchive : AbstractArchive<RarArchiveEntry, RarVolume>
|
||||
{
|
||||
internal Lazy<IRarUnpack> UnpackV2017 { get; } = new Lazy<IRarUnpack>(() => new SharpCompress.Compressors.Rar.UnpackV2017.Unpack());
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace SharpCompress.Common
|
||||
Password = password;
|
||||
}
|
||||
|
||||
#if !NET461
|
||||
#if !NETFRAMEWORK
|
||||
static ArchiveEncoding()
|
||||
{
|
||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||
|
||||
@@ -14,14 +14,25 @@ namespace SharpCompress.Common
|
||||
Action<string, ExtractionOptions?> write)
|
||||
{
|
||||
string destinationFileName;
|
||||
string file = Path.GetFileName(entry.Key);
|
||||
string fullDestinationDirectoryPath = Path.GetFullPath(destinationDirectory);
|
||||
|
||||
//check for trailing slash.
|
||||
if (fullDestinationDirectoryPath[fullDestinationDirectoryPath.Length - 1] != Path.DirectorySeparatorChar)
|
||||
{
|
||||
fullDestinationDirectoryPath += Path.DirectorySeparatorChar;
|
||||
}
|
||||
|
||||
if (!Directory.Exists(fullDestinationDirectoryPath))
|
||||
{
|
||||
throw new ExtractionException($"Directory does not exist to extract to: {fullDestinationDirectoryPath}");
|
||||
}
|
||||
|
||||
options ??= new ExtractionOptions()
|
||||
{
|
||||
Overwrite = true
|
||||
};
|
||||
|
||||
string file = Path.GetFileName(entry.Key);
|
||||
if (options.ExtractFullPath)
|
||||
{
|
||||
string folder = Path.GetDirectoryName(entry.Key)!;
|
||||
|
||||
@@ -63,6 +63,8 @@ namespace SharpCompress.Common.Zip.Headers
|
||||
var zip64ExtraData = Extra.OfType<Zip64ExtendedInformationExtraField>().FirstOrDefault();
|
||||
if (zip64ExtraData != null)
|
||||
{
|
||||
zip64ExtraData.Process(UncompressedSize, CompressedSize, RelativeOffsetOfEntryHeader, DiskNumberStart);
|
||||
|
||||
if (CompressedSize == uint.MaxValue)
|
||||
{
|
||||
CompressedSize = zip64ExtraData.CompressedSize;
|
||||
|
||||
@@ -53,6 +53,8 @@ namespace SharpCompress.Common.Zip.Headers
|
||||
var zip64ExtraData = Extra.OfType<Zip64ExtendedInformationExtraField>().FirstOrDefault();
|
||||
if (zip64ExtraData != null)
|
||||
{
|
||||
zip64ExtraData.Process(UncompressedSize, CompressedSize, 0, 0);
|
||||
|
||||
if (CompressedSize == uint.MaxValue)
|
||||
{
|
||||
CompressedSize = zip64ExtraData.CompressedSize;
|
||||
|
||||
@@ -66,46 +66,74 @@ namespace SharpCompress.Common.Zip.Headers
|
||||
public Zip64ExtendedInformationExtraField(ExtraDataType type, ushort length, byte[] dataBytes)
|
||||
: base(type, length, dataBytes)
|
||||
{
|
||||
Process();
|
||||
}
|
||||
|
||||
private void Process()
|
||||
// From the spec, values are only in the extradata if the standard
|
||||
// value is set to 0xFFFFFFFF (or 0xFFFF for the Disk Start Number).
|
||||
// Values, if present, must appear in the following order:
|
||||
// - Original Size
|
||||
// - Compressed Size
|
||||
// - Relative Header Offset
|
||||
// - Disk Start Number
|
||||
public void Process(long uncompressedFileSize, long compressedFileSize, long relativeHeaderOffset, ushort diskNumber)
|
||||
{
|
||||
if (DataBytes.Length >= 8)
|
||||
var bytesRequired = ((uncompressedFileSize == uint.MaxValue) ? 8 : 0)
|
||||
+ ((compressedFileSize == uint.MaxValue) ? 8 : 0)
|
||||
+ ((relativeHeaderOffset == uint.MaxValue) ? 8 : 0)
|
||||
+ ((diskNumber == ushort.MaxValue) ? 4 : 0);
|
||||
var currentIndex = 0;
|
||||
|
||||
if (bytesRequired > DataBytes.Length)
|
||||
{
|
||||
UncompressedSize = BinaryPrimitives.ReadInt64LittleEndian(DataBytes);
|
||||
throw new ArchiveException("Zip64 extended information extra field is not large enough for the required information");
|
||||
}
|
||||
|
||||
if (DataBytes.Length >= 16)
|
||||
if (uncompressedFileSize == uint.MaxValue)
|
||||
{
|
||||
CompressedSize = BinaryPrimitives.ReadInt64LittleEndian(DataBytes.AsSpan(8));
|
||||
UncompressedSize = BinaryPrimitives.ReadInt64LittleEndian(DataBytes.AsSpan(currentIndex));
|
||||
currentIndex += 8;
|
||||
}
|
||||
|
||||
if (DataBytes.Length >= 24)
|
||||
if (compressedFileSize == uint.MaxValue)
|
||||
{
|
||||
RelativeOffsetOfEntryHeader = BinaryPrimitives.ReadInt64LittleEndian(DataBytes.AsSpan(16));
|
||||
CompressedSize = BinaryPrimitives.ReadInt64LittleEndian(DataBytes.AsSpan(currentIndex));
|
||||
currentIndex += 8;
|
||||
}
|
||||
|
||||
if (DataBytes.Length >= 28)
|
||||
if (relativeHeaderOffset == uint.MaxValue)
|
||||
{
|
||||
VolumeNumber = BinaryPrimitives.ReadUInt32LittleEndian(DataBytes.AsSpan(24));
|
||||
RelativeOffsetOfEntryHeader = BinaryPrimitives.ReadInt64LittleEndian(DataBytes.AsSpan(currentIndex));
|
||||
currentIndex += 8;
|
||||
}
|
||||
|
||||
switch (DataBytes.Length)
|
||||
if (diskNumber == ushort.MaxValue)
|
||||
{
|
||||
case 8:
|
||||
case 16:
|
||||
case 24:
|
||||
case 28:
|
||||
break;
|
||||
default:
|
||||
throw new ArchiveException($"Unexpected size of of Zip64 extended information extra field: {DataBytes.Length}");
|
||||
VolumeNumber = BinaryPrimitives.ReadUInt32LittleEndian(DataBytes.AsSpan(currentIndex));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uncompressed file size. Only valid after <see cref="Process(long, long, long, ushort)"/> has been called and if the
|
||||
/// original entry header had a corresponding 0xFFFFFFFF value.
|
||||
/// </summary>
|
||||
public long UncompressedSize { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Compressed file size. Only valid after <see cref="Process(long, long, long, ushort)"/> has been called and if the
|
||||
/// original entry header had a corresponding 0xFFFFFFFF value.
|
||||
/// </summary>
|
||||
public long CompressedSize { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Relative offset of the entry header. Only valid after <see cref="Process(long, long, long, ushort)"/> has been called and if the
|
||||
/// original entry header had a corresponding 0xFFFFFFFF value.
|
||||
/// </summary>
|
||||
public long RelativeOffsetOfEntryHeader { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Volume number. Only valid after <see cref="Process(long, long, long, ushort)"/> has been called and if the
|
||||
/// original entry header had a corresponding 0xFFFF value.
|
||||
/// </summary>
|
||||
public uint VolumeNumber { get; private set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -105,6 +105,6 @@ namespace SharpCompress.Common.Zip.Headers
|
||||
|
||||
internal ZipFilePart Part { get; set; }
|
||||
|
||||
internal bool IsZip64 => CompressedSize == uint.MaxValue;
|
||||
internal bool IsZip64 => CompressedSize >= uint.MaxValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace SharpCompress.Common.Zip
|
||||
// ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR should be before the EOCD
|
||||
stream.Seek(eocd_location - ZIP64_EOCD_LENGTH - 4, SeekOrigin.Begin);
|
||||
uint zip64_locator = reader.ReadUInt32();
|
||||
if( zip64_locator != ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR )
|
||||
if (zip64_locator != ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR)
|
||||
{
|
||||
throw new ArchiveException("Failed to locate the Zip64 Directory Locator");
|
||||
}
|
||||
@@ -86,11 +86,11 @@ namespace SharpCompress.Common.Zip
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsMatch( byte[] haystack, int position, byte[] needle)
|
||||
private static bool IsMatch(byte[] haystack, int position, byte[] needle)
|
||||
{
|
||||
for( int i = 0; i < needle.Length; i++ )
|
||||
for (int i = 0; i < needle.Length; i++)
|
||||
{
|
||||
if( haystack[ position + i ] != needle[ i ] )
|
||||
if (haystack[position + i] != needle[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -117,11 +117,12 @@ namespace SharpCompress.Common.Zip
|
||||
// Search in reverse
|
||||
Array.Reverse(seek);
|
||||
|
||||
var max_search_area = len - MINIMUM_EOCD_LENGTH;
|
||||
// don't exclude the minimum eocd region, otherwise you fail to locate the header in empty zip files
|
||||
var max_search_area = len; // - MINIMUM_EOCD_LENGTH;
|
||||
|
||||
for( int pos_from_end = 0; pos_from_end < max_search_area; ++pos_from_end)
|
||||
for (int pos_from_end = 0; pos_from_end < max_search_area; ++pos_from_end)
|
||||
{
|
||||
if( IsMatch(seek, pos_from_end, needle) )
|
||||
if (IsMatch(seek, pos_from_end, needle))
|
||||
{
|
||||
stream.Seek(-pos_from_end, SeekOrigin.End);
|
||||
return;
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace SharpCompress.Compressors.BZip2
|
||||
stream.SetLength(value);
|
||||
}
|
||||
|
||||
#if !NET461 && !NETSTANDARD2_0
|
||||
#if !NETFRAMEWORK && !NETSTANDARD2_0
|
||||
|
||||
public override int Read(Span<byte> buffer)
|
||||
{
|
||||
@@ -123,4 +123,4 @@ namespace SharpCompress.Compressors.BZip2
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,13 +502,37 @@ namespace SharpCompress.Compressors.Deflate
|
||||
throw new ZlibException("Cannot Read after Writing.");
|
||||
}
|
||||
|
||||
int rc = 0;
|
||||
|
||||
// set up the output of the deflate/inflate codec:
|
||||
_z.OutputBuffer = buffer;
|
||||
_z.NextOut = offset;
|
||||
_z.AvailableBytesOut = count;
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (nomoreinput && _wantCompress)
|
||||
{
|
||||
return 0; // workitem 8557
|
||||
// no more input data available; therefore we flush to
|
||||
// try to complete the read
|
||||
rc = _z.Deflate(FlushType.Finish);
|
||||
|
||||
if (rc != ZlibConstants.Z_OK && rc != ZlibConstants.Z_STREAM_END)
|
||||
{
|
||||
throw new ZlibException(String.Format("Deflating: rc={0} msg={1}", rc, _z.Message));
|
||||
}
|
||||
|
||||
rc = (count - _z.AvailableBytesOut);
|
||||
|
||||
// calculate CRC after reading
|
||||
if (crc != null)
|
||||
{
|
||||
crc.SlurpBlock(buffer, offset, rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
if (buffer is null)
|
||||
{
|
||||
@@ -527,13 +551,6 @@ namespace SharpCompress.Compressors.Deflate
|
||||
throw new ArgumentOutOfRangeException(nameof(count));
|
||||
}
|
||||
|
||||
int rc = 0;
|
||||
|
||||
// set up the output of the deflate/inflate codec:
|
||||
_z.OutputBuffer = buffer;
|
||||
_z.NextOut = offset;
|
||||
_z.AvailableBytesOut = count;
|
||||
|
||||
// This is necessary in case _workingBuffer has been resized. (new byte[])
|
||||
// (The first reference to _workingBuffer goes through the private accessor which
|
||||
// may initialize it.)
|
||||
|
||||
@@ -118,7 +118,7 @@ namespace SharpCompress.Compressors.LZMA
|
||||
public override void SetLength(long value) => throw new NotImplementedException();
|
||||
|
||||
|
||||
#if !NET461 && !NETSTANDARD2_0
|
||||
#if !NETFRAMEWORK && !NETSTANDARD2_0
|
||||
|
||||
public override int Read(Span<byte> buffer)
|
||||
{
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace SharpCompress.Crypto
|
||||
|
||||
public override void SetLength(long value) => throw new NotSupportedException();
|
||||
|
||||
#if !NET461 && !NETSTANDARD2_0
|
||||
#if !NETFRAMEWORK && !NETSTANDARD2_0
|
||||
|
||||
public override void Write(ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace SharpCompress.IO
|
||||
Stream.Write(buffer, offset, count);
|
||||
}
|
||||
|
||||
#if !NET461 && !NETSTANDARD2_0
|
||||
#if !NETFRAMEWORK && !NETSTANDARD2_0
|
||||
|
||||
public override int Read(Span<byte> buffer)
|
||||
{
|
||||
@@ -72,4 +72,4 @@ namespace SharpCompress.IO
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#if NET461 || NETSTANDARD2_0
|
||||
#if NETFRAMEWORK || NETSTANDARD2_0
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#if NET461 || NETSTANDARD2_0
|
||||
#if NETFRAMEWORK || NETSTANDARD2_0
|
||||
|
||||
namespace SharpCompress
|
||||
{
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
<PropertyGroup>
|
||||
<AssemblyTitle>SharpCompress - Pure C# Decompression/Compression</AssemblyTitle>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<VersionPrefix>0.28.2</VersionPrefix>
|
||||
<AssemblyVersion>0.28.2</AssemblyVersion>
|
||||
<FileVersion>0.28.2</FileVersion>
|
||||
<VersionPrefix>0.30.1</VersionPrefix>
|
||||
<AssemblyVersion>0.30.1</AssemblyVersion>
|
||||
<FileVersion>0.30.1</FileVersion>
|
||||
<Authors>Adam Hathcock</Authors>
|
||||
<TargetFrameworks>netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0</TargetFrameworks>
|
||||
<TargetFrameworks>net461;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0</TargetFrameworks>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
<AssemblyName>SharpCompress</AssemblyName>
|
||||
@@ -18,7 +18,7 @@
|
||||
<PackageLicense>https://github.com/adamhathcock/sharpcompress/blob/master/LICENSE.txt</PackageLicense>
|
||||
<GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
|
||||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
|
||||
<Description>SharpCompress is a compression library for NET Standard 2.0/2.1//NET 4.6 that can unrar, decompress 7zip, decompress xz, zip/unzip, tar/untar lzip/unlzip, bzip2/unbzip2 and gzip/ungzip with forward-only reading and file random access APIs. Write support for zip/tar/bzip2/gzip is implemented.</Description>
|
||||
<Description>SharpCompress is a compression library for NET Standard 2.0/2.1/NET 5.0 that can unrar, decompress 7zip, decompress xz, zip/unzip, tar/untar lzip/unlzip, bzip2/unbzip2 and gzip/ungzip with forward-only reading and file random access APIs. Write support for zip/tar/bzip2/gzip is implemented.</Description>
|
||||
<LangVersion>9</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
@@ -37,5 +37,8 @@
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" />
|
||||
<PackageReference Include="System.Memory" Version="4.5.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(VersionlessImplicitFrameworkDefine)' == 'NETFRAMEWORK' ">
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" />
|
||||
<PackageReference Include="System.Memory" Version="4.5.4" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -280,7 +280,7 @@ namespace SharpCompress
|
||||
{
|
||||
return ArrayPool<byte>.Shared.Rent(81920);
|
||||
}
|
||||
|
||||
|
||||
public static bool ReadFully(this Stream stream, byte[] buffer)
|
||||
{
|
||||
int total = 0;
|
||||
@@ -295,7 +295,7 @@ namespace SharpCompress
|
||||
}
|
||||
return (total >= buffer.Length);
|
||||
}
|
||||
|
||||
|
||||
public static bool ReadFully(this Stream stream, Span<byte> buffer)
|
||||
{
|
||||
int total = 0;
|
||||
|
||||
@@ -87,18 +87,15 @@ namespace SharpCompress.Writers.Tar
|
||||
header.Name = NormalizeFilename(filename);
|
||||
header.Size = realSize;
|
||||
header.Write(OutputStream);
|
||||
|
||||
size = source.TransferTo(OutputStream);
|
||||
PadTo512(size.Value, false);
|
||||
PadTo512(size.Value);
|
||||
}
|
||||
|
||||
private void PadTo512(long size, bool forceZeros)
|
||||
private void PadTo512(long size)
|
||||
{
|
||||
int zeros = (int)size % 512;
|
||||
if (zeros == 0 && !forceZeros)
|
||||
{
|
||||
return;
|
||||
}
|
||||
zeros = 512 - zeros;
|
||||
int zeros = unchecked((int)(((size + 511L) & ~511L) - size));
|
||||
|
||||
OutputStream.Write(stackalloc byte[zeros]);
|
||||
}
|
||||
|
||||
@@ -108,8 +105,7 @@ namespace SharpCompress.Writers.Tar
|
||||
{
|
||||
if (finalizeArchiveOnClose)
|
||||
{
|
||||
PadTo512(0, true);
|
||||
PadTo512(0, true);
|
||||
OutputStream.Write(stackalloc byte[1024]);
|
||||
}
|
||||
switch (OutputStream)
|
||||
{
|
||||
|
||||
@@ -238,13 +238,13 @@ namespace SharpCompress.Writers.Zip
|
||||
private void WriteEndRecord(ulong size)
|
||||
{
|
||||
|
||||
var zip64 = isZip64 || entries.Count > ushort.MaxValue || streamPosition >= uint.MaxValue || size >= uint.MaxValue;
|
||||
var zip64EndOfCentralDirectoryNeeded = entries.Count > ushort.MaxValue || streamPosition >= uint.MaxValue || size >= uint.MaxValue;
|
||||
|
||||
var sizevalue = size >= uint.MaxValue ? uint.MaxValue : (uint)size;
|
||||
var streampositionvalue = streamPosition >= uint.MaxValue ? uint.MaxValue : (uint)streamPosition;
|
||||
|
||||
Span<byte> intBuf = stackalloc byte[8];
|
||||
if (zip64)
|
||||
if (zip64EndOfCentralDirectoryNeeded)
|
||||
{
|
||||
var recordlen = 2 + 2 + 4 + 4 + 8 + 8 + 8 + 8;
|
||||
|
||||
@@ -281,8 +281,7 @@ namespace SharpCompress.Writers.Zip
|
||||
BinaryPrimitives.WriteUInt32LittleEndian(intBuf, 1);
|
||||
OutputStream.Write(intBuf.Slice(0, 4)); // Number of disks
|
||||
|
||||
streamPosition += recordlen + (4 + 4 + 8 + 4);
|
||||
streampositionvalue = streamPosition >= uint.MaxValue ? uint.MaxValue : (uint)streampositionvalue;
|
||||
streamPosition += 4 + 8 + recordlen + (4 + 4 + 8 + 4);
|
||||
}
|
||||
|
||||
// Write normal end of central directory record
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net5.0</TargetFrameworks>
|
||||
<TargetFrameworks>net5.0;net461</TargetFrameworks>
|
||||
<AssemblyName>SharpCompress.Test</AssemblyName>
|
||||
<AssemblyOriginatorKeyFile>../../SharpCompress.snk</AssemblyOriginatorKeyFile>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
@@ -12,13 +12,13 @@
|
||||
<ProjectReference Include="..\..\src\SharpCompress\SharpCompress.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="FluentAssertions" Version="6.2.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="Xunit.SkippableFact" Version="1.4.13" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(VersionlessImplicitFrameworkDefine)' != 'NETFRAMEWORK' ">
|
||||
<PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
88
tests/SharpCompress.Test/Streams/ZlibBaseStreamTests.cs
Normal file
88
tests/SharpCompress.Test/Streams/ZlibBaseStreamTests.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using FluentAssertions;
|
||||
using SharpCompress.Compressors;
|
||||
using SharpCompress.Compressors.Deflate;
|
||||
using SharpCompress.IO;
|
||||
using Xunit;
|
||||
|
||||
namespace SharpCompress.Test.Streams
|
||||
{
|
||||
public class ZLibBaseStreamTests
|
||||
{
|
||||
[Fact]
|
||||
public void TestChunkedZlibCompressesEverything()
|
||||
{
|
||||
byte[] plainData = new byte[] { 0xf7, 0x1b, 0xda, 0x0f, 0xb6, 0x2b, 0x3d, 0x91, 0xd7, 0xe1, 0xb5, 0x11, 0x34, 0x5a, 0x51, 0x3f, 0x8b, 0xce, 0x49, 0xd2 };
|
||||
byte[] buf = new byte[plainData.Length * 2];
|
||||
|
||||
MemoryStream plainStream1 = new MemoryStream(plainData);
|
||||
DeflateStream compressor1 = new DeflateStream(plainStream1, CompressionMode.Compress);
|
||||
// This is enough to read the entire data
|
||||
int realCompressedSize = compressor1.Read(buf, 0, plainData.Length * 2);
|
||||
|
||||
MemoryStream plainStream2 = new MemoryStream(plainData);
|
||||
DeflateStream compressor2 = new DeflateStream(plainStream2, CompressionMode.Compress);
|
||||
int total = 0;
|
||||
int r = -1; // Jumpstart
|
||||
while (r != 0)
|
||||
{
|
||||
// Reading in chunks
|
||||
r = compressor2.Read(buf, 0, plainData.Length);
|
||||
total += r;
|
||||
}
|
||||
|
||||
Assert.Equal(total, realCompressedSize);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Zlib_should_read_the_previously_written_message()
|
||||
{
|
||||
var message = new string('a', 131073); // 131073 causes the failure, but 131072 (-1) doesn't
|
||||
var bytes = Encoding.ASCII.GetBytes(message);
|
||||
|
||||
using (var inputStream = new MemoryStream(bytes))
|
||||
{
|
||||
using (var compressedStream = new MemoryStream())
|
||||
using (var byteBufferStream = new BufferedStream(inputStream)) // System.IO
|
||||
{
|
||||
Compress(byteBufferStream, compressedStream, compressionLevel: 1);
|
||||
compressedStream.Position = 0;
|
||||
|
||||
using (var decompressedStream = new MemoryStream())
|
||||
{
|
||||
Decompress(compressedStream, decompressedStream);
|
||||
|
||||
byteBufferStream.Position = 0;
|
||||
var result = Encoding.ASCII.GetString(GetBytes(byteBufferStream));
|
||||
result.Should().Be(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Compress(Stream input, Stream output, int compressionLevel)
|
||||
{
|
||||
using (var zlibStream = new ZlibStream(new NonDisposingStream(output), CompressionMode.Compress, (CompressionLevel)compressionLevel))
|
||||
{
|
||||
zlibStream.FlushMode = FlushType.Sync;
|
||||
input.CopyTo(zlibStream);
|
||||
}
|
||||
}
|
||||
|
||||
public void Decompress(Stream input, Stream output)
|
||||
{
|
||||
using (var zlibStream = new ZlibStream(new NonDisposingStream(input), CompressionMode.Decompress))
|
||||
{
|
||||
zlibStream.CopyTo(output);
|
||||
}
|
||||
}
|
||||
|
||||
byte[] GetBytes(BufferedStream stream)
|
||||
{
|
||||
byte[] bytes = new byte[stream.Length];
|
||||
stream.Read(bytes, 0, (int)stream.Length);
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -190,7 +190,7 @@ namespace SharpCompress.Test.Tar
|
||||
}
|
||||
}
|
||||
|
||||
#if !NET461
|
||||
#if !NETFRAMEWORK
|
||||
[Fact]
|
||||
public void Tar_GZip_With_Symlink_Entries()
|
||||
{
|
||||
|
||||
@@ -290,6 +290,28 @@ namespace SharpCompress.Test.Zip
|
||||
Directory.Delete(SCRATCH_FILES_PATH, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an empty zip file and attempts to read it right afterwards.
|
||||
/// Ensures that parsing file headers works even in that case
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Zip_Create_Empty_And_Read()
|
||||
{
|
||||
var archive = ZipArchive.Create();
|
||||
|
||||
var archiveStream = new MemoryStream();
|
||||
|
||||
archive.SaveTo(archiveStream, CompressionType.LZMA);
|
||||
|
||||
archiveStream.Position = 0;
|
||||
|
||||
var readArchive = ArchiveFactory.Open(archiveStream);
|
||||
|
||||
var count = readArchive.Entries.Count();
|
||||
|
||||
Assert.Equal(0, count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Zip_Create_New_Add_Remove()
|
||||
{
|
||||
@@ -570,11 +592,29 @@ namespace SharpCompress.Test.Zip
|
||||
{
|
||||
string zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.LongComment.zip");
|
||||
|
||||
using(ZipArchive za = ZipArchive.Open(zipPath))
|
||||
using (ZipArchive za = ZipArchive.Open(zipPath))
|
||||
{
|
||||
var count = za.Entries.Count;
|
||||
Assert.Equal(1, count);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Zip_Zip64_CompressedSizeExtraOnly_Read()
|
||||
{
|
||||
string zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.zip64.compressedonly.zip");
|
||||
|
||||
using (ZipArchive za = ZipArchive.Open(zipPath))
|
||||
{
|
||||
var firstEntry = za.Entries.First(x => x.Key == "test/test.txt");
|
||||
|
||||
using (var memoryStream = new MemoryStream())
|
||||
using (var firstStream = firstEntry.OpenEntryStream())
|
||||
{
|
||||
firstStream.CopyTo(memoryStream);
|
||||
Assert.Equal(15, memoryStream.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,16 +268,16 @@ namespace SharpCompress.Test.Zip
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void Zip_Deflate_ZipCrypto_Read()
|
||||
{
|
||||
int count = 0;
|
||||
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "zipcrypto.zip")))
|
||||
using (var reader = ZipReader.Open(stream, new ReaderOptions()
|
||||
{
|
||||
Password = "test"
|
||||
}))
|
||||
{
|
||||
Password = "test"
|
||||
}))
|
||||
{
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
|
||||
BIN
tests/TestArchives/Archives/Zip.zip64.compressedonly.zip
Normal file
BIN
tests/TestArchives/Archives/Zip.zip64.compressedonly.zip
Normal file
Binary file not shown.
Reference in New Issue
Block a user