Fix method signatures in IFileSystemProxy

This commit is contained in:
Alex Barney 2020-11-02 17:05:13 -07:00
parent 882e6bc937
commit a3220cc8df
20 changed files with 404 additions and 208 deletions

View file

@ -3,6 +3,7 @@ using System.Runtime.CompilerServices;
using LibHac.Common; using LibHac.Common;
using LibHac.Fs.Accessors; using LibHac.Fs.Accessors;
using LibHac.FsSrv; using LibHac.FsSrv;
using LibHac.Sf;
namespace LibHac.Fs namespace LibHac.Fs
{ {
@ -187,7 +188,7 @@ namespace LibHac.Fs
string logString = AccessLogHelpers.BuildDefaultLogLine(result, startTime, endTime, handleId, message, caller); string logString = AccessLogHelpers.BuildDefaultLogLine(result, startTime, endTime, handleId, message, caller);
IFileSystemProxy fsProxy = GetFileSystemProxyServiceObject(); IFileSystemProxy fsProxy = GetFileSystemProxyServiceObject();
fsProxy.OutputAccessLogToSdCard(logString.ToU8Span()); fsProxy.OutputAccessLogToSdCard(new InBuffer(logString.ToU8Span())).IgnoreResult();
} }
} }

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices;
using LibHac.Common; using LibHac.Common;
using LibHac.Fs.Impl; using LibHac.Fs.Impl;
using LibHac.FsSrv; using LibHac.FsSrv;
@ -137,8 +138,7 @@ namespace LibHac.Fs.Shim
// todo: Decide how to handle SetBisRootForHost since it allows mounting any directory on the user's computer // todo: Decide how to handle SetBisRootForHost since it allows mounting any directory on the user's computer
public static Result SetBisRootForHost(this FileSystemClient fs, BisPartitionId partitionId, U8Span rootPath) public static Result SetBisRootForHost(this FileSystemClient fs, BisPartitionId partitionId, U8Span rootPath)
{ {
FsPath sfPath; Unsafe.SkipInit(out FsPath path);
unsafe { _ = &sfPath; } // workaround for CS0165
int pathLen = StringUtils.GetLength(rootPath, PathTools.MaxPathLength + 1); int pathLen = StringUtils.GetLength(rootPath, PathTools.MaxPathLength + 1);
if (pathLen > PathTools.MaxPathLength) if (pathLen > PathTools.MaxPathLength)
@ -150,18 +150,20 @@ namespace LibHac.Fs.Shim
? StringTraits.NullTerminator ? StringTraits.NullTerminator
: StringTraits.DirectorySeparator; : StringTraits.DirectorySeparator;
var sb = new U8StringBuilder(sfPath.Str); var sb = new U8StringBuilder(path.Str);
Result rc = sb.Append(rootPath).Append(endingSeparator).ToSfPath(); Result rc = sb.Append(rootPath).Append(endingSeparator).ToSfPath();
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
} }
else else
{ {
sfPath.Str[0] = StringTraits.NullTerminator; path.Str[0] = StringTraits.NullTerminator;
} }
FspPath.FromSpan(out FspPath sfPath, path.Str);
IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject(); IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();
return fsProxy.SetBisRootForHost(partitionId, ref sfPath); return fsProxy.SetBisRootForHost(partitionId, in sfPath);
} }
public static Result OpenBisPartition(this FileSystemClient fs, out IStorage partitionStorage, BisPartitionId partitionId) public static Result OpenBisPartition(this FileSystemClient fs, out IStorage partitionStorage, BisPartitionId partitionId)

View file

@ -1,7 +1,8 @@
using System; using System;
using LibHac.Common; using LibHac.Common;
using LibHac.Fs.Fsa; using LibHac.Fs.Impl;
using LibHac.FsSrv; using LibHac.FsSrv;
using LibHac.FsSrv.Sf;
namespace LibHac.Fs.Shim namespace LibHac.Fs.Shim
{ {
@ -12,12 +13,22 @@ namespace LibHac.Fs.Shim
Result rc = MountHelpers.CheckMountName(mountName); Result rc = MountHelpers.CheckMountName(mountName);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject(); ReferenceCountedDisposable<IFileSystemSf> customFs = null;
try
{
IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();
rc = fsProxy.OpenCustomStorageFileSystem(out IFileSystem customFs, storageId); rc = fsProxy.OpenCustomStorageFileSystem(out customFs, storageId);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
return fs.Register(mountName, customFs); var adapter = new FileSystemServiceObjectAdapter(customFs);
return fs.Register(mountName, adapter);
}
finally
{
customFs?.Dispose();
}
} }
public static string GetCustomStorageDirectoryName(CustomStorageId storageId) public static string GetCustomStorageDirectoryName(CustomStorageId storageId)

View file

