Added comments.

This commit is contained in:
2016-07-29 02:22:24 +01:00
parent 6129e52d41
commit c55612ffe8
11 changed files with 306 additions and 19 deletions

View File

@@ -1,3 +1,16 @@
2016-07-29 Natalia Portillo <claunia@claunia.com>
* 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 <claunia@claunia.com>
* Dir.cs:

View File

@@ -133,7 +133,7 @@ namespace DiscImageChef.Filesystems
/// <summary>
/// Reads an extended attribute, alternate data stream or fork from the given file.
/// </summary>
/// <returns>The extended attribute, alternate data stream or fork name.</returns>
/// <returns>Error number.</returns>
/// <param name="path">File path.</param>
/// <param name="xattr">Extendad attribute, alternate data stream or fork name.</param>
/// <param name="buf">Buffer.</param>

View File

@@ -34,41 +34,126 @@ namespace DiscImageChef.Filesystems.LisaFS
{
partial class LisaFS : Filesystem
{
/// <summary>
/// Lisa FS v1, from Lisa OS 1.0 (Workshop or Office)
/// Never seen on Sony floppies.
/// </summary>
const byte LisaFSv1 = 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
/// </summary>
const byte LisaFSv2 = 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)
/// </summary>
const byte LisaFSv3 = 0x11;
/// <summary>Maximum string size in LisaFS</summary>
const uint E_NAME = 32;
/// <summary>
/// Unused file ID
/// </summary>
const ushort FILEID_FREE = 0x0000;
/// <summary>
/// Used by the boot blocks
/// </summary>
const ushort FILEID_BOOT = 0xAAAA;
/// <summary>
/// Used by the operating system loader blocks
/// </summary>
const ushort FILEID_LOADER = 0xBBBB;
/// <summary>
/// Used by the MDDF
/// </summary>
const ushort FILEID_MDDF = 0x0001;
/// <summary>
/// Used by the volume bitmap, sits between MDDF and S-Records file.
/// </summary>
const ushort FILEID_BITMAP = 0x0002;
/// <summary>
/// S-Records file
/// </summary>
const ushort FILEID_SRECORD = 0x0003;
/// <summary>"Catalog file"</summary>
const ushort FILEID_DIRECTORY = 0x0004;
/// <summary>The root catalog</summary>
const ushort FILEID_ROOTCATALOG = 0x0004;
const short FILEID_BOOT_SIGNED = -21846;
const short FILEID_LOADER_SIGNED = -17477;
/// <summary>
/// A file that has been erased
/// </summary>
const ushort FILEID_ERASED = 0x7FFF;
const ushort FILEID_MAX = FILEID_ERASED;
enum FileType : byte
{
/// <summary>
/// Undefined file type
/// </summary>
Undefined = 0,
/// <summary>
/// MDDF
/// </summary>
MDDFile = 1,
/// <summary>
/// Root catalog
/// </summary>
RootCat = 2,
/// <summary>
/// Bitmap
/// </summary>
FreeList = 3,
/// <summary>
/// Unknown, maybe refers to the S-Records File?
/// </summary>
BadBlocks = 4,
/// <summary>
/// System data
/// </summary>
SysData = 5,
/// <summary>
/// Printer spool
/// </summary>
Spool = 6,
/// <summary>
/// Executable. Yet application files don't use it
/// </summary>
Exec = 7,
/// <summary>
/// User catalog
/// </summary>
UserCat = 8,
/// <summary>
/// Pipe. Not seen on disk.
/// </summary>
Pipe = 9,
/// <summary>
/// Boot file?
/// </summary>
BootFile = 10,
/// <summary>
/// Swap for data
/// </summary>
SwapData = 11,
/// <summary>
/// Swap for code
/// </summary>
SwapCode = 12,
/// <summary>
/// Unknown
/// </summary>
RamAP = 13,
/// <summary>
/// Any file
/// </summary>
UserFile = 14,
/// <summary>
/// Erased?
/// </summary>
KilledObject = 15
}
}

View File

