FIx solid support. I did it wrong

This commit is contained in:
Adam Hathcock
2018-04-29 11:12:28 +01:00
parent b43d2c3d95
commit 031b3c55f6
8 changed files with 35 additions and 30 deletions

View File

@@ -64,10 +64,10 @@ namespace SharpCompress.Archives.Rar
if (IsRarV3)
{
return new RarStream(archive.UnpackV1.Value, archive.IsSolid, FileHeader, new MultiVolumeReadOnlyStream(Parts.Cast<RarFilePart>(), archive));
return new RarStream(archive.UnpackV1.Value, FileHeader, new MultiVolumeReadOnlyStream(Parts.Cast<RarFilePart>(), archive));
}
return new RarStream(archive.UnpackV2017.Value, archive.IsSolid, FileHeader, new MultiVolumeReadOnlyStream(Parts.Cast<RarFilePart>(), archive));
return new RarStream(archive.UnpackV2017.Value, FileHeader, new MultiVolumeReadOnlyStream(Parts.Cast<RarFilePart>(), archive));
}
public bool IsComplete

View File

@@ -55,20 +55,24 @@ namespace SharpCompress.Common.Rar.Headers
FileCrc = reader.ReadUInt32();
}
var us = reader.ReadRarVIntUInt16();
var compressionInfo = reader.ReadRarVIntUInt16();
// Lower 6 bits (0x003f mask) contain the version of compression algorithm, resulting in possible 0 - 63 values. Current version is 0.
// "+ 50" to not mix with old RAR format algorithms. For example,
// we may need to use the compression algorithm 15 in the future,
// but it was already used in RAR 1.5 and Unpack needs to distinguish
// them.
CompressionAlgorithm = (byte)((us & 0x3f) + 50);
CompressionAlgorithm = (byte)((compressionInfo & 0x3f) + 50);
// 7th bit (0x0040) defines the solid flag. If it is set, RAR continues to use the compression dictionary left after processing preceding files.
// It can be set only for file headers and is never set for service headers.
IsSolid = (compressionInfo & 0x40) == 0x40;
// Bits 8 - 10 (0x0380 mask) define the compression method. Currently only values 0 - 5 are used. 0 means no compression.
CompressionMethod = (byte)((us >> 7) & 0x7);
CompressionMethod = (byte)((compressionInfo >> 7) & 0x7);
// Bits 11 - 14 (0x3c00) define the minimum size of dictionary size required to extract data. Value 0 means 128 KB, 1 - 256 KB, ..., 14 - 2048 MB, 15 - 4096 MB.
WindowSize = IsDirectory ? 0 : ((size_t)0x20000) << ((us>>10) & 0xf);
WindowSize = IsDirectory ? 0 : ((size_t)0x20000) << ((compressionInfo>>10) & 0xf);
HostOs = reader.ReadRarVIntByte();
@@ -205,6 +209,7 @@ namespace SharpCompress.Common.Rar.Headers
private void ReadFromReaderV4(MarkingBinaryReader reader)
{
Flags = HeaderFlags;
IsSolid = HasFlag(FileFlagsV4.Solid);
WindowSize = IsDirectory ? 0U : ((size_t)0x10000) << ((Flags & FileFlagsV4.WindowMask) >> 5);
uint lowUncompressedSize = reader.ReadUInt32();
@@ -408,6 +413,8 @@ namespace SharpCompress.Common.Rar.Headers
//case 29: // rar 3.x compression
//case 50: // RAR 5.0 compression algorithm.
internal byte CompressionAlgorithm { get; private set; }
public bool IsSolid { get; private set; }
// unused for UnpackV1 implementation (limitation)
internal size_t WindowSize { get; private set; }

View File

@@ -5,8 +5,8 @@ namespace SharpCompress.Compressors.Rar
{
interface IRarUnpack
{
void DoUnpack(bool isSolid, FileHeader fileHeader, Stream readStream, Stream writeStream);
void DoUnpack(bool isSolid);
void DoUnpack(FileHeader fileHeader, Stream readStream, Stream writeStream);
void DoUnpack();
// eg u/i pause/resume button
bool Suspended { get; set; }

View File

@@ -9,8 +9,8 @@ namespace SharpCompress.Compressors.Rar
private readonly MultiVolumeReadOnlyStream readStream;
private uint currentCrc;
public RarCrcStream(IRarUnpack unpack, bool isSolid, FileHeader fileHeader, MultiVolumeReadOnlyStream readStream)
: base(unpack, isSolid, fileHeader, readStream)
public RarCrcStream(IRarUnpack unpack, FileHeader fileHeader, MultiVolumeReadOnlyStream readStream)
: base(unpack, fileHeader, readStream)
{
this.readStream = readStream;
ResetCrc();

View File

@@ -9,7 +9,6 @@ namespace SharpCompress.Compressors.Rar
private readonly IRarUnpack unpack;
private readonly FileHeader fileHeader;
private readonly Stream readStream;
private readonly bool isSolid;
private bool fetch;
@@ -23,14 +22,13 @@ namespace SharpCompress.Compressors.Rar
private int outTotal;
private bool isDisposed;
public RarStream(IRarUnpack unpack, bool isSolid, FileHeader fileHeader, Stream readStream)
public RarStream(IRarUnpack unpack, FileHeader fileHeader, Stream readStream)
{
this.isSolid = isSolid;
this.unpack = unpack;
this.fileHeader = fileHeader;
this.readStream = readStream;
this.fetch = true;
unpack.DoUnpack(isSolid, fileHeader, readStream, this);
unpack.DoUnpack(fileHeader, readStream, this);
this.fetch = false;
}
@@ -76,7 +74,7 @@ namespace SharpCompress.Compressors.Rar
outOffset = offset;
outCount = count;
fetch = true;
unpack.DoUnpack(isSolid);
unpack.DoUnpack();
fetch = false;
}
return outTotal;

View File

@@ -103,21 +103,21 @@ namespace SharpCompress.Compressors.Rar.UnpackV1
UnpInitData(false);
}
public void DoUnpack(bool isSolid, FileHeader fileHeader, Stream readStream, Stream writeStream)
public void DoUnpack(FileHeader fileHeader, Stream readStream, Stream writeStream)
{
this.destUnpSize = fileHeader.UncompressedSize;
this.fileHeader = fileHeader;
this.readStream = readStream;
this.writeStream = writeStream;
if (!isSolid)
if (!fileHeader.IsSolid)
{
Init(null);
}
this.suspended = false;
DoUnpack(isSolid);
DoUnpack();
}
public void DoUnpack(bool isSolid)
public void DoUnpack()
{
if (fileHeader.CompressionMethod == 0)
{
@@ -127,21 +127,21 @@ namespace SharpCompress.Compressors.Rar.UnpackV1
switch (fileHeader.CompressionAlgorithm)
{
case 15: // rar 1.5 compression
unpack15(isSolid);
unpack15(fileHeader.IsSolid);
break;
case 20: // rar 2.x compression
case 26: // files larger than 2GB
unpack20(isSolid);
unpack20(fileHeader.IsSolid);
break;
case 29: // rar 3.x compression
case 36: // alternative hash
Unpack29(isSolid);
Unpack29(fileHeader.IsSolid);
break;
case 50: // rar 5.x compression
Unpack5(isSolid);
Unpack5(fileHeader.IsSolid);
break;
default:

View File

@@ -37,7 +37,7 @@ namespace SharpCompress.Compressors.Rar.UnpackV2017
this.writeStream.Write(buf, checked((int)offset), checked((int)count));
}
public void DoUnpack(bool isSolid, FileHeader fileHeader, Stream readStream, Stream writeStream)
public void DoUnpack(FileHeader fileHeader, Stream readStream, Stream writeStream)
{
// as of 12/2017 .NET limits array indexing to using a signed integer
// MaxWinSize causes unpack to use a fragmented window when the file
@@ -51,19 +51,19 @@ namespace SharpCompress.Compressors.Rar.UnpackV2017
this.readStream = readStream;
this.writeStream = writeStream;
if (!fileHeader.IsStored) {
Init(fileHeader.WindowSize, isSolid);
Init(fileHeader.WindowSize, fileHeader.IsSolid);
}
Suspended = false;
DoUnpack(isSolid);
DoUnpack();
}
public void DoUnpack(bool isSolid)
public void DoUnpack()
{
if (this.fileHeader.IsStored)
{
UnstoreFile();
} else {
DoUnpack(this.fileHeader.CompressionAlgorithm, isSolid);
DoUnpack(this.fileHeader.CompressionAlgorithm, fileHeader.IsSolid);
}
}

View File

@@ -70,9 +70,9 @@ namespace SharpCompress.Readers.Rar
var stream = new MultiVolumeReadOnlyStream(CreateFilePartEnumerableForCurrentEntry().Cast<RarFilePart>(), this);
if (Entry.IsRarV3)
{
return CreateEntryStream(new RarCrcStream(UnpackV1.Value, volume.IsSolidArchive, Entry.FileHeader, stream));
return CreateEntryStream(new RarCrcStream(UnpackV1.Value, Entry.FileHeader, stream));
}
return CreateEntryStream(new RarCrcStream(UnpackV2017.Value, volume.IsSolidArchive, Entry.FileHeader, stream));
return CreateEntryStream(new RarCrcStream(UnpackV2017.Value, Entry.FileHeader, stream));
}
}
}