From 7e0dc0a2517cca376ba92db92ed757318dd66097 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Mon, 19 Dec 2022 00:26:55 +0000 Subject: [PATCH] Add OpenFile and CloseFile methods to IReadOnlyFilesystem. --- Aaru.CommonTypes | 2 +- Aaru.Filesystems/AppleDOS/File.cs | 70 ++++++++++++++++++++ Aaru.Filesystems/AppleDOS/Structs.cs | 12 ++++ Aaru.Filesystems/AppleMFS/File.cs | 64 ++++++++++++++++++ Aaru.Filesystems/AppleMFS/Structs.cs | 12 ++++ Aaru.Filesystems/CPM/File.cs | 45 +++++++++++++ Aaru.Filesystems/CPM/Structs.cs | 12 ++++ Aaru.Filesystems/FAT/File.cs | 48 ++++++++++++++ Aaru.Filesystems/FAT/Structs.cs | 13 ++++ Aaru.Filesystems/FATX/File.cs | 45 +++++++++++++ Aaru.Filesystems/FATX/Structs.cs | 12 ++++ Aaru.Filesystems/ISO9660/File.cs | 51 ++++++++++++-- Aaru.Filesystems/ISO9660/Structs/Internal.cs | 12 ++++ Aaru.Filesystems/LisaFS/File.cs | 45 +++++++++++++ Aaru.Filesystems/LisaFS/Structs.cs | 13 ++++ Aaru.Filesystems/Opera/File.cs | 44 ++++++++++++ Aaru.Filesystems/Opera/Structs.cs | 12 ++++ Aaru.Filesystems/UCSDPascal/File.cs | 66 ++++++++++++++++++ Aaru.Filesystems/UCSDPascal/Structs.cs | 12 ++++ 19 files changed, 584 insertions(+), 6 deletions(-) diff --git a/Aaru.CommonTypes b/Aaru.CommonTypes index 2a4635bb3..685f2456a 160000 --- a/Aaru.CommonTypes +++ b/Aaru.CommonTypes @@ -1 +1 @@ -Subproject commit 2a4635bb3879342da0cb50a3ebd33682c3f6a9c2 +Subproject commit 685f2456a594df2771ffd3216a499b90aaed7f21 diff --git a/Aaru.Filesystems/AppleDOS/File.cs b/Aaru.Filesystems/AppleDOS/File.cs index 8fa7bfe87..2718449c5 100644 --- a/Aaru.Filesystems/AppleDOS/File.cs +++ b/Aaru.Filesystems/AppleDOS/File.cs @@ -31,6 +31,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using Aaru.CommonTypes.Enums; +using Aaru.CommonTypes.Interfaces; using Aaru.CommonTypes.Structs; using Aaru.Helpers; using FileAttributes = Aaru.CommonTypes.Structs.FileAttributes; @@ -74,6 +75,75 @@ public sealed partial class AppleDOS return ErrorNumber.NoError; } + public ErrorNumber OpenFile(string path, out IFileNode node) + { + node = null; + + if(!_mounted) + return ErrorNumber.AccessDenied; + + string[] pathElements = path.Split(new[] + { + '/' + }, StringSplitOptions.RemoveEmptyEntries); + + if(pathElements.Length != 1) + return ErrorNumber.NotSupported; + + byte[] file; + string filename = pathElements[0].ToUpperInvariant(); + + if(filename.Length > 30) + return ErrorNumber.NameTooLong; + + if(_debug && (string.Compare(path, "$", StringComparison.InvariantCulture) == 0 || + string.Compare(path, "$Boot", StringComparison.InvariantCulture) == 0 || + string.Compare(path, "$Vtoc", StringComparison.InvariantCulture) == 0)) + if(string.Compare(path, "$", StringComparison.InvariantCulture) == 0) + file = _catalogBlocks; + else if(string.Compare(path, "$Vtoc", StringComparison.InvariantCulture) == 0) + file = _vtocBlocks; + else + file = _bootBlocks; + else + { + if(!_fileCache.TryGetValue(filename, out file)) + { + ErrorNumber error = CacheFile(filename); + + if(error != ErrorNumber.NoError) + return error; + + if(!_fileCache.TryGetValue(filename, out file)) + return ErrorNumber.InvalidArgument; + } + } + + node = new AppleDosFileNode + { + Path = path, + Length = file.Length, + Offset = 0, + _cache = file + }; + + return ErrorNumber.NoError; + } + + /// + public ErrorNumber CloseFile(IFileNode node) + { + if(!_mounted) + return ErrorNumber.AccessDenied; + + if(node is not AppleDosFileNode mynode) + return ErrorNumber.InvalidArgument; + + mynode._cache = null; + + return ErrorNumber.NoError; + } + /// public ErrorNumber Read(string path, long offset, long size, ref byte[] buf) { diff --git a/Aaru.Filesystems/AppleDOS/Structs.cs b/Aaru.Filesystems/AppleDOS/Structs.cs index 20c1e971a..f3973ad88 100644 --- a/Aaru.Filesystems/AppleDOS/Structs.cs +++ b/Aaru.Filesystems/AppleDOS/Structs.cs @@ -27,6 +27,7 @@ // ****************************************************************************/ using System.Runtime.InteropServices; +using Aaru.CommonTypes.Interfaces; namespace Aaru.Filesystems; @@ -102,4 +103,15 @@ public sealed partial class AppleDOS public readonly byte track; public readonly byte sector; } + + sealed class AppleDosFileNode : IFileNode + { + internal byte[] _cache; + /// + public string Path { get; init; } + /// + public long Length { get; init; } + /// + public long Offset { get; init; } + } } \ No newline at end of file diff --git a/Aaru.Filesystems/AppleMFS/File.cs b/Aaru.Filesystems/AppleMFS/File.cs index 5be9c219f..2a3f2e943 100644 --- a/Aaru.Filesystems/AppleMFS/File.cs +++ b/Aaru.Filesystems/AppleMFS/File.cs @@ -29,6 +29,7 @@ using System; using System.IO; using Aaru.CommonTypes.Enums; +using Aaru.CommonTypes.Interfaces; using Aaru.CommonTypes.Structs; using Aaru.Console; using Aaru.Helpers; @@ -153,6 +154,69 @@ public sealed partial class AppleMFS return ErrorNumber.NoError; } + /// + public ErrorNumber OpenFile(string path, out IFileNode node) + { + node = null; + + if(!_mounted) + return ErrorNumber.AccessDenied; + + byte[] file; + ErrorNumber error = ErrorNumber.NoError; + + switch(_debug) + { + case true when string.Compare(path, "$", StringComparison.InvariantCulture) == 0: + file = _directoryBlocks; + + break; + case true when string.Compare(path, "$Boot", StringComparison.InvariantCulture) == 0 && _bootBlocks != null: + file = _bootBlocks; + + break; + case true when string.Compare(path, "$Bitmap", StringComparison.InvariantCulture) == 0: + file = _blockMapBytes; + + break; + case true when string.Compare(path, "$MDB", StringComparison.InvariantCulture) == 0: + file = _mdbBlocks; + + break; + default: + error = ReadFile(path, out file, false, false); + + break; + } + + if(error != ErrorNumber.NoError) + return error; + + node = new AppleMfsFileNode + { + Path = path, + Length = file.Length, + Offset = 0, + _cache = file + }; + + return ErrorNumber.NoError; + } + + /// + public ErrorNumber CloseFile(IFileNode node) + { + if(!_mounted) + return ErrorNumber.AccessDenied; + + if(node is not AppleMfsFileNode mynode) + return ErrorNumber.InvalidArgument; + + mynode._cache = null; + + return ErrorNumber.NoError; + } + /// public ErrorNumber Read(string path, long offset, long size, ref byte[] buf) { diff --git a/Aaru.Filesystems/AppleMFS/Structs.cs b/Aaru.Filesystems/AppleMFS/Structs.cs index b0e48b0e4..ece2b59a3 100644 --- a/Aaru.Filesystems/AppleMFS/Structs.cs +++ b/Aaru.Filesystems/AppleMFS/Structs.cs @@ -28,6 +28,7 @@ using System; using System.Diagnostics.CodeAnalysis; +using Aaru.CommonTypes.Interfaces; #pragma warning disable 169 @@ -107,4 +108,15 @@ public sealed partial class AppleMFS /// 0x32, file name prefixed with length public byte[] flNam; } + + sealed class AppleMfsFileNode : IFileNode + { + internal byte[] _cache; + /// + public string Path { get; init; } + /// + public long Length { get; init; } + /// + public long Offset { get; init; } + } } \ No newline at end of file diff --git a/Aaru.Filesystems/CPM/File.cs b/Aaru.Filesystems/CPM/File.cs index f872d0347..5cb3b7529 100644 --- a/Aaru.Filesystems/CPM/File.cs +++ b/Aaru.Filesystems/CPM/File.cs @@ -28,6 +28,7 @@ using System; using Aaru.CommonTypes.Enums; +using Aaru.CommonTypes.Interfaces; using Aaru.CommonTypes.Structs; using Aaru.Helpers; @@ -77,6 +78,50 @@ public sealed partial class CPM return !_mounted ? ErrorNumber.AccessDenied : ErrorNumber.NotImplemented; } + /// + public ErrorNumber OpenFile(string path, out IFileNode node) + { + node = null; + + if(!_mounted) + return ErrorNumber.AccessDenied; + + string[] pathElements = path.Split(new[] + { + '/' + }, StringSplitOptions.RemoveEmptyEntries); + + if(pathElements.Length != 1) + return ErrorNumber.NotSupported; + + if(!_fileCache.TryGetValue(pathElements[0].ToUpperInvariant(), out byte[] file)) + return ErrorNumber.NoSuchFile; + + node = new CpmFileNode + { + Path = path, + Length = file.Length, + Offset = 0, + _cache = file + }; + + return ErrorNumber.NoError; + } + + /// + public ErrorNumber CloseFile(IFileNode node) + { + if(!_mounted) + return ErrorNumber.AccessDenied; + + if(node is not CpmFileNode mynode) + return ErrorNumber.InvalidArgument; + + mynode._cache = null; + + return ErrorNumber.NoError; + } + /// public ErrorNumber Read(string path, long offset, long size, ref byte[] buf) { diff --git a/Aaru.Filesystems/CPM/Structs.cs b/Aaru.Filesystems/CPM/Structs.cs index 894dd612b..1005c9d4a 100644 --- a/Aaru.Filesystems/CPM/Structs.cs +++ b/Aaru.Filesystems/CPM/Structs.cs @@ -34,6 +34,7 @@ using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; +using Aaru.CommonTypes.Interfaces; namespace Aaru.Filesystems; @@ -366,4 +367,15 @@ public sealed partial class CPM [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public readonly ushort[] allocations; } + + sealed class CpmFileNode : IFileNode + { + internal byte[] _cache; + /// + public string Path { get; init; } + /// + public long Length { get; init; } + /// + public long Offset { get; init; } + } } \ No newline at end of file diff --git a/Aaru.Filesystems/FAT/File.cs b/Aaru.Filesystems/FAT/File.cs index 6141b7a51..29cbbf3ad 100644 --- a/Aaru.Filesystems/FAT/File.cs +++ b/Aaru.Filesystems/FAT/File.cs @@ -31,6 +31,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using Aaru.CommonTypes.Enums; +using Aaru.CommonTypes.Interfaces; using Aaru.CommonTypes.Structs; using Aaru.Helpers; using FileAttributes = Aaru.CommonTypes.Structs.FileAttributes; @@ -84,6 +85,53 @@ public sealed partial class FAT return ErrorNumber.NoError; } + /// + public ErrorNumber OpenFile(string path, out IFileNode node) + { + node = null; + + if(!_mounted) + return ErrorNumber.AccessDenied; + + ErrorNumber err = Stat(path, out FileEntryInfo stat); + + if(err != ErrorNumber.NoError) + return err; + + if(stat.Attributes.HasFlag(FileAttributes.Directory) && + !_debug) + return ErrorNumber.IsDirectory; + + uint[] clusters = GetClusters((uint)stat.Inode); + + if(clusters is null) + return ErrorNumber.InvalidArgument; + + node = new FatFileNode + { + Path = path, + Length = stat.Length, + Offset = 0, + _clusters = clusters + }; + + return ErrorNumber.NoError; + } + + /// + public ErrorNumber CloseFile(IFileNode node) + { + if(!_mounted) + return ErrorNumber.AccessDenied; + + if(node is not FatFileNode mynode) + return ErrorNumber.InvalidArgument; + + mynode._clusters = null; + + return ErrorNumber.NoError; + } + /// public ErrorNumber Read(string path, long offset, long size, ref byte[] buf) { diff --git a/Aaru.Filesystems/FAT/Structs.cs b/Aaru.Filesystems/FAT/Structs.cs index 8aa94b8a2..939a97cec 100644 --- a/Aaru.Filesystems/FAT/Structs.cs +++ b/Aaru.Filesystems/FAT/Structs.cs @@ -30,6 +30,7 @@ using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; +using Aaru.CommonTypes.Interfaces; namespace Aaru.Filesystems; @@ -983,4 +984,16 @@ public sealed partial class FAT return !string.IsNullOrEmpty(Longname) ? Longname : Shortname; } } + + sealed class FatFileNode : IFileNode + { + /// + public string Path { get; init; } + /// + public long Length { get; init; } + /// + public long Offset { get; init; } + + internal uint[] _clusters; + } } \ No newline at end of file diff --git a/Aaru.Filesystems/FATX/File.cs b/Aaru.Filesystems/FATX/File.cs index 549401717..233fc4c84 100644 --- a/Aaru.Filesystems/FATX/File.cs +++ b/Aaru.Filesystems/FATX/File.cs @@ -31,6 +31,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using Aaru.CommonTypes.Enums; +using Aaru.CommonTypes.Interfaces; using Aaru.CommonTypes.Structs; using Aaru.Helpers; using FileAttributes = Aaru.CommonTypes.Structs.FileAttributes; @@ -84,6 +85,50 @@ public sealed partial class XboxFatPlugin return ErrorNumber.NoError; } + /// + public ErrorNumber OpenFile(string path, out IFileNode node) + { + node = null; + + if(!_mounted) + return ErrorNumber.AccessDenied; + + ErrorNumber err = Stat(path, out FileEntryInfo stat); + + if(err != ErrorNumber.NoError) + return err; + + if(stat.Attributes.HasFlag(FileAttributes.Directory) && + !_debug) + return ErrorNumber.IsDirectory; + + uint[] clusters = GetClusters((uint)stat.Inode); + + node = new FatxFileNode + { + Path = path, + Length = stat.Length, + Offset = 0, + _clusters = clusters + }; + + return ErrorNumber.NoError; + } + + /// + public ErrorNumber CloseFile(IFileNode node) + { + if(!_mounted) + return ErrorNumber.AccessDenied; + + if(node is not FatxFileNode mynode) + return ErrorNumber.InvalidArgument; + + mynode._clusters = null; + + return ErrorNumber.NoError; + } + /// public ErrorNumber Read(string path, long offset, long size, ref byte[] buf) { diff --git a/Aaru.Filesystems/FATX/Structs.cs b/Aaru.Filesystems/FATX/Structs.cs index 2b12e739d..a58c279a8 100644 --- a/Aaru.Filesystems/FATX/Structs.cs +++ b/Aaru.Filesystems/FATX/Structs.cs @@ -27,6 +27,7 @@ // ****************************************************************************/ using System.Runtime.InteropServices; +using Aaru.CommonTypes.Interfaces; namespace Aaru.Filesystems; @@ -61,4 +62,15 @@ public sealed partial class XboxFatPlugin public readonly ushort creationTime; public readonly ushort creationDate; } + + sealed class FatxFileNode : IFileNode + { + internal uint[] _clusters; + /// + public string Path { get; init; } + /// + public long Length { get; init; } + /// + public long Offset { get; init; } + } } \ No newline at end of file diff --git a/Aaru.Filesystems/ISO9660/File.cs b/Aaru.Filesystems/ISO9660/File.cs index 39d73e677..6abcf5640 100644 --- a/Aaru.Filesystems/ISO9660/File.cs +++ b/Aaru.Filesystems/ISO9660/File.cs @@ -34,6 +34,7 @@ using System.IO; using System.Linq; using System.Runtime.CompilerServices; using Aaru.CommonTypes.Enums; +using Aaru.CommonTypes.Interfaces; using Aaru.CommonTypes.Structs; using Aaru.Console; using Aaru.Helpers; @@ -87,6 +88,51 @@ public sealed partial class ISO9660 return ErrorNumber.NoError; } + /// + public ErrorNumber OpenFile(string path, out IFileNode node) + { + node = null; + + if(!_mounted) + return ErrorNumber.AccessDenied; + + ErrorNumber err = GetFileEntry(path, out DecodedDirectoryEntry entry); + + if(err != ErrorNumber.NoError) + return err; + + if(entry.Flags.HasFlag(FileFlags.Directory) && + !_debug) + return ErrorNumber.IsDirectory; + + if(entry.Extents is null) + return ErrorNumber.InvalidArgument; + + node = new Iso9660FileNode + { + Path = path, + Length = (long)entry.Size, + Offset = 0, + _dentry = entry + }; + + return ErrorNumber.NoError; + } + + /// + public ErrorNumber CloseFile(IFileNode node) + { + if(!_mounted) + return ErrorNumber.AccessDenied; + + if(node is not Iso9660FileNode mynode) + return ErrorNumber.InvalidArgument; + + mynode._dentry = null; + + return ErrorNumber.NoError; + } + // TODO: Resolve symbolic link /// public ErrorNumber Read(string path, long offset, long size, ref byte[] buf) @@ -157,11 +203,6 @@ public sealed partial class ISO9660 return ErrorNumber.UnexpectedException; } - - return ReadWithExtents(offset, size, entry.Extents, - entry.XA?.signature == XA_MAGIC && - entry.XA?.attributes.HasFlag(XaAttributes.Interleaved) == true, - entry.XA?.filenumber ?? 0, out buf); } /// diff --git a/Aaru.Filesystems/ISO9660/Structs/Internal.cs b/Aaru.Filesystems/ISO9660/Structs/Internal.cs index 87378ab00..7a18a7b36 100644 --- a/Aaru.Filesystems/ISO9660/Structs/Internal.cs +++ b/Aaru.Filesystems/ISO9660/Structs/Internal.cs @@ -29,6 +29,7 @@ using System; using System.Collections.Generic; +using Aaru.CommonTypes.Interfaces; namespace Aaru.Filesystems; @@ -102,4 +103,15 @@ public sealed partial class ISO9660 public override string ToString() => Name; } + + sealed class Iso9660FileNode : IFileNode + { + internal DecodedDirectoryEntry _dentry; + /// + public string Path { get; init; } + /// + public long Length { get; init; } + /// + public long Offset { get; init; } + } } \ No newline at end of file diff --git a/Aaru.Filesystems/LisaFS/File.cs b/Aaru.Filesystems/LisaFS/File.cs index d10b1c22f..5089a71eb 100644 --- a/Aaru.Filesystems/LisaFS/File.cs +++ b/Aaru.Filesystems/LisaFS/File.cs @@ -28,6 +28,7 @@ using System; using Aaru.CommonTypes.Enums; +using Aaru.CommonTypes.Interfaces; using Aaru.CommonTypes.Structs; using Aaru.Console; using Aaru.Decoders; @@ -55,6 +56,50 @@ public sealed partial class LisaFS return ErrorNumber.NoError; } + /// + public ErrorNumber OpenFile(string path, out IFileNode node) + { + node = null; + + if(!_mounted) + return ErrorNumber.AccessDenied; + + ErrorNumber error = LookupFileId(path, out short fileId, out bool isDir); + + if(error != ErrorNumber.NoError) + return error; + + if(isDir) + return ErrorNumber.IsDirectory; + + error = Stat(fileId, out FileEntryInfo stat); + + if(error != ErrorNumber.NoError) + return error; + + node = new LisaFileNode + { + Path = path, + Length = stat.Length, + Offset = 0, + _fileId = fileId + }; + + return ErrorNumber.NoError; + } + + /// + public ErrorNumber CloseFile(IFileNode node) + { + if(!_mounted) + return ErrorNumber.AccessDenied; + + if(node is not LisaFileNode mynode) + return ErrorNumber.InvalidArgument; + + return ErrorNumber.NoError; + } + /// public ErrorNumber Read(string path, long offset, long size, ref byte[] buf) { diff --git a/Aaru.Filesystems/LisaFS/Structs.cs b/Aaru.Filesystems/LisaFS/Structs.cs index ce7cb2376..4aee25e14 100644 --- a/Aaru.Filesystems/LisaFS/Structs.cs +++ b/Aaru.Filesystems/LisaFS/Structs.cs @@ -30,6 +30,7 @@ using System; using System.Diagnostics.CodeAnalysis; +using Aaru.CommonTypes.Interfaces; #pragma warning disable CS0649 namespace Aaru.Filesystems; @@ -397,4 +398,16 @@ public sealed partial class LisaFS /// 0x26, 16 bytes, unknown public byte[] unknown3; } + + sealed class LisaFileNode : IFileNode + { + /// + public string Path { get; init; } + /// + public long Length { get; init; } + /// + public long Offset { get; init; } + + internal short _fileId; + } } \ No newline at end of file diff --git a/Aaru.Filesystems/Opera/File.cs b/Aaru.Filesystems/Opera/File.cs index 4210e6bb8..aeb35b596 100644 --- a/Aaru.Filesystems/Opera/File.cs +++ b/Aaru.Filesystems/Opera/File.cs @@ -31,6 +31,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using Aaru.CommonTypes.Enums; +using Aaru.CommonTypes.Interfaces; using Aaru.CommonTypes.Structs; namespace Aaru.Filesystems; @@ -77,6 +78,49 @@ public sealed partial class OperaFS return ErrorNumber.NoError; } + /// + public ErrorNumber OpenFile(string path, out IFileNode node) + { + node = null; + + if(!_mounted) + return ErrorNumber.AccessDenied; + + ErrorNumber err = GetFileEntry(path, out DirectoryEntryWithPointers entry); + + if(err != ErrorNumber.NoError) + return err; + + if((entry.Entry.flags & FLAGS_MASK) == (uint)FileFlags.Directory && + !_debug) + return ErrorNumber.IsDirectory; + + if(entry.Pointers.Length < 1) + return ErrorNumber.InvalidArgument; + + node = new OperaFileNode + { + Path = path, + Length = entry.Entry.byte_count, + Offset = 0, + _dentry = entry + }; + + return ErrorNumber.NoError; + } + + /// + public ErrorNumber CloseFile(IFileNode node) + { + if(!_mounted) + return ErrorNumber.AccessDenied; + + if(node is not OperaFileNode mynode) + return ErrorNumber.InvalidArgument; + + return ErrorNumber.NoError; + } + /// public ErrorNumber Read(string path, long offset, long size, ref byte[] buf) { diff --git a/Aaru.Filesystems/Opera/Structs.cs b/Aaru.Filesystems/Opera/Structs.cs index 58c4d53f6..9ec54483a 100644 --- a/Aaru.Filesystems/Opera/Structs.cs +++ b/Aaru.Filesystems/Opera/Structs.cs @@ -27,6 +27,7 @@ // ****************************************************************************/ using System.Runtime.InteropServices; +using Aaru.CommonTypes.Interfaces; namespace Aaru.Filesystems; @@ -112,4 +113,15 @@ public sealed partial class OperaFS public DirectoryEntry Entry; public uint[] Pointers; } + + sealed class OperaFileNode : IFileNode + { + internal DirectoryEntryWithPointers _dentry; + /// + public string Path { get; init; } + /// + public long Length { get; init; } + /// + public long Offset { get; init; } + } } \ No newline at end of file diff --git a/Aaru.Filesystems/UCSDPascal/File.cs b/Aaru.Filesystems/UCSDPascal/File.cs index ad10b7b7d..8954547d3 100644 --- a/Aaru.Filesystems/UCSDPascal/File.cs +++ b/Aaru.Filesystems/UCSDPascal/File.cs @@ -29,6 +29,7 @@ using System; using System.Linq; using Aaru.CommonTypes.Enums; +using Aaru.CommonTypes.Interfaces; using Aaru.CommonTypes.Structs; using Aaru.Helpers; @@ -71,6 +72,71 @@ public sealed partial class PascalPlugin return error; } + /// + public ErrorNumber OpenFile(string path, out IFileNode node) + { + node = null; + + if(!_mounted) + return ErrorNumber.AccessDenied; + + string[] pathElements = path.Split(new[] + { + '/' + }, StringSplitOptions.RemoveEmptyEntries); + + if(pathElements.Length != 1) + return ErrorNumber.NotSupported; + + byte[] file; + + if(_debug && (string.Compare(path, "$", StringComparison.InvariantCulture) == 0 || + string.Compare(path, "$Boot", StringComparison.InvariantCulture) == 0)) + file = string.Compare(path, "$", StringComparison.InvariantCulture) == 0 ? _catalogBlocks : _bootBlocks; + else + { + ErrorNumber error = GetFileEntry(path, out PascalFileEntry entry); + + if(error != ErrorNumber.NoError) + return error; + + error = _device.ReadSectors((ulong)entry.FirstBlock * _multiplier, + (uint)(entry.LastBlock - entry.FirstBlock) * _multiplier, out byte[] tmp); + + if(error != ErrorNumber.NoError) + return error; + + file = new byte[((entry.LastBlock - entry.FirstBlock - 1) * _device.Info.SectorSize * _multiplier) + + entry.LastBytes]; + + Array.Copy(tmp, 0, file, 0, file.Length); + } + + node = new PascalFileNode + { + Path = path, + Length = file.Length, + Offset = 0, + _cache = file + }; + + return ErrorNumber.NoError; + } + + /// + public ErrorNumber CloseFile(IFileNode node) + { + if(!_mounted) + return ErrorNumber.AccessDenied; + + if(node is not PascalFileNode mynode) + return ErrorNumber.InvalidArgument; + + mynode._cache = null; + + return ErrorNumber.NoError; + } + /// public ErrorNumber Read(string path, long offset, long size, ref byte[] buf) { diff --git a/Aaru.Filesystems/UCSDPascal/Structs.cs b/Aaru.Filesystems/UCSDPascal/Structs.cs index 6c15b86cc..c09f45163 100644 --- a/Aaru.Filesystems/UCSDPascal/Structs.cs +++ b/Aaru.Filesystems/UCSDPascal/Structs.cs @@ -31,6 +31,7 @@ // ****************************************************************************/ using System.Diagnostics.CodeAnalysis; +using Aaru.CommonTypes.Interfaces; namespace Aaru.Filesystems; @@ -75,4 +76,15 @@ public sealed partial class PascalPlugin /// 0x18, modification time public short ModificationTime; } + + sealed class PascalFileNode : IFileNode + { + internal byte[] _cache; + /// + public string Path { get; init; } + /// + public long Length { get; init; } + /// + public long Offset { get; init; } + } } \ No newline at end of file