@ -12,33 +12,63 @@ namespace LibHac.Fs.Shim
{ {
handle = default; handle = default;
IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject(); ReferenceCountedDisposable<IDeviceOperator> deviceOperator = null;
try
{
IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();
Result rc = fsProxy.OpenDeviceOperator(out IDeviceOperator deviceOperator); Result rc = fsProxy.OpenDeviceOperator(out deviceOperator);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
return deviceOperator.GetGameCardHandle(out handle); return deviceOperator.Target.GetGameCardHandle(out handle);
}
finally
{
deviceOperator?.Dispose();
}
} }
public static bool IsGameCardInserted(this FileSystemClient fs) public static bool IsGameCardInserted(this FileSystemClient fs)
{ {
IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject(); ReferenceCountedDisposable<IDeviceOperator> deviceOperator = null;
try
{
IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();
Result rc = fsProxy.OpenDeviceOperator(out IDeviceOperator deviceOperator); Result rc = fsProxy.OpenDeviceOperator(out deviceOperator);
if (rc.IsFailure()) throw new LibHacException("Abort"); if (rc.IsFailure()) throw new LibHacException("Abort");
rc = deviceOperator.IsGameCardInserted(out bool isInserted); rc = deviceOperator.Target.IsGameCardInserted(out bool isInserted);
if (rc.IsFailure()) throw new LibHacException("Abort"); if (rc.IsFailure()) throw new LibHacException("Abort");
return isInserted; return isInserted;
}
finally
{
deviceOperator?.Dispose();
}
} }
public static Result OpenGameCardPartition(this FileSystemClient fs, out IStorage storage, public static Result OpenGameCardPartition(this FileSystemClient fs, out IStorage storage,
GameCardHandle handle, GameCardPartitionRaw partitionType) GameCardHandle handle, GameCardPartitionRaw partitionType)
{ {
IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject(); storage = default;
return fsProxy.OpenGameCardStorage(out storage, handle, partitionType); ReferenceCountedDisposable<IStorageSf> sfStorage = null;
try
{
IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();
Result rc = fsProxy.OpenGameCardStorage(out sfStorage, handle, partitionType);
if (rc.IsFailure()) return rc;
storage = new StorageServiceObjectAdapter(sfStorage);
return Result.Success;
}
finally
{
sfStorage?.Dispose();
}
} }
public static Result MountGameCardPartition(this FileSystemClient fs, U8Span mountName, GameCardHandle handle, public static Result MountGameCardPartition(this FileSystemClient fs, U8Span mountName, GameCardHandle handle,

View file

@ -3,7 +3,9 @@ using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using LibHac.Common; using LibHac.Common;
using LibHac.Fs.Fsa; using LibHac.Fs.Fsa;
using LibHac.Fs.Impl;
using LibHac.FsSrv; using LibHac.FsSrv;
using LibHac.FsSrv.Sf;
using LibHac.FsSystem; using LibHac.FsSystem;
using LibHac.Util; using LibHac.Util;
using static LibHac.Fs.CommonPaths; using static LibHac.Fs.CommonPaths;
@ -76,12 +78,11 @@ namespace LibHac.Fs.Shim
public static Result MountHostRoot(this FileSystemClient fs) public static Result MountHostRoot(this FileSystemClient fs)
{ {
IFileSystem hostFileSystem = default; IFileSystem hostFileSystem = default;
var path = new FsPath(); FspPath.CreateEmpty(out FspPath path);
path.Str[0] = 0;
static string LogMessageGenerator() => $", name: \"{HostRootFileSystemMountName.ToString()}\""; static string LogMessageGenerator() => $", name: \"{HostRootFileSystemMountName.ToString()}\"";
Result OpenHostFs() => OpenHostFileSystemImpl(fs, out hostFileSystem, ref path, MountHostOption.None); Result OpenHostFs() => OpenHostFileSystemImpl(fs, out hostFileSystem, in path, MountHostOption.None);
Result MountHostFs() => fs.Register(HostRootFileSystemMountName, hostFileSystem, Result MountHostFs() => fs.Register(HostRootFileSystemMountName, hostFileSystem,
new HostRootCommonMountNameGenerator()); new HostRootCommonMountNameGenerator());
@ -110,13 +111,12 @@ namespace LibHac.Fs.Shim
public static Result MountHostRoot(this FileSystemClient fs, MountHostOption option) public static Result MountHostRoot(this FileSystemClient fs, MountHostOption option)
{ {
IFileSystem hostFileSystem = default; IFileSystem hostFileSystem = default;
var path = new FsPath(); FspPath.CreateEmpty(out FspPath path);
path.Str[0] = 0;
string LogMessageGenerator() => string LogMessageGenerator() =>
$", name: \"{HostRootFileSystemMountName.ToString()}, mount_host_option: {option}\""; $", name: \"{HostRootFileSystemMountName.ToString()}, mount_host_option: {option}\"";
Result OpenHostFs() => OpenHostFileSystemImpl(fs, out hostFileSystem, ref path, option); Result OpenHostFs() => OpenHostFileSystemImpl(fs, out hostFileSystem, in path, option);
Result MountHostFs() => fs.Register(HostRootFileSystemMountName, hostFileSystem, Result MountHostFs() => fs.Register(HostRootFileSystemMountName, hostFileSystem,
new HostRootCommonMountNameGenerator()); new HostRootCommonMountNameGenerator());
@ -318,8 +318,7 @@ namespace LibHac.Fs.Shim
if (pathLength + 1 > PathTools.MaxPathLength) if (pathLength + 1 > PathTools.MaxPathLength)
return ResultFs.TooLongPath.Log(); return ResultFs.TooLongPath.Log();
FsPath fullPath; Unsafe.SkipInit(out FsPath fullPath);
unsafe { _ = &fullPath; } // workaround for CS0165
var sb = new U8StringBuilder(fullPath.Str); var sb = new U8StringBuilder(fullPath.Str);
sb.Append(StringTraits.DirectorySeparator).Append(path); sb.Append(StringTraits.DirectorySeparator).Append(path);
@ -341,7 +340,9 @@ namespace LibHac.Fs.Shim
} }
} }
return OpenHostFileSystemImpl(fs, out fileSystem, ref fullPath, option); FspPath.FromSpan(out FspPath sfPath, fullPath.Str);
return OpenHostFileSystemImpl(fs, out fileSystem, in sfPath, option);
} }
/// <summary> /// <summary>
@ -352,26 +353,34 @@ namespace LibHac.Fs.Shim
/// <param name="path">The path on the host computer to open. e.g. /C:\Windows\System32/</param> /// <param name="path">The path on the host computer to open. e.g. /C:\Windows\System32/</param>
/// <param name="option">Options for opening the host file system.</param> /// <param name="option">Options for opening the host file system.</param>
/// <returns>The <see cref="Result"/> of the operation.</returns> /// <returns>The <see cref="Result"/> of the operation.</returns>
private static Result OpenHostFileSystemImpl(FileSystemClient fs, out IFileSystem fileSystem, ref FsPath path, MountHostOption option) private static Result OpenHostFileSystemImpl(FileSystemClient fs, out IFileSystem fileSystem, in FspPath path,
MountHostOption option)
{ {
fileSystem = default; fileSystem = default;
IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject(); IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();
IFileSystem hostFs; ReferenceCountedDisposable<IFileSystemSf> hostFs = null;
if (option == MountHostOption.None) try
{ {
Result rc = fsProxy.OpenHostFileSystem(out hostFs, ref path); if (option == MountHostOption.None)
if (rc.IsFailure()) return rc; {
} Result rc = fsProxy.OpenHostFileSystem(out hostFs, in path);
else if (rc.IsFailure()) return rc;
{ }
Result rc = fsProxy.OpenHostFileSystemWithOption(out hostFs, ref path, option); else
if (rc.IsFailure()) return rc; {
} Result rc = fsProxy.OpenHostFileSystemWithOption(out hostFs, in path, option);
if (rc.IsFailure()) return rc;
}
fileSystem = hostFs; fileSystem = new FileSystemServiceObjectAdapter(hostFs);
return Result.Success; return Result.Success;
}
finally
{
hostFs?.Dispose();
}
} }
} }
} }

View file

@ -212,7 +212,7 @@ namespace LibHac.Fs.Shim
SpaceId = spaceId SpaceId = spaceId
}; };
return fsProxy.CreateSaveDataFileSystemBySystemSaveDataId(ref attribute, ref createInfo); return fsProxy.CreateSaveDataFileSystemBySystemSaveDataId(in attribute, in createInfo);
}, },
() => $", savedataspaceid: {spaceId}, savedataid: 0x{saveDataId:X}, userid: 0x{userId.Id.High:X16}{userId.Id.Low:X16}, save_data_owner_id: 0x{ownerId:X}, save_data_size: {size}, save_data_journal_size: {journalSize}, save_data_flags: 0x{(int)flags:x8}"); () => $", savedataspaceid: {spaceId}, savedataid: 0x{saveDataId:X}, userid: 0x{userId.Id.High:X16}{userId.Id.Low:X16}, save_data_owner_id: 0x{ownerId:X}, save_data_size: {size}, save_data_journal_size: {journalSize}, save_data_flags: 0x{(int)flags:x8}");
} }

View file

@ -56,15 +56,23 @@ namespace LibHac.Fs.Shim
public static bool IsSdCardInserted(this FileSystemClient fs) public static bool IsSdCardInserted(this FileSystemClient fs)
{ {
IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject(); ReferenceCountedDisposable<IDeviceOperator> deviceOperator = null;
try
{
IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();
Result rc = fsProxy.OpenDeviceOperator(out IDeviceOperator deviceOperator); Result rc = fsProxy.OpenDeviceOperator(out deviceOperator);
if (rc.IsFailure()) throw new HorizonResultException(rc, "Abort"); if (rc.IsFailure()) throw new HorizonResultException(rc, "Abort");
rc = deviceOperator.IsSdCardInserted(out bool isInserted); rc = deviceOperator.Target.IsSdCardInserted(out bool isInserted);
if (rc.IsFailure()) throw new HorizonResultException(rc, "Abort"); if (rc.IsFailure()) throw new HorizonResultException(rc, "Abort");
return isInserted; return isInserted;
}
finally
{
deviceOperator?.Dispose();
}
} }
public static Result SetSdCardEncryptionSeed(this FileSystemClient fs, in EncryptionSeed seed) public static Result SetSdCardEncryptionSeed(this FileSystemClient fs, in EncryptionSeed seed)

View file

