Update FileSystemProxyImpl

This commit is contained in:
Alex Barney 2024-03-31 23:27:06 -07:00
parent 7f7c8b6578
commit 27cc721b31
37 changed files with 1146 additions and 936 deletions

View file

@ -15,16 +15,16 @@ Tma,,
Dnmt,,
Pm,,
Ns,,
Htc,,
Htc,,Htc/ResultHtc.cs
Kvdb,,Kvdb/ResultKvdb.cs
Sm,,Sm/ResultSm.cs
Ro,,
Sdmmc,,Sdmmc/ResultSdmmc.cs
Spl,,Spl/ResultSpl.cs
Socket,,
HtcLow,,
HtcLow,,HtcLow/ResultHtcLow.cs
Ddsf,,
HtcFs,,
HtcFs,,HtcFs/ResultHtcFs.cs
I2C,,
Gpio,,
Settings,,

1 Namespace Class Name Path
15 Dnmt
16 Pm
17 Ns
18 Htc Htc/ResultHtc.cs
19 Kvdb Kvdb/ResultKvdb.cs
20 Sm Sm/ResultSm.cs
21 Ro
22 Sdmmc Sdmmc/ResultSdmmc.cs
23 Spl Spl/ResultSpl.cs
24 Socket
25 HtcLow HtcLow/ResultHtcLow.cs
26 Ddsf
27 HtcFs HtcFs/ResultHtcFs.cs
28 I2C
29 Gpio
30 Settings

View file

@ -8,8 +8,14 @@ public struct FatReport
public ushort DirectoryPeakOpenCount;
}
public struct FatReportInfo
public struct FatReportInfo1
{
public ushort FilePeakOpenCount;
public ushort DirectoryPeakOpenCount;
}
public struct FatReportInfo2
{
public ushort OpenUniqueFileEntryPeakCount;
public ushort OpenUniqueDirectoryEntryPeakCount;
}

View file

@ -0,0 +1,8 @@
namespace LibHac.Fat;
public struct FatSafeInfo
{
public uint Result;
public uint ErrorNumber;
public uint SafeErrorNumber;
}

View file

@ -165,6 +165,14 @@ public ref struct Path
return Result.Success;
}
public Result InitializeAsEmpty()
{
_buffer = EmptyBuffer;
_length = 0;
return Result.Success;
}
public readonly int GetLength() => _length;
public readonly ReadOnlySpan<byte> GetString() => _buffer;

View file

@ -5,21 +5,28 @@ namespace LibHac.Fs;
public struct FileSystemProxyErrorInfo
{
public int RemountForDataCorruptionCount;
public int UnrecoverableDataCorruptionByRemountCount;
public uint RemountForDataCorruptionCount;
public uint UnrecoverableDataCorruptionByRemountCount;
public FatError FatFsError;
public int RecoveredByInvalidateCacheCount;
public uint RecoveredByInvalidateCacheCount;
public int SaveDataIndexCount;
public FatReportInfo BisSystemFatReportInfo;
public FatReportInfo BisUserFatReport;
public FatReportInfo SdCardFatReport;
public Array68<byte> Reserved;
public FatReportInfo1 BisSystemFatReportInfo1;
public FatReportInfo1 BisUserFatReport1;
public FatReportInfo1 SdCardFatReport1;
public FatReportInfo2 BisSystemFatReportInfo2;
public FatReportInfo2 BisUserFatReport2;
public FatReportInfo2 SdCardFatReport2;
public uint DeepRetryStartCount;
public uint UnrecoverableByGameCardAccessFailedCount;
public FatSafeInfo BisSystemFatSafeInfo;
public FatSafeInfo BisUserFatSafeInfo;
public Array24<byte> Reserved;
}
public struct StorageErrorInfo
{
public int NumActivationFailures;
public int NumActivationErrorCorrections;
public int NumReadWriteFailures;
public int NumReadWriteErrorCorrections;
public uint NumActivationFailures;
public uint NumActivationErrorCorrections;
public uint NumReadWriteFailures;
public uint NumReadWriteErrorCorrections;
}

View file

@ -1,5 +1,9 @@
using System.Runtime.CompilerServices;
using System;
using System.Runtime.CompilerServices;
using LibHac.Diag;
using LibHac.Htc;
using LibHac.HtcFs;
using LibHac.HtcLow;
namespace LibHac.Fs;
@ -75,4 +79,23 @@ public static class ResultHandlingUtility
if (!result.IsSuccess())
Abort.DoAbort(result);
}
public static bool IsResultHtcAccessFailed(Result result)
{
if (ResultHtc.ConnectionFailure.Module == result.Module)
return true;
if (ResultHtcLow.ConnectionFailure.Module == result.Module)
return true;
if (ResultHtcFs.ConnectionFailure.Module == result.Module)
return true;
return false;
}
public static void SetErrorContextEnabled(this FileSystemClientImpl fs, bool isEnabled)
{
// Todo
}
}

View file

@ -60,7 +60,7 @@ public static class Application
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
using var fileSystem = new SharedRef<IFileSystemSf>();
res = fileSystemProxy.Get.OpenFileSystemWithId(ref fileSystem.Ref, in sfPath,
res = fileSystemProxy.Get.OpenFileSystemWithId(ref fileSystem.Ref, in sfPath, ContentAttributes.None,
Ncm.ProgramId.InvalidId.Value, FileSystemProxyType.Package);
if (res.IsFailure()) return res.Miss();

View file

@ -6,6 +6,7 @@ using LibHac.Fs.Impl;
using LibHac.FsSrv.Sf;
using LibHac.Ncm;
using LibHac.Os;
using LibHac.Sf;
using static LibHac.Fs.Impl.AccessLogStrings;
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
@ -20,13 +21,13 @@ namespace LibHac.Fs.Shim;
public static class Code
{
public static Result MountCode(this FileSystemClient fs, out CodeVerificationData verificationData,
U8Span mountName, U8Span path, ProgramId programId)
U8Span mountName, U8Span path, ContentAttributes attributes, ProgramId programId)
{
Result res;
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System))
{
Tick start = fs.Hos.Os.GetSystemTick();
res = Mount(fs, out verificationData, mountName, path, programId);
res = Mount(fs, out verificationData, mountName, path, attributes, programId);
Tick end = fs.Hos.Os.GetSystemTick();
Span<byte> logBuffer = stackalloc byte[0x300];
@ -40,7 +41,7 @@ public static class Code
}
else
{
res = Mount(fs, out verificationData, mountName, path, programId);
res = Mount(fs, out verificationData, mountName, path, attributes, programId);
}
fs.Impl.AbortIfNeeded(res);
@ -52,7 +53,7 @@ public static class Code
return Result.Success;
static Result Mount(FileSystemClient fs, out CodeVerificationData verificationData,
U8Span mountName, U8Span path, ProgramId programId)
U8Span mountName, U8Span path, ContentAttributes attributes, ProgramId programId)
{
UnsafeHelpers.SkipParamInit(out verificationData);
@ -71,8 +72,8 @@ public static class Code
using var fileSystem = new SharedRef<IFileSystemSf>();
res = fileSystemProxy.Get.OpenCodeFileSystem(ref fileSystem.Ref, out verificationData, in sfPath,
programId);
res = fileSystemProxy.Get.OpenCodeFileSystem(ref fileSystem.Ref, OutBuffer.FromStruct(ref verificationData),
in sfPath, attributes, programId);
if (res.IsFailure()) return res.Miss();
using var fileSystemAdapter =

View file

@ -34,8 +34,8 @@ public static class Content
}
}
private static Result MountContentImpl(FileSystemClient fs, U8Span mountName, U8Span path, ulong id,
ContentType contentType)
private static Result MountContentImpl(FileSystemClient fs, U8Span mountName, U8Span path,
ContentAttributes attributes, ulong id, ContentType contentType)
{
Result res = fs.Impl.CheckMountNameAcceptingReservedMountName(mountName);
if (res.IsFailure()) return res.Miss();
@ -48,7 +48,7 @@ public static class Content
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
using var fileSystem = new SharedRef<IFileSystemSf>();
res = fileSystemProxy.Get.OpenFileSystemWithId(ref fileSystem.Ref, in sfPath, id, fsType);
res = fileSystemProxy.Get.OpenFileSystemWithId(ref fileSystem.Ref, in sfPath, attributes, id, fsType);
if (res.IsFailure()) return res.Miss();
using var fileSystemAdapter =
@ -63,7 +63,8 @@ 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,
ContentAttributes attributes, ContentType contentType)
{
Result res;
Span<byte> logBuffer = stackalloc byte[0x300];
@ -96,7 +97,7 @@ public static class Content
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System))
{
Tick start = fs.Hos.Os.GetSystemTick();
res = MountContentImpl(fs, mountName, path, programId.Value, contentType);
res = MountContentImpl(fs, mountName, path, attributes, programId.Value, contentType);
Tick end = fs.Hos.Os.GetSystemTick();
var idString = new IdString();
@ -111,7 +112,7 @@ public static class Content
}
else
{
res = MountContentImpl(fs, mountName, path, programId.Value, contentType);
res = MountContentImpl(fs, mountName, path, attributes, programId.Value, contentType);
}
fs.Impl.AbortIfNeeded(res);
@ -131,8 +132,8 @@ public static class Content
}
}
public static Result MountContent(this FileSystemClient fs, U8Span mountName, U8Span path, ProgramId programId,
ContentType contentType)
public static Result MountContent(this FileSystemClient fs, U8Span mountName, U8Span path,
ContentAttributes attributes, ProgramId programId, ContentType contentType)
{
Result res;
Span<byte> logBuffer = stackalloc byte[0x300];
@ -140,7 +141,7 @@ public static class Content
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System))
{
Tick start = fs.Hos.Os.GetSystemTick();
res = MountContentImpl(fs, mountName, path, programId.Value, contentType);
res = MountContentImpl(fs, mountName, path, attributes, programId.Value, contentType);
Tick end = fs.Hos.Os.GetSystemTick();
var idString = new IdString();
@ -157,7 +158,7 @@ public static class Content
}
else
{
res = MountContentImpl(fs, mountName, path, programId.Value, contentType);
res = MountContentImpl(fs, mountName, path, attributes, programId.Value, contentType);
}
fs.Impl.AbortIfNeeded(res);
@ -169,8 +170,8 @@ public static class Content
return Result.Success;
}
public static Result MountContent(this FileSystemClient fs, U8Span mountName, U8Span path, DataId dataId,
ContentType contentType)
public static Result MountContent(this FileSystemClient fs, U8Span mountName, U8Span path,
ContentAttributes attributes, DataId dataId, ContentType contentType)
{
Result res;
Span<byte> logBuffer = stackalloc byte[0x300];
@ -178,7 +179,7 @@ public static class Content
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System))
{
Tick start = fs.Hos.Os.GetSystemTick();
res = MountContentImpl(fs, mountName, path, dataId.Value, contentType);
res = MountContentImpl(fs, mountName, path, attributes, dataId.Value, contentType);
Tick end = fs.Hos.Os.GetSystemTick();
var idString = new IdString();
@ -193,7 +194,7 @@ public static class Content
}
else
{
res = MountContentImpl(fs, mountName, path, dataId.Value, contentType);
res = MountContentImpl(fs, mountName, path, attributes, dataId.Value, contentType);
}
fs.Impl.AbortIfNeeded(res);

