211 lines
8.5 KiB
C#
211 lines
8.5 KiB
C#
// 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;
|
|
}
|
|
}
|
|
}
|