@ -110,12 +110,12 @@ namespace LibHac.FsSrv.Creators
var partitionPath = GetPartitionPath(partitionId).ToU8String(); var partitionPath = GetPartitionPath(partitionId).ToU8String();
ReferenceCountedDisposable<IFileSystem> partitionFileSystem = null; ReferenceCountedDisposable<IFileSystem> partitionFileSystem = null;
ReferenceCountedDisposable<IFileSystem> sharedRootFs = null;
try try
{ {
// Todo: Store shared file systems sharedRootFs = new ReferenceCountedDisposable<IFileSystem>(Config.RootFileSystem);
using var sharedRootFs = new ReferenceCountedDisposable<IFileSystem>(Config.RootFileSystem);
Result rc = Utility.WrapSubDirectory(out partitionFileSystem, sharedRootFs, partitionPath, true); Result rc = Utility.WrapSubDirectory(out partitionFileSystem, ref sharedRootFs, partitionPath, true);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
@ -125,11 +125,12 @@ namespace LibHac.FsSrv.Creators
return Result.Success; return Result.Success;
} }
return Utility.CreateSubDirectoryFileSystem(out fileSystem, partitionFileSystem, rootPath); return Utility.CreateSubDirectoryFileSystem(out fileSystem, ref partitionFileSystem, rootPath);
} }
finally finally
{ {
partitionFileSystem?.Dispose(); partitionFileSystem?.Dispose();
sharedRootFs?.Dispose();
} }
} }

View file

@ -5,11 +5,7 @@ namespace LibHac.FsSrv.Creators
{ {
public interface ISubDirectoryFileSystemCreator public interface ISubDirectoryFileSystemCreator
{ {
// Todo: Remove the raw IFileSystem overloads Result Create(out ReferenceCountedDisposable<IFileSystem> subDirFileSystem, ref ReferenceCountedDisposable<IFileSystem> baseFileSystem, U8Span path);
Result Create(out IFileSystem subDirFileSystem, IFileSystem baseFileSystem, U8Span path); Result Create(out ReferenceCountedDisposable<IFileSystem> subDirFileSystem, ref ReferenceCountedDisposable<IFileSystem> baseFileSystem, U8Span path, bool preserveUnc);
Result Create(out IFileSystem subDirFileSystem, IFileSystem baseFileSystem, U8Span path, bool preserveUnc);
Result Create(out ReferenceCountedDisposable<IFileSystem> subDirFileSystem, ReferenceCountedDisposable<IFileSystem> baseFileSystem, U8Span path);
Result Create(out ReferenceCountedDisposable<IFileSystem> subDirFileSystem, ReferenceCountedDisposable<IFileSystem> baseFileSystem, U8Span path, bool preserveUnc);
} }
} }

View file

