mirror of
https://github.com/aaru-dps/Aaru.git
synced 2026-07-08 18:16:24 +00:00
[LIF] Add support for devices with a sector size different from 256 bytes
This commit is contained in:
@@ -124,8 +124,10 @@ public sealed partial class LIF
|
||||
|
||||
if(lengthInSectors == 0) return overlaps;
|
||||
|
||||
ulong absoluteStartSector = _partition.Start + startSector;
|
||||
ulong absoluteEndSector = absoluteStartSector + lengthInSectors - 1;
|
||||
ulong startByteOffset = (ulong)startSector * LIF_RECORD_SIZE;
|
||||
ulong endByteOffset = startByteOffset + (ulong)lengthInSectors * LIF_RECORD_SIZE - 1;
|
||||
ulong absoluteStartSector = _partition.Start + startByteOffset / _imagePlugin.Info.SectorSize;
|
||||
ulong absoluteEndSector = _partition.Start + endByteOffset / _imagePlugin.Info.SectorSize;
|
||||
|
||||
AddExtentOverlaps(absoluteStartSector, absoluteEndSector, sectorExtents, overlaps);
|
||||
|
||||
|
||||
@@ -30,7 +30,8 @@ namespace Aaru.Filesystems;
|
||||
|
||||
public sealed partial class LIF
|
||||
{
|
||||
const uint LIF_MAGIC = 0x8000;
|
||||
const uint LIF_RECORD_SIZE = 256;
|
||||
const uint LIF_MAGIC = 0x8000;
|
||||
|
||||
const string FS_TYPE = "hplif";
|
||||
}
|
||||
@@ -48,7 +48,7 @@ public sealed partial class LIF
|
||||
stat = new FileEntryInfo
|
||||
{
|
||||
Attributes = FileAttributes.Directory,
|
||||
BlockSize = 256,
|
||||
BlockSize = LIF_RECORD_SIZE,
|
||||
CreationTime = DateHandlers.LifToDateTime(_systemBlock.creationDate)
|
||||
};
|
||||
|
||||
@@ -70,9 +70,9 @@ public sealed partial class LIF
|
||||
stat = new FileEntryInfo
|
||||
{
|
||||
Attributes = FileAttributes.File,
|
||||
BlockSize = 256,
|
||||
BlockSize = LIF_RECORD_SIZE,
|
||||
Blocks = entry.fileLength,
|
||||
Length = entry.fileLength * 256,
|
||||
Length = entry.fileLength * LIF_RECORD_SIZE,
|
||||
CreationTime = DateHandlers.LifToDateTime(entry.creationDate),
|
||||
Links = 1
|
||||
};
|
||||
@@ -108,9 +108,9 @@ public sealed partial class LIF
|
||||
node = new LifFileNode
|
||||
{
|
||||
Path = path,
|
||||
Length = entry.fileLength * 256,
|
||||
Length = entry.fileLength * LIF_RECORD_SIZE,
|
||||
Offset = 0,
|
||||
StartSector = entry.fileStart
|
||||
StartRecord = entry.fileStart
|
||||
};
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
@@ -144,30 +144,18 @@ public sealed partial class LIF
|
||||
|
||||
if(length + lifNode.Offset > lifNode.Length) length = lifNode.Length - lifNode.Offset;
|
||||
|
||||
ulong currentSector = lifNode.StartSector + (ulong)(lifNode.Offset / 256);
|
||||
var offsetInSector = (int)(lifNode.Offset % 256);
|
||||
long bytesRemaining = length;
|
||||
var bufferOffset = 0;
|
||||
ErrorNumber error = ReadLogicalBytes(_imagePlugin,
|
||||
_partition,
|
||||
(ulong)lifNode.StartRecord * LIF_RECORD_SIZE + (ulong)lifNode.Offset,
|
||||
(uint)length,
|
||||
out byte[] data);
|
||||
|
||||
while(bytesRemaining > 0)
|
||||
{
|
||||
ErrorNumber errno =
|
||||
_imagePlugin.ReadSector(_partition.Start + currentSector, false, out byte[] sectorData, out _);
|
||||
if(error != ErrorNumber.NoError) return error;
|
||||
|
||||
if(errno != ErrorNumber.NoError) return errno;
|
||||
Array.Copy(data, 0, buffer, 0, data.Length);
|
||||
|
||||
var bytesToCopy = (int)Math.Min(bytesRemaining, 256 - offsetInSector);
|
||||
|
||||
Array.Copy(sectorData, offsetInSector, buffer, bufferOffset, bytesToCopy);
|
||||
|
||||
bufferOffset += bytesToCopy;
|
||||
bytesRemaining -= bytesToCopy;
|
||||
lifNode.Offset += bytesToCopy;
|
||||
currentSector++;
|
||||
offsetInSector = 0;
|
||||
}
|
||||
|
||||
read = bufferOffset;
|
||||
read = data.Length;
|
||||
lifNode.Offset += data.Length;
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ public sealed partial class LIF
|
||||
{
|
||||
if(imagePlugin.Info.SectorSize < 256) return false;
|
||||
|
||||
ErrorNumber errno = imagePlugin.ReadSector(partition.Start, false, out byte[] sector, out _);
|
||||
ErrorNumber errno = ReadLogicalRecords(imagePlugin, partition, 0, 1, out byte[] sector);
|
||||
|
||||
if(errno != ErrorNumber.NoError) return false;
|
||||
|
||||
@@ -65,7 +65,7 @@ public sealed partial class LIF
|
||||
|
||||
if(imagePlugin.Info.SectorSize < 256) return;
|
||||
|
||||
ErrorNumber errno = imagePlugin.ReadSector(partition.Start, false, out byte[] sector, out _);
|
||||
ErrorNumber errno = ReadLogicalRecords(imagePlugin, partition, 0, 1, out byte[] sector);
|
||||
|
||||
if(errno != ErrorNumber.NoError) return;
|
||||
|
||||
@@ -93,8 +93,8 @@ public sealed partial class LIF
|
||||
metadata = new FileSystem
|
||||
{
|
||||
Type = FS_TYPE,
|
||||
ClusterSize = 256,
|
||||
Clusters = partition.Size / 256,
|
||||
ClusterSize = LIF_RECORD_SIZE,
|
||||
Clusters = partition.Size / LIF_RECORD_SIZE,
|
||||
CreationDate = DateHandlers.LifToDateTime(lifSb.creationDate),
|
||||
VolumeName = StringHandlers.CToString(lifSb.volumeLabel, encoding)
|
||||
};
|
||||
|
||||
@@ -26,13 +26,69 @@
|
||||
// Copyright © 2011-2026 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
using Partition = Aaru.CommonTypes.Partition;
|
||||
|
||||
namespace Aaru.Filesystems;
|
||||
|
||||
/// <inheritdoc />
|
||||
public sealed partial class LIF
|
||||
{
|
||||
static ErrorNumber ReadLogicalBytes(IMediaImage imagePlugin, Partition partition, ulong byteOffset, uint length,
|
||||
out byte[] data)
|
||||
{
|
||||
data = null;
|
||||
|
||||
if(imagePlugin is null || length == 0) return ErrorNumber.InvalidArgument;
|
||||
|
||||
uint imageSectorSize = imagePlugin.Info.SectorSize;
|
||||
|
||||
if(imageSectorSize == 0) return ErrorNumber.InvalidArgument;
|
||||
|
||||
ulong sectorOffset = byteOffset / imageSectorSize;
|
||||
ulong offsetInSector = byteOffset % imageSectorSize;
|
||||
ulong bytesToRead = offsetInSector + length;
|
||||
ulong sectorsNeeded = bytesToRead / imageSectorSize;
|
||||
|
||||
if(bytesToRead % imageSectorSize > 0) sectorsNeeded++;
|
||||
|
||||
if(sectorsNeeded == 0 || sectorsNeeded > uint.MaxValue) return ErrorNumber.InvalidArgument;
|
||||
|
||||
ErrorNumber errno = imagePlugin.ReadSectors(partition.Start + sectorOffset,
|
||||
false,
|
||||
(uint)sectorsNeeded,
|
||||
out byte[] sectorData,
|
||||
out _);
|
||||
|
||||
if(errno != ErrorNumber.NoError) return errno;
|
||||
|
||||
if(sectorData.LongLength < (long)(offsetInSector + length)) return ErrorNumber.InvalidArgument;
|
||||
|
||||
data = new byte[length];
|
||||
Array.Copy(sectorData, (long)offsetInSector, data, 0L, length);
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
static ErrorNumber ReadLogicalRecords(IMediaImage imagePlugin, Partition partition, uint record, uint recordCount,
|
||||
out byte[] data)
|
||||
{
|
||||
if(recordCount > uint.MaxValue / LIF_RECORD_SIZE)
|
||||
{
|
||||
data = null;
|
||||
|
||||
return ErrorNumber.InvalidArgument;
|
||||
}
|
||||
|
||||
return ReadLogicalBytes(imagePlugin,
|
||||
partition,
|
||||
(ulong)record * LIF_RECORD_SIZE,
|
||||
recordCount * LIF_RECORD_SIZE,
|
||||
out data);
|
||||
}
|
||||
|
||||
sealed class LifDirNode : IDirNode
|
||||
{
|
||||
internal string[] Contents;
|
||||
@@ -44,14 +100,14 @@ public sealed partial class LIF
|
||||
|
||||
sealed class LifFileNode : IFileNode
|
||||
{
|
||||
/// <summary>Starting sector of the file data on the medium.</summary>
|
||||
internal uint StartSector;
|
||||
/// <summary>Starting logical record of the file data on the medium.</summary>
|
||||
internal uint StartRecord;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Path { get; init; }
|
||||
public string Path { get; init; }
|
||||
/// <inheritdoc />
|
||||
public long Length { get; init; }
|
||||
public long Length { get; init; }
|
||||
/// <inheritdoc />
|
||||
public long Offset { get; set; }
|
||||
public long Offset { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -56,7 +56,7 @@ public sealed partial class LIF
|
||||
if(imagePlugin.Info.SectorSize < 256) return ErrorNumber.InvalidArgument;
|
||||
|
||||
// Read the system block (record 0)
|
||||
ErrorNumber errno = imagePlugin.ReadSector(partition.Start, false, out byte[] sector, out _);
|
||||
ErrorNumber errno = ReadLogicalRecords(imagePlugin, partition, 0, 1, out byte[] sector);
|
||||
|
||||
if(errno != ErrorNumber.NoError) return errno;
|
||||
|
||||
@@ -70,11 +70,11 @@ public sealed partial class LIF
|
||||
if(_systemBlock.directoryStart == 0 || _systemBlock.directorySize == 0) return ErrorNumber.InvalidArgument;
|
||||
|
||||
// Read the directory area
|
||||
errno = imagePlugin.ReadSectors(partition.Start + _systemBlock.directoryStart,
|
||||
false,
|
||||
_systemBlock.directorySize,
|
||||
out byte[] directoryData,
|
||||
out _);
|
||||
errno = ReadLogicalRecords(imagePlugin,
|
||||
partition,
|
||||
_systemBlock.directoryStart,
|
||||
_systemBlock.directorySize,
|
||||
out byte[] directoryData);
|
||||
|
||||
if(errno != ErrorNumber.NoError) return errno;
|
||||
|
||||
@@ -99,7 +99,7 @@ public sealed partial class LIF
|
||||
|
||||
_statFs = new FileSystemInfo
|
||||
{
|
||||
Blocks = partition.Size / 256,
|
||||
Blocks = partition.Size / LIF_RECORD_SIZE,
|
||||
FilenameLength = 10,
|
||||
Files = (ulong)_rootDirectoryCache.Count,
|
||||
PluginId = Id,
|
||||
@@ -109,7 +109,7 @@ public sealed partial class LIF
|
||||
Metadata = new FileSystem
|
||||
{
|
||||
Type = FS_TYPE,
|
||||
ClusterSize = 256,
|
||||
ClusterSize = LIF_RECORD_SIZE,
|
||||
Clusters = _statFs.Blocks,
|
||||
Files = _statFs.Files,
|
||||
CreationDate = DateHandlers.LifToDateTime(_systemBlock.creationDate),
|
||||
|
||||
Reference in New Issue
Block a user