diff --git a/src/LibHac/Fs/Impl/DirectoryServiceObjectAdapter.cs b/src/LibHac/Fs/Impl/DirectoryServiceObjectAdapter.cs
deleted file mode 100644
index e9312614..00000000
--- a/src/LibHac/Fs/Impl/DirectoryServiceObjectAdapter.cs
+++ /dev/null
@@ -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
-{
- ///
- /// An adapter for using an service object as an . Used
- /// when receiving a Horizon IPC directory object so it can be used as an locally.
- ///
- internal class DirectoryServiceObjectAdapter : IDirectory
- {
- private ReferenceCountedDisposable BaseDirectory { get; }
-
- public DirectoryServiceObjectAdapter(ReferenceCountedDisposable baseDirectory)
- {
- BaseDirectory = baseDirectory.AddReference();
- }
-
- protected override Result DoRead(out long entriesRead, Span entryBuffer)
- {
- Span buffer = MemoryMarshal.Cast(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);
- }
- }
-}
diff --git a/src/LibHac/Fs/Impl/FileServiceObjectAdapter.cs b/src/LibHac/Fs/Impl/FileServiceObjectAdapter.cs
deleted file mode 100644
index 3781c2ae..00000000
--- a/src/LibHac/Fs/Impl/FileServiceObjectAdapter.cs
+++ /dev/null
@@ -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
-{
- ///
- /// An adapter for using an service object as an . Used
- /// when receiving a Horizon IPC file object so it can be used as an locally.
- ///
- internal class FileServiceObjectAdapter : IFile
- {
- private ReferenceCountedDisposable BaseFile { get; }
-
- public FileServiceObjectAdapter(ReferenceCountedDisposable baseFile)
- {
- BaseFile = baseFile.AddReference();
- }
-
- protected override Result DoRead(out long bytesRead, long offset, Span destination, in ReadOption option)
- {
- return BaseFile.Target.Read(out bytesRead, offset, new OutBuffer(destination), destination.Length, option);
- }
-
- protected override Result DoWrite(long offset, ReadOnlySpan 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 outBuffer, OperationId operationId, long offset, long size,
- ReadOnlySpan inBuffer)
- {
- switch (operationId)
- {
- case OperationId.InvalidateCache:
- return BaseFile.Target.OperateRange(out _, (int)OperationId.InvalidateCache, offset, size);
- case OperationId.QueryRange:
- if (outBuffer.Length != Unsafe.SizeOf())
- return ResultFs.InvalidSize.Log();
-
- ref QueryRangeInfo info = ref SpanHelpers.AsStruct(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);
- }
- }
-}
\ No newline at end of file
diff --git a/src/LibHac/Fs/Impl/FileSystemServiceObjectAdapter.cs b/src/LibHac/Fs/Shim/FileSystemServiceObjectAdapter.cs
similarity index 56%
rename from src/LibHac/Fs/Impl/FileSystemServiceObjectAdapter.cs
rename to src/LibHac/Fs/Shim/FileSystemServiceObjectAdapter.cs
index aeac867f..1286d837 100644
--- a/src/LibHac/Fs/Impl/FileSystemServiceObjectAdapter.cs
+++ b/src/LibHac/Fs/Shim/FileSystemServiceObjectAdapter.cs
@@ -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
{
///
- /// An adapter for using an service object as an . Used
- /// when receiving a Horizon IPC file system object so it can be used as an locally.
+ /// An adapter for using an service object as an . Used
+ /// when receiving a Horizon IPC file object so it can be used as an locally.
///
+ /// Based on FS 12.0.3 (nnSdk 12.3.1)
+ internal class FileServiceObjectAdapter : IFile
+ {
+ private ReferenceCountedDisposable BaseFile { get; }
+
+ public FileServiceObjectAdapter(ReferenceCountedDisposable 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 destination, in ReadOption option)
+ {
+ return BaseFile.Target.Read(out bytesRead, offset, new OutBuffer(destination), destination.Length, option);
+ }
+
+ protected override Result DoWrite(long offset, ReadOnlySpan 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 outBuffer, OperationId operationId, long offset, long size,
+ ReadOnlySpan inBuffer)
+ {
+ switch (operationId)
+ {
+ case OperationId.InvalidateCache:
+ return BaseFile.Target.OperateRange(out _, (int)OperationId.InvalidateCache, offset, size);
+ case OperationId.QueryRange:
+ if (outBuffer.Length != Unsafe.SizeOf())
+ return ResultFs.InvalidSize.Log();
+
+ ref QueryRangeInfo info = ref SpanHelpers.AsStruct(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);
+ }
+ }
+ }
+
+ ///
+ /// An adapter for using an service object as an . Used
+ /// when receiving a Horizon IPC directory object so it can be used as an locally.
+ ///
+ /// Based on FS 12.0.3 (nnSdk 12.3.1)
+ internal class DirectoryServiceObjectAdapter : IDirectory
+ {
+ private ReferenceCountedDisposable BaseDirectory { get; }
+
+ public DirectoryServiceObjectAdapter(ReferenceCountedDisposable 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 entryBuffer)
+ {
+ Span buffer = MemoryMarshal.Cast(entryBuffer);
+ return BaseDirectory.Target.Read(out entriesRead, new OutBuffer(buffer));
+ }
+
+ protected override Result DoGetEntryCount(out long entryCount)
+ {
+ return BaseDirectory.Target.GetEntryCount(out entryCount);
+ }
+ }
+
+ ///
+ /// An adapter for using an service object as an . Used
+ /// when receiving a Horizon IPC file system object so it can be used as an locally.
+ ///
+ /// Based on FS 12.0.3 (nnSdk 12.3.1)
internal class FileSystemServiceObjectAdapter : IFileSystem, IMultiCommitTarget
{
private ReferenceCountedDisposable 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 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 GetMultiCommitTarget()
+ public ReferenceCountedDisposable GetFileSystem()
{
return BaseFs.AddReference();
}
- public override void Dispose()
+ public ReferenceCountedDisposable 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 outPath = SpanHelpers.AsByteSpan(ref sfPath);
-
- // Copy and null terminate
- StringUtils.Copy(outPath, path);
- outPath[Unsafe.SizeOf() - 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();
}
}
}
diff --git a/src/LibHac/FsSrv/Sf/IFile.cs b/src/LibHac/FsSrv/Sf/IFile.cs
index 5236bf59..95d086df 100644
--- a/src/LibHac/FsSrv/Sf/IFile.cs
+++ b/src/LibHac/FsSrv/Sf/IFile.cs
@@ -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);
}
}
\ No newline at end of file