@@ -38,12 +38,22 @@ namespace DiscImageChef.Filesystems.LisaFS
{
partial class LisaFS : Filesystem
{
/// <summary>
/// Solves a symbolic link.
/// </summary>
/// <param name="path">Link path.</param>
/// <param name="dest">Link destination.</param>
public override Errno ReadLink(string path, ref string dest)
{
// LisaFS does not support symbolic links (afaik)
return Errno.NotSupported;
}
/// <summary>
/// Lists contents from a directory.
/// </summary>
/// <param name="path">Directory path.</param>
/// <param name="contents">Directory contents.</param>
public override Errno ReadDir(string path, ref List<string> contents)
{
short fileId;
@@ -58,10 +68,14 @@ namespace DiscImageChef.Filesystems.LisaFS
List<CatalogEntry> 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;
}
/// <summary>
/// Lists contents from a catalog.
/// </summary>
/// <param name="fileId">Catalog id.</param>
/// <param name="catalog">Catalog contents.</param>
Errno ReadCatalog(short fileId, out List<CatalogEntry> 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<CatalogEntryV2> catalogV2 = new List<CatalogEntryV2>();
// 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<CatalogEntry>();
// 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<byte[]> catalogBlocks = new List<byte[]>();
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<CatalogEntry>();
// 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();

View File

@@ -105,11 +105,21 @@ namespace DiscImageChef.Filesystems.LisaFS
'\u0000','\u0000','\u0000','\u0000','\u0000','\u0000','\u0000','\u0000'
};
/// <summary>
/// Converts a LisaRoman character to an Unicode character
/// </summary>
/// <returns>Unicode character.</returns>
/// <param name="character">LisaRoman character.</param>
static char GetChar(byte character)
{
return LisaRomanTable[character];
}
/// <summary>
/// Converts a LisaRoman string, null-terminated or null-paded, to a C# string
/// </summary>
/// <returns>The C# string.</returns>
/// <param name="str">LisaRoman string.</param>
static string GetString(byte[] str)
{
string uni = "";
@@ -125,6 +135,11 @@ namespace DiscImageChef.Filesystems.LisaFS
return uni;
}
/// <summary>
/// Converts a LisaRoman string, in Pascal length-prefixed format, to a C# string
/// </summary>
/// <returns>The C# string.</returns>
/// <param name="PascalString">The LisaRoman string in Pascal format.</param>
static string GetStringFromPascal(byte[] PascalString)
{
if(PascalString == null)

View File

@@ -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;
}
/// <summary>
/// Reads all the S-Records and caches it
/// </summary>
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++)

View File

@@ -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<CatalogEntry> catalog;
Errno error = ReadCatalog((short)FILEID_DIRECTORY, out catalog);
Errno error = ReadCatalog((short)FILEID_ROOTCATALOG, out catalog);
if(error != Errno.NoError)
return error;

View File

@@ -51,11 +51,17 @@ namespace DiscImageChef.Filesystems.LisaFS
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>
Dictionary<short, 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;
#endregion Caches

View File

@@ -35,6 +35,13 @@ namespace DiscImageChef.Filesystems.LisaFS
{
partial class LisaFS : Filesystem
{
/// <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.
/// </summary>
struct MDDF
{
/// <summary>0x00, Filesystem version</summary>
@@ -200,6 +207,13 @@ namespace DiscImageChef.Filesystems.LisaFS
public byte scavenge_flag;
}
/// <summary>
/// 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).
/// </summary>
struct Tag
{
/// <summary>0x00 version</summary>
@@ -235,11 +249,17 @@ namespace DiscImageChef.Filesystems.LisaFS
public bool isLast;
}
/// <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.
/// </summary>
struct CatalogEntry
{
/// <summary>0x00, seems to be 0x24 when the entry is valid</summary>
public byte marker;
/// <summary>0x01, seems to be always zero</summary>
/// <summary>0x01, must be zero otherwise LisaOS gives an error</summary>
public ushort zero;
/// <summary>0x03, filename, 32-bytes, null-padded</summary>
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...
/// </summary>
public byte fileType;
@@ -269,12 +288,23 @@ namespace DiscImageChef.Filesystems.LisaFS
public byte[] tail;
}
/// <summary>
/// An extent indicating a start and a run of sectors.
/// </summary>
struct Extent
{
public int start;
public short length;
}
/// <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.
/// </summary>
struct ExtentFile
{
/// <summary>0x00, filename length</summary>
@@ -349,10 +379,26 @@ namespace DiscImageChef.Filesystems.LisaFS
public Extent[] extents;
/// <summary>0x17E, unknown, empty, padding?</summary>
public short unknown10;
/// <summary>0x180, 128 bytes</summary>
/// <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.
/// </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.
/// </summary>
struct SRecord
{
/// <summary>0x00, block where ExtentsFile for this entry resides</summary>
@@ -365,6 +411,16 @@ namespace DiscImageChef.Filesystems.LisaFS
public ushort flags;
}
/// <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.
/// </summary>
struct CatalogEntryV2
{
/// <summary>0x00, filename, 32-bytes, null-padded</summary>

View File

@@ -39,15 +39,24 @@ namespace DiscImageChef.Filesystems.LisaFS
{
partial class LisaFS : Filesystem
{
/// <summary>
/// Mounts an Apple Lisa filesystem
/// </summary>
public override Errno Mount()
{
return Mount(false);
}
/// <summary>
/// Mounts an Apple Lisa filesystem
/// </summary>
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<short, ExtentFile>();
systemFileCache = new Dictionary<short, byte[]>();
fileCache = new Dictionary<short, byte[]>();
@@ -214,6 +226,7 @@ namespace DiscImageChef.Filesystems.LisaFS
printedExtents = new List<short>();
}
// 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<CatalogEntry> 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
}
}
/// <summary>
/// Umounts this Lisa filesystem
/// </summary>
public override Errno Unmount()
{
mounted = false;
@@ -329,6 +348,10 @@ namespace DiscImageChef.Filesystems.LisaFS
return Errno.NoError;
}
/// <summary>
/// Gets information about the mounted volume.
/// </summary>
/// <param name="stat">Information about the mounted volume.</param>
public override Errno StatFs(ref FileSystemInfo stat)
{
if(!mounted)

View File

@@ -39,6 +39,12 @@ namespace DiscImageChef.Filesystems.LisaFS
{
partial class LisaFS : Filesystem
{
/// <summary>
/// Lists all extended attributes, alternate data streams and forks of the given file.
/// </summary>
/// <returns>Error number.</returns>
/// <param name="path">Path.</param>
/// <param name="xattrs">List of extended attributes, alternate data streams and forks.</param>
public override Errno ListXAttr(string path, ref List<string> xattrs)
{
short fileId;
@@ -49,6 +55,13 @@ namespace DiscImageChef.Filesystems.LisaFS
return ListXAttr(fileId, ref xattrs);
}
/// <summary>
/// Reads an extended attribute, alternate data stream or fork from the given file.
/// </summary>
/// <returns>Error number.</returns>
/// <param name="path">File path.</param>
/// <param name="xattr">Extendad attribute, alternate data stream or fork name.</param>
/// <param name="buf">Buffer.</param>
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);
}
/// <summary>
/// Lists special Apple Lisa filesystem features as extended attributes
/// </summary>
/// <returns>Error number.</returns>
/// <param name="fileId">File identifier.</param>
/// <param name="xattrs">Extended attributes.</param>
Errno ListXAttr(short fileId, ref List<string> 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<string>();
// 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<string>();
// 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;
}
/// <summary>
/// Lists special Apple Lisa filesystem features as extended attributes
/// </summary>
/// <returns>Error number.</returns>
/// <param name="fileId">File identifier.</param>
/// <param name="xattr">Extended attribute name.</param>
/// <param name="buf">Buffer where the extended attribute will be stored.</param>
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;
}
/// <summary>
/// Decodes a sector tag. Not tested with 24-byte tags.
/// </summary>
/// <returns>Error number.</returns>
/// <param name="tag">Sector tag.</param>
/// <param name="decoded">Decoded sector tag.</param>
Errno DecodeTag(byte[] tag, out Tag decoded)
{
decoded = new Tag();
@@ -214,4 +257,3 @@ namespace DiscImageChef.Filesystems.LisaFS
}
}
}