From 86e412cf77994141d0644b4541f8eb5ed2f3bafa Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Sat, 31 Jan 2026 15:44:09 +0000 Subject: [PATCH] more fixes? --- src/SharpCompress/Archives/Zip/ZipArchive.cs | 4 +- src/SharpCompress/Common/AsyncBinaryReader.cs | 1 - src/SharpCompress/Common/Rar/RarVolume.cs | 2 +- src/SharpCompress/Common/Volume.cs | 10 +-- .../Common/Zip/StreamingZipFilePart.cs | 4 +- .../Compressors/Deflate/ZlibBaseStream.cs | 8 +-- .../Compressors/LZMA/LZipStream.cs | 2 +- src/SharpCompress/IO/CountingStream.cs | 69 +++++++++++++++++++ src/SharpCompress/IO/NonDisposingStream.cs | 9 ++- src/SharpCompress/Readers/Tar/TarReader.cs | 28 ++++---- src/SharpCompress/Writers/Zip/ZipWriter.cs | 2 +- 11 files changed, 107 insertions(+), 32 deletions(-) create mode 100644 src/SharpCompress/IO/CountingStream.cs diff --git a/src/SharpCompress/Archives/Zip/ZipArchive.cs b/src/SharpCompress/Archives/Zip/ZipArchive.cs index 108e8908..0777f1e6 100644 --- a/src/SharpCompress/Archives/Zip/ZipArchive.cs +++ b/src/SharpCompress/Archives/Zip/ZipArchive.cs @@ -35,7 +35,7 @@ public partial class ZipArchive : AbstractWritableArchive LoadVolumes(SourceStream stream) { stream.LoadAllParts(); - stream.Position = 0; + //stream.Position = 0; var streams = stream.Streams.ToList(); var idx = 0; @@ -156,7 +156,7 @@ public partial class ZipArchive : AbstractWritableArchive +/// A simple stream wrapper that counts bytes written without buffering. +/// +internal class CountingStream : Stream +{ + private readonly Stream _stream; + private readonly bool _leaveOpen; + private long _bytesWritten; + + public CountingStream(Stream stream) + { + _stream = stream ?? throw new ArgumentNullException(nameof(stream)); + } + + /// + /// Gets the total number of bytes written to this stream. + /// + public long BytesWritten => _bytesWritten; + + public override bool CanRead => _stream.CanRead; + + public override bool CanSeek => _stream.CanSeek; + + public override bool CanWrite => _stream.CanWrite; + + public override long Length => _stream.Length; + + public override long Position + { + get => _stream.Position; + set => _stream.Position = value; + } + + public override void Flush() => _stream.Flush(); + + public override int Read(byte[] buffer, int offset, int count) => + _stream.Read(buffer, offset, count); + + public override long Seek(long offset, SeekOrigin origin) => + _stream.Seek(offset, origin); + + public override void SetLength(long value) => _stream.SetLength(value); + + public override void Write(byte[] buffer, int offset, int count) + { + _stream.Write(buffer, offset, count); + _bytesWritten += count; + } + + public override void WriteByte(byte value) + { + _stream.WriteByte(value); + _bytesWritten++; + } + + protected override void Dispose(bool disposing) + { + if (disposing && !_leaveOpen) + { + _stream.Dispose(); + } + base.Dispose(disposing); + } +} diff --git a/src/SharpCompress/IO/NonDisposingStream.cs b/src/SharpCompress/IO/NonDisposingStream.cs index 55a63007..2e290b3e 100644 --- a/src/SharpCompress/IO/NonDisposingStream.cs +++ b/src/SharpCompress/IO/NonDisposingStream.cs @@ -10,7 +10,7 @@ namespace SharpCompress.IO; /// This is useful when working with compression streams directly and you want /// to keep the base stream open after the compression stream is disposed. /// -internal class NonDisposingStream : Stream +internal class NonDisposingStream : Stream, IStreamStack { private readonly Stream _stream; private bool _isDisposed; @@ -214,4 +214,11 @@ internal class NonDisposingStream : Stream throw new ObjectDisposedException(nameof(NonDisposingStream)); } } + + public int DefaultBufferSize { get; set; } + public Stream BaseStream() => _stream; + + public int BufferSize { get; set; } + public int BufferPosition { get; set; } + public void SetPosition(long position) => throw new NotImplementedException(); } diff --git a/src/SharpCompress/Readers/Tar/TarReader.cs b/src/SharpCompress/Readers/Tar/TarReader.cs index be9bf45d..030ad33f 100644 --- a/src/SharpCompress/Readers/Tar/TarReader.cs +++ b/src/SharpCompress/Readers/Tar/TarReader.cs @@ -57,23 +57,23 @@ public partial class TarReader : AbstractReader { stream.NotNull(nameof(stream)); options = options ?? new ReaderOptions(); - var rewindableStream = new SharpCompressStream(stream); - long pos = ((IStreamStack)rewindableStream).GetPosition(); + var rewindableStream = RewindableStream.EnsureSeekable(stream); + long pos = rewindableStream.Position; if (GZipArchive.IsGZipFile(rewindableStream)) { - ((IStreamStack)rewindableStream).StackSeek(pos); + rewindableStream.Position = pos; var testStream = new GZipStream(rewindableStream, CompressionMode.Decompress); if (TarArchive.IsTarFile(testStream)) { - ((IStreamStack)rewindableStream).StackSeek(pos); + rewindableStream.Position = pos; return new TarReader(rewindableStream, options, CompressionType.GZip); } throw new InvalidFormatException("Not a tar file."); } - ((IStreamStack)rewindableStream).StackSeek(pos); + rewindableStream.Position = pos; if (BZip2Stream.IsBZip2(rewindableStream)) { - ((IStreamStack)rewindableStream).StackSeek(pos); + rewindableStream.Position = pos; var testStream = BZip2Stream.Create( rewindableStream, CompressionMode.Decompress, @@ -81,36 +81,36 @@ public partial class TarReader : AbstractReader ); if (TarArchive.IsTarFile(testStream)) { - ((IStreamStack)rewindableStream).StackSeek(pos); + rewindableStream.Position = pos; return new TarReader(rewindableStream, options, CompressionType.BZip2); } throw new InvalidFormatException("Not a tar file."); } - ((IStreamStack)rewindableStream).StackSeek(pos); + rewindableStream.Position = pos; if (ZStandardStream.IsZStandard(rewindableStream)) { - ((IStreamStack)rewindableStream).StackSeek(pos); + rewindableStream.Position = pos; var testStream = new ZStandardStream(rewindableStream); if (TarArchive.IsTarFile(testStream)) { - ((IStreamStack)rewindableStream).StackSeek(pos); + rewindableStream.Position = pos; return new TarReader(rewindableStream, options, CompressionType.ZStandard); } throw new InvalidFormatException("Not a tar file."); } - ((IStreamStack)rewindableStream).StackSeek(pos); + rewindableStream.Position = pos; if (LZipStream.IsLZipFile(rewindableStream)) { - ((IStreamStack)rewindableStream).StackSeek(pos); + rewindableStream.Position = pos; var testStream = new LZipStream(rewindableStream, CompressionMode.Decompress); if (TarArchive.IsTarFile(testStream)) { - ((IStreamStack)rewindableStream).StackSeek(pos); + rewindableStream.Position = pos; return new TarReader(rewindableStream, options, CompressionType.LZip); } throw new InvalidFormatException("Not a tar file."); } - ((IStreamStack)rewindableStream).StackSeek(pos); + rewindableStream.Position = pos; return new TarReader(rewindableStream, options, CompressionType.None); } diff --git a/src/SharpCompress/Writers/Zip/ZipWriter.cs b/src/SharpCompress/Writers/Zip/ZipWriter.cs index ecf45336..e69af91e 100644 --- a/src/SharpCompress/Writers/Zip/ZipWriter.cs +++ b/src/SharpCompress/Writers/Zip/ZipWriter.cs @@ -417,7 +417,7 @@ public partial class ZipWriter : AbstractWriter private Stream GetWriteStream(Stream writeStream) { - counting = new CountingStream(writeStream, leaveOpen: true); + counting = new CountingStream(new NonDisposingStream(writeStream)); Stream output = counting; switch (zipCompressionMethod) {