mirror of
https://github.com/aaru-dps/Aaru.git
synced 2026-07-08 17:56:18 +00:00
Implement support for the Twiggy spare bad block sector track, allowing to read disks with remapped sectors.
Fixes reading currently on-the-wild dump of LOS 1.2.
This commit is contained in:
@@ -127,7 +127,7 @@ public sealed partial class LisaFS
|
||||
// If root catalog is not pointed in MDDF (unchecked) maybe it's always following S-Records File?
|
||||
for(ulong i = 0; i < _device.Info.Sectors; i++)
|
||||
{
|
||||
errno = _device.ReadSectorTag(i, false, SectorTagType.AppleSonyTag, out byte[] tag);
|
||||
errno = ReadLisaSectorTag(i, out byte[] tag);
|
||||
|
||||
if(errno != ErrorNumber.NoError) continue;
|
||||
|
||||
@@ -135,7 +135,7 @@ public sealed partial class LisaFS
|
||||
|
||||
if(catTag.FileId != FILEID_CATALOG || catTag.RelPage != 0) continue;
|
||||
|
||||
errno = _device.ReadSectors(i, false, 4, out firstCatalogBlock, out _);
|
||||
errno = ReadLisaSectors(i, 4, out firstCatalogBlock);
|
||||
|
||||
if(errno != ErrorNumber.NoError) return errno;
|
||||
|
||||
@@ -150,10 +150,7 @@ public sealed partial class LisaFS
|
||||
// Traverse double-linked list until first catalog block
|
||||
while(prevCatalogPointer != 0xFFFFFFFF)
|
||||
{
|
||||
errno = _device.ReadSectorTag(prevCatalogPointer + _mddf.mddf_block + _volumePrefix,
|
||||
false,
|
||||
SectorTagType.AppleSonyTag,
|
||||
out byte[] tag);
|
||||
errno = ReadLisaSectorTag(prevCatalogPointer + _mddf.mddf_block + _volumePrefix, out byte[] tag);
|
||||
|
||||
if(errno != ErrorNumber.NoError) return errno;
|
||||
|
||||
@@ -161,11 +158,7 @@ public sealed partial class LisaFS
|
||||
|
||||
if(prevTag.FileId != FILEID_CATALOG) return ErrorNumber.InvalidArgument;
|
||||
|
||||
errno = _device.ReadSectors(prevCatalogPointer + _mddf.mddf_block + _volumePrefix,
|
||||
false,
|
||||
4,
|
||||
out firstCatalogBlock,
|
||||
out _);
|
||||
errno = ReadLisaSectors(prevCatalogPointer + _mddf.mddf_block + _volumePrefix, 4, out firstCatalogBlock);
|
||||
|
||||
if(errno != ErrorNumber.NoError) return errno;
|
||||
|
||||
@@ -179,10 +172,7 @@ public sealed partial class LisaFS
|
||||
// Traverse double-linked list to read full catalog
|
||||
while(nextCatalogPointer != 0xFFFFFFFF)
|
||||
{
|
||||
errno = _device.ReadSectorTag(nextCatalogPointer + _mddf.mddf_block + _volumePrefix,
|
||||
false,
|
||||
SectorTagType.AppleSonyTag,
|
||||
out byte[] tag);
|
||||
errno = ReadLisaSectorTag(nextCatalogPointer + _mddf.mddf_block + _volumePrefix, out byte[] tag);
|
||||
|
||||
if(errno != ErrorNumber.NoError) return errno;
|
||||
|
||||
@@ -190,11 +180,9 @@ public sealed partial class LisaFS
|
||||
|
||||
if(nextTag.FileId != FILEID_CATALOG) return ErrorNumber.InvalidArgument;
|
||||
|
||||
errno = _device.ReadSectors(nextCatalogPointer + _mddf.mddf_block + _volumePrefix,
|
||||
false,
|
||||
4,
|
||||
out byte[] nextCatalogBlock,
|
||||
out _);
|
||||
errno = ReadLisaSectors(nextCatalogPointer + _mddf.mddf_block + _volumePrefix,
|
||||
4,
|
||||
out byte[] nextCatalogBlock);
|
||||
|
||||
if(errno != ErrorNumber.NoError) return errno;
|
||||
|
||||
@@ -401,4 +389,4 @@ public sealed partial class LisaFS
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,11 +57,16 @@ public sealed partial class LisaFS
|
||||
|
||||
ulong ptr = _srecords[fileId].extent_ptr;
|
||||
|
||||
// An invalid pointer denotes file does not exist
|
||||
if(ptr is 0xFFFFFFFF or 0x00000000) return ErrorNumber.NoSuchFile;
|
||||
var searchExtentByTag = false;
|
||||
|
||||
// Pointers are relative to MDDF
|
||||
ptr += _mddf.mddf_block + _volumePrefix;
|
||||
if(ptr is not 0xFFFFFFFF and not 0x00000000) ptr += _mddf.mddf_block + _volumePrefix;
|
||||
else
|
||||
{
|
||||
if(_srecords[fileId].filesize == 0) return ErrorNumber.NoSuchFile;
|
||||
|
||||
searchExtentByTag = true;
|
||||
}
|
||||
|
||||
LisaTag.PriamTag extTag;
|
||||
byte[] tag;
|
||||
@@ -69,19 +74,19 @@ public sealed partial class LisaFS
|
||||
// This happens on some disks.
|
||||
// This is a filesystem corruption that makes LisaOS crash on scavenge.
|
||||
// This code just allow to ignore that corruption by searching the Extents File using sector tags
|
||||
if(ptr >= _device.Info.Sectors)
|
||||
if(searchExtentByTag || ptr >= _device.Info.Sectors)
|
||||
{
|
||||
var found = false;
|
||||
|
||||
for(ulong i = 0; i < _device.Info.Sectors; i++)
|
||||
{
|
||||
errno = _device.ReadSectorTag(i, false, SectorTagType.AppleSonyTag, out tag);
|
||||
errno = ReadLisaSectorTag(i, out tag);
|
||||
|
||||
if(errno != ErrorNumber.NoError) continue;
|
||||
|
||||
DecodeTag(tag, out extTag);
|
||||
|
||||
if(extTag.FileId != fileId * -1) continue;
|
||||
if(extTag.FileId != fileId * -1 || extTag.RelPage != 0) continue;
|
||||
|
||||
ptr = i;
|
||||
found = true;
|
||||
@@ -93,17 +98,36 @@ public sealed partial class LisaFS
|
||||
}
|
||||
|
||||
// Checks that the sector tag indicates its the Extents File we are searching for
|
||||
errno = _device.ReadSectorTag(ptr, false, SectorTagType.AppleSonyTag, out tag);
|
||||
errno = ReadLisaSectorTag(ptr, out tag);
|
||||
|
||||
if(errno != ErrorNumber.NoError) return errno;
|
||||
|
||||
DecodeTag(tag, out extTag);
|
||||
|
||||
if(extTag.FileId != (short)(-1 * fileId)) return ErrorNumber.NoSuchFile;
|
||||
if(extTag.FileId != (short)(-1 * fileId) || extTag.RelPage != 0)
|
||||
{
|
||||
var found = false;
|
||||
|
||||
errno = _mddf.fsversion == LISA_V1
|
||||
? _device.ReadSectors(ptr, false, 2, out byte[] sector, out _)
|
||||
: _device.ReadSector(ptr, false, out sector, out _);
|
||||
for(ulong i = 0; i < _device.Info.Sectors; i++)
|
||||
{
|
||||
errno = ReadLisaSectorTag(i, out tag);
|
||||
|
||||
if(errno != ErrorNumber.NoError) continue;
|
||||
|
||||
DecodeTag(tag, out extTag);
|
||||
|
||||
if(extTag.FileId != fileId * -1 || extTag.RelPage != 0) continue;
|
||||
|
||||
ptr = i;
|
||||
found = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(!found) return ErrorNumber.NoSuchFile;
|
||||
}
|
||||
|
||||
errno = _mddf.fsversion == LISA_V1 ? ReadLisaSectors(ptr, 2, out byte[] sector) : ReadLisaSector(ptr, out sector);
|
||||
|
||||
if(errno != ErrorNumber.NoError) return errno;
|
||||
|
||||
@@ -306,11 +330,8 @@ public sealed partial class LisaFS
|
||||
if(!_mounted) return ErrorNumber.AccessDenied;
|
||||
|
||||
// Searches the S-Records place using MDDF pointers
|
||||
ErrorNumber errno = _device.ReadSectors(_mddf.srec_ptr + _mddf.mddf_block + _volumePrefix,
|
||||
false,
|
||||
_mddf.srec_len,
|
||||
out byte[] sectors,
|
||||
out _);
|
||||
ErrorNumber errno =
|
||||
ReadLisaSectors(_mddf.srec_ptr + _mddf.mddf_block + _volumePrefix, _mddf.srec_len, out byte[] sectors);
|
||||
|
||||
if(errno != ErrorNumber.NoError) return errno;
|
||||
|
||||
@@ -330,4 +351,4 @@ public sealed partial class LisaFS
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,11 +117,7 @@ public sealed partial class LisaFS
|
||||
{
|
||||
if(!tags)
|
||||
{
|
||||
errno = _device.ReadSectors(_mddf.mddf_block + _volumePrefix + _mddf.srec_ptr,
|
||||
false,
|
||||
_mddf.srec_len,
|
||||
out buf,
|
||||
out _);
|
||||
errno = ReadLisaSectors(_mddf.mddf_block + _volumePrefix + _mddf.srec_ptr, _mddf.srec_len, out buf);
|
||||
|
||||
if(errno != ErrorNumber.NoError) return errno;
|
||||
|
||||
@@ -130,11 +126,7 @@ public sealed partial class LisaFS
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
errno = _device.ReadSectorsTag(_mddf.mddf_block + _volumePrefix + _mddf.srec_ptr,
|
||||
false,
|
||||
_mddf.srec_len,
|
||||
SectorTagType.AppleSonyTag,
|
||||
out buf);
|
||||
errno = ReadLisaSectorsTag(_mddf.mddf_block + _volumePrefix + _mddf.srec_ptr, _mddf.srec_len, out buf);
|
||||
|
||||
return errno != ErrorNumber.NoError ? errno : ErrorNumber.NoError;
|
||||
}
|
||||
@@ -144,7 +136,7 @@ public sealed partial class LisaFS
|
||||
// Should be enough to check 100 sectors?
|
||||
for(ulong i = 0; i < 100; i++)
|
||||
{
|
||||
errno = _device.ReadSectorTag(i, false, SectorTagType.AppleSonyTag, out byte[] tag);
|
||||
errno = ReadLisaSectorTag(i, out byte[] tag);
|
||||
|
||||
if(errno != ErrorNumber.NoError) continue;
|
||||
|
||||
@@ -160,7 +152,7 @@ public sealed partial class LisaFS
|
||||
// Should be enough to check 100 sectors?
|
||||
for(ulong i = 0; i < 100; i++)
|
||||
{
|
||||
errno = _device.ReadSectorTag(i, false, SectorTagType.AppleSonyTag, out byte[] tag);
|
||||
errno = ReadLisaSectorTag(i, out byte[] tag);
|
||||
|
||||
if(errno != ErrorNumber.NoError) continue;
|
||||
|
||||
@@ -168,9 +160,7 @@ public sealed partial class LisaFS
|
||||
|
||||
if(sysTag.FileId != fileId) continue;
|
||||
|
||||
errno = !tags
|
||||
? _device.ReadSector(i, false, out byte[] sector, out _)
|
||||
: _device.ReadSectorTag(i, false, SectorTagType.AppleSonyTag, out sector);
|
||||
errno = !tags ? ReadLisaSector(i, out byte[] sector) : ReadLisaSectorTag(i, out sector);
|
||||
|
||||
if(errno != ErrorNumber.NoError) continue;
|
||||
|
||||
@@ -306,20 +296,16 @@ public sealed partial class LisaFS
|
||||
for(var i = 0; i < file.extents.Length; i++)
|
||||
{
|
||||
ErrorNumber errno = !tags
|
||||
? _device.ReadSectors((ulong)file.extents[i].start +
|
||||
_mddf.mddf_block +
|
||||
_volumePrefix,
|
||||
false,
|
||||
(uint)file.extents[i].length,
|
||||
out byte[] sector,
|
||||
out _)
|
||||
: _device.ReadSectorsTag((ulong)file.extents[i].start +
|
||||
_mddf.mddf_block +
|
||||
_volumePrefix,
|
||||
false,
|
||||
(uint)file.extents[i].length,
|
||||
SectorTagType.AppleSonyTag,
|
||||
out sector);
|
||||
? ReadLisaSectors((ulong)file.extents[i].start +
|
||||
_mddf.mddf_block +
|
||||
_volumePrefix,
|
||||
(uint)file.extents[i].length,
|
||||
out byte[] sector)
|
||||
: ReadLisaSectorsTag((ulong)file.extents[i].start +
|
||||
_mddf.mddf_block +
|
||||
_volumePrefix,
|
||||
(uint)file.extents[i].length,
|
||||
out sector);
|
||||
|
||||
if(errno != ErrorNumber.NoError) return errno;
|
||||
|
||||
@@ -537,4 +523,4 @@ public sealed partial class LisaFS
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Aaru.CommonTypes.AaruMetadata;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
|
||||
namespace Aaru.Filesystems;
|
||||
@@ -48,6 +49,7 @@ public sealed partial class LisaFS : IReadOnlyFilesystem
|
||||
MDDF _mddf;
|
||||
bool _mounted;
|
||||
SRecord[] _srecords;
|
||||
Dictionary<ulong, ulong> _twiggyBadBlockMap;
|
||||
ulong _volumePrefix;
|
||||
|
||||
static Dictionary<string, string> GetDefaultOptions() => new()
|
||||
@@ -106,4 +108,4 @@ public sealed partial class LisaFS : IReadOnlyFilesystem
|
||||
Dictionary<short, DateTime> _directoryDtcCache;
|
||||
|
||||
#endregion Caches
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,6 +230,8 @@ public sealed partial class LisaFS
|
||||
|
||||
if(_debug) _printedExtents = [];
|
||||
|
||||
InitializeTwiggyBadBlockMap();
|
||||
|
||||
// Read the S-Records file
|
||||
ErrorNumber error = ReadSRecords();
|
||||
|
||||
@@ -356,6 +358,7 @@ public sealed partial class LisaFS
|
||||
_fileSizeCache = null;
|
||||
_printedExtents = null;
|
||||
_mddf = new MDDF();
|
||||
_twiggyBadBlockMap = null;
|
||||
_volumePrefix = 0;
|
||||
_devTagSize = 0;
|
||||
_srecords = null;
|
||||
@@ -398,4 +401,4 @@ public sealed partial class LisaFS
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user