From c55612ffe8c2309e879ba5b32dfa12ce0791078e Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Fri, 29 Jul 2016 02:22:24 +0100 Subject: [PATCH] Added comments. --- DiscImageChef.Filesystems/ChangeLog | 13 +++ DiscImageChef.Filesystems/Filesystem.cs | 2 +- DiscImageChef.Filesystems/LisaFS/Consts.cs | 89 +++++++++++++++++++- DiscImageChef.Filesystems/LisaFS/Dir.cs | 42 ++++++++- DiscImageChef.Filesystems/LisaFS/Encoding.cs | 15 ++++ DiscImageChef.Filesystems/LisaFS/Extent.cs | 11 ++- DiscImageChef.Filesystems/LisaFS/File.cs | 8 +- DiscImageChef.Filesystems/LisaFS/LisaFS.cs | 6 ++ DiscImageChef.Filesystems/LisaFS/Structs.cs | 62 +++++++++++++- DiscImageChef.Filesystems/LisaFS/Super.cs | 25 +++++- DiscImageChef.Filesystems/LisaFS/Xattr.cs | 52 ++++++++++-- 11 files changed, 306 insertions(+), 19 deletions(-) diff --git a/DiscImageChef.Filesystems/ChangeLog b/DiscImageChef.Filesystems/ChangeLog index ba6271e82..e6d4c9193 100644 --- a/DiscImageChef.Filesystems/ChangeLog +++ b/DiscImageChef.Filesystems/ChangeLog @@ -1,3 +1,16 @@ +2016-07-29 Natalia Portillo + + * Filesystem.cs: + * Dir.cs: + * File.cs: + * Super.cs: + * Xattr.cs: + * LisaFS.cs: + * Consts.cs: + * Extent.cs: + * Structs.cs: + * Encoding.cs: Added comments. + 2016-07-28 Natalia Portillo * Dir.cs: diff --git a/DiscImageChef.Filesystems/Filesystem.cs b/DiscImageChef.Filesystems/Filesystem.cs index a1575ed47..f9d1861ae 100644 --- a/DiscImageChef.Filesystems/Filesystem.cs +++ b/DiscImageChef.Filesystems/Filesystem.cs @@ -133,7 +133,7 @@ namespace DiscImageChef.Filesystems /// /// Reads an extended attribute, alternate data stream or fork from the given file. /// - /// The extended attribute, alternate data stream or fork name. + /// Error number. /// File path. /// Extendad attribute, alternate data stream or fork name. /// Buffer. diff --git a/DiscImageChef.Filesystems/LisaFS/Consts.cs b/DiscImageChef.Filesystems/LisaFS/Consts.cs index 2d0ab3c23..9a7cae88a 100644 --- a/DiscImageChef.Filesystems/LisaFS/Consts.cs +++ b/DiscImageChef.Filesystems/LisaFS/Consts.cs @@ -34,41 +34,126 @@ namespace DiscImageChef.Filesystems.LisaFS { partial class LisaFS : Filesystem { + /// + /// Lisa FS v1, from Lisa OS 1.0 (Workshop or Office) + /// Never seen on Sony floppies. + /// const byte LisaFSv1 = 0x0E; + /// + /// 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 + /// const byte LisaFSv2 = 0x0F; + /// + /// 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) + /// const byte LisaFSv3 = 0x11; /// Maximum string size in LisaFS const uint E_NAME = 32; + /// + /// Unused file ID + /// const ushort FILEID_FREE = 0x0000; + /// + /// Used by the boot blocks + /// const ushort FILEID_BOOT = 0xAAAA; + /// + /// Used by the operating system loader blocks + /// const ushort FILEID_LOADER = 0xBBBB; + /// + /// Used by the MDDF + /// const ushort FILEID_MDDF = 0x0001; + /// + /// Used by the volume bitmap, sits between MDDF and S-Records file. + /// const ushort FILEID_BITMAP = 0x0002; + /// + /// S-Records file + /// const ushort FILEID_SRECORD = 0x0003; - /// "Catalog file" - const ushort FILEID_DIRECTORY = 0x0004; + /// The root catalog + const ushort FILEID_ROOTCATALOG = 0x0004; const short FILEID_BOOT_SIGNED = -21846; const short FILEID_LOADER_SIGNED = -17477; + /// + /// A file that has been erased + /// const ushort FILEID_ERASED = 0x7FFF; const ushort FILEID_MAX = FILEID_ERASED; enum FileType : byte { + /// + /// Undefined file type + /// Undefined = 0, + /// + /// MDDF + /// MDDFile = 1, + /// + /// Root catalog + /// RootCat = 2, + /// + /// Bitmap + /// FreeList = 3, + /// + /// Unknown, maybe refers to the S-Records File? + /// BadBlocks = 4, + /// + /// System data + /// SysData = 5, + /// + /// Printer spool + /// Spool = 6, + /// + /// Executable. Yet application files don't use it + /// Exec = 7, + /// + /// User catalog + /// UserCat = 8, + /// + /// Pipe. Not seen on disk. + /// Pipe = 9, + /// + /// Boot file? + /// BootFile = 10, + /// + /// Swap for data + /// SwapData = 11, + /// + /// Swap for code + /// SwapCode = 12, + /// + /// Unknown + /// RamAP = 13, + /// + /// Any file + /// UserFile = 14, + /// + /// Erased? + /// KilledObject = 15 } } diff --git a/DiscImageChef.Filesystems/LisaFS/Dir.cs b/DiscImageChef.Filesystems/LisaFS/Dir.cs index 62145c15f..ba5702130 100644 --- a/DiscImageChef.Filesystems/LisaFS/Dir.cs +++ b/DiscImageChef.Filesystems/LisaFS/Dir.cs @@ -38,12 +38,22 @@ namespace DiscImageChef.Filesystems.LisaFS { partial class LisaFS : Filesystem { + /// + /// Solves a symbolic link. + /// + /// Link path. + /// Link destination. public override Errno ReadLink(string path, ref string dest) { // LisaFS does not support symbolic links (afaik) return Errno.NotSupported; } + /// + /// Lists contents from a directory. + /// + /// Directory path. + /// Directory contents. public override Errno ReadDir(string path, ref List contents) { short fileId; @@ -58,10 +68,14 @@ namespace DiscImageChef.Filesystems.LisaFS List catalog; ReadCatalog(fileId, out catalog); + // Do same trick as Mac OS X, replace filesystem '/' with ':' + // Maybe as ':' is the path separator in Lisa OS I should do that foreach(CatalogEntry entry in catalog) contents.Add(GetString(entry.filename).Replace('/', ':')); - if(debug && fileId == FILEID_DIRECTORY) + // On debug add system files as readable files + // Syntax similar to NTFS + if(debug && fileId == FILEID_ROOTCATALOG) { contents.Add("$MDDF"); contents.Add("$Boot"); @@ -75,6 +89,11 @@ namespace DiscImageChef.Filesystems.LisaFS return Errno.NoError; } + /// + /// Lists contents from a catalog. + /// + /// Catalog id. + /// Catalog contents. Errno ReadCatalog(short fileId, out List catalog) { catalog = null; @@ -90,11 +109,14 @@ namespace DiscImageChef.Filesystems.LisaFS Errno error; + // Do differently for V1 and V2 if(mddf.fsversion == LisaFSv2 || mddf.fsversion == LisaFSv1) { - if(fileId != FILEID_DIRECTORY) + // V1 and V2 can only contain the root catalog + if(fileId != FILEID_ROOTCATALOG) { ExtentFile ext; + // Check if it's a file to return correct error error = ReadExtentsFile(fileId, out ext); if(error == Errno.NoError) return Errno.NotDirectory; @@ -106,6 +128,7 @@ namespace DiscImageChef.Filesystems.LisaFS int offset = 0; List catalogV2 = new List(); + // For each entry on the catalog while(offset + 54 < buf.Length) { CatalogEntryV2 entV2 = new CatalogEntryV2(); @@ -121,12 +144,14 @@ namespace DiscImageChef.Filesystems.LisaFS offset += 54; + // Check that the entry is correct, not empty or garbage if(entV2.filenameLen != 0 && entV2.filenameLen <= E_NAME && entV2.fileType != 0 && entV2.fileID > 0) catalogV2.Add(entV2); } catalog = new List(); + // Convert entries to V3 format foreach(CatalogEntryV2 entV2 in catalogV2) { ExtentFile ext; @@ -152,6 +177,9 @@ namespace DiscImageChef.Filesystems.LisaFS byte[] firstCatalogBlock = null; + // Search for the first sector describing the catalog + // While root catalog is not stored in S-Records, probably rest are? (unchecked) + // If root catalog is not pointed in MDDF (unchecked) maybe it's always following S-Records File? for(ulong i = 0; i < device.GetSectors(); i++) { Tag catTag; @@ -163,16 +191,19 @@ namespace DiscImageChef.Filesystems.LisaFS break; } + // Found Extents File for a catalog, not allowable in V3, at least for root catalog if(catTag.fileID == -fileId) return Errno.NotDirectory; } + // Catalog not found if(firstCatalogBlock == null) return Errno.NoSuchFile; ulong prevCatalogPointer; prevCatalogPointer = BigEndianBitConverter.ToUInt32(firstCatalogBlock, 0x7F6); + // Traverse double-linked list until first catalog block while(prevCatalogPointer != 0xFFFFFFFF) { Tag prevTag; @@ -191,6 +222,7 @@ namespace DiscImageChef.Filesystems.LisaFS List catalogBlocks = new List(); catalogBlocks.Add(firstCatalogBlock); + // Traverse double-linked list to read full catalog while(nextCatalogPointer != 0xFFFFFFFF) { Tag nextTag; @@ -206,18 +238,24 @@ namespace DiscImageChef.Filesystems.LisaFS catalog = new List(); + // Foreach catalog block foreach(byte[] buf in catalogBlocks) { int offset = 0; + // Traverse all entries while((offset + 64) <= buf.Length) { + // 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; + // Apparently reserved to indicate end of catalog? else if(buf[offset + 0x24] == 0xFF) break; + // Normal entry else if(buf[offset + 0x24] == 0x03 && buf[offset] == 0x24) { CatalogEntry entry = new CatalogEntry(); diff --git a/DiscImageChef.Filesystems/LisaFS/Encoding.cs b/DiscImageChef.Filesystems/LisaFS/Encoding.cs index 2bba46b7b..eeccfaa65 100644 --- a/DiscImageChef.Filesystems/LisaFS/Encoding.cs +++ b/DiscImageChef.Filesystems/LisaFS/Encoding.cs @@ -105,11 +105,21 @@ namespace DiscImageChef.Filesystems.LisaFS '\u0000','\u0000','\u0000','\u0000','\u0000','\u0000','\u0000','\u0000' }; + /// + /// Converts a LisaRoman character to an Unicode character + /// + /// Unicode character. + /// LisaRoman character. static char GetChar(byte character) { return LisaRomanTable[character]; } + /// + /// Converts a LisaRoman string, null-terminated or null-paded, to a C# string + /// + /// The C# string. + /// LisaRoman string. static string GetString(byte[] str) { string uni = ""; @@ -125,6 +135,11 @@ namespace DiscImageChef.Filesystems.LisaFS return uni; } + /// + /// Converts a LisaRoman string, in Pascal length-prefixed format, to a C# string + /// + /// The C# string. + /// The LisaRoman string in Pascal format. static string GetStringFromPascal(byte[] PascalString) { if(PascalString == null) diff --git a/DiscImageChef.Filesystems/LisaFS/Extent.cs b/DiscImageChef.Filesystems/LisaFS/Extent.cs index fc80c0835..1b4250e88 100644 --- a/DiscImageChef.Filesystems/LisaFS/Extent.cs +++ b/DiscImageChef.Filesystems/LisaFS/Extent.cs @@ -63,21 +63,24 @@ namespace DiscImageChef.Filesystems.LisaFS if(extentCache.TryGetValue(fileId, out file)) return Errno.NoError; + // A file ID that cannot be stored in the S-Records File if(fileId >= srecords.Length) return Errno.InvalidArgument; ulong ptr = srecords[fileId].extent_ptr; + // An invalid pointer denotes file does not exist if(ptr == 0xFFFFFFFF || ptr == 0x00000000) return Errno.NoSuchFile; + // Pointers are relative to MDDF ptr += mddf.mddf_block + volumePrefix; Tag extTag; // This happens on some disks. // This is a filesystem corruption that makes LisaOS crash on scavenge. - // This code just allow to ignore that corruption + // This code just allow to ignore that corruption by searching the Extents File using sector tags if(ptr >= device.ImageInfo.sectors) { bool found = false; @@ -96,6 +99,7 @@ namespace DiscImageChef.Filesystems.LisaFS return Errno.InvalidArgument; } + // Checks that the sector tag indicates its the Extents File we are searching for DecodeTag(device.ReadSectorTag(ptr, SectorTagType.AppleSectorTag), out extTag); if(extTag.fileID == ((short)(-1 * fileId))) @@ -249,13 +253,18 @@ namespace DiscImageChef.Filesystems.LisaFS return Errno.NoSuchFile; } + /// + /// Reads all the S-Records and caches it + /// Errno ReadSRecords() { if(!mounted) return Errno.AccessDenied; + // Searches the S-Records place using MDDF pointers byte[] sectors = device.ReadSectors(mddf.srec_ptr + mddf.mddf_block + volumePrefix, mddf.srec_len); + // Each entry takes 14 bytes srecords = new SRecord[sectors.Length / 14]; for(int s = 0; s < srecords.Length; s++) diff --git a/DiscImageChef.Filesystems/LisaFS/File.cs b/DiscImageChef.Filesystems/LisaFS/File.cs index 1306de783..6b1f37af0 100644 --- a/DiscImageChef.Filesystems/LisaFS/File.cs +++ b/DiscImageChef.Filesystems/LisaFS/File.cs @@ -76,7 +76,7 @@ namespace DiscImageChef.Filesystems.LisaFS case (short)FILEID_MDDF: case (short)FILEID_BITMAP: case (short)FILEID_SRECORD: - case (short)FILEID_DIRECTORY: + case (short)FILEID_ROOTCATALOG: error = ReadSystemFile(fileId, out tmp); break; default: @@ -453,7 +453,7 @@ namespace DiscImageChef.Filesystems.LisaFS if(pathElements.Length == 0) { - fileId = (short)FILEID_DIRECTORY; + fileId = (short)FILEID_ROOTCATALOG; isDir = true; return Errno.NoError; } @@ -496,7 +496,7 @@ namespace DiscImageChef.Filesystems.LisaFS if(string.Compare(pathElements[0], "$", StringComparison.InvariantCulture) == 0) { - fileId = (short)FILEID_DIRECTORY; + fileId = (short)FILEID_ROOTCATALOG; isDir = true; return Errno.NoError; } @@ -504,7 +504,7 @@ namespace DiscImageChef.Filesystems.LisaFS List catalog; - Errno error = ReadCatalog((short)FILEID_DIRECTORY, out catalog); + Errno error = ReadCatalog((short)FILEID_ROOTCATALOG, out catalog); if(error != Errno.NoError) return error; diff --git a/DiscImageChef.Filesystems/LisaFS/LisaFS.cs b/DiscImageChef.Filesystems/LisaFS/LisaFS.cs index a07cf3b00..838f2600f 100644 --- a/DiscImageChef.Filesystems/LisaFS/LisaFS.cs +++ b/DiscImageChef.Filesystems/LisaFS/LisaFS.cs @@ -51,11 +51,17 @@ namespace DiscImageChef.Filesystems.LisaFS SRecord[] srecords; #region Caches + /// Caches Extents Files Dictionary extentCache; + /// Caches system files Dictionary systemFileCache; + /// Caches user files files Dictionary fileCache; + /// Caches catalogs Dictionary> catalogCache; + /// Caches file size Dictionary fileSizeCache; + /// Lists Extents Files already printed in debug mode to not repeat them List printedExtents; #endregion Caches diff --git a/DiscImageChef.Filesystems/LisaFS/Structs.cs b/DiscImageChef.Filesystems/LisaFS/Structs.cs index 523d062b7..e70071cee 100644 --- a/DiscImageChef.Filesystems/LisaFS/Structs.cs +++ b/DiscImageChef.Filesystems/LisaFS/Structs.cs @@ -35,6 +35,13 @@ namespace DiscImageChef.Filesystems.LisaFS { partial class LisaFS : Filesystem { + /// + /// 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. + /// struct MDDF { /// 0x00, Filesystem version @@ -200,6 +207,13 @@ namespace DiscImageChef.Filesystems.LisaFS public byte scavenge_flag; } + /// + /// The sector tag. Before the sector is encoded to GCR the tag is attached to the data. + /// Its size and format varies depending on device. + /// Lisa OS relies on tags for scavenging a floppy, but ignores most of them for normal usage, + /// except on hard disks where the checksum byte is absolutely enforced (a sector with an invalid + /// one gives an OS error). + /// struct Tag { /// 0x00 version @@ -235,11 +249,17 @@ namespace DiscImageChef.Filesystems.LisaFS public bool isLast; } + /// + /// 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. + /// struct CatalogEntry { /// 0x00, seems to be 0x24 when the entry is valid public byte marker; - /// 0x01, seems to be always zero + /// 0x01, must be zero otherwise LisaOS gives an error public ushort zero; /// 0x03, filename, 32-bytes, null-padded public byte[] filename; @@ -249,7 +269,6 @@ namespace DiscImageChef.Filesystems.LisaFS /// At 0x24 /// 0x03 here for entries 64 bytes long /// 0x08 here for entries 78 bytes long - /// 0x7C here for entries 50 bytes long /// This is incomplete, may fail, mostly works... /// public byte fileType; @@ -269,12 +288,23 @@ namespace DiscImageChef.Filesystems.LisaFS public byte[] tail; } + /// + /// An extent indicating a start and a run of sectors. + /// struct Extent { public int start; public short length; } + /// + /// 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. + /// struct ExtentFile { /// 0x00, filename length @@ -349,10 +379,26 @@ namespace DiscImageChef.Filesystems.LisaFS public Extent[] extents; /// 0x17E, unknown, empty, padding? public short unknown10; - /// 0x180, 128 bytes + /// + /// 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. + /// public byte[] LisaInfo; } + /// + /// 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. + /// struct SRecord { /// 0x00, block where ExtentsFile for this entry resides @@ -365,6 +411,16 @@ namespace DiscImageChef.Filesystems.LisaFS public ushort flags; } + + /// + /// 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. + /// struct CatalogEntryV2 { /// 0x00, filename, 32-bytes, null-padded diff --git a/DiscImageChef.Filesystems/LisaFS/Super.cs b/DiscImageChef.Filesystems/LisaFS/Super.cs index 8b74d20cf..3daa67546 100644 --- a/DiscImageChef.Filesystems/LisaFS/Super.cs +++ b/DiscImageChef.Filesystems/LisaFS/Super.cs @@ -39,15 +39,24 @@ namespace DiscImageChef.Filesystems.LisaFS { partial class LisaFS : Filesystem { + /// + /// Mounts an Apple Lisa filesystem + /// public override Errno Mount() { return Mount(false); } + /// + /// Mounts an Apple Lisa filesystem + /// public override Errno Mount(bool debug) { try { + // Lisa OS is unable to work on disks without tags. + // This code is designed like that. + // However with some effort the code may be modified to ignore them. if(device.ImageInfo.readableSectorTags == null || !device.ImageInfo.readableSectorTags.Contains(SectorTagType.AppleSectorTag)) { @@ -170,6 +179,7 @@ namespace DiscImageChef.Filesystems.LisaFS mddf.vol_sequence = BigEndianBitConverter.ToUInt16(sector, 0x136); mddf.vol_left_mounted = sector[0x138]; + // Check that the MDDF is correct if(mddf.mddf_block != i - volumePrefix || mddf.vol_size > device.GetSectors() || mddf.vol_size - 1 != mddf.volsize_minus_one || @@ -182,6 +192,7 @@ namespace DiscImageChef.Filesystems.LisaFS return Errno.InvalidArgument; } + // Check MDDF version switch(mddf.fsversion) { case LisaFSv1: @@ -198,6 +209,7 @@ namespace DiscImageChef.Filesystems.LisaFS return Errno.NotSupported; } + // Initialize caches extentCache = new Dictionary(); systemFileCache = new Dictionary(); fileCache = new Dictionary(); @@ -214,6 +226,7 @@ namespace DiscImageChef.Filesystems.LisaFS printedExtents = new List(); } + // Read the S-Records file error = ReadSRecords(); if(error != Errno.NoError) { @@ -221,8 +234,9 @@ namespace DiscImageChef.Filesystems.LisaFS return error; } + // Read the root catalog List tempCat; - error = ReadCatalog((short)FILEID_DIRECTORY, out tempCat); + error = ReadCatalog((short)FILEID_ROOTCATALOG, out tempCat); if(error != Errno.NoError) { @@ -231,6 +245,7 @@ namespace DiscImageChef.Filesystems.LisaFS return error; } + // If debug, cache system files if(debug) { byte[] temp; @@ -276,6 +291,7 @@ namespace DiscImageChef.Filesystems.LisaFS } } + // Create XML metadata for mounted filesystem xmlFSType = new Schemas.FileSystemType(); if(DateTime.Compare(mddf.dtvb, DateHandlers.LisaToDateTime(0)) > 0) { @@ -312,6 +328,9 @@ namespace DiscImageChef.Filesystems.LisaFS } } + /// + /// Umounts this Lisa filesystem + /// public override Errno Unmount() { mounted = false; @@ -329,6 +348,10 @@ namespace DiscImageChef.Filesystems.LisaFS return Errno.NoError; } + /// + /// Gets information about the mounted volume. + /// + /// Information about the mounted volume. public override Errno StatFs(ref FileSystemInfo stat) { if(!mounted) diff --git a/DiscImageChef.Filesystems/LisaFS/Xattr.cs b/DiscImageChef.Filesystems/LisaFS/Xattr.cs index 756a579bb..b4b00ae88 100644 --- a/DiscImageChef.Filesystems/LisaFS/Xattr.cs +++ b/DiscImageChef.Filesystems/LisaFS/Xattr.cs @@ -39,6 +39,12 @@ namespace DiscImageChef.Filesystems.LisaFS { partial class LisaFS : Filesystem { + /// + /// Lists all extended attributes, alternate data streams and forks of the given file. + /// + /// Error number. + /// Path. + /// List of extended attributes, alternate data streams and forks. public override Errno ListXAttr(string path, ref List xattrs) { short fileId; @@ -49,6 +55,13 @@ namespace DiscImageChef.Filesystems.LisaFS return ListXAttr(fileId, ref xattrs); } + /// + /// Reads an extended attribute, alternate data stream or fork from the given file. + /// + /// Error number. + /// File path. + /// Extendad attribute, alternate data stream or fork name. + /// Buffer. public override Errno GetXattr(string path, string xattr, ref byte[] buf) { short fileId; @@ -59,6 +72,12 @@ namespace DiscImageChef.Filesystems.LisaFS return GetXattr(fileId, xattr, out buf); } + /// + /// Lists special Apple Lisa filesystem features as extended attributes + /// + /// Error number. + /// File identifier. + /// Extended attributes. Errno ListXAttr(short fileId, ref List xattrs) { xattrs = null; @@ -66,6 +85,7 @@ namespace DiscImageChef.Filesystems.LisaFS if(!mounted) return Errno.AccessDenied; + // System files if(fileId < 4) { if(!debug || fileId == 0) @@ -73,34 +93,41 @@ namespace DiscImageChef.Filesystems.LisaFS xattrs = new List(); + // Only MDDF contains an extended attributes if(fileId == FILEID_MDDF) { byte[] buf = Encoding.ASCII.GetBytes(mddf.password); + + // If the MDDF contains a password, show it if(buf.Length > 0) xattrs.Add("com.apple.lisa.password"); } } else { - + // Search for the file ExtentFile file; - Errno error = ReadExtentsFile(fileId, out file); if(error != Errno.NoError) return error; xattrs = new List(); + + // Password field is never emptied, check if valid if(file.password_valid > 0) xattrs.Add("com.apple.lisa.password"); + // Check for a valid copy-protection serial number if(file.serial > 0) xattrs.Add("com.apple.lisa.serial"); + // Check if the label contains something or is empty if(!ArrayHelpers.ArrayIsNullOrEmpty(file.LisaInfo)) xattrs.Add("com.apple.lisa.label"); } + // On debug mode allow sector tags to be accessed as an xattr if(debug) xattrs.Add("com.apple.lisa.tags"); @@ -109,6 +136,13 @@ namespace DiscImageChef.Filesystems.LisaFS return Errno.NoError; } + /// + /// Lists special Apple Lisa filesystem features as extended attributes + /// + /// Error number. + /// File identifier. + /// Extended attribute name. + /// Buffer where the extended attribute will be stored. Errno GetXattr(short fileId, string xattr, out byte[] buf) { buf = null; @@ -116,11 +150,13 @@ namespace DiscImageChef.Filesystems.LisaFS if(!mounted) return Errno.AccessDenied; + // System files if(fileId < 4) { if(!debug || fileId == 0) return Errno.InvalidArgument; + // Only MDDF contains an extended attributes if(fileId == FILEID_MDDF) { if(xattr == "com.apple.lisa.password") @@ -130,14 +166,15 @@ namespace DiscImageChef.Filesystems.LisaFS } } + // But on debug mode even system files contain tags if(debug && xattr == "com.apple.lisa.tags") return ReadSystemFile(fileId, out buf, true); return Errno.NoSuchExtendedAttribute; } + // Search for the file ExtentFile file; - Errno error = ReadExtentsFile(fileId, out file); if(error != Errno.NoError) @@ -169,6 +206,12 @@ namespace DiscImageChef.Filesystems.LisaFS return Errno.NoSuchExtendedAttribute; } + /// + /// Decodes a sector tag. Not tested with 24-byte tags. + /// + /// Error number. + /// Sector tag. + /// Decoded sector tag. Errno DecodeTag(byte[] tag, out Tag decoded) { decoded = new Tag(); @@ -213,5 +256,4 @@ namespace DiscImageChef.Filesystems.LisaFS return Errno.NoError; } } -} - +} \ No newline at end of file