@ -6,31 +6,14 @@ namespace LibHac.FsSrv.Creators
{ {
public class SubDirectoryFileSystemCreator : ISubDirectoryFileSystemCreator public class SubDirectoryFileSystemCreator : ISubDirectoryFileSystemCreator
{ {
public Result Create(out IFileSystem subDirFileSystem, IFileSystem baseFileSystem, U8Span path) public Result Create(out ReferenceCountedDisposable<IFileSystem> subDirFileSystem,
ref ReferenceCountedDisposable<IFileSystem> baseFileSystem, U8Span path)
{ {
return Create(out subDirFileSystem, baseFileSystem, path, false); return Create(out subDirFileSystem, ref baseFileSystem, path, false);
}
public Result Create(out IFileSystem subDirFileSystem, IFileSystem baseFileSystem, U8Span path, bool preserveUnc)
{
subDirFileSystem = default;
Result rc = baseFileSystem.OpenDirectory(out IDirectory _, path, OpenDirectoryMode.Directory);
if (rc.IsFailure()) return rc;
rc = SubdirectoryFileSystem.CreateNew(out SubdirectoryFileSystem fs, baseFileSystem, path.ToU8String(), preserveUnc);
subDirFileSystem = fs;
return rc;
} }
public Result Create(out ReferenceCountedDisposable<IFileSystem> subDirFileSystem, public Result Create(out ReferenceCountedDisposable<IFileSystem> subDirFileSystem,
ReferenceCountedDisposable<IFileSystem> baseFileSystem, U8Span path) ref ReferenceCountedDisposable<IFileSystem> baseFileSystem, U8Span path, bool preserveUnc)
{
return Create(out subDirFileSystem, baseFileSystem, path, false);
}
public Result Create(out ReferenceCountedDisposable<IFileSystem> subDirFileSystem,
ReferenceCountedDisposable<IFileSystem> baseFileSystem, U8Span path, bool preserveUnc)
{ {
subDirFileSystem = default; subDirFileSystem = default;
@ -39,7 +22,7 @@ namespace LibHac.FsSrv.Creators
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
// Initialize the SubdirectoryFileSystem // Initialize the SubdirectoryFileSystem
var subDir = new SubdirectoryFileSystem(baseFileSystem, preserveUnc); var subDir = new SubdirectoryFileSystem(ref baseFileSystem, preserveUnc);
using var subDirShared = new ReferenceCountedDisposable<SubdirectoryFileSystem>(subDir); using var subDirShared = new ReferenceCountedDisposable<SubdirectoryFileSystem>(subDir);
rc = subDirShared.Target.Initialize(path); rc = subDirShared.Target.Initialize(path);

View file

@ -13,6 +13,8 @@ namespace LibHac.FsSrv
SdCard = sdCard; SdCard = sdCard;
} }
public void Dispose() { }
public Result IsSdCardInserted(out bool isInserted) public Result IsSdCardInserted(out bool isInserted)
{ {
isInserted = SdCard.IsSdCardInserted(); isInserted = SdCard.IsSdCardInserted();

View file

@ -4,6 +4,8 @@ using LibHac.Fs;
using LibHac.Fs.Fsa; using LibHac.Fs.Fsa;
using LibHac.Fs.Shim; using LibHac.Fs.Shim;
using LibHac.FsSrv.Creators; using LibHac.FsSrv.Creators;
using LibHac.FsSrv.Impl;
using LibHac.FsSrv.Sf;
namespace LibHac.FsSrv namespace LibHac.FsSrv
{ {
@ -13,7 +15,7 @@ namespace LibHac.FsSrv
private FileSystemCreators FsCreators => Config.FsCreatorInterfaces; private FileSystemCreators FsCreators => Config.FsCreatorInterfaces;
internal ProgramRegistryImpl ProgramRegistry { get; } internal ProgramRegistryImpl ProgramRegistry { get; }
private IDeviceOperator DeviceOperator { get; } private ReferenceCountedDisposable<IDeviceOperator> DeviceOperator { get; }
private byte[] SdEncryptionSeed { get; } = new byte[0x10]; private byte[] SdEncryptionSeed { get; } = new byte[0x10];
@ -27,31 +29,57 @@ namespace LibHac.FsSrv
{ {
Config = config; Config = config;
ProgramRegistry = new ProgramRegistryImpl(Config.ProgramRegistryService); ProgramRegistry = new ProgramRegistryImpl(Config.ProgramRegistryService);
DeviceOperator = deviceOperator; DeviceOperator = new ReferenceCountedDisposable<IDeviceOperator>(deviceOperator);
} }
public Result OpenGameCardStorage(out IStorage storage, GameCardHandle handle, GameCardPartitionRaw partitionId) public Result OpenGameCardStorage(out ReferenceCountedDisposable<IStorageSf> storage, GameCardHandle handle,
GameCardPartitionRaw partitionId)
{ {
switch (partitionId) storage = default;
Result rc;
IStorage gcStorage = null;
ReferenceCountedDisposable<IStorage> sharedGcStorage = null;
try
{ {
case GameCardPartitionRaw.NormalReadOnly: switch (partitionId)
return FsCreators.GameCardStorageCreator.CreateNormal(handle, out storage); {
case GameCardPartitionRaw.SecureReadOnly: case GameCardPartitionRaw.NormalReadOnly:
return FsCreators.GameCardStorageCreator.CreateSecure(handle, out storage); rc = FsCreators.GameCardStorageCreator.CreateNormal(handle, out gcStorage);
case GameCardPartitionRaw.RootWriteOnly: break;
return FsCreators.GameCardStorageCreator.CreateWritable(handle, out storage); case GameCardPartitionRaw.SecureReadOnly:
default: rc = FsCreators.GameCardStorageCreator.CreateSecure(handle, out gcStorage);
throw new ArgumentOutOfRangeException(nameof(partitionId), partitionId, null); break;
case GameCardPartitionRaw.RootWriteOnly:
rc = FsCreators.GameCardStorageCreator.CreateWritable(handle, out gcStorage);
break;
default:
throw new ArgumentOutOfRangeException(nameof(partitionId), partitionId, null);
}
if (rc.IsFailure()) return rc;
sharedGcStorage = new ReferenceCountedDisposable<IStorage>(gcStorage);
gcStorage = null;
storage = StorageInterfaceAdapter.CreateShared(ref sharedGcStorage);
return Result.Success;
}
finally
{
gcStorage?.Dispose();
sharedGcStorage?.Dispose();
} }
} }
public Result OpenDeviceOperator(out IDeviceOperator deviceOperator) public Result OpenDeviceOperator(out ReferenceCountedDisposable<IDeviceOperator> deviceOperator)
{ {
deviceOperator = DeviceOperator; deviceOperator = DeviceOperator.AddReference();
return Result.Success; return Result.Success;
} }
public Result OpenCustomStorageFileSystem(out IFileSystem fileSystem, CustomStorageId storageId) public Result OpenCustomStorageFileSystem(out ReferenceCountedDisposable<IFileSystem> fileSystem,
CustomStorageId storageId)
{ {
fileSystem = default; fileSystem = default;
@ -72,7 +100,7 @@ namespace LibHac.FsSrv
EncryptedFsKeyId.CustomStorage, SdEncryptionSeed); EncryptedFsKeyId.CustomStorage, SdEncryptionSeed);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
fileSystem = encryptedFs; fileSystem = new ReferenceCountedDisposable<IFileSystem>(encryptedFs);
return Result.Success; return Result.Success;
} }
case CustomStorageId.System: case CustomStorageId.System:
@ -87,7 +115,8 @@ namespace LibHac.FsSrv
rc = Util.CreateSubFileSystem(out IFileSystem subFs, userFs, subDirName, true); rc = Util.CreateSubFileSystem(out IFileSystem subFs, userFs, subDirName, true);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
fileSystem = subFs; // Todo: Get shared object from earlier functions
fileSystem = new ReferenceCountedDisposable<IFileSystem>(subFs);
return Result.Success; return Result.Success;
} }
default: default:
@ -95,7 +124,8 @@ namespace LibHac.FsSrv
} }
} }
public Result OpenHostFileSystem(out IFileSystem fileSystem, U8Span path, bool openCaseSensitive) public Result OpenHostFileSystem(out ReferenceCountedDisposable<IFileSystem> fileSystem, U8Span path,
bool openCaseSensitive)
{ {
fileSystem = default; fileSystem = default;
Result rc; Result rc;
@ -106,27 +136,42 @@ namespace LibHac.FsSrv
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
} }
// Todo: Return shared fs from Create
rc = FsCreators.TargetManagerFileSystemCreator.Create(out IFileSystem hostFs, openCaseSensitive); rc = FsCreators.TargetManagerFileSystemCreator.Create(out IFileSystem hostFs, openCaseSensitive);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
if (path.IsEmpty()) ReferenceCountedDisposable<IFileSystem> sharedHostFs = null;
ReferenceCountedDisposable<IFileSystem> subDirFs = null;
try
{ {
ReadOnlySpan<byte> rootHostPath = new[] { (byte)'C', (byte)':', (byte)'/' }; sharedHostFs = new ReferenceCountedDisposable<IFileSystem>(hostFs);
rc = hostFs.GetEntryType(out _, new U8Span(rootHostPath));
// Nintendo ignores all results other than this one if (path.IsEmpty())
if (ResultFs.TargetNotFound.Includes(rc)) {
return rc; ReadOnlySpan<byte> rootHostPath = new[] { (byte)'C', (byte)':', (byte)'/' };
rc = sharedHostFs.Target.GetEntryType(out _, new U8Span(rootHostPath));
fileSystem = hostFs; // Nintendo ignores all results other than this one
if (ResultFs.TargetNotFound.Includes(rc))
return rc;
Shared.Move(out fileSystem, ref sharedHostFs);
return Result.Success;
}
rc = FsCreators.SubDirectoryFileSystemCreator.Create(out subDirFs, ref sharedHostFs, path,
preserveUnc: true);
if (rc.IsFailure()) return rc;
fileSystem = subDirFs;
return Result.Success; return Result.Success;
} }
finally
rc = FsCreators.SubDirectoryFileSystemCreator.Create(out IFileSystem subDirFs, hostFs, path, preserveUnc: true); {
if (rc.IsFailure()) return rc; sharedHostFs?.Dispose();
subDirFs?.Dispose();
fileSystem = subDirFs; }
return Result.Success;
} }
public Result SetSdCardEncryptionSeed(in EncryptionSeed seed) public Result SetSdCardEncryptionSeed(in EncryptionSeed seed)
@ -139,7 +184,7 @@ namespace LibHac.FsSrv
return Result.Success; return Result.Success;
} }
public Result SetGlobalAccessLogMode(GlobalAccessLogMode mode) public Result SetGlobalAccessLogMode(GlobalAccessLogMode mode)
{ {
LogMode = mode; LogMode = mode;

View file

@ -254,8 +254,8 @@ namespace LibHac.FsSrv
in hashSalt); in hashSalt);
} }
public Result CreateSaveDataFileSystemBySystemSaveDataId(ref SaveDataAttribute attribute, public Result CreateSaveDataFileSystemBySystemSaveDataId(in SaveDataAttribute attribute,
ref SaveDataCreationInfo creationInfo) in SaveDataCreationInfo creationInfo)
{ {
Result rc = GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService); Result rc = GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
@ -399,17 +399,44 @@ namespace LibHac.FsSrv
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Result OpenHostFileSystem(out IFileSystem fileSystem, ref FsPath path) public Result OpenHostFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, in FspPath path)
{ {
return OpenHostFileSystemWithOption(out fileSystem, ref path, MountHostOption.None); return OpenHostFileSystemWithOption(out fileSystem, in path, MountHostOption.None);
} }
public Result OpenHostFileSystemWithOption(out IFileSystem fileSystem, ref FsPath path, MountHostOption option) public Result OpenHostFileSystemWithOption(out ReferenceCountedDisposable<IFileSystemSf> fileSystem,
in FspPath path, MountHostOption option)
{ {
// Missing permission check fileSystem = default;
return FsProxyCore.OpenHostFileSystem(out fileSystem, new U8Span(path.Str), Result rc = GetProgramInfo(out ProgramInfo programInfo);
option.HasFlag(MountHostOption.PseudoCaseSensitive)); if (rc.IsFailure()) return rc;
Accessibility accessibility = programInfo.AccessControl.GetAccessibilityFor(AccessibilityType.MountHost);
if (!accessibility.CanRead || !accessibility.CanWrite)
return ResultFs.PermissionDenied.Log();
ReferenceCountedDisposable<IFileSystem> hostFs = null;
try
{
rc = FsProxyCore.OpenHostFileSystem(out hostFs, new U8Span(path.Str),
option.HasFlag(MountHostOption.PseudoCaseSensitive));
if (rc.IsFailure()) return rc;
bool isRootPath = path.Str[0] == 0;
fileSystem = FileSystemInterfaceAdapter.CreateShared(ref hostFs, isRootPath);
if (fileSystem is null)
return ResultFs.AllocationFailureInCreateShared.Log();
return Result.Success;
}
finally
{
hostFs?.Dispose();
}
} }
public Result OpenSdCardFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem) public Result OpenSdCardFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem)
@ -432,20 +459,31 @@ namespace LibHac.FsSrv
return GetBaseFileSystemService().IsExFatSupported(out isSupported); return GetBaseFileSystemService().IsExFatSupported(out isSupported);
} }
public Result OpenGameCardStorage(out IStorage storage, GameCardHandle handle, GameCardPartitionRaw partitionId) public Result OpenGameCardStorage(out ReferenceCountedDisposable<IStorageSf> storage, GameCardHandle handle,
GameCardPartitionRaw partitionId)
{ {
// Missing permission check and StorageInterfaceAdapter // Missing permission check and StorageInterfaceAdapter
return FsProxyCore.OpenGameCardStorage(out storage, handle, partitionId); return FsProxyCore.OpenGameCardStorage(out storage, handle, partitionId);
} }
public Result OpenDeviceOperator(out IDeviceOperator deviceOperator) public Result OpenDeviceOperator(out ReferenceCountedDisposable<IDeviceOperator> deviceOperator)
{ {
// Missing permission check // Missing permission check
return FsProxyCore.OpenDeviceOperator(out deviceOperator); return FsProxyCore.OpenDeviceOperator(out deviceOperator);
} }
public Result OpenSdCardDetectionEventNotifier(out ReferenceCountedDisposable<IEventNotifier> eventNotifier)
{
throw new NotImplementedException();
}
public Result OpenGameCardDetectionEventNotifier(out ReferenceCountedDisposable<IEventNotifier> eventNotifier)
{
throw new NotImplementedException();
}
public Result OpenSystemDataUpdateEventNotifier(out ReferenceCountedDisposable<IEventNotifier> eventNotifier) public Result OpenSystemDataUpdateEventNotifier(out ReferenceCountedDisposable<IEventNotifier> eventNotifier)
{ {
Result rc = GetNcaFileSystemService(out NcaFileSystemService ncaFsService); Result rc = GetNcaFileSystemService(out NcaFileSystemService ncaFsService);
@ -659,11 +697,37 @@ namespace LibHac.FsSrv
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Result OpenCustomStorageFileSystem(out IFileSystem fileSystem, CustomStorageId storageId) public Result OpenCustomStorageFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, CustomStorageId storageId)
{ {
// Missing permission check, speed emulation storage type wrapper, and FileSystemInterfaceAdapter fileSystem = default;
var storageFlag = StorageType.NonGameCard;
using var scopedLayoutType = new ScopedStorageLayoutTypeSetter(storageFlag);
return FsProxyCore.OpenCustomStorageFileSystem(out fileSystem, storageId); Result rc = GetProgramInfo(out ProgramInfo programInfo);
if (rc.IsFailure()) return rc;
AccessibilityType accessType = storageId > CustomStorageId.SdCard
? AccessibilityType.NotMount
: AccessibilityType.MountCustomStorage;
Accessibility accessibility = programInfo.AccessControl.GetAccessibilityFor(accessType);
if (!accessibility.CanRead || !accessibility.CanWrite)
return ResultFs.PermissionDenied.Log();
ReferenceCountedDisposable<IFileSystem> customFs = null;
try
{
customFs = StorageLayoutTypeSetFileSystem.CreateShared(ref customFs, storageFlag);
customFs = AsynchronousAccessFileSystem.CreateShared(ref customFs);
fileSystem = FileSystemInterfaceAdapter.CreateShared(ref customFs);
return Result.Success;
}
finally
{
customFs?.Dispose();
}
} }
public Result OpenGameCardFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, public Result OpenGameCardFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem,
@ -766,7 +830,7 @@ namespace LibHac.FsSrv
.RegisterProgramIndexMapInfo(programIndexMapInfoBuffer, programCount); .RegisterProgramIndexMapInfo(programIndexMapInfoBuffer, programCount);
} }
public Result SetBisRootForHost(BisPartitionId partitionId, ref FsPath path) public Result SetBisRootForHost(BisPartitionId partitionId, in FspPath path)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
@ -839,7 +903,7 @@ namespace LibHac.FsSrv
return GetProgramIndexRegistryService().GetProgramIndex(out programIndex, out programCount); return GetProgramIndexRegistryService().GetProgramIndex(out programIndex, out programCount);
} }
public Result OutputAccessLogToSdCard(U8Span logString) public Result OutputAccessLogToSdCard(InBuffer logString)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }

View file

@ -1,6 +1,8 @@
namespace LibHac.FsSrv using System;
namespace LibHac.FsSrv
{ {
public interface IDeviceOperator public interface IDeviceOperator : IDisposable
{ {
Result IsSdCardInserted(out bool isInserted); Result IsSdCardInserted(out bool isInserted);
Result IsGameCardInserted(out bool isInserted); Result IsGameCardInserted(out bool isInserted);

View file

@ -20,24 +20,24 @@ namespace LibHac.FsSrv
Result OpenBisFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, in FspPath rootPath, BisPartitionId partitionId); Result OpenBisFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, in FspPath rootPath, BisPartitionId partitionId);
Result OpenBisStorage(out ReferenceCountedDisposable<IStorageSf> storage, BisPartitionId partitionId); Result OpenBisStorage(out ReferenceCountedDisposable<IStorageSf> storage, BisPartitionId partitionId);
Result InvalidateBisCache(); Result InvalidateBisCache();
Result OpenHostFileSystemWithOption(out IFileSystem fileSystem, ref FsPath path, MountHostOption option); Result OpenHostFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, in FspPath path);
Result OpenHostFileSystem(out IFileSystem fileSystem, ref FsPath path);
Result OpenSdCardFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem); Result OpenSdCardFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem);
Result FormatSdCardFileSystem(); Result FormatSdCardFileSystem();
Result DeleteSaveDataFileSystem(ulong saveDataId); Result DeleteSaveDataFileSystem(ulong saveDataId);
Result CreateSaveDataFileSystem(in SaveDataAttribute attribute, in SaveDataCreationInfo creationInfo, in SaveDataMetaInfo metaInfo); Result CreateSaveDataFileSystem(in SaveDataAttribute attribute, in SaveDataCreationInfo creationInfo, in SaveDataMetaInfo metaInfo);
Result CreateSaveDataFileSystemBySystemSaveDataId(ref SaveDataAttribute attribute, ref SaveDataCreationInfo creationInfo); Result CreateSaveDataFileSystemBySystemSaveDataId(in SaveDataAttribute attribute, in SaveDataCreationInfo creationInfo);
Result RegisterSaveDataFileSystemAtomicDeletion(InBuffer saveDataIds); Result RegisterSaveDataFileSystemAtomicDeletion(InBuffer saveDataIds);
Result DeleteSaveDataFileSystemBySaveDataSpaceId(SaveDataSpaceId spaceId, ulong saveDataId); Result DeleteSaveDataFileSystemBySaveDataSpaceId(SaveDataSpaceId spaceId, ulong saveDataId);
Result FormatSdCardDryRun(); Result FormatSdCardDryRun();
Result IsExFatSupported(out bool isSupported); Result IsExFatSupported(out bool isSupported);
Result DeleteSaveDataFileSystemBySaveDataAttribute(SaveDataSpaceId spaceId, in SaveDataAttribute attribute); Result DeleteSaveDataFileSystemBySaveDataAttribute(SaveDataSpaceId spaceId, in SaveDataAttribute attribute);
Result OpenGameCardStorage(out IStorage storage, GameCardHandle handle, GameCardPartitionRaw partitionId); Result OpenGameCardStorage(out ReferenceCountedDisposable<IStorageSf> storage, GameCardHandle handle, GameCardPartitionRaw partitionId);
Result OpenGameCardFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, GameCardHandle handle, GameCardPartition partitionId); Result OpenGameCardFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, GameCardHandle handle, GameCardPartition partitionId);
Result ExtendSaveDataFileSystem(SaveDataSpaceId spaceId, ulong saveDataId, long dataSize, long journalSize); Result ExtendSaveDataFileSystem(SaveDataSpaceId spaceId, ulong saveDataId, long dataSize, long journalSize);
Result DeleteCacheStorage(ushort index); Result DeleteCacheStorage(ushort index);
Result GetCacheStorageSize(out long dataSize, out long journalSize, ushort index); Result GetCacheStorageSize(out long dataSize, out long journalSize, ushort index);
Result CreateSaveDataFileSystemWithHashSalt(in SaveDataAttribute attribute, in SaveDataCreationInfo creationInfo, in SaveDataMetaInfo metaInfo, in HashSalt hashSalt); Result CreateSaveDataFileSystemWithHashSalt(in SaveDataAttribute attribute, in SaveDataCreationInfo creationInfo, in SaveDataMetaInfo metaInfo, in HashSalt hashSalt);
Result OpenHostFileSystemWithOption(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, in FspPath path, MountHostOption option);
Result OpenSaveDataFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, SaveDataSpaceId spaceId, in SaveDataAttribute attribute); Result OpenSaveDataFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, SaveDataSpaceId spaceId, in SaveDataAttribute attribute);
Result OpenSaveDataFileSystemBySystemSaveDataId(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, SaveDataSpaceId spaceId, in SaveDataAttribute attribute); Result OpenSaveDataFileSystemBySystemSaveDataId(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, SaveDataSpaceId spaceId, in SaveDataAttribute attribute);
Result OpenReadOnlySaveDataFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, SaveDataSpaceId spaceId, in SaveDataAttribute attribute); Result OpenReadOnlySaveDataFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, SaveDataSpaceId spaceId, in SaveDataAttribute attribute);
@ -62,15 +62,17 @@ namespace LibHac.FsSrv
Result OpenImageDirectoryFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, ImageDirectoryId directoryId); Result OpenImageDirectoryFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, ImageDirectoryId directoryId);
Result OpenContentStorageFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, ContentStorageId storageId); Result OpenContentStorageFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, ContentStorageId storageId);
Result OpenCloudBackupWorkStorageFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, CloudBackupWorkStorageId storageId); Result OpenCloudBackupWorkStorageFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, CloudBackupWorkStorageId storageId);
Result OpenCustomStorageFileSystem(out IFileSystem fileSystem, CustomStorageId storageId); Result OpenCustomStorageFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, CustomStorageId storageId);
Result OpenDataStorageByCurrentProcess(out ReferenceCountedDisposable<IStorageSf> storage); Result OpenDataStorageByCurrentProcess(out ReferenceCountedDisposable<IStorageSf> storage);
Result OpenDataStorageByProgramId(out ReferenceCountedDisposable<IStorageSf> storage, ProgramId programId); Result OpenDataStorageByProgramId(out ReferenceCountedDisposable<IStorageSf> storage, ProgramId programId);
Result OpenDataStorageByDataId(out ReferenceCountedDisposable<IStorageSf> storage, DataId dataId, StorageId storageId); Result OpenDataStorageByDataId(out ReferenceCountedDisposable<IStorageSf> storage, DataId dataId, StorageId storageId);
Result OpenPatchDataStorageByCurrentProcess(out ReferenceCountedDisposable<IStorageSf> storage); Result OpenPatchDataStorageByCurrentProcess(out ReferenceCountedDisposable<IStorageSf> storage);
Result OpenDataFileSystemWithProgramIndex(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, byte programIndex); Result OpenDataFileSystemWithProgramIndex(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, byte programIndex);
Result OpenDataStorageWithProgramIndex(out ReferenceCountedDisposable<IStorageSf> storage, byte programIndex); Result OpenDataStorageWithProgramIndex(out ReferenceCountedDisposable<IStorageSf> storage, byte programIndex);
Result OpenDeviceOperator(out IDeviceOperator deviceOperator); Result OpenDeviceOperator(out ReferenceCountedDisposable<IDeviceOperator> deviceOperator);
Result OpenSdCardDetectionEventNotifier(out ReferenceCountedDisposable<IEventNotifier> eventNotifier);
Result OpenGameCardDetectionEventNotifier(out ReferenceCountedDisposable<IEventNotifier> eventNotifier);
Result OpenSystemDataUpdateEventNotifier(out ReferenceCountedDisposable<IEventNotifier> eventNotifier); Result OpenSystemDataUpdateEventNotifier(out ReferenceCountedDisposable<IEventNotifier> eventNotifier);
Result NotifySystemDataUpdateEvent(); Result NotifySystemDataUpdateEvent();
@ -96,13 +98,13 @@ namespace LibHac.FsSrv
Result IsSdCardAccessible(out bool isAccessible); Result IsSdCardAccessible(out bool isAccessible);
Result RegisterProgramIndexMapInfo(InBuffer programIndexMapInfoBuffer, int programCount); Result RegisterProgramIndexMapInfo(InBuffer programIndexMapInfoBuffer, int programCount);
Result SetBisRootForHost(BisPartitionId partitionId, ref FsPath path); Result SetBisRootForHost(BisPartitionId partitionId, in FspPath path);
Result SetSaveDataSize(long saveDataSize, long saveDataJournalSize); Result SetSaveDataSize(long saveDataSize, long saveDataJournalSize);
Result SetSaveDataRootPath(in FspPath path); Result SetSaveDataRootPath(in FspPath path);
Result DisableAutoSaveDataCreation(); Result DisableAutoSaveDataCreation();
Result SetGlobalAccessLogMode(GlobalAccessLogMode mode); Result SetGlobalAccessLogMode(GlobalAccessLogMode mode);
Result GetGlobalAccessLogMode(out GlobalAccessLogMode mode); Result GetGlobalAccessLogMode(out GlobalAccessLogMode mode);
Result OutputAccessLogToSdCard(U8Span logString); Result OutputAccessLogToSdCard(InBuffer logString);
Result RegisterUpdatePartition(); Result RegisterUpdatePartition();
Result OpenRegisteredUpdatePartition(out ReferenceCountedDisposable<IFileSystemSf> fileSystem); Result OpenRegisteredUpdatePartition(out ReferenceCountedDisposable<IFileSystemSf> fileSystem);