View file

@ -17,7 +17,8 @@ namespace LibHac.Fs.Shim;
/// <remarks>Based on nnSdk 14.3.0</remarks>
public static class Logo
{
public static Result MountLogo(this FileSystemClient fs, U8Span mountName, U8Span path, ProgramId programId)
public static Result MountLogo(this FileSystemClient fs, U8Span mountName, U8Span path,
ContentAttributes attributes, ProgramId programId)
{
Result res;
Span<byte> logBuffer = stackalloc byte[0x300];
@ -25,7 +26,7 @@ public static class Logo
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System))
{
Tick start = fs.Hos.Os.GetSystemTick();
res = Mount(fs, mountName, path, programId);
res = Mount(fs, mountName, path, attributes, programId);
Tick end = fs.Hos.Os.GetSystemTick();
var sb = new U8StringBuilder(logBuffer, true);
@ -38,7 +39,7 @@ public static class Logo
}
else
{
res = Mount(fs, mountName, path, programId);
res = Mount(fs, mountName, path, attributes, programId);
}
fs.Impl.AbortIfNeeded(res);
@ -49,7 +50,7 @@ public static class Logo
return Result.Success;
static Result Mount(FileSystemClient fs, U8Span mountName, U8Span path, ProgramId programId)
static Result Mount(FileSystemClient fs, U8Span mountName, U8Span path,ContentAttributes attributes, ProgramId programId)
{
Result res = fs.Impl.CheckMountName(mountName);
if (res.IsFailure()) return res.Miss();
@ -60,7 +61,7 @@ public static class Logo
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
using var fileSystem = new SharedRef<IFileSystemSf>();
res = fileSystemProxy.Get.OpenFileSystemWithId(ref fileSystem.Ref, in sfPath, programId.Value,
res = fileSystemProxy.Get.OpenFileSystemWithId(ref fileSystem.Ref, in sfPath, attributes, programId.Value,
FileSystemProxyType.Logo);
if (res.IsFailure()) return res.Miss();

View file

@ -23,24 +23,13 @@ public static class RightsIdShim
return Result.Success;
}
public static Result GetRightsId(this FileSystemClient fs, out RightsId rightsId, U8Span path)
public static Result GetRightsId(this FileSystemClient fs, out RightsId rightsId, U8Span path, ContentAttributes attributes)
{
UnsafeHelpers.SkipParamInit(out rightsId);
Result res = PathUtility.ConvertToFspPath(out FspPath sfPath, path);
fs.Impl.AbortIfNeeded(res);
if (res.IsFailure()) return res.Miss();
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
res = fileSystemProxy.Get.GetRightsIdByPath(out rightsId, in sfPath);
fs.Impl.AbortIfNeeded(res);
if (res.IsFailure()) return res.Miss();
return Result.Success;
return GetRightsId(fs, out rightsId, out _, path, attributes);
}
public static Result GetRightsId(this FileSystemClient fs, out RightsId rightsId, out byte keyGeneration, U8Span path)
public static Result GetRightsId(this FileSystemClient fs, out RightsId rightsId, out byte keyGeneration,
U8Span path, ContentAttributes attributes)
{
UnsafeHelpers.SkipParamInit(out rightsId, out keyGeneration);
@ -50,7 +39,7 @@ public static class RightsIdShim
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
res = fileSystemProxy.Get.GetRightsIdAndKeyGenerationByPath(out rightsId, out keyGeneration, in sfPath);
res = fileSystemProxy.Get.GetRightsIdAndKeyGenerationByPath(out rightsId, out keyGeneration, in sfPath, attributes);
fs.Impl.AbortIfNeeded(res);
if (res.IsFailure()) return res.Miss();

View file

@ -150,11 +150,6 @@ public readonly struct BaseFileSystemService
return Result.Success;
}
public Result SetBisRootForHost(BisPartitionId partitionId, ref readonly FspPath path)
{
throw new NotImplementedException();
}
public Result CreatePaddingFile(long size)
{
// File size must be non-negative

File diff suppressed because it is too large Load diff

View file

@ -125,7 +125,7 @@ public static class FileSystemServerInitializer
ncaFsServiceConfig.SpeedEmulationRange = speedEmulationRange;
ncaFsServiceConfig.FsServer = server;
var ncaFsService = new NcaFileSystemServiceImpl(in ncaFsServiceConfig, config.ExternalKeySet);
var ncaFsService = new NcaFileSystemServiceImpl(in ncaFsServiceConfig);
var saveFsServiceConfig = new SaveDataFileSystemServiceImpl.Configuration();
saveFsServiceConfig.BaseFsService = baseFsService;

View file

@ -51,17 +51,17 @@ public class FatFileSystemCreator : IFatFileSystemCreator
_fatFsError = default;
}
public void GetAndClearFatReportInfo(out FatReportInfo outBisSystemFatReportInfo,
out FatReportInfo outBisUserFatReportInfo, out FatReportInfo outSdCardFatReportInfo)
public void GetAndClearFatReportInfo(out FatReportInfo1 outBisSystemFatReportInfo1,
out FatReportInfo1 outBisUserFatReportInfo1, out FatReportInfo1 outSdCardFatReportInfo1)
{
using var scopedLock = new ScopedLock<SdkMutexType>(ref _fatReportMutex);
outBisSystemFatReportInfo.FilePeakOpenCount = _bisSystemReport.FilePeakOpenCount;
outBisSystemFatReportInfo.DirectoryPeakOpenCount = _bisSystemReport.DirectoryPeakOpenCount;
outBisUserFatReportInfo.FilePeakOpenCount = _bisUserReport.FilePeakOpenCount;
outBisUserFatReportInfo.DirectoryPeakOpenCount = _bisUserReport.DirectoryPeakOpenCount;
outSdCardFatReportInfo.FilePeakOpenCount = _sdCardReport.FilePeakOpenCount;
outSdCardFatReportInfo.DirectoryPeakOpenCount = _sdCardReport.DirectoryPeakOpenCount;
outBisSystemFatReportInfo1.FilePeakOpenCount = _bisSystemReport.FilePeakOpenCount;
outBisSystemFatReportInfo1.DirectoryPeakOpenCount = _bisSystemReport.DirectoryPeakOpenCount;
outBisUserFatReportInfo1.FilePeakOpenCount = _bisUserReport.FilePeakOpenCount;
outBisUserFatReportInfo1.DirectoryPeakOpenCount = _bisUserReport.DirectoryPeakOpenCount;
outSdCardFatReportInfo1.FilePeakOpenCount = _sdCardReport.FilePeakOpenCount;
outSdCardFatReportInfo1.DirectoryPeakOpenCount = _sdCardReport.DirectoryPeakOpenCount;
_bisSystemReport.FilePeakOpenCount = _bisSystemReport.FileCurrentOpenCount;
_bisSystemReport.DirectoryPeakOpenCount = _bisSystemReport.DirectoryCurrentOpenCount;

View file

@ -0,0 +1,10 @@
using LibHac.Common;
using LibHac.Fs;
using LibHac.Fs.Fsa;
namespace LibHac.FsSrv.FsCreator;
public interface INspRootFileSystemCreator
{
Result Create(ref SharedRef<IFileSystem> outFileSystem, ref readonly SharedRef<IStorage> baseStorage);
}

View file

@ -6,5 +6,5 @@ namespace LibHac.FsSrv.FsCreator;
public interface ISubDirectoryFileSystemCreator
{
Result Create(ref SharedRef<IFileSystem> outSubDirFileSystem, ref SharedRef<IFileSystem> baseFileSystem, ref readonly Path path);
Result Create(ref SharedRef<IFileSystem> outSubDirFileSystem, ref readonly SharedRef<IFileSystem> baseFileSystem, ref readonly Path path);
}

View file

@ -7,7 +7,7 @@ namespace LibHac.FsSrv.FsCreator;
public class SubDirectoryFileSystemCreator : ISubDirectoryFileSystemCreator
{
public Result Create(ref SharedRef<IFileSystem> outSubDirFileSystem, ref SharedRef<IFileSystem> baseFileSystem,
public Result Create(ref SharedRef<IFileSystem> outSubDirFileSystem, ref readonly SharedRef<IFileSystem> baseFileSystem,
ref readonly Path path)
{
using var directory = new UniqueRef<IDirectory>();
@ -17,7 +17,7 @@ public class SubDirectoryFileSystemCreator : ISubDirectoryFileSystemCreator
directory.Reset();
using var subFs = new SharedRef<SubdirectoryFileSystem>(new SubdirectoryFileSystem(ref baseFileSystem));
using var subFs = new SharedRef<SubdirectoryFileSystem>(new SubdirectoryFileSystem(in baseFileSystem));
if (!subFs.HasValue)
return ResultFs.AllocationMemoryFailedInSubDirectoryFileSystemCreatorA.Log();

View file

@ -498,6 +498,10 @@ public class AccessControl
return accessBits.CanSetDebugConfiguration();
case OperationType.OpenDataStorageByPath:
return accessBits.CanOpenDataStorageByPath();
case OperationType.NotifyErrorContextServiceReady:
return accessBits.CanNotifyErrorContextServiceReady();
case OperationType.GetProgramId:
return accessBits.CanGetProgramId();
default:
Abort.UnexpectedDefault();
return default;
@ -593,6 +597,8 @@ public readonly struct AccessControlBits
RegisterProgramIndexMapInfo = 1UL << 34,
CreateOwnSaveData = 1UL << 35,
MoveCacheStorage = 1UL << 36,
DeviceTreeBlob = 1UL << 37,
NotifyErrorContextServiceReady = 1UL << 38,
Debug = 1UL << 62,
FullPermission = 1UL << 63
}
@ -630,6 +636,7 @@ public readonly struct AccessControlBits
public bool CanGetGameCardAsicInfo() => Has(Bits.GameCardPrivate);
public bool CanGetGameCardDeviceCertificate() => Has(Bits.GameCard);
public bool CanGetGameCardIdSet() => Has(Bits.GameCard);
public bool CanGetProgramId() => Has(Bits.GetRightsId);
public bool CanGetRightsId() => Has(Bits.GetRightsId);
public bool CanGetSaveDataCommitId() => Has(Bits.SaveDataTransferVersion2 | Bits.SaveDataBackUp);
public bool CanInvalidateBisCache() => Has(Bits.BisAllRaw);
@ -682,6 +689,7 @@ public readonly struct AccessControlBits
public bool CanMountSystemSaveDataWrite() => Has(Bits.SaveDataBackUp | Bits.SystemSaveData);
public bool CanMountTemporaryDirectoryRead() => Has(Bits.Debug);
public bool CanMountTemporaryDirectoryWrite() => Has(Bits.Debug);
public bool CanNotifyErrorContextServiceReady() => Has(Bits.NotifyErrorContextServiceReady);
public bool CanNotifySystemDataUpdateEvent() => Has(Bits.SystemUpdate);
public bool CanOpenAccessFailureDetectionEventNotifier() => Has(Bits.AccessFailureResolution);
public bool CanOpenBisPartitionBootConfigAndPackage2Part1Read() => Has(Bits.SystemUpdate | Bits.BisAllRaw);
@ -870,7 +878,9 @@ public enum OperationType
FindOwnSaveDataWithFilter,
OpenSaveDataTransferManagerForRepair,
SetDebugConfiguration,
OpenDataStorageByPath
OpenDataStorageByPath,
NotifyErrorContextServiceReady,
GetProgramId
}
public enum AccessibilityType

View file

@ -0,0 +1,46 @@
using System;
using LibHac.Fs;
using LibHac.Os;
using LibHac.Spl;
namespace LibHac.FsSrv.Impl;
public class ExternalKeyManager
{
private SdkMutexType _mutex;
public ExternalKeyManager()
{
_mutex = new SdkMutexType();
}
public Result Register(in RightsId rightsId, in AccessKey accessKey)
{
throw new NotImplementedException();
}
public Result Unregister(in RightsId rightsId)
{
throw new NotImplementedException();
}
public Result UnregisterAll()
{
throw new NotImplementedException();
}
public bool IsAvailableKeySource(ReadOnlySpan<byte> keySource)
{
throw new NotImplementedException();
}
public Result Find(out AccessKey outAccessKey, in RightsId rightsId)
{
throw new NotImplementedException();
}
private Result FindCore(out AccessKey outAccessKey, in RightsId rightsId)
{
throw new NotImplementedException();
}
}

View file

@ -47,11 +47,9 @@ public static class FileSystemProxyServiceObject
return ResultFs.PortAcceptableCountLimited.Log();
}
public Result OpenCodeFileSystem(ref SharedRef<IFileSystem> fileSystem,
out CodeVerificationData verificationData, ref readonly FspPath path, ProgramId programId)
public Result OpenCodeFileSystem(ref SharedRef<IFileSystem> fileSystem, OutBuffer outVerificationData,
ref readonly FspPath path, ContentAttributes attributes, ProgramId programId)
{
UnsafeHelpers.SkipParamInit(out verificationData);
return ResultFs.PortAcceptableCountLimited.Log();
}

View file

@ -8,9 +8,11 @@ namespace LibHac.FsSrv.Impl;
public interface IRomFileSystemAccessFailureManager : IDisposable
{
Result OpenDataStorageCore(ref SharedRef<IStorage> outStorage, out Hash ncaHeaderDigest, ulong id, StorageId storageId);
Result HandleResolubleAccessFailure(out bool wasDeferred, Result resultForNoFailureDetected);
Result OpenDataStorageCore(ref SharedRef<IStorage> outStorage, ref SharedRef<IAsynchronousAccessSplitter> outStorageAccessSplitter, out Hash ncaHeaderDigest, ulong id, StorageId storageId);
Result HandleResolubleAccessFailure(out bool wasDeferred, Result nonDeferredResult);
void IncrementRomFsDeepRetryStartCount();
void IncrementRomFsRemountForDataCorruptionCount();
void IncrementRomFsUnrecoverableDataCorruptionByRemountCount();
void IncrementRomFsRecoveredByInvalidateCacheCount();
void IncrementRomFsUnrecoverableByGameCardAccessFailedCount();
}

View file

@ -0,0 +1,32 @@
using System;
using LibHac.Common;
namespace LibHac.FsSrv.Impl;
public class SystemDataUpdateEventManager : IDisposable
{
public SystemDataUpdateEventManager()
{
// Todo: Implement
}
public void Dispose()
{
throw new NotImplementedException();
}
public Result CreateNotifier(ref UniqueRef<SystemDataUpdateEventNotifier> outNotifier)
{
throw new NotImplementedException();
}
public Result NotifySystemDataUpdateEvent()
{
throw new NotImplementedException();
}
public void DeleteNotifier(SystemDataUpdateEventNotifier notifier)
{
throw new NotImplementedException();
}
}

View file

@ -0,0 +1,22 @@
using System;
using LibHac.Sf;
namespace LibHac.FsSrv.Impl;
public class SystemDataUpdateEventNotifier : IDisposable
{
public SystemDataUpdateEventNotifier()
{
throw new NotImplementedException();
}
public void Dispose()
{
throw new NotImplementedException();
}
public Result GetEventHandle(out NativeHandle outHandle)
{
throw new NotImplementedException();
}
}

View file

@ -0,0 +1,67 @@
using System;
using LibHac.Common;
using LibHac.Fs;
using LibHac.Fs.Impl;
using LibHac.Os;
namespace LibHac.FsSrv.Impl;
public class UpdatePartitionPath : IDisposable
{
private Path.Stored _path;
private ContentAttributes _contentAttributes;
private ulong _updaterProgramId;
private SdkMutexType _mutex;
public UpdatePartitionPath()
{
_path = new Path.Stored();
_mutex = new SdkMutexType();
_path.InitializeAsEmpty();
}
public void Dispose()
{
_path.Dispose();
}
public Result Set(ulong updaterProgramId, ref readonly Path path, ContentAttributes contentAttributes)
{
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
if (path.IsEmpty())
{
return _path.InitializeAsEmpty().Ret();
}
if (path.IsMatchHead(CommonMountNames.RegisteredUpdatePartitionMountName, CommonMountNames.RegisteredUpdatePartitionMountName.Length))
{
return ResultFs.InvalidPath.Log();
}
Result res = _path.Initialize(in path);
if (res.IsFailure()) return res.Miss();
_updaterProgramId = updaterProgramId;
_contentAttributes = contentAttributes;
return Result.Success;
}
public Result Get(ref Path outPath, out ContentAttributes outContentAttributes, out ulong outUpdaterProgramId)
{
UnsafeHelpers.SkipParamInit(out outContentAttributes);
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
using Path tempPath = _path.DangerousGetPath();
outUpdaterProgramId = _updaterProgramId;
Result res = _path.Initialize(in tempPath);
if (res.IsFailure()) return res.Miss();
outContentAttributes = _contentAttributes;
return Result.Success;
}
}

View file

@ -70,4 +70,10 @@ internal static class Utility
Crypto.Sha256.GenerateSha256Hash(SpanHelpers.AsReadOnlyByteSpan(in extraData), hash);
return BitConverter.ToInt64(hash);
}
public static ulong ClearPlatformIdInProgramId(ulong programId)
{
const ulong clearPlatformIdMask = 0x_00FF_FFFF_FFFF_FFFF;
return programId & clearPlatformIdMask;
}
}

