mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-12 05:25:03 +00:00
162 lines
5.3 KiB
C#
162 lines
5.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using SharpCompress.Common;
|
|
using SharpCompress.Common.Rar;
|
|
using SharpCompress.Common.Rar.Headers;
|
|
|
|
namespace SharpCompress.Compressor.Rar
|
|
{
|
|
internal class MultiVolumeReadOnlyStream : Stream
|
|
{
|
|
private long currentPosition;
|
|
private long maxPosition;
|
|
|
|
private IEnumerator<RarFilePart> filePartEnumerator;
|
|
private Stream currentStream;
|
|
|
|
private readonly IExtractionListener streamListener;
|
|
|
|
private long currentPartTotalReadBytes;
|
|
private long currentEntryTotalReadBytes;
|
|
|
|
internal MultiVolumeReadOnlyStream(IEnumerable<RarFilePart> parts, IExtractionListener streamListener)
|
|
{
|
|
this.streamListener = streamListener;
|
|
|
|
filePartEnumerator = parts.GetEnumerator();
|
|
filePartEnumerator.MoveNext();
|
|
InitializeNextFilePart();
|
|
}
|
|
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
base.Dispose(disposing);
|
|
if (disposing)
|
|
{
|
|
if (filePartEnumerator != null)
|
|
{
|
|
filePartEnumerator.Dispose();
|
|
filePartEnumerator = null;
|
|
}
|
|
if (currentStream != null)
|
|
{
|
|
currentStream.Dispose();
|
|
currentStream = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void InitializeNextFilePart()
|
|
{
|
|
maxPosition = filePartEnumerator.Current.FileHeader.CompressedSize;
|
|
currentPosition = 0;
|
|
if (currentStream != null)
|
|
{
|
|
currentStream.Dispose();
|
|
}
|
|
currentStream = filePartEnumerator.Current.GetCompressedStream();
|
|
|
|
currentPartTotalReadBytes = 0;
|
|
|
|
streamListener.FireFilePartExtractionBegin(filePartEnumerator.Current.FilePartName,
|
|
filePartEnumerator.Current.FileHeader.CompressedSize,
|
|
filePartEnumerator.Current.FileHeader.UncompressedSize);
|
|
}
|
|
|
|
public override int Read(byte[] buffer, int offset, int count)
|
|
{
|
|
int totalRead = 0;
|
|
int currentOffset = offset;
|
|
int currentCount = count;
|
|
while (currentCount > 0)
|
|
{
|
|
int readSize = currentCount;
|
|
if (currentCount > maxPosition - currentPosition)
|
|
{
|
|
readSize = (int) (maxPosition - currentPosition);
|
|
}
|
|
|
|
int read = currentStream.Read(buffer, currentOffset, readSize);
|
|
if (read < 0)
|
|
{
|
|
throw new EndOfStreamException();
|
|
}
|
|
|
|
currentPosition += read;
|
|
currentOffset += read;
|
|
currentCount -= read;
|
|
totalRead += read;
|
|
if (((maxPosition - currentPosition) == 0)
|
|
&& filePartEnumerator.Current.FileHeader.FileFlags.HasFlag(FileFlags.SPLIT_AFTER))
|
|
{
|
|
if (filePartEnumerator.Current.FileHeader.Salt != null)
|
|
{
|
|
throw new InvalidFormatException("Sharpcompress currently does not support multi-volume decryption.");
|
|
}
|
|
string fileName = filePartEnumerator.Current.FileHeader.FileName;
|
|
if (!filePartEnumerator.MoveNext())
|
|
{
|
|
throw new InvalidFormatException(
|
|
"Multi-part rar file is incomplete. Entry expects a new volume: " + fileName);
|
|
}
|
|
InitializeNextFilePart();
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
currentPartTotalReadBytes += totalRead;
|
|
currentEntryTotalReadBytes += totalRead;
|
|
streamListener.FireCompressedBytesRead(currentPartTotalReadBytes, currentEntryTotalReadBytes);
|
|
return totalRead;
|
|
}
|
|
|
|
public override bool CanRead
|
|
{
|
|
get { return true; }
|
|
}
|
|
|
|
public override bool CanSeek
|
|
{
|
|
get { return false; }
|
|
}
|
|
|
|
public override bool CanWrite
|
|
{
|
|
get { return false; }
|
|
}
|
|
|
|
public override void Flush()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override long Length
|
|
{
|
|
get { throw new NotImplementedException(); }
|
|
}
|
|
|
|
public override long Position
|
|
{
|
|
get { throw new NotImplementedException(); }
|
|
set { throw new NotImplementedException(); }
|
|
}
|
|
|
|
public override long Seek(long offset, SeekOrigin origin)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override void SetLength(long value)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override void Write(byte[] buffer, int offset, int count)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
} |