Use globals in more places

Adds globals for FileSystemProxyImpl, ProgramRegistryImpl, AccessControl and StorageDeviceManagerFactory
This commit is contained in:
Alex Barney 2021-02-02 21:11:51 -07:00
parent e9918fa5aa
commit dadc019439
14 changed files with 243 additions and 173 deletions

View file

@ -1,5 +1,6 @@
using System;
using LibHac.Common;
using LibHac.Diag;
using LibHac.Fs.Impl;
using LibHac.FsSrv.Sf;
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
@ -31,16 +32,24 @@ namespace LibHac.Fs.Shim
}
}
public static string GetCustomStorageDirectoryName(CustomStorageId storageId)
public static U8Span GetCustomStorageDirectoryName(CustomStorageId storageId)
{
switch (storageId)
{
case CustomStorageId.System:
case CustomStorageId.SdCard:
return "CustomStorage0";
return new U8Span(CustomStorageDirectoryName);
default:
throw new ArgumentOutOfRangeException(nameof(storageId), storageId, null);
Abort.UnexpectedDefault();
return default;
}
}
private static ReadOnlySpan<byte> CustomStorageDirectoryName => // CustomStorage0
new[]
{
(byte) 'C', (byte) 'u', (byte) 's', (byte) 't', (byte) 'o', (byte) 'm', (byte) 'S', (byte) 't',
(byte) 'o', (byte) 'r', (byte) 'a', (byte) 'g', (byte) 'e', (byte) '0'
};
}
}

View file

@ -1,5 +1,4 @@
using System;
using LibHac.Common.Keys;
using LibHac.Common.Keys;
using LibHac.Fs;
using LibHac.Fs.Fsa;
using LibHac.FsSystem;
@ -15,25 +14,6 @@ namespace LibHac.FsSrv.Creators
KeySet = keySet;
}
public Result Create(out IFileSystem encryptedFileSystem, IFileSystem baseFileSystem, EncryptedFsKeyId keyId,
ReadOnlySpan<byte> encryptionSeed)
{
encryptedFileSystem = default;
if (keyId < EncryptedFsKeyId.Save || keyId > EncryptedFsKeyId.CustomStorage)
{
return ResultFs.InvalidArgument.Log();
}
// todo: "proper" key generation instead of a lazy hack
KeySet.SetSdSeed(encryptionSeed.ToArray());
encryptedFileSystem = new AesXtsFileSystem(baseFileSystem,
KeySet.SdCardEncryptionKeys[(int)keyId].DataRo.ToArray(), 0x4000);
return Result.Success;
}
public Result Create(out ReferenceCountedDisposable<IFileSystem> encryptedFileSystem, ReferenceCountedDisposable<IFileSystem> baseFileSystem,
EncryptedFsKeyId keyId, in EncryptionSeed encryptionSeed)
{

View file

@ -1,6 +1,6 @@
namespace LibHac.FsSrv.Creators
{
public class FileSystemCreators
public class FileSystemCreatorInterfaces
{
public IRomFileSystemCreator RomFileSystemCreator { get; set; }
public IPartitionFileSystemCreator PartitionFileSystemCreator { get; set; }

View file

@ -1,15 +1,10 @@
using System;
using LibHac.Fs;
using LibHac.Fs;
using LibHac.Fs.Fsa;
namespace LibHac.FsSrv.Creators
{
public interface IEncryptedFileSystemCreator
{
// Todo: remove the function using raw IFileSystems
Result Create(out IFileSystem encryptedFileSystem, IFileSystem baseFileSystem, EncryptedFsKeyId keyId,
ReadOnlySpan<byte> encryptionSeed);
Result Create(out ReferenceCountedDisposable<IFileSystem> encryptedFileSystem,
ReferenceCountedDisposable<IFileSystem> baseFileSystem, EncryptedFsKeyId keyId,
in EncryptionSeed encryptionSeed);

View file

@ -7,14 +7,14 @@ namespace LibHac.FsSrv
{
public class DefaultFsServerObjects
{
public FileSystemCreators FsCreators { get; set; }
public FileSystemCreatorInterfaces FsCreators { get; set; }
public IDeviceOperator DeviceOperator { get; set; }
public EmulatedGameCard GameCard { get; set; }
public EmulatedSdCard SdCard { get; set; }
public static DefaultFsServerObjects GetDefaultEmulatedCreators(IFileSystem rootFileSystem, KeySet keySet)
{
var creators = new FileSystemCreators();
var creators = new FileSystemCreatorInterfaces();
var gameCard = new EmulatedGameCard(keySet);
var sdCard = new EmulatedSdCard();

View file

@ -4,7 +4,7 @@ namespace LibHac.FsSrv
{
public class FileSystemProxyConfiguration
{
public FileSystemCreators FsCreatorInterfaces { get; set; }
public FileSystemCreatorInterfaces FsCreatorInterfaces { get; set; }
public BaseStorageServiceImpl BaseStorageService { get; set; }
public BaseFileSystemServiceImpl BaseFileSystemService { get; set; }
public NcaFileSystemServiceImpl NcaFileSystemService { get; set; }

View file

@ -4,23 +4,20 @@ using LibHac.Fs;
using LibHac.Fs.Fsa;
using LibHac.Fs.Shim;
using LibHac.FsSrv.Creators;
using LibHac.FsSrv.Impl;
namespace LibHac.FsSrv
{
public class FileSystemProxyCoreImpl
{
internal FileSystemProxyConfiguration Config { get; }
private FileSystemCreators FsCreators => Config.FsCreatorInterfaces;
internal ProgramRegistryImpl ProgramRegistry { get; }
private FileSystemCreatorInterfaces FsCreators { get; }
private BaseFileSystemServiceImpl BaseFileSystemService { get; }
private EncryptionSeed SdEncryptionSeed { get; set; }
private byte[] SdEncryptionSeed { get; } = new byte[0x10];
private const string NintendoDirectoryName = "Nintendo";
public FileSystemProxyCoreImpl(FileSystemProxyConfiguration config)
public FileSystemProxyCoreImpl(FileSystemCreatorInterfaces fsCreators, BaseFileSystemServiceImpl baseFsService)
{
Config = config;
ProgramRegistry = new ProgramRegistryImpl(Config.ProgramRegistryService);
FsCreators = fsCreators;
BaseFileSystemService = baseFsService;
}
public Result OpenCloudBackupWorkStorageFileSystem(out ReferenceCountedDisposable<IFileSystem> fileSystem,
@ -34,44 +31,60 @@ namespace LibHac.FsSrv
{
fileSystem = default;
switch (storageId)
ReferenceCountedDisposable<IFileSystem> tempFs = null;
ReferenceCountedDisposable<IFileSystem> encryptedFs = null;
try
{
case CustomStorageId.SdCard:
Span<byte> path = stackalloc byte[0x40];
switch (storageId)
{
Result rc = FsCreators.SdCardFileSystemCreator.Create(out IFileSystem sdFs, false);
if (rc.IsFailure()) return rc;
case CustomStorageId.SdCard:
{
Result rc = BaseFileSystemService.OpenSdCardProxyFileSystem(out tempFs);
if (rc.IsFailure()) return rc;
string customStorageDir = CustomStorage.GetCustomStorageDirectoryName(CustomStorageId.SdCard);
string subDirName = $"/{NintendoDirectoryName}/{customStorageDir}";
U8Span customStorageDir = CustomStorage.GetCustomStorageDirectoryName(CustomStorageId.SdCard);
var sb = new U8StringBuilder(path);
sb.Append((byte)'/')
.Append(CommonPaths.SdCardNintendoRootDirectoryName)
.Append((byte)'/')
.Append(customStorageDir);
rc = Util.CreateSubFileSystem(out IFileSystem subFs, sdFs, subDirName, true);
if (rc.IsFailure()) return rc;
rc = Utility.WrapSubDirectory(out tempFs, ref tempFs, new U8Span(path), true);
if (rc.IsFailure()) return rc;
rc = FsCreators.EncryptedFileSystemCreator.Create(out IFileSystem encryptedFs, subFs,
EncryptedFsKeyId.CustomStorage, SdEncryptionSeed);
if (rc.IsFailure()) return rc;
rc = FsCreators.EncryptedFileSystemCreator.Create(out encryptedFs, tempFs,
EncryptedFsKeyId.CustomStorage, SdEncryptionSeed);
if (rc.IsFailure()) return rc;
fileSystem = new ReferenceCountedDisposable<IFileSystem>(encryptedFs);
return Result.Success;
return Result.Success;
}
case CustomStorageId.System:
{
Result rc = BaseFileSystemService.OpenBisFileSystem(out tempFs, U8Span.Empty,
BisPartitionId.User);
if (rc.IsFailure()) return rc;
U8Span customStorageDir = CustomStorage.GetCustomStorageDirectoryName(CustomStorageId.System);
var sb = new U8StringBuilder(path);
sb.Append((byte)'/')
.Append(customStorageDir);
rc = Utility.WrapSubDirectory(out tempFs, ref tempFs, new U8Span(path), true);
if (rc.IsFailure()) return rc;
fileSystem = Shared.Move(ref tempFs);
return Result.Success;
}
default:
return ResultFs.InvalidArgument.Log();
}
case CustomStorageId.System:
{
Result rc = FsCreators.BuiltInStorageFileSystemCreator.Create(out IFileSystem userFs, string.Empty,
BisPartitionId.User);
if (rc.IsFailure()) return rc;
string customStorageDir = CustomStorage.GetCustomStorageDirectoryName(CustomStorageId.System);
string subDirName = $"/{customStorageDir}";
rc = Util.CreateSubFileSystem(out IFileSystem subFs, userFs, subDirName, true);
if (rc.IsFailure()) return rc;
// Todo: Get shared object from earlier functions
fileSystem = new ReferenceCountedDisposable<IFileSystem>(subFs);
return Result.Success;
}
default:
return ResultFs.InvalidArgument.Log();
}
finally
{
tempFs?.Dispose();
encryptedFs?.Dispose();
}
}
@ -127,7 +140,7 @@ namespace LibHac.FsSrv
public Result SetSdCardEncryptionSeed(in EncryptionSeed seed)
{
seed.Value.CopyTo(SdEncryptionSeed);
SdEncryptionSeed = seed;
return Result.Success;
}
}

View file

@ -7,6 +7,7 @@ using LibHac.FsSystem;
using LibHac.Ncm;
using LibHac.Sf;
using LibHac.Spl;
using LibHac.Util;
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
using IFileSf = LibHac.FsSrv.Sf.IFile;
@ -14,22 +15,64 @@ using IStorageSf = LibHac.FsSrv.Sf.IStorage;
namespace LibHac.FsSrv
{
public static class FileSystemProxyImplGlobalMethods
{
public static void InitializeFileSystemProxy(this FileSystemServer fsSrv,
FileSystemProxyConfiguration configuration)
{
ref FileSystemProxyImplGlobals g = ref fsSrv.Globals.FileSystemProxyImpl;
g.FileSystemProxyCoreImpl.Set(new FileSystemProxyCoreImpl(configuration.FsCreatorInterfaces,
configuration.BaseFileSystemService));
g.BaseStorageServiceImpl = configuration.BaseStorageService;
g.BaseFileSystemServiceImpl = configuration.BaseFileSystemService;
g.NcaFileSystemServiceImpl = configuration.NcaFileSystemService;
g.SaveDataFileSystemServiceImpl = configuration.SaveDataFileSystemService;
g.AccessFailureManagementServiceImpl = configuration.AccessFailureManagementService;
g.TimeServiceImpl = configuration.TimeService;
g.StatusReportServiceImpl = configuration.StatusReportService;
g.ProgramRegistryServiceImpl = configuration.ProgramRegistryService;
g.AccessLogServiceImpl = configuration.AccessLogService;
}
}
internal struct FileSystemProxyImplGlobals
{
public NcaFileSystemServiceImpl NcaFileSystemServiceImpl;
public SaveDataFileSystemServiceImpl SaveDataFileSystemServiceImpl;
public BaseStorageServiceImpl BaseStorageServiceImpl;
public BaseFileSystemServiceImpl BaseFileSystemServiceImpl;
public AccessFailureManagementServiceImpl AccessFailureManagementServiceImpl;
public TimeServiceImpl TimeServiceImpl;
public StatusReportServiceImpl StatusReportServiceImpl;
public ProgramRegistryServiceImpl ProgramRegistryServiceImpl;
public AccessLogServiceImpl AccessLogServiceImpl;
public Optional<FileSystemProxyCoreImpl> FileSystemProxyCoreImpl;
}
public class FileSystemProxyImpl : IFileSystemProxy, IFileSystemProxyForLoader
{
private FileSystemServer FsServer { get; }
private ref FileSystemProxyImplGlobals Globals => ref FsServer.Globals.FileSystemProxyImpl;
private FileSystemProxyCoreImpl FsProxyCore { get; }
private ReferenceCountedDisposable<NcaFileSystemService> NcaFsService { get; set; }
private ReferenceCountedDisposable<SaveDataFileSystemService> SaveFsService { get; set; }
private ulong CurrentProcess { get; set; }
internal FileSystemProxyImpl(FileSystemProxyCoreImpl fsProxyCore)
internal FileSystemProxyImpl(FileSystemServer server)
{
FsProxyCore = fsProxyCore;
FsServer = server;
FsProxyCore = Globals.FileSystemProxyCoreImpl.Value;
CurrentProcess = ulong.MaxValue;
}
private Result GetProgramInfo(out ProgramInfo programInfo)
{
return FsProxyCore.ProgramRegistry.GetProgramInfo(out programInfo, CurrentProcess);
var registry = new ProgramRegistryImpl(FsServer);
return registry.GetProgramInfo(out programInfo, CurrentProcess);
}
private Result GetNcaFileSystemService(out NcaFileSystemService ncaFsService)
@ -58,38 +101,37 @@ namespace LibHac.FsSrv
private BaseStorageService GetBaseStorageService()
{
return new BaseStorageService(FsProxyCore.Config.BaseStorageService, CurrentProcess);
return new BaseStorageService(Globals.BaseStorageServiceImpl, CurrentProcess);
}
private BaseFileSystemService GetBaseFileSystemService()
{
return new BaseFileSystemService(FsProxyCore.Config.BaseFileSystemService, CurrentProcess);
return new BaseFileSystemService(Globals.BaseFileSystemServiceImpl, CurrentProcess);
}
private AccessFailureManagementService GetAccessFailureManagementService()
{
return new AccessFailureManagementService(FsProxyCore.Config.AccessFailureManagementService,
CurrentProcess);
return new AccessFailureManagementService(Globals.AccessFailureManagementServiceImpl, CurrentProcess);
}
private TimeService GetTimeService()
{
return new TimeService(FsProxyCore.Config.TimeService, CurrentProcess);
return new TimeService(Globals.TimeServiceImpl, CurrentProcess);
}
private StatusReportService GetStatusReportService()
{
return new StatusReportService(FsProxyCore.Config.StatusReportService);
return new StatusReportService(Globals.StatusReportServiceImpl);
}
private ProgramIndexRegistryService GetProgramIndexRegistryService()
{
return new ProgramIndexRegistryService(FsProxyCore.Config.ProgramRegistryService, CurrentProcess);
return new ProgramIndexRegistryService(Globals.ProgramRegistryServiceImpl, CurrentProcess);
}
private AccessLogService GetAccessLogService()
{
return new AccessLogService(FsProxyCore.Config.AccessLogService, CurrentProcess);
return new AccessLogService(Globals.AccessLogServiceImpl, CurrentProcess);
}
public Result OpenFileSystemWithId(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, in FspPath path,
@ -138,10 +180,8 @@ namespace LibHac.FsSrv
CurrentProcess = processId;
// Initialize the NCA file system service
NcaFsService = NcaFileSystemService.CreateShared(FsProxyCore.Config.NcaFileSystemService, processId);
SaveFsService =
SaveDataFileSystemService.CreateShared(FsProxyCore.Config.SaveDataFileSystemService, processId);
NcaFsService = NcaFileSystemService.CreateShared(Globals.NcaFileSystemServiceImpl, processId);
SaveFsService = SaveDataFileSystemService.CreateShared(Globals.SaveDataFileSystemServiceImpl, processId);
return Result.Success;
}
@ -1055,7 +1095,6 @@ namespace LibHac.FsSrv
public Result SetGlobalAccessLogMode(GlobalAccessLogMode mode)
{
return GetAccessLogService().SetAccessLogMode(mode);
}
public Result GetGlobalAccessLogMode(out GlobalAccessLogMode mode)

View file

@ -1,5 +1,4 @@
using System;
using LibHac.Diag;
using LibHac.Fs;
using LibHac.Fs.Impl;
using LibHac.Fs.Shim;
@ -18,19 +17,15 @@ namespace LibHac.FsSrv
private const ulong SpeedEmulationProgramIdMinimum = 0x100000000000000;
private const ulong SpeedEmulationProgramIdMaximum = 0x100000000001FFF;
private FileSystemProxyCoreImpl FsProxyCore { get; }
public StorageService Storage { get; }
internal FileSystemServerImpl Impl => new FileSystemServerImpl(this);
public StorageService Storage => new StorageService(this);
/// <summary>The client instance to be used for internal operations like save indexer access.</summary>
public HorizonClient Hos { get; }
public HorizonClient Hos => Globals.Hos;
public bool IsDebugMode { get; }
private ITimeSpanGenerator Timer { get; }
// Functions in the nn::fssrv::detail namespace use this field.
// Possibly move this to the main class if the separation doesn't seem necessary.
internal FileSystemServerImpl Impl;
internal ref FileSystemServerGlobals Globals => ref Impl.Globals;
internal FileSystemServerGlobals Globals;
/// <summary>
/// Creates a new <see cref="FileSystemServer"/> and registers its services using the provided HOS client.
@ -45,21 +40,13 @@ namespace LibHac.FsSrv
if (config.DeviceOperator == null)
throw new ArgumentException("DeviceOperator must not be null");
Impl = new FileSystemServerImpl();
Impl.Globals.Hos = horizonClient;
Impl.Globals.InitMutex = new object();
Hos = horizonClient;
Storage = new StorageService(this);
IsDebugMode = false;
Globals.Hos = horizonClient;
Globals.InitMutex = new object();
Timer = config.TimeSpanGenerator ?? new StopWatchTimeSpanGenerator();
FileSystemProxyConfiguration fspConfig = InitializeFileSystemProxyConfiguration(config);
FsProxyCore = new FileSystemProxyCoreImpl(fspConfig);
this.InitializeFileSystemProxy(fspConfig);
FileSystemProxyImpl fsProxy = GetFileSystemProxyServiceObject();
ulong processId = Hos.Os.GetCurrentProcessId().Value;
@ -106,7 +93,9 @@ namespace LibHac.FsSrv
new ArrayPoolMemoryResource(), new SdHandleManager(), false);
var programRegistryService = new ProgramRegistryServiceImpl(this);
var programRegistry = new ProgramRegistryImpl(programRegistryService);
var programRegistry = new ProgramRegistryImpl(this);
this.InitializeProgramRegistryImpl(programRegistryService);
var baseStorageConfig = new BaseStorageServiceImpl.Configuration();
baseStorageConfig.BisStorageCreator = config.FsCreators.BuiltInStorageCreator;
@ -200,17 +189,17 @@ namespace LibHac.FsSrv
private FileSystemProxyImpl GetFileSystemProxyServiceObject()
{
return new FileSystemProxyImpl(FsProxyCore);
return new FileSystemProxyImpl(this);
}
private FileSystemProxyImpl GetFileSystemProxyForLoaderServiceObject()
{
return new FileSystemProxyImpl(FsProxyCore);
return new FileSystemProxyImpl(this);
}
private ProgramRegistryImpl GetProgramRegistryServiceObject()
{
return new ProgramRegistryImpl(FsProxyCore.Config.ProgramRegistryService);
return new ProgramRegistryImpl(this);
}
private class FileSystemProxyService : IServiceObject
@ -273,9 +262,9 @@ namespace LibHac.FsSrv
public class FileSystemServerConfig
{
/// <summary>
/// The <see cref="FileSystemCreators"/> used for creating filesystems.
/// The <see cref="FileSystemCreatorInterfaces"/> used for creating filesystems.
/// </summary>
public FileSystemCreators FsCreators { get; set; }
public FileSystemCreatorInterfaces FsCreators { get; set; }
/// <summary>
/// An <see cref="IDeviceOperator"/> for managing the gamecard and SD card.
@ -295,42 +284,30 @@ namespace LibHac.FsSrv
public ITimeSpanGenerator TimeSpanGenerator { get; set; }
}
public class StorageService
public readonly struct StorageService
{
internal FileSystemServer Fs;
private IStorageDeviceManagerFactory _factory;
internal readonly FileSystemServer FsSrv;
internal StorageService(FileSystemServer parentServer)
{
Fs = parentServer;
}
public void SetStorageDeviceManagerFactory(IStorageDeviceManagerFactory factory)
{
Assert.NotNull(factory);
Assert.Null(_factory);
_factory = factory;
}
public IStorageDeviceManagerFactory GetStorageDeviceManagerFactory()
{
Assert.NotNull(_factory);
return _factory;
}
internal StorageService(FileSystemServer parentServer) => FsSrv = parentServer;
}
// Functions in the nn::fssrv::detail namespace use this struct.
// Possibly move this to the main class if the separation doesn't seem necessary.
internal struct FileSystemServerImpl
public readonly struct FileSystemServerImpl
{
public FileSystemServerGlobals Globals;
internal readonly FileSystemServer FsSrv;
public FileSystemServerImpl(FileSystemServer parentServer) => FsSrv = parentServer;
}
internal struct FileSystemServerGlobals
{
public HorizonClient Hos;
public object InitMutex;
public FileSystemProxyImplGlobals FileSystemProxyImpl;
public ProgramRegistryImplGlobals ProgramRegistryImpl;
public DeviceEventSimulatorGlobals DeviceEventSimulator;
public AccessControlGlobals AccessControl;
public StorageDeviceManagerFactoryGlobals StorageDeviceManagerFactory;
}
}

View file

@ -9,6 +9,19 @@ using LibHac.Util;
namespace LibHac.FsSrv.Impl
{
public static class AccessControlGlobalMethods
{
public static void SetDebugFlagEnabled(this FileSystemServerImpl fsSrv, bool isEnabled)
{
fsSrv.FsSrv.Globals.AccessControl.DebugFlag = isEnabled;
}
}
internal struct AccessControlGlobals
{
public bool DebugFlag;
}
/// <summary>
/// Controls access to FS resources for a single process.
/// </summary>
@ -17,15 +30,16 @@ namespace LibHac.FsSrv.Impl
/// <br/>Based on FS 10.0.0 (nnSdk 10.4.0)</remarks>
public class AccessControl
{
private AccessControlBits? AccessBits { get; }
private FileSystemServer FsServer { get; }
private ref AccessControlGlobals Globals => ref FsServer.Globals.AccessControl;
private Optional<AccessControlBits> AccessBits { get; }
private LinkedList<ContentOwnerInfo> ContentOwners { get; } = new LinkedList<ContentOwnerInfo>();
private LinkedList<SaveDataOwnerInfo> SaveDataOwners { get; } = new LinkedList<SaveDataOwnerInfo>();
private FileSystemServer FsServer { get; }
public AccessControl(FileSystemServer fsServer, ReadOnlySpan<byte> accessControlData,
ReadOnlySpan<byte> accessControlDescriptor) :
this(fsServer, accessControlData, accessControlDescriptor, GetAccessBitsMask(fsServer.IsDebugMode))
ReadOnlySpan<byte> accessControlDescriptor) : this(fsServer, accessControlData, accessControlDescriptor,
GetAccessBitsMask(fsServer.Globals.AccessControl.DebugFlag))
{ }
public AccessControl(FileSystemServer fsServer, ReadOnlySpan<byte> accessControlData,
@ -302,7 +316,7 @@ namespace LibHac.FsSrv.Impl
case OperationType.ExtendOthersSystemSaveData:
return accessBits.CanExtendOthersSystemSaveData();
case OperationType.RegisterUpdatePartition:
return accessBits.CanRegisterUpdatePartition() && FsServer.IsDebugMode;
return accessBits.CanRegisterUpdatePartition() && Globals.DebugFlag;
case OperationType.OpenSaveDataTransferManager:
return accessBits.CanOpenSaveDataTransferManager();
case OperationType.OpenSaveDataTransferManagerVersion2:
@ -465,7 +479,7 @@ namespace LibHac.FsSrv.Impl
case AccessibilityType.MountHost:
return new Accessibility(accessBits.CanMountHostRead(), accessBits.CanMountHostWrite());
case AccessibilityType.MountRegisteredUpdatePartition:
return new Accessibility(accessBits.CanMountRegisteredUpdatePartitionRead() && FsServer.IsDebugMode, false);
return new Accessibility(accessBits.CanMountRegisteredUpdatePartitionRead() && Globals.DebugFlag, false);
case AccessibilityType.MountSaveDataInternalStorage:
return new Accessibility(accessBits.CanOpenSaveDataInternalStorageRead(), accessBits.CanOpenSaveDataInternalStorageWrite());
case AccessibilityType.MountTemporaryDirectory:

View file

@ -14,27 +14,27 @@ namespace LibHac.FsSrv.Impl
internal static class DeviceEventSimulatorGlobalMethods
{
public static SdCardEventSimulator GetSdCardEventSimulator(this ref FileSystemServerImpl fs)
public static SdCardEventSimulator GetSdCardEventSimulator(this FileSystemServerImpl fs)
{
ref DeviceEventSimulatorGlobals g = ref fs.Globals.DeviceEventSimulator;
using var guard = new InitializationGuard(ref g.SdCardEventSimulatorInit, fs.Globals.InitMutex);
ref DeviceEventSimulatorGlobals g = ref fs.FsSrv.Globals.DeviceEventSimulator;
using var guard = new InitializationGuard(ref g.SdCardEventSimulatorInit, fs.FsSrv.Globals.InitMutex);
if (guard.IsInitialized)
return g.SdCardEventSimulator;
g.SdCardEventSimulator = new SdCardEventSimulator(fs.Globals.Hos.Os);
g.SdCardEventSimulator = new SdCardEventSimulator(fs.FsSrv.Globals.Hos.Os);
return g.SdCardEventSimulator;
}
public static GameCardEventSimulator GetGameCardEventSimulator(this ref FileSystemServerImpl fs)
public static GameCardEventSimulator GetGameCardEventSimulator(this FileSystemServerImpl fs)
{
ref DeviceEventSimulatorGlobals g = ref fs.Globals.DeviceEventSimulator;
using var guard = new InitializationGuard(ref g.GameCardEventSimulatorInit, fs.Globals.InitMutex);
ref DeviceEventSimulatorGlobals g = ref fs.FsSrv.Globals.DeviceEventSimulator;
using var guard = new InitializationGuard(ref g.GameCardEventSimulatorInit, fs.FsSrv.Globals.InitMutex);
if (guard.IsInitialized)
return g.GameCardEventSimulator;
g.GameCardEventSimulator = new GameCardEventSimulator(fs.Globals.Hos.Os);
g.GameCardEventSimulator = new GameCardEventSimulator(fs.FsSrv.Globals.Hos.Os);
return g.GameCardEventSimulator;
}
}

View file

@ -6,6 +6,20 @@ using LibHac.Sf;
namespace LibHac.FsSrv
{
public static class ProgramRegistryImplGlobalMethods
{
public static void InitializeProgramRegistryImpl(this FileSystemServer fsSrv,
ProgramRegistryServiceImpl serviceImpl)
{
fsSrv.Globals.ProgramRegistryImpl.ServiceImpl = serviceImpl;
}
}
internal struct ProgramRegistryImplGlobals
{
public ProgramRegistryServiceImpl ServiceImpl;
}
/// <summary>
/// Used to add, remove or access the Program Registry.
/// </summary>
@ -16,21 +30,15 @@ namespace LibHac.FsSrv
/// <br/>Based on FS 10.0.0 (nnSdk 10.4.0)</remarks>
public class ProgramRegistryImpl : IProgramRegistry
{
private FileSystemServer _fsServer;
private ulong _processId;
// Note: FS keeps this object as a global variable
private readonly ProgramRegistryServiceImpl _registryService;
private ref ProgramRegistryImplGlobals Globals => ref _fsServer.Globals.ProgramRegistryImpl;
public ProgramRegistryImpl(ProgramRegistryServiceImpl registryService)
public ProgramRegistryImpl(FileSystemServer server)
{
_fsServer = server;
_processId = ulong.MaxValue;
_registryService = registryService;
}
public ProgramRegistryImpl(ProgramRegistryServiceImpl registryService, ulong processId)
{
_processId = processId;
_registryService = registryService;
}
/// <returns><see cref="Result.Success"/>: The operation was successful.<br/>
@ -43,7 +51,7 @@ namespace LibHac.FsSrv
if (!ProgramInfo.IsInitialProgram(_processId))
return ResultFs.PermissionDenied.Log();
return _registryService.RegisterProgramInfo(processId, programId, storageId, accessControlData.Buffer,
return Globals.ServiceImpl.RegisterProgramInfo(processId, programId, storageId, accessControlData.Buffer,
accessControlDescriptor.Buffer);
}
@ -56,19 +64,19 @@ namespace LibHac.FsSrv
if (!ProgramInfo.IsInitialProgram(_processId))
return ResultFs.PermissionDenied.Log();
return _registryService.UnregisterProgramInfo(processId);
return Globals.ServiceImpl.UnregisterProgramInfo(processId);
}
/// <inheritdoc cref="ProgramRegistryManager.GetProgramInfo"/>
public Result GetProgramInfo(out ProgramInfo programInfo, ulong processId)
{
return _registryService.GetProgramInfo(out programInfo, processId);
return Globals.ServiceImpl.GetProgramInfo(out programInfo, processId);
}
/// <inheritdoc cref="ProgramRegistryManager.GetProgramInfoByProgramId"/>
public Result GetProgramInfoByProgramId(out ProgramInfo programInfo, ulong programId)
{
return _registryService.GetProgramInfoByProgramId(out programInfo, programId);
return Globals.ServiceImpl.GetProgramInfoByProgramId(out programInfo, programId);
}
/// <summary>

View file

@ -101,7 +101,7 @@ namespace LibHac.FsSrv.Storage
tempStorage = StorageServiceObjectAdapter.CreateShared(ref sdCardStorage);
SdCardEventSimulator eventSimulator = service.Fs.Impl.GetSdCardEventSimulator();
SdCardEventSimulator eventSimulator = service.FsSrv.Impl.GetSdCardEventSimulator();
tempStorage = DeviceEventSimulationStorage.CreateShared(ref tempStorage, eventSimulator);
tempStorage = SpeedEmulationStorage.CreateShared(ref tempStorage);

View file

@ -1,17 +1,52 @@
using LibHac.Diag;
using LibHac.Common;
using LibHac.Diag;
using LibHac.FsSrv.Storage.Sf;
namespace LibHac.FsSrv.Storage
{
internal struct StorageDeviceManagerFactoryGlobals
{
public nint FactoryGuard;
public IStorageDeviceManagerFactory Factory;
}
public static class StorageDeviceManagerFactoryApi
{
/// <summary>
/// Sets the <see cref="IStorageDeviceManagerFactory"/> to be used by the <see cref="FileSystemServer"/>.
/// Calling this method more than once will do nothing.
/// </summary>
/// <param name="storage">The Storage instance to use.</param>
/// <param name="factory">The <see cref="IStorageDeviceManagerFactory"/> to be used by this Storage instance.</param>
public static void InitializeStorageDeviceManagerFactory(this StorageService storage,
IStorageDeviceManagerFactory factory)
{
storage.GetStorageDeviceManagerFactory(factory);
}
}
internal static class StorageDeviceManagerFactory
{
public static Result CreateStorageDeviceManager(this StorageService storage,
out ReferenceCountedDisposable<IStorageDeviceManager> deviceManager, StorageDevicePortId portId)
{
IStorageDeviceManagerFactory factory = storage.GetStorageDeviceManagerFactory();
IStorageDeviceManagerFactory factory = storage.GetStorageDeviceManagerFactory(null);
Assert.NotNull(factory);
return factory.Create(out deviceManager, portId);
}
public static IStorageDeviceManagerFactory GetStorageDeviceManagerFactory(this StorageService storage,
IStorageDeviceManagerFactory factory)
{
ref StorageDeviceManagerFactoryGlobals g = ref storage.FsSrv.Globals.StorageDeviceManagerFactory;
using var initGuard = new InitializationGuard(ref g.FactoryGuard, storage.FsSrv.Globals.InitMutex);
if (initGuard.IsInitialized)
return g.Factory;
g.Factory = factory;
return g.Factory;
}
}
}