View file

@ -8,6 +8,7 @@ using LibHac.FsSrv.Sf;
using LibHac.FsSystem;
using LibHac.Lr;
using LibHac.Ncm;
using LibHac.Sf;
using LibHac.Spl;
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
using IStorage = LibHac.Fs.IStorage;
@ -22,12 +23,14 @@ internal class NcaFileSystemService : IRomFileSystemAccessFailureManager
{
private const int AocSemaphoreCount = 128;
private const int RomSemaphoreCount = 10;
private const int RomDivisionSizeUnitCountSemaphoreCount = 128;
private WeakRef<NcaFileSystemService> _selfReference;
private NcaFileSystemServiceImpl _serviceImpl;
private ulong _processId;
private SemaphoreAdapter _aocMountCountSemaphore;
private SemaphoreAdapter _romMountCountSemaphore;
private SemaphoreAdapter _romDivisionSizeUnitCountSemaphore;
private NcaFileSystemService(NcaFileSystemServiceImpl serviceImpl, ulong processId)
{
@ -35,6 +38,7 @@ internal class NcaFileSystemService : IRomFileSystemAccessFailureManager
_processId = processId;
_aocMountCountSemaphore = new SemaphoreAdapter(AocSemaphoreCount, AocSemaphoreCount);
_romMountCountSemaphore = new SemaphoreAdapter(RomSemaphoreCount, RomSemaphoreCount);
_romDivisionSizeUnitCountSemaphore = new SemaphoreAdapter(RomDivisionSizeUnitCountSemaphoreCount, RomDivisionSizeUnitCountSemaphoreCount);
}
public static SharedRef<NcaFileSystemService> CreateShared(NcaFileSystemServiceImpl serviceImpl,
@ -54,22 +58,26 @@ internal class NcaFileSystemService : IRomFileSystemAccessFailureManager
{
_aocMountCountSemaphore?.Dispose();
_romMountCountSemaphore?.Dispose();
_romDivisionSizeUnitCountSemaphore?.Dispose();
_selfReference.Destroy();
}
private Result GetProgramInfo(out ProgramInfo programInfo)
{
return _serviceImpl.GetProgramInfoByProcessId(out programInfo, _processId);
var programRegistry = new ProgramRegistryImpl(_serviceImpl.FsServer);
return programRegistry.GetProgramInfo(out programInfo, _processId).Ret();
}
private Result GetProgramInfoByProcessId(out ProgramInfo programInfo, ulong processId)
{
return _serviceImpl.GetProgramInfoByProcessId(out programInfo, processId);
var programRegistry = new ProgramRegistryImpl(_serviceImpl.FsServer);
return programRegistry.GetProgramInfo(out programInfo, processId).Ret();
}
private Result GetProgramInfoByProgramId(out ProgramInfo programInfo, ulong programId)
{
return _serviceImpl.GetProgramInfoByProgramId(out programInfo, programId);
var programRegistry = new ProgramRegistryImpl(_serviceImpl.FsServer);
return programRegistry.GetProgramInfoByProgramId(out programInfo, programId).Ret();
}
public Result OpenFileSystemWithPatch(ref SharedRef<IFileSystemSf> outFileSystem, ProgramId programId,
@ -110,7 +118,8 @@ internal class NcaFileSystemService : IRomFileSystemAccessFailureManager
// Try to find the path to the original version of the file system
using var originalPath = new Path();
Result originalResult = _serviceImpl.ResolveApplicationHtmlDocumentPath(out bool isDirectory,
ref originalPath.Ref(), new Ncm.ApplicationId(programId.Value), ownerProgramInfo.StorageId);
ref originalPath.Ref(), out ContentAttributes contentAttributes, out ulong originalProgramId,
programId.Value, ownerProgramInfo.StorageId);
// The file system might have a patch version with no original version, so continue if not found
if (originalResult.IsFailure() && !ResultLr.HtmlDocumentNotFound.Includes(originalResult))
@ -118,7 +127,8 @@ internal class NcaFileSystemService : IRomFileSystemAccessFailureManager
// Try to find the path to the patch file system
using var patchPath = new Path();
Result patchResult = _serviceImpl.ResolveRegisteredHtmlDocumentPath(ref patchPath.Ref(), programId.Value);
Result patchResult = _serviceImpl.ResolveRegisteredHtmlDocumentPath(ref patchPath.Ref(),
out ContentAttributes patchContentAttributes, programId.Value);
using var fileSystem = new SharedRef<IFileSystem>();
@ -129,7 +139,7 @@ internal class NcaFileSystemService : IRomFileSystemAccessFailureManager
return originalResult;
// There is an original version and no patch version. Open the original directly
res = _serviceImpl.OpenFileSystem(ref fileSystem.Ref, in originalPath, fsType, programId.Value,
res = _serviceImpl.OpenFileSystem(ref fileSystem.Ref, in originalPath, default, fsType, programId.Value,
isDirectory);
if (res.IsFailure()) return res.Miss();
}
@ -143,8 +153,8 @@ internal class NcaFileSystemService : IRomFileSystemAccessFailureManager
: ref PathExtensions.GetNullRef();
// Open the file system using both the original and patch versions
res = _serviceImpl.OpenFileSystemWithPatch(ref fileSystem.Ref, in originalNcaPath, in patchPath,
fsType, programId.Value);
res = _serviceImpl.OpenFileSystemWithPatch(ref fileSystem.Ref, in originalNcaPath, contentAttributes,
in patchPath, patchContentAttributes, fsType, originalProgramId, programId.Value);
if (res.IsFailure()) return res.Miss();
}
@ -169,8 +179,8 @@ internal class NcaFileSystemService : IRomFileSystemAccessFailureManager
return Result.Success;
}
public Result OpenCodeFileSystem(ref SharedRef<IFileSystemSf> outFileSystem,
out CodeVerificationData verificationData, ref readonly FspPath path, ProgramId programId)
public Result OpenCodeFileSystem(ref SharedRef<IFileSystemSf> outFileSystem, OutBuffer outVerificationData,
ref readonly FspPath path, ContentAttributes attributes, ProgramId programId)
{
throw new NotImplementedException();
}
@ -181,21 +191,32 @@ internal class NcaFileSystemService : IRomFileSystemAccessFailureManager
}
public Result OpenDataStorageByPath(ref SharedRef<IFileSystemSf> outFileSystem, ref readonly FspPath path,
FileSystemProxyType fsType)
ContentAttributes attributes, FileSystemProxyType fsType)
{
throw new NotImplementedException();
}
private Result TryAcquireAddOnContentOpenCountSemaphore(ref UniqueRef<IUniqueLock> outSemaphoreLock)
private Result TryAcquireAddOnContentDivisionSizeUnitCountSemaphore(ref UniqueRef<IUniqueLock> outSemaphore, IStorage storage)
{
throw new NotImplementedException();
}
private Result TryAcquireRomMountCountSemaphore(ref UniqueRef<IUniqueLock> outSemaphoreLock)
private Result TryAcquireRomMountCountSemaphore(ref UniqueRef<IUniqueLock> outSemaphore)
{
throw new NotImplementedException();
}
private Result TryAcquireRomDivisionSizeUnitCountSemaphore(ref UniqueRef<IUniqueLock> outSemaphore,
ref UniqueRef<IUniqueLock> mountCountSemaphore, IStorage storage)
{
throw new NotImplementedException();
}
public void IncrementRomFsDeepRetryStartCount()
{
_serviceImpl.IncrementRomFsRemountForDataCorruptionCount();
}
public void IncrementRomFsRemountForDataCorruptionCount()
{
_serviceImpl.IncrementRomFsRemountForDataCorruptionCount();
@ -211,8 +232,14 @@ internal class NcaFileSystemService : IRomFileSystemAccessFailureManager
_serviceImpl.IncrementRomFsRecoveredByInvalidateCacheCount();
}
private Result OpenDataStorageCore(ref SharedRef<IStorage> outStorage, out Hash ncaHeaderDigest,
ulong id, StorageId storageId)
public void IncrementRomFsUnrecoverableByGameCardAccessFailedCount()
{
_serviceImpl.IncrementRomFsRecoveredByInvalidateCacheCount();
}
private Result OpenDataStorageCore(ref SharedRef<IStorage> outStorage,
ref SharedRef<IAsynchronousAccessSplitter> outStorageAccessSplitter, out Hash ncaHeaderDigest, ulong id,
StorageId storageId)
{
throw new NotImplementedException();
}
@ -227,8 +254,14 @@ internal class NcaFileSystemService : IRomFileSystemAccessFailureManager
throw new NotImplementedException();
}
public Result OpenFileSystemWithId(ref SharedRef<IFileSystemSf> outFileSystem, ref readonly FspPath path,
ulong id, FileSystemProxyType fsType)
public Result OpenDataStorageByPath(ref SharedRef<IStorageSf> outStorage, in FspPath path,
ContentAttributes attributes, FileSystemProxyType fspType)
{
throw new NotImplementedException();
}
public Result OpenFileSystemWithId(ref SharedRef<IFileSystemSf> outFileSystem, in FspPath path,
ContentAttributes attributes, ulong id, FileSystemProxyType fsType)
{
const StorageLayoutType storageFlag = StorageLayoutType.All;
using var scopedContext = new ScopedStorageLayoutTypeSetter(storageFlag);
@ -292,7 +325,7 @@ internal class NcaFileSystemService : IRomFileSystemAccessFailureManager
bool isDirectory = PathUtility.IsDirectoryPath(in path);
using var fileSystem = new SharedRef<IFileSystem>();
res = _serviceImpl.OpenFileSystem(ref fileSystem.Ref, in pathNormalized, fsType, canMountSystemDataPrivate,
res = _serviceImpl.OpenFileSystem(ref fileSystem.Ref, in pathNormalized, default, fsType, canMountSystemDataPrivate,
id, isDirectory);
if (res.IsFailure()) return res.Miss();
@ -321,6 +354,16 @@ internal class NcaFileSystemService : IRomFileSystemAccessFailureManager
throw new NotImplementedException();
}
public Result OpenDataFileSystemByDataId(ref SharedRef<IFileSystemSf> outFileSystem, DataId dataId, StorageId storageId)
{
throw new NotImplementedException();
}
public Result OpenPatchDataStorageByCurrentProcess(ref SharedRef<IStorageSf> outStorage)
{
throw new NotImplementedException();
}
public Result OpenDataFileSystemWithProgramIndex(ref SharedRef<IFileSystemSf> outFileSystem, byte programIndex)
{
Result res = GetProgramInfo(out ProgramInfo programInfo);
@ -372,13 +415,14 @@ internal class NcaFileSystemService : IRomFileSystemAccessFailureManager
return ResultFs.PermissionDenied.Log();
using var programPath = new Path();
res = _serviceImpl.ResolveProgramPath(out bool isDirectory, ref programPath.Ref(), programId, storageId);
res = _serviceImpl.ResolveProgramPath(out bool isDirectory, ref programPath.Ref(),
out ContentAttributes contentAttributes, programId, storageId);
if (res.IsFailure()) return res.Miss();
if (isDirectory)
return ResultFs.TargetNotFound.Log();
res = _serviceImpl.GetRightsId(out RightsId rightsId, out _, in programPath, programId);
res = _serviceImpl.GetRightsId(out RightsId rightsId, out _, in programPath, contentAttributes, programId);
if (res.IsFailure()) return res.Miss();
outRightsId = rightsId;
@ -386,7 +430,8 @@ internal class NcaFileSystemService : IRomFileSystemAccessFailureManager
return Result.Success;
}
public Result GetRightsIdAndKeyGenerationByPath(out RightsId outRightsId, out byte outKeyGeneration, ref readonly FspPath path)
public Result GetRightsIdAndKeyGenerationByPath(out RightsId outRightsId, out byte outKeyGeneration,
ref readonly FspPath path, ContentAttributes attributes)
{
const ulong checkThroughProgramId = ulong.MaxValue;
UnsafeHelpers.SkipParamInit(out outRightsId, out outKeyGeneration);
@ -412,7 +457,7 @@ internal class NcaFileSystemService : IRomFileSystemAccessFailureManager
if (PathUtility.IsDirectoryPath(in path))
return ResultFs.TargetNotFound.Log();
res = _serviceImpl.GetRightsId(out RightsId rightsId, out byte keyGeneration, in pathNormalized,
res = _serviceImpl.GetRightsId(out RightsId rightsId, out byte keyGeneration, in pathNormalized, default,
new ProgramId(checkThroughProgramId));
if (res.IsFailure()) return res.Miss();
@ -422,9 +467,14 @@ internal class NcaFileSystemService : IRomFileSystemAccessFailureManager
return Result.Success;
}
public Result GetProgramId(out ProgramId outProgramId, ref readonly FspPath path, ContentAttributes attributes)
{
throw new NotImplementedException();
}
// ReSharper disable once OutParameterValueIsAlwaysDiscarded.Local
private Result OpenDataFileSystemCore(ref SharedRef<IFileSystem> outFileSystem, out bool isHostFs,
ulong programId, StorageId storageId)
private Result OpenDataFileSystemCore(ref SharedRef<IFileSystem> outFileSystem, out bool isHostFs, ulong programId,
StorageId storageId)
{
UnsafeHelpers.SkipParamInit(out isHostFs);
@ -432,13 +482,14 @@ internal class NcaFileSystemService : IRomFileSystemAccessFailureManager
using var scopedContext = new ScopedStorageLayoutTypeSetter(storageFlag);
using var programPath = new Path();
Result res = _serviceImpl.ResolveRomPath(out bool isDirectory, ref programPath.Ref(), programId, storageId);
Result res = _serviceImpl.ResolveRomPath(out bool isDirectory, ref programPath.Ref(),
out ContentAttributes contentAttributes, out _, programId, storageId);
if (res.IsFailure()) return res.Miss();
isHostFs = Utility.IsHostFsMountName(programPath.GetString());
using var fileSystem = new SharedRef<IFileSystem>();
res = _serviceImpl.OpenDataFileSystem(ref fileSystem.Ref, in programPath, FileSystemProxyType.Rom,
res = _serviceImpl.OpenDataFileSystem(ref fileSystem.Ref, in programPath, contentAttributes, FileSystemProxyType.Rom,
programId, isDirectory);
if (res.IsFailure()) return res.Miss();
@ -529,10 +580,11 @@ internal class NcaFileSystemService : IRomFileSystemAccessFailureManager
ulong targetProgramId = programInfo.ProgramIdValue;
using var programPath = new Path();
res = _serviceImpl.ResolveRomPath(out _, ref programPath.Ref(), targetProgramId, programInfo.StorageId);
res = _serviceImpl.ResolveRomPath(out _, ref programPath.Ref(), out ContentAttributes contentAttributes, out _,
targetProgramId, programInfo.StorageId);
if (res.IsFailure()) return res.Miss();
return _serviceImpl.RegisterUpdatePartition(targetProgramId, in programPath);
return _serviceImpl.RegisterUpdatePartition(targetProgramId, in programPath, contentAttributes);
}
public Result OpenRegisteredUpdatePartition(ref SharedRef<IFileSystemSf> outFileSystem)
@ -583,6 +635,11 @@ internal class NcaFileSystemService : IRomFileSystemAccessFailureManager
return _serviceImpl.SetSdCardEncryptionSeed(in encryptionSeed);
}
public Result OpenHostFileSystem(ref SharedRef<IFileSystemSf> outFileSystem, ref readonly FspPath path)
{
throw new NotImplementedException();
}
public Result OpenSystemDataUpdateEventNotifier(ref SharedRef<IEventNotifier> outEventNotifier)
{
throw new NotImplementedException();
@ -593,14 +650,15 @@ internal class NcaFileSystemService : IRomFileSystemAccessFailureManager
throw new NotImplementedException();
}
public Result HandleResolubleAccessFailure(out bool wasDeferred, Result resultForNoFailureDetected)
public Result HandleResolubleAccessFailure(out bool wasDeferred, Result nonDeferredResult)
{
return _serviceImpl.HandleResolubleAccessFailure(out wasDeferred, resultForNoFailureDetected, _processId);
return _serviceImpl.HandleResolubleAccessFailure(out wasDeferred, nonDeferredResult, _processId);
}
Result IRomFileSystemAccessFailureManager.OpenDataStorageCore(ref SharedRef<IStorage> outStorage,
out Hash ncaHeaderDigest, ulong id, StorageId storageId)
ref SharedRef<IAsynchronousAccessSplitter> outStorageAccessSplitter, out Hash ncaHeaderDigest, ulong id,
StorageId storageId)
{
return OpenDataStorageCore(ref outStorage, out ncaHeaderDigest, id, storageId);
return OpenDataStorageCore(ref outStorage, ref outStorageAccessSplitter, out ncaHeaderDigest, id, storageId).Ret();
}
}

File diff suppressed because it is too large Load diff

View file

@ -13,14 +13,15 @@ namespace LibHac.FsSrv.Sf;
/// <summary>
/// The interface most programs use to interact with the FS service.
/// </summary>
/// <remarks>Based on nnSdk 14.3.0 (FS 14.1.0)</remarks>
/// <remarks>Based on nnSdk 17.5.0 (FS 17.0.0)</remarks>
public interface IFileSystemProxy : IDisposable
{
Result SetCurrentProcess(ulong processId);
Result OpenDataFileSystemByCurrentProcess(ref SharedRef<IFileSystemSf> outFileSystem);
Result OpenFileSystemWithPatch(ref SharedRef<IFileSystemSf> outFileSystem, ProgramId programId, FileSystemProxyType fsType);
Result OpenFileSystemWithId(ref SharedRef<IFileSystemSf> outFileSystem, ref readonly FspPath path, ulong id, FileSystemProxyType fsType);
Result OpenFileSystemWithIdObsolete(ref SharedRef<IFileSystemSf> outFileSystem, ref readonly FspPath path, ulong programId, FileSystemProxyType fsType);
Result OpenDataFileSystemByProgramId(ref SharedRef<IFileSystemSf> outFileSystem, ProgramId programId);
Result OpenFileSystemWithId(ref SharedRef<IFileSystemSf> outFileSystem, ref readonly FspPath path, ContentAttributes attributes, ulong programId, FileSystemProxyType fsType);
Result OpenBisFileSystem(ref SharedRef<IFileSystemSf> outFileSystem, ref readonly FspPath rootPath, BisPartitionId partitionId);
Result OpenBisStorage(ref SharedRef<IStorageSf> outStorage, BisPartitionId partitionId);
Result InvalidateBisCache();
@ -72,15 +73,15 @@ public interface IFileSystemProxy : IDisposable
Result OpenBaseFileSystem(ref SharedRef<IFileSystemSf> outFileSystem, BaseFileSystemId fileSystemId);
Result FormatBaseFileSystem(BaseFileSystemId fileSystemId);
Result OpenContentStorageFileSystem(ref SharedRef<IFileSystemSf> outFileSystem, ContentStorageId storageId);
Result OpenCloudBackupWorkStorageFileSystem(ref SharedRef<IFileSystemSf> outFileSystem, CloudBackupWorkStorageId storageId);
Result OpenCustomStorageFileSystem(ref SharedRef<IFileSystemSf> outFileSystem, CustomStorageId storageId);
Result OpenDataStorageByCurrentProcess(ref SharedRef<IStorageSf> outStorage);
Result OpenDataStorageByProgramId(ref SharedRef<IStorageSf> outStorage, ProgramId programId);
Result OpenDataStorageByDataId(ref SharedRef<IStorageSf> outStorage, DataId dataId, StorageId storageId);
Result OpenPatchDataStorageByCurrentProcess(ref SharedRef<IStorageSf> outStorage);
Result OpenDataFileSystemWithProgramIndex(ref SharedRef<IFileSystemSf> outFileSystem, byte programIndex);
Result OpenDataStorageByPath(ref SharedRef<IFileSystemSf> outFileSystem, ref readonly FspPath path, FileSystemProxyType fsType);
Result OpenDataStorageWithProgramIndex(ref SharedRef<IStorageSf> outStorage, byte programIndex);
Result OpenDataStorageByPath(ref SharedRef<IFileSystemSf> outFileSystem, ref readonly FspPath path, ContentAttributes attributes, FileSystemProxyType fsType);
Result OpenDataFileSystemByDataId(ref SharedRef<IFileSystemSf> outFileSystem, DataId dataId, StorageId storageId);
Result OpenDeviceOperator(ref SharedRef<IDeviceOperator> outDeviceOperator);
Result OpenSdCardDetectionEventNotifier(ref SharedRef<IEventNotifier> outEventNotifier);
Result OpenGameCardDetectionEventNotifier(ref SharedRef<IEventNotifier> outEventNotifier);
@ -95,8 +96,7 @@ public interface IFileSystemProxy : IDisposable
Result GetRightsId(out RightsId rightsId, ProgramId programId, StorageId storageId);
Result RegisterExternalKey(in RightsId rightsId, in AccessKey externalKey);
Result UnregisterAllExternalKey();
Result GetRightsIdByPath(out RightsId rightsId, ref readonly FspPath path);
Result GetRightsIdAndKeyGenerationByPath(out RightsId rightsId, out byte keyGeneration, ref readonly FspPath path);
Result GetRightsIdAndKeyGenerationByPath(out RightsId rightsId, out byte keyGeneration, ref readonly FspPath path, ContentAttributes attributes);
Result SetCurrentPosixTimeWithTimeDifference(long currentTime, int timeDifference);
Result GetFreeSpaceSizeForSaveData(out long freeSpaceSize, SaveDataSpaceId spaceId);
Result VerifySaveDataFileSystemBySaveDataSpaceId(SaveDataSpaceId spaceId, ulong saveDataId, OutBuffer readBuffer);
@ -104,6 +104,7 @@ public interface IFileSystemProxy : IDisposable
Result QuerySaveDataInternalStorageTotalSize(out long size, SaveDataSpaceId spaceId, ulong saveDataId);
Result GetSaveDataCommitId(out long commitId, SaveDataSpaceId spaceId, ulong saveDataId);
Result UnregisterExternalKey(in RightsId rightsId);
Result GetProgramId(out ProgramId outProgramId, ref readonly FspPath path, ContentAttributes attributes);
Result SetSdCardEncryptionSeed(in EncryptionSeed seed);
Result SetSdCardAccessibility(bool isAccessible);
Result IsSdCardAccessible(out bool isAccessible);
@ -114,7 +115,6 @@ public interface IFileSystemProxy : IDisposable
Result AbandonAccessFailure(ulong processId);
Result GetAndClearErrorInfo(out FileSystemProxyErrorInfo errorInfo);
Result RegisterProgramIndexMapInfo(InBuffer programIndexMapInfoBuffer, int programCount);
Result SetBisRootForHost(BisPartitionId partitionId, ref readonly FspPath path);
Result SetSaveDataSize(long saveDataSize, long saveDataJournalSize);
Result SetSaveDataRootPath(ref readonly FspPath path);
Result DisableAutoSaveDataCreation();
@ -136,4 +136,5 @@ public interface IFileSystemProxy : IDisposable
Result CorruptSaveDataFileSystemByOffset(SaveDataSpaceId spaceId, ulong saveDataId, long offset);
Result OpenMultiCommitManager(ref SharedRef<IMultiCommitManager> outCommitManager);
Result OpenBisWiper(ref SharedRef<IWiper> outBisWiper, NativeHandle transferMemoryHandle, ulong transferMemorySize);
Result NotifyErrorContextServiceReady(bool isReady);
}

