Files
Aaru/Aaru.Images/AaruFormat/Read.cs

314 lines
11 KiB
C#

using System;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Structs;
namespace Aaru.Images;
public sealed partial class AaruFormat
{
// AARU_EXPORT int32_t AARU_CALL aaruf_read_media_tag(void *context, uint8_t *data, const int32_t tag, uint32_t *length)
[LibraryImport("libaaruformat", EntryPoint = "aaruf_read_media_tag", SetLastError = true)]
[UnmanagedCallConv(CallConvs = [typeof(CallConvStdcall)])]
private static partial Status aaruf_read_media_tag(IntPtr context, byte[] data, MediaTagType tag, ref uint length);
// AARU_EXPORT int32_t AARU_CALL aaruf_read_sector(void *context, const uint64_t sector_address, bool negative,
// uint8_t *data, uint32_t *length, uint8_t *sector_status)
[LibraryImport("libaaruformat", EntryPoint = "aaruf_read_sector", SetLastError = true)]
[UnmanagedCallConv(CallConvs = [typeof(CallConvStdcall)])]
private static partial Status aaruf_read_sector(IntPtr context, ulong sectorAddress,
[MarshalAs(UnmanagedType.I4)] bool negative, byte[] data,
ref uint length, out byte sectorStatus);
// AARU_EXPORT int32_t AARU_CALL aaruf_read_track_sector(void *context, uint8_t *data, const uint64_t sector_address,
// uint32_t *length, const uint8_t track, uint8_t *sector_status)
[LibraryImport("libaaruformat", EntryPoint = "aaruf_read_track_sector", SetLastError = true)]
[UnmanagedCallConv(CallConvs = [typeof(CallConvStdcall)])]
private static partial Status aaruf_read_track_sector(IntPtr context, byte[] data, ulong sectorAddress,
ref uint length, byte track, out byte sectorStatus);
// AARU_EXPORT int32_t AARU_CALL aaruf_read_sector_long(void *context, const uint64_t sector_address, bool negative,
// uint8_t *data, uint32_t *length, uint8_t *sector_status)
[LibraryImport("libaaruformat", EntryPoint = "aaruf_read_sector_long", SetLastError = true)]
[UnmanagedCallConv(CallConvs = [typeof(CallConvStdcall)])]
private static partial Status aaruf_read_sector_long(IntPtr context, ulong sectorAddress,
[MarshalAs(UnmanagedType.I4)] bool negative, byte[] data,
ref uint length, out byte sectorStatus);
// AARU_EXPORT int32_t AARU_CALL aaruf_read_sector_tag(const void *context, const uint64_t sector_address,
// const bool negative, uint8_t *buffer, uint32_t *length,
// const int32_t tag)
[LibraryImport("libaaruformat", EntryPoint = "aaruf_read_sector_tag", SetLastError = true)]
[UnmanagedCallConv(CallConvs = [typeof(CallConvStdcall)])]
private static partial Status aaruf_read_sector_tag(IntPtr context, ulong sectorAddress,
[MarshalAs(UnmanagedType.I4)] bool negative, byte[] buffer,
ref uint length, SectorTagType tag);
#region IWritableOpticalImage Members
/// <inheritdoc />
public ErrorNumber ReadMediaTag(MediaTagType tag, out byte[] buffer)
{
buffer = null;
uint length = 0;
Status res = aaruf_read_media_tag(_context, buffer, tag, ref length);
if(res != Status.Ok) return StatusToErrorNumber(res);
buffer = new byte[length];
res = aaruf_read_media_tag(_context, buffer, tag, ref length);
return StatusToErrorNumber(res);
}
/// <inheritdoc />
public ErrorNumber ReadSector(ulong sectorAddress, out byte[] buffer)
{
buffer = null;
uint length = 0;
// TODO: Sector status API
Status res = aaruf_read_sector(_context, sectorAddress, false, buffer, ref length, out _);
if(res != Status.BufferTooSmall) return StatusToErrorNumber(res);
buffer = new byte[length];
res = aaruf_read_sector(_context, sectorAddress, false, buffer, ref length, out _);
// Sector not dumped
if(res != Status.SectorNotDumped || length <= 0) return StatusToErrorNumber(res);
buffer = new byte[length];
return ErrorNumber.NoError;
}
/// <inheritdoc />
public ErrorNumber ReadSector(ulong sectorAddress, uint track, out byte[] buffer)
{
buffer = null;
uint length = 0;
Status res = aaruf_read_track_sector(_context, buffer, sectorAddress, ref length, (byte)track, out _);
if(res != Status.BufferTooSmall) return StatusToErrorNumber(res);
buffer = new byte[length];
res = aaruf_read_track_sector(_context, buffer, sectorAddress, ref length, (byte)track, out _);
// Sector not dumped
if(res != Status.SectorNotDumped || length <= 0) return StatusToErrorNumber(res);
buffer = new byte[length];
return ErrorNumber.NoError;
}
/// <inheritdoc />
public ErrorNumber ReadSectorLong(ulong sectorAddress, out byte[] buffer)
{
buffer = null;
uint length = 0;
Status res = aaruf_read_sector_long(_context, sectorAddress, false, buffer, ref length, out _);
if(res != Status.BufferTooSmall) return StatusToErrorNumber(res);
buffer = new byte[length];
res = aaruf_read_sector_long(_context, sectorAddress, false, buffer, ref length, out _);
// Sector not dumped
if(res != Status.SectorNotDumped || length <= 0) return StatusToErrorNumber(res);
buffer = new byte[length];
return ErrorNumber.NoError;
}
/// <inheritdoc />
public ErrorNumber ReadSectorTag(ulong sectorAddress, SectorTagType tag, out byte[] buffer)
{
buffer = null;
uint length = 0;
Status res = aaruf_read_sector_tag(_context, sectorAddress, false, buffer, ref length, tag);
if(res != Status.BufferTooSmall) return StatusToErrorNumber(res);
buffer = new byte[length];
res = aaruf_read_sector_tag(_context, sectorAddress, false, buffer, ref length, tag);
return StatusToErrorNumber(res);
}
/// <inheritdoc />
public ErrorNumber ReadSectors(ulong sectorAddress, uint length, out byte[] buffer)
{
MemoryStream ms = new();
for(uint i = 0; i < length; i++)
{
ErrorNumber res = ReadSector(sectorAddress + i, out byte[] sectorBuffer);
if(res != ErrorNumber.NoError)
{
buffer = ms.ToArray();
return res;
}
ms.Write(sectorBuffer, 0, sectorBuffer.Length);
}
buffer = ms.ToArray();
return ErrorNumber.NoError;
}
/// <inheritdoc />
public ErrorNumber ReadSectorsLong(ulong sectorAddress, uint length, out byte[] buffer)
{
MemoryStream ms = new();
for(uint i = 0; i < length; i++)
{
ErrorNumber res = ReadSectorLong(sectorAddress + i, out byte[] sectorBuffer);
if(res != ErrorNumber.NoError)
{
buffer = ms.ToArray();
return res;
}
ms.Write(sectorBuffer, 0, sectorBuffer.Length);
}
buffer = ms.ToArray();
return ErrorNumber.NoError;
}
/// <inheritdoc />
public ErrorNumber ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag, out byte[] buffer)
{
MemoryStream ms = new();
for(uint i = 0; i < length; i++)
{
ErrorNumber res = ReadSectorTag(sectorAddress + i, tag, out byte[] sectorBuffer);
if(res != ErrorNumber.NoError)
{
buffer = ms.ToArray();
return res;
}
ms.Write(sectorBuffer, 0, sectorBuffer.Length);
}
buffer = ms.ToArray();
return ErrorNumber.NoError;
}
/// <inheritdoc />
public ErrorNumber ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag, out byte[] buffer)
{
buffer = null;
if(_imageInfo.MetadataMediaType != MetadataMediaType.OpticalDisc) return ErrorNumber.NotSupported;
if(Tracks == null) return ErrorNumber.SectorNotFound;
Track trk = Tracks.FirstOrDefault(t => t.Sequence == track);
return trk?.Sequence != track
? ErrorNumber.SectorNotFound
: ReadSectorTag(trk.StartSector + sectorAddress, tag, out buffer);
}
/// <inheritdoc />
public ErrorNumber ReadSectors(ulong sectorAddress, uint length, uint track, out byte[] buffer)
{
buffer = null;
if(_imageInfo.MetadataMediaType != MetadataMediaType.OpticalDisc) return ErrorNumber.NotSupported;
if(Tracks == null) return ErrorNumber.SectorNotFound;
Track trk = Tracks.FirstOrDefault(t => t.Sequence == track);
if(trk?.Sequence != track) return ErrorNumber.SectorNotFound;
return trk.StartSector + sectorAddress + length > trk.EndSector + 1
? ErrorNumber.OutOfRange
: ReadSectors(trk.StartSector + sectorAddress, length, out buffer);
}
/// <inheritdoc />
public ErrorNumber ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag,
out byte[] buffer)
{
buffer = null;
if(_imageInfo.MetadataMediaType != MetadataMediaType.OpticalDisc) return ErrorNumber.NotSupported;
if(Tracks == null) return ErrorNumber.SectorNotFound;
Track trk = Tracks.FirstOrDefault(t => t.Sequence == track);
return trk?.Sequence != track
? ErrorNumber.SectorNotFound
: trk.StartSector + sectorAddress + length > trk.EndSector + 1
? ErrorNumber.OutOfRange
: ReadSectorsTag(trk.StartSector + sectorAddress, length, tag, out buffer);
}
/// <inheritdoc />
public ErrorNumber ReadSectorLong(ulong sectorAddress, uint track, out byte[] buffer)
{
buffer = null;
if(_imageInfo.MetadataMediaType != MetadataMediaType.OpticalDisc) return ErrorNumber.NotSupported;
if(Tracks == null) return ErrorNumber.SectorNotFound;
Track trk = Tracks.FirstOrDefault(t => t.Sequence == track);
return trk?.Sequence != track
? ErrorNumber.SectorNotFound
: ReadSectorLong(trk.StartSector + sectorAddress, out buffer);
}
/// <inheritdoc />
public ErrorNumber ReadSectorsLong(ulong sectorAddress, uint length, uint track, out byte[] buffer)
{
buffer = null;
if(_imageInfo.MetadataMediaType != MetadataMediaType.OpticalDisc) return ErrorNumber.NotSupported;
if(Tracks == null) return ErrorNumber.SectorNotFound;
Track trk = Tracks.FirstOrDefault(t => t.Sequence == track);
return trk?.Sequence != track
? ErrorNumber.SectorNotFound
: trk.StartSector + sectorAddress + length > trk.EndSector + 1
? ErrorNumber.OutOfRange
: ReadSectorsLong(trk.StartSector + sectorAddress, length, out buffer);
}
#endregion
}