mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Update FileSystemServiceObjectAdapter
This commit is contained in:
parent
7d3ceb5315
commit
8e162cc3c8
4 changed files with 145 additions and 152 deletions
|
@ -1,43 +0,0 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using LibHac.Sf;
|
||||
using IDirectory = LibHac.Fs.Fsa.IDirectory;
|
||||
using IDirectorySf = LibHac.FsSrv.Sf.IDirectory;
|
||||
|
||||
namespace LibHac.Fs.Impl
|
||||
{
|
||||
/// <summary>
|
||||
/// An adapter for using an <see cref="IDirectorySf"/> service object as an <see cref="IDirectory"/>. Used
|
||||
/// when receiving a Horizon IPC directory object so it can be used as an <see cref="IDirectory"/> locally.
|
||||
/// </summary>
|
||||
internal class DirectoryServiceObjectAdapter : IDirectory
|
||||
{
|
||||
private ReferenceCountedDisposable<IDirectorySf> BaseDirectory { get; }
|
||||
|
||||
public DirectoryServiceObjectAdapter(ReferenceCountedDisposable<IDirectorySf> baseDirectory)
|
||||
{
|
||||
BaseDirectory = baseDirectory.AddReference();
|
||||
}
|
||||
|
||||
protected override Result DoRead(out long entriesRead, Span<DirectoryEntry> entryBuffer)
|
||||
{
|
||||
Span<byte> buffer = MemoryMarshal.Cast<DirectoryEntry, byte>(entryBuffer);
|
||||
return BaseDirectory.Target.Read(out entriesRead, new OutBuffer(buffer));
|
||||
}
|
||||
|
||||
protected override Result DoGetEntryCount(out long entryCount)
|
||||
{
|
||||
return BaseDirectory.Target.GetEntryCount(out entryCount);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
BaseDirectory?.Dispose();
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Sf;
|
||||
using IFile = LibHac.Fs.Fsa.IFile;
|
||||
using IFileSf = LibHac.FsSrv.Sf.IFile;
|
||||
|
||||
namespace LibHac.Fs.Impl
|
||||
{
|
||||
/// <summary>
|
||||
/// An adapter for using an <see cref="IFileSf"/> service object as an <see cref="IFile"/>. Used
|
||||
/// when receiving a Horizon IPC file object so it can be used as an <see cref="IFile"/> locally.
|
||||
/// </summary>
|
||||
internal class FileServiceObjectAdapter : IFile
|
||||
{
|
||||
private ReferenceCountedDisposable<IFileSf> BaseFile { get; }
|
||||
|
||||
public FileServiceObjectAdapter(ReferenceCountedDisposable<IFileSf> baseFile)
|
||||
{
|
||||
BaseFile = baseFile.AddReference();
|
||||
}
|
||||
|
||||
protected override Result DoRead(out long bytesRead, long offset, Span<byte> destination, in ReadOption option)
|
||||
{
|
||||
return BaseFile.Target.Read(out bytesRead, offset, new OutBuffer(destination), destination.Length, option);
|
||||
}
|
||||
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source, in WriteOption option)
|
||||
{
|
||||
return BaseFile.Target.Write(offset, new InBuffer(source), source.Length, option);
|
||||
}
|
||||
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return BaseFile.Target.Flush();
|
||||
}
|
||||
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
return BaseFile.Target.SetSize(size);
|
||||
}
|
||||
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
return BaseFile.Target.GetSize(out size);
|
||||
}
|
||||
|
||||
protected override Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size,
|
||||
ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
switch (operationId)
|
||||
{
|
||||
case OperationId.InvalidateCache:
|
||||
return BaseFile.Target.OperateRange(out _, (int)OperationId.InvalidateCache, offset, size);
|
||||
case OperationId.QueryRange:
|
||||
if (outBuffer.Length != Unsafe.SizeOf<QueryRangeInfo>())
|
||||
return ResultFs.InvalidSize.Log();
|
||||
|
||||
ref QueryRangeInfo info = ref SpanHelpers.AsStruct<QueryRangeInfo>(outBuffer);
|
||||
|
||||
return BaseFile.Target.OperateRange(out info, (int)OperationId.QueryRange, offset, size);
|
||||
default:
|
||||
return ResultFs.UnsupportedOperateRangeForFileServiceObjectAdapter.Log();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
BaseFile?.Dispose();
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,28 +1,161 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.Sf;
|
||||
using LibHac.Util;
|
||||
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
|
||||
|
||||
using IFile = LibHac.Fs.Fsa.IFile;
|
||||
using IFileSf = LibHac.FsSrv.Sf.IFile;
|
||||
using IDirectory = LibHac.Fs.Fsa.IDirectory;
|
||||
using IDirectorySf = LibHac.FsSrv.Sf.IDirectory;
|
||||
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
|
||||
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
|
||||
using PathSf = LibHac.FsSrv.Sf.Path;
|
||||
|
||||
// ReSharper disable CheckNamespace
|
||||
namespace LibHac.Fs.Impl
|
||||
{
|
||||
/// <summary>
|
||||
/// An adapter for using an <see cref="IFileSystemSf"/> service object as an <see cref="Fsa.IFileSystem"/>. Used
|
||||
/// when receiving a Horizon IPC file system object so it can be used as an <see cref="Fsa.IFileSystem"/> locally.
|
||||
/// An adapter for using an <see cref="IFileSf"/> service object as an <see cref="IFile"/>. Used
|
||||
/// when receiving a Horizon IPC file object so it can be used as an <see cref="IFile"/> locally.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.0.3 (nnSdk 12.3.1)</remarks>
|
||||
internal class FileServiceObjectAdapter : IFile
|
||||
{
|
||||
private ReferenceCountedDisposable<IFileSf> BaseFile { get; }
|
||||
|
||||
public FileServiceObjectAdapter(ReferenceCountedDisposable<IFileSf> baseFile)
|
||||
{
|
||||
BaseFile = baseFile.AddReference();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
BaseFile?.Dispose();
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
protected override Result DoRead(out long bytesRead, long offset, Span<byte> destination, in ReadOption option)
|
||||
{
|
||||
return BaseFile.Target.Read(out bytesRead, offset, new OutBuffer(destination), destination.Length, option);
|
||||
}
|
||||
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source, in WriteOption option)
|
||||
{
|
||||
return BaseFile.Target.Write(offset, new InBuffer(source), source.Length, option);
|
||||
}
|
||||
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return BaseFile.Target.Flush();
|
||||
}
|
||||
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
return BaseFile.Target.SetSize(size);
|
||||
}
|
||||
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
return BaseFile.Target.GetSize(out size);
|
||||
}
|
||||
|
||||
protected override Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size,
|
||||
ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
switch (operationId)
|
||||
{
|
||||
case OperationId.InvalidateCache:
|
||||
return BaseFile.Target.OperateRange(out _, (int)OperationId.InvalidateCache, offset, size);
|
||||
case OperationId.QueryRange:
|
||||
if (outBuffer.Length != Unsafe.SizeOf<QueryRangeInfo>())
|
||||
return ResultFs.InvalidSize.Log();
|
||||
|
||||
ref QueryRangeInfo info = ref SpanHelpers.AsStruct<QueryRangeInfo>(outBuffer);
|
||||
|
||||
return BaseFile.Target.OperateRange(out info, (int)OperationId.QueryRange, offset, size);
|
||||
default:
|
||||
return BaseFile.Target.OperateRangeWithBuffer(new OutBuffer(outBuffer), new InBuffer(inBuffer),
|
||||
(int)operationId, offset, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An adapter for using an <see cref="IDirectorySf"/> service object as an <see cref="IDirectory"/>. Used
|
||||
/// when receiving a Horizon IPC directory object so it can be used as an <see cref="IDirectory"/> locally.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.0.3 (nnSdk 12.3.1)</remarks>
|
||||
internal class DirectoryServiceObjectAdapter : IDirectory
|
||||
{
|
||||
private ReferenceCountedDisposable<IDirectorySf> BaseDirectory { get; }
|
||||
|
||||
public DirectoryServiceObjectAdapter(ReferenceCountedDisposable<IDirectorySf> baseDirectory)
|
||||
{
|
||||
BaseDirectory = baseDirectory.AddReference();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
BaseDirectory?.Dispose();
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
protected override Result DoRead(out long entriesRead, Span<DirectoryEntry> entryBuffer)
|
||||
{
|
||||
Span<byte> buffer = MemoryMarshal.Cast<DirectoryEntry, byte>(entryBuffer);
|
||||
return BaseDirectory.Target.Read(out entriesRead, new OutBuffer(buffer));
|
||||
}
|
||||
|
||||
protected override Result DoGetEntryCount(out long entryCount)
|
||||
{
|
||||
return BaseDirectory.Target.GetEntryCount(out entryCount);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An adapter for using an <see cref="IFileSystemSf"/> service object as an <see cref="IFileSystem"/>. Used
|
||||
/// when receiving a Horizon IPC file system object so it can be used as an <see cref="IFileSystem"/> locally.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.0.3 (nnSdk 12.3.1)</remarks>
|
||||
internal class FileSystemServiceObjectAdapter : IFileSystem, IMultiCommitTarget
|
||||
{
|
||||
private ReferenceCountedDisposable<IFileSystemSf> BaseFs { get; }
|
||||
|
||||
private static Result GetPathForServiceObject(out PathSf sfPath, in Path path)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out sfPath);
|
||||
|
||||
int length = StringUtils.Copy(SpanHelpers.AsByteSpan(ref sfPath), path.GetString(),
|
||||
PathTool.EntryNameLengthMax + 1);
|
||||
|
||||
if (length > PathTool.EntryNameLengthMax)
|
||||
return ResultFs.TooLongPath.Log();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public FileSystemServiceObjectAdapter(ReferenceCountedDisposable<IFileSystemSf> baseFileSystem)
|
||||
{
|
||||
BaseFs = baseFileSystem.AddReference();
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
BaseFs?.Dispose();
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
protected override Result DoCreateFile(in Path path, long size, CreateFileOptions option)
|
||||
{
|
||||
Result rc = GetPathForServiceObject(out PathSf sfPath, path);
|
||||
|
@ -73,24 +206,24 @@ namespace LibHac.Fs.Impl
|
|||
|
||||
protected override Result DoRenameFile(in Path currentPath, in Path newPath)
|
||||
{
|
||||
Result rc = GetPathForServiceObject(out PathSf oldSfPath, currentPath);
|
||||
Result rc = GetPathForServiceObject(out PathSf currentSfPath, currentPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = GetPathForServiceObject(out PathSf newSfPath, newPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFs.Target.RenameFile(in oldSfPath, in newSfPath);
|
||||
return BaseFs.Target.RenameFile(in currentSfPath, in newSfPath);
|
||||
}
|
||||
|
||||
protected override Result DoRenameDirectory(in Path currentPath, in Path newPath)
|
||||
{
|
||||
Result rc = GetPathForServiceObject(out PathSf oldSfPath, currentPath);
|
||||
Result rc = GetPathForServiceObject(out PathSf currentSfPath, currentPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = GetPathForServiceObject(out PathSf newSfPath, newPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFs.Target.RenameDirectory(in oldSfPath, in newSfPath);
|
||||
return BaseFs.Target.RenameDirectory(in currentSfPath, in newSfPath);
|
||||
}
|
||||
|
||||
protected override Result DoGetEntryType(out DirectoryEntryType entryType, in Path path)
|
||||
|
@ -190,38 +323,17 @@ namespace LibHac.Fs.Impl
|
|||
Result rc = GetPathForServiceObject(out PathSf sfPath, path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFs.Target.QueryEntry(outBuffer, inBuffer, (int)queryId, in sfPath);
|
||||
return BaseFs.Target.QueryEntry(new OutBuffer(outBuffer), new InBuffer(inBuffer), (int)queryId, in sfPath);
|
||||
}
|
||||
|
||||
public ReferenceCountedDisposable<IFileSystemSf> GetMultiCommitTarget()
|
||||
public ReferenceCountedDisposable<IFileSystemSf> GetFileSystem()
|
||||
{
|
||||
return BaseFs.AddReference();
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
public ReferenceCountedDisposable<IFileSystemSf> GetMultiCommitTarget()
|
||||
{
|
||||
BaseFs?.Dispose();
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
private Result GetPathForServiceObject(out PathSf sfPath, U8Span path)
|
||||
{
|
||||
// This is the function used to create Sf.Path structs. Get an unsafe byte span for init only.
|
||||
UnsafeHelpers.SkipParamInit(out sfPath);
|
||||
Span<byte> outPath = SpanHelpers.AsByteSpan(ref sfPath);
|
||||
|
||||
// Copy and null terminate
|
||||
StringUtils.Copy(outPath, path);
|
||||
outPath[Unsafe.SizeOf<PathSf>() - 1] = StringTraits.NullTerminator;
|
||||
|
||||
// Replace directory separators
|
||||
PathUtility.Replace(outPath, StringTraits.AltDirectorySeparator, StringTraits.DirectorySeparator);
|
||||
|
||||
// Get lengths
|
||||
int windowsSkipLength = WindowsPath.GetWindowsPathSkipLength(path);
|
||||
var nonWindowsPath = new U8Span(sfPath.Str.Slice(windowsSkipLength));
|
||||
int maxLength = PathTool.EntryNameLengthMax - windowsSkipLength;
|
||||
return PathUtility.VerifyPath(null, nonWindowsPath, maxLength, maxLength);
|
||||
return GetFileSystem();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,5 +12,6 @@ namespace LibHac.FsSrv.Sf
|
|||
Result SetSize(long size);
|
||||
Result GetSize(out long size);
|
||||
Result OperateRange(out QueryRangeInfo rangeInfo, int operationId, long offset, long size);
|
||||
Result OperateRangeWithBuffer(OutBuffer outBuffer, InBuffer inBuffer, int operationId, long offset, long size);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue