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.Fs.Accessors;
using LibHac.FsSrv;
using LibHac.Sf;
namespace LibHac.Fs
{
@ -187,7 +188,7 @@ namespace LibHac.Fs
string logString = AccessLogHelpers.BuildDefaultLogLine(result, startTime, endTime, handleId, message, caller);
IFileSystemProxy fsProxy = GetFileSystemProxyServiceObject();
fsProxy.OutputAccessLogToSdCard(logString.ToU8Span());
fsProxy.OutputAccessLogToSdCard(new InBuffer(logString.ToU8Span())).IgnoreResult();
}
}

View file

@ -1,5 +1,6 @@
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using LibHac.Common;
using LibHac.Fs.Impl;
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
public static Result SetBisRootForHost(this FileSystemClient fs, BisPartitionId partitionId, U8Span rootPath)
{
FsPath sfPath;
unsafe { _ = &sfPath; } // workaround for CS0165
Unsafe.SkipInit(out FsPath path);
int pathLen = StringUtils.GetLength(rootPath, PathTools.MaxPathLength + 1);
if (pathLen > PathTools.MaxPathLength)
@ -150,18 +150,20 @@ namespace LibHac.Fs.Shim
? StringTraits.NullTerminator
: StringTraits.DirectorySeparator;
var sb = new U8StringBuilder(sfPath.Str);
var sb = new U8StringBuilder(path.Str);
Result rc = sb.Append(rootPath).Append(endingSeparator).ToSfPath();
if (rc.IsFailure()) return rc;
}
else
{
sfPath.Str[0] = StringTraits.NullTerminator;
path.Str[0] = StringTraits.NullTerminator;
}
FspPath.FromSpan(out FspPath sfPath, path.Str);
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)

View file

@ -1,7 +1,8 @@
using System;
using LibHac.Common;
using LibHac.Fs.Fsa;
using LibHac.Fs.Impl;
using LibHac.FsSrv;
using LibHac.FsSrv.Sf;
namespace LibHac.Fs.Shim
{
@ -12,12 +13,22 @@ namespace LibHac.Fs.Shim
Result rc = MountHelpers.CheckMountName(mountName);
if (rc.IsFailure()) return rc;
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;
return fs.Register(mountName, customFs);
var adapter = new FileSystemServiceObjectAdapter(customFs);
return fs.Register(mountName, adapter);
}
finally
{
customFs?.Dispose();
}
}
public static string GetCustomStorageDirectoryName(CustomStorageId storageId)

View file

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

View file

@ -3,7 +3,9 @@ using System.Diagnostics;
using System.Runtime.CompilerServices;
using LibHac.Common;
using LibHac.Fs.Fsa;
using LibHac.Fs.Impl;
using LibHac.FsSrv;
using LibHac.FsSrv.Sf;
using LibHac.FsSystem;
using LibHac.Util;
using static LibHac.Fs.CommonPaths;
@ -76,12 +78,11 @@ namespace LibHac.Fs.Shim
public static Result MountHostRoot(this FileSystemClient fs)
{
IFileSystem hostFileSystem = default;
var path = new FsPath();
path.Str[0] = 0;
FspPath.CreateEmpty(out FspPath path);
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,
new HostRootCommonMountNameGenerator());
@ -110,13 +111,12 @@ namespace LibHac.Fs.Shim
public static Result MountHostRoot(this FileSystemClient fs, MountHostOption option)
{
IFileSystem hostFileSystem = default;
var path = new FsPath();
path.Str[0] = 0;
FspPath.CreateEmpty(out FspPath path);
string LogMessageGenerator() =>
$", 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,
new HostRootCommonMountNameGenerator());
@ -318,8 +318,7 @@ namespace LibHac.Fs.Shim
if (pathLength + 1 > PathTools.MaxPathLength)
return ResultFs.TooLongPath.Log();
FsPath fullPath;
unsafe { _ = &fullPath; } // workaround for CS0165
Unsafe.SkipInit(out FsPath fullPath);
var sb = new U8StringBuilder(fullPath.Str);
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>
@ -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="option">Options for opening the host file system.</param>
/// <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;
IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();
IFileSystem hostFs;
ReferenceCountedDisposable<IFileSystemSf> hostFs = null;
try
{
if (option == MountHostOption.None)
{
Result rc = fsProxy.OpenHostFileSystem(out hostFs, ref path);
Result rc = fsProxy.OpenHostFileSystem(out hostFs, in path);
if (rc.IsFailure()) return rc;
}
else
{
Result rc = fsProxy.OpenHostFileSystemWithOption(out hostFs, ref path, option);
Result rc = fsProxy.OpenHostFileSystemWithOption(out hostFs, in path, option);
if (rc.IsFailure()) return rc;
}
fileSystem = hostFs;
fileSystem = new FileSystemServiceObjectAdapter(hostFs);
return Result.Success;
}
finally
{
hostFs?.Dispose();
}
}
}
}