View file

@ -10,9 +10,21 @@ namespace LibHac.FsSrv.Impl
{ {
private ReferenceCountedDisposable<IStorage> BaseStorage { get; } private ReferenceCountedDisposable<IStorage> BaseStorage { get; }
public StorageInterfaceAdapter(ReferenceCountedDisposable<IStorage> baseStorage) private StorageInterfaceAdapter(ref ReferenceCountedDisposable<IStorage> baseStorage)
{ {
BaseStorage = baseStorage.AddReference(); BaseStorage = Shared.Move(ref baseStorage);
}
public static ReferenceCountedDisposable<IStorageSf> CreateShared(
ref ReferenceCountedDisposable<IStorage> baseStorage)
{
var adapter = new StorageInterfaceAdapter(ref baseStorage);
return new ReferenceCountedDisposable<IStorageSf>(adapter);
}
public void Dispose()
{
BaseStorage?.Dispose();
} }
public Result Read(long offset, Span<byte> destination) public Result Read(long offset, Span<byte> destination)
@ -47,7 +59,7 @@ namespace LibHac.FsSrv.Impl
if (source.Length < 0) if (source.Length < 0)
return ResultFs.InvalidSize.Log(); return ResultFs.InvalidSize.Log();
// Note: Thread priority is temporarily when writing in FS // Note: Thread priority is temporarily increased when writing in FS
return BaseStorage.Target.Write(offset, source); return BaseStorage.Target.Write(offset, source);
} }
@ -93,9 +105,5 @@ namespace LibHac.FsSrv.Impl
return Result.Success; return Result.Success;
} }
public void Dispose()
{
BaseStorage?.Dispose();
}
} }
} }

View file

