diff --git a/src/LibHac/Fs/Shim/Bis.cs b/src/LibHac/Fs/Shim/Bis.cs index 3cae5f21..c0c2991a 100644 --- a/src/LibHac/Fs/Shim/Bis.cs +++ b/src/LibHac/Fs/Shim/Bis.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using LibHac.Common; using LibHac.Fs.Fsa; using LibHac.FsSrv; +using LibHac.FsSrv.Sf; using LibHac.FsSystem; using LibHac.Util; using static LibHac.Fs.CommonMountNames; @@ -85,15 +86,12 @@ namespace LibHac.Fs.Shim Result rc = MountHelpers.CheckMountNameAcceptingReservedMountName(mountName); if (rc.IsFailure()) return rc; - FsPath sfPath; - unsafe { _ = &sfPath; } // workaround for CS0165 - IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject(); // Nintendo doesn't use the provided rootPath - sfPath.Str[0] = 0; + FspPath.CreateEmpty(out FspPath sfPath); - rc = fsProxy.OpenBisFileSystem(out IFileSystem fileSystem, ref sfPath, partitionId); + rc = fsProxy.OpenBisFileSystem(out IFileSystem fileSystem, in sfPath, partitionId); if (rc.IsFailure()) return rc; var nameGenerator = new BisCommonMountNameGenerator(partitionId); diff --git a/src/LibHac/FsSrv/BaseFileSystemService.cs b/src/LibHac/FsSrv/BaseFileSystemService.cs index 41d083de..d098bfbc 100644 --- a/src/LibHac/FsSrv/BaseFileSystemService.cs +++ b/src/LibHac/FsSrv/BaseFileSystemService.cs @@ -37,7 +37,7 @@ namespace LibHac.FsSrv // Reject opening invalid partitions if (requiredAccess == AccessibilityType.NotMount) - return ResultFs.InvalidAlignment.Log(); + return ResultFs.InvalidArgument.Log(); // Verify the caller has the required permissions Accessibility accessibility = programInfo.AccessControl.GetAccessibilityFor(requiredAccess); diff --git a/src/LibHac/FsSrv/FileSystemProxy.cs b/src/LibHac/FsSrv/FileSystemProxy.cs index 75d266be..429f3ee1 100644 --- a/src/LibHac/FsSrv/FileSystemProxy.cs +++ b/src/LibHac/FsSrv/FileSystemProxy.cs @@ -9,6 +9,7 @@ using LibHac.FsSrv.Sf; using LibHac.FsSystem; using LibHac.Kvdb; using LibHac.Ncm; +using LibHac.Sf; using LibHac.Spl; using LibHac.Util; @@ -718,9 +719,9 @@ namespace LibHac.FsSrv throw new NotImplementedException(); } - public Result OpenImageDirectoryFileSystem(out IFileSystem fileSystem, ImageDirectoryId dirId) + public Result OpenImageDirectoryFileSystem(out IFileSystem fileSystem, ImageDirectoryId directoryId) { - throw new NotImplementedException(); + return GetBaseFileSystemService().OpenImageDirectoryFileSystem(out fileSystem, directoryId); } public Result RegisterProgramIndexMapInfo(ReadOnlySpan programIndexMapInfoBuffer, int programCount) @@ -733,16 +734,9 @@ namespace LibHac.FsSrv throw new NotImplementedException(); } - public Result OpenBisFileSystem(out IFileSystem fileSystem, ref FsPath rootPath, BisPartitionId partitionId) + public Result OpenBisFileSystem(out IFileSystem fileSystem, in FspPath rootPath, BisPartitionId partitionId) { - fileSystem = default; - - // Missing permission check, speed emulation storage type wrapper, and FileSystemInterfaceAdapter - - Result rc = PathTools.Normalize(out U8Span normalizedPath, rootPath); - if (rc.IsFailure()) return rc; - - return FsProxyCore.OpenBisFileSystem(out fileSystem, normalizedPath.ToString(), partitionId); + return GetBaseFileSystemService().OpenBisFileSystem(out fileSystem, in rootPath, partitionId); } public Result OpenBisStorage(out IStorage storage, BisPartitionId partitionId) @@ -769,24 +763,22 @@ namespace LibHac.FsSrv public Result OpenSdCardFileSystem(out IFileSystem fileSystem) { - // Missing permission check, speed emulation storage type wrapper, and FileSystemInterfaceAdapter - - return FsProxyCore.OpenSdCardFileSystem(out fileSystem); + return GetBaseFileSystemService().OpenSdCardFileSystem(out fileSystem); } public Result FormatSdCardFileSystem() { - throw new NotImplementedException(); + return GetBaseFileSystemService().FormatSdCardFileSystem(); } public Result FormatSdCardDryRun() { - throw new NotImplementedException(); + return GetBaseFileSystemService().FormatSdCardDryRun(); } public Result IsExFatSupported(out bool isSupported) { - throw new NotImplementedException(); + return GetBaseFileSystemService().IsExFatSupported(out isSupported); } public Result OpenGameCardStorage(out IStorage storage, GameCardHandle handle, GameCardPartitionRaw partitionId) @@ -1045,9 +1037,7 @@ namespace LibHac.FsSrv public Result OpenGameCardFileSystem(out IFileSystem fileSystem, GameCardHandle handle, GameCardPartition partitionId) { - // Missing permission check and FileSystemInterfaceAdapter - - return FsProxyCore.OpenGameCardFileSystem(out fileSystem, handle, partitionId); + return GetBaseFileSystemService().OpenGameCardFileSystem(out fileSystem, handle, partitionId); } public Result QuerySaveDataTotalSize(out long totalSize, long dataSize, long journalSize) @@ -1137,12 +1127,12 @@ namespace LibHac.FsSrv public Result CreatePaddingFile(long size) { - throw new NotImplementedException(); + return GetBaseFileSystemService().CreatePaddingFile(size); } public Result DeleteAllPaddingFiles() { - throw new NotImplementedException(); + return GetBaseFileSystemService().DeleteAllPaddingFiles(); } public Result DisableAutoSaveDataCreation() @@ -1223,6 +1213,11 @@ namespace LibHac.FsSrv return Result.Success; } + public Result OpenBisWiper(out IWiper bisWiper, NativeHandle transferMemoryHandle, ulong transferMemorySize) + { + return GetBaseFileSystemService().OpenBisWiper(out bisWiper, transferMemoryHandle, transferMemorySize); + } + internal Result OpenMultiCommitContextSaveData(out IFileSystem fileSystem) { fileSystem = default; @@ -1272,6 +1267,11 @@ namespace LibHac.FsSrv return FsProxyCore.ProgramRegistry.GetProgramInfo(out programInfo, CurrentProcess); } + private BaseFileSystemService GetBaseFileSystemService() + { + return new BaseFileSystemService(FsProxyCore.Config.BaseFileSystemServiceImpl, CurrentProcess); + } + internal bool IsCurrentProcess(ulong processId) { ulong currentId = Hos.Os.GetCurrentProcessId().Value; diff --git a/src/LibHac/FsSrv/FileSystemProxyConfiguration.cs b/src/LibHac/FsSrv/FileSystemProxyConfiguration.cs index ed15e0fd..d691e60f 100644 --- a/src/LibHac/FsSrv/FileSystemProxyConfiguration.cs +++ b/src/LibHac/FsSrv/FileSystemProxyConfiguration.cs @@ -5,6 +5,7 @@ namespace LibHac.FsSrv public class FileSystemProxyConfiguration { public FileSystemCreators FsCreatorInterfaces { get; set; } + public BaseFileSystemServiceImpl BaseFileSystemServiceImpl { get; set; } public ProgramRegistryServiceImpl ProgramRegistryServiceImpl { get; set; } } } diff --git a/src/LibHac/FsSrv/FileSystemServer.cs b/src/LibHac/FsSrv/FileSystemServer.cs index cebda0a8..c2a535e3 100644 --- a/src/LibHac/FsSrv/FileSystemServer.cs +++ b/src/LibHac/FsSrv/FileSystemServer.cs @@ -3,6 +3,7 @@ using LibHac.Fs; using LibHac.Fs.Impl; using LibHac.Fs.Shim; using LibHac.FsSrv.Creators; +using LibHac.FsSrv.Impl; using LibHac.Sm; namespace LibHac.FsSrv @@ -39,11 +40,7 @@ namespace LibHac.FsSrv ExternalKeySet externalKeySet = config.ExternalKeySet ?? new ExternalKeySet(); Timer = config.TimeSpanGenerator ?? new StopWatchTimeSpanGenerator(); - var fspConfig = new FileSystemProxyConfiguration - { - FsCreatorInterfaces = config.FsCreators, - ProgramRegistryServiceImpl = new ProgramRegistryServiceImpl(this) - }; + FileSystemProxyConfiguration fspConfig = InitializeFileSystemProxyConfiguration(config); FsProxyCore = new FileSystemProxyCore(fspConfig, externalKeySet, config.DeviceOperator); @@ -81,6 +78,29 @@ namespace LibHac.FsSrv return new FileSystemClient(Hos); } + private FileSystemProxyConfiguration InitializeFileSystemProxyConfiguration(FileSystemServerConfig config) + { + var programRegistryService = new ProgramRegistryServiceImpl(this); + var programRegistry = new ProgramRegistryImpl(programRegistryService); + + var baseFsServiceConfig = new BaseFileSystemServiceImpl.Configuration(); + baseFsServiceConfig.BisFileSystemCreator = config.FsCreators.BuiltInStorageFileSystemCreator; + baseFsServiceConfig.GameCardFileSystemCreator = config.FsCreators.GameCardFileSystemCreator; + baseFsServiceConfig.SdCardFileSystemCreator = config.FsCreators.SdCardFileSystemCreator; + baseFsServiceConfig.BisWiperCreator = BisWiper.CreateWiper; + baseFsServiceConfig.ProgramRegistry = programRegistry; + var baseFsService = new BaseFileSystemServiceImpl(in baseFsServiceConfig); + + var fspConfig = new FileSystemProxyConfiguration + { + FsCreatorInterfaces = config.FsCreators, + BaseFileSystemServiceImpl = baseFsService, + ProgramRegistryServiceImpl = programRegistryService + }; + + return fspConfig; + } + private FileSystemProxy GetFileSystemProxyServiceObject() { return new FileSystemProxy(Hos, FsProxyCore); diff --git a/src/LibHac/FsSrv/IFileSystemProxy.cs b/src/LibHac/FsSrv/IFileSystemProxy.cs index fe466db5..61b43016 100644 --- a/src/LibHac/FsSrv/IFileSystemProxy.cs +++ b/src/LibHac/FsSrv/IFileSystemProxy.cs @@ -2,8 +2,10 @@ using LibHac.Common; using LibHac.Fs; using LibHac.Fs.Fsa; +using LibHac.FsSrv.Sf; using LibHac.FsSystem; using LibHac.Ncm; +using LibHac.Sf; using LibHac.Spl; namespace LibHac.FsSrv @@ -15,7 +17,7 @@ namespace LibHac.FsSrv Result OpenFileSystemWithPatch(out IFileSystem fileSystem, ProgramId programId, FileSystemProxyType type); Result OpenFileSystemWithId(out IFileSystem fileSystem, ref FsPath path, ulong id, FileSystemProxyType type); Result OpenDataFileSystemByProgramId(out IFileSystem fileSystem, ProgramId programId); - Result OpenBisFileSystem(out IFileSystem fileSystem, ref FsPath rootPath, BisPartitionId partitionId); + Result OpenBisFileSystem(out IFileSystem fileSystem, in FspPath rootPath, BisPartitionId partitionId); Result OpenBisStorage(out IStorage storage, BisPartitionId partitionId); Result InvalidateBisCache(); Result OpenHostFileSystemWithOption(out IFileSystem fileSystem, ref FsPath path, MountHostOption option); @@ -55,7 +57,7 @@ namespace LibHac.FsSrv Result OpenSaveDataMetaFile(out IFile file, SaveDataSpaceId spaceId, ref SaveDataAttribute attribute, SaveDataMetaType type); Result ListAccessibleSaveDataOwnerId(out int readCount, Span idBuffer, ProgramId programId, int startIndex, int bufferIdCount); - Result OpenImageDirectoryFileSystem(out IFileSystem fileSystem, ImageDirectoryId dirId); + Result OpenImageDirectoryFileSystem(out IFileSystem fileSystem, ImageDirectoryId directoryId); Result OpenContentStorageFileSystem(out IFileSystem fileSystem, ContentStorageId storageId); Result OpenCloudBackupWorkStorageFileSystem(out IFileSystem fileSystem, CloudBackupWorkStorageId storageId); Result OpenCustomStorageFileSystem(out IFileSystem fileSystem, CustomStorageId storageId); @@ -103,5 +105,6 @@ namespace LibHac.FsSrv Result OverrideSaveDataTransferTokenSignVerificationKey(ReadOnlySpan key); Result CorruptSaveDataFileSystemByOffset(SaveDataSpaceId spaceId, ulong saveDataId, long offset); Result OpenMultiCommitManager(out IMultiCommitManager commitManager); + Result OpenBisWiper(out IWiper bisWiper, NativeHandle transferMemoryHandle, ulong transferMemorySize); } } \ No newline at end of file diff --git a/src/LibHac/FsSrv/Impl/BisWiper.cs b/src/LibHac/FsSrv/Impl/BisWiper.cs new file mode 100644 index 00000000..d82ccf77 --- /dev/null +++ b/src/LibHac/FsSrv/Impl/BisWiper.cs @@ -0,0 +1,29 @@ +using System; +using LibHac.FsSrv.Sf; +using LibHac.Sf; + +namespace LibHac.FsSrv.Impl +{ + internal class BisWiper : IWiper + { + // ReSharper disable UnusedParameter.Local + public BisWiper(NativeHandle memoryHandle, ulong memorySize) { } + // ReSharper restore UnusedParameter.Local + + public Result Startup(out long spaceToWipe) + { + throw new NotImplementedException(); + } + + public Result Process(out long remainingSpaceToWipe) + { + throw new NotImplementedException(); + } + + public static Result CreateWiper(out IWiper wiper, NativeHandle memoryHandle, ulong memorySize) + { + wiper = new BisWiper(memoryHandle, memorySize); + return Result.Success; + } + } +} diff --git a/src/LibHac/FsSrv/Sf/FspPath.cs b/src/LibHac/FsSrv/Sf/FspPath.cs index fe314ada..761507c0 100644 --- a/src/LibHac/FsSrv/Sf/FspPath.cs +++ b/src/LibHac/FsSrv/Sf/FspPath.cs @@ -38,6 +38,12 @@ namespace LibHac.FsSrv.Sf return overflowed ? ResultFs.TooLongPath.Log() : Result.Success; } + public static void CreateEmpty(out FspPath fspPath) + { + Unsafe.SkipInit(out fspPath); + SpanHelpers.AsByteSpan(ref fspPath)[0] = 0; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator U8Span(in FspPath value) => new U8Span(SpanHelpers.AsReadOnlyByteSpan(in value));