Add AccessFailureManagementService

This commit is contained in:
Alex Barney 2021-01-31 01:23:38 -07:00
parent e9f518ddc1
commit e9918fa5aa
9 changed files with 283 additions and 31 deletions

View File

@ -0,0 +1,103 @@
using System.Runtime.CompilerServices;
using LibHac.Fs;
using LibHac.FsSrv.Impl;
using LibHac.FsSrv.Sf;
using LibHac.Sf;
namespace LibHac.FsSrv
{
public readonly struct AccessFailureManagementService
{
private readonly AccessFailureManagementServiceImpl _serviceImpl;
private readonly ulong _processId;
public AccessFailureManagementService(AccessFailureManagementServiceImpl serviceImpl, ulong processId)
{
_serviceImpl = serviceImpl;
_processId = processId;
}
internal Result GetProgramInfo(out ProgramInfo programInfo)
{
return _serviceImpl.GetProgramInfo(out programInfo, _processId);
}
public Result OpenAccessFailureDetectionEventNotifier(out ReferenceCountedDisposable<IEventNotifier> notifier,
ulong processId, bool notifyOnDeepRetry)
{
notifier = default;
Result rc = GetProgramInfo(out ProgramInfo programInfo);
if (rc.IsFailure()) return rc;
if (!programInfo.AccessControl.CanCall(OperationType.OpenAccessFailureDetectionEventNotifier))
return ResultFs.PermissionDenied.Log();
rc = _serviceImpl.CreateNotifier(out IEventNotifier tempNotifier, processId, notifyOnDeepRetry);
if (rc.IsFailure()) return rc;
notifier = new ReferenceCountedDisposable<IEventNotifier>(tempNotifier);
return Result.Success;
}
public Result GetAccessFailureDetectionEvent(out NativeHandle eventHandle)
{
eventHandle = default;
Result rc = GetProgramInfo(out ProgramInfo programInfo);
if (rc.IsFailure()) return rc;
if (!programInfo.AccessControl.CanCall(OperationType.GetAccessFailureDetectionEvent))
return ResultFs.PermissionDenied.Log();
Svc.Handle handle = _serviceImpl.GetEvent();
eventHandle = new NativeHandle(_serviceImpl.HorizonClient.Os, handle, false);
return Result.Success;
}
public Result IsAccessFailureDetected(out bool isDetected, ulong processId)
{
Unsafe.SkipInit(out isDetected);
Result rc = GetProgramInfo(out ProgramInfo programInfo);
if (rc.IsFailure()) return rc;
if (!programInfo.AccessControl.CanCall(OperationType.IsAccessFailureDetected))
return ResultFs.PermissionDenied.Log();
isDetected = _serviceImpl.IsAccessFailureDetectionNotified(processId);
return Result.Success;
}
public Result ResolveAccessFailure(ulong processId)
{
Result rc = GetProgramInfo(out ProgramInfo programInfo);
if (rc.IsFailure()) return rc;
if (!programInfo.AccessControl.CanCall(OperationType.ResolveAccessFailure))
return ResultFs.PermissionDenied.Log();
_serviceImpl.ResetAccessFailureDetection(processId);
// Todo: Modify ServiceContext
return Result.Success;
}
public Result AbandonAccessFailure(ulong processId)
{
Result rc = GetProgramInfo(out ProgramInfo programInfo);
if (rc.IsFailure()) return rc;
if (!programInfo.AccessControl.CanCall(OperationType.AbandonAccessFailure))
return ResultFs.PermissionDenied.Log();
_serviceImpl.DisableAccessFailureDetection(processId);
// Todo: Modify ServiceContext
return Result.Success;
}
}
}

View File