@ -122,7 +122,7 @@ namespace LibHac.FsSrv.Impl
} }
public static Result CreateSubDirectoryFileSystem(out ReferenceCountedDisposable<IFileSystem> subDirFileSystem, public static Result CreateSubDirectoryFileSystem(out ReferenceCountedDisposable<IFileSystem> subDirFileSystem,
ReferenceCountedDisposable<IFileSystem> baseFileSystem, U8Span subPath, bool preserveUnc = false) ref ReferenceCountedDisposable<IFileSystem> baseFileSystem, U8Span subPath, bool preserveUnc = false)
{ {
subDirFileSystem = default; subDirFileSystem = default;
@ -132,7 +132,7 @@ namespace LibHac.FsSrv.Impl
dir.Dispose(); dir.Dispose();
var fs = new SubdirectoryFileSystem(baseFileSystem, preserveUnc); var fs = new SubdirectoryFileSystem(ref baseFileSystem, preserveUnc);
using (var subDirFs = new ReferenceCountedDisposable<SubdirectoryFileSystem>(fs)) using (var subDirFs = new ReferenceCountedDisposable<SubdirectoryFileSystem>(fs))
{ {
rc = subDirFs.Target.Initialize(subPath); rc = subDirFs.Target.Initialize(subPath);
@ -144,7 +144,7 @@ namespace LibHac.FsSrv.Impl
} }
public static Result WrapSubDirectory(out ReferenceCountedDisposable<IFileSystem> fileSystem, public static Result WrapSubDirectory(out ReferenceCountedDisposable<IFileSystem> fileSystem,
ReferenceCountedDisposable<IFileSystem> baseFileSystem, U8Span path, bool createIfMissing) ref ReferenceCountedDisposable<IFileSystem> baseFileSystem, U8Span path, bool createIfMissing)
{ {
fileSystem = default; fileSystem = default;
@ -159,7 +159,7 @@ namespace LibHac.FsSrv.Impl
Result rc = EnsureDirectory(baseFileSystem.Target, path); Result rc = EnsureDirectory(baseFileSystem.Target, path);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
return CreateSubDirectoryFileSystem(out fileSystem, baseFileSystem, path); return CreateSubDirectoryFileSystem(out fileSystem, ref baseFileSystem, path);
} }
private static ReadOnlySpan<byte> FileSystemRootPath => // / private static ReadOnlySpan<byte> FileSystemRootPath => // /

View file

@ -100,17 +100,29 @@ namespace LibHac.FsSrv
if (type == FileSystemProxyType.Manual) if (type == FileSystemProxyType.Manual)
{ {
rc = TryOpenCaseSensitiveContentDirectory( ReferenceCountedDisposable<IFileSystem> manualFileSystem = null;
out ReferenceCountedDisposable<IFileSystem> manualFileSystem, baseFileSystem, currentPath); ReferenceCountedDisposable<IFileSystem> readOnlyFileSystem = null;
if (rc.IsFailure()) return rc; try
{
rc = TryOpenCaseSensitiveContentDirectory(out manualFileSystem, ref baseFileSystem,
currentPath);
if (rc.IsFailure()) return rc;
var readOnlyFs = new ReadOnlyFileSystem(manualFileSystem); readOnlyFileSystem = ReadOnlyFileSystem.CreateShared(ref manualFileSystem);
fileSystem = new ReferenceCountedDisposable<IFileSystem>(readOnlyFs); if (readOnlyFileSystem?.Target is null)
return ResultFs.AllocationFailureInAllocateShared.Log();
return Result.Success; Shared.Move(out fileSystem, ref readOnlyFileSystem);
return Result.Success;
}
finally
{
manualFileSystem?.Dispose();
readOnlyFileSystem?.Dispose();
}
} }
return TryOpenContentDirectory(currentPath, out fileSystem, baseFileSystem, type, true); return TryOpenContentDirectory(currentPath, out fileSystem, ref baseFileSystem, type, true);
} }
rc = TryOpenNsp(ref currentPath, out ReferenceCountedDisposable<IFileSystem> nspFileSystem, baseFileSystem); rc = TryOpenNsp(ref currentPath, out ReferenceCountedDisposable<IFileSystem> nspFileSystem, baseFileSystem);
@ -371,20 +383,27 @@ namespace LibHac.FsSrv
private Result TryOpenContentDirectory(U8Span path, private Result TryOpenContentDirectory(U8Span path,
out ReferenceCountedDisposable<IFileSystem> contentFileSystem, out ReferenceCountedDisposable<IFileSystem> contentFileSystem,
ReferenceCountedDisposable<IFileSystem> baseFileSystem, FileSystemProxyType fsType, bool preserveUnc) ref ReferenceCountedDisposable<IFileSystem> baseFileSystem, FileSystemProxyType fsType, bool preserveUnc)
{ {
contentFileSystem = default; contentFileSystem = default;
Result rc = _config.SubDirectoryFsCreator.Create(out ReferenceCountedDisposable<IFileSystem> subDirFs, ReferenceCountedDisposable<IFileSystem> subDirFs = null;
baseFileSystem, path, preserveUnc); try
if (rc.IsFailure()) return rc; {
Result rc = _config.SubDirectoryFsCreator.Create(out subDirFs, ref baseFileSystem, path, preserveUnc);
if (rc.IsFailure()) return rc;
return OpenSubDirectoryForFsType(out contentFileSystem, subDirFs, fsType); return OpenSubDirectoryForFsType(out contentFileSystem, ref subDirFs, fsType);
}
finally
{
subDirFs?.Dispose();
}
} }
private Result TryOpenCaseSensitiveContentDirectory( private Result TryOpenCaseSensitiveContentDirectory(
out ReferenceCountedDisposable<IFileSystem> contentFileSystem, out ReferenceCountedDisposable<IFileSystem> contentFileSystem,
ReferenceCountedDisposable<IFileSystem> baseFileSystem, U8Span path) ref ReferenceCountedDisposable<IFileSystem> baseFileSystem, U8Span path)
{ {
contentFileSystem = default; contentFileSystem = default;
Unsafe.SkipInit(out FsPath fullPath); Unsafe.SkipInit(out FsPath fullPath);
@ -408,11 +427,11 @@ namespace LibHac.FsSrv
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
} }
return _config.SubDirectoryFsCreator.Create(out contentFileSystem, baseFileSystem, fullPath); return _config.SubDirectoryFsCreator.Create(out contentFileSystem, ref baseFileSystem, fullPath);
} }
private Result OpenSubDirectoryForFsType(out ReferenceCountedDisposable<IFileSystem> fileSystem, private Result OpenSubDirectoryForFsType(out ReferenceCountedDisposable<IFileSystem> fileSystem,
ReferenceCountedDisposable<IFileSystem> baseFileSystem, FileSystemProxyType fsType) ref ReferenceCountedDisposable<IFileSystem> baseFileSystem, FileSystemProxyType fsType)
{ {
fileSystem = default; fileSystem = default;
ReadOnlySpan<byte> dirName; ReadOnlySpan<byte> dirName;
@ -442,19 +461,26 @@ namespace LibHac.FsSrv
return ResultFs.InvalidArgument.Log(); return ResultFs.InvalidArgument.Log();
} }
// Open the subdirectory filesystem ReferenceCountedDisposable<IFileSystem> subDirFs = null;
Result rc = _config.SubDirectoryFsCreator.Create(out ReferenceCountedDisposable<IFileSystem> subDirFs, try
baseFileSystem, new U8Span(dirName));
if (rc.IsFailure()) return rc;
if (fsType == FileSystemProxyType.Code)
{ {
rc = _config.StorageOnNcaCreator.VerifyAcidSignature(subDirFs.Target, null); // Open the subdirectory filesystem
Result rc = _config.SubDirectoryFsCreator.Create(out subDirFs, ref baseFileSystem, new U8Span(dirName));
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
}
fileSystem = subDirFs; if (fsType == FileSystemProxyType.Code)
return Result.Success; {
rc = _config.StorageOnNcaCreator.VerifyAcidSignature(subDirFs.Target, null);
if (rc.IsFailure()) return rc;
}
Shared.Move(out fileSystem, ref subDirFs);
return Result.Success;
}
finally
{
subDirFs?.Dispose();
}
} }
private Result TryOpenNsp(ref U8Span path, out ReferenceCountedDisposable<IFileSystem> fileSystem, private Result TryOpenNsp(ref U8Span path, out ReferenceCountedDisposable<IFileSystem> fileSystem,
@ -659,29 +685,37 @@ namespace LibHac.FsSrv
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
} }
rc = _config.TargetManagerFsCreator.Create(out ReferenceCountedDisposable<IFileSystem> hostFs, ReferenceCountedDisposable<IFileSystem> hostFs = null;
openCaseSensitive); ReferenceCountedDisposable<IFileSystem> subDirFs = null;
if (rc.IsFailure()) return rc; try
if (path.IsEmpty())
{ {
ReadOnlySpan<byte> rootHostPath = new[] { (byte)'C', (byte)':', (byte)'/' }; rc = _config.TargetManagerFsCreator.Create(out hostFs, openCaseSensitive);
rc = hostFs.Target.GetEntryType(out _, new U8Span(rootHostPath)); if (rc.IsFailure()) return rc;
// Nintendo ignores all results other than this one if (path.IsEmpty())
if (ResultFs.TargetNotFound.Includes(rc)) {
return rc; ReadOnlySpan<byte> rootHostPath = new[] { (byte)'C', (byte)':', (byte)'/' };
rc = hostFs.Target.GetEntryType(out _, new U8Span(rootHostPath));
fileSystem = hostFs; // Nintendo ignores all results other than this one
if (ResultFs.TargetNotFound.Includes(rc))
return rc;
Shared.Move(out fileSystem, ref hostFs);
return Result.Success;
}
rc = _config.SubDirectoryFsCreator.Create(out subDirFs, ref hostFs, path, preserveUnc: true);
if (rc.IsFailure()) return rc;
Shared.Move(out fileSystem, ref subDirFs);
return Result.Success; return Result.Success;
} }
finally
rc = _config.SubDirectoryFsCreator.Create(out ReferenceCountedDisposable<IFileSystem> subDirFs, hostFs, {
path, preserveUnc: true); hostFs?.Dispose();
if (rc.IsFailure()) return rc; subDirFs?.Dispose();
}
fileSystem = subDirFs;
return Result.Success;
} }
public Result OpenFileSystemWithPatch(out ReferenceCountedDisposable<IFileSystem> fileSystem, public Result OpenFileSystemWithPatch(out ReferenceCountedDisposable<IFileSystem> fileSystem,
@ -746,7 +780,7 @@ namespace LibHac.FsSrv
rc = Utility.EnsureDirectory(baseFileSystem.Target, new U8Span(contentStoragePath)); rc = Utility.EnsureDirectory(baseFileSystem.Target, new U8Span(contentStoragePath));
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
rc = _config.SubDirectoryFsCreator.Create(out subDirFileSystem, baseFileSystem, rc = _config.SubDirectoryFsCreator.Create(out subDirFileSystem, ref baseFileSystem,
new U8Span(contentStoragePath)); new U8Span(contentStoragePath));
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
@ -754,8 +788,7 @@ namespace LibHac.FsSrv
if (contentStorageId != ContentStorageId.SdCard) if (contentStorageId != ContentStorageId.SdCard)
{ {
// Move the shared reference to the out variable // Move the shared reference to the out variable
fileSystem = subDirFileSystem; Shared.Move(out fileSystem, ref subDirFileSystem);
subDirFileSystem = null;
return Result.Success; return Result.Success;
} }
@ -765,8 +798,7 @@ namespace LibHac.FsSrv
EncryptedFsKeyId.Content, in _encryptionSeed); EncryptedFsKeyId.Content, in _encryptionSeed);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
fileSystem = encryptedFileSystem; Shared.Move(out fileSystem, ref encryptedFileSystem);
encryptedFileSystem = null;
return Result.Success; return Result.Success;
} }

