mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
* DiscImageChef.Filesystems/LisaFS/Dir.cs:
* DiscImageChef.Filesystems/LisaFS/File.cs: * DiscImageChef.Filesystems/LisaFS/Info.cs: * DiscImageChef.Filesystems/LisaFS/Super.cs: Added hard disk support. Use tag decoder. * DiscImageChef.Filesystems/LisaFS/Extent.cs: Use tag decoder. * DiscImageChef.Filesystems/LisaFS/LisaFS.cs: Added hard disk support. * DiscImageChef.Filesystems/LisaFS/Structs.cs: Added missing tag fields. * DiscImageChef.Filesystems/LisaFS/Xattr.cs: Added tag decoder.
This commit is contained in:
@@ -97,17 +97,16 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
for(ulong i = 0; i < device.GetSectors(); i++)
|
||||
{
|
||||
byte[] tag = device.ReadSectorTag(i, SectorTagType.AppleSectorTag);
|
||||
UInt16 id = BigEndianBitConverter.ToUInt16(tag, 0x04);
|
||||
UInt16 pos = BigEndianBitConverter.ToUInt16(tag, 0x06);
|
||||
Tag catTag;
|
||||
DecodeTag(device.ReadSectorTag(i, SectorTagType.AppleSectorTag), out catTag);
|
||||
|
||||
if(id == fileId && pos == 0)
|
||||
if(catTag.fileID == fileId && catTag.relBlock == 0)
|
||||
{
|
||||
firstCatalogBlock = device.ReadSectors(i, 4);
|
||||
break;
|
||||
}
|
||||
|
||||
if(id == -fileId)
|
||||
if(catTag.fileID == -fileId)
|
||||
return Errno.NotDirectory;
|
||||
}
|
||||
|
||||
@@ -119,13 +118,13 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
while(prevCatalogPointer != 0xFFFFFFFF)
|
||||
{
|
||||
byte[] tag = device.ReadSectorTag(prevCatalogPointer + mddf.mddf_block, SectorTagType.AppleSectorTag);
|
||||
UInt16 id = BigEndianBitConverter.ToUInt16(tag, 0x04);
|
||||
Tag prevTag;
|
||||
DecodeTag(device.ReadSectorTag(prevCatalogPointer + mddf.mddf_block + volumePrefix, SectorTagType.AppleSectorTag), out prevTag);
|
||||
|
||||
if(id != fileId)
|
||||
if(prevTag.fileID != fileId)
|
||||
return Errno.InvalidArgument;
|
||||
|
||||
firstCatalogBlock = device.ReadSectors(prevCatalogPointer + mddf.mddf_block, 4);
|
||||
firstCatalogBlock = device.ReadSectors(prevCatalogPointer + mddf.mddf_block + volumePrefix, 4);
|
||||
prevCatalogPointer = BigEndianBitConverter.ToUInt32(firstCatalogBlock, 0x7F6);
|
||||
}
|
||||
|
||||
@@ -137,13 +136,13 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
while(nextCatalogPointer != 0xFFFFFFFF)
|
||||
{
|
||||
byte[] tag = device.ReadSectorTag(nextCatalogPointer + mddf.mddf_block, SectorTagType.AppleSectorTag);
|
||||
UInt16 id = BigEndianBitConverter.ToUInt16(tag, 0x04);
|
||||
Tag nextTag;
|
||||
DecodeTag(device.ReadSectorTag(nextCatalogPointer + mddf.mddf_block + volumePrefix, SectorTagType.AppleSectorTag), out nextTag);
|
||||
|
||||
if(id != fileId)
|
||||
if(nextTag.fileID != fileId)
|
||||
return Errno.InvalidArgument;
|
||||
|
||||
byte[] nextCatalogBlock = device.ReadSectors(nextCatalogPointer + mddf.mddf_block, 4);
|
||||
byte[] nextCatalogBlock = device.ReadSectors(nextCatalogPointer + mddf.mddf_block + volumePrefix, 4);
|
||||
nextCatalogPointer = BigEndianBitConverter.ToUInt32(nextCatalogBlock, 0x7FA);
|
||||
catalogBlocks.Add(nextCatalogBlock);
|
||||
}
|
||||
|
||||
@@ -73,13 +73,13 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
for(ulong i = 0; i < device.GetSectors(); i++)
|
||||
{
|
||||
byte[] tag = device.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag);
|
||||
Int16 foundid = BigEndianBitConverter.ToInt16(tag, 0x04);
|
||||
Tag extTag;
|
||||
DecodeTag(device.ReadSectorTag(i, SectorTagType.AppleSectorTag), out extTag);
|
||||
|
||||
if(foundid == fileId)
|
||||
if(extTag.fileID == fileId)
|
||||
fileFound = true;
|
||||
|
||||
if(foundid == ((short)(-1 * fileId)))
|
||||
if(extTag.fileID == ((short)(-1 * fileId)))
|
||||
{
|
||||
byte[] sector = device.ReadSector((ulong)i);
|
||||
|
||||
|
||||
@@ -204,13 +204,14 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
int count = 0;
|
||||
|
||||
Tag sysTag;
|
||||
|
||||
// Should be enough to check 100 sectors?
|
||||
for(ulong i = 0; i < 100; i++)
|
||||
{
|
||||
byte[] tag = device.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag);
|
||||
Int16 id = BigEndianBitConverter.ToInt16(tag, 0x04);
|
||||
DecodeTag(device.ReadSectorTag(i, SectorTagType.AppleSectorTag), out sysTag);
|
||||
|
||||
if(id == fileId)
|
||||
if(sysTag.fileID == fileId)
|
||||
count++;
|
||||
}
|
||||
|
||||
@@ -220,25 +221,27 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
if(!tags)
|
||||
buf = new byte[count * device.GetSectorSize()];
|
||||
else
|
||||
buf = new byte[count * 12];
|
||||
buf = new byte[count * devTagSize];
|
||||
|
||||
// Should be enough to check 100 sectors?
|
||||
for(ulong i = 0; i < 100; i++)
|
||||
{
|
||||
byte[] tag = device.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag);
|
||||
UInt16 id = BigEndianBitConverter.ToUInt16(tag, 0x04);
|
||||
DecodeTag(device.ReadSectorTag(i, SectorTagType.AppleSectorTag), out sysTag);
|
||||
|
||||
if(id == fileId)
|
||||
if(sysTag.fileID == fileId)
|
||||
{
|
||||
UInt16 pos = BigEndianBitConverter.ToUInt16(tag, 0x06);
|
||||
byte[] sector;
|
||||
|
||||
if(!tags)
|
||||
sector = device.ReadSector(i);
|
||||
else
|
||||
sector = device.ReadSectorTag(i, SectorTagType.AppleSectorTag);
|
||||
|
||||
Array.Copy(sector, 0, buf, sector.Length * pos, sector.Length);
|
||||
|
||||
// Relative block for $Loader starts at $Boot block
|
||||
if(sysTag.fileID == FILEID_LOADER_SIGNED)
|
||||
sysTag.relBlock--;
|
||||
|
||||
Array.Copy(sector, 0, buf, sector.Length * sysTag.relBlock, sector.Length);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -387,7 +390,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
int sectorSize;
|
||||
if(tags)
|
||||
sectorSize = 12;
|
||||
sectorSize = devTagSize;
|
||||
else
|
||||
sectorSize = (int)device.GetSectorSize();
|
||||
|
||||
@@ -399,9 +402,9 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
byte[] sector;
|
||||
|
||||
if(!tags)
|
||||
sector = device.ReadSectors((ulong)(file.extents[i].start + mddf.mddf_block), (uint)file.extents[i].length);
|
||||
sector = device.ReadSectors(((ulong)file.extents[i].start + mddf.mddf_block + volumePrefix), (uint)file.extents[i].length);
|
||||
else
|
||||
sector = device.ReadSectorsTag((ulong)(file.extents[i].start + mddf.mddf_block), (uint)file.extents[i].length, SectorTagType.AppleSectorTag);
|
||||
sector = device.ReadSectorsTag(((ulong)file.extents[i].start + mddf.mddf_block + volumePrefix), (uint)file.extents[i].length, SectorTagType.AppleSectorTag);
|
||||
|
||||
Array.Copy(sector, 0, temp, offset, sector.Length);
|
||||
offset += sector.Length;
|
||||
|
||||
@@ -39,6 +39,7 @@ using System;
|
||||
using System.Text;
|
||||
using DiscImageChef.Console;
|
||||
using DiscImageChef.ImagePlugins;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace DiscImageChef.Filesystems.LisaFS
|
||||
{
|
||||
@@ -61,15 +62,20 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
if(imagePlugin.GetSectors() < 800)
|
||||
return false;
|
||||
|
||||
int before_mddf = -1;
|
||||
|
||||
// LisaOS searches sectors until tag tells MDDF resides there, so we'll search 100 sectors
|
||||
for(int i = 0; i < 100; i++)
|
||||
{
|
||||
byte[] tag = imagePlugin.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag);
|
||||
UInt16 fileid = BigEndianBitConverter.ToUInt16(tag, 0x04);
|
||||
Tag searchTag;
|
||||
DecodeTag(imagePlugin.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag), out searchTag);
|
||||
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Sector {0}, file ID 0x{1:X4}", i, fileid);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Sector {0}, file ID 0x{1:X4}", i, searchTag.fileID);
|
||||
|
||||
if(fileid == FILEID_MDDF)
|
||||
if(before_mddf == -1 && searchTag.fileID == FILEID_LOADER_SIGNED)
|
||||
before_mddf = i - 1;
|
||||
|
||||
if(searchTag.fileID == FILEID_MDDF)
|
||||
{
|
||||
byte[] sector = imagePlugin.ReadSector((ulong)i);
|
||||
MDDF mddf = new MDDF();
|
||||
@@ -91,7 +97,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.blocksize = {0} bytes", mddf.blocksize);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.datasize = {0} bytes", mddf.datasize);
|
||||
|
||||
if(mddf.mddf_block != i)
|
||||
if(mddf.mddf_block != i - before_mddf)
|
||||
return false;
|
||||
|
||||
if(mddf.vol_size > imagePlugin.GetSectors())
|
||||
@@ -100,7 +106,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
if(mddf.vol_size - 1 != mddf.volsize_minus_one)
|
||||
return false;
|
||||
|
||||
if(mddf.vol_size - i - 1 != mddf.volsize_minus_mddf_minus_one)
|
||||
if(mddf.vol_size - i - 1 != mddf.volsize_minus_mddf_minus_one - before_mddf)
|
||||
return false;
|
||||
|
||||
if(mddf.datasize > mddf.blocksize)
|
||||
@@ -145,15 +151,20 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
if(imagePlugin.GetSectors() < 800)
|
||||
return;
|
||||
|
||||
int before_mddf = -1;
|
||||
|
||||
// LisaOS searches sectors until tag tells MDDF resides there, so we'll search 100 sectors
|
||||
for(int i = 0; i < 100; i++)
|
||||
{
|
||||
byte[] tag = imagePlugin.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag);
|
||||
UInt16 fileid = BigEndianBitConverter.ToUInt16(tag, 0x04);
|
||||
Tag searchTag;
|
||||
DecodeTag(imagePlugin.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag), out searchTag);
|
||||
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Sector {0}, file ID 0x{1:X4}", i, fileid);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Sector {0}, file ID 0x{1:X4}", i, searchTag.fileID);
|
||||
|
||||
if(fileid == FILEID_MDDF)
|
||||
if(before_mddf == -1 && searchTag.fileID == FILEID_LOADER_SIGNED)
|
||||
before_mddf = i - 1;
|
||||
|
||||
if(searchTag.fileID == FILEID_MDDF)
|
||||
{
|
||||
byte[] sector = imagePlugin.ReadSector((ulong)i);
|
||||
MDDF mddf = new MDDF();
|
||||
@@ -281,7 +292,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown38 = 0x{0:X8} ({0})", mddf.unknown38);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown_timestamp = 0x{0:X8} ({0}, {1})", mddf.unknown_timestamp, DateHandlers.LisaToDateTime(mddf.unknown_timestamp));
|
||||
|
||||
if(mddf.mddf_block != i)
|
||||
if(mddf.mddf_block != i - before_mddf)
|
||||
return;
|
||||
|
||||
if(mddf.vol_size > imagePlugin.GetSectors())
|
||||
@@ -290,7 +301,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
if(mddf.vol_size - 1 != mddf.volsize_minus_one)
|
||||
return;
|
||||
|
||||
if(mddf.vol_size - i - 1 != mddf.volsize_minus_mddf_minus_one)
|
||||
if(mddf.vol_size - i - 1 != mddf.volsize_minus_mddf_minus_one - before_mddf)
|
||||
return;
|
||||
|
||||
if(mddf.datasize > mddf.blocksize)
|
||||
@@ -334,7 +345,8 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
sb.AppendFormat("Some timestamp, says {0}", mddf.dtcc).AppendLine();
|
||||
sb.AppendFormat("Volume backed up on {0}", mddf.dtvb).AppendLine();
|
||||
sb.AppendFormat("Volume scavenged on {0}", mddf.dtvs).AppendLine();
|
||||
sb.AppendFormat("MDDF is in block {0}", mddf.mddf_block).AppendLine();
|
||||
sb.AppendFormat("MDDF is in block {0}", mddf.mddf_block + before_mddf).AppendLine();
|
||||
sb.AppendFormat("There are {0} reserved blocks before volume", before_mddf).AppendLine();
|
||||
sb.AppendFormat("{0} blocks minus one", mddf.volsize_minus_one).AppendLine();
|
||||
sb.AppendFormat("{0} blocks minus one minus MDDF offset", mddf.volsize_minus_mddf_minus_one).AppendLine();
|
||||
sb.AppendFormat("{0} blocks in volume", mddf.vol_size).AppendLine();
|
||||
|
||||
@@ -52,6 +52,8 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
readonly ImagePlugin device;
|
||||
|
||||
MDDF mddf;
|
||||
ulong volumePrefix;
|
||||
int devTagSize;
|
||||
|
||||
#region Caches
|
||||
Dictionary<Int16, ExtentFile> extentCache;
|
||||
|
||||
@@ -205,20 +205,37 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
struct Tag
|
||||
{
|
||||
/// <summary>0x00 Unknown</summary>
|
||||
/// <summary>0x00 version</summary>
|
||||
public UInt16 version;
|
||||
/// <summary>0x02 unknown</summary>
|
||||
public UInt16 unknown;
|
||||
/// <summary>0x02 File type</summary>
|
||||
public byte fileType;
|
||||
/// <summary>Seems to be always zero</summary>
|
||||
public byte zero;
|
||||
/// <summary>0x04 File ID. Negative numbers are extents for the file with same absolute value number</summary>
|
||||
public Int16 fileID;
|
||||
/// <summary>0x06 Relative block</summary>
|
||||
/// <summary>Only in 20 bytes tag at 0x06, mask 0x8000 if valid tag</summary>
|
||||
public UInt16 usedBytes;
|
||||
/// <summary>Only in 20 bytes tag at 0x08, 3 bytes</summary>
|
||||
public UInt32 absoluteBlock;
|
||||
/// <summary>Only in 20 bytes tag at 0x0B, checksum byte</summary>
|
||||
public byte checksum;
|
||||
/// <summary>0x06 in 12 bytes tag, 0x0C in 20 bytes tag, relative block</summary>
|
||||
public UInt16 relBlock;
|
||||
/// <summary>0x08 Next block for this file. 0x8000 bit seems always set, 0x07FF means this is last block</summary>
|
||||
public UInt16 nextBlock;
|
||||
/// <summary>0x0A Previous block for this file. 0x07FF means this is first block.</summary>
|
||||
public UInt16 prevBlock;
|
||||
/// <summary>
|
||||
/// Next block for this file.
|
||||
/// In 12 bytes tag at 0x08, 2 bytes, 0x8000 bit seems always set, 0x07FF means this is last block.
|
||||
/// In 20 bytes tag at 0x0E, 3 bytes, 0xFFFFFF means this is last block.
|
||||
/// </summary>
|
||||
public UInt32 nextBlock;
|
||||
/// <summary>
|
||||
/// Previous block for this file.
|
||||
/// In 12 bytes tag at 0x0A, 2 bytes, 0x07FF means this is first block.
|
||||
/// In 20 bytes tag at 0x11, 3 bytes, 0xFFFFFF means this is first block.
|
||||
/// </summary>
|
||||
public UInt32 prevBlock;
|
||||
|
||||
/// <summary>On-memory value for easy first block search.</summary>
|
||||
public bool isFirst;
|
||||
/// <summary>On-memory value for easy last block search.</summary>
|
||||
public bool isLast;
|
||||
}
|
||||
|
||||
struct CatalogEntry
|
||||
|
||||
@@ -71,16 +71,24 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
return Errno.InOutError;
|
||||
}
|
||||
|
||||
// MDDF cannot be at end of device, of course
|
||||
volumePrefix = device.ImageInfo.sectors;
|
||||
|
||||
// LisaOS searches sectors until tag tells MDDF resides there, so we'll search 100 sectors
|
||||
for(int i = 0; i < 100; i++)
|
||||
for(ulong i = 0; i < 100; i++)
|
||||
{
|
||||
byte[] tag = device.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag);
|
||||
UInt16 fileid = BigEndianBitConverter.ToUInt16(tag, 0x04);
|
||||
Tag searchTag;
|
||||
DecodeTag(device.ReadSectorTag(i, SectorTagType.AppleSectorTag), out searchTag);
|
||||
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Sector {0}, file ID 0x{1:X4}", i, fileid);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Sector {0}, file ID 0x{1:X4}", i, searchTag.fileID);
|
||||
|
||||
if(fileid == FILEID_MDDF)
|
||||
if(volumePrefix == device.ImageInfo.sectors && searchTag.fileID == FILEID_LOADER_SIGNED)
|
||||
volumePrefix = i - 1;
|
||||
|
||||
if(searchTag.fileID == FILEID_MDDF)
|
||||
{
|
||||
devTagSize = device.ReadSectorTag(i, SectorTagType.AppleSectorTag).Length;
|
||||
|
||||
byte[] sector = device.ReadSector((ulong)i);
|
||||
mddf = new MDDF();
|
||||
byte[] pString = new byte[33];
|
||||
@@ -167,10 +175,10 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
mddf.vol_sequence = BigEndianBitConverter.ToUInt16(sector, 0x136);
|
||||
mddf.vol_left_mounted = sector[0x138];
|
||||
|
||||
if(mddf.mddf_block != i ||
|
||||
if(mddf.mddf_block != i - volumePrefix ||
|
||||
mddf.vol_size > device.GetSectors() ||
|
||||
mddf.vol_size - 1 != mddf.volsize_minus_one ||
|
||||
mddf.vol_size - i - 1 != mddf.volsize_minus_mddf_minus_one ||
|
||||
mddf.vol_size - i - 1 != mddf.volsize_minus_mddf_minus_one - volumePrefix ||
|
||||
mddf.datasize > mddf.blocksize ||
|
||||
mddf.blocksize < device.GetSectorSize() ||
|
||||
mddf.datasize != device.GetSectorSize())
|
||||
|
||||
@@ -177,6 +177,50 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
return Errno.NoSuchExtendedAttribute;
|
||||
}
|
||||
|
||||
Errno DecodeTag(byte[] tag, out Tag decoded)
|
||||
{
|
||||
decoded = new Tag();
|
||||
|
||||
if(tag.Length == 12)
|
||||
{
|
||||
decoded.version = BigEndianBitConverter.ToUInt16(tag, 0x00);
|
||||
decoded.unknown = BigEndianBitConverter.ToUInt16(tag, 0x02);
|
||||
decoded.fileID = BigEndianBitConverter.ToInt16(tag, 0x04);
|
||||
decoded.relBlock = BigEndianBitConverter.ToUInt16(tag, 0x06);
|
||||
decoded.nextBlock = BigEndianBitConverter.ToUInt16(tag, 0x08);
|
||||
decoded.nextBlock &= 0x7FF;
|
||||
decoded.prevBlock = BigEndianBitConverter.ToUInt16(tag, 0x0A);
|
||||
decoded.prevBlock &= 0x7FF;
|
||||
|
||||
if(decoded.nextBlock == 0x7FF)
|
||||
decoded.isLast = true;
|
||||
if(decoded.prevBlock == 0x7FF)
|
||||
decoded.isFirst = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
decoded.version = BigEndianBitConverter.ToUInt16(tag, 0x00);
|
||||
decoded.unknown = BigEndianBitConverter.ToUInt16(tag, 0x02);
|
||||
decoded.fileID = BigEndianBitConverter.ToInt16(tag, 0x04);
|
||||
decoded.usedBytes = BigEndianBitConverter.ToUInt16(tag, 0x06);
|
||||
decoded.absoluteBlock = BigEndianBitConverter.ToUInt32(tag, 0x07);
|
||||
decoded.absoluteBlock &= 0xFFFFFF;
|
||||
decoded.checksum = tag[0x0B];
|
||||
decoded.relBlock = BigEndianBitConverter.ToUInt16(tag, 0x0C);
|
||||
decoded.nextBlock = BigEndianBitConverter.ToUInt32(tag, 0x0D);
|
||||
decoded.nextBlock &= 0xFFFFFF;
|
||||
decoded.prevBlock = BigEndianBitConverter.ToUInt32(tag, 0x10);
|
||||
decoded.prevBlock &= 0xFFFFFF;
|
||||
|
||||
if(decoded.nextBlock == 0xFFFFFF)
|
||||
decoded.isLast = true;
|
||||
if(decoded.prevBlock == 0xFFFFFF)
|
||||
decoded.isFirst = true;
|
||||
}
|
||||
|
||||
return Errno.NoError;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user