@ -0,0 +1,61 @@
using System;
using LibHac.FsSrv.Impl;
using LibHac.FsSrv.Sf;
using LibHac.Svc;
namespace LibHac.FsSrv
{
public class AccessFailureManagementServiceImpl
{
private ProgramRegistryImpl _programRegistry;
internal HorizonClient HorizonClient { get; }
private AccessFailureDetectionEventManager _eventManager;
public AccessFailureManagementServiceImpl(ProgramRegistryImpl programRegistry, HorizonClient horizonClient)
{
_programRegistry = programRegistry;
HorizonClient = horizonClient;
_eventManager = new AccessFailureDetectionEventManager();
}
internal Result GetProgramInfo(out ProgramInfo programInfo, ulong processId)
{
return _programRegistry.GetProgramInfo(out programInfo, processId);
}
public Result CreateNotifier(out IEventNotifier notifier, ulong processId, bool notifyOnDeepRetry)
{
return _eventManager.CreateNotifier(out notifier, processId, notifyOnDeepRetry);
}
public void ResetAccessFailureDetection(ulong processId)
{
_eventManager.ResetAccessFailureDetection(processId);
}
public void DisableAccessFailureDetection(ulong processId)
{
_eventManager.DisableAccessFailureDetection(processId);
}
public void NotifyAccessFailureDetection(ulong processId)
{
_eventManager.NotifyAccessFailureDetection(processId);
}
public bool IsAccessFailureDetectionNotified(ulong processId)
{
return _eventManager.IsAccessFailureDetectionNotified(processId);
}
public Handle GetEvent()
{
return _eventManager.GetEvent();
}
public Result HandleResolubleAccessFailure(out bool wasDeferred, Result nonDeferredResult, ulong processId)
{
throw new NotImplementedException();
}
}
}

View File

@ -9,6 +9,7 @@ namespace LibHac.FsSrv
public BaseFileSystemServiceImpl BaseFileSystemService { get; set; }
public NcaFileSystemServiceImpl NcaFileSystemService { get; set; }
public SaveDataFileSystemServiceImpl SaveDataFileSystemService { get; set; }
public AccessFailureManagementServiceImpl AccessFailureManagementService { get; set; }
public TimeServiceImpl TimeService { get; set; }
public StatusReportServiceImpl StatusReportService { get; set; }
public ProgramRegistryServiceImpl ProgramRegistryService { get; set; }

View File