View file

@ -2,14 +2,15 @@
using LibHac.Common;
using LibHac.Fs;
using LibHac.Ncm;
using LibHac.Sf;
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
namespace LibHac.FsSrv.Sf;
public interface IFileSystemProxyForLoader : IDisposable
{
Result OpenCodeFileSystem(ref SharedRef<IFileSystemSf> fileSystem,
out CodeVerificationData verificationData, ref readonly FspPath path, ProgramId programId);
Result OpenCodeFileSystem(ref SharedRef<IFileSystemSf> fileSystem, OutBuffer outVerificationData,
ref readonly FspPath path, ContentAttributes attributes, ProgramId programId);
Result IsArchivedProgram(out bool isArchived, ulong processId);
Result SetCurrentProcess(ulong processId);

View file

@ -76,15 +76,15 @@ public class StatusReportServiceImpl
Assert.SdkRequiresNotNull(_config.NcaFileSystemServiceImpl);
_config.NcaFileSystemServiceImpl.GetAndClearRomFsErrorInfo(out errorInfo.RemountForDataCorruptionCount,
out errorInfo.UnrecoverableDataCorruptionByRemountCount,
out errorInfo.RecoveredByInvalidateCacheCount);
_config.NcaFileSystemServiceImpl.GetAndClearRomFsErrorInfo(out errorInfo.DeepRetryStartCount,
out errorInfo.RemountForDataCorruptionCount, out errorInfo.UnrecoverableDataCorruptionByRemountCount,
out errorInfo.RecoveredByInvalidateCacheCount, out errorInfo.UnrecoverableByGameCardAccessFailedCount);
if (_config.FatFileSystemCreator is not null)
{
_config.FatFileSystemCreator.GetAndClearFatFsError(out errorInfo.FatFsError);
_config.FatFileSystemCreator.GetAndClearFatReportInfo(out errorInfo.BisSystemFatReportInfo,
out errorInfo.BisUserFatReport, out errorInfo.SdCardFatReport);
_config.FatFileSystemCreator.GetAndClearFatReportInfo(out errorInfo.BisSystemFatReportInfo1,
out errorInfo.BisUserFatReport1, out errorInfo.SdCardFatReport1);
}
Assert.SdkRequiresNotNull(_config.SaveDataFileSystemServiceImpl);

View file

@ -20,9 +20,9 @@ public class SubdirectoryFileSystem : IFileSystem
_baseFileSystem = baseFileSystem;
}
public SubdirectoryFileSystem(ref SharedRef<IFileSystem> baseFileSystem)
public SubdirectoryFileSystem(ref readonly SharedRef<IFileSystem> baseFileSystem)
{
_baseFileSystemShared = SharedRef<IFileSystem>.CreateMove(ref baseFileSystem);
_baseFileSystemShared = SharedRef<IFileSystem>.CreateCopy(in baseFileSystem);
_baseFileSystem = _baseFileSystemShared.Get;
}