View file

@ -212,7 +212,7 @@ namespace LibHac.Fs.Shim
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}");
}

View file

@ -55,17 +55,25 @@ namespace LibHac.Fs.Shim
}
public static bool IsSdCardInserted(this FileSystemClient fs)
{
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");
rc = deviceOperator.IsSdCardInserted(out bool isInserted);
rc = deviceOperator.Target.IsSdCardInserted(out bool isInserted);
if (rc.IsFailure()) throw new HorizonResultException(rc, "Abort");
return isInserted;
}
finally
{
deviceOperator?.Dispose();
}
}
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();
ReferenceCountedDisposable<IFileSystem> partitionFileSystem = null;
ReferenceCountedDisposable<IFileSystem> sharedRootFs = null;
try
{
// Todo: Store shared file systems
using var sharedRootFs = new ReferenceCountedDisposable<IFileSystem>(Config.RootFileSystem);
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;
@ -125,11 +125,12 @@ namespace LibHac.FsSrv.Creators
return Result.Success;
}
return Utility.CreateSubDirectoryFileSystem(out fileSystem, partitionFileSystem, rootPath);
return Utility.CreateSubDirectoryFileSystem(out fileSystem, ref partitionFileSystem, rootPath);
}
finally
{
partitionFileSystem?.Dispose();
sharedRootFs?.Dispose();
}
}

View file

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

View file

