mirror of
https://github.com/aaru-dps/Aaru.Server.git
synced 2025-12-16 19:24:27 +00:00
REFACTOR: Final cleanup of DiscImageChef.Filesystems.
This commit is contained in:
@@ -35,48 +35,48 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
public partial class LisaFS
|
||||
{
|
||||
/// <summary>
|
||||
/// Lisa FS v1, from Lisa OS 1.0 (Workshop or Office)
|
||||
/// Never seen on Sony floppies.
|
||||
/// Lisa FS v1, from Lisa OS 1.0 (Workshop or Office)
|
||||
/// Never seen on Sony floppies.
|
||||
/// </summary>
|
||||
const byte LISA_V1 = 0x0E;
|
||||
/// <summary>
|
||||
/// Lisa FS v2, from Lisa OS 2.0 (Workshop or Office)
|
||||
/// Contrary to what most information online says the only difference with V1
|
||||
/// is the Extents File size. Catalog format is the same
|
||||
/// Lisa FS v2, from Lisa OS 2.0 (Workshop or Office)
|
||||
/// Contrary to what most information online says the only difference with V1
|
||||
/// is the Extents File size. Catalog format is the same
|
||||
/// </summary>
|
||||
const byte LISA_V2 = 0x0F;
|
||||
/// <summary>
|
||||
/// Lisa FS v3, from Lisa OS 3.0 (Workshop or Office)
|
||||
/// Adds support for user catalogs (aka subdirectories),
|
||||
/// and changes the catalog format from extents to double-linked list.
|
||||
/// Uses '-' as path separator (so people that created Lisa/FILE.TEXT just
|
||||
/// created a file named like that :p)
|
||||
/// Lisa FS v3, from Lisa OS 3.0 (Workshop or Office)
|
||||
/// Adds support for user catalogs (aka subdirectories),
|
||||
/// and changes the catalog format from extents to double-linked list.
|
||||
/// Uses '-' as path separator (so people that created Lisa/FILE.TEXT just
|
||||
/// created a file named like that :p)
|
||||
/// </summary>
|
||||
const byte LISA_V3 = 0x11;
|
||||
/// <summary>Maximum string size in LisaFS</summary>
|
||||
const uint E_NAME = 32;
|
||||
/// <summary>
|
||||
/// Unused file ID
|
||||
/// Unused file ID
|
||||
/// </summary>
|
||||
const ushort FILEID_FREE = 0x0000;
|
||||
/// <summary>
|
||||
/// Used by the boot blocks
|
||||
/// Used by the boot blocks
|
||||
/// </summary>
|
||||
const ushort FILEID_BOOT = 0xAAAA;
|
||||
/// <summary>
|
||||
/// Used by the operating system loader blocks
|
||||
/// Used by the operating system loader blocks
|
||||
/// </summary>
|
||||
const ushort FILEID_LOADER = 0xBBBB;
|
||||
/// <summary>
|
||||
/// Used by the MDDF
|
||||
/// Used by the MDDF
|
||||
/// </summary>
|
||||
const ushort FILEID_MDDF = 0x0001;
|
||||
/// <summary>
|
||||
/// Used by the volume bitmap, sits between MDDF and S-Records file.
|
||||
/// Used by the volume bitmap, sits between MDDF and S-Records file.
|
||||
/// </summary>
|
||||
const ushort FILEID_BITMAP = 0x0002;
|
||||
/// <summary>
|
||||
/// S-Records file
|
||||
/// S-Records file
|
||||
/// </summary>
|
||||
const ushort FILEID_SRECORD = 0x0003;
|
||||
/// <summary>The root catalog</summary>
|
||||
@@ -84,7 +84,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
const short FILEID_BOOT_SIGNED = -21846;
|
||||
const short FILEID_LOADER_SIGNED = -17477;
|
||||
/// <summary>
|
||||
/// A file that has been erased
|
||||
/// A file that has been erased
|
||||
/// </summary>
|
||||
const ushort FILEID_ERASED = 0x7FFF;
|
||||
const ushort FILEID_MAX = FILEID_ERASED;
|
||||
@@ -95,67 +95,67 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
enum FileType : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Undefined file type
|
||||
/// Undefined file type
|
||||
/// </summary>
|
||||
Undefined = 0,
|
||||
/// <summary>
|
||||
/// MDDF
|
||||
/// MDDF
|
||||
/// </summary>
|
||||
MDDFile = 1,
|
||||
/// <summary>
|
||||
/// Root catalog
|
||||
/// Root catalog
|
||||
/// </summary>
|
||||
RootCat = 2,
|
||||
/// <summary>
|
||||
/// Bitmap
|
||||
/// Bitmap
|
||||
/// </summary>
|
||||
FreeList = 3,
|
||||
/// <summary>
|
||||
/// Unknown, maybe refers to the S-Records File?
|
||||
/// Unknown, maybe refers to the S-Records File?
|
||||
/// </summary>
|
||||
BadBlocks = 4,
|
||||
/// <summary>
|
||||
/// System data
|
||||
/// System data
|
||||
/// </summary>
|
||||
SysData = 5,
|
||||
/// <summary>
|
||||
/// Printer spool
|
||||
/// Printer spool
|
||||
/// </summary>
|
||||
Spool = 6,
|
||||
/// <summary>
|
||||
/// Executable. Yet application files don't use it
|
||||
/// Executable. Yet application files don't use it
|
||||
/// </summary>
|
||||
Exec = 7,
|
||||
/// <summary>
|
||||
/// User catalog
|
||||
/// User catalog
|
||||
/// </summary>
|
||||
UserCat = 8,
|
||||
/// <summary>
|
||||
/// Pipe. Not seen on disk.
|
||||
/// Pipe. Not seen on disk.
|
||||
/// </summary>
|
||||
Pipe = 9,
|
||||
/// <summary>
|
||||
/// Boot file?
|
||||
/// Boot file?
|
||||
/// </summary>
|
||||
BootFile = 10,
|
||||
/// <summary>
|
||||
/// Swap for data
|
||||
/// Swap for data
|
||||
/// </summary>
|
||||
SwapData = 11,
|
||||
/// <summary>
|
||||
/// Swap for code
|
||||
/// Swap for code
|
||||
/// </summary>
|
||||
SwapCode = 12,
|
||||
/// <summary>
|
||||
/// Unknown
|
||||
/// Unknown
|
||||
/// </summary>
|
||||
RamAP = 13,
|
||||
/// <summary>
|
||||
/// Any file
|
||||
/// Any file
|
||||
/// </summary>
|
||||
UserFile = 14,
|
||||
/// <summary>
|
||||
/// Erased?
|
||||
/// Erased?
|
||||
/// </summary>
|
||||
KilledObject = 15
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
public partial class LisaFS
|
||||
{
|
||||
/// <summary>
|
||||
/// Solves a symbolic link.
|
||||
/// Solves a symbolic link.
|
||||
/// </summary>
|
||||
/// <param name="path">Link path.</param>
|
||||
/// <param name="dest">Link destination.</param>
|
||||
@@ -52,7 +52,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lists contents from a directory.
|
||||
/// Lists contents from a directory.
|
||||
/// </summary>
|
||||
/// <param name="path">Directory path.</param>
|
||||
/// <param name="contents">Directory contents.</param>
|
||||
@@ -90,13 +90,15 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
{
|
||||
// Do same trick as Mac OS X, replace filesystem '/' with '-',
|
||||
// as '-' is the path separator in Lisa OS
|
||||
contents = (from entry in catalogCache where entry.parentID == dirId select StringHandlers.CToString(entry.filename, CurrentEncoding).Replace('/', '-')).ToList();
|
||||
contents = (from entry in catalogCache
|
||||
where entry.parentID == dirId
|
||||
select StringHandlers.CToString(entry.filename, CurrentEncoding).Replace('/', '-')).ToList();
|
||||
|
||||
return Errno.NoError;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads, interprets and caches the Catalog File
|
||||
/// Reads, interprets and caches the Catalog File
|
||||
/// </summary>
|
||||
Errno ReadCatalog()
|
||||
{
|
||||
@@ -215,7 +217,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
// Traverse all entries
|
||||
while(offset + 64 <= buf.Length)
|
||||
// Catalog block header
|
||||
// Catalog block header
|
||||
if(buf[offset + 0x24] == 0x08) offset += 78;
|
||||
// Maybe just garbage? Found in more than 1 disk
|
||||
else if(buf[offset + 0x24] == 0x7C) offset += 50;
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches the disk for an extents file (or gets it from cache)
|
||||
/// Searches the disk for an extents file (or gets it from cache)
|
||||
/// </summary>
|
||||
/// <returns>Error.</returns>
|
||||
/// <param name="fileId">File identifier.</param>
|
||||
@@ -171,13 +171,11 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
file.extents = new Extent[extentsCount];
|
||||
|
||||
for(int j = 0; j < extentsCount; j++)
|
||||
{
|
||||
file.extents[j] = new Extent
|
||||
{
|
||||
{
|
||||
start = BigEndianBitConverter.ToInt32(sector, extentsOffset + j * 6),
|
||||
length = BigEndianBitConverter.ToInt16(sector, extentsOffset + j * 6 + 4)
|
||||
};
|
||||
}
|
||||
|
||||
extentCache.Add(fileId, file);
|
||||
|
||||
@@ -185,77 +183,64 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
if(printedExtents.Contains(fileId)) return Errno.NoError;
|
||||
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].filenameLen = {1}", fileId,
|
||||
file.filenameLen);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].filenameLen = {1}", fileId, file.filenameLen);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].filename = {1}", fileId,
|
||||
StringHandlers.CToString(file.filename, CurrentEncoding));
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown1 = 0x{1:X4}", fileId,
|
||||
file.unknown1);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].file_uid = 0x{1:X16}", fileId,
|
||||
file.file_uid);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown2 = 0x{1:X2}", fileId,
|
||||
file.unknown2);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown1 = 0x{1:X4}", fileId, file.unknown1);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].file_uid = 0x{1:X16}", fileId, file.file_uid);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown2 = 0x{1:X2}", fileId, file.unknown2);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].etype = 0x{1:X2}", fileId, file.etype);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].ftype = {1}", fileId, file.ftype);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown3 = 0x{1:X2}", fileId,
|
||||
file.unknown3);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown3 = 0x{1:X2}", fileId, file.unknown3);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].dtc = {1}", fileId, file.dtc);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].dta = {1}", fileId, file.dta);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].dtm = {1}", fileId, file.dtm);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].dtb = {1}", fileId, file.dtb);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].dts = {1}", fileId, file.dts);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].serial = {1}", fileId, file.serial);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown4 = 0x{1:X2}", fileId,
|
||||
file.unknown4);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown4 = 0x{1:X2}", fileId, file.unknown4);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].locked = {1}", fileId, file.locked > 0);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].protect = {1}", fileId,
|
||||
file.protect > 0);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].protect = {1}", fileId, file.protect > 0);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].master = {1}", fileId, file.master > 0);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].scavenged = {1}", fileId,
|
||||
file.scavenged > 0);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].scavenged = {1}", fileId, file.scavenged > 0);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].closed = {1}", fileId, file.closed > 0);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].open = {1}", fileId, file.open > 0);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin",
|
||||
"ExtentFile[{0}].unknown5 = 0x{1:X2}{2:X2}{3:X2}{4:X2}{5:X2}{6:X2}{7:X2}{8:X2}{9:X2}" +
|
||||
"{10:X2}{11:X2}", fileId, file.unknown5[0], file.unknown5[1],
|
||||
file.unknown5[2], file.unknown5[3], file.unknown5[4], file.unknown5[5],
|
||||
file.unknown5[6], file.unknown5[7], file.unknown5[8], file.unknown5[9],
|
||||
file.unknown5[10]);
|
||||
"{10:X2}{11:X2}", fileId, file.unknown5[0], file.unknown5[1], file.unknown5[2],
|
||||
file.unknown5[3], file.unknown5[4], file.unknown5[5], file.unknown5[6],
|
||||
file.unknown5[7], file.unknown5[8], file.unknown5[9], file.unknown5[10]);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].release = {1}", fileId, file.release);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].build = {1}", fileId, file.build);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].compatibility = {1}", fileId,
|
||||
file.compatibility);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].revision = {1}", fileId, file.revision);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown6 = 0x{1:X4}", fileId,
|
||||
file.unknown6);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown6 = 0x{1:X4}", fileId, file.unknown6);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].password_valid = {1}", fileId,
|
||||
file.password_valid > 0);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].password = {1}", fileId,
|
||||
CurrentEncoding.GetString(file.password));
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown7 = 0x{1:X2}{2:X2}{3:X2}",
|
||||
fileId, file.unknown7[0], file.unknown7[1], file.unknown7[2]);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown7 = 0x{1:X2}{2:X2}{3:X2}", fileId,
|
||||
file.unknown7[0], file.unknown7[1], file.unknown7[2]);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].overhead = {1}", fileId, file.overhead);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin",
|
||||
"ExtentFile[{0}].unknown8 = 0x{1:X2}{2:X2}{3:X2}{4:X2}{5:X2}{6:X2}{7:X2}{8:X2}{9:X2}" +
|
||||
"{10:X2}{11:X2}{12:X2}{13:X2}{14:X2}{15:X2}{16:X2}", fileId,
|
||||
file.unknown8[0], file.unknown8[1], file.unknown8[2], file.unknown8[3],
|
||||
file.unknown8[4], file.unknown8[5], file.unknown8[6], file.unknown8[7],
|
||||
file.unknown8[8], file.unknown8[9], file.unknown8[10], file.unknown8[11],
|
||||
file.unknown8[12], file.unknown8[13], file.unknown8[14],
|
||||
file.unknown8[15]);
|
||||
"{10:X2}{11:X2}{12:X2}{13:X2}{14:X2}{15:X2}{16:X2}", fileId, file.unknown8[0],
|
||||
file.unknown8[1], file.unknown8[2], file.unknown8[3], file.unknown8[4],
|
||||
file.unknown8[5], file.unknown8[6], file.unknown8[7], file.unknown8[8],
|
||||
file.unknown8[9], file.unknown8[10], file.unknown8[11], file.unknown8[12],
|
||||
file.unknown8[13], file.unknown8[14], file.unknown8[15]);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].length = {1}", fileId, file.length);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown9 = 0x{1:X8}", fileId,
|
||||
file.unknown9);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown9 = 0x{1:X8}", fileId, file.unknown9);
|
||||
for(int ext = 0; ext < file.extents.Length; ext++)
|
||||
{
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].extents[{1}].start = {2}", fileId,
|
||||
ext, file.extents[ext].start);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].extents[{1}].length = {2}", fileId,
|
||||
ext, file.extents[ext].length);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].extents[{1}].start = {2}", fileId, ext,
|
||||
file.extents[ext].start);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].extents[{1}].length = {2}", fileId, ext,
|
||||
file.extents[ext].length);
|
||||
}
|
||||
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown10 = 0x{1:X4}", fileId,
|
||||
file.unknown10);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown10 = 0x{1:X4}", fileId, file.unknown10);
|
||||
|
||||
printedExtents.Add(fileId);
|
||||
|
||||
@@ -263,7 +248,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads all the S-Records and caches it
|
||||
/// Reads all the S-Records and caches it
|
||||
/// </summary>
|
||||
Errno ReadSRecords()
|
||||
{
|
||||
@@ -276,15 +261,13 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
srecords = new SRecord[sectors.Length / 14];
|
||||
|
||||
for(int s = 0; s < srecords.Length; s++)
|
||||
{
|
||||
srecords[s] = new SRecord
|
||||
{
|
||||
{
|
||||
extent_ptr = BigEndianBitConverter.ToUInt32(sectors, 0x00 + 14 * s),
|
||||
unknown = BigEndianBitConverter.ToUInt32(sectors, 0x04 + 14 * s),
|
||||
filesize = BigEndianBitConverter.ToUInt32(sectors, 0x08 + 14 * s),
|
||||
flags = BigEndianBitConverter.ToUInt16(sectors, 0x0C + 14 * s)
|
||||
};
|
||||
}
|
||||
|
||||
return Errno.NoError;
|
||||
}
|
||||
|
||||
@@ -161,7 +161,8 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
buf = null;
|
||||
if(!mounted || !debug) return Errno.AccessDenied;
|
||||
|
||||
if(fileId > 4 || fileId <= 0) if(fileId != FILEID_BOOT_SIGNED && fileId != FILEID_LOADER_SIGNED) return Errno.InvalidArgument;
|
||||
if(fileId > 4 || fileId <= 0)
|
||||
if(fileId != FILEID_BOOT_SIGNED && fileId != FILEID_LOADER_SIGNED) return Errno.InvalidArgument;
|
||||
|
||||
if(systemFileCache.TryGetValue(fileId, out buf) && !tags) return Errno.NoError;
|
||||
|
||||
@@ -346,7 +347,8 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
if(!tags)
|
||||
{
|
||||
if(fileSizeCache.TryGetValue(fileId, out int realSize)) if(realSize > temp.Length) DicConsole.ErrorWriteLine("File {0} gets truncated.", fileId);
|
||||
if(fileSizeCache.TryGetValue(fileId, out int realSize))
|
||||
if(realSize > temp.Length) DicConsole.ErrorWriteLine("File {0} gets truncated.", fileId);
|
||||
buf = temp;
|
||||
|
||||
fileCache.Add(fileId, buf);
|
||||
|
||||
@@ -61,7 +61,8 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
// LisaOS searches sectors until tag tells MDDF resides there, so we'll search 100 sectors
|
||||
for(int i = 0; i < 100; i++)
|
||||
{
|
||||
DecodeTag(imagePlugin.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag), out LisaTag.PriamTag searchTag);
|
||||
DecodeTag(imagePlugin.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag),
|
||||
out LisaTag.PriamTag searchTag);
|
||||
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Sector {0}, file ID 0x{1:X4}", i, searchTag.FileId);
|
||||
|
||||
@@ -137,7 +138,8 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
// LisaOS searches sectors until tag tells MDDF resides there, so we'll search 100 sectors
|
||||
for(int i = 0; i < 100; i++)
|
||||
{
|
||||
DecodeTag(imagePlugin.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag), out LisaTag.PriamTag searchTag);
|
||||
DecodeTag(imagePlugin.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag),
|
||||
out LisaTag.PriamTag searchTag);
|
||||
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Sector {0}, file ID 0x{1:X4}", i, searchTag.FileId);
|
||||
|
||||
@@ -307,11 +309,10 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
sb.AppendFormat("Master copy ID: 0x{0:X8}", infoMddf.master_copy_id).AppendLine();
|
||||
|
||||
sb.AppendFormat("Volume is number {0} of {1}", infoMddf.volnum, infoMddf.vol_sequence)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("Volume is number {0} of {1}", infoMddf.volnum, infoMddf.vol_sequence).AppendLine();
|
||||
|
||||
sb.AppendFormat("Serial number of Lisa computer that created this volume: {0}",
|
||||
infoMddf.machine_id).AppendLine();
|
||||
sb.AppendFormat("Serial number of Lisa computer that created this volume: {0}", infoMddf.machine_id)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("Serial number of Lisa computer that can use this volume's software {0}",
|
||||
infoMddf.serialization).AppendLine();
|
||||
|
||||
@@ -341,8 +342,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
infoMddf.srec_ptr + infoMddf.mddf_block + beforeMddf, infoMddf.srec_len)
|
||||
.AppendLine();
|
||||
|
||||
if(infoMddf.vol_left_mounted == 0) sb.AppendLine("Volume is clean");
|
||||
else sb.AppendLine("Volume is dirty");
|
||||
sb.AppendLine(infoMddf.vol_left_mounted == 0 ? "Volume is clean" : "Volume is dirty");
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
|
||||
@@ -43,31 +43,14 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
// Variable names from Lisa API
|
||||
public partial class LisaFS : Filesystem
|
||||
{
|
||||
bool mounted;
|
||||
bool debug;
|
||||
readonly ImagePlugin device;
|
||||
bool debug;
|
||||
int devTagSize;
|
||||
|
||||
MDDF mddf;
|
||||
ulong volumePrefix;
|
||||
int devTagSize;
|
||||
bool mounted;
|
||||
SRecord[] srecords;
|
||||
|
||||
#region Caches
|
||||
/// <summary>Caches Extents Files</summary>
|
||||
Dictionary<short, ExtentFile> extentCache;
|
||||
/// <summary>Caches system files</summary>
|
||||
Dictionary<short, byte[]> systemFileCache;
|
||||
/// <summary>Caches user files files</summary>
|
||||
Dictionary<short, byte[]> fileCache;
|
||||
/// <summary>Caches catalogs</summary>
|
||||
List<CatalogEntry> catalogCache;
|
||||
/// <summary>Caches file size</summary>
|
||||
Dictionary<short, int> fileSizeCache;
|
||||
/// <summary>Lists Extents Files already printed in debug mode to not repeat them</summary>
|
||||
List<short> printedExtents;
|
||||
/// <summary>Caches the creation times for subdirectories as to not have to traverse the Catalog File on each stat</summary>
|
||||
Dictionary<short, DateTime> directoryDtcCache;
|
||||
#endregion Caches
|
||||
ulong volumePrefix;
|
||||
|
||||
public LisaFS()
|
||||
{
|
||||
@@ -90,5 +73,22 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
PluginUuid = new Guid("7E6034D1-D823-4248-A54D-239742B28391");
|
||||
CurrentEncoding = new LisaRoman();
|
||||
}
|
||||
|
||||
#region Caches
|
||||
/// <summary>Caches Extents Files</summary>
|
||||
Dictionary<short, ExtentFile> extentCache;
|
||||
/// <summary>Caches system files</summary>
|
||||
Dictionary<short, byte[]> systemFileCache;
|
||||
/// <summary>Caches user files files</summary>
|
||||
Dictionary<short, byte[]> fileCache;
|
||||
/// <summary>Caches catalogs</summary>
|
||||
List<CatalogEntry> catalogCache;
|
||||
/// <summary>Caches file size</summary>
|
||||
Dictionary<short, int> fileSizeCache;
|
||||
/// <summary>Lists Extents Files already printed in debug mode to not repeat them</summary>
|
||||
List<short> printedExtents;
|
||||
/// <summary>Caches the creation times for subdirectories as to not have to traverse the Catalog File on each stat</summary>
|
||||
Dictionary<short, DateTime> directoryDtcCache;
|
||||
#endregion Caches
|
||||
}
|
||||
}
|
||||
@@ -37,11 +37,11 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
public partial class LisaFS
|
||||
{
|
||||
/// <summary>
|
||||
/// The MDDF is the most import block on a Lisa FS volume.
|
||||
/// It describes the volume and its contents.
|
||||
/// On initialization the memory where it resides is not emptied
|
||||
/// so it tends to contain a lot of garbage. This has difficulted
|
||||
/// its reverse engineering.
|
||||
/// The MDDF is the most import block on a Lisa FS volume.
|
||||
/// It describes the volume and its contents.
|
||||
/// On initialization the memory where it resides is not emptied
|
||||
/// so it tends to contain a lot of garbage. This has difficulted
|
||||
/// its reverse engineering.
|
||||
/// </summary>
|
||||
struct MDDF
|
||||
{
|
||||
@@ -209,10 +209,10 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An entry in the catalog from V3.
|
||||
/// The first entry is bigger than the rest, may be a header, I have not needed any of its values so I just ignored it.
|
||||
/// Each catalog is divided in 4-sector blocks, and if it needs more than a block there are previous and next block
|
||||
/// pointers, effectively making the V3 catalog a double-linked list. Garbage is not zeroed.
|
||||
/// An entry in the catalog from V3.
|
||||
/// The first entry is bigger than the rest, may be a header, I have not needed any of its values so I just ignored it.
|
||||
/// Each catalog is divided in 4-sector blocks, and if it needs more than a block there are previous and next block
|
||||
/// pointers, effectively making the V3 catalog a double-linked list. Garbage is not zeroed.
|
||||
/// </summary>
|
||||
struct CatalogEntry
|
||||
{
|
||||
@@ -225,11 +225,11 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
/// <summary>0x23, null-termination</summary>
|
||||
public byte terminator;
|
||||
/// <summary>
|
||||
/// At 0x24
|
||||
/// 0x01 here for subdirectories, entries 48 bytes long
|
||||
/// 0x03 here for entries 64 bytes long
|
||||
/// 0x08 here for entries 78 bytes long
|
||||
/// This is incomplete, may fail, mostly works...
|
||||
/// At 0x24
|
||||
/// 0x01 here for subdirectories, entries 48 bytes long
|
||||
/// 0x03 here for entries 64 bytes long
|
||||
/// 0x08 here for entries 78 bytes long
|
||||
/// This is incomplete, may fail, mostly works...
|
||||
/// </summary>
|
||||
public byte fileType;
|
||||
/// <summary>0x25, lot of values found here, unknown</summary>
|
||||
@@ -249,7 +249,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An extent indicating a start and a run of sectors.
|
||||
/// An extent indicating a start and a run of sectors.
|
||||
/// </summary>
|
||||
struct Extent
|
||||
{
|
||||
@@ -258,12 +258,12 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Extents File. There is one Extents File per each file stored on disk.
|
||||
/// The file ID present on the sectors tags for the Extents File is the negated
|
||||
/// value of the file ID it represents. e.g. file = 5 (0x0005) extents = -5 (0xFFFB)
|
||||
/// It spans a single sector on V2 and V3 but 2 sectors on V1.
|
||||
/// It contains all information about a file, and is indexed in the S-Records file.
|
||||
/// It also contains the label. Garbage is zeroed.
|
||||
/// The Extents File. There is one Extents File per each file stored on disk.
|
||||
/// The file ID present on the sectors tags for the Extents File is the negated
|
||||
/// value of the file ID it represents. e.g. file = 5 (0x0005) extents = -5 (0xFFFB)
|
||||
/// It spans a single sector on V2 and V3 but 2 sectors on V1.
|
||||
/// It contains all information about a file, and is indexed in the S-Records file.
|
||||
/// It also contains the label. Garbage is zeroed.
|
||||
/// </summary>
|
||||
struct ExtentFile
|
||||
{
|
||||
@@ -335,29 +335,38 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
public int length;
|
||||
/// <summary>0x84, 0x204 in v1, unknown</summary>
|
||||
public int unknown9;
|
||||
/// <summary>0x88, 0x208 in v1, extents, can contain up to 41 extents (85 in v1), dunno LisaOS maximum (never seen more than 3)</summary>
|
||||
/// <summary>
|
||||
/// 0x88, 0x208 in v1, extents, can contain up to 41 extents (85 in v1), dunno LisaOS maximum (never seen more
|
||||
/// than 3)
|
||||
/// </summary>
|
||||
public Extent[] extents;
|
||||
/// <summary>0x17E, unknown, empty, padding?</summary>
|
||||
public short unknown10;
|
||||
/// <summary>
|
||||
/// At 0x180, this is the label.
|
||||
/// While 1982 pre-release documentation says the label can be up to 448 bytes, v1 onward only have space for a 128 bytes one.
|
||||
/// Any application can write whatever they want in the label, however, Lisa Office uses it to store its own information, something
|
||||
/// that will effectively overwrite any information a user application wrote there.
|
||||
/// The information written here by Lisa Office is like the information Finder writes in the FinderInfo structures, plus
|
||||
/// the non-unique name that is shown on the GUI. For this reason I called it LisaInfo.
|
||||
/// I have not tried to reverse engineer it.
|
||||
/// At 0x180, this is the label.
|
||||
/// While 1982 pre-release documentation says the label can be up to 448 bytes, v1 onward only have space for a 128
|
||||
/// bytes one.
|
||||
/// Any application can write whatever they want in the label, however, Lisa Office uses it to store its own
|
||||
/// information, something
|
||||
/// that will effectively overwrite any information a user application wrote there.
|
||||
/// The information written here by Lisa Office is like the information Finder writes in the FinderInfo structures,
|
||||
/// plus
|
||||
/// the non-unique name that is shown on the GUI. For this reason I called it LisaInfo.
|
||||
/// I have not tried to reverse engineer it.
|
||||
/// </summary>
|
||||
public byte[] LisaInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The S-Records File is a hashtable of S-Records, where the hash is the file ID they belong to.
|
||||
/// The S-Records File cannot be fragmented or grown, and it can easily become full before the 32766 file IDs are exhausted.
|
||||
/// Each S-Record entry contains a block pointer to the Extents File that correspond to that file ID as well as the real file size,
|
||||
/// the only important information about a file that's not inside the Extents File.
|
||||
/// It also contains a low value (less than 0x200) variable field of unknown meaning and another one that seems to be flags,
|
||||
/// with values like 0, 1, 3 and 5.
|
||||
/// The S-Records File is a hashtable of S-Records, where the hash is the file ID they belong to.
|
||||
/// The S-Records File cannot be fragmented or grown, and it can easily become full before the 32766 file IDs are
|
||||
/// exhausted.
|
||||
/// Each S-Record entry contains a block pointer to the Extents File that correspond to that file ID as well as the
|
||||
/// real file size,
|
||||
/// the only important information about a file that's not inside the Extents File.
|
||||
/// It also contains a low value (less than 0x200) variable field of unknown meaning and another one that seems to be
|
||||
/// flags,
|
||||
/// with values like 0, 1, 3 and 5.
|
||||
/// </summary>
|
||||
struct SRecord
|
||||
{
|
||||
@@ -372,13 +381,13 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The catalog entry for the V1 and V2 volume formats.
|
||||
/// It merely contains the file name, type and ID, plus a few (mostly empty) unknown fields.
|
||||
/// Contrary to V3, it has no header and instead of being a double-linked list it is fragmented using an Extents File.
|
||||
/// The Extents File position for the root catalog is then stored in the S-Records File.
|
||||
/// Its entries are not filed sequentially denoting some kind of in-memory structure while at the same time
|
||||
/// forcing LisaOS to read the whole catalog. That or I missed the pointers.
|
||||
/// Empty entries just contain a 0-len filename. Garbage is not zeroed.
|
||||
/// The catalog entry for the V1 and V2 volume formats.
|
||||
/// It merely contains the file name, type and ID, plus a few (mostly empty) unknown fields.
|
||||
/// Contrary to V3, it has no header and instead of being a double-linked list it is fragmented using an Extents File.
|
||||
/// The Extents File position for the root catalog is then stored in the S-Records File.
|
||||
/// Its entries are not filed sequentially denoting some kind of in-memory structure while at the same time
|
||||
/// forcing LisaOS to read the whole catalog. That or I missed the pointers.
|
||||
/// Empty entries just contain a 0-len filename. Garbage is not zeroed.
|
||||
/// </summary>
|
||||
struct CatalogEntryV2
|
||||
{
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
public partial class LisaFS
|
||||
{
|
||||
/// <summary>
|
||||
/// Mounts an Apple Lisa filesystem
|
||||
/// Mounts an Apple Lisa filesystem
|
||||
/// </summary>
|
||||
public override Errno Mount()
|
||||
{
|
||||
@@ -50,7 +50,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mounts an Apple Lisa filesystem
|
||||
/// Mounts an Apple Lisa filesystem
|
||||
/// </summary>
|
||||
public override Errno Mount(bool debug)
|
||||
{
|
||||
@@ -319,7 +319,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Umounts this Lisa filesystem
|
||||
/// Umounts this Lisa filesystem
|
||||
/// </summary>
|
||||
public override Errno Unmount()
|
||||
{
|
||||
@@ -339,7 +339,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets information about the mounted volume.
|
||||
/// Gets information about the mounted volume.
|
||||
/// </summary>
|
||||
/// <param name="stat">Information about the mounted volume.</param>
|
||||
public override Errno StatFs(ref FileSystemInfo stat)
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
public partial class LisaFS
|
||||
{
|
||||
/// <summary>
|
||||
/// Lists all extended attributes, alternate data streams and forks of the given file.
|
||||
/// Lists all extended attributes, alternate data streams and forks of the given file.
|
||||
/// </summary>
|
||||
/// <returns>Error number.</returns>
|
||||
/// <param name="path">Path.</param>
|
||||
@@ -55,7 +55,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an extended attribute, alternate data stream or fork from the given file.
|
||||
/// Reads an extended attribute, alternate data stream or fork from the given file.
|
||||
/// </summary>
|
||||
/// <returns>Error number.</returns>
|
||||
/// <param name="path">File path.</param>
|
||||
@@ -70,7 +70,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lists special Apple Lisa filesystem features as extended attributes
|
||||
/// Lists special Apple Lisa filesystem features as extended attributes
|
||||
/// </summary>
|
||||
/// <returns>Error number.</returns>
|
||||
/// <param name="fileId">File identifier.</param>
|
||||
@@ -125,7 +125,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lists special Apple Lisa filesystem features as extended attributes
|
||||
/// Lists special Apple Lisa filesystem features as extended attributes
|
||||
/// </summary>
|
||||
/// <returns>Error number.</returns>
|
||||
/// <param name="fileId">File identifier.</param>
|
||||
@@ -161,7 +161,8 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
if(error != Errno.NoError) return error;
|
||||
|
||||
switch(xattr) {
|
||||
switch(xattr)
|
||||
{
|
||||
case "com.apple.lisa.password" when file.password_valid > 0:
|
||||
buf = new byte[8];
|
||||
Array.Copy(file.password, 0, buf, 0, 8);
|
||||
@@ -184,7 +185,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes a sector tag. Not tested with 24-byte tags.
|
||||
/// Decodes a sector tag. Not tested with 24-byte tags.
|
||||
/// </summary>
|
||||
/// <returns>Error number.</returns>
|
||||
/// <param name="tag">Sector tag.</param>
|
||||
|
||||
Reference in New Issue
Block a user