123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using SharpCompress.Common;
- using SharpCompress.Common.Rar;
- namespace SharpCompress.Compressors.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;
- }
- currentStream = null;
- }
- }
- private void InitializeNextFilePart()
- {
- maxPosition = filePartEnumerator.Current.FileHeader.CompressedSize;
- currentPosition = 0;
- currentStream = filePartEnumerator.Current.GetCompressedStream();
- currentPartTotalReadBytes = 0;
- CurrentCrc = filePartEnumerator.Current.FileHeader.FileCrc;
- 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.IsSplitAfter)
- {
- if (filePartEnumerator.Current.FileHeader.R4Salt != 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 => true;
- public override bool CanSeek => false;
- public override bool CanWrite => false;
- public uint CurrentCrc { get; private set; }
- public override void Flush()
- {
- throw new NotSupportedException();
- }
- public override long Length => throw new NotSupportedException();
- public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); }
- public override long Seek(long offset, SeekOrigin origin)
- {
- throw new NotSupportedException();
- }
- public override void SetLength(long value)
- {
- throw new NotSupportedException();
- }
- public override void Write(byte[] buffer, int offset, int count)
- {
- throw new NotSupportedException();
- }
- }
- }
|