[LIF] Add support for devices with a sector size different from 256 bytes

This commit is contained in:
2026-06-19 15:42:06 +01:00
parent cc4b91bd3c
commit 4824a80744
6 changed files with 93 additions and 46 deletions

View File

@@ -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);

View File

@@ -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";
}

View File

@@ -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;
}

View File

@@ -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)
};

View File

@@ -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; }
}
}

View File

@@ -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),