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;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using LibHac.Common;
|
using LibHac.Common;
|
||||||
using LibHac.Fs.Fsa;
|
using LibHac.Fs.Fsa;
|
||||||
|
using LibHac.Sf;
|
||||||
using LibHac.Util;
|
using LibHac.Util;
|
||||||
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
|
|
||||||
|
using IFile = LibHac.Fs.Fsa.IFile;
|
||||||
using IFileSf = LibHac.FsSrv.Sf.IFile;
|
using IFileSf = LibHac.FsSrv.Sf.IFile;
|
||||||
|
using IDirectory = LibHac.Fs.Fsa.IDirectory;
|
||||||
using IDirectorySf = LibHac.FsSrv.Sf.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;
|
using PathSf = LibHac.FsSrv.Sf.Path;
|
||||||
|
|
||||||
|
// ReSharper disable CheckNamespace
|
||||||
namespace LibHac.Fs.Impl
|
namespace LibHac.Fs.Impl
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An adapter for using an <see cref="IFileSystemSf"/> service object as an <see cref="Fsa.IFileSystem"/>. Used
|
/// An adapter for using an <see cref="IFileSf"/> service object as an <see cref="IFile"/>. Used
|
||||||
/// when receiving a Horizon IPC file system object so it can be used as an <see cref="Fsa.IFileSystem"/> locally.
|
/// when receiving a Horizon IPC file object so it can be used as an <see cref="IFile"/> locally.
|
||||||
/// </summary>
|
/// </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
|
internal class FileSystemServiceObjectAdapter : IFileSystem, IMultiCommitTarget
|
||||||
{
|
{
|
||||||
private ReferenceCountedDisposable<IFileSystemSf> BaseFs { get; }
|
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)
|
public FileSystemServiceObjectAdapter(ReferenceCountedDisposable<IFileSystemSf> baseFileSystem)
|
||||||
{
|
{
|
||||||
BaseFs = baseFileSystem.AddReference();
|
BaseFs = baseFileSystem.AddReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
BaseFs?.Dispose();
|
||||||
|
base.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
protected override Result DoCreateFile(in Path path, long size, CreateFileOptions option)
|
protected override Result DoCreateFile(in Path path, long size, CreateFileOptions option)
|
||||||
{
|
{
|
||||||
Result rc = GetPathForServiceObject(out PathSf sfPath, path);
|
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)
|
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;
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
rc = GetPathForServiceObject(out PathSf newSfPath, newPath);
|
rc = GetPathForServiceObject(out PathSf newSfPath, newPath);
|
||||||
if (rc.IsFailure()) return rc;
|
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)
|
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;
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
rc = GetPathForServiceObject(out PathSf newSfPath, newPath);
|
rc = GetPathForServiceObject(out PathSf newSfPath, newPath);
|
||||||
if (rc.IsFailure()) return rc;
|
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)
|
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);
|
Result rc = GetPathForServiceObject(out PathSf sfPath, path);
|
||||||
if (rc.IsFailure()) return rc;
|
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();
|
return BaseFs.AddReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Dispose()
|
public ReferenceCountedDisposable<IFileSystemSf> GetMultiCommitTarget()
|
||||||
{
|
{
|
||||||
BaseFs?.Dispose();
|
return GetFileSystem();
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -12,5 +12,6 @@ namespace LibHac.FsSrv.Sf
|
||||||
Result SetSize(long size);
|
Result SetSize(long size);
|
||||||
Result GetSize(out long size);
|
Result GetSize(out long size);
|
||||||
Result OperateRange(out QueryRangeInfo rangeInfo, int operationId, long offset, 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