From a1f82e0e720cd30db8b384f53eeee68223b3aab8 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Wed, 27 Dec 2017 23:55:59 +0000 Subject: [PATCH] Add option to pass an arbitrary list of options to IReadOnlyFilesystem.Mount() --- .../AppleDOS/AppleDOS.cs | 39 +-- DiscImageChef.Filesystems/AppleDOS/Super.cs | 49 ++-- .../AppleMFS/AppleMFS.cs | 53 ++-- DiscImageChef.Filesystems/AppleMFS/Super.cs | 122 ++++----- DiscImageChef.Filesystems/CPM/CPM.cs | 17 +- DiscImageChef.Filesystems/CPM/Super.cs | 222 +++++++++-------- .../IReadOnlyFilesystem.cs | 10 +- DiscImageChef.Filesystems/LisaFS/LisaFS.cs | 33 +-- DiscImageChef.Filesystems/LisaFS/Super.cs | 231 +++++++++--------- DiscImageChef.Filesystems/UCSDPascal/Super.cs | 78 +++--- .../UCSDPascal/UCSDPascal.cs | 17 +- 11 files changed, 454 insertions(+), 417 deletions(-) diff --git a/DiscImageChef.Filesystems/AppleDOS/AppleDOS.cs b/DiscImageChef.Filesystems/AppleDOS/AppleDOS.cs index f0493fd58..941930fa7 100644 --- a/DiscImageChef.Filesystems/AppleDOS/AppleDOS.cs +++ b/DiscImageChef.Filesystems/AppleDOS/AppleDOS.cs @@ -40,22 +40,27 @@ namespace DiscImageChef.Filesystems.AppleDOS { public partial class AppleDOS : IReadOnlyFilesystem { - bool debug; + bool debug; IMediaImage device; - bool mounted; - int sectorsPerTrack; - ulong start; - ulong totalFileEntries; - bool track1UsedByFiles; - bool track2UsedByFiles; - int usedSectors; + bool mounted; + int sectorsPerTrack; + ulong start; + ulong totalFileEntries; + bool track1UsedByFiles; + bool track2UsedByFiles; + int usedSectors; Vtoc vtoc; public FileSystemType XmlFsType { get; private set; } - public Encoding Encoding { get; private set; } - public string Name => "Apple DOS File System"; - public Guid Id => new Guid("8658A1E9-B2E7-4BCC-9638-157A31B0A700\n"); + public Encoding Encoding { get; private set; } + public string Name => "Apple DOS File System"; + public Guid Id => new Guid("8658A1E9-B2E7-4BCC-9638-157A31B0A700\n"); + + static Dictionary GetDefaultOptions() + { + return new Dictionary {{"debug", false.ToString()}}; + } #region Caches /// Caches track/sector lists @@ -65,17 +70,17 @@ namespace DiscImageChef.Filesystems.AppleDOS /// Caches catalog Dictionary catalogCache; /// Caches file size - Dictionary fileSizeCache; + Dictionary fileSizeCache; /// Caches VTOC - byte[] vtocBlocks; + byte[] vtocBlocks; /// Caches catalog - byte[] catalogBlocks; + byte[] catalogBlocks; /// Caches boot code - byte[] bootBlocks; + byte[] bootBlocks; /// Caches file type - Dictionary fileTypeCache; + Dictionary fileTypeCache; /// Caches locked files - List lockedFiles; + List lockedFiles; #endregion Caches } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/AppleDOS/Super.cs b/DiscImageChef.Filesystems/AppleDOS/Super.cs index 352a6d922..8a3712e0f 100644 --- a/DiscImageChef.Filesystems/AppleDOS/Super.cs +++ b/DiscImageChef.Filesystems/AppleDOS/Super.cs @@ -31,6 +31,7 @@ // ****************************************************************************/ using System; +using System.Collections.Generic; using System.Runtime.InteropServices; using Claunia.Encoding; using DiscImageChef.CommonTypes; @@ -46,10 +47,11 @@ namespace DiscImageChef.Filesystems.AppleDOS /// /// Mounts an Apple DOS filesystem /// - public Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) + public Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, + Dictionary options) { - device = imagePlugin; - start = partition.Start; + device = imagePlugin; + start = partition.Start; Encoding = encoding ?? new Apple2(); if(device.Info.Sectors != 455 && device.Info.Sectors != 560) @@ -73,8 +75,8 @@ namespace DiscImageChef.Filesystems.AppleDOS sectorsPerTrack = device.Info.Sectors == 455 ? 13 : 16; // Read the VTOC - vtocBlocks = device.ReadSector((ulong)(17 * sectorsPerTrack)); - vtoc = new Vtoc(); + vtocBlocks = device.ReadSector((ulong)(17 * sectorsPerTrack)); + vtoc = new Vtoc(); IntPtr vtocPtr = Marshal.AllocHGlobal(256); Marshal.Copy(vtocBlocks, 0, vtocPtr, 256); vtoc = (Vtoc)Marshal.PtrToStructure(vtocPtr, typeof(Vtoc)); @@ -82,7 +84,7 @@ namespace DiscImageChef.Filesystems.AppleDOS track1UsedByFiles = false; track2UsedByFiles = false; - usedSectors = 1; + usedSectors = 1; Errno error = ReadCatalog(); if(error != Errno.NoError) @@ -101,17 +103,18 @@ namespace DiscImageChef.Filesystems.AppleDOS // Create XML metadata for mounted filesystem XmlFsType = new FileSystemType { - Bootable = true, - Clusters = (long)device.Info.Sectors, - ClusterSize = vtoc.bytesPerSector, - Files = catalogCache.Count, - FilesSpecified = true, + Bootable = true, + Clusters = (long)device.Info.Sectors, + ClusterSize = vtoc.bytesPerSector, + Files = catalogCache.Count, + FilesSpecified = true, FreeClustersSpecified = true, - Type = "Apple DOS" + Type = "Apple DOS" }; XmlFsType.FreeClusters = XmlFsType.Clusters - usedSectors; - this.debug = debug; + if(options == null) options = GetDefaultOptions(); + if(options.TryGetValue("debug", out string debugString)) bool.TryParse(debugString, out debug); mounted = true; return Errno.NoError; } @@ -121,10 +124,10 @@ namespace DiscImageChef.Filesystems.AppleDOS /// public Errno Unmount() { - mounted = false; - extentCache = null; - fileCache = null; - catalogCache = null; + mounted = false; + extentCache = null; + fileCache = null; + catalogCache = null; fileSizeCache = null; return Errno.NoError; @@ -138,14 +141,14 @@ namespace DiscImageChef.Filesystems.AppleDOS { stat = new FileSystemInfo { - Blocks = (long)device.Info.Sectors, + Blocks = (long)device.Info.Sectors, FilenameLength = 30, - Files = (ulong)catalogCache.Count, - PluginId = Id, - Type = "Apple DOS" + Files = (ulong)catalogCache.Count, + PluginId = Id, + Type = "Apple DOS" }; - stat.FreeFiles = totalFileEntries - stat.Files; - stat.FreeBlocks = stat.Blocks - usedSectors; + stat.FreeFiles = totalFileEntries - stat.Files; + stat.FreeBlocks = stat.Blocks - usedSectors; return Errno.NoError; } diff --git a/DiscImageChef.Filesystems/AppleMFS/AppleMFS.cs b/DiscImageChef.Filesystems/AppleMFS/AppleMFS.cs index 3674bd004..c92d73dd7 100644 --- a/DiscImageChef.Filesystems/AppleMFS/AppleMFS.cs +++ b/DiscImageChef.Filesystems/AppleMFS/AppleMFS.cs @@ -33,7 +33,6 @@ using System; using System.Collections.Generic; using System.Text; -using DiscImageChef.CommonTypes; using DiscImageChef.DiscImages; using Schemas; @@ -42,47 +41,35 @@ namespace DiscImageChef.Filesystems.AppleMFS // Information from Inside Macintosh Volume II public partial class AppleMFS : IReadOnlyFilesystem { - bool mounted; - bool debug; + bool mounted; + bool debug; IMediaImage device; - ulong partitionStart; + ulong partitionStart; - Dictionary idToFilename; + Dictionary idToFilename; Dictionary idToEntry; - Dictionary filenameToId; + Dictionary filenameToId; MFS_MasterDirectoryBlock volMDB; - byte[] bootBlocks; - byte[] mdbBlocks; - byte[] directoryBlocks; - byte[] blockMapBytes; - uint[] blockMap; - int sectorsPerBlock; - byte[] bootTags; - byte[] mdbTags; - byte[] directoryTags; - byte[] bitmapTags; + byte[] bootBlocks; + byte[] mdbBlocks; + byte[] directoryBlocks; + byte[] blockMapBytes; + uint[] blockMap; + int sectorsPerBlock; + byte[] bootTags; + byte[] mdbTags; + byte[] directoryTags; + byte[] bitmapTags; public FileSystemType XmlFsType { get; private set; } - public string Name => "Apple Macintosh File System"; - public Guid Id => new Guid("36405F8D-0D26-4066-6538-5DBF5D065C3A"); - public Encoding Encoding { get; private set; } + public string Name => "Apple Macintosh File System"; + public Guid Id => new Guid("36405F8D-0D26-4066-6538-5DBF5D065C3A"); + public Encoding Encoding { get; private set; } - public AppleMFS() + static Dictionary GetDefaultOptions() { - Encoding = Encoding.GetEncoding("macintosh"); - } - - public AppleMFS(Encoding encoding) - { - Encoding = encoding ?? Encoding.GetEncoding("macintosh"); - } - - public AppleMFS(IMediaImage imagePlugin, Partition partition, Encoding encoding) - { - device = imagePlugin; - partitionStart = partition.Start; - Encoding = encoding ?? Encoding.GetEncoding("macintosh"); + return new Dictionary {{"debug", false.ToString()}}; } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/AppleMFS/Super.cs b/DiscImageChef.Filesystems/AppleMFS/Super.cs index 9f33d3764..e5a5f189a 100644 --- a/DiscImageChef.Filesystems/AppleMFS/Super.cs +++ b/DiscImageChef.Filesystems/AppleMFS/Super.cs @@ -31,6 +31,7 @@ // ****************************************************************************/ using System; +using System.Collections.Generic; using System.Text; using DiscImageChef.CommonTypes; using DiscImageChef.DiscImages; @@ -41,15 +42,17 @@ namespace DiscImageChef.Filesystems.AppleMFS // Information from Inside Macintosh Volume II public partial class AppleMFS { - public Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) + public Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, + Dictionary options) { - device = imagePlugin; - partitionStart = partition.Start; - Encoding = encoding ?? Encoding.GetEncoding("macintosh"); - this.debug = debug; + device = imagePlugin; + partitionStart = partition.Start; + Encoding = encoding ?? Encoding.GetEncoding("macintosh"); + if(options == null) options = GetDefaultOptions(); + if(options.TryGetValue("debug", out string debugString)) bool.TryParse(debugString, out debug); volMDB = new MFS_MasterDirectoryBlock(); - mdbBlocks = device.ReadSector(2 + partitionStart); + mdbBlocks = device.ReadSector(2 + partitionStart); bootBlocks = device.ReadSector(0 + partitionStart); BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; @@ -57,63 +60,64 @@ namespace DiscImageChef.Filesystems.AppleMFS volMDB.drSigWord = BigEndianBitConverter.ToUInt16(mdbBlocks, 0x000); if(volMDB.drSigWord != MFS_MAGIC) return Errno.InvalidArgument; - volMDB.drCrDate = BigEndianBitConverter.ToUInt32(mdbBlocks, 0x002); - volMDB.drLsBkUp = BigEndianBitConverter.ToUInt32(mdbBlocks, 0x006); - volMDB.drAtrb = BigEndianBitConverter.ToUInt16(mdbBlocks, 0x00A); - volMDB.drNmFls = BigEndianBitConverter.ToUInt16(mdbBlocks, 0x00C); - volMDB.drDirSt = BigEndianBitConverter.ToUInt16(mdbBlocks, 0x00E); - volMDB.drBlLen = BigEndianBitConverter.ToUInt16(mdbBlocks, 0x010); - volMDB.drNmAlBlks = BigEndianBitConverter.ToUInt16(mdbBlocks, 0x012); - volMDB.drAlBlkSiz = BigEndianBitConverter.ToUInt32(mdbBlocks, 0x014); - volMDB.drClpSiz = BigEndianBitConverter.ToUInt32(mdbBlocks, 0x018); - volMDB.drAlBlSt = BigEndianBitConverter.ToUInt16(mdbBlocks, 0x01C); - volMDB.drNxtFNum = BigEndianBitConverter.ToUInt32(mdbBlocks, 0x01E); - volMDB.drFreeBks = BigEndianBitConverter.ToUInt16(mdbBlocks, 0x022); - volMDB.drVNSiz = mdbBlocks[0x024]; - byte[] variableSize = new byte[volMDB.drVNSiz + 1]; + volMDB.drCrDate = BigEndianBitConverter.ToUInt32(mdbBlocks, 0x002); + volMDB.drLsBkUp = BigEndianBitConverter.ToUInt32(mdbBlocks, 0x006); + volMDB.drAtrb = BigEndianBitConverter.ToUInt16(mdbBlocks, 0x00A); + volMDB.drNmFls = BigEndianBitConverter.ToUInt16(mdbBlocks, 0x00C); + volMDB.drDirSt = BigEndianBitConverter.ToUInt16(mdbBlocks, 0x00E); + volMDB.drBlLen = BigEndianBitConverter.ToUInt16(mdbBlocks, 0x010); + volMDB.drNmAlBlks = BigEndianBitConverter.ToUInt16(mdbBlocks, 0x012); + volMDB.drAlBlkSiz = BigEndianBitConverter.ToUInt32(mdbBlocks, 0x014); + volMDB.drClpSiz = BigEndianBitConverter.ToUInt32(mdbBlocks, 0x018); + volMDB.drAlBlSt = BigEndianBitConverter.ToUInt16(mdbBlocks, 0x01C); + volMDB.drNxtFNum = BigEndianBitConverter.ToUInt32(mdbBlocks, 0x01E); + volMDB.drFreeBks = BigEndianBitConverter.ToUInt16(mdbBlocks, 0x022); + volMDB.drVNSiz = mdbBlocks[0x024]; + byte[] variableSize = new byte[volMDB.drVNSiz + 1]; Array.Copy(mdbBlocks, 0x024, variableSize, 0, volMDB.drVNSiz + 1); volMDB.drVN = StringHandlers.PascalToString(variableSize, Encoding); - directoryBlocks = device.ReadSectors(volMDB.drDirSt + partitionStart, volMDB.drBlLen); - int bytesInBlockMap = volMDB.drNmAlBlks * 12 / 8 + volMDB.drNmAlBlks * 12 % 8; + directoryBlocks = device.ReadSectors(volMDB.drDirSt + partitionStart, volMDB.drBlLen); + int bytesInBlockMap = volMDB.drNmAlBlks * 12 / 8 + volMDB.drNmAlBlks * 12 % 8; const int BYTES_BEFORE_BLOCK_MAP = 64; - int bytesInWholeMdb = bytesInBlockMap + BYTES_BEFORE_BLOCK_MAP; - int sectorsInWholeMdb = bytesInWholeMdb / (int)device.Info.SectorSize + - bytesInWholeMdb % (int)device.Info.SectorSize; + int bytesInWholeMdb = bytesInBlockMap + BYTES_BEFORE_BLOCK_MAP; + int sectorsInWholeMdb = bytesInWholeMdb / (int)device.Info.SectorSize + + bytesInWholeMdb % (int)device.Info.SectorSize; byte[] wholeMdb = device.ReadSectors(partitionStart + 2, (uint)sectorsInWholeMdb); - blockMapBytes = new byte[bytesInBlockMap]; + blockMapBytes = new byte[bytesInBlockMap]; Array.Copy(wholeMdb, BYTES_BEFORE_BLOCK_MAP, blockMapBytes, 0, blockMapBytes.Length); int offset = 0; - blockMap = new uint[volMDB.drNmAlBlks + 2 + 1]; - for(int i = 2; i < volMDB.drNmAlBlks + 2; i += 8) + blockMap = new uint[volMDB.drNmAlBlks + 2 + 1]; + for(int i = 2; i < volMDB.drNmAlBlks + 2; i += 8) { uint tmp1 = 0; uint tmp2 = 0; uint tmp3 = 0; - if(offset + 4 <= blockMapBytes.Length) tmp1 = BigEndianBitConverter.ToUInt32(blockMapBytes, offset); - if(offset + 4 + 4 <= blockMapBytes.Length) + if(offset + 4 <= blockMapBytes.Length) + tmp1 = BigEndianBitConverter.ToUInt32(blockMapBytes, offset); + if(offset + 4 + 4 <= blockMapBytes.Length) tmp2 = BigEndianBitConverter.ToUInt32(blockMapBytes, offset + 4); - if(offset + 8 + 4 <= blockMapBytes.Length) + if(offset + 8 + 4 <= blockMapBytes.Length) tmp3 = BigEndianBitConverter.ToUInt32(blockMapBytes, offset + 8); - if(i < blockMap.Length) blockMap[i] = (tmp1 & 0xFFF00000) >> 20; - if(i + 2 < blockMap.Length) blockMap[i + 1] = (tmp1 & 0xFFF00) >> 8; - if(i + 3 < blockMap.Length) blockMap[i + 2] = ((tmp1 & 0xFF) << 4) + ((tmp2 & 0xF0000000) >> 28); - if(i + 4 < blockMap.Length) blockMap[i + 3] = (tmp2 & 0xFFF0000) >> 16; - if(i + 5 < blockMap.Length) blockMap[i + 4] = (tmp2 & 0xFFF0) >> 4; - if(i + 6 < blockMap.Length) blockMap[i + 5] = ((tmp2 & 0xF) << 8) + ((tmp3 & 0xFF000000) >> 24); - if(i + 7 < blockMap.Length) blockMap[i + 6] = (tmp3 & 0xFFF000) >> 12; - if(i + 8 < blockMap.Length) blockMap[i + 7] = tmp3 & 0xFFF; + if(i < blockMap.Length) blockMap[i] = (tmp1 & 0xFFF00000) >> 20; + if(i + 2 < blockMap.Length) blockMap[i + 1] = (tmp1 & 0xFFF00) >> 8; + if(i + 3 < blockMap.Length) blockMap[i + 2] = ((tmp1 & 0xFF) << 4) + ((tmp2 & 0xF0000000) >> 28); + if(i + 4 < blockMap.Length) blockMap[i + 3] = (tmp2 & 0xFFF0000) >> 16; + if(i + 5 < blockMap.Length) blockMap[i + 4] = (tmp2 & 0xFFF0) >> 4; + if(i + 6 < blockMap.Length) blockMap[i + 5] = ((tmp2 & 0xF) << 8) + ((tmp3 & 0xFF000000) >> 24); + if(i + 7 < blockMap.Length) blockMap[i + 6] = (tmp3 & 0xFFF000) >> 12; + if(i + 8 < blockMap.Length) blockMap[i + 7] = tmp3 & 0xFFF; offset += 12; } if(device.Info.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag)) { - mdbTags = device.ReadSectorTag(2 + partitionStart, SectorTagType.AppleSectorTag); - bootTags = device.ReadSectorTag(0 + partitionStart, SectorTagType.AppleSectorTag); + mdbTags = device.ReadSectorTag(2 + partitionStart, SectorTagType.AppleSectorTag); + bootTags = device.ReadSectorTag(0 + partitionStart, SectorTagType.AppleSectorTag); directoryTags = device.ReadSectorsTag(volMDB.drDirSt + partitionStart, volMDB.drBlLen, SectorTagType.AppleSectorTag); bitmapTags = device.ReadSectorsTag(partitionStart + 2, (uint)sectorsInWholeMdb, @@ -133,34 +137,36 @@ namespace DiscImageChef.Filesystems.AppleMFS XmlFsType = new FileSystemType(); if(volMDB.drLsBkUp > 0) { - XmlFsType.BackupDate = DateHandlers.MacToDateTime(volMDB.drLsBkUp); + XmlFsType.BackupDate = DateHandlers.MacToDateTime(volMDB.drLsBkUp); XmlFsType.BackupDateSpecified = true; } - XmlFsType.Bootable = bbSig == MFSBB_MAGIC; - XmlFsType.Clusters = volMDB.drNmAlBlks; + + XmlFsType.Bootable = bbSig == MFSBB_MAGIC; + XmlFsType.Clusters = volMDB.drNmAlBlks; XmlFsType.ClusterSize = (int)volMDB.drAlBlkSiz; if(volMDB.drCrDate > 0) { - XmlFsType.CreationDate = DateHandlers.MacToDateTime(volMDB.drCrDate); + XmlFsType.CreationDate = DateHandlers.MacToDateTime(volMDB.drCrDate); XmlFsType.CreationDateSpecified = true; } - XmlFsType.Files = volMDB.drNmFls; - XmlFsType.FilesSpecified = true; - XmlFsType.FreeClusters = volMDB.drFreeBks; + + XmlFsType.Files = volMDB.drNmFls; + XmlFsType.FilesSpecified = true; + XmlFsType.FreeClusters = volMDB.drFreeBks; XmlFsType.FreeClustersSpecified = true; - XmlFsType.Type = "MFS"; - XmlFsType.VolumeName = volMDB.drVN; + XmlFsType.Type = "MFS"; + XmlFsType.VolumeName = volMDB.drVN; return Errno.NoError; } public Errno Unmount() { - mounted = false; + mounted = false; idToFilename = null; - idToEntry = null; + idToEntry = null; filenameToId = null; - bootBlocks = null; + bootBlocks = null; return Errno.NoError; } @@ -169,12 +175,12 @@ namespace DiscImageChef.Filesystems.AppleMFS { stat = new FileSystemInfo { - Blocks = volMDB.drNmAlBlks, + Blocks = volMDB.drNmAlBlks, FilenameLength = 255, - Files = volMDB.drNmFls, - FreeBlocks = volMDB.drFreeBks, - PluginId = Id, - Type = "Apple MFS" + Files = volMDB.drNmFls, + FreeBlocks = volMDB.drFreeBks, + PluginId = Id, + Type = "Apple MFS" }; stat.FreeFiles = uint.MaxValue - stat.Files; diff --git a/DiscImageChef.Filesystems/CPM/CPM.cs b/DiscImageChef.Filesystems/CPM/CPM.cs index 5402d4e04..899193753 100644 --- a/DiscImageChef.Filesystems/CPM/CPM.cs +++ b/DiscImageChef.Filesystems/CPM/CPM.cs @@ -60,7 +60,7 @@ namespace DiscImageChef.Filesystems.CPM /// Stores all known CP/M disk definitions /// CpmDefinitions definitions; - IMediaImage device; + IMediaImage device; /// /// Cached directory listing /// @@ -84,8 +84,8 @@ namespace DiscImageChef.Filesystems.CPM /// /// Timestamp in volume label for update /// - byte[] labelUpdateDate; - bool mounted; + byte[] labelUpdateDate; + bool mounted; Partition partition; /// /// Cached file passwords @@ -113,8 +113,13 @@ namespace DiscImageChef.Filesystems.CPM CpmDefinition workingDefinition; public FileSystemType XmlFsType { get; private set; } - public Encoding Encoding { get; private set; } - public string Name => "CP/M File System"; - public Guid Id => new Guid("AA2B8585-41DF-4E3B-8A35-D1A935E2F8A1"); + public Encoding Encoding { get; private set; } + public string Name => "CP/M File System"; + public Guid Id => new Guid("AA2B8585-41DF-4E3B-8A35-D1A935E2F8A1"); + + static Dictionary GetDefaultOptions() + { + return new Dictionary {{"debug", false.ToString()}}; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/CPM/Super.cs b/DiscImageChef.Filesystems/CPM/Super.cs index 20b1bccfb..ffc179593 100644 --- a/DiscImageChef.Filesystems/CPM/Super.cs +++ b/DiscImageChef.Filesystems/CPM/Super.cs @@ -47,11 +47,12 @@ namespace DiscImageChef.Filesystems.CPM { partial class CPM { - public Errno Mount(IMediaImage imagePlugin, Partition partition1, Encoding encoding, bool debug) + public Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, + Dictionary options) { - device = imagePlugin; - partition = partition; - Encoding = encoding ?? Encoding.GetEncoding("IBM437"); + device = imagePlugin; + this.partition = partition; + Encoding = encoding ?? Encoding.GetEncoding("IBM437"); // As the identification is so complex, just call Identify() and relay on its findings if(!Identify(device, partition) || !cpmFound || workingDefinition == null || dpb == null) @@ -75,7 +76,7 @@ namespace DiscImageChef.Filesystems.CPM sectorMask[m] = workingDefinition.side1.sectorIds[m] - workingDefinition.side1.sectorIds[0]; // Skip first track (first side) for(int m = 0; m < workingDefinition.side2.sectorIds.Length; m++) - sectorMask[m + workingDefinition.side1.sectorIds.Length] = + sectorMask[m + workingDefinition.side1.sectorIds.Length] = workingDefinition.side2.sectorIds[m] - workingDefinition.side2.sectorIds[0] + workingDefinition.side1.sectorIds.Length; } @@ -87,8 +88,8 @@ namespace DiscImageChef.Filesystems.CPM sectorMask[m] = workingDefinition.side1.sectorIds[m] - workingDefinition.side1.sectorIds[0]; // Skip first track (first side) and first track (second side) for(int m = 0; m < workingDefinition.side1.sectorIds.Length; m++) - sectorMask[m + workingDefinition.side1.sectorIds.Length] = - workingDefinition.side1.sectorIds[m] - workingDefinition.side1.sectorIds[0] + + sectorMask[m + workingDefinition.side1.sectorIds.Length] = + workingDefinition.side1.sectorIds[m] - workingDefinition.side1.sectorIds[0] + workingDefinition.side1.sectorIds.Length + workingDefinition.side2.sectorIds.Length; // TODO: Implement CYLINDERS ordering @@ -96,9 +97,8 @@ namespace DiscImageChef.Filesystems.CPM return Errno.NotImplemented; } // TODO: Implement COLUMBIA ordering - else if( - string.Compare(workingDefinition.order, "COLUMBIA", StringComparison.InvariantCultureIgnoreCase) == - 0) + else if(string.Compare(workingDefinition.order, "COLUMBIA", + StringComparison.InvariantCultureIgnoreCase) == 0) { DicConsole.DebugWriteLine("CP/M Plugin", "Don't know how to handle COLUMBIA ordering, not proceeding with this definition."); @@ -123,7 +123,7 @@ namespace DiscImageChef.Filesystems.CPM // Deinterleave whole volume Dictionary deinterleavedSectors = new Dictionary(); - if(workingDefinition.sides == 1 || + if(workingDefinition.sides == 1 || string.Compare(workingDefinition.order, "SIDES", StringComparison.InvariantCultureIgnoreCase) == 0) { DicConsole.DebugWriteLine("CP/M Plugin", "Deinterleaving whole volume."); @@ -132,18 +132,19 @@ namespace DiscImageChef.Filesystems.CPM { byte[] readSector = device.ReadSector((ulong)((int)partition.Start + p / sectorMask.Length * sectorMask.Length + - sectorMask[p % sectorMask.Length])); + sectorMask[p % sectorMask.Length])); if(workingDefinition.complement) - for(int b = 0; b < readSector.Length; b++) readSector[b] = (byte)(~readSector[b] & 0xFF); + for(int b = 0; b < readSector.Length; b++) + readSector[b] = (byte)(~readSector[b] & 0xFF); deinterleavedSectors.Add((ulong)p, readSector); } } - int blockSize = 128 << dpb.bsh; - MemoryStream blockMs = new MemoryStream(); - ulong blockNo = 0; - int sectorsPerBlock = 0; + int blockSize = 128 << dpb.bsh; + MemoryStream blockMs = new MemoryStream(); + ulong blockNo = 0; + int sectorsPerBlock = 0; Dictionary allocationBlocks = new Dictionary(); DicConsole.DebugWriteLine("CP/M Plugin", "Creating allocation blocks."); @@ -154,7 +155,7 @@ namespace DiscImageChef.Filesystems.CPM deinterleavedSectors.TryGetValue(a, out byte[] sector); // May it happen? Just in case, CP/M blocks are smaller than physical sectors - if(sector.Length > blockSize) + if(sector.Length > blockSize) for(int i = 0; i < sector.Length / blockSize; i++) { byte[] tmp = new byte[blockSize]; @@ -171,18 +172,19 @@ namespace DiscImageChef.Filesystems.CPM allocationBlocks.Add(blockNo++, blockMs.ToArray()); sectorsPerBlock = 0; - blockMs = new MemoryStream(); + blockMs = new MemoryStream(); } // CP/M blocks are same size than physical sectors - else allocationBlocks.Add(blockNo++, sector); + else + allocationBlocks.Add(blockNo++, sector); } DicConsole.DebugWriteLine("CP/M Plugin", "Reading directory."); int dirOff; - int dirSectors = (dpb.drm + 1) * 32 / workingDefinition.bytesPerSector; + int dirSectors = (dpb.drm + 1) * 32 / workingDefinition.bytesPerSector; if(workingDefinition.sofs > 0) dirOff = workingDefinition.sofs; - else dirOff = workingDefinition.ofs * workingDefinition.sectorsPerTrack; + else dirOff = workingDefinition.ofs * workingDefinition.sectorsPerTrack; // Read the whole directory blocks MemoryStream dirMs = new MemoryStream(); @@ -196,19 +198,19 @@ namespace DiscImageChef.Filesystems.CPM if(directory == null) return Errno.InvalidArgument; - int dirCnt = 0; - string file1 = null; - string file2 = null; - string file3 = null; + int dirCnt = 0; + string file1 = null; + string file2 = null; + string file3 = null; Dictionary>> fileExtents = new Dictionary>>(); - statCache = new Dictionary(); - cpmStat = new FileSystemInfo(); - bool atime = false; - dirList = new List(); + statCache = new Dictionary(); + cpmStat = new FileSystemInfo(); + bool atime = false; + dirList = new List(); labelCreationDate = null; - labelUpdateDate = null; - passwordCache = new Dictionary(); + labelUpdateDate = null; + passwordCache = new Dictionary(); DicConsole.DebugWriteLine("CP/M Plugin", "Traversing directory."); IntPtr dirPtr; @@ -216,7 +218,7 @@ namespace DiscImageChef.Filesystems.CPM // For each directory entry for(int dOff = 0; dOff < directory.Length; dOff += 32) // Describes a file (does not support PDOS entries with user >= 16, because they're identical to password entries - if((directory[dOff] & 0x7F) < 0x10) + if((directory[dOff] & 0x7F) < 0x10) if(allocationBlocks.Count > 256) { dirPtr = Marshal.AllocHGlobal(32); @@ -225,7 +227,7 @@ namespace DiscImageChef.Filesystems.CPM (DirectoryEntry16)Marshal.PtrToStructure(dirPtr, typeof(DirectoryEntry16)); Marshal.FreeHGlobal(dirPtr); - bool hidden = (entry.statusUser & 0x80) == 0x80; + bool hidden = (entry.statusUser & 0x80) == 0x80; bool rdOnly = (entry.filename[0] & 0x80) == 0x80 || (entry.extension[0] & 0x80) == 0x80; bool system = (entry.filename[1] & 0x80) == 0x80 || (entry.extension[2] & 0x80) == 0x80; //bool backed = (entry.filename[3] & 0x80) == 0x80 || (entry.extension[3] & 0x80) == 0x80; @@ -236,21 +238,22 @@ namespace DiscImageChef.Filesystems.CPM for(int i = 0; i < 8; i++) { entry.filename[i] &= 0x7F; - validEntry &= entry.filename[i] >= 0x20; + validEntry &= entry.filename[i] >= 0x20; } + for(int i = 0; i < 3; i++) { entry.extension[i] &= 0x7F; - validEntry &= entry.extension[i] >= 0x20; + validEntry &= entry.extension[i] >= 0x20; } if(!validEntry) continue; - string filename = Encoding.ASCII.GetString(entry.filename).Trim(); + string filename = Encoding.ASCII.GetString(entry.filename).Trim(); string extension = Encoding.ASCII.GetString(entry.extension).Trim(); // If user is != 0, append user to name to have identical filenames - if(user > 0) filename = $"{user:X1}:{filename}"; + if(user > 0) filename = $"{user:X1}:{filename}"; if(!string.IsNullOrEmpty(extension)) filename = filename + "." + extension; int entryNo = (32 * entry.extentCounter + entry.extentCounterHigh) / (dpb.exm + 1); @@ -273,11 +276,11 @@ namespace DiscImageChef.Filesystems.CPM if(rdOnly) fInfo.Attributes |= FileAttributes.ReadOnly; if(system) fInfo.Attributes |= FileAttributes.System; - // Supposedly there is a value in the directory entry telling how many blocks are designated in this entry - // However some implementations tend to do whatever they wish, but none will ever allocate block 0 for a file - // because that's where the directory resides. - // There is also a field telling how many bytes are used in the last block, but its meaning is non-standard so - // we must ignore it. + // Supposedly there is a value in the directory entry telling how many blocks are designated in + // this entry. However some implementations tend to do whatever they wish, but none will ever + // allocate block 0 for a file because that's where the directory resides. + // There is also a field telling how many bytes are used in the last block, but its meaning is + // non-standard so we must ignore it. foreach(ushort blk in entry.allocations.Where(blk => !blocks.Contains(blk) && blk != 0)) blocks.Add(blk); @@ -313,7 +316,7 @@ namespace DiscImageChef.Filesystems.CPM DirectoryEntry entry = (DirectoryEntry)Marshal.PtrToStructure(dirPtr, typeof(DirectoryEntry)); Marshal.FreeHGlobal(dirPtr); - bool hidden = (entry.statusUser & 0x80) == 0x80; + bool hidden = (entry.statusUser & 0x80) == 0x80; bool rdOnly = (entry.filename[0] & 0x80) == 0x80 || (entry.extension[0] & 0x80) == 0x80; bool system = (entry.filename[1] & 0x80) == 0x80 || (entry.extension[2] & 0x80) == 0x80; //bool backed = (entry.filename[3] & 0x80) == 0x80 || (entry.extension[3] & 0x80) == 0x80; @@ -324,21 +327,22 @@ namespace DiscImageChef.Filesystems.CPM for(int i = 0; i < 8; i++) { entry.filename[i] &= 0x7F; - validEntry &= entry.filename[i] >= 0x20; + validEntry &= entry.filename[i] >= 0x20; } + for(int i = 0; i < 3; i++) { entry.extension[i] &= 0x7F; - validEntry &= entry.extension[i] >= 0x20; + validEntry &= entry.extension[i] >= 0x20; } if(!validEntry) continue; - string filename = Encoding.ASCII.GetString(entry.filename).Trim(); + string filename = Encoding.ASCII.GetString(entry.filename).Trim(); string extension = Encoding.ASCII.GetString(entry.extension).Trim(); // If user is != 0, append user to name to have identical filenames - if(user > 0) filename = $"{user:X1}:{filename}"; + if(user > 0) filename = $"{user:X1}:{filename}"; if(!string.IsNullOrEmpty(extension)) filename = filename + "." + extension; int entryNo = (32 * entry.extentCounterHigh + entry.extentCounter) / (dpb.exm + 1); @@ -361,11 +365,11 @@ namespace DiscImageChef.Filesystems.CPM if(rdOnly) fInfo.Attributes |= FileAttributes.ReadOnly; if(system) fInfo.Attributes |= FileAttributes.System; - // Supposedly there is a value in the directory entry telling how many blocks are designated in this entry - // However some implementations tend to do whatever they wish, but none will ever allocate block 0 for a file - // because that's where the directory resides. - // There is also a field telling how many bytes are used in the last block, but its meaning is non-standard so - // we must ignore it. + // Supposedly there is a value in the directory entry telling how many blocks are designated in + // this entry. However some implementations tend to do whatever they wish, but none will ever + // allocate block 0 for a file because that's where the directory resides. + // There is also a field telling how many bytes are used in the last block, but its meaning is + // non-standard so we must ignore it. foreach(ushort blk in entry.allocations.Cast() .Where(blk => !blocks.Contains(blk) && blk != 0)) blocks.Add(blk); @@ -404,14 +408,14 @@ namespace DiscImageChef.Filesystems.CPM int user = entry.userNumber & 0x0F; - for(int i = 0; i < 8; i++) entry.filename[i] &= 0x7F; + for(int i = 0; i < 8; i++) entry.filename[i] &= 0x7F; for(int i = 0; i < 3; i++) entry.extension[i] &= 0x7F; - string filename = Encoding.ASCII.GetString(entry.filename).Trim(); + string filename = Encoding.ASCII.GetString(entry.filename).Trim(); string extension = Encoding.ASCII.GetString(entry.extension).Trim(); // If user is != 0, append user to name to have identical filenames - if(user > 0) filename = $"{user:X1}:{filename}"; + if(user > 0) filename = $"{user:X1}:{filename}"; if(!string.IsNullOrEmpty(extension)) filename = filename + "." + extension; // Do not repeat passwords @@ -449,14 +453,15 @@ namespace DiscImageChef.Filesystems.CPM labelEntry = (LabelEntry)Marshal.PtrToStructure(dirPtr, typeof(LabelEntry)); Marshal.FreeHGlobal(dirPtr); - // The volume label defines if one of the fields in CP/M 3 timestamp is a creation or an access time + // The volume label defines if one of the fields in CP/M 3 timestamp is a creation or an + // access time atime |= (labelEntry.flags & 0x40) == 0x40; - label = Encoding.ASCII.GetString(directory, dOff + 1, 11).Trim(); + label = Encoding.ASCII.GetString(directory, dOff + 1, 11).Trim(); labelCreationDate = new byte[4]; - labelUpdateDate = new byte[4]; + labelUpdateDate = new byte[4]; Array.Copy(directory, dOff + 24, labelCreationDate, 0, 4); - Array.Copy(directory, dOff + 28, labelUpdateDate, 0, 4); + Array.Copy(directory, dOff + 28, labelUpdateDate, 0, 4); // Count entries 3 by 3 for timestamps switch(dirCnt % 3) @@ -492,7 +497,7 @@ namespace DiscImageChef.Filesystems.CPM else fInfo = new FileEntryInfo(); if(atime) fInfo.AccessTime = DateHandlers.CpmToDateTime(dateEntry.date1); - else fInfo.CreationTime = DateHandlers.CpmToDateTime(dateEntry.date1); + else fInfo.CreationTime = DateHandlers.CpmToDateTime(dateEntry.date1); fInfo.LastWriteTime = DateHandlers.CpmToDateTime(dateEntry.date2); @@ -505,7 +510,7 @@ namespace DiscImageChef.Filesystems.CPM else fInfo = new FileEntryInfo(); if(atime) fInfo.AccessTime = DateHandlers.CpmToDateTime(dateEntry.date3); - else fInfo.CreationTime = DateHandlers.CpmToDateTime(dateEntry.date3); + else fInfo.CreationTime = DateHandlers.CpmToDateTime(dateEntry.date3); fInfo.LastWriteTime = DateHandlers.CpmToDateTime(dateEntry.date4); @@ -518,16 +523,16 @@ namespace DiscImageChef.Filesystems.CPM else fInfo = new FileEntryInfo(); if(atime) fInfo.AccessTime = DateHandlers.CpmToDateTime(dateEntry.date5); - else fInfo.CreationTime = DateHandlers.CpmToDateTime(dateEntry.date5); + else fInfo.CreationTime = DateHandlers.CpmToDateTime(dateEntry.date5); fInfo.LastWriteTime = DateHandlers.CpmToDateTime(dateEntry.date6); statCache.Add(file3, fInfo); } - file1 = null; - file2 = null; - file3 = null; + file1 = null; + file2 = null; + file3 = null; dirCnt = 0; } // However, if this byte is 0, timestamp is in Z80DOS or DOS+ format @@ -548,11 +553,11 @@ namespace DiscImageChef.Filesystems.CPM else fInfo = new FileEntryInfo(); byte[] ctime = new byte[4]; - ctime[0] = trdPartyDateEntry.create1[0]; - ctime[1] = trdPartyDateEntry.create1[1]; + ctime[0] = trdPartyDateEntry.create1[0]; + ctime[1] = trdPartyDateEntry.create1[1]; - fInfo.AccessTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.access1); - fInfo.CreationTime = DateHandlers.CpmToDateTime(ctime); + fInfo.AccessTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.access1); + fInfo.CreationTime = DateHandlers.CpmToDateTime(ctime); fInfo.LastWriteTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.modify1); statCache.Add(file1, fInfo); @@ -564,11 +569,11 @@ namespace DiscImageChef.Filesystems.CPM else fInfo = new FileEntryInfo(); byte[] ctime = new byte[4]; - ctime[0] = trdPartyDateEntry.create2[0]; - ctime[1] = trdPartyDateEntry.create2[1]; + ctime[0] = trdPartyDateEntry.create2[0]; + ctime[1] = trdPartyDateEntry.create2[1]; - fInfo.AccessTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.access2); - fInfo.CreationTime = DateHandlers.CpmToDateTime(ctime); + fInfo.AccessTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.access2); + fInfo.CreationTime = DateHandlers.CpmToDateTime(ctime); fInfo.LastWriteTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.modify2); statCache.Add(file2, fInfo); @@ -580,21 +585,22 @@ namespace DiscImageChef.Filesystems.CPM else fInfo = new FileEntryInfo(); byte[] ctime = new byte[4]; - ctime[0] = trdPartyDateEntry.create3[0]; - ctime[1] = trdPartyDateEntry.create3[1]; + ctime[0] = trdPartyDateEntry.create3[0]; + ctime[1] = trdPartyDateEntry.create3[1]; - fInfo.AccessTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.access3); - fInfo.CreationTime = DateHandlers.CpmToDateTime(ctime); + fInfo.AccessTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.access3); + fInfo.CreationTime = DateHandlers.CpmToDateTime(ctime); fInfo.LastWriteTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.modify3); statCache.Add(file3, fInfo); } - file1 = null; - file2 = null; - file3 = null; + file1 = null; + file2 = null; + file3 = null; dirCnt = 0; } + break; } @@ -602,7 +608,7 @@ namespace DiscImageChef.Filesystems.CPM // this should not be a problem DicConsole.DebugWriteLine("CP/M Plugin", "Reading files."); long usedBlocks = 0; - fileCache = new Dictionary(); + fileCache = new Dictionary(); foreach(string filename in dirList) { MemoryStream fileMs = new MemoryStream(); @@ -626,8 +632,8 @@ namespace DiscImageChef.Filesystems.CPM // If you insist to call CP/M "extent based" fInfo.Attributes |= FileAttributes.Extents; - fInfo.BlockSize = blockSize; - fInfo.Length = fileMs.Length; + fInfo.BlockSize = blockSize; + fInfo.Length = fileMs.Length; cpmStat.Files++; usedBlocks += fInfo.Blocks; @@ -648,34 +654,36 @@ namespace DiscImageChef.Filesystems.CPM } // Generate statfs. - cpmStat.Blocks = dpb.dsm + 1; + cpmStat.Blocks = dpb.dsm + 1; cpmStat.FilenameLength = 11; - cpmStat.Files = (ulong)fileCache.Count; - cpmStat.FreeBlocks = cpmStat.Blocks - usedBlocks; - cpmStat.PluginId = Id; - cpmStat.Type = "CP/M filesystem"; + cpmStat.Files = (ulong)fileCache.Count; + cpmStat.FreeBlocks = cpmStat.Blocks - usedBlocks; + cpmStat.PluginId = Id; + cpmStat.Type = "CP/M filesystem"; // Generate XML info XmlFsType = new FileSystemType { - Clusters = cpmStat.Blocks, - ClusterSize = blockSize, - Files = fileCache.Count, - FilesSpecified = true, - FreeClusters = cpmStat.FreeBlocks, + Clusters = cpmStat.Blocks, + ClusterSize = blockSize, + Files = fileCache.Count, + FilesSpecified = true, + FreeClusters = cpmStat.FreeBlocks, FreeClustersSpecified = true, - Type = "CP/M filesystem" + Type = "CP/M filesystem" }; if(labelCreationDate != null) { - XmlFsType.CreationDate = DateHandlers.CpmToDateTime(labelCreationDate); + XmlFsType.CreationDate = DateHandlers.CpmToDateTime(labelCreationDate); XmlFsType.CreationDateSpecified = true; } + if(labelUpdateDate != null) { - XmlFsType.ModificationDate = DateHandlers.CpmToDateTime(labelUpdateDate); + XmlFsType.ModificationDate = DateHandlers.CpmToDateTime(labelUpdateDate); XmlFsType.ModificationDateSpecified = true; } + if(!string.IsNullOrEmpty(label)) XmlFsType.VolumeName = label; mounted = true; @@ -698,17 +706,17 @@ namespace DiscImageChef.Filesystems.CPM public Errno Unmount() { - mounted = false; - definitions = null; - cpmFound = false; - workingDefinition = null; - dpb = null; - sectorMask = null; - label = null; + mounted = false; + definitions = null; + cpmFound = false; + workingDefinition = null; + dpb = null; + sectorMask = null; + label = null; thirdPartyTimestamps = false; - standardTimestamps = false; - labelCreationDate = null; - labelUpdateDate = null; + standardTimestamps = false; + labelCreationDate = null; + labelUpdateDate = null; return Errno.NoError; } } diff --git a/DiscImageChef.Filesystems/IReadOnlyFilesystem.cs b/DiscImageChef.Filesystems/IReadOnlyFilesystem.cs index 9d067b44b..4b261b4d8 100644 --- a/DiscImageChef.Filesystems/IReadOnlyFilesystem.cs +++ b/DiscImageChef.Filesystems/IReadOnlyFilesystem.cs @@ -31,12 +31,10 @@ // Copyright © 2011-2018 Natalia Portillo // ****************************************************************************/ -using System; using System.Collections.Generic; using System.Text; using DiscImageChef.CommonTypes; using DiscImageChef.DiscImages; -using Schemas; namespace DiscImageChef.Filesystems { @@ -52,13 +50,13 @@ namespace DiscImageChef.Filesystems /// /// /// Which encoding to use for this filesystem. - /// If true enable debug. - Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug); + /// Dictionary of key=value pairs containing options to pass to the filesystem + Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, + Dictionary options); /// /// Frees all internal structures created by - /// + /// /// Errno Unmount(); diff --git a/DiscImageChef.Filesystems/LisaFS/LisaFS.cs b/DiscImageChef.Filesystems/LisaFS/LisaFS.cs index 31594c739..fe6014765 100644 --- a/DiscImageChef.Filesystems/LisaFS/LisaFS.cs +++ b/DiscImageChef.Filesystems/LisaFS/LisaFS.cs @@ -42,35 +42,40 @@ namespace DiscImageChef.Filesystems.LisaFS // Variable names from Lisa API public partial class LisaFS : IReadOnlyFilesystem { - bool debug; + bool debug; IMediaImage device; - int devTagSize; + int devTagSize; - MDDF mddf; - bool mounted; + MDDF mddf; + bool mounted; SRecord[] srecords; - ulong volumePrefix; + ulong volumePrefix; - public string Name => "Apple Lisa File System"; - public Guid Id => new Guid("7E6034D1-D823-4248-A54D-239742B28391"); - public Encoding Encoding { get; private set; } + public string Name => "Apple Lisa File System"; + public Guid Id => new Guid("7E6034D1-D823-4248-A54D-239742B28391"); + public Encoding Encoding { get; private set; } public FileSystemType XmlFsType { get; private set; } + static Dictionary GetDefaultOptions() + { + return new Dictionary {{"debug", false.ToString()}}; + } + #region Caches /// Caches Extents Files Dictionary extentCache; /// Caches system files - Dictionary systemFileCache; + Dictionary systemFileCache; /// Caches user files files - Dictionary fileCache; + Dictionary fileCache; /// Caches catalogs - List catalogCache; + List catalogCache; /// Caches file size - Dictionary fileSizeCache; + Dictionary fileSizeCache; /// Lists Extents Files already printed in debug mode to not repeat them - List printedExtents; + List printedExtents; /// Caches the creation times for subdirectories as to not have to traverse the Catalog File on each stat - Dictionary directoryDtcCache; + Dictionary directoryDtcCache; #endregion Caches } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/LisaFS/Super.cs b/DiscImageChef.Filesystems/LisaFS/Super.cs index 07ed2ff65..7ed7fea25 100644 --- a/DiscImageChef.Filesystems/LisaFS/Super.cs +++ b/DiscImageChef.Filesystems/LisaFS/Super.cs @@ -47,11 +47,12 @@ namespace DiscImageChef.Filesystems.LisaFS /// /// Mounts an Apple Lisa filesystem /// - public Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) + public Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, + Dictionary options) { try { - device = imagePlugin; + device = imagePlugin; Encoding = new LisaRoman(); // Lisa OS is unable to work on disks without tags. @@ -91,96 +92,101 @@ namespace DiscImageChef.Filesystems.LisaFS devTagSize = device.ReadSectorTag(i, SectorTagType.AppleSectorTag).Length; - byte[] sector = device.ReadSector(i); - mddf = new MDDF(); + byte[] sector = device.ReadSector(i); + mddf = new MDDF(); byte[] pString = new byte[33]; - uint lisaTime; + uint lisaTime; mddf.fsversion = BigEndianBitConverter.ToUInt16(sector, 0x00); - mddf.volid = BigEndianBitConverter.ToUInt64(sector, 0x02); - mddf.volnum = BigEndianBitConverter.ToUInt16(sector, 0x0A); + mddf.volid = BigEndianBitConverter.ToUInt64(sector, 0x02); + mddf.volnum = BigEndianBitConverter.ToUInt16(sector, 0x0A); Array.Copy(sector, 0x0C, pString, 0, 33); - mddf.volname = StringHandlers.PascalToString(pString, Encoding); + mddf.volname = StringHandlers.PascalToString(pString, Encoding); mddf.unknown1 = sector[0x2D]; Array.Copy(sector, 0x2E, pString, 0, 33); // Prevent garbage - mddf.password = pString[0] <= 32 ? StringHandlers.PascalToString(pString, Encoding) : ""; - mddf.unknown2 = sector[0x4F]; - mddf.machine_id = BigEndianBitConverter.ToUInt32(sector, 0x50); - mddf.master_copy_id = BigEndianBitConverter.ToUInt32(sector, 0x54); - lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x58); - mddf.dtvc = DateHandlers.LisaToDateTime(lisaTime); - lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x5C); - mddf.dtcc = DateHandlers.LisaToDateTime(lisaTime); - lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x60); - mddf.dtvb = DateHandlers.LisaToDateTime(lisaTime); - lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x64); - mddf.dtvs = DateHandlers.LisaToDateTime(lisaTime); - mddf.unknown3 = BigEndianBitConverter.ToUInt32(sector, 0x68); - mddf.mddf_block = BigEndianBitConverter.ToUInt32(sector, 0x6C); - mddf.volsize_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x70); + mddf.password = + pString[0] <= 32 ? StringHandlers.PascalToString(pString, Encoding) : ""; + mddf.unknown2 = sector[0x4F]; + mddf.machine_id = BigEndianBitConverter.ToUInt32(sector, 0x50); + mddf.master_copy_id = BigEndianBitConverter.ToUInt32(sector, 0x54); + lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x58); + mddf.dtvc = DateHandlers.LisaToDateTime(lisaTime); + lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x5C); + mddf.dtcc = DateHandlers.LisaToDateTime(lisaTime); + lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x60); + mddf.dtvb = DateHandlers.LisaToDateTime(lisaTime); + lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x64); + mddf.dtvs = DateHandlers.LisaToDateTime(lisaTime); + mddf.unknown3 = BigEndianBitConverter.ToUInt32(sector, 0x68); + mddf.mddf_block = BigEndianBitConverter.ToUInt32(sector, 0x6C); + mddf.volsize_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x70); mddf.volsize_minus_mddf_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x74); - mddf.vol_size = BigEndianBitConverter.ToUInt32(sector, 0x78); - mddf.blocksize = BigEndianBitConverter.ToUInt16(sector, 0x7C); - mddf.datasize = BigEndianBitConverter.ToUInt16(sector, 0x7E); - mddf.unknown4 = BigEndianBitConverter.ToUInt16(sector, 0x80); - mddf.unknown5 = BigEndianBitConverter.ToUInt32(sector, 0x82); - mddf.unknown6 = BigEndianBitConverter.ToUInt32(sector, 0x86); - mddf.clustersize = BigEndianBitConverter.ToUInt16(sector, 0x8A); - mddf.fs_size = BigEndianBitConverter.ToUInt32(sector, 0x8C); - mddf.unknown7 = BigEndianBitConverter.ToUInt32(sector, 0x90); - mddf.srec_ptr = BigEndianBitConverter.ToUInt32(sector, 0x94); - mddf.unknown9 = BigEndianBitConverter.ToUInt16(sector, 0x98); - mddf.srec_len = BigEndianBitConverter.ToUInt16(sector, 0x9A); - mddf.unknown10 = BigEndianBitConverter.ToUInt32(sector, 0x9C); - mddf.unknown11 = BigEndianBitConverter.ToUInt32(sector, 0xA0); - mddf.unknown12 = BigEndianBitConverter.ToUInt32(sector, 0xA4); - mddf.unknown13 = BigEndianBitConverter.ToUInt32(sector, 0xA8); - mddf.unknown14 = BigEndianBitConverter.ToUInt32(sector, 0xAC); - mddf.filecount = BigEndianBitConverter.ToUInt16(sector, 0xB0); - mddf.unknown15 = BigEndianBitConverter.ToUInt32(sector, 0xB2); - mddf.unknown16 = BigEndianBitConverter.ToUInt32(sector, 0xB6); - mddf.freecount = BigEndianBitConverter.ToUInt32(sector, 0xBA); - mddf.unknown17 = BigEndianBitConverter.ToUInt16(sector, 0xBE); - mddf.unknown18 = BigEndianBitConverter.ToUInt32(sector, 0xC0); - mddf.overmount_stamp = BigEndianBitConverter.ToUInt64(sector, 0xC4); - mddf.serialization = BigEndianBitConverter.ToUInt32(sector, 0xCC); - mddf.unknown19 = BigEndianBitConverter.ToUInt32(sector, 0xD0); - mddf.unknown_timestamp = BigEndianBitConverter.ToUInt32(sector, 0xD4); - mddf.unknown20 = BigEndianBitConverter.ToUInt32(sector, 0xD8); - mddf.unknown21 = BigEndianBitConverter.ToUInt32(sector, 0xDC); - mddf.unknown22 = BigEndianBitConverter.ToUInt32(sector, 0xE0); - mddf.unknown23 = BigEndianBitConverter.ToUInt32(sector, 0xE4); - mddf.unknown24 = BigEndianBitConverter.ToUInt32(sector, 0xE8); - mddf.unknown25 = BigEndianBitConverter.ToUInt32(sector, 0xEC); - mddf.unknown26 = BigEndianBitConverter.ToUInt32(sector, 0xF0); - mddf.unknown27 = BigEndianBitConverter.ToUInt32(sector, 0xF4); - mddf.unknown28 = BigEndianBitConverter.ToUInt32(sector, 0xF8); - mddf.unknown29 = BigEndianBitConverter.ToUInt32(sector, 0xFC); - mddf.unknown30 = BigEndianBitConverter.ToUInt32(sector, 0x100); - mddf.unknown31 = BigEndianBitConverter.ToUInt32(sector, 0x104); - mddf.unknown32 = BigEndianBitConverter.ToUInt32(sector, 0x108); - mddf.unknown33 = BigEndianBitConverter.ToUInt32(sector, 0x10C); - mddf.unknown34 = BigEndianBitConverter.ToUInt32(sector, 0x110); - mddf.unknown35 = BigEndianBitConverter.ToUInt32(sector, 0x114); - mddf.backup_volid = BigEndianBitConverter.ToUInt64(sector, 0x118); - mddf.label_size = BigEndianBitConverter.ToUInt16(sector, 0x120); - mddf.fs_overhead = BigEndianBitConverter.ToUInt16(sector, 0x122); - mddf.result_scavenge = BigEndianBitConverter.ToUInt16(sector, 0x124); - mddf.boot_code = BigEndianBitConverter.ToUInt16(sector, 0x126); - mddf.boot_environ = BigEndianBitConverter.ToUInt16(sector, 0x6C); - mddf.unknown36 = BigEndianBitConverter.ToUInt32(sector, 0x12A); - mddf.unknown37 = BigEndianBitConverter.ToUInt32(sector, 0x12E); - mddf.unknown38 = BigEndianBitConverter.ToUInt32(sector, 0x132); - mddf.vol_sequence = BigEndianBitConverter.ToUInt16(sector, 0x136); - mddf.vol_left_mounted = sector[0x138]; + mddf.vol_size = BigEndianBitConverter.ToUInt32(sector, 0x78); + mddf.blocksize = BigEndianBitConverter.ToUInt16(sector, 0x7C); + mddf.datasize = BigEndianBitConverter.ToUInt16(sector, 0x7E); + mddf.unknown4 = BigEndianBitConverter.ToUInt16(sector, 0x80); + mddf.unknown5 = BigEndianBitConverter.ToUInt32(sector, 0x82); + mddf.unknown6 = BigEndianBitConverter.ToUInt32(sector, 0x86); + mddf.clustersize = BigEndianBitConverter.ToUInt16(sector, 0x8A); + mddf.fs_size = BigEndianBitConverter.ToUInt32(sector, 0x8C); + mddf.unknown7 = BigEndianBitConverter.ToUInt32(sector, 0x90); + mddf.srec_ptr = BigEndianBitConverter.ToUInt32(sector, 0x94); + mddf.unknown9 = BigEndianBitConverter.ToUInt16(sector, 0x98); + mddf.srec_len = BigEndianBitConverter.ToUInt16(sector, 0x9A); + mddf.unknown10 = BigEndianBitConverter.ToUInt32(sector, 0x9C); + mddf.unknown11 = BigEndianBitConverter.ToUInt32(sector, 0xA0); + mddf.unknown12 = BigEndianBitConverter.ToUInt32(sector, 0xA4); + mddf.unknown13 = BigEndianBitConverter.ToUInt32(sector, 0xA8); + mddf.unknown14 = BigEndianBitConverter.ToUInt32(sector, 0xAC); + mddf.filecount = BigEndianBitConverter.ToUInt16(sector, 0xB0); + mddf.unknown15 = BigEndianBitConverter.ToUInt32(sector, 0xB2); + mddf.unknown16 = BigEndianBitConverter.ToUInt32(sector, 0xB6); + mddf.freecount = BigEndianBitConverter.ToUInt32(sector, 0xBA); + mddf.unknown17 = BigEndianBitConverter.ToUInt16(sector, 0xBE); + mddf.unknown18 = BigEndianBitConverter.ToUInt32(sector, 0xC0); + mddf.overmount_stamp = BigEndianBitConverter.ToUInt64(sector, 0xC4); + mddf.serialization = BigEndianBitConverter.ToUInt32(sector, 0xCC); + mddf.unknown19 = BigEndianBitConverter.ToUInt32(sector, 0xD0); + mddf.unknown_timestamp = BigEndianBitConverter.ToUInt32(sector, 0xD4); + mddf.unknown20 = BigEndianBitConverter.ToUInt32(sector, 0xD8); + mddf.unknown21 = BigEndianBitConverter.ToUInt32(sector, 0xDC); + mddf.unknown22 = BigEndianBitConverter.ToUInt32(sector, 0xE0); + mddf.unknown23 = BigEndianBitConverter.ToUInt32(sector, 0xE4); + mddf.unknown24 = BigEndianBitConverter.ToUInt32(sector, 0xE8); + mddf.unknown25 = BigEndianBitConverter.ToUInt32(sector, 0xEC); + mddf.unknown26 = BigEndianBitConverter.ToUInt32(sector, 0xF0); + mddf.unknown27 = BigEndianBitConverter.ToUInt32(sector, 0xF4); + mddf.unknown28 = BigEndianBitConverter.ToUInt32(sector, 0xF8); + mddf.unknown29 = BigEndianBitConverter.ToUInt32(sector, 0xFC); + mddf.unknown30 = BigEndianBitConverter.ToUInt32(sector, 0x100); + mddf.unknown31 = BigEndianBitConverter.ToUInt32(sector, 0x104); + mddf.unknown32 = BigEndianBitConverter.ToUInt32(sector, 0x108); + mddf.unknown33 = BigEndianBitConverter.ToUInt32(sector, 0x10C); + mddf.unknown34 = BigEndianBitConverter.ToUInt32(sector, 0x110); + mddf.unknown35 = BigEndianBitConverter.ToUInt32(sector, 0x114); + mddf.backup_volid = BigEndianBitConverter.ToUInt64(sector, 0x118); + mddf.label_size = BigEndianBitConverter.ToUInt16(sector, 0x120); + mddf.fs_overhead = BigEndianBitConverter.ToUInt16(sector, 0x122); + mddf.result_scavenge = BigEndianBitConverter.ToUInt16(sector, 0x124); + mddf.boot_code = BigEndianBitConverter.ToUInt16(sector, 0x126); + mddf.boot_environ = BigEndianBitConverter.ToUInt16(sector, 0x6C); + mddf.unknown36 = BigEndianBitConverter.ToUInt32(sector, 0x12A); + mddf.unknown37 = BigEndianBitConverter.ToUInt32(sector, 0x12E); + mddf.unknown38 = BigEndianBitConverter.ToUInt32(sector, 0x132); + 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.Info.Sectors || - mddf.vol_size - 1 != mddf.volsize_minus_one || - mddf.vol_size - i - 1 != mddf.volsize_minus_mddf_minus_one - volumePrefix || - mddf.datasize > mddf.blocksize || mddf.blocksize < device.Info.SectorSize || - mddf.datasize != device.Info.SectorSize) + if(mddf.mddf_block != i - volumePrefix || + mddf.vol_size > device.Info.Sectors || + mddf.vol_size - 1 != + mddf.volsize_minus_one || + mddf.vol_size - i - 1 != + mddf.volsize_minus_mddf_minus_one - volumePrefix || + mddf.datasize > + mddf.blocksize || mddf.blocksize < device.Info.SectorSize || + mddf.datasize != device.Info.SectorSize) { DicConsole.DebugWriteLine("LisaFS plugin", "Incorrect MDDF found"); return Errno.InvalidArgument; @@ -204,14 +210,15 @@ namespace DiscImageChef.Filesystems.LisaFS } // Initialize caches - extentCache = new Dictionary(); + extentCache = new Dictionary(); systemFileCache = new Dictionary(); - fileCache = new Dictionary(); + fileCache = new Dictionary(); //catalogCache = new Dictionary>(); fileSizeCache = new Dictionary(); - mounted = true; - this.debug = debug; + mounted = true; + if(options == null) options = GetDefaultOptions(); + if(options.TryGetValue("debug", out string debugString)) bool.TryParse(debugString, out debug); if(debug) printedExtents = new List(); @@ -284,24 +291,26 @@ namespace DiscImageChef.Filesystems.LisaFS XmlFsType = new FileSystemType(); if(DateTime.Compare(mddf.dtvb, DateHandlers.LisaToDateTime(0)) > 0) { - XmlFsType.BackupDate = mddf.dtvb; + XmlFsType.BackupDate = mddf.dtvb; XmlFsType.BackupDateSpecified = true; } - XmlFsType.Clusters = mddf.vol_size; + + XmlFsType.Clusters = mddf.vol_size; XmlFsType.ClusterSize = mddf.clustersize * mddf.datasize; if(DateTime.Compare(mddf.dtvc, DateHandlers.LisaToDateTime(0)) > 0) { - XmlFsType.CreationDate = mddf.dtvc; + XmlFsType.CreationDate = mddf.dtvc; XmlFsType.CreationDateSpecified = true; } - XmlFsType.Dirty = mddf.vol_left_mounted != 0; - XmlFsType.Files = mddf.filecount; - XmlFsType.FilesSpecified = true; - XmlFsType.FreeClusters = mddf.freecount; + + XmlFsType.Dirty = mddf.vol_left_mounted != 0; + XmlFsType.Files = mddf.filecount; + XmlFsType.FilesSpecified = true; + XmlFsType.FreeClusters = mddf.freecount; XmlFsType.FreeClustersSpecified = true; - XmlFsType.Type = "LisaFS"; - XmlFsType.VolumeName = mddf.volname; - XmlFsType.VolumeSerial = $"{mddf.volid:X16}"; + XmlFsType.Type = "LisaFS"; + XmlFsType.VolumeName = mddf.volname; + XmlFsType.VolumeSerial = $"{mddf.volid:X16}"; return Errno.NoError; } @@ -321,17 +330,17 @@ namespace DiscImageChef.Filesystems.LisaFS /// public Errno Unmount() { - mounted = false; - extentCache = null; + mounted = false; + extentCache = null; systemFileCache = null; - fileCache = null; - catalogCache = null; - fileSizeCache = null; - printedExtents = null; - mddf = new MDDF(); - volumePrefix = 0; - devTagSize = 0; - srecords = null; + fileCache = null; + catalogCache = null; + fileSizeCache = null; + printedExtents = null; + mddf = new MDDF(); + volumePrefix = 0; + devTagSize = 0; + srecords = null; return Errno.NoError; } @@ -347,12 +356,12 @@ namespace DiscImageChef.Filesystems.LisaFS stat = new FileSystemInfo { - Blocks = mddf.vol_size, + Blocks = mddf.vol_size, FilenameLength = (ushort)E_NAME, - Files = mddf.filecount, - FreeBlocks = mddf.freecount, - Id = {Serial64 = mddf.volid, IsLong = true}, - PluginId = Id + Files = mddf.filecount, + FreeBlocks = mddf.freecount, + Id = {Serial64 = mddf.volid, IsLong = true}, + PluginId = Id }; stat.FreeFiles = FILEID_MAX - stat.Files; switch(mddf.fsversion) diff --git a/DiscImageChef.Filesystems/UCSDPascal/Super.cs b/DiscImageChef.Filesystems/UCSDPascal/Super.cs index fe5c01092..2e2f70243 100644 --- a/DiscImageChef.Filesystems/UCSDPascal/Super.cs +++ b/DiscImageChef.Filesystems/UCSDPascal/Super.cs @@ -43,11 +43,13 @@ namespace DiscImageChef.Filesystems.UCSDPascal // Information from Call-A.P.P.L.E. Pascal Disk Directory Structure public partial class PascalPlugin { - public Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) + public Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, + Dictionary options) { - device = imagePlugin; - Encoding = encoding ?? new Apple2(); - this.debug = debug; + device = imagePlugin; + Encoding = encoding ?? new Apple2(); + if(options == null) options = GetDefaultOptions(); + if(options.TryGetValue("debug", out string debugString)) bool.TryParse(debugString, out debug); if(device.Info.Sectors < 3) return Errno.InvalidArgument; // Blocks 0 and 1 are boot code @@ -55,38 +57,41 @@ namespace DiscImageChef.Filesystems.UCSDPascal BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; - mountedVolEntry.firstBlock = BigEndianBitConverter.ToInt16(catalogBlocks, 0x00); - mountedVolEntry.lastBlock = BigEndianBitConverter.ToInt16(catalogBlocks, 0x02); - mountedVolEntry.entryType = (PascalFileKind)BigEndianBitConverter.ToInt16(catalogBlocks, 0x04); + mountedVolEntry.firstBlock = BigEndianBitConverter.ToInt16(catalogBlocks, 0x00); + mountedVolEntry.lastBlock = BigEndianBitConverter.ToInt16(catalogBlocks, 0x02); + mountedVolEntry.entryType = (PascalFileKind)BigEndianBitConverter.ToInt16(catalogBlocks, 0x04); mountedVolEntry.volumeName = new byte[8]; Array.Copy(catalogBlocks, 0x06, mountedVolEntry.volumeName, 0, 8); - mountedVolEntry.blocks = BigEndianBitConverter.ToInt16(catalogBlocks, 0x0E); - mountedVolEntry.files = BigEndianBitConverter.ToInt16(catalogBlocks, 0x10); - mountedVolEntry.dummy = BigEndianBitConverter.ToInt16(catalogBlocks, 0x12); + mountedVolEntry.blocks = BigEndianBitConverter.ToInt16(catalogBlocks, 0x0E); + mountedVolEntry.files = BigEndianBitConverter.ToInt16(catalogBlocks, 0x10); + mountedVolEntry.dummy = BigEndianBitConverter.ToInt16(catalogBlocks, 0x12); mountedVolEntry.lastBoot = BigEndianBitConverter.ToInt16(catalogBlocks, 0x14); - mountedVolEntry.tail = BigEndianBitConverter.ToInt32(catalogBlocks, 0x16); + mountedVolEntry.tail = BigEndianBitConverter.ToInt32(catalogBlocks, 0x16); - if(mountedVolEntry.firstBlock != 0 || mountedVolEntry.lastBlock <= mountedVolEntry.firstBlock || - (ulong)mountedVolEntry.lastBlock > device.Info.Sectors - 2 || - mountedVolEntry.entryType != PascalFileKind.Volume && - mountedVolEntry.entryType != PascalFileKind.Secure || mountedVolEntry.volumeName[0] > 7 || - mountedVolEntry.blocks < 0 || (ulong)mountedVolEntry.blocks != device.Info.Sectors || - mountedVolEntry.files < 0) return Errno.InvalidArgument; + if(mountedVolEntry.firstBlock != 0 || + mountedVolEntry.lastBlock <= mountedVolEntry.firstBlock || + (ulong)mountedVolEntry.lastBlock > device.Info.Sectors - 2 || + mountedVolEntry.entryType != PascalFileKind.Volume && + mountedVolEntry.entryType != PascalFileKind.Secure || + mountedVolEntry.volumeName[0] > 7 || + mountedVolEntry.blocks < 0 || + (ulong)mountedVolEntry.blocks != device.Info.Sectors || + mountedVolEntry.files < 0) return Errno.InvalidArgument; catalogBlocks = device.ReadSectors(2, (uint)(mountedVolEntry.lastBlock - mountedVolEntry.firstBlock - 2)); - int offset = 26; + int offset = 26; fileEntries = new List(); while(offset + 26 < catalogBlocks.Length) { PascalFileEntry entry = new PascalFileEntry { - filename = new byte[16], - firstBlock = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x00), - lastBlock = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x02), - entryType = (PascalFileKind)BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x04), - lastBytes = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x16), - mtime = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x18) + filename = new byte[16], + firstBlock = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x00), + lastBlock = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x02), + entryType = (PascalFileKind)BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x04), + lastBytes = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x16), + mtime = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x18) }; Array.Copy(catalogBlocks, offset + 0x06, entry.filename, 0, 16); @@ -99,13 +104,13 @@ namespace DiscImageChef.Filesystems.UCSDPascal XmlFsType = new FileSystemType { - Bootable = !ArrayHelpers.ArrayIsNullOrEmpty(bootBlocks), - Clusters = mountedVolEntry.blocks, - ClusterSize = (int)device.Info.SectorSize, - Files = mountedVolEntry.files, + Bootable = !ArrayHelpers.ArrayIsNullOrEmpty(bootBlocks), + Clusters = mountedVolEntry.blocks, + ClusterSize = (int)device.Info.SectorSize, + Files = mountedVolEntry.files, FilesSpecified = true, - Type = "UCSD Pascal", - VolumeName = StringHandlers.PascalToString(mountedVolEntry.volumeName, Encoding) + Type = "UCSD Pascal", + VolumeName = StringHandlers.PascalToString(mountedVolEntry.volumeName, Encoding) }; mounted = true; @@ -115,7 +120,7 @@ namespace DiscImageChef.Filesystems.UCSDPascal public Errno Unmount() { - mounted = false; + mounted = false; fileEntries = null; return Errno.NoError; } @@ -124,15 +129,16 @@ namespace DiscImageChef.Filesystems.UCSDPascal { stat = new FileSystemInfo { - Blocks = mountedVolEntry.blocks, + Blocks = mountedVolEntry.blocks, FilenameLength = 16, - Files = (ulong)mountedVolEntry.files, - FreeBlocks = 0, - PluginId = Id, - Type = "UCSD Pascal" + Files = (ulong)mountedVolEntry.files, + FreeBlocks = 0, + PluginId = Id, + Type = "UCSD Pascal" }; stat.FreeBlocks = mountedVolEntry.blocks - (mountedVolEntry.lastBlock - mountedVolEntry.firstBlock); + foreach(PascalFileEntry entry in fileEntries) stat.FreeBlocks -= entry.lastBlock - entry.firstBlock; return Errno.NotImplemented; diff --git a/DiscImageChef.Filesystems/UCSDPascal/UCSDPascal.cs b/DiscImageChef.Filesystems/UCSDPascal/UCSDPascal.cs index ae3a551fa..24cdab8fc 100644 --- a/DiscImageChef.Filesystems/UCSDPascal/UCSDPascal.cs +++ b/DiscImageChef.Filesystems/UCSDPascal/UCSDPascal.cs @@ -44,17 +44,17 @@ namespace DiscImageChef.Filesystems.UCSDPascal byte[] bootBlocks; byte[] catalogBlocks; - bool debug; - IMediaImage device; + bool debug; + IMediaImage device; List fileEntries; - bool mounted; + bool mounted; PascalVolumeEntry mountedVolEntry; public FileSystemType XmlFsType { get; private set; } - public string Name => "U.C.S.D. Pascal filesystem"; - public Guid Id => new Guid("B0AC2CB5-72AA-473A-9200-270B5A2C2D53"); - public Encoding Encoding { get; private set; } + public string Name => "U.C.S.D. Pascal filesystem"; + public Guid Id => new Guid("B0AC2CB5-72AA-473A-9200-270B5A2C2D53"); + public Encoding Encoding { get; private set; } public Errno ListXAttr(string path, out List xattrs) { @@ -72,5 +72,10 @@ namespace DiscImageChef.Filesystems.UCSDPascal dest = null; return Errno.NotSupported; } + + static Dictionary GetDefaultOptions() + { + return new Dictionary {{"debug", false.ToString()}}; + } } } \ No newline at end of file