View file

@ -0,0 +1,46 @@
//-----------------------------------------------------------------------------
// This file was automatically generated.
// Changes to this file will be lost when the file is regenerated.
//
// To change this file, modify /build/CodeGen/results.csv at the root of this
// repo and run the build script.
//
// The script can be run with the "codegen" option to run only the
// code generation portion of the build.
//-----------------------------------------------------------------------------
namespace LibHac.Htc;
public static class ResultHtc
{
public const int ModuleHtc = 18;
/// <summary>Error code: 2018-0001; Inner value: 0x212</summary>
public static Result.Base ConnectionFailure => new Result.Base(ModuleHtc, 1);
/// <summary>Error code: 2018-0002; Inner value: 0x412</summary>
public static Result.Base NotFound => new Result.Base(ModuleHtc, 2);
/// <summary>Error code: 2018-0003; Inner value: 0x612</summary>
public static Result.Base NotEnoughBuffer => new Result.Base(ModuleHtc, 3);
/// <summary>Error code: 2018-0101; Inner value: 0xca12</summary>
public static Result.Base Cancelled => new Result.Base(ModuleHtc, 101);
/// <summary>Error code: 2018-1023; Inner value: 0x7fe12</summary>
public static Result.Base Result1023 => new Result.Base(ModuleHtc, 1023);
/// <summary>Error code: 2018-2001; Inner value: 0xfa212</summary>
public static Result.Base Result2001 => new Result.Base(ModuleHtc, 2001);
/// <summary>Error code: 2018-2003; Inner value: 0xfa612</summary>
public static Result.Base InvalidTaskId => new Result.Base(ModuleHtc, 2003);
/// <summary>Error code: 2018-2011; Inner value: 0xfb612</summary>
public static Result.Base InvalidSize => new Result.Base(ModuleHtc, 2011);
/// <summary>Error code: 2018-2021; Inner value: 0xfca12</summary>
public static Result.Base TaskCancelled => new Result.Base(ModuleHtc, 2021);
/// <summary>Error code: 2018-2022; Inner value: 0xfcc12</summary>
public static Result.Base TaskNotCompleted => new Result.Base(ModuleHtc, 2022);
/// <summary>Error code: 2018-2023; Inner value: 0xfce12</summary>
public static Result.Base TaskQueueNotAvailable => new Result.Base(ModuleHtc, 2023);
/// <summary>Error code: 2018-2101; Inner value: 0x106a12</summary>
public static Result.Base Result2101 => new Result.Base(ModuleHtc, 2101);
/// <summary>Error code: 2018-2102; Inner value: 0x106c12</summary>
public static Result.Base OutOfRpcTask => new Result.Base(ModuleHtc, 2102);
/// <summary>Error code: 2018-2123; Inner value: 0x109612</summary>
public static Result.Base InvalidCategory => new Result.Base(ModuleHtc, 2123);
}