@ -6,31 +6,14 @@ namespace LibHac.FsSrv.Creators
{
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);
}
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;
return Create(out subDirFileSystem, ref baseFileSystem, path, false);
}
public Result Create(out ReferenceCountedDisposable<IFileSystem> subDirFileSystem,
ReferenceCountedDisposable<IFileSystem> baseFileSystem, U8Span path)
{
return Create(out subDirFileSystem, baseFileSystem, path, false);
}
public Result Create(out ReferenceCountedDisposable<IFileSystem> subDirFileSystem,
ReferenceCountedDisposable<IFileSystem> baseFileSystem, U8Span path, bool preserveUnc)
ref ReferenceCountedDisposable<IFileSystem> baseFileSystem, U8Span path, bool preserveUnc)
{
subDirFileSystem = default;
@ -39,7 +22,7 @@ namespace LibHac.FsSrv.Creators
if (rc.IsFailure()) return rc;
// Initialize the SubdirectoryFileSystem
var subDir = new SubdirectoryFileSystem(baseFileSystem, preserveUnc);
var subDir = new SubdirectoryFileSystem(ref baseFileSystem, preserveUnc);
using var subDirShared = new ReferenceCountedDisposable<SubdirectoryFileSystem>(subDir);
rc = subDirShared.Target.Initialize(path);

View file

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

View file

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

View file

@ -254,8 +254,8 @@ namespace LibHac.FsSrv
in hashSalt);
}
public Result CreateSaveDataFileSystemBySystemSaveDataId(ref SaveDataAttribute attribute,
ref SaveDataCreationInfo creationInfo)
public Result CreateSaveDataFileSystemBySystemSaveDataId(in SaveDataAttribute attribute,
in SaveDataCreationInfo creationInfo)
{
Result rc = GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService);
if (rc.IsFailure()) return rc;
@ -399,17 +399,44 @@ namespace LibHac.FsSrv
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);
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)
@ -432,20 +459,31 @@ namespace LibHac.FsSrv
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
return FsProxyCore.OpenGameCardStorage(out storage, handle, partitionId);
}
public Result OpenDeviceOperator(out IDeviceOperator deviceOperator)
public Result OpenDeviceOperator(out ReferenceCountedDisposable<IDeviceOperator> deviceOperator)
{
// Missing permission check
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)
{
Result rc = GetNcaFileSystemService(out NcaFileSystemService ncaFsService);
@ -659,11 +697,37 @@ namespace LibHac.FsSrv
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,
@ -766,7 +830,7 @@ namespace LibHac.FsSrv
.RegisterProgramIndexMapInfo(programIndexMapInfoBuffer, programCount);
}
public Result SetBisRootForHost(BisPartitionId partitionId, ref FsPath path)
public Result SetBisRootForHost(BisPartitionId partitionId, in FspPath path)
{
throw new NotImplementedException();
}
@ -839,7 +903,7 @@ namespace LibHac.FsSrv
return GetProgramIndexRegistryService().GetProgramIndex(out programIndex, out programCount);
}
public Result OutputAccessLogToSdCard(U8Span logString)
public Result OutputAccessLogToSdCard(InBuffer logString)
{
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 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 OpenBisStorage(out ReferenceCountedDisposable<IStorageSf> storage, BisPartitionId partitionId);
Result InvalidateBisCache();
Result OpenHostFileSystemWithOption(out IFileSystem fileSystem, ref FsPath path, MountHostOption option);
Result OpenHostFileSystem(out IFileSystem fileSystem, ref FsPath path);
Result OpenHostFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, in FspPath path);
Result OpenSdCardFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem);
Result FormatSdCardFileSystem();
Result DeleteSaveDataFileSystem(ulong saveDataId);
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 DeleteSaveDataFileSystemBySaveDataSpaceId(SaveDataSpaceId spaceId, ulong saveDataId);
Result FormatSdCardDryRun();
Result IsExFatSupported(out bool isSupported);
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 ExtendSaveDataFileSystem(SaveDataSpaceId spaceId, ulong saveDataId, long dataSize, long journalSize);
Result DeleteCacheStorage(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 OpenHostFileSystemWithOption(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, in FspPath path, MountHostOption option);
Result OpenSaveDataFileSystem(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);
@ -62,15 +62,17 @@ namespace LibHac.FsSrv
Result OpenImageDirectoryFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, ImageDirectoryId directoryId);
Result OpenContentStorageFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, ContentStorageId 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 OpenDataStorageByProgramId(out ReferenceCountedDisposable<IStorageSf> storage, ProgramId programId);
Result OpenDataStorageByDataId(out ReferenceCountedDisposable<IStorageSf> storage, DataId dataId, StorageId storageId);
Result OpenPatchDataStorageByCurrentProcess(out ReferenceCountedDisposable<IStorageSf> storage);
Result OpenDataFileSystemWithProgramIndex(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, 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 NotifySystemDataUpdateEvent();
@ -96,13 +98,13 @@ namespace LibHac.FsSrv
Result IsSdCardAccessible(out bool isAccessible);
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 SetSaveDataRootPath(in FspPath path);
Result DisableAutoSaveDataCreation();
Result SetGlobalAccessLogMode(GlobalAccessLogMode mode);
Result GetGlobalAccessLogMode(out GlobalAccessLogMode mode);
Result OutputAccessLogToSdCard(U8Span logString);
Result OutputAccessLogToSdCard(InBuffer logString);
Result RegisterUpdatePartition();
Result OpenRegisteredUpdatePartition(out ReferenceCountedDisposable<IFileSystemSf> fileSystem);

View file

@ -10,9 +10,21 @@ namespace LibHac.FsSrv.Impl
{
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)
@ -47,7 +59,7 @@ namespace LibHac.FsSrv.Impl
if (source.Length < 0)
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);
}
@ -93,9 +105,5 @@ namespace LibHac.FsSrv.Impl
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,
ReferenceCountedDisposable<IFileSystem> baseFileSystem, U8Span subPath, bool preserveUnc = false)
ref ReferenceCountedDisposable<IFileSystem> baseFileSystem, U8Span subPath, bool preserveUnc = false)
{
subDirFileSystem = default;
@ -132,7 +132,7 @@ namespace LibHac.FsSrv.Impl
dir.Dispose();
var fs = new SubdirectoryFileSystem(baseFileSystem, preserveUnc);
var fs = new SubdirectoryFileSystem(ref baseFileSystem, preserveUnc);
using (var subDirFs = new ReferenceCountedDisposable<SubdirectoryFileSystem>(fs))
{
rc = subDirFs.Target.Initialize(subPath);
@ -144,7 +144,7 @@ namespace LibHac.FsSrv.Impl
}
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;
@ -159,7 +159,7 @@ namespace LibHac.FsSrv.Impl
Result rc = EnsureDirectory(baseFileSystem.Target, path);
if (rc.IsFailure()) return rc;
return CreateSubDirectoryFileSystem(out fileSystem, baseFileSystem, path);
return CreateSubDirectoryFileSystem(out fileSystem, ref baseFileSystem, path);
}
private static ReadOnlySpan<byte> FileSystemRootPath => // /

