Ensure shim classes are updated to 13.1.0

- Fs.Impl.DirectoryServiceObjectAdapter
- Fs.Impl.FileServiceObjectAdapter
- Fs.Impl.FileSystemServiceObjectAdapter
- Fs.Impl.StorageServiceObjectAdapter

- Fs.Shim.Application
- Fs.Shim.BcatSaveData
- Fs.Shim.Bis
- Fs.Shim.Code
- Fs.Shim.Content
- Fs.Shim.ContentStorage
- Fs.Shim.CustomStorage
- Fs.Shim.LoaderApi
This commit is contained in:
Alex Barney 2022-01-16 18:43:12 -07:00
parent 330bc2b483
commit 0b9af17dfd
11 changed files with 66 additions and 56 deletions

View file

@ -10,7 +10,7 @@ namespace LibHac.Fs.Impl;
/// An adapter for using an <see cref="IStorageSf"/> service object as an <see cref="IStorage"/>. Used
/// when receiving a Horizon IPC storage object so it can be used as an <see cref="IStorage"/> locally.
/// </summary>
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
internal class StorageServiceObjectAdapter : IStorage
{
private SharedRef<IStorageSf> _baseStorage;
@ -20,6 +20,12 @@ internal class StorageServiceObjectAdapter : IStorage
_baseStorage = SharedRef<IStorageSf>.CreateMove(ref baseStorage);
}
public override void Dispose()
{
_baseStorage.Destroy();
base.Dispose();
}
public override Result Read(long offset, Span<byte> destination)
{
return _baseStorage.Get.Read(offset, new OutBuffer(destination), destination.Length);
@ -50,8 +56,6 @@ internal class StorageServiceObjectAdapter : IStorage
{
switch (operationId)
{
case OperationId.InvalidateCache:
return _baseStorage.Get.OperateRange(out _, (int)OperationId.InvalidateCache, offset, size);
case OperationId.QueryRange:
if (outBuffer.Length != Unsafe.SizeOf<QueryRangeInfo>())
return ResultFs.InvalidSize.Log();
@ -59,14 +63,12 @@ internal class StorageServiceObjectAdapter : IStorage
ref QueryRangeInfo info = ref SpanHelpers.AsStruct<QueryRangeInfo>(outBuffer);
return _baseStorage.Get.OperateRange(out info, (int)OperationId.QueryRange, offset, size);
case OperationId.InvalidateCache:
return _baseStorage.Get.OperateRange(out _, (int)OperationId.InvalidateCache, offset, size);
default:
return ResultFs.UnsupportedOperateRangeForStorageServiceObjectAdapter.Log();
}
}
public override void Dispose()
{
_baseStorage.Destroy();
base.Dispose();
}
}

View file