View file

@ -0,0 +1,57 @@
//-----------------------------------------------------------------------------
// This file was automatically generated.
// Changes to this file will be lost when the file is regenerated.
//
// To change this file, modify /build/CodeGen/results.csv at the root of this
// repo and run the build script.
//
// The script can be run with the "codegen" option to run only the
// code generation portion of the build.
//-----------------------------------------------------------------------------
using System.Runtime.CompilerServices;
namespace LibHac.HtcFs;
public static class ResultHtcFs
{
public const int ModuleHtcFs = 31;
/// <summary>Error code: 2031-0003; Inner value: 0x61f</summary>
public static Result.Base InvalidArgument => new Result.Base(ModuleHtcFs, 3);
/// <summary>Error code: 2031-0100; Range: 100-199; Inner value: 0xc81f</summary>
public static Result.Base ConnectionFailure => new Result.Base(ModuleHtcFs, 100, 199);
/// <summary>Error code: 2031-0101; Inner value: 0xca1f</summary>
public static Result.Base HtclowChannelClosed => new Result.Base(ModuleHtcFs, 101);
/// <summary>Error code: 2031-0110; Range: 110-119; Inner value: 0xdc1f</summary>
public static Result.Base UnexpectedResponse => new Result.Base(ModuleHtcFs, 110, 119);
/// <summary>Error code: 2031-0111; Inner value: 0xde1f</summary>
public static Result.Base UnexpectedResponseProtocolId => new Result.Base(ModuleHtcFs, 111);
/// <summary>Error code: 2031-0112; Inner value: 0xe01f</summary>
public static Result.Base UnexpectedResponseProtocolVersion => new Result.Base(ModuleHtcFs, 112);
/// <summary>Error code: 2031-0113; Inner value: 0xe21f</summary>
public static Result.Base UnexpectedResponsePacketCategory => new Result.Base(ModuleHtcFs, 113);
/// <summary>Error code: 2031-0114; Inner value: 0xe41f</summary>
public static Result.Base UnexpectedResponsePacketType => new Result.Base(ModuleHtcFs, 114);
/// <summary>Error code: 2031-0115; Inner value: 0xe61f</summary>
public static Result.Base UnexpectedResponseBodySize => new Result.Base(ModuleHtcFs, 115);
/// <summary>Error code: 2031-0116; Inner value: 0xe81f</summary>
public static Result.Base UnexpectedResponseBody => new Result.Base(ModuleHtcFs, 116);
/// <summary>Error code: 2031-0200; Range: 200-299; Inner value: 0x1901f</summary>
public static Result.Base InternalError { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleHtcFs, 200, 299); }
/// <summary>Error code: 2031-0201; Inner value: 0x1921f</summary>
public static Result.Base InvalidSize => new Result.Base(ModuleHtcFs, 201);
/// <summary>Error code: 2031-0211; Inner value: 0x1a61f</summary>
public static Result.Base UnknownError => new Result.Base(ModuleHtcFs, 211);
/// <summary>Error code: 2031-0212; Inner value: 0x1a81f</summary>
public static Result.Base UnsupportedProtocolVersion => new Result.Base(ModuleHtcFs, 212);
/// <summary>Error code: 2031-0213; Inner value: 0x1aa1f</summary>
public static Result.Base InvalidRequest => new Result.Base(ModuleHtcFs, 213);
/// <summary>Error code: 2031-0214; Inner value: 0x1ac1f</summary>
public static Result.Base InvalidHandle => new Result.Base(ModuleHtcFs, 214);
/// <summary>Error code: 2031-0215; Inner value: 0x1ae1f</summary>
public static Result.Base OutOfHandle => new Result.Base(ModuleHtcFs, 215);
}

View file

