* 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:
2016-07-27 22:13:47 +01:00
parent c2717100d9
commit 44d436ab04
8 changed files with 145 additions and 60 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -52,6 +52,8 @@ namespace DiscImageChef.Filesystems.LisaFS
readonly ImagePlugin device;
MDDF mddf;
ulong volumePrefix;
int devTagSize;
#region Caches
Dictionary<Int16, ExtentFile> extentCache;

View File

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

View File

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

View File

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