// Decompiled with JetBrains decompiler // Type: ImageReader.Stream.DiscSectorStream // Assembly: ImageReader, Version=1.5.2.0, Culture=neutral, PublicKeyToken=611be24fdeb07e08 // MVID: E0717604-B50B-4CB4-B85C-C17F43D5C04B // Assembly location: ImageReader.dll using ImageReader.DiscSectors; using System; using System.IO; namespace ImageReader.Stream { public class DiscSectorStream : System.IO.Stream { private System.IO.Stream sourceStream; private IDiscSector sector; private long absStartAddress; private long absEndAddress; private bool disposed; private bool disposeSourceStream; public DiscSectorStream( System.IO.Stream source, IDiscSector sector, uint extent, uint size, bool autoReleaseSource) { this.disposed = false; if (size > (uint) int.MaxValue) throw new ArgumentException(string.Format("invalid size: files larger than {0} in size are not supported", (object) int.MaxValue), nameof (size)); if (size > uint.MaxValue) throw new ArgumentException(string.Format("invalid size: a file on an ISO 9660 formatted disc cannot be larger than {0} in size", (object) uint.MaxValue), nameof (size)); if (!source.CanSeek) throw new ArgumentException(string.Format("invalid base stream: only seekable streams are supported"), "baseStream"); this.sector = sector; this.sourceStream = source; this.absStartAddress = (long) extent * (long) sector.Size; this.absEndAddress = this.absStartAddress + this.LogicalToPhysical((long) size); this.disposeSourceStream = autoReleaseSource; this.Seek(0L, SeekOrigin.Begin); } public DiscSectorStream(string isoFile, IDiscSector sector, uint extent, uint size) : this((System.IO.Stream) new FileStream(isoFile, FileMode.Open, FileAccess.Read, FileShare.Read), sector, extent, size, true) { } public DiscSectorStream(System.IO.Stream source, IDiscSector sector) : this(source, sector, 0U, 0U, true) => this.absEndAddress = this.absStartAddress + source.Length; public override bool CanRead => !this.disposed && this.sourceStream.CanRead; public override bool CanTimeout => this.disposed || this.sourceStream.CanTimeout; public override bool CanSeek => !this.disposed && this.sourceStream.CanSeek; public override bool CanWrite => !this.disposed && this.sourceStream.CanWrite; public override long Length => this.PhysicalToLogical(this.absEndAddress - this.absStartAddress); public override long Position { get => this.PhysicalToLogical(this.sourceStream.Position - this.absStartAddress); set => this.Seek(value, SeekOrigin.Begin); } public override int Read(byte[] buffer, int offset, int count) { long logical = this.PhysicalToLogical(this.sourceStream.Position - this.absStartAddress); long num1 = Math.Min((long) count, this.Length - logical); long sectors = num1 / (long) this.sector.DataLength; long num2 = num1 % (long) this.sector.DataLength; int num3 = 0; if ((long) (buffer.Length - offset) < sectors * (long) this.sector.DataLength + num2) throw new ArgumentOutOfRangeException("buffer is too small"); if (sectors > 0L) num3 += this.ReadSector(buffer, offset, sectors); if (num2 > 0L) { if (this.sourceStream.Position % (long) this.sector.Size == 0L) this.sourceStream.Seek((long) this.sector.DataOffset, SeekOrigin.Current); num3 += this.sourceStream.Read(buffer, Convert.ToInt32(sectors * (long) this.sector.DataLength), (int) num2); } return num3; } public override void Write(byte[] buffer, int offset, int count) { if (buffer.Length - offset < count) throw new ArgumentOutOfRangeException("buffer is too small"); long logical = this.PhysicalToLogical(this.sourceStream.Position - this.absStartAddress); long num1 = Math.Min((long) count, this.Length - logical); long sectors = num1 / (long) this.sector.DataLength; long num2 = num1 % (long) this.sector.DataLength; long num3 = 0; if (sectors > 0L) num3 += (long) this.WriteSector(buffer, offset, sectors); if (num2 <= 0L) return; if (sectors > 0L || this.sourceStream.Position == this.absStartAddress) this.sourceStream.Seek((long) this.sector.DataOffset, SeekOrigin.Current); this.sourceStream.Write(buffer, Convert.ToInt32(sectors * (long) this.sector.DataLength), (int) num2); long num4 = num3 + num2; } public override long Seek(long offset, SeekOrigin origin) { long offset1; switch (origin) { case SeekOrigin.Begin: if (offset < 0L || offset > this.Length) throw new ArgumentException(string.Format("must be in range of (0, {0}) when seeking from {1}", (object) this.Length, (object) SeekOrigin.Begin), nameof (offset)); offset1 = this.absStartAddress + this.LogicalToPhysical(offset); break; case SeekOrigin.Current: long logical = this.PhysicalToLogical(this.sourceStream.Position - this.absStartAddress); if ((offset > 0L || logical + offset < 0L) && (offset < 0L || logical + offset > this.Length)) throw new ArgumentException(string.Format("must be in range of (0, {0}) or (-{0}, 0) when seeking from {1}", (object) this.Length, (object) SeekOrigin.Current), nameof (offset)); offset1 = this.LogicalToPhysical(logical + offset) - (this.sourceStream.Position - this.absStartAddress); break; case SeekOrigin.End: if (offset > 0L || this.Length + offset < 0L) throw new ArgumentException(string.Format("must be in range of (-{0}, 0) when seeking from {1}", (object) this.Length, (object) SeekOrigin.End), nameof (offset)); offset1 = this.absStartAddress + this.LogicalToPhysical(this.Length + offset); origin = SeekOrigin.Begin; break; default: throw new ArgumentException(); } return this.PhysicalToLogical(this.sourceStream.Seek(offset1, origin) - this.absStartAddress); } public override void Close() { if (this.sourceStream == null || !this.disposeSourceStream) return; this.sourceStream.Close(); } public override void SetLength(long value) => throw new NotSupportedException(); public override void WriteByte(byte value) => throw new NotSupportedException(); public override void Flush() => throw new NotSupportedException(); private long LogicalToPhysical(long logicalAddress) { long num1 = logicalAddress / (long) this.sector.DataLength; long num2 = logicalAddress % (long) this.sector.DataLength; if (num2 != 0L) num2 += (long) this.sector.DataOffset; return num1 * (long) this.sector.Size + num2; } private long PhysicalToLogical(long physicalAddress) { long num1 = physicalAddress % (long) this.sector.Size; long num2 = physicalAddress / (long) this.sector.Size; if (num1 != 0L) { string.Format("the specified absolute address {0} is out of the stream's logical range", (object) physicalAddress); num1 -= (long) this.sector.DataOffset; } return num2 * (long) this.sector.DataLength + num1; } private int ReadSector(byte[] buffer, int offset, long sectors) { int num = 0; byte[] buffer1 = new byte[this.sector.Size]; for (int index = 0; (long) index < sectors; ++index) { this.sourceStream.Read(buffer1, 0, buffer1.Length); Buffer.BlockCopy((Array) buffer1, this.sector.DataOffset, (Array) buffer, offset + index * this.sector.DataLength, this.sector.DataLength); num += this.sector.DataLength; } return num; } private int WriteSector(byte[] buffer, int offset, long sectors) { int num = 0; for (int index = 0; (long) index < sectors; ++index) { this.sourceStream.Seek((long) this.sector.DataOffset, SeekOrigin.Current); this.sourceStream.Write(buffer, offset + index * this.sector.DataLength, this.sector.DataLength); this.sourceStream.Seek((long) (this.sector.Size - this.sector.DataOffset), SeekOrigin.Current); num += this.sector.DataLength; } return num; } public new virtual void Dispose() { this.Dispose(true); GC.SuppressFinalize((object) this); } protected new virtual void Dispose(bool disposing) { if (this.disposed) return; if (disposing) this.Close(); this.disposed = true; } } }