View file

@ -100,17 +100,29 @@ namespace LibHac.FsSrv
if (type == FileSystemProxyType.Manual)
{
rc = TryOpenCaseSensitiveContentDirectory(
out ReferenceCountedDisposable<IFileSystem> manualFileSystem, baseFileSystem, currentPath);
ReferenceCountedDisposable<IFileSystem> manualFileSystem = null;
ReferenceCountedDisposable<IFileSystem> readOnlyFileSystem = null;
try
{
rc = TryOpenCaseSensitiveContentDirectory(out manualFileSystem, ref baseFileSystem,
currentPath);
if (rc.IsFailure()) return rc;
var readOnlyFs = new ReadOnlyFileSystem(manualFileSystem);
fileSystem = new ReferenceCountedDisposable<IFileSystem>(readOnlyFs);
readOnlyFileSystem = ReadOnlyFileSystem.CreateShared(ref manualFileSystem);
if (readOnlyFileSystem?.Target is null)
return ResultFs.AllocationFailureInAllocateShared.Log();
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);
@ -371,20 +383,27 @@ namespace LibHac.FsSrv
private Result TryOpenContentDirectory(U8Span path,
out ReferenceCountedDisposable<IFileSystem> contentFileSystem,
ReferenceCountedDisposable<IFileSystem> baseFileSystem, FileSystemProxyType fsType, bool preserveUnc)
ref ReferenceCountedDisposable<IFileSystem> baseFileSystem, FileSystemProxyType fsType, bool preserveUnc)
{
contentFileSystem = default;
Result rc = _config.SubDirectoryFsCreator.Create(out ReferenceCountedDisposable<IFileSystem> subDirFs,
baseFileSystem, path, preserveUnc);
ReferenceCountedDisposable<IFileSystem> subDirFs = null;
try
{
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(
out ReferenceCountedDisposable<IFileSystem> contentFileSystem,
ReferenceCountedDisposable<IFileSystem> baseFileSystem, U8Span path)
ref ReferenceCountedDisposable<IFileSystem> baseFileSystem, U8Span path)
{
contentFileSystem = default;
Unsafe.SkipInit(out FsPath fullPath);
@ -408,11 +427,11 @@ namespace LibHac.FsSrv
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,
ReferenceCountedDisposable<IFileSystem> baseFileSystem, FileSystemProxyType fsType)
ref ReferenceCountedDisposable<IFileSystem> baseFileSystem, FileSystemProxyType fsType)
{
fileSystem = default;
ReadOnlySpan<byte> dirName;
@ -442,9 +461,11 @@ namespace LibHac.FsSrv
return ResultFs.InvalidArgument.Log();
}
ReferenceCountedDisposable<IFileSystem> subDirFs = null;
try
{
// Open the subdirectory filesystem
Result rc = _config.SubDirectoryFsCreator.Create(out ReferenceCountedDisposable<IFileSystem> subDirFs,
baseFileSystem, new U8Span(dirName));
Result rc = _config.SubDirectoryFsCreator.Create(out subDirFs, ref baseFileSystem, new U8Span(dirName));
if (rc.IsFailure()) return rc;
if (fsType == FileSystemProxyType.Code)
@ -453,9 +474,14 @@ namespace LibHac.FsSrv
if (rc.IsFailure()) return rc;
}
fileSystem = subDirFs;
Shared.Move(out fileSystem, ref subDirFs);
return Result.Success;
}
finally
{
subDirFs?.Dispose();
}
}
private Result TryOpenNsp(ref U8Span path, out ReferenceCountedDisposable<IFileSystem> fileSystem,
ReferenceCountedDisposable<IFileSystem> baseFileSystem)
@ -659,8 +685,11 @@ namespace LibHac.FsSrv
if (rc.IsFailure()) return rc;
}
rc = _config.TargetManagerFsCreator.Create(out ReferenceCountedDisposable<IFileSystem> hostFs,
openCaseSensitive);
ReferenceCountedDisposable<IFileSystem> hostFs = null;
ReferenceCountedDisposable<IFileSystem> subDirFs = null;
try
{
rc = _config.TargetManagerFsCreator.Create(out hostFs, openCaseSensitive);
if (rc.IsFailure()) return rc;
if (path.IsEmpty())
@ -672,17 +701,22 @@ namespace LibHac.FsSrv
if (ResultFs.TargetNotFound.Includes(rc))
return rc;
fileSystem = hostFs;
Shared.Move(out fileSystem, ref hostFs);
return Result.Success;
}
rc = _config.SubDirectoryFsCreator.Create(out ReferenceCountedDisposable<IFileSystem> subDirFs, hostFs,
path, preserveUnc: true);
rc = _config.SubDirectoryFsCreator.Create(out subDirFs, ref hostFs, path, preserveUnc: true);
if (rc.IsFailure()) return rc;
fileSystem = subDirFs;
Shared.Move(out fileSystem, ref subDirFs);
return Result.Success;
}
finally
{
hostFs?.Dispose();
subDirFs?.Dispose();
}
}
public Result OpenFileSystemWithPatch(out ReferenceCountedDisposable<IFileSystem> fileSystem,
ProgramId programId, FileSystemProxyType fsType)
@ -746,7 +780,7 @@ namespace LibHac.FsSrv
rc = Utility.EnsureDirectory(baseFileSystem.Target, new U8Span(contentStoragePath));
if (rc.IsFailure()) return rc;
rc = _config.SubDirectoryFsCreator.Create(out subDirFileSystem, baseFileSystem,
rc = _config.SubDirectoryFsCreator.Create(out subDirFileSystem, ref baseFileSystem,
new U8Span(contentStoragePath));
if (rc.IsFailure()) return rc;
@ -754,8 +788,7 @@ namespace LibHac.FsSrv
if (contentStorageId != ContentStorageId.SdCard)
{
// Move the shared reference to the out variable
fileSystem = subDirFileSystem;
subDirFileSystem = null;
Shared.Move(out fileSystem, ref subDirFileSystem);
return Result.Success;
}
@ -765,8 +798,7 @@ namespace LibHac.FsSrv
EncryptedFsKeyId.Content, in _encryptionSeed);
if (rc.IsFailure()) return rc;
fileSystem = encryptedFileSystem;
encryptedFileSystem = null;
Shared.Move(out fileSystem, ref encryptedFileSystem);
return Result.Success;
}

View file

@ -437,7 +437,7 @@ namespace LibHac.FsSrv
rc = _config.TargetManagerFsCreator.Create(out tmFs, isTargetFsCaseSensitive);
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
{
@ -482,14 +482,14 @@ namespace LibHac.FsSrv
rc = _config.BaseFsService.OpenBisFileSystem(out tempFs, U8Span.Empty, BisPartitionId.System, true);
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.Temporary:
rc = _config.BaseFsService.OpenBisFileSystem(out tempFs, U8Span.Empty, BisPartitionId.User, true);
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.SdCache:
@ -503,7 +503,7 @@ namespace LibHac.FsSrv
.Append((byte)'/')
.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;
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);
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:
rc = _config.BaseFsService.OpenBisFileSystem(out tempFs, U8Span.Empty, BisPartitionId.SafeMode, true);
if (rc.IsFailure()) return rc;
return Utility.WrapSubDirectory(out fileSystem, tempFs, basePath, createIfMissing);
return Utility.WrapSubDirectory(out fileSystem, ref tempFs, basePath, createIfMissing);
default:
return ResultFs.InvalidArgument.Log();

View file

@ -36,9 +36,9 @@ namespace LibHac.FsSystem
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;
PreserveUnc = preserveUnc;
}