mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Add OpenFile and CloseFile methods to IReadOnlyFilesystem.
This commit is contained in:
Submodule Aaru.CommonTypes updated: 2a4635bb38...685f2456a5
@@ -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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber Read(string path, long offset, long size, ref byte[] buf)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
/// <inheritdoc />
|
||||
public string Path { get; init; }
|
||||
/// <inheritdoc />
|
||||
public long Length { get; init; }
|
||||
/// <inheritdoc />
|
||||
public long Offset { get; init; }
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber Read(string path, long offset, long size, ref byte[] buf)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
/// <summary>0x32, file name prefixed with length</summary>
|
||||
public byte[] flNam;
|
||||
}
|
||||
|
||||
sealed class AppleMfsFileNode : IFileNode
|
||||
{
|
||||
internal byte[] _cache;
|
||||
/// <inheritdoc />
|
||||
public string Path { get; init; }
|
||||
/// <inheritdoc />
|
||||
public long Length { get; init; }
|
||||
/// <inheritdoc />
|
||||
public long Offset { get; init; }
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber Read(string path, long offset, long size, ref byte[] buf)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
/// <inheritdoc />
|
||||
public string Path { get; init; }
|
||||
/// <inheritdoc />
|
||||
public long Length { get; init; }
|
||||
/// <inheritdoc />
|
||||
public long Offset { get; init; }
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber Read(string path, long offset, long size, ref byte[] buf)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public string Path { get; init; }
|
||||
/// <inheritdoc />
|
||||
public long Length { get; init; }
|
||||
/// <inheritdoc />
|
||||
public long Offset { get; init; }
|
||||
|
||||
internal uint[] _clusters;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber Read(string path, long offset, long size, ref byte[] buf)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
/// <inheritdoc />
|
||||
public string Path { get; init; }
|
||||
/// <inheritdoc />
|
||||
public long Length { get; init; }
|
||||
/// <inheritdoc />
|
||||
public long Offset { get; init; }
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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
|
||||
/// <inheritdoc />
|
||||
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);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -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;
|
||||
/// <inheritdoc />
|
||||
public string Path { get; init; }
|
||||
/// <inheritdoc />
|
||||
public long Length { get; init; }
|
||||
/// <inheritdoc />
|
||||
public long Offset { get; init; }
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber CloseFile(IFileNode node)
|
||||
{
|
||||
if(!_mounted)
|
||||
return ErrorNumber.AccessDenied;
|
||||
|
||||
if(node is not LisaFileNode mynode)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber Read(string path, long offset, long size, ref byte[] buf)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
/// <summary>0x26, 16 bytes, unknown</summary>
|
||||
public byte[] unknown3;
|
||||
}
|
||||
|
||||
sealed class LisaFileNode : IFileNode
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public string Path { get; init; }
|
||||
/// <inheritdoc />
|
||||
public long Length { get; init; }
|
||||
/// <inheritdoc />
|
||||
public long Offset { get; init; }
|
||||
|
||||
internal short _fileId;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber CloseFile(IFileNode node)
|
||||
{
|
||||
if(!_mounted)
|
||||
return ErrorNumber.AccessDenied;
|
||||
|
||||
if(node is not OperaFileNode mynode)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber Read(string path, long offset, long size, ref byte[] buf)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
/// <inheritdoc />
|
||||
public string Path { get; init; }
|
||||
/// <inheritdoc />
|
||||
public long Length { get; init; }
|
||||
/// <inheritdoc />
|
||||
public long Offset { get; init; }
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber Read(string path, long offset, long size, ref byte[] buf)
|
||||
{
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
// ****************************************************************************/
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
|
||||
namespace Aaru.Filesystems;
|
||||
|
||||
@@ -75,4 +76,15 @@ public sealed partial class PascalPlugin
|
||||
/// <summary>0x18, modification time</summary>
|
||||
public short ModificationTime;
|
||||
}
|
||||
|
||||
sealed class PascalFileNode : IFileNode
|
||||
{
|
||||
internal byte[] _cache;
|
||||
/// <inheritdoc />
|
||||
public string Path { get; init; }
|
||||
/// <inheritdoc />
|
||||
public long Length { get; init; }
|
||||
/// <inheritdoc />
|
||||
public long Offset { get; init; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user