View file

@ -437,7 +437,7 @@ namespace LibHac.FsSrv
rc = _config.TargetManagerFsCreator.Create(out tmFs, isTargetFsCaseSensitive); rc = _config.TargetManagerFsCreator.Create(out tmFs, isTargetFsCaseSensitive);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
return Utility.CreateSubDirectoryFileSystem(out fileSystem, tmFs, new U8Span(path.Str), true); return Utility.CreateSubDirectoryFileSystem(out fileSystem, ref tmFs, new U8Span(path.Str), true);
} }
finally finally
{ {
@ -482,14 +482,14 @@ namespace LibHac.FsSrv
rc = _config.BaseFsService.OpenBisFileSystem(out tempFs, U8Span.Empty, BisPartitionId.System, true); rc = _config.BaseFsService.OpenBisFileSystem(out tempFs, U8Span.Empty, BisPartitionId.System, true);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
return Utility.WrapSubDirectory(out fileSystem, tempFs, basePath, createIfMissing); return Utility.WrapSubDirectory(out fileSystem, ref tempFs, basePath, createIfMissing);
case SaveDataSpaceId.User: case SaveDataSpaceId.User:
case SaveDataSpaceId.Temporary: case SaveDataSpaceId.Temporary:
rc = _config.BaseFsService.OpenBisFileSystem(out tempFs, U8Span.Empty, BisPartitionId.User, true); rc = _config.BaseFsService.OpenBisFileSystem(out tempFs, U8Span.Empty, BisPartitionId.User, true);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
return Utility.WrapSubDirectory(out fileSystem, tempFs, basePath, createIfMissing); return Utility.WrapSubDirectory(out fileSystem, ref tempFs, basePath, createIfMissing);
case SaveDataSpaceId.SdSystem: case SaveDataSpaceId.SdSystem:
case SaveDataSpaceId.SdCache: case SaveDataSpaceId.SdCache:
@ -503,7 +503,7 @@ namespace LibHac.FsSrv
.Append((byte)'/') .Append((byte)'/')
.Append(CommonPaths.SdCardNintendoRootDirectoryName); .Append(CommonPaths.SdCardNintendoRootDirectoryName);
rc = Utility.WrapSubDirectory(out tempSubFs, tempFs, path, createIfMissing); rc = Utility.WrapSubDirectory(out tempSubFs, ref tempFs, path, createIfMissing);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
return _config.EncryptedFsCreator.Create(out fileSystem, tempSubFs, EncryptedFsKeyId.Save, return _config.EncryptedFsCreator.Create(out fileSystem, tempSubFs, EncryptedFsKeyId.Save,
@ -513,13 +513,13 @@ namespace LibHac.FsSrv
rc = _config.BaseFsService.OpenBisFileSystem(out tempFs, U8Span.Empty, BisPartitionId.SystemProperPartition, true); rc = _config.BaseFsService.OpenBisFileSystem(out tempFs, U8Span.Empty, BisPartitionId.SystemProperPartition, true);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
return Utility.WrapSubDirectory(out fileSystem, tempFs, basePath, createIfMissing); return Utility.WrapSubDirectory(out fileSystem, ref tempFs, basePath, createIfMissing);
case SaveDataSpaceId.SafeMode: case SaveDataSpaceId.SafeMode:
rc = _config.BaseFsService.OpenBisFileSystem(out tempFs, U8Span.Empty, BisPartitionId.SafeMode, true); rc = _config.BaseFsService.OpenBisFileSystem(out tempFs, U8Span.Empty, BisPartitionId.SafeMode, true);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
return Utility.WrapSubDirectory(out fileSystem, tempFs, basePath, createIfMissing); return Utility.WrapSubDirectory(out fileSystem, ref tempFs, basePath, createIfMissing);
default: default:
return ResultFs.InvalidArgument.Log(); return ResultFs.InvalidArgument.Log();

View file

@ -36,9 +36,9 @@ namespace LibHac.FsSystem
PreserveUnc = preserveUnc; PreserveUnc = preserveUnc;
} }
public SubdirectoryFileSystem(ReferenceCountedDisposable<IFileSystem> baseFileSystem, bool preserveUnc = false) public SubdirectoryFileSystem(ref ReferenceCountedDisposable<IFileSystem> baseFileSystem, bool preserveUnc = false)
{ {
BaseFileSystemShared = baseFileSystem.AddReference(); BaseFileSystemShared = Shared.Move(ref baseFileSystem);
BaseFileSystem = BaseFileSystemShared.Target; BaseFileSystem = BaseFileSystemShared.Target;
PreserveUnc = preserveUnc; PreserveUnc = preserveUnc;
} }