@ -1,5 +1,4 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.CompilerServices;
using LibHac.Common;
using LibHac.Fs;
using LibHac.FsSrv.Impl;
@ -67,6 +66,12 @@ namespace LibHac.FsSrv
return new BaseFileSystemService(FsProxyCore.Config.BaseFileSystemService, CurrentProcess);
}
private AccessFailureManagementService GetAccessFailureManagementService()
{
return new AccessFailureManagementService(FsProxyCore.Config.AccessFailureManagementService,
CurrentProcess);
}
private TimeService GetTimeService()
{
return new TimeService(FsProxyCore.Config.TimeService, CurrentProcess);
@ -128,16 +133,6 @@ namespace LibHac.FsSrv
return ncaFsService.OpenCodeFileSystem(out fileSystem, out verificationData, in path, programId);
}
public Result IsArchivedProgram(out bool isArchived, ulong processId)
{
Unsafe.SkipInit(out isArchived);
Result rc = GetNcaFileSystemService(out NcaFileSystemService ncaFsService);
if (rc.IsFailure()) return rc;
return ncaFsService.IsArchivedProgram(out isArchived, processId);
}
public Result SetCurrentProcess(ulong processId)
{
CurrentProcess = processId;
@ -145,7 +140,8 @@ namespace LibHac.FsSrv
// Initialize the NCA file system service
NcaFsService = NcaFileSystemService.CreateShared(FsProxyCore.Config.NcaFileSystemService, processId);
SaveFsService = SaveDataFileSystemService.CreateShared(FsProxyCore.Config.SaveDataFileSystemService, processId);
SaveFsService =
SaveDataFileSystemService.CreateShared(FsProxyCore.Config.SaveDataFileSystemService, processId);
return Result.Success;
}
@ -197,7 +193,8 @@ namespace LibHac.FsSrv
return ncaFsService.OpenDataStorageByCurrentProcess(out storage);
}
public Result OpenDataStorageByProgramId(out ReferenceCountedDisposable<IStorageSf> storage, ProgramId programId)
public Result OpenDataStorageByProgramId(out ReferenceCountedDisposable<IStorageSf> storage,
ProgramId programId)
{
Result rc = GetNcaFileSystemService(out NcaFileSystemService ncaFsService);
if (rc.IsFailure())
@ -209,7 +206,8 @@ namespace LibHac.FsSrv
return ncaFsService.OpenDataStorageByProgramId(out storage, programId);
}
public Result OpenDataStorageByDataId(out ReferenceCountedDisposable<IStorageSf> storage, DataId dataId, StorageId storageId)
public Result OpenDataStorageByDataId(out ReferenceCountedDisposable<IStorageSf> storage, DataId dataId,
StorageId storageId)
{
Result rc = GetNcaFileSystemService(out NcaFileSystemService ncaFsService);
if (rc.IsFailure())
@ -240,7 +238,8 @@ namespace LibHac.FsSrv
return ncaFsService.OpenDataFileSystemWithProgramIndex(out fileSystem, programIndex);
}
public Result OpenDataStorageWithProgramIndex(out ReferenceCountedDisposable<IStorageSf> storage, byte programIndex)
public Result OpenDataStorageWithProgramIndex(out ReferenceCountedDisposable<IStorageSf> storage,
byte programIndex)
{
Result rc = GetNcaFileSystemService(out NcaFileSystemService ncaFsService);
if (rc.IsFailure())
@ -276,7 +275,8 @@ namespace LibHac.FsSrv
return saveFsService.DeleteSaveDataFileSystemBySaveDataSpaceId(spaceId, saveDataId);
}
public Result DeleteSaveDataFileSystemBySaveDataAttribute(SaveDataSpaceId spaceId, in SaveDataAttribute attribute)
public Result DeleteSaveDataFileSystemBySaveDataAttribute(SaveDataSpaceId spaceId,
in SaveDataAttribute attribute)
{
Result rc = GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService);
if (rc.IsFailure()) return rc;
@ -797,7 +797,8 @@ namespace LibHac.FsSrv
return saveFsService.UnsetSaveDataRootPath();
}
public Result OpenContentStorageFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, ContentStorageId storageId)
public Result OpenContentStorageFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem,
ContentStorageId storageId)
{
Result rc = GetNcaFileSystemService(out NcaFileSystemService ncaFsService);
if (rc.IsFailure())
@ -843,7 +844,8 @@ namespace LibHac.FsSrv
}
}
public Result OpenCustomStorageFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, CustomStorageId storageId)
public Result OpenCustomStorageFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem,
CustomStorageId storageId)
{
fileSystem = default;
var storageFlag = StorageType.NonGameCard;
@ -885,6 +887,16 @@ namespace LibHac.FsSrv
return GetBaseFileSystemService().OpenGameCardFileSystem(out fileSystem, handle, partitionId);
}
public Result IsArchivedProgram(out bool isArchived, ulong processId)
{
Unsafe.SkipInit(out isArchived);
Result rc = GetNcaFileSystemService(out NcaFileSystemService ncaFsService);
if (rc.IsFailure()) return rc;
return ncaFsService.IsArchivedProgram(out isArchived, processId);
}
public Result QuerySaveDataTotalSize(out long totalSize, long dataSize, long journalSize)
{
Unsafe.SkipInit(out totalSize);
@ -1135,27 +1147,28 @@ namespace LibHac.FsSrv
public Result OpenAccessFailureDetectionEventNotifier(out ReferenceCountedDisposable<IEventNotifier> notifier,
ulong processId, bool notifyOnDeepRetry)
{
throw new NotImplementedException();
return GetAccessFailureManagementService()
.OpenAccessFailureDetectionEventNotifier(out notifier, processId, notifyOnDeepRetry);
}
public Result GetAccessFailureDetectionEvent(out NativeHandle eventHandle)
{
throw new NotImplementedException();
return GetAccessFailureManagementService().GetAccessFailureDetectionEvent(out eventHandle);
}
public Result IsAccessFailureDetected(out bool isDetected, ulong processId)
{
throw new NotImplementedException();
return GetAccessFailureManagementService().IsAccessFailureDetected(out isDetected, processId);
}
public Result ResolveAccessFailure(ulong processId)
{
throw new NotImplementedException();
return GetAccessFailureManagementService().ResolveAccessFailure(processId);
}
public Result AbandonAccessFailure(ulong processId)
{
throw new NotImplementedException();
return GetAccessFailureManagementService().AbandonAccessFailure(processId);
}
public Result OpenMultiCommitManager(out ReferenceCountedDisposable<IMultiCommitManager> commitManager)

View File

@ -128,6 +128,8 @@ namespace LibHac.FsSrv
baseFsServiceConfig.ProgramRegistry = programRegistry;
var baseFsService = new BaseFileSystemServiceImpl(in baseFsServiceConfig);
var accessFailureManagementService = new AccessFailureManagementServiceImpl(programRegistry, Hos);
var ncaFsServiceConfig = new NcaFileSystemServiceImpl.Configuration();
ncaFsServiceConfig.BaseFsService = baseFsService;
ncaFsServiceConfig.HostFsCreator = config.FsCreators.HostFileSystemCreator;
@ -186,6 +188,7 @@ namespace LibHac.FsSrv
BaseFileSystemService = baseFsService,
NcaFileSystemService = ncaFsService,
SaveDataFileSystemService = saveFsService,
AccessFailureManagementService = accessFailureManagementService,
TimeService = timeService,
StatusReportService = statusReportService,
ProgramRegistryService = programRegistryService,

View File

@ -0,0 +1,39 @@
using System;
using LibHac.FsSrv.Sf;
using LibHac.Svc;
namespace LibHac.FsSrv.Impl
{
public class AccessFailureDetectionEventManager
{
public Result CreateNotifier(out IEventNotifier notifier, ulong processId, bool notifyOnDeepRetry)
{
throw new NotImplementedException();
}
public void NotifyAccessFailureDetection(ulong processId)
{
throw new NotImplementedException();
}
public void ResetAccessFailureDetection(ulong processId)
{
throw new NotImplementedException();
}
public void DisableAccessFailureDetection(ulong processId)
{
throw new NotImplementedException();
}
public bool IsAccessFailureDetectionNotified(ulong processId)
{
throw new NotImplementedException();
}
public Handle GetEvent()
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,10 @@
namespace LibHac.Os
{
public static class NativeHandleApi
{
public static void CloseNativeHandle(this OsState os, object handle)
{
}
}
}

View File

@ -1,21 +1,31 @@
namespace LibHac.Sf
using System;
using LibHac.Os;
using LibHac.Svc;
namespace LibHac.Sf
{
// How should this be handled? Using a C# struct would be more accurate, but C#
// doesn't have copy constructors or any way to prevent a struct from being copied.
public class NativeHandle
public class NativeHandle : IDisposable
{
public uint Handle { get; private set; }
private OsState Os { get; }
public Handle Handle { get; private set; }
public bool IsManaged { get; private set; }
public NativeHandle(uint handle)
public NativeHandle(OsState os, Handle handle)
{
Os = os;
Handle = handle;
}
public NativeHandle(uint handle, bool isManaged)
public NativeHandle(OsState os, Handle handle, bool isManaged)
{
Handle = handle;
IsManaged = isManaged;
}
public void Dispose()
{
if (IsManaged)
Os.CloseNativeHandle(Handle.Object);
}
}
}

12
src/LibHac/Svc/Handle.cs Normal file
View File

@ -0,0 +1,12 @@
namespace LibHac.Svc
{
public readonly struct Handle
{
public readonly object Object;
public Handle(object obj)
{
Object = obj;
}
}
}