@ -14,7 +14,7 @@ namespace LibHac.Fs.Shim;
/// <summary>
/// Contains functions for mounting application packages.
/// </summary>
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
[SkipLocalsInit]
public static class Application
{

View file

@ -14,7 +14,7 @@ namespace LibHac.Fs.Shim;
/// <summary>
/// Contains functions for mounting BCAT save data.
/// </summary>
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
[SkipLocalsInit]
public static class BcatSaveData
{

View file

@ -19,7 +19,7 @@ namespace LibHac.Fs.Shim;
/// Contains functions for mounting built-in-storage partition file systems
/// and opening the raw partitions as <see cref="IStorage"/>s.
/// </summary>
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
[SkipLocalsInit]
public static class Bis
{
@ -122,7 +122,7 @@ public static class Bis
public static Result MountBis(this FileSystemClient fs, U8Span mountName, BisPartitionId partitionId)
{
return MountBis(fs.Impl, mountName, partitionId, default);
return MountBis(fs.Impl, mountName, partitionId, U8Span.Empty);
}
public static Result MountBis(this FileSystemClient fs, BisPartitionId partitionId, U8Span rootPath)
@ -167,17 +167,21 @@ public static class Bis
public static Result OpenBisPartition(this FileSystemClient fs, ref UniqueRef<IStorage> outPartitionStorage,
BisPartitionId partitionId)
{
using var storage = new SharedRef<IStorageSf>();
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
using var storage = new SharedRef<IStorageSf>();
Result rc = fileSystemProxy.Get.OpenBisStorage(ref storage.Ref(), partitionId);
fs.Impl.AbortIfNeeded(rc);
if (rc.IsFailure()) return rc;
if (rc.IsFailure()) return rc.Miss();
using var storageAdapter = new UniqueRef<IStorage>(new StorageServiceObjectAdapter(ref storage.Ref()));
if (!storageAdapter.HasValue)
return ResultFs.AllocationMemoryFailedInBisC.Log();
{
rc = ResultFs.AllocationMemoryFailedInBisC.Value;
fs.Impl.AbortIfNeeded(rc);
if (rc.IsFailure()) return rc.Log();
}
outPartitionStorage.Set(ref storageAdapter.Ref());
return Result.Success;

View file

@ -15,7 +15,7 @@ namespace LibHac.Fs.Shim;
/// <summary>
/// Contains functions for mounting code file systems.
/// </summary>
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
[SkipLocalsInit]
public static class Code
{
@ -59,20 +59,19 @@ public static class Code
Result rc = fs.Impl.CheckMountName(mountName);
if (rc.IsFailure()) return rc;
if (path.IsNull())
return ResultFs.NullptrArgument.Log();
rc = PathUtility.ConvertToFspPath(out FspPath fsPath, path);
rc = PathUtility.ConvertToFspPath(out FspPath sfPath, path);
if (rc.IsFailure()) return rc;
using SharedRef<IFileSystemProxyForLoader> fileSystemProxy =
fs.Impl.GetFileSystemProxyForLoaderServiceObject();
// SetCurrentProcess
// Todo: IPC code should automatically set process ID
rc = fileSystemProxy.Get.SetCurrentProcess(fs.Hos.Os.GetCurrentProcessId().Value);
if (rc.IsFailure()) return rc.Miss();
using var fileSystem = new SharedRef<IFileSystemSf>();
rc = fileSystemProxy.Get.OpenCodeFileSystem(ref fileSystem.Ref(), out verificationData, in fsPath,
rc = fileSystemProxy.Get.OpenCodeFileSystem(ref fileSystem.Ref(), out verificationData, in sfPath,
programId);
if (rc.IsFailure()) return rc;

View file

@ -16,7 +16,7 @@ namespace LibHac.Fs.Shim;
/// <summary>
/// Contains functions for mounting content file systems.
/// </summary>
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
[SkipLocalsInit]
public static class Content
{
@ -42,16 +42,13 @@ public static class Content
FileSystemProxyType fsType = ConvertToFileSystemProxyType(contentType);
if (path.IsNull())
return ResultFs.NullptrArgument.Log();
rc = PathUtility.ConvertToFspPath(out FspPath fsPath, path);
rc = PathUtility.ConvertToFspPath(out FspPath sfPath, path);
if (rc.IsFailure()) return rc;
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
using var fileSystem = new SharedRef<IFileSystemSf>();
rc = fileSystemProxy.Get.OpenFileSystemWithId(ref fileSystem.Ref(), in fsPath, id, fsType);
rc = fileSystemProxy.Get.OpenFileSystemWithId(ref fileSystem.Ref(), in sfPath, id, fsType);
if (rc.IsFailure()) return rc;
using var fileSystemAdapter =
@ -66,8 +63,7 @@ public static class Content
return Result.Success;
}
public static Result MountContent(this FileSystemClient fs, U8Span mountName, U8Span path,
ContentType contentType)
public static Result MountContent(this FileSystemClient fs, U8Span mountName, U8Span path, ContentType contentType)
{
Result rc;
Span<byte> logBuffer = stackalloc byte[0x300];
@ -95,12 +91,12 @@ public static class Content
fs.Impl.AbortIfNeeded(rc);
if (rc.IsFailure()) return rc;
const ulong programId = 0;
ProgramId programId = default;
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System))
{
Tick start = fs.Hos.Os.GetSystemTick();
rc = MountContentImpl(fs, mountName, path, programId, contentType);
rc = MountContentImpl(fs, mountName, path, programId.Value, contentType);
Tick end = fs.Hos.Os.GetSystemTick();
var idString = new IdString();
@ -108,14 +104,14 @@ public static class Content
sb.Append(LogName).Append(mountName).Append(LogQuote)
.Append(LogPath).Append(path).Append(LogQuote)
.Append(LogProgramId).AppendFormat(programId, 'X')
.Append(LogProgramId).AppendFormat(programId.Value, 'X')
.Append(LogContentType).Append(idString.ToString(contentType));
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
}
else
{
rc = MountContentImpl(fs, mountName, path, programId, contentType);
rc = MountContentImpl(fs, mountName, path, programId.Value, contentType);
}
fs.Impl.AbortIfNeeded(rc);
@ -128,7 +124,7 @@ public static class Content
static Result PreMount(ContentType contentType)
{
if (contentType == ContentType.Meta)
if (contentType != ContentType.Meta)
return ResultFs.InvalidArgument.Log();
return Result.Success;

View file

@ -16,7 +16,7 @@ namespace LibHac.Fs.Shim;
/// <summary>
/// Contains functions for mounting the directories where content is stored.
/// </summary>
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
[SkipLocalsInit]
public static class ContentStorage
{
@ -109,6 +109,8 @@ public static class ContentStorage
if (!ResultFs.SystemPartitionNotReady.Includes(rc))
return rc;
// Note: Nintendo has an off-by-one error where they check if
// "i == maxRetries" instead of "i == maxRetries - 1"
if (i == maxRetries - 1)
return rc;

View file

@ -13,7 +13,7 @@ namespace LibHac.Fs.Shim;
/// <summary>
/// Contains functions for mounting custom storage file systems.
/// </summary>
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
[SkipLocalsInit]
public static class CustomStorage
{
@ -60,7 +60,8 @@ public static class CustomStorage
}
}
private static ReadOnlySpan<byte> CustomStorageDirectoryName => // "CustomStorage0"
/// <summary>"<c>CustomStorage0</c>"</summary>
private static ReadOnlySpan<byte> CustomStorageDirectoryName =>
new[]
{
(byte)'C', (byte)'u', (byte)'s', (byte)'t', (byte)'o', (byte)'m', (byte)'S', (byte)'t',

View file

@ -21,7 +21,7 @@ namespace LibHac.Fs.Impl;
/// 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.1.0 (nnSdk 12.3.1)</remarks>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
internal class FileServiceObjectAdapter : IFile
{
private SharedRef<IFileSf> _baseFile;
@ -67,8 +67,6 @@ internal class FileServiceObjectAdapter : IFile
{
switch (operationId)
{
case OperationId.InvalidateCache:
return _baseFile.Get.OperateRange(out _, (int)OperationId.InvalidateCache, offset, size);
case OperationId.QueryRange:
if (outBuffer.Length != Unsafe.SizeOf<QueryRangeInfo>())
return ResultFs.InvalidSize.Log();
@ -76,6 +74,8 @@ internal class FileServiceObjectAdapter : IFile
ref QueryRangeInfo info = ref SpanHelpers.AsStruct<QueryRangeInfo>(outBuffer);
return _baseFile.Get.OperateRange(out info, (int)OperationId.QueryRange, offset, size);
case OperationId.InvalidateCache:
return _baseFile.Get.OperateRange(out _, (int)OperationId.InvalidateCache, offset, size);
default:
return _baseFile.Get.OperateRangeWithBuffer(new OutBuffer(outBuffer), new InBuffer(inBuffer),
(int)operationId, offset, size);
@ -87,7 +87,7 @@ internal class FileServiceObjectAdapter : IFile
/// 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.1.0 (nnSdk 12.3.1)</remarks>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
internal class DirectoryServiceObjectAdapter : IDirectory
{
private SharedRef<IDirectorySf> _baseDirectory;
@ -119,7 +119,7 @@ internal class DirectoryServiceObjectAdapter : IDirectory
/// 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.1.0 (nnSdk 12.3.1)</remarks>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
internal class FileSystemServiceObjectAdapter : IFileSystem, IMultiCommitTarget
{
private SharedRef<IFileSystemSf> _baseFs;

View file

@ -4,6 +4,10 @@ using LibHac.Os;
namespace LibHac.Fs.Shim;
/// <summary>
/// Contains functions for use by the Loader service.
/// </summary>
/// <remarks>Based on nnSdk 13.4.0</remarks>
public static class LoaderApi
{
public static Result IsArchivedProgram(this FileSystemClient fs, out bool isArchived, ProcessId processId)
@ -13,6 +17,8 @@ public static class LoaderApi
Result rc = fileSystemProxy.Get.IsArchivedProgram(out isArchived, processId.Value);
fs.Impl.AbortIfNeeded(rc);
return rc;
if (rc.IsFailure()) return rc.Miss();
return Result.Success;
}
}

View file

@ -31,7 +31,7 @@ public class AccessControlTests
StorageId.BuiltInUser, SpanHelpers.AsReadOnlyByteSpan(in dataHeader),
SpanHelpers.AsReadOnlyByteSpan(in descriptor)));
Result rc = client.Fs.MountContent("test".ToU8Span(), "@System:/fake.nca".ToU8Span(), ContentType.Control);
Result rc = client.Fs.MountContent("test".ToU8Span(), "@System:/fake.nca".ToU8Span(), ContentType.Meta);
Assert.Result(ResultFs.PermissionDenied, rc);
}
@ -57,7 +57,7 @@ public class AccessControlTests
SpanHelpers.AsReadOnlyByteSpan(in descriptor)));
// We should get UnexpectedInNcaFileSystemServiceImplA because mounting NCAs from @System isn't allowed
Result rc = client.Fs.MountContent("test".ToU8Span(), "@System:/fake.nca".ToU8Span(), ContentType.Control);
Result rc = client.Fs.MountContent("test".ToU8Span(), "@System:/fake.nca".ToU8Span(), ContentType.Meta);
Assert.Result(ResultFs.UnexpectedInNcaFileSystemServiceImplA, rc);
}
}