@ -0,0 +1,116 @@
//-----------------------------------------------------------------------------
// This file was automatically generated.
// Changes to this file will be lost when the file is regenerated.
//
// To change this file, modify /build/CodeGen/results.csv at the root of this
// repo and run the build script.
//
// The script can be run with the "codegen" option to run only the
// code generation portion of the build.
//-----------------------------------------------------------------------------
using System.Runtime.CompilerServices;
namespace LibHac.HtcLow;
public static class ResultHtcLow
{
public const int ModuleHtcLow = 29;
/// <summary>Error code: 2029-0001; Inner value: 0x21d</summary>
public static Result.Base ConnectionFailure => new Result.Base(ModuleHtcLow, 1);
/// <summary>Error code: 2029-0003; Inner value: 0x61d</summary>
public static Result.Base UnknownDriverType => new Result.Base(ModuleHtcLow, 3);
/// <summary>Error code: 2029-0005; Inner value: 0xa1d</summary>
public static Result.Base NonBlockingReceiveFailed => new Result.Base(ModuleHtcLow, 5);
/// <summary>Error code: 2029-0008; Inner value: 0x101d</summary>
public static Result.Base ChannelWaitCancelled => new Result.Base(ModuleHtcLow, 8);
/// <summary>Error code: 2029-0009; Inner value: 0x121d</summary>
public static Result.Base ChannelAlreadyExist => new Result.Base(ModuleHtcLow, 9);
/// <summary>Error code: 2029-0010; Inner value: 0x141d</summary>
public static Result.Base ChannelNotExist => new Result.Base(ModuleHtcLow, 10);
/// <summary>Error code: 2029-0151; Inner value: 0x12e1d</summary>
public static Result.Base OutOfChannel => new Result.Base(ModuleHtcLow, 151);
/// <summary>Error code: 2029-0152; Inner value: 0x1301d</summary>
public static Result.Base OutOfTask => new Result.Base(ModuleHtcLow, 152);
/// <summary>Error code: 2029-0200; Inner value: 0x1901d</summary>
public static Result.Base InvalidChannelState => new Result.Base(ModuleHtcLow, 200);
/// <summary>Error code: 2029-0201; Inner value: 0x1921d</summary>
public static Result.Base InvalidChannelStateDisconnected => new Result.Base(ModuleHtcLow, 201);
/// <summary>Error code: 2029-1000; Range: 1000-2999; Inner value: 0x7d01d</summary>
public static Result.Base InternalError { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleHtcLow, 1000, 2999); }
/// <summary>Error code: 2029-1001; Inner value: 0x7d21d</summary>
public static Result.Base Overflow => new Result.Base(ModuleHtcLow, 1001);
/// <summary>Error code: 2029-1002; Inner value: 0x7d41d</summary>
public static Result.Base OutOfMemory => new Result.Base(ModuleHtcLow, 1002);
/// <summary>Error code: 2029-1003; Inner value: 0x7d61d</summary>
public static Result.Base InvalidArgument => new Result.Base(ModuleHtcLow, 1003);
/// <summary>Error code: 2029-1004; Inner value: 0x7d81d</summary>
public static Result.Base ProtocolError => new Result.Base(ModuleHtcLow, 1004);
/// <summary>Error code: 2029-1005; Inner value: 0x7da1d</summary>
public static Result.Base Cancelled => new Result.Base(ModuleHtcLow, 1005);
/// <summary>Error code: 2029-1100; Range: 1100-1199; Inner value: 0x8981d</summary>
public static Result.Base MuxError { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleHtcLow, 1100, 1199); }
/// <summary>Error code: 2029-1101; Inner value: 0x89a1d</summary>
public static Result.Base ChannelBufferOverflow => new Result.Base(ModuleHtcLow, 1101);
/// <summary>Error code: 2029-1102; Inner value: 0x89c1d</summary>
public static Result.Base ChannelBufferHasNotEnoughData => new Result.Base(ModuleHtcLow, 1102);
/// <summary>Error code: 2029-1103; Inner value: 0x89e1d</summary>
public static Result.Base ChannelVersionNotMatched => new Result.Base(ModuleHtcLow, 1103);
/// <summary>Error code: 2029-1104; Inner value: 0x8a01d</summary>
public static Result.Base ChannelStateTransitionError => new Result.Base(ModuleHtcLow, 1104);
/// <summary>Error code: 2029-1106; Inner value: 0x8a41d</summary>
public static Result.Base ChannelReceiveBufferEmpty => new Result.Base(ModuleHtcLow, 1106);
/// <summary>Error code: 2029-1107; Inner value: 0x8a61d</summary>
public static Result.Base ChannelSequenceIdNotMatched => new Result.Base(ModuleHtcLow, 1107);
/// <summary>Error code: 2029-1108; Inner value: 0x8a81d</summary>
public static Result.Base ChannelCannotDiscard => new Result.Base(ModuleHtcLow, 1108);
/// <summary>Error code: 2029-1200; Range: 1200-1999; Inner value: 0x9601d</summary>
public static Result.Base DriverError { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleHtcLow, 1200, 1999); }
/// <summary>Error code: 2029-1201; Inner value: 0x9621d</summary>
public static Result.Base DriverOpened => new Result.Base(ModuleHtcLow, 1201);
/// <summary>Error code: 2029-1300; Range: 1300-1399; Inner value: 0xa281d</summary>
public static Result.Base SocketDriverError { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleHtcLow, 1300, 1399); }
/// <summary>Error code: 2029-1301; Inner value: 0xa2a1d</summary>
public static Result.Base SocketSocketExemptError => new Result.Base(ModuleHtcLow, 1301);
/// <summary>Error code: 2029-1302; Inner value: 0xa2c1d</summary>
public static Result.Base SocketBindError => new Result.Base(ModuleHtcLow, 1302);
/// <summary>Error code: 2029-1304; Inner value: 0xa301d</summary>
public static Result.Base SocketListenError => new Result.Base(ModuleHtcLow, 1304);
/// <summary>Error code: 2029-1305; Inner value: 0xa321d</summary>
public static Result.Base SocketAcceptError => new Result.Base(ModuleHtcLow, 1305);
/// <summary>Error code: 2029-1306; Inner value: 0xa341d</summary>
public static Result.Base SocketReceiveError => new Result.Base(ModuleHtcLow, 1306);
/// <summary>Error code: 2029-1307; Inner value: 0xa361d</summary>
public static Result.Base SocketSendError => new Result.Base(ModuleHtcLow, 1307);
/// <summary>Error code: 2029-1308; Inner value: 0xa381d</summary>
public static Result.Base SocketReceiveFromError => new Result.Base(ModuleHtcLow, 1308);
/// <summary>Error code: 2029-1309; Inner value: 0xa3a1d</summary>
public static Result.Base SocketSendToError => new Result.Base(ModuleHtcLow, 1309);
/// <summary>Error code: 2029-1310; Inner value: 0xa3c1d</summary>
public static Result.Base SocketSetSockOptError => new Result.Base(ModuleHtcLow, 1310);
/// <summary>Error code: 2029-1311; Inner value: 0xa3e1d</summary>
public static Result.Base SocketGetSockNameError => new Result.Base(ModuleHtcLow, 1311);
/// <summary>Error code: 2029-1400; Range: 1400-1499; Inner value: 0xaf01d</summary>
public static Result.Base UsbDriverError { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleHtcLow, 1400, 1499); }
/// <summary>Error code: 2029-1401; Inner value: 0xaf21d</summary>
public static Result.Base UsbDriverUnknownError => new Result.Base(ModuleHtcLow, 1401);
/// <summary>Error code: 2029-1402; Inner value: 0xaf41d</summary>
public static Result.Base UsbDriverBusyError => new Result.Base(ModuleHtcLow, 1402);
/// <summary>Error code: 2029-1403; Inner value: 0xaf61d</summary>
public static Result.Base UsbDriverReceiveError => new Result.Base(ModuleHtcLow, 1403);
/// <summary>Error code: 2029-1404; Inner value: 0xaf81d</summary>
public static Result.Base UsbDriverSendError => new Result.Base(ModuleHtcLow, 1404);
/// <summary>Error code: 2029-2000; Inner value: 0xfa01d</summary>
public static Result.Base HtcctrlError => new Result.Base(ModuleHtcLow, 2000);
/// <summary>Error code: 2029-2001; Inner value: 0xfa21d</summary>
public static Result.Base HtcctrlStateTransitionNotAllowed => new Result.Base(ModuleHtcLow, 2001);
/// <summary>Error code: 2029-2002; Inner value: 0xfa41d</summary>
public static Result.Base HtcctrlReceiveUnexpectedPacket => new Result.Base(ModuleHtcLow, 2002);
}

View file

@ -240,10 +240,17 @@ public class TypeLayoutTests
Assert.Equal(0x08, GetOffset(in s, in s.FatFsError));
Assert.Equal(0x28, GetOffset(in s, in s.RecoveredByInvalidateCacheCount));
Assert.Equal(0x2C, GetOffset(in s, in s.SaveDataIndexCount));
Assert.Equal(0x30, GetOffset(in s, in s.BisSystemFatReportInfo));
Assert.Equal(0x34, GetOffset(in s, in s.BisUserFatReport));
Assert.Equal(0x38, GetOffset(in s, in s.SdCardFatReport));
Assert.Equal(0x3C, GetOffset(in s, in s.Reserved));
Assert.Equal(0x30, GetOffset(in s, in s.BisSystemFatReportInfo1));
Assert.Equal(0x34, GetOffset(in s, in s.BisUserFatReport1));
Assert.Equal(0x38, GetOffset(in s, in s.SdCardFatReport1));
Assert.Equal(0x3C, GetOffset(in s, in s.BisSystemFatReportInfo2));
Assert.Equal(0x40, GetOffset(in s, in s.BisUserFatReport2));
Assert.Equal(0x44, GetOffset(in s, in s.SdCardFatReport2));
Assert.Equal(0x48, GetOffset(in s, in s.DeepRetryStartCount));
Assert.Equal(0x4C, GetOffset(in s, in s.UnrecoverableByGameCardAccessFailedCount));
Assert.Equal(0x50, GetOffset(in s, in s.BisSystemFatSafeInfo));
Assert.Equal(0x5C, GetOffset(in s, in s.BisUserFatSafeInfo));
Assert.Equal(0x68, GetOffset(in s, in s.Reserved));
}
[Fact]

View file

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