mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2025-02-09 13:14:46 +01:00
Move code to use SharedRef instead of ReferenceCountedDisposable
This commit is contained in:
parent
c28128c7dd
commit
a23d01e934
@ -1219,10 +1219,11 @@ Module,DescriptionStart,DescriptionEnd,Flags,Namespace,Name,Summary
|
||||
6,8,,,,InvalidHandle,
|
||||
6,1023,,,,InternalError,
|
||||
|
||||
8,1,,,,ResolverNotFound,
|
||||
8,2,,,,ProgramNotFound,
|
||||
8,3,,,,DataNotFound,
|
||||
8,4,,,,UnknownStorageId,
|
||||
8,5,,,,LocationResolverNotFound,
|
||||
8,4,,,,UnknownResolver,
|
||||
8,5,,,,ApplicationNotFound,
|
||||
8,6,,,,HtmlDocumentNotFound,
|
||||
8,7,,,,AddOnContentNotFound,
|
||||
8,8,,,,ControlNotFound,
|
||||
|
|
@ -1,66 +1,74 @@
|
||||
using LibHac.Arp.Impl;
|
||||
using System;
|
||||
using LibHac.Arp.Impl;
|
||||
using LibHac.Common;
|
||||
using LibHac.Ns;
|
||||
|
||||
namespace LibHac.Arp
|
||||
{
|
||||
public class ArpClient
|
||||
public class ArpClient : IDisposable
|
||||
{
|
||||
private HorizonClient HosClient { get; }
|
||||
private IReader Reader { get; set; }
|
||||
private HorizonClient _hosClient;
|
||||
private SharedRef<IReader> _reader;
|
||||
|
||||
private readonly object _readerInitLocker = new object();
|
||||
|
||||
internal ArpClient(HorizonClient horizonClient)
|
||||
{
|
||||
HosClient = horizonClient;
|
||||
_hosClient = horizonClient;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_reader.Destroy();
|
||||
}
|
||||
|
||||
public Result GetApplicationLaunchProperty(out ApplicationLaunchProperty launchProperty, ulong processId)
|
||||
{
|
||||
EnsureReaderInitialized();
|
||||
|
||||
return Reader.GetApplicationLaunchProperty(out launchProperty, processId);
|
||||
return _reader.Get.GetApplicationLaunchProperty(out launchProperty, processId);
|
||||
}
|
||||
|
||||
public Result GetApplicationLaunchProperty(out ApplicationLaunchProperty launchProperty, ApplicationId applicationId)
|
||||
{
|
||||
EnsureReaderInitialized();
|
||||
|
||||
return Reader.GetApplicationLaunchPropertyWithApplicationId(out launchProperty, applicationId);
|
||||
return _reader.Get.GetApplicationLaunchPropertyWithApplicationId(out launchProperty, applicationId);
|
||||
}
|
||||
|
||||
public Result GetApplicationControlProperty(out ApplicationControlProperty controlProperty, ulong processId)
|
||||
{
|
||||
EnsureReaderInitialized();
|
||||
|
||||
return Reader.GetApplicationControlProperty(out controlProperty, processId);
|
||||
return _reader.Get.GetApplicationControlProperty(out controlProperty, processId);
|
||||
}
|
||||
|
||||
public Result GetApplicationControlProperty(out ApplicationControlProperty controlProperty, ApplicationId applicationId)
|
||||
{
|
||||
EnsureReaderInitialized();
|
||||
|
||||
return Reader.GetApplicationControlPropertyWithApplicationId(out controlProperty, applicationId);
|
||||
return _reader.Get.GetApplicationControlPropertyWithApplicationId(out controlProperty, applicationId);
|
||||
}
|
||||
|
||||
private void EnsureReaderInitialized()
|
||||
{
|
||||
if (Reader != null)
|
||||
if (_reader.HasValue)
|
||||
return;
|
||||
|
||||
lock (_readerInitLocker)
|
||||
{
|
||||
if (Reader != null)
|
||||
if (_reader.HasValue)
|
||||
return;
|
||||
|
||||
Result rc = HosClient.Sm.GetService(out IReader reader, "arp:r");
|
||||
using var reader = new SharedRef<IReader>();
|
||||
Result rc = _hosClient.Sm.GetService(ref reader.Ref(), "arp:r");
|
||||
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
throw new HorizonResultException(rc, "Failed to initialize arp reader.");
|
||||
}
|
||||
|
||||
Reader = reader;
|
||||
_reader.SetByMove(ref reader.Ref());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
using LibHac.Ns;
|
||||
using System;
|
||||
using LibHac.Ns;
|
||||
|
||||
namespace LibHac.Arp.Impl
|
||||
{
|
||||
public interface IReader
|
||||
public interface IReader : IDisposable
|
||||
{
|
||||
Result GetApplicationLaunchProperty(out ApplicationLaunchProperty launchProperty, ulong processId);
|
||||
Result GetApplicationLaunchPropertyWithApplicationId(out ApplicationLaunchProperty launchProperty, ApplicationId applicationId);
|
||||
|
@ -2,6 +2,7 @@
|
||||
using LibHac.Bcat.Impl.Ipc;
|
||||
using LibHac.Bcat.Impl.Service;
|
||||
using LibHac.Bcat.Impl.Service.Core;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
|
||||
namespace LibHac.Bcat
|
||||
@ -11,7 +12,7 @@ namespace LibHac.Bcat
|
||||
private const int ServiceTypeCount = 4;
|
||||
|
||||
internal HorizonClient Hos { get; }
|
||||
private ServiceCreator[] ServiceCreators { get; } = new ServiceCreator[ServiceTypeCount];
|
||||
private SharedRef<ServiceCreator>[] _serviceCreators;
|
||||
|
||||
private readonly object _bcatServiceInitLocker = new object();
|
||||
private readonly object _storageManagerInitLocker = new object();
|
||||
@ -21,6 +22,7 @@ namespace LibHac.Bcat
|
||||
public BcatServer(HorizonClient horizonClient)
|
||||
{
|
||||
Hos = horizonClient;
|
||||
_serviceCreators = new SharedRef<ServiceCreator>[ServiceTypeCount];
|
||||
|
||||
InitBcatService(BcatServiceType.BcatU, "bcat:u", AccessControl.MountOwnDeliveryCacheStorage);
|
||||
InitBcatService(BcatServiceType.BcatS, "bcat:s", AccessControl.MountOthersDeliveryCacheStorage);
|
||||
@ -32,9 +34,9 @@ namespace LibHac.Bcat
|
||||
{
|
||||
InitServiceCreator(type, name, accessControl);
|
||||
|
||||
IServiceCreator service = GetServiceCreator(type);
|
||||
using SharedRef<IServiceCreator> service = GetServiceCreator(type);
|
||||
|
||||
Result rc = Hos.Sm.RegisterService(new BcatServiceObject(service), name);
|
||||
Result rc = Hos.Sm.RegisterService(new BcatServiceObject(ref service.Ref()), name);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
throw new HorizonResultException(rc, "Abort");
|
||||
@ -47,15 +49,18 @@ namespace LibHac.Bcat
|
||||
{
|
||||
Debug.Assert((uint)type < ServiceTypeCount);
|
||||
|
||||
ServiceCreators[(int)type] = new ServiceCreator(this, name, accessControl);
|
||||
_serviceCreators[(int)type].Reset(new ServiceCreator(this, name, accessControl));
|
||||
}
|
||||
}
|
||||
|
||||
private IServiceCreator GetServiceCreator(BcatServiceType type)
|
||||
private SharedRef<IServiceCreator> GetServiceCreator(BcatServiceType type)
|
||||
{
|
||||
Debug.Assert((uint)type < ServiceTypeCount);
|
||||
lock (_bcatServiceInitLocker)
|
||||
{
|
||||
Debug.Assert((uint)type < ServiceTypeCount);
|
||||
|
||||
return ServiceCreators[(int)type];
|
||||
return SharedRef<IServiceCreator>.CreateCopy(ref _serviceCreators[(int)type]);
|
||||
}
|
||||
}
|
||||
|
||||
internal DeliveryCacheStorageManager GetStorageManager()
|
||||
|
@ -1,19 +1,26 @@
|
||||
using LibHac.Sm;
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Sm;
|
||||
|
||||
namespace LibHac.Bcat.Impl.Ipc
|
||||
{
|
||||
internal class BcatServiceObject : IServiceObject
|
||||
{
|
||||
private IServiceCreator _serviceCreator;
|
||||
private SharedRef<IServiceCreator> _serviceCreator;
|
||||
|
||||
public BcatServiceObject(IServiceCreator serviceCreator)
|
||||
public BcatServiceObject(ref SharedRef<IServiceCreator> serviceCreator)
|
||||
{
|
||||
_serviceCreator = serviceCreator;
|
||||
_serviceCreator = SharedRef<IServiceCreator>.CreateMove(ref serviceCreator);
|
||||
}
|
||||
|
||||
public Result GetServiceObject(out object serviceObject)
|
||||
public void Dispose()
|
||||
{
|
||||
serviceObject = _serviceCreator;
|
||||
_serviceCreator.Destroy();
|
||||
}
|
||||
|
||||
public Result GetServiceObject(ref SharedRef<IDisposable> serviceObject)
|
||||
{
|
||||
serviceObject.SetByCopy(ref _serviceCreator);
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,14 @@
|
||||
namespace LibHac.Bcat.Impl.Ipc
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
|
||||
namespace LibHac.Bcat.Impl.Ipc
|
||||
{
|
||||
public interface IServiceCreator
|
||||
public interface IServiceCreator : IDisposable
|
||||
{
|
||||
Result CreateDeliveryCacheStorageService(out IDeliveryCacheStorageService service,
|
||||
Result CreateDeliveryCacheStorageService(ref SharedRef<IDeliveryCacheStorageService> outService,
|
||||
ulong processId);
|
||||
|
||||
Result CreateDeliveryCacheStorageServiceWithApplicationId(out IDeliveryCacheStorageService service,
|
||||
ApplicationId applicationId);
|
||||
Result CreateDeliveryCacheStorageServiceWithApplicationId(
|
||||
ref SharedRef<IDeliveryCacheStorageService> outService, ApplicationId applicationId);
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ using LibHac.Common;
|
||||
|
||||
namespace LibHac.Bcat.Impl.Service
|
||||
{
|
||||
// Todo: Update BCAT service object management
|
||||
internal class ServiceCreator : IServiceCreator
|
||||
{
|
||||
private BcatServer Server { get; }
|
||||
@ -19,43 +20,38 @@ namespace LibHac.Bcat.Impl.Service
|
||||
AccessControl = accessControl;
|
||||
}
|
||||
|
||||
public Result CreateDeliveryCacheStorageService(out IDeliveryCacheStorageService service, ulong processId)
|
||||
public void Dispose() { }
|
||||
|
||||
public Result CreateDeliveryCacheStorageService(ref SharedRef<IDeliveryCacheStorageService> outService,
|
||||
ulong processId)
|
||||
{
|
||||
Result rc = Server.Hos.Arp.GetApplicationLaunchProperty(out ApplicationLaunchProperty launchProperty,
|
||||
processId);
|
||||
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out service);
|
||||
return ResultBcat.NotFound.LogConverted(rc);
|
||||
}
|
||||
|
||||
return CreateDeliveryCacheStorageServiceImpl(out service, launchProperty.ApplicationId);
|
||||
return CreateDeliveryCacheStorageServiceImpl(ref outService, launchProperty.ApplicationId);
|
||||
}
|
||||
|
||||
public Result CreateDeliveryCacheStorageServiceWithApplicationId(out IDeliveryCacheStorageService service,
|
||||
ApplicationId applicationId)
|
||||
public Result CreateDeliveryCacheStorageServiceWithApplicationId(
|
||||
ref SharedRef<IDeliveryCacheStorageService> outService, ApplicationId applicationId)
|
||||
{
|
||||
if (!AccessControl.HasFlag(AccessControl.MountOthersDeliveryCacheStorage))
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out service);
|
||||
return ResultBcat.PermissionDenied.Log();
|
||||
}
|
||||
|
||||
return CreateDeliveryCacheStorageServiceImpl(out service, applicationId);
|
||||
return CreateDeliveryCacheStorageServiceImpl(ref outService, applicationId);
|
||||
}
|
||||
|
||||
private Result CreateDeliveryCacheStorageServiceImpl(out IDeliveryCacheStorageService service,
|
||||
private Result CreateDeliveryCacheStorageServiceImpl(ref SharedRef<IDeliveryCacheStorageService> outService,
|
||||
ApplicationId applicationId)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out service);
|
||||
|
||||
Result rc = Server.GetStorageManager().Open(applicationId.Value);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
// todo: Check if network account required
|
||||
|
||||
service = new DeliveryCacheStorageService(Server, applicationId.Value, AccessControl);
|
||||
outService.Reset(new DeliveryCacheStorageService(Server, applicationId.Value, AccessControl));
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
26
src/LibHac/Common/FixedArrays/Array5.cs
Normal file
26
src/LibHac/Common/FixedArrays/Array5.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace LibHac.Common.FixedArrays
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Array5<T>
|
||||
{
|
||||
public const int Length = 5;
|
||||
|
||||
private T _1;
|
||||
private T _2;
|
||||
private T _3;
|
||||
private T _4;
|
||||
private T _5;
|
||||
|
||||
public ref T this[int i] => ref Items[i];
|
||||
|
||||
public Span<T> Items => SpanHelpers.CreateSpan(ref _1, Length);
|
||||
public readonly ReadOnlySpan<T> ItemsRo => SpanHelpers.CreateReadOnlySpan(in _1, Length);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator ReadOnlySpan<T>(in Array5<T> value) => value.ItemsRo;
|
||||
}
|
||||
}
|
@ -254,6 +254,46 @@ namespace LibHac.Common
|
||||
oldRefCount?.Decrement();
|
||||
}
|
||||
|
||||
public void Set<TFrom>(ref UniqueRef<TFrom> other) where TFrom : class, T
|
||||
{
|
||||
RefCount oldRefCount = _refCount;
|
||||
TFrom otherValue = other.Release();
|
||||
|
||||
if (otherValue is not null)
|
||||
{
|
||||
_value = Unsafe.As<TFrom, T>(ref otherValue);
|
||||
_refCount = new RefCount(otherValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
_value = null;
|
||||
_refCount = null;
|
||||
}
|
||||
|
||||
oldRefCount?.Decrement();
|
||||
}
|
||||
|
||||
public bool TryCastSet<TFrom>(ref SharedRef<TFrom> other) where TFrom : class, IDisposable
|
||||
{
|
||||
RefCount oldRefCount = _refCount;
|
||||
TFrom otherValue = other.Get;
|
||||
|
||||
if (otherValue is T)
|
||||
{
|
||||
_value = Unsafe.As<TFrom, T>(ref other._value);
|
||||
_refCount = other._refCount;
|
||||
|
||||
other._value = null;
|
||||
other._refCount = null;
|
||||
|
||||
oldRefCount?.Decrement();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void ThrowBadWeakPtr()
|
||||
{
|
||||
throw new ObjectDisposedException(string.Empty, "bad_weak_ptr");
|
||||
|
@ -68,6 +68,14 @@ namespace LibHac.Diag
|
||||
DoAbort(result, message);
|
||||
}
|
||||
|
||||
public static void DoAbortUnlessSuccess(Result result, string message = null)
|
||||
{
|
||||
if (!result.IsSuccess())
|
||||
{
|
||||
DoAbort(result, message);
|
||||
}
|
||||
}
|
||||
|
||||
[DoesNotReturn]
|
||||
public static void UnexpectedDefault([CallerMemberName] string caller = "")
|
||||
{
|
||||
|
@ -63,9 +63,9 @@ namespace LibHac.Fs
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.GetGlobalAccessLogMode(out mode);
|
||||
Result rc = fileSystemProxy.Get.GetGlobalAccessLogMode(out mode);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
@ -79,9 +79,9 @@ namespace LibHac.Fs
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.SetGlobalAccessLogMode(mode);
|
||||
Result rc = fileSystemProxy.Get.SetGlobalAccessLogMode(mode);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
@ -133,8 +133,8 @@ namespace LibHac.Fs
|
||||
|
||||
public static void OutputApplicationInfoAccessLog(this FileSystemClient fs, in ApplicationInfo applicationInfo)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
fsProxy.Target.OutputApplicationInfoAccessLog(in applicationInfo).IgnoreResult();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
fileSystemProxy.Get.OutputApplicationInfoAccessLog(in applicationInfo).IgnoreResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -323,14 +323,14 @@ namespace LibHac.Fs.Impl
|
||||
|
||||
private static void FlushAccessLogOnSdCardImpl(FileSystemClientImpl fs)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
fsProxy.Target.FlushAccessLogOnSdCard().IgnoreResult();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
fileSystemProxy.Get.FlushAccessLogOnSdCard().IgnoreResult();
|
||||
}
|
||||
|
||||
private static void OutputAccessLogToSdCardImpl(FileSystemClientImpl fs, U8Span message)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
fsProxy.Target.OutputAccessLogToSdCard(new InBuffer(message.Value)).IgnoreResult();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
fileSystemProxy.Get.OutputAccessLogToSdCard(new InBuffer(message.Value)).IgnoreResult();
|
||||
}
|
||||
|
||||
// The original function creates a string using the input format string and format args.
|
||||
@ -423,8 +423,8 @@ namespace LibHac.Fs.Impl
|
||||
|
||||
private static void GetProgramIndexForAccessLog(FileSystemClientImpl fs, out int index, out int count)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
Result rc = fsProxy.Target.GetProgramIndexForAccessLog(out index, out count);
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
Result rc = fileSystemProxy.Get.GetProgramIndexForAccessLog(out index, out count);
|
||||
Abort.DoAbortUnless(rc.IsSuccess());
|
||||
}
|
||||
|
||||
|
286
src/LibHac/Fs/Common/FileStorage.cs
Normal file
286
src/LibHac/Fs/Common/FileStorage.cs
Normal file
@ -0,0 +1,286 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Diag;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.Os;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
public class FileStorage : IStorage
|
||||
{
|
||||
private const long InvalidSize = -1;
|
||||
|
||||
private SharedRef<IFile> _baseFileShared;
|
||||
private IFile _baseFile;
|
||||
private long _fileSize;
|
||||
|
||||
protected FileStorage()
|
||||
{
|
||||
_fileSize = InvalidSize;
|
||||
}
|
||||
|
||||
public FileStorage(IFile baseFile)
|
||||
{
|
||||
_baseFile = baseFile;
|
||||
_fileSize = InvalidSize;
|
||||
}
|
||||
|
||||
public FileStorage(ref SharedRef<IFile> baseFile)
|
||||
{
|
||||
_baseFile = baseFile.Get;
|
||||
_baseFileShared = SharedRef<IFile>.CreateMove(ref baseFile);
|
||||
_fileSize = InvalidSize;
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
_baseFileShared.Destroy();
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
protected void SetFile(IFile file)
|
||||
{
|
||||
Assert.SdkRequiresNotNull(file);
|
||||
Assert.SdkRequiresNull(_baseFile);
|
||||
|
||||
_baseFile = file;
|
||||
}
|
||||
|
||||
protected override Result DoRead(long offset, Span<byte> destination)
|
||||
{
|
||||
if (destination.Length == 0)
|
||||
return Result.Success;
|
||||
|
||||
Result rc = UpdateSize();
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
if (!CheckAccessRange(offset, destination.Length, _fileSize))
|
||||
return ResultFs.OutOfRange.Log();
|
||||
|
||||
return _baseFile.Read(out _, offset, destination, ReadOption.None);
|
||||
}
|
||||
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
if (source.Length == 0)
|
||||
return Result.Success;
|
||||
|
||||
Result rc = UpdateSize();
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
if (!CheckAccessRange(offset, source.Length, _fileSize))
|
||||
return ResultFs.OutOfRange.Log();
|
||||
|
||||
return _baseFile.Write(offset, source, WriteOption.None);
|
||||
}
|
||||
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return _baseFile.Flush();
|
||||
}
|
||||
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out size);
|
||||
|
||||
Result rc = UpdateSize();
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
size = _fileSize;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
_fileSize = InvalidSize;
|
||||
return _baseFile.SetSize(size);
|
||||
}
|
||||
|
||||
protected override Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size, ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
if (operationId == OperationId.InvalidateCache || operationId == OperationId.QueryRange)
|
||||
{
|
||||
if (size == 0)
|
||||
{
|
||||
if (operationId == OperationId.QueryRange)
|
||||
{
|
||||
if (outBuffer.Length != Unsafe.SizeOf<QueryRangeInfo>())
|
||||
return ResultFs.InvalidSize.Log();
|
||||
|
||||
SpanHelpers.AsStruct<QueryRangeInfo>(outBuffer).Clear();
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
Result rc = UpdateSize();
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
if (!CheckOffsetAndSize(offset, size))
|
||||
return ResultFs.OutOfRange.Log();
|
||||
|
||||
return _baseFile.OperateRange(outBuffer, operationId, offset, size, inBuffer);
|
||||
}
|
||||
|
||||
return ResultFs.UnsupportedOperateRangeForFileStorage.Log();
|
||||
}
|
||||
|
||||
private Result UpdateSize()
|
||||
{
|
||||
if (_fileSize != InvalidSize)
|
||||
return Result.Success;
|
||||
|
||||
Result rc = _baseFile.GetSize(out long size);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
_fileSize = size;
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
public class FileStorageBasedFileSystem : FileStorage
|
||||
{
|
||||
private SharedRef<IFileSystem> _baseFileSystem;
|
||||
private UniqueRef<IFile> _baseFile;
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
_baseFile.Destroy();
|
||||
_baseFileSystem.Destroy();
|
||||
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
public Result Initialize(ref SharedRef<IFileSystem> baseFileSystem, in Path path, OpenMode mode)
|
||||
{
|
||||
using var baseFile = new UniqueRef<IFile>();
|
||||
|
||||
Result rc = baseFileSystem.Get.OpenFile(ref baseFile.Ref(), in path, mode);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
SetFile(baseFile.Get);
|
||||
_baseFileSystem.SetByMove(ref baseFileSystem);
|
||||
_baseFile.Set(ref baseFile.Ref());
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
public class FileHandleStorage : IStorage
|
||||
{
|
||||
private const long InvalidSize = -1;
|
||||
|
||||
private FileHandle _handle;
|
||||
private bool _closeFile;
|
||||
private long _size;
|
||||
private SdkMutexType _mutex;
|
||||
|
||||
// LibHac addition
|
||||
private FileSystemClient _fsClient;
|
||||
|
||||
public FileHandleStorage(FileSystemClient fsClient, FileHandle handle) : this(fsClient, handle, false) { }
|
||||
|
||||
public FileHandleStorage(FileSystemClient fsClient, FileHandle handle, bool closeFile)
|
||||
{
|
||||
_fsClient = fsClient;
|
||||
_handle = handle;
|
||||
_closeFile = closeFile;
|
||||
_size = InvalidSize;
|
||||
_mutex.Initialize();
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
if (_closeFile)
|
||||
{
|
||||
_fsClient.CloseFile(_handle);
|
||||
_closeFile = false;
|
||||
_handle = default;
|
||||
}
|
||||
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
protected override Result DoRead(long offset, Span<byte> destination)
|
||||
{
|
||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
if (destination.Length == 0)
|
||||
return Result.Success;
|
||||
|
||||
Result rc = UpdateSize();
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
if (!CheckAccessRange(offset, destination.Length, _size))
|
||||
return ResultFs.OutOfRange.Log();
|
||||
|
||||
return _fsClient.ReadFile(_handle, offset, destination, ReadOption.None);
|
||||
}
|
||||
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
if (source.Length == 0)
|
||||
return Result.Success;
|
||||
|
||||
Result rc = UpdateSize();
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
if (!CheckAccessRange(offset, source.Length, _size))
|
||||
return ResultFs.OutOfRange.Log();
|
||||
|
||||
return _fsClient.WriteFile(_handle, offset, source, WriteOption.None);
|
||||
}
|
||||
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return _fsClient.FlushFile(_handle);
|
||||
}
|
||||
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out size);
|
||||
|
||||
Result rc = UpdateSize();
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
size = _size;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
_size = InvalidSize;
|
||||
return _fsClient.SetFileSize(_handle, size);
|
||||
}
|
||||
|
||||
protected override Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size, ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
if (operationId != OperationId.QueryRange)
|
||||
return ResultFs.UnsupportedOperateRangeForFileHandleStorage.Log();
|
||||
|
||||
if (outBuffer.Length != Unsafe.SizeOf<QueryRangeInfo>())
|
||||
return ResultFs.InvalidSize.Log();
|
||||
|
||||
Result rc = _fsClient.QueryRange(out SpanHelpers.AsStruct<QueryRangeInfo>(outBuffer), _handle, offset, size);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private Result UpdateSize()
|
||||
{
|
||||
if (_size != InvalidSize)
|
||||
return Result.Success;
|
||||
|
||||
Result rc = _fsClient.GetFileSize(out long size, _handle);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
_size = size;
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
@ -81,7 +81,7 @@ namespace LibHac.Fs
|
||||
/// ensure a write buffer is allocated and copy the input path to it. <see cref="SetShallowBuffer"/> will
|
||||
/// directly use the input buffer without copying. If this method is used, the caller must ensure the path
|
||||
/// is normalized before passing it to <see cref="SetShallowBuffer"/>.</para>
|
||||
/// <br/>Based on FS 12.0.3 (nnSdk 12.3.1)</remarks>
|
||||
/// <para>Based on FS 12.1.0 (nnSdk 12.3.1)</para></remarks>
|
||||
[DebuggerDisplay("{" + nameof(ToString) + "(),nq}")]
|
||||
public ref struct Path
|
||||
{
|
||||
@ -1084,6 +1084,16 @@ namespace LibHac.Fs
|
||||
|
||||
public static class PathFunctions
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a <see cref="Path"/> with the provided basic path.
|
||||
/// The provided path must be a normalized basic path starting with a directory separator
|
||||
/// and not containing any sort of prefix such as a mount name.
|
||||
/// </summary>
|
||||
/// <param name="path">The <see cref="Path"/> to initialize.</param>
|
||||
/// <param name="pathBuffer">The string used to initialize the <see cref="Path"/>.</param>
|
||||
/// <returns><see cref="Result.Success"/>: The operation was successful.<br/>
|
||||
/// <see cref="ResultFs.InvalidCharacter"/>: The path contains an invalid character.<br/>
|
||||
/// <see cref="ResultFs.InvalidPathFormat"/>: The path is in an invalid format or is not normalized.</returns>
|
||||
public static Result SetUpFixedPath(ref Path path, ReadOnlySpan<byte> pathBuffer)
|
||||
{
|
||||
Result rc = PathNormalizer.IsNormalized(out bool isNormalized, out _, pathBuffer);
|
||||
@ -1101,6 +1111,14 @@ namespace LibHac.Fs
|
||||
// Only a small number of format strings are used with these functions, so we can hard code them all easily.
|
||||
|
||||
// /%s
|
||||
/// <summary>
|
||||
/// Initializes a <see cref="Path"/> using the format string <c>/%s</c>
|
||||
/// </summary>
|
||||
/// <param name="path">The <see cref="Path"/> to be initialized.</param>
|
||||
/// <param name="pathBuffer">The buffer that will contain the built string.</param>
|
||||
/// <param name="entryName">The first entry in the generated path.</param>
|
||||
/// <returns><see cref="Result.Success"/>: The operation was successful.<br/>
|
||||
/// <see cref="ResultFs.InvalidArgument"/>: <paramref name="pathBuffer"/> was too small to contain the built path.</returns>
|
||||
internal static Result SetUpFixedPathSingleEntry(ref Path path, Span<byte> pathBuffer,
|
||||
ReadOnlySpan<byte> entryName)
|
||||
{
|
||||
@ -1114,6 +1132,15 @@ namespace LibHac.Fs
|
||||
}
|
||||
|
||||
// /%s/%s
|
||||
/// <summary>
|
||||
/// Initializes a <see cref="Path"/> using the format string <c>/%s/%s</c>
|
||||
/// </summary>
|
||||
/// <param name="path">The <see cref="Path"/> to be initialized.</param>
|
||||
/// <param name="pathBuffer">The buffer that will contain the built string.</param>
|
||||
/// <param name="entryName1">The first entry in the generated path.</param>
|
||||
/// <param name="entryName2">The second entry in the generated path.</param>
|
||||
/// <returns><see cref="Result.Success"/>: The operation was successful.<br/>
|
||||
/// <see cref="ResultFs.InvalidArgument"/>: <paramref name="pathBuffer"/> was too small to contain the built path.</returns>
|
||||
internal static Result SetUpFixedPathDoubleEntry(ref Path path, Span<byte> pathBuffer,
|
||||
ReadOnlySpan<byte> entryName1, ReadOnlySpan<byte> entryName2)
|
||||
{
|
||||
@ -1128,6 +1155,14 @@ namespace LibHac.Fs
|
||||
}
|
||||
|
||||
// /%016llx
|
||||
/// <summary>
|
||||
/// Initializes a <see cref="Path"/> using the format string <c>/%016llx</c>
|
||||
/// </summary>
|
||||
/// <param name="path">The <see cref="Path"/> to be initialized.</param>
|
||||
/// <param name="pathBuffer">The buffer that will contain the built string.</param>
|
||||
/// <param name="saveDataId">The save data ID to insert into the path.</param>
|
||||
/// <returns><see cref="Result.Success"/>: The operation was successful.<br/>
|
||||
/// <see cref="ResultFs.InvalidArgument"/>: <paramref name="pathBuffer"/> was too small to contain the built path.</returns>
|
||||
internal static Result SetUpFixedPathSaveId(ref Path path, Span<byte> pathBuffer, ulong saveDataId)
|
||||
{
|
||||
var sb = new U8StringBuilder(pathBuffer);
|
||||
@ -1140,6 +1175,14 @@ namespace LibHac.Fs
|
||||
}
|
||||
|
||||
// /%08x.meta
|
||||
/// <summary>
|
||||
/// Initializes a <see cref="Path"/> using the format string <c>/%08x.meta</c>
|
||||
/// </summary>
|
||||
/// <param name="path">The <see cref="Path"/> to be initialized.</param>
|
||||
/// <param name="pathBuffer">The buffer that will contain the built string.</param>
|
||||
/// <param name="metaType">The <see cref="SaveDataMetaType"/> to insert into the path.</param>
|
||||
/// <returns><see cref="Result.Success"/>: The operation was successful.<br/>
|
||||
/// <see cref="ResultFs.InvalidArgument"/>: <paramref name="pathBuffer"/> was too small to contain the built path.</returns>
|
||||
internal static Result SetUpFixedPathSaveMetaName(ref Path path, Span<byte> pathBuffer, uint metaType)
|
||||
{
|
||||
ReadOnlySpan<byte> metaExtension = new[] { (byte)'.', (byte)'m', (byte)'e', (byte)'t', (byte)'a' }; // ".meta"
|
||||
@ -1154,6 +1197,14 @@ namespace LibHac.Fs
|
||||
}
|
||||
|
||||
// /saveMeta/%016llx
|
||||
/// <summary>
|
||||
/// Initializes a <see cref="Path"/> using the format string <c>/saveMeta/%016llx</c>
|
||||
/// </summary>
|
||||
/// <param name="path">The <see cref="Path"/> to be initialized.</param>
|
||||
/// <param name="pathBuffer">The buffer that will contain the built string.</param>
|
||||
/// <param name="saveDataId">The save data ID to insert into the path.</param>
|
||||
/// <returns><see cref="Result.Success"/>: The operation was successful.<br/>
|
||||
/// <see cref="ResultFs.InvalidArgument"/>: <paramref name="pathBuffer"/> was too small to contain the built path.</returns>
|
||||
internal static Result SetUpFixedPathSaveMetaDir(ref Path path, Span<byte> pathBuffer, ulong saveDataId)
|
||||
{
|
||||
ReadOnlySpan<byte> metaDirectoryName = new[]
|
||||
|
@ -14,7 +14,7 @@ namespace LibHac.Fs
|
||||
/// <summary>
|
||||
/// Contains functions for working with path formatting and normalization.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.0.3 (nnSdk 12.3.1)</remarks>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
public static class PathFormatter
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
@ -11,7 +11,7 @@ namespace LibHac.Fs
|
||||
/// <summary>
|
||||
/// Contains functions for doing with basic path normalization.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.0.3 (nnSdk 12.3.1)</remarks>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
public static class PathNormalizer
|
||||
{
|
||||
private enum PathState
|
||||
|
@ -8,6 +8,10 @@ using static LibHac.Fs.StringTraits;
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains various utility functions for working with paths.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
public static class PathUtility
|
||||
{
|
||||
public static void Replace(Span<byte> buffer, byte currentChar, byte newChar)
|
||||
|
@ -10,7 +10,7 @@ namespace LibHac.Fs
|
||||
/// <summary>
|
||||
/// Contains functions for working with Windows paths.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.0.3 (nnSdk 12.3.1)</remarks>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
public static class WindowsPath
|
||||
{
|
||||
private const int WindowsDriveLength = 2;
|
||||
|
@ -1,98 +1,98 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Fsa;
|
||||
//using System;
|
||||
//using LibHac.Common;
|
||||
//using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
public class FileHandleStorage : IStorage
|
||||
{
|
||||
private const long InvalidSize = -1;
|
||||
private readonly object _locker = new object();
|
||||
//namespace LibHac.Fs
|
||||
//{
|
||||
// public class FileHandleStorage : IStorage
|
||||
// {
|
||||
// private const long InvalidSize = -1;
|
||||
// private readonly object _locker = new object();
|
||||
|
||||
private FileSystemClient FsClient { get; }
|
||||
private FileHandle Handle { get; }
|
||||
private long FileSize { get; set; } = InvalidSize;
|
||||
private bool CloseHandle { get; }
|
||||
// private FileSystemClient FsClient { get; }
|
||||
// private FileHandle Handle { get; }
|
||||
// private long FileSize { get; set; } = InvalidSize;
|
||||
// private bool CloseHandle { get; }
|
||||
|
||||
public FileHandleStorage(FileSystemClient fsClient, FileHandle handle) : this(fsClient, handle, false) { }
|
||||
// public FileHandleStorage(FileSystemClient fsClient, FileHandle handle) : this(fsClient, handle, false) { }
|
||||
|
||||
public FileHandleStorage(FileSystemClient fsClient, FileHandle handle, bool closeHandleOnDispose)
|
||||
{
|
||||
FsClient = fsClient;
|
||||
Handle = handle;
|
||||
CloseHandle = closeHandleOnDispose;
|
||||
}
|
||||
// public FileHandleStorage(FileSystemClient fsClient, FileHandle handle, bool closeHandleOnDispose)
|
||||
// {
|
||||
// FsClient = fsClient;
|
||||
// Handle = handle;
|
||||
// CloseHandle = closeHandleOnDispose;
|
||||
// }
|
||||
|
||||
protected override Result DoRead(long offset, Span<byte> destination)
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
if (destination.Length == 0) return Result.Success;
|
||||
// protected override Result DoRead(long offset, Span<byte> destination)
|
||||
// {
|
||||
// lock (_locker)
|
||||
// {
|
||||
// if (destination.Length == 0) return Result.Success;
|
||||
|
||||
Result rc = UpdateSize();
|
||||
if (rc.IsFailure()) return rc;
|
||||
// Result rc = UpdateSize();
|
||||
// if (rc.IsFailure()) return rc;
|
||||
|
||||
if (!IsRangeValid(offset, destination.Length, FileSize)) return ResultFs.OutOfRange.Log();
|
||||
// if (!CheckAccessRange(offset, destination.Length, FileSize)) return ResultFs.OutOfRange.Log();
|
||||
|
||||
return FsClient.ReadFile(Handle, offset, destination);
|
||||
}
|
||||
}
|
||||
// return FsClient.ReadFile(Handle, offset, destination);
|
||||
// }
|
||||
// }
|
||||
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
if (source.Length == 0) return Result.Success;
|
||||
// protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
// {
|
||||
// lock (_locker)
|
||||
// {
|
||||
// if (source.Length == 0) return Result.Success;
|
||||
|
||||
Result rc = UpdateSize();
|
||||
if (rc.IsFailure()) return rc;
|
||||
// Result rc = UpdateSize();
|
||||
// if (rc.IsFailure()) return rc;
|
||||
|
||||
if (!IsRangeValid(offset, source.Length, FileSize)) return ResultFs.OutOfRange.Log();
|
||||
// if (!CheckAccessRange(offset, source.Length, FileSize)) return ResultFs.OutOfRange.Log();
|
||||
|
||||
return FsClient.WriteFile(Handle, offset, source, WriteOption.None);
|
||||
}
|
||||
}
|
||||
// return FsClient.WriteFile(Handle, offset, source, WriteOption.None);
|
||||
// }
|
||||
// }
|
||||
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return FsClient.FlushFile(Handle);
|
||||
}
|
||||
// protected override Result DoFlush()
|
||||
// {
|
||||
// return FsClient.FlushFile(Handle);
|
||||
// }
|
||||
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
FileSize = InvalidSize;
|
||||
// protected override Result DoSetSize(long size)
|
||||
// {
|
||||
// FileSize = InvalidSize;
|
||||
|
||||
return FsClient.SetFileSize(Handle, size);
|
||||
}
|
||||
// return FsClient.SetFileSize(Handle, size);
|
||||
// }
|
||||
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out size);
|
||||
// protected override Result DoGetSize(out long size)
|
||||
// {
|
||||
// UnsafeHelpers.SkipParamInit(out size);
|
||||
|
||||
Result rc = UpdateSize();
|
||||
if (rc.IsFailure()) return rc;
|
||||
// Result rc = UpdateSize();
|
||||
// if (rc.IsFailure()) return rc;
|
||||
|
||||
size = FileSize;
|
||||
return Result.Success;
|
||||
}
|
||||
// size = FileSize;
|
||||
// return Result.Success;
|
||||
// }
|
||||
|
||||
private Result UpdateSize()
|
||||
{
|
||||
if (FileSize != InvalidSize) return Result.Success;
|
||||
// private Result UpdateSize()
|
||||
// {
|
||||
// if (FileSize != InvalidSize) return Result.Success;
|
||||
|
||||
Result rc = FsClient.GetFileSize(out long fileSize, Handle);
|
||||
if (rc.IsFailure()) return rc;
|
||||
// Result rc = FsClient.GetFileSize(out long fileSize, Handle);
|
||||
// if (rc.IsFailure()) return rc;
|
||||
|
||||
FileSize = fileSize;
|
||||
return Result.Success;
|
||||
}
|
||||
// FileSize = fileSize;
|
||||
// return Result.Success;
|
||||
// }
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (CloseHandle)
|
||||
{
|
||||
FsClient.CloseFile(Handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// protected override void Dispose(bool disposing)
|
||||
// {
|
||||
// if (CloseHandle)
|
||||
// {
|
||||
// FsClient.CloseFile(Handle);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
@ -1,130 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
public class FileStorage2 : IStorage
|
||||
{
|
||||
protected const long SizeNotInitialized = -1;
|
||||
|
||||
private IFile BaseFile { get; set; }
|
||||
protected long FileSize { get; set; }
|
||||
|
||||
public FileStorage2(IFile baseFile)
|
||||
{
|
||||
BaseFile = baseFile;
|
||||
FileSize = SizeNotInitialized;
|
||||
}
|
||||
|
||||
protected FileStorage2() { }
|
||||
|
||||
protected void SetFile(IFile file)
|
||||
{
|
||||
Debug.Assert(file != null);
|
||||
Debug.Assert(BaseFile == null);
|
||||
|
||||
BaseFile = file;
|
||||
}
|
||||
|
||||
private Result UpdateSize()
|
||||
{
|
||||
if (FileSize != SizeNotInitialized)
|
||||
return Result.Success;
|
||||
|
||||
Result rc = BaseFile.GetSize(out long fileSize);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
FileSize = fileSize;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result DoRead(long offset, Span<byte> destination)
|
||||
{
|
||||
if (destination.Length == 0)
|
||||
return Result.Success;
|
||||
|
||||
Result rc = UpdateSize();
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (!IsRangeValid(offset, destination.Length, FileSize))
|
||||
return ResultFs.OutOfRange.Log();
|
||||
|
||||
return BaseFile.Read(out _, offset, destination, ReadOption.None);
|
||||
}
|
||||
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
if (source.Length == 0)
|
||||
return Result.Success;
|
||||
|
||||
Result rc = UpdateSize();
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (!IsRangeValid(offset, source.Length, FileSize))
|
||||
return ResultFs.OutOfRange.Log();
|
||||
|
||||
return BaseFile.Write(offset, source, WriteOption.None);
|
||||
}
|
||||
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return BaseFile.Flush();
|
||||
}
|
||||
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out size);
|
||||
|
||||
Result rc = UpdateSize();
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
size = FileSize;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
FileSize = SizeNotInitialized;
|
||||
return BaseFile.SetSize(size);
|
||||
}
|
||||
|
||||
protected override Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size, ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
switch (operationId)
|
||||
{
|
||||
case OperationId.InvalidateCache:
|
||||
case OperationId.QueryRange:
|
||||
if (size == 0)
|
||||
{
|
||||
if (operationId == OperationId.QueryRange)
|
||||
{
|
||||
if (outBuffer.Length != Unsafe.SizeOf<QueryRangeInfo>())
|
||||
{
|
||||
return ResultFs.InvalidSize.Log();
|
||||
}
|
||||
|
||||
Unsafe.As<byte, QueryRangeInfo>(ref outBuffer[0]) = new QueryRangeInfo();
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
Result rc = UpdateSize();
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (size < 0 || offset < 0)
|
||||
{
|
||||
return ResultFs.OutOfRange.Log();
|
||||
}
|
||||
|
||||
return BaseFile.OperateRange(outBuffer, operationId, offset, size, inBuffer);
|
||||
|
||||
default:
|
||||
return ResultFs.UnsupportedOperateRangeForFileStorage.Log();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +1,41 @@
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Fsa;
|
||||
//using LibHac.Common;
|
||||
//using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
public class FileStorageBasedFileSystem : FileStorage2
|
||||
{
|
||||
private ReferenceCountedDisposable<IFileSystem> _baseFileSystem;
|
||||
private UniqueRef<IFile> _baseFile;
|
||||
//namespace LibHac.Fs
|
||||
//{
|
||||
// public class FileStorageBasedFileSystem : FileStorage2
|
||||
// {
|
||||
// private ReferenceCountedDisposable<IFileSystem> _baseFileSystem;
|
||||
// private UniqueRef<IFile> _baseFile;
|
||||
|
||||
public FileStorageBasedFileSystem()
|
||||
{
|
||||
FileSize = SizeNotInitialized;
|
||||
}
|
||||
// public FileStorageBasedFileSystem()
|
||||
// {
|
||||
// FileSize = SizeNotInitialized;
|
||||
// }
|
||||
|
||||
public Result Initialize(ref ReferenceCountedDisposable<IFileSystem> baseFileSystem, in Path path,
|
||||
OpenMode mode)
|
||||
{
|
||||
using var baseFile = new UniqueRef<IFile>();
|
||||
Result rc = baseFileSystem.Target.OpenFile(ref baseFile.Ref(), in path, mode);
|
||||
if (rc.IsFailure()) return rc;
|
||||
// public Result Initialize(ref ReferenceCountedDisposable<IFileSystem> baseFileSystem, in Path path,
|
||||
// OpenMode mode)
|
||||
// {
|
||||
// using var baseFile = new UniqueRef<IFile>();
|
||||
// Result rc = baseFileSystem.Get.OpenFile(ref baseFile.Ref(), in path, mode);
|
||||
// if (rc.IsFailure()) return rc;
|
||||
|
||||
SetFile(baseFile.Get);
|
||||
_baseFileSystem = Shared.Move(ref baseFileSystem);
|
||||
_baseFile.Set(ref _baseFile.Ref());
|
||||
// SetFile(baseFile.Get);
|
||||
// _baseFileSystem = Shared.Move(ref baseFileSystem);
|
||||
// _baseFile.Set(ref _baseFile.Ref());
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
// return Result.Success;
|
||||
// }
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_baseFile.Destroy();
|
||||
_baseFileSystem?.Dispose();
|
||||
}
|
||||
// protected override void Dispose(bool disposing)
|
||||
// {
|
||||
// if (disposing)
|
||||
// {
|
||||
// _baseFile.Destroy();
|
||||
// _baseFileSystem?.Dispose();
|
||||
// }
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
// base.Dispose(disposing);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
@ -19,12 +19,12 @@ namespace LibHac.Fs.Impl
|
||||
private const string InvalidFsEntryObjectMessage = "Invalid file or directory object.";
|
||||
|
||||
private MountName _mountName;
|
||||
private IFileSystem _fileSystem;
|
||||
private UniqueRef<IFileSystem> _fileSystem;
|
||||
private LinkedList<FileAccessor> _openFiles;
|
||||
private LinkedList<DirectoryAccessor> _openDirectories;
|
||||
private SdkMutexType _openListLock;
|
||||
private ICommonMountNameGenerator _mountNameGenerator;
|
||||
private ISaveDataAttributeGetter _saveDataAttributeGetter;
|
||||
private UniqueRef<ICommonMountNameGenerator> _mountNameGenerator;
|
||||
private UniqueRef<ISaveDataAttributeGetter> _saveDataAttributeGetter;
|
||||
private bool _isAccessLogEnabled;
|
||||
private bool _isDataCacheAttachable;
|
||||
private bool _isPathCacheAttachable;
|
||||
@ -36,17 +36,17 @@ namespace LibHac.Fs.Impl
|
||||
internal HorizonClient Hos { get; }
|
||||
|
||||
public FileSystemAccessor(HorizonClient hosClient, U8Span name, IMultiCommitTarget multiCommitTarget,
|
||||
IFileSystem fileSystem, ICommonMountNameGenerator mountNameGenerator,
|
||||
ISaveDataAttributeGetter saveAttributeGetter)
|
||||
ref UniqueRef<IFileSystem> fileSystem, ref UniqueRef<ICommonMountNameGenerator> mountNameGenerator,
|
||||
ref UniqueRef<ISaveDataAttributeGetter> saveAttributeGetter)
|
||||
{
|
||||
Hos = hosClient;
|
||||
|
||||
_fileSystem = fileSystem;
|
||||
_fileSystem = new UniqueRef<IFileSystem>(ref fileSystem);
|
||||
_openFiles = new LinkedList<FileAccessor>();
|
||||
_openDirectories = new LinkedList<DirectoryAccessor>();
|
||||
_openListLock.Initialize();
|
||||
_mountNameGenerator = mountNameGenerator;
|
||||
_saveDataAttributeGetter = saveAttributeGetter;
|
||||
_mountNameGenerator = new UniqueRef<ICommonMountNameGenerator>(ref mountNameGenerator);
|
||||
_saveDataAttributeGetter = new UniqueRef<ISaveDataAttributeGetter>(ref saveAttributeGetter);
|
||||
_multiCommitTarget = multiCommitTarget;
|
||||
|
||||
if (name.IsEmpty())
|
||||
@ -94,14 +94,9 @@ namespace LibHac.Fs.Impl
|
||||
}
|
||||
}
|
||||
|
||||
ISaveDataAttributeGetter saveDataAttributeGetter = Shared.Move(ref _saveDataAttributeGetter);
|
||||
saveDataAttributeGetter?.Dispose();
|
||||
|
||||
ICommonMountNameGenerator mountNameGenerator = Shared.Move(ref _mountNameGenerator);
|
||||
mountNameGenerator?.Dispose();
|
||||
|
||||
IFileSystem fileSystem = Shared.Move(ref _fileSystem);
|
||||
fileSystem?.Dispose();
|
||||
_saveDataAttributeGetter.Destroy();
|
||||
_mountNameGenerator.Destroy();
|
||||
_fileSystem.Destroy();
|
||||
}
|
||||
|
||||
private static void Remove<T>(LinkedList<T> list, T item)
|
||||
@ -132,7 +127,7 @@ namespace LibHac.Fs.Impl
|
||||
}
|
||||
|
||||
public Optional<Ncm.DataId> GetDataId() => _dataId;
|
||||
public void SetDataId(Ncm.DataId dataId) => _dataId.Set(dataId);
|
||||
public void SetDataId(Optional<Ncm.DataId> dataId) => _dataId = dataId;
|
||||
|
||||
public Result SetUpPath(ref Path path, U8Span pathBuffer)
|
||||
{
|
||||
@ -177,7 +172,7 @@ namespace LibHac.Fs.Impl
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = _fileSystem.CreateFile(in pathNormalized, size, option);
|
||||
rc = _fileSystem.Get.CreateFile(in pathNormalized, size, option);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
|
||||
@ -190,7 +185,7 @@ namespace LibHac.Fs.Impl
|
||||
Result rc = SetUpPath(ref pathNormalized.Ref(), path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = _fileSystem.DeleteFile(in pathNormalized);
|
||||
rc = _fileSystem.Get.DeleteFile(in pathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
@ -202,7 +197,7 @@ namespace LibHac.Fs.Impl
|
||||
Result rc = SetUpPath(ref pathNormalized.Ref(), path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = _fileSystem.CreateDirectory(in pathNormalized);
|
||||
rc = _fileSystem.Get.CreateDirectory(in pathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
@ -214,7 +209,7 @@ namespace LibHac.Fs.Impl
|
||||
Result rc = SetUpPath(ref pathNormalized.Ref(), path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = _fileSystem.CreateDirectory(in pathNormalized);
|
||||
rc = _fileSystem.Get.CreateDirectory(in pathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
@ -226,7 +221,7 @@ namespace LibHac.Fs.Impl
|
||||
Result rc = SetUpPath(ref pathNormalized.Ref(), path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = _fileSystem.DeleteDirectoryRecursively(in pathNormalized);
|
||||
rc = _fileSystem.Get.DeleteDirectoryRecursively(in pathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
@ -238,7 +233,7 @@ namespace LibHac.Fs.Impl
|
||||
Result rc = SetUpPath(ref pathNormalized.Ref(), path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = _fileSystem.CleanDirectoryRecursively(in pathNormalized);
|
||||
rc = _fileSystem.Get.CleanDirectoryRecursively(in pathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
@ -260,7 +255,7 @@ namespace LibHac.Fs.Impl
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = _fileSystem.RenameFile(in currentPathNormalized, in newPathNormalized);
|
||||
rc = _fileSystem.Get.RenameFile(in currentPathNormalized, in newPathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
|
||||
@ -283,7 +278,7 @@ namespace LibHac.Fs.Impl
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = _fileSystem.RenameDirectory(in currentPathNormalized, in newPathNormalized);
|
||||
rc = _fileSystem.Get.RenameDirectory(in currentPathNormalized, in newPathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
return Result.Success;
|
||||
@ -297,7 +292,7 @@ namespace LibHac.Fs.Impl
|
||||
Result rc = SetUpPath(ref pathNormalized.Ref(), path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = _fileSystem.GetEntryType(out entryType, in pathNormalized);
|
||||
rc = _fileSystem.Get.GetEntryType(out entryType, in pathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
@ -311,7 +306,7 @@ namespace LibHac.Fs.Impl
|
||||
Result rc = SetUpPath(ref pathNormalized.Ref(), path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = _fileSystem.GetFreeSpaceSize(out freeSpace, in pathNormalized);
|
||||
rc = _fileSystem.Get.GetFreeSpaceSize(out freeSpace, in pathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
@ -325,7 +320,7 @@ namespace LibHac.Fs.Impl
|
||||
Result rc = SetUpPath(ref pathNormalized.Ref(), path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = _fileSystem.GetTotalSpaceSize(out totalSpace, in pathNormalized);
|
||||
rc = _fileSystem.Get.GetTotalSpaceSize(out totalSpace, in pathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
@ -338,7 +333,7 @@ namespace LibHac.Fs.Impl
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
using var file = new UniqueRef<IFile>();
|
||||
rc = _fileSystem.OpenFile(ref file.Ref(), in pathNormalized, mode);
|
||||
rc = _fileSystem.Get.OpenFile(ref file.Ref(), in pathNormalized, mode);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
var accessor = new FileAccessor(Hos, ref file.Ref(), this, mode);
|
||||
@ -371,7 +366,7 @@ namespace LibHac.Fs.Impl
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
using var directory = new UniqueRef<IDirectory>();
|
||||
rc = _fileSystem.OpenDirectory(ref directory.Ref(), in pathNormalized, mode);
|
||||
rc = _fileSystem.Get.OpenDirectory(ref directory.Ref(), in pathNormalized, mode);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
var accessor = new DirectoryAccessor(ref directory.Ref(), this);
|
||||
@ -408,7 +403,7 @@ namespace LibHac.Fs.Impl
|
||||
return ResultFs.WriteModeFileNotClosed.Log();
|
||||
}
|
||||
|
||||
return _fileSystem.Commit();
|
||||
return _fileSystem.Get.Commit();
|
||||
}
|
||||
|
||||
public Result GetFileTimeStampRaw(out FileTimeStampRaw timeStamp, U8Span path)
|
||||
@ -419,7 +414,7 @@ namespace LibHac.Fs.Impl
|
||||
Result rc = SetUpPath(ref pathNormalized.Ref(), path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = _fileSystem.GetFileTimeStampRaw(out timeStamp, in pathNormalized);
|
||||
rc = _fileSystem.Get.GetFileTimeStampRaw(out timeStamp, in pathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
@ -431,7 +426,7 @@ namespace LibHac.Fs.Impl
|
||||
Result rc = SetUpPath(ref pathNormalized.Ref(), path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = _fileSystem.QueryEntry(outBuffer, inBuffer, queryId, in pathNormalized);
|
||||
rc = _fileSystem.Get.QueryEntry(outBuffer, inBuffer, queryId, in pathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
@ -444,44 +439,51 @@ namespace LibHac.Fs.Impl
|
||||
|
||||
public Result GetCommonMountName(Span<byte> nameBuffer)
|
||||
{
|
||||
if (_mountNameGenerator is null)
|
||||
if (!_mountNameGenerator.HasValue)
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return _mountNameGenerator.GenerateCommonMountName(nameBuffer);
|
||||
return _mountNameGenerator.Get.GenerateCommonMountName(nameBuffer);
|
||||
}
|
||||
|
||||
public Result GetSaveDataAttribute(out SaveDataAttribute attribute)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out attribute);
|
||||
|
||||
if (_saveDataAttributeGetter is null)
|
||||
if (!_saveDataAttributeGetter.HasValue)
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
Result rc = _saveDataAttributeGetter.GetSaveDataAttribute(out attribute);
|
||||
Result rc = _saveDataAttributeGetter.Get.GetSaveDataAttribute(out attribute);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public ReferenceCountedDisposable<IFileSystemSf> GetMultiCommitTarget()
|
||||
public SharedRef<IFileSystemSf> GetMultiCommitTarget()
|
||||
{
|
||||
return _multiCommitTarget?.GetMultiCommitTarget();
|
||||
if (_multiCommitTarget is not null)
|
||||
{
|
||||
return _multiCommitTarget.GetMultiCommitTarget();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new SharedRef<IFileSystemSf>();
|
||||
}
|
||||
}
|
||||
|
||||
public void PurgeFileDataCache(FileDataCacheAccessor cacheAccessor)
|
||||
{
|
||||
cacheAccessor.Purge(_fileSystem);
|
||||
cacheAccessor.Purge(_fileSystem.Get);
|
||||
}
|
||||
|
||||
internal void NotifyCloseFile(FileAccessor file)
|
||||
{
|
||||
using ScopedLock<SdkMutexType> lk = ScopedLock.Lock(ref _openListLock);
|
||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _openListLock);
|
||||
Remove(_openFiles, file);
|
||||
}
|
||||
|
||||
internal void NotifyCloseDirectory(DirectoryAccessor directory)
|
||||
{
|
||||
using ScopedLock<SdkMutexType> lk = ScopedLock.Lock(ref _openListLock);
|
||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _openListLock);
|
||||
Remove(_openDirectories, directory);
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
|
||||
using LibHac.Common;
|
||||
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
|
||||
|
||||
namespace LibHac.Fs.Fsa
|
||||
{
|
||||
public interface IMultiCommitTarget
|
||||
{
|
||||
ReferenceCountedDisposable<IFileSystemSf> GetMultiCommitTarget();
|
||||
SharedRef<IFileSystemSf> GetMultiCommitTarget();
|
||||
}
|
||||
}
|
||||
|
@ -1,40 +1,77 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Diag;
|
||||
using LibHac.Ncm;
|
||||
using LibHac.Os;
|
||||
using LibHac.Util;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace LibHac.Fs.Impl
|
||||
{
|
||||
internal class MountTable
|
||||
/// <summary>
|
||||
/// Holds a list of <see cref="FileSystemAccessor"/>s that are indexed by their name.
|
||||
/// These may be retrieved or removed using their name as a key.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
internal class MountTable : IDisposable
|
||||
{
|
||||
private LinkedList<FileSystemAccessor> _fileSystemList;
|
||||
private SdkMutexType _mutex;
|
||||
|
||||
// LibHac addition
|
||||
private FileSystemClient _fsClient;
|
||||
|
||||
public MountTable(FileSystemClient fsClient)
|
||||
{
|
||||
_fileSystemList = new LinkedList<FileSystemAccessor>();
|
||||
_mutex = new SdkMutexType();
|
||||
_mutex.Initialize();
|
||||
|
||||
_fsClient = fsClient;
|
||||
}
|
||||
|
||||
public Result Mount(FileSystemAccessor fileSystem)
|
||||
// Note: The original class does not have a destructor
|
||||
public void Dispose()
|
||||
{
|
||||
using ScopedLock<SdkMutexType> lk = ScopedLock.Lock(ref _mutex);
|
||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
if (!CanAcceptMountName(fileSystem.GetName()))
|
||||
LinkedListNode<FileSystemAccessor> currentEntry = _fileSystemList.First;
|
||||
|
||||
while (currentEntry is not null)
|
||||
{
|
||||
FileSystemAccessor accessor = currentEntry.Value;
|
||||
_fileSystemList.Remove(currentEntry);
|
||||
accessor?.Dispose();
|
||||
|
||||
currentEntry = _fileSystemList.First;
|
||||
}
|
||||
|
||||
_fileSystemList = null;
|
||||
_fsClient = null;
|
||||
}
|
||||
|
||||
private static bool Matches(FileSystemAccessor accessor, U8Span name)
|
||||
{
|
||||
return StringUtils.Compare(accessor.GetName(), name, Unsafe.SizeOf<MountName>()) == 0;
|
||||
}
|
||||
|
||||
public Result Mount(ref UniqueRef<FileSystemAccessor> fileSystem)
|
||||
{
|
||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
if (!CanAcceptMountName(fileSystem.Get.GetName()))
|
||||
return ResultFs.MountNameAlreadyExists.Log();
|
||||
|
||||
_fileSystemList.AddLast(fileSystem);
|
||||
_fileSystemList.AddLast(fileSystem.Release());
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result Find(out FileSystemAccessor accessor, U8Span name)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out accessor);
|
||||
using ScopedLock<SdkMutexType> lk = ScopedLock.Lock(ref _mutex);
|
||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
for (LinkedListNode<FileSystemAccessor> currentNode = _fileSystemList.First;
|
||||
currentNode is not null;
|
||||
@ -50,23 +87,28 @@ namespace LibHac.Fs.Impl
|
||||
|
||||
public void Unmount(U8Span name)
|
||||
{
|
||||
using ScopedLock<SdkMutexType> lk = ScopedLock.Lock(ref _mutex);
|
||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
LinkedListNode<FileSystemAccessor> currentNode;
|
||||
for (currentNode = _fileSystemList.First; currentNode is not null; currentNode = currentNode.Next)
|
||||
for (LinkedListNode<FileSystemAccessor> currentNode = _fileSystemList.First;
|
||||
currentNode is not null;
|
||||
currentNode = currentNode.Next)
|
||||
{
|
||||
if (Matches(currentNode.Value, name))
|
||||
break;
|
||||
{
|
||||
_fileSystemList.Remove(currentNode);
|
||||
currentNode.Value.Dispose();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentNode is null)
|
||||
Abort.DoAbort(ResultFs.NotMounted.Log(), $"{name.ToString()} is not mounted.");
|
||||
_fsClient.Impl.LogErrorMessage(ResultFs.NotMounted.Value,
|
||||
"Error: Unmount failed because the mount name was not mounted. The mount name is \"{0}\".\n",
|
||||
name.ToString());
|
||||
|
||||
_fileSystemList.Remove(currentNode);
|
||||
currentNode.Value.Dispose();
|
||||
Abort.DoAbortUnlessSuccess(ResultFs.NotMounted.Value);
|
||||
}
|
||||
|
||||
public bool CanAcceptMountName(U8Span name)
|
||||
private bool CanAcceptMountName(U8Span name)
|
||||
{
|
||||
Assert.SdkAssert(_mutex.IsLockedByCurrentThread());
|
||||
|
||||
@ -81,9 +123,44 @@ namespace LibHac.Fs.Impl
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool Matches(FileSystemAccessor accessor, U8Span name)
|
||||
public int GetDataIdCount()
|
||||
{
|
||||
return StringUtils.Compare(accessor.GetName(), name, Unsafe.SizeOf<MountName>()) == 0;
|
||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (LinkedListNode<FileSystemAccessor> currentNode = _fileSystemList.First;
|
||||
currentNode is not null;
|
||||
currentNode = currentNode.Next)
|
||||
{
|
||||
if (currentNode.Value.GetDataId().HasValue)
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public Result ListDataId(out int dataIdCount, Span<DataId> dataIdBuffer)
|
||||
{
|
||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (LinkedListNode<FileSystemAccessor> currentNode = _fileSystemList.First;
|
||||
currentNode is not null && count < dataIdBuffer.Length;
|
||||
currentNode = currentNode.Next)
|
||||
{
|
||||
Optional<DataId> dataId = currentNode.Value.GetDataId();
|
||||
|
||||
if (dataId.HasValue)
|
||||
{
|
||||
dataIdBuffer[count] = dataId.Value;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
dataIdCount = count;
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Impl;
|
||||
using LibHac.Util;
|
||||
|
||||
namespace LibHac.Fs.Fsa
|
||||
{
|
||||
@ -14,42 +15,94 @@ namespace LibHac.Fs.Fsa
|
||||
Result GetSaveDataAttribute(out SaveDataAttribute attribute);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains functions for registering and unregistering mounted <see cref="IFileSystem"/>s.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
public static class Registrar
|
||||
{
|
||||
public static Result Register(this FileSystemClient fs, U8Span name, IFileSystem fileSystem)
|
||||
public static Result Register(this FileSystemClient fs, U8Span name, ref UniqueRef<IFileSystem> fileSystem)
|
||||
{
|
||||
var accessor = new FileSystemAccessor(fs.Hos, name, null, fileSystem, null, null);
|
||||
fs.Impl.Register(accessor);
|
||||
using var attributeGetter = new UniqueRef<ISaveDataAttributeGetter>();
|
||||
using var mountNameGenerator = new UniqueRef<ICommonMountNameGenerator>();
|
||||
|
||||
using var accessor = new UniqueRef<FileSystemAccessor>(new FileSystemAccessor(fs.Hos, name, null,
|
||||
ref fileSystem, ref mountNameGenerator.Ref(), ref attributeGetter.Ref()));
|
||||
|
||||
Result rc = fs.Impl.Register(ref accessor.Ref());
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result Register(this FileSystemClient fs, U8Span name, IFileSystem fileSystem,
|
||||
ICommonMountNameGenerator mountNameGenerator)
|
||||
public static Result Register(this FileSystemClient fs, U8Span name, ref UniqueRef<IFileSystem> fileSystem,
|
||||
ref UniqueRef<ICommonMountNameGenerator> mountNameGenerator)
|
||||
{
|
||||
var accessor = new FileSystemAccessor(fs.Hos, name, null, fileSystem, mountNameGenerator, null);
|
||||
fs.Impl.Register(accessor);
|
||||
using var attributeGetter = new UniqueRef<ISaveDataAttributeGetter>();
|
||||
|
||||
using var accessor = new UniqueRef<FileSystemAccessor>(new FileSystemAccessor(fs.Hos, name, null,
|
||||
ref fileSystem, ref mountNameGenerator, ref attributeGetter.Ref()));
|
||||
|
||||
Result rc = fs.Impl.Register(ref accessor.Ref());
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result Register(this FileSystemClient fs, U8Span name, IMultiCommitTarget multiCommitTarget,
|
||||
IFileSystem fileSystem, ICommonMountNameGenerator mountNameGenerator, bool useDataCache, bool usePathCache)
|
||||
ref UniqueRef<IFileSystem> fileSystem, ref UniqueRef<ICommonMountNameGenerator> mountNameGenerator,
|
||||
bool useDataCache, bool usePathCache)
|
||||
{
|
||||
return fs.Register(name, multiCommitTarget, fileSystem, mountNameGenerator, null, useDataCache,
|
||||
usePathCache);
|
||||
using var attributeGetter = new UniqueRef<ISaveDataAttributeGetter>();
|
||||
|
||||
Result rc = Register(fs, name, multiCommitTarget, ref fileSystem, ref mountNameGenerator,
|
||||
ref attributeGetter.Ref(), useDataCache, usePathCache, new Optional<Ncm.DataId>());
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result Register(this FileSystemClient fs, U8Span name, IMultiCommitTarget multiCommitTarget,
|
||||
IFileSystem fileSystem, ICommonMountNameGenerator mountNameGenerator,
|
||||
ISaveDataAttributeGetter saveAttributeGetter, bool useDataCache, bool usePathCache)
|
||||
ref UniqueRef<IFileSystem> fileSystem, ref UniqueRef<ICommonMountNameGenerator> mountNameGenerator,
|
||||
bool useDataCache, bool usePathCache, Optional<Ncm.DataId> dataId)
|
||||
{
|
||||
var accessor = new FileSystemAccessor(fs.Hos, name, multiCommitTarget, fileSystem, mountNameGenerator,
|
||||
saveAttributeGetter);
|
||||
using var attributeGetter = new UniqueRef<ISaveDataAttributeGetter>();
|
||||
|
||||
accessor.SetFileDataCacheAttachable(useDataCache);
|
||||
accessor.SetPathBasedFileDataCacheAttachable(usePathCache);
|
||||
fs.Impl.Register(accessor);
|
||||
Result rc = Register(fs, name, multiCommitTarget, ref fileSystem, ref mountNameGenerator,
|
||||
ref attributeGetter.Ref(), useDataCache, usePathCache, dataId);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result Register(this FileSystemClient fs, U8Span name, IMultiCommitTarget multiCommitTarget,
|
||||
ref UniqueRef<IFileSystem> fileSystem, ref UniqueRef<ICommonMountNameGenerator> mountNameGenerator,
|
||||
ref UniqueRef<ISaveDataAttributeGetter> saveAttributeGetter, bool useDataCache, bool usePathCache)
|
||||
{
|
||||
Result rc = Register(fs, name, multiCommitTarget, ref fileSystem, ref mountNameGenerator,
|
||||
ref saveAttributeGetter, useDataCache, usePathCache, new Optional<Ncm.DataId>());
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result Register(this FileSystemClient fs, U8Span name, IMultiCommitTarget multiCommitTarget,
|
||||
ref UniqueRef<IFileSystem> fileSystem, ref UniqueRef<ICommonMountNameGenerator> mountNameGenerator,
|
||||
ref UniqueRef<ISaveDataAttributeGetter> saveAttributeGetter, bool useDataCache, bool usePathCache,
|
||||
Optional<Ncm.DataId> dataId)
|
||||
{
|
||||
using var accessor = new UniqueRef<FileSystemAccessor>(new FileSystemAccessor(fs.Hos, name,
|
||||
multiCommitTarget, ref fileSystem, ref mountNameGenerator, ref saveAttributeGetter));
|
||||
|
||||
if (!accessor.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInRegisterB.Log();
|
||||
|
||||
accessor.Get.SetFileDataCacheAttachable(useDataCache);
|
||||
accessor.Get.SetPathBasedFileDataCacheAttachable(usePathCache);
|
||||
accessor.Get.SetDataId(dataId);
|
||||
|
||||
Result rc = fs.Impl.Register(ref accessor.Ref());
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
@ -60,4 +113,3 @@ namespace LibHac.Fs.Fsa
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -638,38 +638,29 @@ namespace LibHac.Fs.Fsa
|
||||
if (mountNames.Length == 0)
|
||||
return Result.Success;
|
||||
|
||||
ReferenceCountedDisposable<IMultiCommitManager> commitManager = null;
|
||||
ReferenceCountedDisposable<IFileSystemSf> fileSystem = null;
|
||||
try
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using var commitManager = new SharedRef<IMultiCommitManager>();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.OpenMultiCommitManager(out commitManager);
|
||||
Result rc = fileSystemProxy.Get.OpenMultiCommitManager(ref commitManager.Ref());
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
for (int i = 0; i < mountNames.Length; i++)
|
||||
{
|
||||
rc = fs.Impl.Find(out FileSystemAccessor accessor, mountNames[i]);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
for (int i = 0; i < mountNames.Length; i++)
|
||||
{
|
||||
rc = fs.Impl.Find(out FileSystemAccessor accessor, mountNames[i]);
|
||||
if (rc.IsFailure()) return rc;
|
||||
using SharedRef<IFileSystemSf> fileSystem = accessor.GetMultiCommitTarget();
|
||||
if (!fileSystem.HasValue)
|
||||
return ResultFs.UnsupportedCommitTarget.Log();
|
||||
|
||||
fileSystem = accessor.GetMultiCommitTarget();
|
||||
if (fileSystem is null)
|
||||
return ResultFs.UnsupportedCommitTarget.Log();
|
||||
|
||||
rc = commitManager.Target.Add(fileSystem);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
|
||||
rc = commitManager.Target.Commit();
|
||||
rc = commitManager.Get.Add(ref fileSystem.Ref());
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
commitManager?.Dispose();
|
||||
fileSystem?.Dispose();
|
||||
}
|
||||
rc = commitManager.Get.Commit();
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result Commit(this FileSystemClient fs, U8Span mountName, CommitOption option)
|
||||
|
@ -1,5 +1,7 @@
|
||||
using LibHac.Common;
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Impl;
|
||||
using LibHac.Ncm;
|
||||
|
||||
namespace LibHac.Fs.Fsa
|
||||
{
|
||||
@ -13,11 +15,15 @@ namespace LibHac.Fs.Fsa
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains functions for adding, removing and retrieving <see cref="FileSystemAccessor"/>s from the mount table.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
internal static class UserMountTable
|
||||
{
|
||||
public static Result Register(this FileSystemClientImpl fs, FileSystemAccessor fileSystem)
|
||||
public static Result Register(this FileSystemClientImpl fs, ref UniqueRef<FileSystemAccessor> fileSystem)
|
||||
{
|
||||
return fs.Globals.UserMountTable.MountTable.Mount(fileSystem);
|
||||
return fs.Globals.UserMountTable.MountTable.Mount(ref fileSystem);
|
||||
}
|
||||
|
||||
public static Result Find(this FileSystemClientImpl fs, out FileSystemAccessor fileSystem, U8Span name)
|
||||
@ -29,5 +35,16 @@ namespace LibHac.Fs.Fsa
|
||||
{
|
||||
fs.Globals.UserMountTable.MountTable.Unmount(name);
|
||||
}
|
||||
|
||||
public static int GetMountedDataIdCount(this FileSystemClientImpl fs)
|
||||
{
|
||||
return fs.Globals.UserMountTable.MountTable.GetDataIdCount();
|
||||
}
|
||||
|
||||
public static Result ListMountedDataId(this FileSystemClientImpl fs, out int dataIdCount,
|
||||
Span<DataId> dataIdBuffer)
|
||||
{
|
||||
return fs.Globals.UserMountTable.MountTable.ListDataId(out dataIdCount, dataIdBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using LibHac.Common;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
@ -16,10 +14,6 @@ namespace LibHac.Fs
|
||||
/// </remarks>
|
||||
public abstract class IStorage : IDisposable
|
||||
{
|
||||
// 0 = not disposed; 1 = disposed
|
||||
private int _disposedState;
|
||||
private bool IsDisposed => _disposedState != 0;
|
||||
|
||||
/// <summary>
|
||||
/// Reads a sequence of bytes from the current <see cref="IStorage"/>.
|
||||
/// </summary>
|
||||
@ -30,9 +24,6 @@ namespace LibHac.Fs
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Result Read(long offset, Span<byte> destination)
|
||||
{
|
||||
if (IsDisposed)
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return DoRead(offset, destination);
|
||||
}
|
||||
|
||||
@ -45,9 +36,6 @@ namespace LibHac.Fs
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Result Write(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
if (IsDisposed)
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return DoWrite(offset, source);
|
||||
}
|
||||
|
||||
@ -58,9 +46,6 @@ namespace LibHac.Fs
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Result Flush()
|
||||
{
|
||||
if (IsDisposed)
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return DoFlush();
|
||||
}
|
||||
|
||||
@ -71,9 +56,6 @@ namespace LibHac.Fs
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Result SetSize(long size)
|
||||
{
|
||||
if (IsDisposed)
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return DoSetSize(size);
|
||||
}
|
||||
|
||||
@ -85,11 +67,6 @@ namespace LibHac.Fs
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Result GetSize(out long size)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out size);
|
||||
|
||||
if (IsDisposed)
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return DoGetSize(out size);
|
||||
}
|
||||
|
||||
@ -106,14 +83,11 @@ namespace LibHac.Fs
|
||||
public Result OperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size,
|
||||
ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
if (IsDisposed)
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return DoOperateRange(outBuffer, operationId, offset, size, inBuffer);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsRangeValid(long offset, long size, long totalSize)
|
||||
public static bool CheckAccessRange(long offset, long size, long totalSize)
|
||||
{
|
||||
return offset >= 0 &&
|
||||
size >= 0 &&
|
||||
@ -122,13 +96,14 @@ namespace LibHac.Fs
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsOffsetAndSizeValid(long offset, long size)
|
||||
public static bool CheckOffsetAndSize(long offset, long size)
|
||||
{
|
||||
return offset >= 0 &&
|
||||
size >= 0 &&
|
||||
offset <= offset + size;
|
||||
}
|
||||
|
||||
// Todo: Remove Do* methods
|
||||
protected abstract Result DoRead(long offset, Span<byte> destination);
|
||||
protected abstract Result DoWrite(long offset, ReadOnlySpan<byte> source);
|
||||
protected abstract Result DoFlush();
|
||||
@ -141,16 +116,6 @@ namespace LibHac.Fs
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// Make sure Dispose is only called once
|
||||
if (Interlocked.CompareExchange(ref _disposedState, 1, 0) == 0)
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing) { }
|
||||
public virtual void Dispose() { }
|
||||
}
|
||||
}
|
||||
|
@ -10,49 +10,39 @@ namespace LibHac.Fs.Impl
|
||||
/// An adapter for using an <see cref="IStorageSf"/> service object as an <see cref="IStorage"/>. Used
|
||||
/// when receiving a Horizon IPC storage object so it can be used as an <see cref="IStorage"/> locally.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
internal class StorageServiceObjectAdapter : IStorage
|
||||
{
|
||||
private ReferenceCountedDisposable<IStorageSf> BaseStorage { get; }
|
||||
private SharedRef<IStorageSf> _baseStorage;
|
||||
|
||||
public StorageServiceObjectAdapter(ReferenceCountedDisposable<IStorageSf> baseStorage)
|
||||
public StorageServiceObjectAdapter(ref SharedRef<IStorageSf> baseStorage)
|
||||
{
|
||||
BaseStorage = baseStorage.AddReference();
|
||||
}
|
||||
|
||||
protected StorageServiceObjectAdapter(ref ReferenceCountedDisposable<IStorageSf> baseStorage)
|
||||
{
|
||||
BaseStorage = Shared.Move(ref baseStorage);
|
||||
}
|
||||
|
||||
public static ReferenceCountedDisposable<IStorage> CreateShared(
|
||||
ref ReferenceCountedDisposable<IStorageSf> baseStorage)
|
||||
{
|
||||
return new ReferenceCountedDisposable<IStorage>(new StorageServiceObjectAdapter(ref baseStorage));
|
||||
_baseStorage = SharedRef<IStorageSf>.CreateMove(ref baseStorage);
|
||||
}
|
||||
|
||||
protected override Result DoRead(long offset, Span<byte> destination)
|
||||
{
|
||||
return BaseStorage.Target.Read(offset, new OutBuffer(destination), destination.Length);
|
||||
return _baseStorage.Get.Read(offset, new OutBuffer(destination), destination.Length);
|
||||
}
|
||||
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
return BaseStorage.Target.Write(offset, new InBuffer(source), source.Length);
|
||||
return _baseStorage.Get.Write(offset, new InBuffer(source), source.Length);
|
||||
}
|
||||
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return BaseStorage.Target.Flush();
|
||||
return _baseStorage.Get.Flush();
|
||||
}
|
||||
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
return BaseStorage.Target.SetSize(size);
|
||||
return _baseStorage.Get.SetSize(size);
|
||||
}
|
||||
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
return BaseStorage.Target.GetSize(out size);
|
||||
return _baseStorage.Get.GetSize(out size);
|
||||
}
|
||||
|
||||
protected override Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size,
|
||||
@ -61,27 +51,23 @@ namespace LibHac.Fs.Impl
|
||||
switch (operationId)
|
||||
{
|
||||
case OperationId.InvalidateCache:
|
||||
return BaseStorage.Target.OperateRange(out _, (int)OperationId.InvalidateCache, offset, size);
|
||||
return _baseStorage.Get.OperateRange(out _, (int)OperationId.InvalidateCache, offset, size);
|
||||
case OperationId.QueryRange:
|
||||
if (outBuffer.Length != Unsafe.SizeOf<QueryRangeInfo>())
|
||||
return ResultFs.InvalidSize.Log();
|
||||
|
||||
ref QueryRangeInfo info = ref SpanHelpers.AsStruct<QueryRangeInfo>(outBuffer);
|
||||
|
||||
return BaseStorage.Target.OperateRange(out info, (int)OperationId.QueryRange, offset, size);
|
||||
return _baseStorage.Get.OperateRange(out info, (int)OperationId.QueryRange, offset, size);
|
||||
default:
|
||||
return ResultFs.UnsupportedOperateRangeForFileServiceObjectAdapter.Log();
|
||||
return ResultFs.UnsupportedOperateRangeForStorageServiceObjectAdapter.Log();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
public override void Dispose()
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
BaseStorage?.Dispose();
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
_baseStorage.Destroy();
|
||||
base.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@ namespace LibHac.Fs
|
||||
if (destination.Length == 0)
|
||||
return Result.Success;
|
||||
|
||||
if (!IsRangeValid(offset, destination.Length, StorageBuffer.Length))
|
||||
if (!CheckAccessRange(offset, destination.Length, StorageBuffer.Length))
|
||||
return ResultFs.OutOfRange.Log();
|
||||
|
||||
StorageBuffer.AsSpan((int)offset, destination.Length).CopyTo(destination);
|
||||
@ -29,7 +29,7 @@ namespace LibHac.Fs
|
||||
if (source.Length == 0)
|
||||
return Result.Success;
|
||||
|
||||
if (!IsRangeValid(offset, source.Length, StorageBuffer.Length))
|
||||
if (!CheckAccessRange(offset, source.Length, StorageBuffer.Length))
|
||||
return ResultFs.OutOfRange.Log();
|
||||
|
||||
source.CopyTo(StorageBuffer.AsSpan((int)offset));
|
||||
|
@ -6,10 +6,15 @@ using LibHac.Fs.Impl;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.Os;
|
||||
using static LibHac.Fs.Impl.AccessLogStrings;
|
||||
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
|
||||
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
|
||||
|
||||
namespace LibHac.Fs.Shim
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains functions for mounting application packages.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
[SkipLocalsInit]
|
||||
public static class Application
|
||||
{
|
||||
@ -35,6 +40,7 @@ namespace LibHac.Fs.Shim
|
||||
{
|
||||
rc = Mount(fs, mountName, path);
|
||||
}
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
@ -48,25 +54,26 @@ namespace LibHac.Fs.Shim
|
||||
Result rc = fs.Impl.CheckMountName(mountName);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = FspPath.FromSpan(out FspPath sfPath, path);
|
||||
rc = PathUtility.ConvertToFspPath(out FspPath sfPath, path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using var fileSystem = new SharedRef<IFileSystemSf>();
|
||||
|
||||
ReferenceCountedDisposable<IFileSystemSf> fileSystem = null;
|
||||
try
|
||||
{
|
||||
rc = fsProxy.Target.OpenFileSystemWithId(out fileSystem, in sfPath, Ncm.ProgramId.InvalidId.Value,
|
||||
FileSystemProxyType.Package);
|
||||
if (rc.IsFailure()) return rc;
|
||||
rc = fileSystemProxy.Get.OpenFileSystemWithId(ref fileSystem.Ref(), in sfPath,
|
||||
Ncm.ProgramId.InvalidId.Value, FileSystemProxyType.Package);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
var fileSystemAdapter = new FileSystemServiceObjectAdapter(fileSystem);
|
||||
return fs.Register(mountName, fileSystemAdapter);
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileSystem?.Dispose();
|
||||
}
|
||||
using var fileSystemAdapter =
|
||||
new UniqueRef<IFileSystem>(new FileSystemServiceObjectAdapter(ref fileSystem.Ref()));
|
||||
|
||||
if (!fileSystemAdapter.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInApplicationA.Log();
|
||||
|
||||
rc = fs.Register(mountName, ref fileSystemAdapter.Ref());
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,10 +6,15 @@ using LibHac.Fs.Impl;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.Os;
|
||||
using static LibHac.Fs.Impl.AccessLogStrings;
|
||||
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
|
||||
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
|
||||
|
||||
namespace LibHac.Fs.Shim
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains functions for mounting BCAT save data.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
[SkipLocalsInit]
|
||||
public static class BcatSaveData
|
||||
{
|
||||
@ -36,6 +41,7 @@ namespace LibHac.Fs.Shim
|
||||
{
|
||||
rc = Mount(fs, mountName, applicationId);
|
||||
}
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
@ -49,25 +55,27 @@ namespace LibHac.Fs.Shim
|
||||
Result rc = fs.Impl.CheckMountName(mountName);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Bcat,
|
||||
Fs.SaveData.InvalidUserId, 0);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
ReferenceCountedDisposable<IFileSystemSf> fileSystem = null;
|
||||
try
|
||||
{
|
||||
rc = fsProxy.Target.OpenSaveDataFileSystem(out fileSystem, SaveDataSpaceId.User, in attribute);
|
||||
if (rc.IsFailure()) return rc;
|
||||
using var fileSystem = new SharedRef<IFileSystemSf>();
|
||||
|
||||
var fileSystemAdapter = new FileSystemServiceObjectAdapter(fileSystem);
|
||||
return fs.Register(mountName, fileSystemAdapter);
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileSystem?.Dispose();
|
||||
}
|
||||
rc = fileSystemProxy.Get.OpenSaveDataFileSystem(ref fileSystem.Ref(), SaveDataSpaceId.User, in attribute);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
using var fileSystemAdapter =
|
||||
new UniqueRef<IFileSystem>(new FileSystemServiceObjectAdapter(ref fileSystem.Ref()));
|
||||
|
||||
if (!fileSystemAdapter.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInBcatSaveDataA.Log();
|
||||
|
||||
rc = fs.Register(mountName, ref fileSystemAdapter.Ref());
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,49 +1,53 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Diag;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.Fs.Impl;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.Os;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.Util;
|
||||
using static LibHac.Fs.Impl.CommonMountNames;
|
||||
using static LibHac.Fs.Impl.AccessLogStrings;
|
||||
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
|
||||
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
|
||||
using IStorageSf = LibHac.FsSrv.Sf.IStorage;
|
||||
|
||||
namespace LibHac.Fs.Shim
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains functions for mounting built-in-storage partition file systems
|
||||
/// and opening the raw partitions as <see cref="IStorage"/>s.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
[SkipLocalsInit]
|
||||
public static class Bis
|
||||
{
|
||||
private class BisCommonMountNameGenerator : ICommonMountNameGenerator
|
||||
{
|
||||
private BisPartitionId PartitionId { get; }
|
||||
private BisPartitionId _partitionId;
|
||||
|
||||
public BisCommonMountNameGenerator(BisPartitionId partitionId)
|
||||
{
|
||||
PartitionId = partitionId;
|
||||
_partitionId = partitionId;
|
||||
}
|
||||
|
||||
public void Dispose() { }
|
||||
|
||||
public Result GenerateCommonMountName(Span<byte> nameBuffer)
|
||||
{
|
||||
ReadOnlySpan<byte> mountName = GetBisMountName(PartitionId);
|
||||
ReadOnlySpan<byte> mountName = GetBisMountName(_partitionId);
|
||||
|
||||
// Add 2 for the mount name separator and null terminator
|
||||
// ReSharper disable once RedundantAssignment
|
||||
int requiredNameBufferSize = StringUtils.GetLength(mountName, PathTools.MountNameLengthMax) + 2;
|
||||
|
||||
Debug.Assert(nameBuffer.Length >= requiredNameBufferSize);
|
||||
Assert.SdkRequiresGreaterEqual(nameBuffer.Length, requiredNameBufferSize);
|
||||
|
||||
var sb = new U8StringBuilder(nameBuffer);
|
||||
sb.Append(mountName).Append(StringTraits.DriveSeparator);
|
||||
|
||||
Debug.Assert(sb.Length == requiredNameBufferSize - 1);
|
||||
Assert.SdkEqual(sb.Length, requiredNameBufferSize - 1);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
@ -86,28 +90,34 @@ namespace LibHac.Fs.Shim
|
||||
static Result Mount(FileSystemClientImpl fs, U8Span mountName, BisPartitionId partitionId)
|
||||
{
|
||||
Result rc = fs.CheckMountNameAcceptingReservedMountName(mountName);
|
||||
if (rc.IsFailure()) return rc;
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
|
||||
// Nintendo doesn't use the provided rootPath
|
||||
FspPath.CreateEmpty(out FspPath sfPath);
|
||||
|
||||
ReferenceCountedDisposable<IFileSystemSf> fileSystem = null;
|
||||
try
|
||||
{
|
||||
rc = fsProxy.Target.OpenBisFileSystem(out fileSystem, in sfPath, partitionId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
using var fileSystem = new SharedRef<IFileSystemSf>();
|
||||
|
||||
var nameGenerator = new BisCommonMountNameGenerator(partitionId);
|
||||
var fileSystemAdapter = new FileSystemServiceObjectAdapter(fileSystem);
|
||||
rc = fileSystemProxy.Get.OpenBisFileSystem(ref fileSystem.Ref(), in sfPath, partitionId);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return fs.Fs.Register(mountName, fileSystemAdapter, nameGenerator);
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileSystem?.Dispose();
|
||||
}
|
||||
using var mountNameGenerator =
|
||||
new UniqueRef<ICommonMountNameGenerator>(new BisCommonMountNameGenerator(partitionId));
|
||||
|
||||
if (!mountNameGenerator.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInBisA.Log();
|
||||
|
||||
using var fileSystemAdapter =
|
||||
new UniqueRef<IFileSystem>(new FileSystemServiceObjectAdapter(ref fileSystem.Ref()));
|
||||
|
||||
if (!fileSystemAdapter.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInBisB.Log();
|
||||
|
||||
rc = fs.Fs.Register(mountName, ref fileSystemAdapter.Ref(), ref mountNameGenerator.Ref());
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,75 +165,34 @@ namespace LibHac.Fs.Shim
|
||||
return ReadOnlySpan<byte>.Empty;
|
||||
}
|
||||
|
||||
public static Result SetBisRootForHost(this FileSystemClient fs, BisPartitionId partitionId, U8Span rootPath)
|
||||
{
|
||||
Unsafe.SkipInit(out FsPath pathBuffer);
|
||||
Result rc;
|
||||
|
||||
int pathLen = StringUtils.GetLength(rootPath, PathTools.MaxPathLength + 1);
|
||||
if (pathLen > PathTools.MaxPathLength)
|
||||
{
|
||||
fs.Impl.LogResultErrorMessage(ResultFs.TooLongPath.Value);
|
||||
return ResultFs.TooLongPath.Log();
|
||||
}
|
||||
|
||||
if (pathLen > 0)
|
||||
{
|
||||
byte endingSeparator = rootPath[pathLen - 1] == StringTraits.DirectorySeparator
|
||||
? StringTraits.NullTerminator
|
||||
: StringTraits.DirectorySeparator;
|
||||
|
||||
var sb = new U8StringBuilder(pathBuffer.Str);
|
||||
sb.Append(rootPath).Append(endingSeparator);
|
||||
|
||||
if (sb.Overflowed)
|
||||
return ResultFs.TooLongPath.Log();
|
||||
}
|
||||
else
|
||||
{
|
||||
pathBuffer.Str[0] = StringTraits.NullTerminator;
|
||||
}
|
||||
|
||||
rc = PathUtility.ConvertToFspPath(out FspPath sfPath, pathBuffer.Str);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
rc = fsProxy.Target.SetBisRootForHost(partitionId, in sfPath);
|
||||
fs.Impl.LogResultErrorMessage(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
public static Result OpenBisPartition(this FileSystemClient fs, out IStorage partitionStorage,
|
||||
public static Result OpenBisPartition(this FileSystemClient fs, ref UniqueRef<IStorage> outPartitionStorage,
|
||||
BisPartitionId partitionId)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out partitionStorage);
|
||||
using var storage = new SharedRef<IStorageSf>();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
ReferenceCountedDisposable<IStorageSf> storage = null;
|
||||
try
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
Result rc = fsProxy.Target.OpenBisStorage(out storage, partitionId);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
Result rc = fileSystemProxy.Get.OpenBisStorage(ref storage.Ref(), partitionId);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
var storageAdapter = new StorageServiceObjectAdapter(storage);
|
||||
var storageAdapter = new UniqueRef<IStorage>(new StorageServiceObjectAdapter(ref storage.Ref()));
|
||||
|
||||
partitionStorage = storageAdapter;
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
storage?.Dispose();
|
||||
}
|
||||
if (!storageAdapter.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInBisC.Log();
|
||||
|
||||
outPartitionStorage.Set(ref storageAdapter.Ref());
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result InvalidateBisCache(this FileSystemClient fs)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
Result rc = fsProxy.Target.InvalidateBisCache();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fileSystemProxy.Get.InvalidateBisCache();
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,10 +7,15 @@ using LibHac.FsSrv.Sf;
|
||||
using LibHac.Ncm;
|
||||
using LibHac.Os;
|
||||
using static LibHac.Fs.Impl.AccessLogStrings;
|
||||
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
|
||||
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
|
||||
|
||||
namespace LibHac.Fs.Shim
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains functions for mounting code file systems.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
[SkipLocalsInit]
|
||||
public static class Code
|
||||
{
|
||||
@ -37,6 +42,7 @@ namespace LibHac.Fs.Shim
|
||||
{
|
||||
rc = Mount(fs, out verificationData, mountName, path, programId);
|
||||
}
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
@ -56,25 +62,30 @@ namespace LibHac.Fs.Shim
|
||||
if (path.IsNull())
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
|
||||
rc = FspPath.FromSpan(out FspPath fsPath, path);
|
||||
rc = PathUtility.ConvertToFspPath(out FspPath fsPath, path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxyForLoader> fsProxy =
|
||||
using SharedRef<IFileSystemProxyForLoader> fileSystemProxy =
|
||||
fs.Impl.GetFileSystemProxyForLoaderServiceObject();
|
||||
|
||||
ReferenceCountedDisposable<IFileSystemSf> fileSystem = null;
|
||||
try
|
||||
{
|
||||
rc = fsProxy.Target.OpenCodeFileSystem(out fileSystem, out verificationData, in fsPath, programId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
// SetCurrentProcess
|
||||
|
||||
var fileSystemAdapter = new FileSystemServiceObjectAdapter(fileSystem);
|
||||
return fs.Register(mountName, fileSystemAdapter);
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileSystem?.Dispose();
|
||||
}
|
||||
using var fileSystem = new SharedRef<IFileSystemSf>();
|
||||
|
||||
rc = fileSystemProxy.Get.OpenCodeFileSystem(ref fileSystem.Ref(), out verificationData, in fsPath,
|
||||
programId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
var fileSystemAdapter =
|
||||
new UniqueRef<IFileSystem>(new FileSystemServiceObjectAdapter(ref fileSystem.Ref()));
|
||||
|
||||
if (!fileSystemAdapter.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInCodeA.Log();
|
||||
|
||||
rc = fs.Register(mountName, ref fileSystemAdapter.Ref());
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,10 +8,15 @@ using LibHac.FsSrv.Sf;
|
||||
using LibHac.Ncm;
|
||||
using LibHac.Os;
|
||||
using static LibHac.Fs.Impl.AccessLogStrings;
|
||||
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
|
||||
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
|
||||
|
||||
namespace LibHac.Fs.Shim
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains functions for mounting content file systems.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
[SkipLocalsInit]
|
||||
public static class Content
|
||||
{
|
||||
@ -40,24 +45,25 @@ namespace LibHac.Fs.Shim
|
||||
if (path.IsNull())
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
|
||||
rc = FspPath.FromSpan(out FspPath fsPath, path);
|
||||
rc = PathUtility.ConvertToFspPath(out FspPath fsPath, path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using var fileSystem = new SharedRef<IFileSystemSf>();
|
||||
|
||||
ReferenceCountedDisposable<IFileSystemSf> fileSystem = null;
|
||||
try
|
||||
{
|
||||
rc = fsProxy.Target.OpenFileSystemWithId(out fileSystem, in fsPath, id, fsType);
|
||||
if (rc.IsFailure()) return rc;
|
||||
rc = fileSystemProxy.Get.OpenFileSystemWithId(ref fileSystem.Ref(), in fsPath, id, fsType);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
var fileSystemAdapter = new FileSystemServiceObjectAdapter(fileSystem);
|
||||
return fs.Register(mountName, fileSystemAdapter);
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileSystem?.Dispose();
|
||||
}
|
||||
using var fileSystemAdapter =
|
||||
new UniqueRef<IFileSystem>(new FileSystemServiceObjectAdapter(ref fileSystem.Ref()));
|
||||
|
||||
if (!fileSystemAdapter.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInContentA.Log();
|
||||
|
||||
rc = fs.Register(mountName, ref fileSystemAdapter.Ref());
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result MountContent(this FileSystemClient fs, U8Span mountName, U8Span path,
|
||||
@ -85,6 +91,7 @@ namespace LibHac.Fs.Shim
|
||||
{
|
||||
rc = PreMount(contentType);
|
||||
}
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
@ -108,8 +115,9 @@ namespace LibHac.Fs.Shim
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = MountContentImpl(fs, mountName, path, 0, contentType);
|
||||
rc = MountContentImpl(fs, mountName, path, programId, contentType);
|
||||
}
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
@ -155,6 +163,7 @@ namespace LibHac.Fs.Shim
|
||||
{
|
||||
rc = MountContentImpl(fs, mountName, path, programId.Value, contentType);
|
||||
}
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
@ -190,6 +199,7 @@ namespace LibHac.Fs.Shim
|
||||
{
|
||||
rc = MountContentImpl(fs, mountName, path, dataId.Value, contentType);
|
||||
}
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
@ -224,6 +234,7 @@ namespace LibHac.Fs.Shim
|
||||
{
|
||||
rc = Mount(fs, mountName, programId, contentType);
|
||||
}
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
@ -239,21 +250,22 @@ namespace LibHac.Fs.Shim
|
||||
|
||||
FileSystemProxyType fsType = ConvertToFileSystemProxyType(contentType);
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using var fileSystem = new SharedRef<IFileSystemSf>();
|
||||
|
||||
ReferenceCountedDisposable<IFileSystemSf> fileSystem = null;
|
||||
try
|
||||
{
|
||||
rc = fsProxy.Target.OpenFileSystemWithPatch(out fileSystem, programId, fsType);
|
||||
if (rc.IsFailure()) return rc;
|
||||
rc = fileSystemProxy.Get.OpenFileSystemWithPatch(ref fileSystem.Ref(), programId, fsType);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
var fileSystemAdapter = new FileSystemServiceObjectAdapter(fileSystem);
|
||||
return fs.Register(mountName, fileSystemAdapter);
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileSystem?.Dispose();
|
||||
}
|
||||
using var fileSystemAdapter =
|
||||
new UniqueRef<IFileSystem>(new FileSystemServiceObjectAdapter(ref fileSystem.Ref()));
|
||||
|
||||
if (!fileSystemAdapter.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInContentA.Log();
|
||||
|
||||
rc = fs.Register(mountName, ref fileSystemAdapter.Ref());
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,38 +8,42 @@ using LibHac.FsSrv.Sf;
|
||||
using LibHac.Os;
|
||||
using LibHac.Util;
|
||||
using static LibHac.Fs.Impl.AccessLogStrings;
|
||||
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
|
||||
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
|
||||
|
||||
namespace LibHac.Fs.Shim
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains functions for mounting the directories where content is stored.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
[SkipLocalsInit]
|
||||
public static class ContentStorage
|
||||
{
|
||||
private class ContentStorageCommonMountNameGenerator : ICommonMountNameGenerator
|
||||
{
|
||||
private ContentStorageId StorageId { get; }
|
||||
private ContentStorageId _storageId;
|
||||
|
||||
public ContentStorageCommonMountNameGenerator(ContentStorageId storageId)
|
||||
{
|
||||
StorageId = storageId;
|
||||
_storageId = storageId;
|
||||
}
|
||||
|
||||
public void Dispose() { }
|
||||
|
||||
public Result GenerateCommonMountName(Span<byte> nameBuffer)
|
||||
{
|
||||
// Determine how much space we need.
|
||||
int neededSize =
|
||||
StringUtils.GetLength(GetContentStorageMountName(StorageId), PathTool.MountNameLengthMax) + 2;
|
||||
ReadOnlySpan<byte> mountName = GetContentStorageMountName(_storageId);
|
||||
|
||||
Assert.SdkRequiresGreaterEqual(nameBuffer.Length, neededSize);
|
||||
// Add 2 for the mount name separator and null terminator
|
||||
int requiredNameBufferSize = StringUtils.GetLength(mountName, PathTool.MountNameLengthMax) + 2;
|
||||
|
||||
Assert.SdkRequiresGreaterEqual(nameBuffer.Length, requiredNameBufferSize);
|
||||
|
||||
// Generate the name.
|
||||
var sb = new U8StringBuilder(nameBuffer);
|
||||
sb.Append(GetContentStorageMountName(StorageId))
|
||||
.Append(StringTraits.DriveSeparator);
|
||||
sb.Append(mountName).Append(StringTraits.DriveSeparator);
|
||||
|
||||
Assert.SdkEqual(sb.Length, neededSize - 1);
|
||||
Assert.SdkEqual(sb.Length, requiredNameBufferSize - 1);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
@ -73,6 +77,7 @@ namespace LibHac.Fs.Shim
|
||||
{
|
||||
rc = Mount(fs, mountName, storageId);
|
||||
}
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
@ -91,35 +96,41 @@ namespace LibHac.Fs.Shim
|
||||
Result rc = fs.Impl.CheckMountNameAcceptingReservedMountName(mountName);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using var fileSystem = new SharedRef<IFileSystemSf>();
|
||||
|
||||
ReferenceCountedDisposable<IFileSystemSf> fileSystem = null;
|
||||
try
|
||||
for (int i = 0; i < maxRetries; i++)
|
||||
{
|
||||
for (int i = 0; i < maxRetries; i++)
|
||||
{
|
||||
rc = fsProxy.Target.OpenContentStorageFileSystem(out fileSystem, storageId);
|
||||
rc = fileSystemProxy.Get.OpenContentStorageFileSystem(ref fileSystem.Ref(), storageId);
|
||||
|
||||
if (rc.IsSuccess())
|
||||
break;
|
||||
if (rc.IsSuccess())
|
||||
break;
|
||||
|
||||
if (!ResultFs.SystemPartitionNotReady.Includes(rc))
|
||||
return rc;
|
||||
if (!ResultFs.SystemPartitionNotReady.Includes(rc))
|
||||
return rc;
|
||||
|
||||
if (i == maxRetries - 1)
|
||||
return rc;
|
||||
if (i == maxRetries - 1)
|
||||
return rc;
|
||||
|
||||
fs.Hos.Os.SleepThread(TimeSpan.FromMilliSeconds(retryInterval));
|
||||
}
|
||||
|
||||
var fileSystemAdapter = new FileSystemServiceObjectAdapter(fileSystem);
|
||||
var mountNameGenerator = new ContentStorageCommonMountNameGenerator(storageId);
|
||||
return fs.Register(mountName, fileSystemAdapter, mountNameGenerator);
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileSystem?.Dispose();
|
||||
fs.Hos.Os.SleepThread(TimeSpan.FromMilliSeconds(retryInterval));
|
||||
}
|
||||
|
||||
using var fileSystemAdapter =
|
||||
new UniqueRef<IFileSystem>(new FileSystemServiceObjectAdapter(ref fileSystem.Ref()));
|
||||
|
||||
if (!fileSystemAdapter.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInContentStorageA.Log();
|
||||
|
||||
using var mountNameGenerator =
|
||||
new UniqueRef<ICommonMountNameGenerator>(new ContentStorageCommonMountNameGenerator(storageId));
|
||||
|
||||
if (!mountNameGenerator.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInContentStorageB.Log();
|
||||
|
||||
rc = fs.Register(mountName, ref fileSystemAdapter.Ref(), ref mountNameGenerator.Ref());
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,20 +5,25 @@ using LibHac.Diag;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.Fs.Impl;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
|
||||
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
|
||||
|
||||
namespace LibHac.Fs.Shim
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains functions for mounting custom storage file systems.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
[SkipLocalsInit]
|
||||
public static class CustomStorage
|
||||
{
|
||||
public static U8Span GetCustomStorageDirectoryName(CustomStorageId storageId)
|
||||
public static ReadOnlySpan<byte> GetCustomStorageDirectoryName(CustomStorageId storageId)
|
||||
{
|
||||
switch (storageId)
|
||||
{
|
||||
case CustomStorageId.System:
|
||||
case CustomStorageId.SdCard:
|
||||
return new U8Span(CustomStorageDirectoryName);
|
||||
return CustomStorageDirectoryName;
|
||||
default:
|
||||
Abort.UnexpectedDefault();
|
||||
return default;
|
||||
@ -27,23 +32,31 @@ namespace LibHac.Fs.Shim
|
||||
|
||||
public static Result MountCustomStorage(this FileSystemClient fs, U8Span mountName, CustomStorageId storageId)
|
||||
{
|
||||
Result rc = fs.Impl.CheckMountName(mountName);
|
||||
if (rc.IsFailure()) return rc;
|
||||
Result rc = Mount(fs, mountName, storageId);
|
||||
|
||||
ReferenceCountedDisposable<IFileSystemSf> fileSystem = null;
|
||||
try
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
|
||||
static Result Mount(FileSystemClient fs, U8Span mountName, CustomStorageId storageId)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
Result rc = fs.Impl.CheckMountName(mountName);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
rc = fsProxy.Target.OpenCustomStorageFileSystem(out fileSystem, storageId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using var fileSystem = new SharedRef<IFileSystemSf>();
|
||||
|
||||
var fileSystemAdapter = new FileSystemServiceObjectAdapter(fileSystem);
|
||||
return fs.Register(mountName, fileSystemAdapter);
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileSystem?.Dispose();
|
||||
rc = fileSystemProxy.Get.OpenCustomStorageFileSystem(ref fileSystem.Ref(), storageId);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
using var fileSystemAdapter =
|
||||
new UniqueRef<IFileSystem>(new FileSystemServiceObjectAdapter(ref fileSystem.Ref()));
|
||||
|
||||
rc = fs.Register(mountName, ref fileSystemAdapter.Ref());
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,21 +6,20 @@ namespace LibHac.Fs.Shim
|
||||
internal struct FileSystemProxyServiceObjectGlobals
|
||||
{
|
||||
public nint FileSystemProxyServiceObjectInitGuard;
|
||||
public ReferenceCountedDisposable<IFileSystemProxy> FileSystemProxyServiceObject;
|
||||
public SharedRef<IFileSystemProxy> FileSystemProxyServiceObject;
|
||||
|
||||
public nint FileSystemProxyForLoaderServiceObjectInitGuard;
|
||||
public ReferenceCountedDisposable<IFileSystemProxyForLoader> FileSystemProxyForLoaderServiceObject;
|
||||
public SharedRef<IFileSystemProxyForLoader> FileSystemProxyForLoaderServiceObject;
|
||||
|
||||
public nint ProgramRegistryServiceObjectInitGuard;
|
||||
public ReferenceCountedDisposable<IProgramRegistry> ProgramRegistryServiceObject;
|
||||
public SharedRef<IProgramRegistry> ProgramRegistryServiceObject;
|
||||
|
||||
public ReferenceCountedDisposable<IFileSystemProxy> DfcFileSystemProxyServiceObject;
|
||||
public SharedRef<IFileSystemProxy> DfcFileSystemProxyServiceObject;
|
||||
}
|
||||
|
||||
public static class FileSystemProxyServiceObject
|
||||
{
|
||||
public static ReferenceCountedDisposable<IFileSystemProxy> GetFileSystemProxyServiceObject(
|
||||
this FileSystemClientImpl fs)
|
||||
public static SharedRef<IFileSystemProxy> GetFileSystemProxyServiceObject(this FileSystemClientImpl fs)
|
||||
{
|
||||
ref FileSystemProxyServiceObjectGlobals g = ref fs.Globals.FileSystemProxyServiceObject;
|
||||
using var guard = new InitializationGuard(ref g.FileSystemProxyServiceObjectInitGuard,
|
||||
@ -28,33 +27,36 @@ namespace LibHac.Fs.Shim
|
||||
|
||||
if (!guard.IsInitialized)
|
||||
{
|
||||
g.FileSystemProxyServiceObject = GetFileSystemProxyServiceObjectImpl(fs);
|
||||
using SharedRef<IFileSystemProxy> createdObject = GetFileSystemProxyServiceObjectImpl(fs);
|
||||
g.FileSystemProxyServiceObject.SetByMove(ref createdObject.Ref());
|
||||
}
|
||||
|
||||
return g.FileSystemProxyServiceObject.AddReference();
|
||||
return SharedRef<IFileSystemProxy>.CreateCopy(ref g.FileSystemProxyServiceObject);
|
||||
}
|
||||
|
||||
private static ReferenceCountedDisposable<IFileSystemProxy> GetFileSystemProxyServiceObjectImpl(
|
||||
FileSystemClientImpl fs)
|
||||
private static SharedRef<IFileSystemProxy> GetFileSystemProxyServiceObjectImpl(FileSystemClientImpl fs)
|
||||
{
|
||||
ReferenceCountedDisposable<IFileSystemProxy> dfcServiceObject =
|
||||
fs.Globals.FileSystemProxyServiceObject.DfcFileSystemProxyServiceObject;
|
||||
ref SharedRef<IFileSystemProxy> dfcServiceObject =
|
||||
ref fs.Globals.FileSystemProxyServiceObject.DfcFileSystemProxyServiceObject;
|
||||
|
||||
if (dfcServiceObject is not null)
|
||||
return dfcServiceObject.AddReference();
|
||||
if (dfcServiceObject.HasValue)
|
||||
{
|
||||
return SharedRef<IFileSystemProxy>.CreateCopy(ref dfcServiceObject);
|
||||
}
|
||||
|
||||
Result rc = fs.Hos.Sm.GetService(out ReferenceCountedDisposable<IFileSystemProxy> fsProxy, "fsp-srv");
|
||||
using var fileSystemProxy = new SharedRef<IFileSystemProxy>();
|
||||
Result rc = fs.Hos.Sm.GetService(ref fileSystemProxy.Ref(), "fsp-srv");
|
||||
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
throw new HorizonResultException(rc, "Failed to get file system proxy service object.");
|
||||
}
|
||||
|
||||
fsProxy.Target.SetCurrentProcess(fs.Hos.Os.GetCurrentProcessId().Value).IgnoreResult();
|
||||
return fsProxy;
|
||||
fileSystemProxy.Get.SetCurrentProcess(fs.Hos.Os.GetCurrentProcessId().Value).IgnoreResult();
|
||||
return SharedRef<IFileSystemProxy>.CreateMove(ref fileSystemProxy.Ref());
|
||||
}
|
||||
|
||||
public static ReferenceCountedDisposable<IFileSystemProxyForLoader> GetFileSystemProxyForLoaderServiceObject(
|
||||
public static SharedRef<IFileSystemProxyForLoader> GetFileSystemProxyForLoaderServiceObject(
|
||||
this FileSystemClientImpl fs)
|
||||
{
|
||||
ref FileSystemProxyServiceObjectGlobals g = ref fs.Globals.FileSystemProxyServiceObject;
|
||||
@ -63,29 +65,29 @@ namespace LibHac.Fs.Shim
|
||||
|
||||
if (!guard.IsInitialized)
|
||||
{
|
||||
g.FileSystemProxyForLoaderServiceObject = GetFileSystemProxyForLoaderServiceObjectImpl(fs);
|
||||
using SharedRef<IFileSystemProxyForLoader> createdObject = GetFileSystemProxyForLoaderServiceObjectImpl(fs);
|
||||
g.FileSystemProxyForLoaderServiceObject.SetByMove(ref createdObject.Ref());
|
||||
}
|
||||
|
||||
return g.FileSystemProxyForLoaderServiceObject.AddReference();
|
||||
return SharedRef<IFileSystemProxyForLoader>.CreateCopy(ref g.FileSystemProxyForLoaderServiceObject);
|
||||
}
|
||||
|
||||
private static ReferenceCountedDisposable<IFileSystemProxyForLoader>
|
||||
GetFileSystemProxyForLoaderServiceObjectImpl(FileSystemClientImpl fs)
|
||||
private static SharedRef<IFileSystemProxyForLoader> GetFileSystemProxyForLoaderServiceObjectImpl(
|
||||
FileSystemClientImpl fs)
|
||||
{
|
||||
Result rc = fs.Hos.Sm.GetService(out ReferenceCountedDisposable<IFileSystemProxyForLoader> fsProxy,
|
||||
"fsp-ldr");
|
||||
using var fileSystemProxy = new SharedRef<IFileSystemProxyForLoader>();
|
||||
Result rc = fs.Hos.Sm.GetService(ref fileSystemProxy.Ref(), "fsp-ldr");
|
||||
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
throw new HorizonResultException(rc, "Failed to get file system proxy service object.");
|
||||
}
|
||||
|
||||
fsProxy.Target.SetCurrentProcess(fs.Hos.Os.GetCurrentProcessId().Value).IgnoreResult();
|
||||
return fsProxy;
|
||||
fileSystemProxy.Get.SetCurrentProcess(fs.Hos.Os.GetCurrentProcessId().Value).IgnoreResult();
|
||||
return SharedRef<IFileSystemProxyForLoader>.CreateMove(ref fileSystemProxy.Ref());
|
||||
}
|
||||
|
||||
public static ReferenceCountedDisposable<IProgramRegistry> GetProgramRegistryServiceObject(
|
||||
this FileSystemClientImpl fs)
|
||||
public static SharedRef<IProgramRegistry> GetProgramRegistryServiceObject(this FileSystemClientImpl fs)
|
||||
{
|
||||
ref FileSystemProxyServiceObjectGlobals g = ref fs.Globals.FileSystemProxyServiceObject;
|
||||
using var guard = new InitializationGuard(ref g.ProgramRegistryServiceObjectInitGuard,
|
||||
@ -93,24 +95,25 @@ namespace LibHac.Fs.Shim
|
||||
|
||||
if (!guard.IsInitialized)
|
||||
{
|
||||
g.ProgramRegistryServiceObject = GetProgramRegistryServiceObjectImpl(fs);
|
||||
using SharedRef<IProgramRegistry> createdObject = GetProgramRegistryServiceObjectImpl(fs);
|
||||
g.ProgramRegistryServiceObject.SetByMove(ref createdObject.Ref());
|
||||
}
|
||||
|
||||
return g.ProgramRegistryServiceObject.AddReference();
|
||||
return SharedRef<IProgramRegistry>.CreateCopy(ref g.ProgramRegistryServiceObject);
|
||||
}
|
||||
|
||||
private static ReferenceCountedDisposable<IProgramRegistry> GetProgramRegistryServiceObjectImpl(
|
||||
FileSystemClientImpl fs)
|
||||
private static SharedRef<IProgramRegistry> GetProgramRegistryServiceObjectImpl(FileSystemClientImpl fs)
|
||||
{
|
||||
Result rc = fs.Hos.Sm.GetService(out ReferenceCountedDisposable<IProgramRegistry> registry, "fsp-pr");
|
||||
using var registry = new SharedRef<IProgramRegistry>();
|
||||
Result rc = fs.Hos.Sm.GetService(ref registry.Ref(), "fsp-pr");
|
||||
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
throw new HorizonResultException(rc, "Failed to get registry service object.");
|
||||
}
|
||||
|
||||
registry.Target.SetCurrentProcess(fs.Hos.Os.GetCurrentProcessId().Value).IgnoreResult();
|
||||
return registry;
|
||||
registry.Get.SetCurrentProcess(fs.Hos.Os.GetCurrentProcessId().Value).IgnoreResult();
|
||||
return SharedRef<IProgramRegistry>.CreateMove(ref registry.Ref());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -121,9 +124,9 @@ namespace LibHac.Fs.Shim
|
||||
/// <param name="fs">The <see cref="FileSystemClient"/> to use.</param>
|
||||
/// <param name="serviceObject">The service object this <see cref="FileSystemClient"/> will use.</param>
|
||||
public static void InitializeDfcFileSystemProxyServiceObject(this FileSystemClientImpl fs,
|
||||
ReferenceCountedDisposable<IFileSystemProxy> serviceObject)
|
||||
ref SharedRef<IFileSystemProxy> serviceObject)
|
||||
{
|
||||
fs.Globals.FileSystemProxyServiceObject.DfcFileSystemProxyServiceObject = serviceObject.AddReference();
|
||||
fs.Globals.FileSystemProxyServiceObject.DfcFileSystemProxyServiceObject.SetByMove(ref serviceObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,46 +21,45 @@ namespace LibHac.Fs.Impl
|
||||
/// An adapter for using an <see cref="IFileSf"/> service object as an <see cref="IFile"/>. Used
|
||||
/// when receiving a Horizon IPC file object so it can be used as an <see cref="IFile"/> locally.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.0.3 (nnSdk 12.3.1)</remarks>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
internal class FileServiceObjectAdapter : IFile
|
||||
{
|
||||
private ReferenceCountedDisposable<IFileSf> BaseFile { get; }
|
||||
private SharedRef<IFileSf> _baseFile;
|
||||
|
||||
public FileServiceObjectAdapter(ReferenceCountedDisposable<IFileSf> baseFile)
|
||||
public FileServiceObjectAdapter(ref SharedRef<IFileSf> baseFile)
|
||||
{
|
||||
BaseFile = baseFile.AddReference();
|
||||
_baseFile = SharedRef<IFileSf>.CreateMove(ref baseFile);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
BaseFile?.Dispose();
|
||||
|
||||
_baseFile.Destroy();
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
protected override Result DoRead(out long bytesRead, long offset, Span<byte> destination, in ReadOption option)
|
||||
{
|
||||
return BaseFile.Target.Read(out bytesRead, offset, new OutBuffer(destination), destination.Length, option);
|
||||
return _baseFile.Get.Read(out bytesRead, offset, new OutBuffer(destination), destination.Length, option);
|
||||
}
|
||||
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source, in WriteOption option)
|
||||
{
|
||||
return BaseFile.Target.Write(offset, new InBuffer(source), source.Length, option);
|
||||
return _baseFile.Get.Write(offset, new InBuffer(source), source.Length, option);
|
||||
}
|
||||
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return BaseFile.Target.Flush();
|
||||
return _baseFile.Get.Flush();
|
||||
}
|
||||
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
return BaseFile.Target.SetSize(size);
|
||||
return _baseFile.Get.SetSize(size);
|
||||
}
|
||||
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
return BaseFile.Target.GetSize(out size);
|
||||
return _baseFile.Get.GetSize(out size);
|
||||
}
|
||||
|
||||
protected override Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size,
|
||||
@ -69,16 +68,16 @@ namespace LibHac.Fs.Impl
|
||||
switch (operationId)
|
||||
{
|
||||
case OperationId.InvalidateCache:
|
||||
return BaseFile.Target.OperateRange(out _, (int)OperationId.InvalidateCache, offset, size);
|
||||
return _baseFile.Get.OperateRange(out _, (int)OperationId.InvalidateCache, offset, size);
|
||||
case OperationId.QueryRange:
|
||||
if (outBuffer.Length != Unsafe.SizeOf<QueryRangeInfo>())
|
||||
return ResultFs.InvalidSize.Log();
|
||||
|
||||
ref QueryRangeInfo info = ref SpanHelpers.AsStruct<QueryRangeInfo>(outBuffer);
|
||||
|
||||
return BaseFile.Target.OperateRange(out info, (int)OperationId.QueryRange, offset, size);
|
||||
return _baseFile.Get.OperateRange(out info, (int)OperationId.QueryRange, offset, size);
|
||||
default:
|
||||
return BaseFile.Target.OperateRangeWithBuffer(new OutBuffer(outBuffer), new InBuffer(inBuffer),
|
||||
return _baseFile.Get.OperateRangeWithBuffer(new OutBuffer(outBuffer), new InBuffer(inBuffer),
|
||||
(int)operationId, offset, size);
|
||||
}
|
||||
}
|
||||
@ -88,32 +87,31 @@ namespace LibHac.Fs.Impl
|
||||
/// An adapter for using an <see cref="IDirectorySf"/> service object as an <see cref="IDirectory"/>. Used
|
||||
/// when receiving a Horizon IPC directory object so it can be used as an <see cref="IDirectory"/> locally.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.0.3 (nnSdk 12.3.1)</remarks>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
internal class DirectoryServiceObjectAdapter : IDirectory
|
||||
{
|
||||
private ReferenceCountedDisposable<IDirectorySf> BaseDirectory { get; }
|
||||
private SharedRef<IDirectorySf> _baseDirectory;
|
||||
|
||||
public DirectoryServiceObjectAdapter(ReferenceCountedDisposable<IDirectorySf> baseDirectory)
|
||||
public DirectoryServiceObjectAdapter(ref SharedRef<IDirectorySf> baseDirectory)
|
||||
{
|
||||
BaseDirectory = baseDirectory.AddReference();
|
||||
_baseDirectory = SharedRef<IDirectorySf>.CreateMove(ref baseDirectory);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
BaseDirectory?.Dispose();
|
||||
|
||||
_baseDirectory.Destroy();
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
protected override Result DoRead(out long entriesRead, Span<DirectoryEntry> entryBuffer)
|
||||
{
|
||||
Span<byte> buffer = MemoryMarshal.Cast<DirectoryEntry, byte>(entryBuffer);
|
||||
return BaseDirectory.Target.Read(out entriesRead, new OutBuffer(buffer));
|
||||
return _baseDirectory.Get.Read(out entriesRead, new OutBuffer(buffer));
|
||||
}
|
||||
|
||||
protected override Result DoGetEntryCount(out long entryCount)
|
||||
{
|
||||
return BaseDirectory.Target.GetEntryCount(out entryCount);
|
||||
return _baseDirectory.Get.GetEntryCount(out entryCount);
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,10 +119,10 @@ namespace LibHac.Fs.Impl
|
||||
/// An adapter for using an <see cref="IFileSystemSf"/> service object as an <see cref="IFileSystem"/>. Used
|
||||
/// when receiving a Horizon IPC file system object so it can be used as an <see cref="IFileSystem"/> locally.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.0.3 (nnSdk 12.3.1)</remarks>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
internal class FileSystemServiceObjectAdapter : IFileSystem, IMultiCommitTarget
|
||||
{
|
||||
private ReferenceCountedDisposable<IFileSystemSf> BaseFs { get; }
|
||||
private SharedRef<IFileSystemSf> _baseFs;
|
||||
|
||||
private static Result GetPathForServiceObject(out PathSf sfPath, in Path path)
|
||||
{
|
||||
@ -139,14 +137,14 @@ namespace LibHac.Fs.Impl
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public FileSystemServiceObjectAdapter(ReferenceCountedDisposable<IFileSystemSf> baseFileSystem)
|
||||
public FileSystemServiceObjectAdapter(ref SharedRef<IFileSystemSf> baseFileSystem)
|
||||
{
|
||||
BaseFs = baseFileSystem.AddReference();
|
||||
_baseFs = SharedRef<IFileSystemSf>.CreateMove(ref baseFileSystem);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
BaseFs?.Dispose();
|
||||
_baseFs.Destroy();
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
@ -155,7 +153,7 @@ namespace LibHac.Fs.Impl
|
||||
Result rc = GetPathForServiceObject(out PathSf sfPath, in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFs.Target.CreateFile(in sfPath, size, (int)option);
|
||||
return _baseFs.Get.CreateFile(in sfPath, size, (int)option);
|
||||
}
|
||||
|
||||
protected override Result DoDeleteFile(in Path path)
|
||||
@ -163,7 +161,7 @@ namespace LibHac.Fs.Impl
|
||||
Result rc = GetPathForServiceObject(out PathSf sfPath, in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFs.Target.DeleteFile(in sfPath);
|
||||
return _baseFs.Get.DeleteFile(in sfPath);
|
||||
}
|
||||
|
||||
protected override Result DoCreateDirectory(in Path path)
|
||||
@ -171,7 +169,7 @@ namespace LibHac.Fs.Impl
|
||||
Result rc = GetPathForServiceObject(out PathSf sfPath, in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFs.Target.CreateDirectory(in sfPath);
|
||||
return _baseFs.Get.CreateDirectory(in sfPath);
|
||||
}
|
||||
|
||||
protected override Result DoDeleteDirectory(in Path path)
|
||||
@ -179,7 +177,7 @@ namespace LibHac.Fs.Impl
|
||||
Result rc = GetPathForServiceObject(out PathSf sfPath, in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFs.Target.DeleteDirectory(in sfPath);
|
||||
return _baseFs.Get.DeleteDirectory(in sfPath);
|
||||
}
|
||||
|
||||
protected override Result DoDeleteDirectoryRecursively(in Path path)
|
||||
@ -187,7 +185,7 @@ namespace LibHac.Fs.Impl
|
||||
Result rc = GetPathForServiceObject(out PathSf sfPath, in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFs.Target.DeleteDirectoryRecursively(in sfPath);
|
||||
return _baseFs.Get.DeleteDirectoryRecursively(in sfPath);
|
||||
}
|
||||
|
||||
protected override Result DoCleanDirectoryRecursively(in Path path)
|
||||
@ -195,7 +193,7 @@ namespace LibHac.Fs.Impl
|
||||
Result rc = GetPathForServiceObject(out PathSf sfPath, in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFs.Target.CleanDirectoryRecursively(in sfPath);
|
||||
return _baseFs.Get.CleanDirectoryRecursively(in sfPath);
|
||||
}
|
||||
|
||||
protected override Result DoRenameFile(in Path currentPath, in Path newPath)
|
||||
@ -206,7 +204,7 @@ namespace LibHac.Fs.Impl
|
||||
rc = GetPathForServiceObject(out PathSf newSfPath, in newPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFs.Target.RenameFile(in currentSfPath, in newSfPath);
|
||||
return _baseFs.Get.RenameFile(in currentSfPath, in newSfPath);
|
||||
}
|
||||
|
||||
protected override Result DoRenameDirectory(in Path currentPath, in Path newPath)
|
||||
@ -217,7 +215,7 @@ namespace LibHac.Fs.Impl
|
||||
rc = GetPathForServiceObject(out PathSf newSfPath, in newPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFs.Target.RenameDirectory(in currentSfPath, in newSfPath);
|
||||
return _baseFs.Get.RenameDirectory(in currentSfPath, in newSfPath);
|
||||
}
|
||||
|
||||
protected override Result DoGetEntryType(out DirectoryEntryType entryType, in Path path)
|
||||
@ -229,7 +227,7 @@ namespace LibHac.Fs.Impl
|
||||
|
||||
ref uint sfEntryType = ref Unsafe.As<DirectoryEntryType, uint>(ref entryType);
|
||||
|
||||
return BaseFs.Target.GetEntryType(out sfEntryType, in sfPath);
|
||||
return _baseFs.Get.GetEntryType(out sfEntryType, in sfPath);
|
||||
}
|
||||
|
||||
protected override Result DoGetFreeSpaceSize(out long freeSpace, in Path path)
|
||||
@ -239,7 +237,7 @@ namespace LibHac.Fs.Impl
|
||||
Result rc = GetPathForServiceObject(out PathSf sfPath, in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFs.Target.GetFreeSpaceSize(out freeSpace, in sfPath);
|
||||
return _baseFs.Get.GetFreeSpaceSize(out freeSpace, in sfPath);
|
||||
}
|
||||
|
||||
protected override Result DoGetTotalSpaceSize(out long totalSpace, in Path path)
|
||||
@ -249,7 +247,7 @@ namespace LibHac.Fs.Impl
|
||||
Result rc = GetPathForServiceObject(out PathSf sfPath, in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFs.Target.GetTotalSpaceSize(out totalSpace, in sfPath);
|
||||
return _baseFs.Get.GetTotalSpaceSize(out totalSpace, in sfPath);
|
||||
}
|
||||
|
||||
protected override Result DoOpenFile(ref UniqueRef<IFile> outFile, in Path path, OpenMode mode)
|
||||
@ -257,19 +255,13 @@ namespace LibHac.Fs.Impl
|
||||
Result rc = GetPathForServiceObject(out PathSf sfPath, in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
ReferenceCountedDisposable<IFileSf> sfFile = null;
|
||||
try
|
||||
{
|
||||
rc = BaseFs.Target.OpenFile(out sfFile, in sfPath, (uint)mode);
|
||||
if (rc.IsFailure()) return rc;
|
||||
using var fileServiceObject = new SharedRef<IFileSf>();
|
||||
|
||||
outFile.Reset(new FileServiceObjectAdapter(sfFile));
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
sfFile?.Dispose();
|
||||
}
|
||||
rc = _baseFs.Get.OpenFile(ref fileServiceObject.Ref(), in sfPath, (uint)mode);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
outFile.Reset(new FileServiceObjectAdapter(ref fileServiceObject.Ref()));
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result DoOpenDirectory(ref UniqueRef<IDirectory> outDirectory, in Path path,
|
||||
@ -278,24 +270,18 @@ namespace LibHac.Fs.Impl
|
||||
Result rc = GetPathForServiceObject(out PathSf sfPath, in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
ReferenceCountedDisposable<IDirectorySf> sfDir = null;
|
||||
try
|
||||
{
|
||||
rc = BaseFs.Target.OpenDirectory(out sfDir, in sfPath, (uint)mode);
|
||||
if (rc.IsFailure()) return rc;
|
||||
using var directoryServiceObject = new SharedRef<IDirectorySf>();
|
||||
|
||||
outDirectory.Reset(new DirectoryServiceObjectAdapter(sfDir));
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
sfDir?.Dispose();
|
||||
}
|
||||
rc = _baseFs.Get.OpenDirectory(ref directoryServiceObject.Ref(), in sfPath, (uint)mode);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
outDirectory.Reset(new DirectoryServiceObjectAdapter(ref directoryServiceObject.Ref()));
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result DoCommit()
|
||||
{
|
||||
return BaseFs.Target.Commit();
|
||||
return _baseFs.Get.Commit();
|
||||
}
|
||||
|
||||
protected override Result DoGetFileTimeStampRaw(out FileTimeStampRaw timeStamp, in Path path)
|
||||
@ -305,7 +291,7 @@ namespace LibHac.Fs.Impl
|
||||
Result rc = GetPathForServiceObject(out PathSf sfPath, in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFs.Target.GetFileTimeStampRaw(out timeStamp, in sfPath);
|
||||
return _baseFs.Get.GetFileTimeStampRaw(out timeStamp, in sfPath);
|
||||
}
|
||||
|
||||
protected override Result DoQueryEntry(Span<byte> outBuffer, ReadOnlySpan<byte> inBuffer, QueryId queryId,
|
||||
@ -314,15 +300,15 @@ namespace LibHac.Fs.Impl
|
||||
Result rc = GetPathForServiceObject(out PathSf sfPath, in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFs.Target.QueryEntry(new OutBuffer(outBuffer), new InBuffer(inBuffer), (int)queryId, in sfPath);
|
||||
return _baseFs.Get.QueryEntry(new OutBuffer(outBuffer), new InBuffer(inBuffer), (int)queryId, in sfPath);
|
||||
}
|
||||
|
||||
public ReferenceCountedDisposable<IFileSystemSf> GetFileSystem()
|
||||
public SharedRef<IFileSystemSf> GetFileSystem()
|
||||
{
|
||||
return BaseFs.AddReference();
|
||||
return SharedRef<IFileSystemSf>.CreateCopy(ref _baseFs);
|
||||
}
|
||||
|
||||
public ReferenceCountedDisposable<IFileSystemSf> GetMultiCommitTarget()
|
||||
public SharedRef<IFileSystemSf> GetMultiCommitTarget()
|
||||
{
|
||||
return GetFileSystem();
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ using LibHac.FsSrv.Sf;
|
||||
using LibHac.Os;
|
||||
using LibHac.Util;
|
||||
using static LibHac.Fs.Impl.AccessLogStrings;
|
||||
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
|
||||
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
|
||||
using IStorageSf = LibHac.FsSrv.Sf.IStorage;
|
||||
|
||||
@ -48,12 +49,12 @@ namespace LibHac.Fs.Shim
|
||||
int handleDigitCount = Unsafe.SizeOf<GameCardHandle>() * 2;
|
||||
|
||||
// Determine how much space we need.
|
||||
int neededSize =
|
||||
int requiredNameBufferSize =
|
||||
StringUtils.GetLength(CommonMountNames.GameCardFileSystemMountName, PathTool.MountNameLengthMax) +
|
||||
StringUtils.GetLength(GetGameCardMountNameSuffix(PartitionId), PathTool.MountNameLengthMax) +
|
||||
handleDigitCount + 2;
|
||||
|
||||
Assert.SdkRequiresGreaterEqual(nameBuffer.Length, neededSize);
|
||||
Assert.SdkRequiresGreaterEqual(nameBuffer.Length, requiredNameBufferSize);
|
||||
|
||||
// Generate the name.
|
||||
var sb = new U8StringBuilder(nameBuffer);
|
||||
@ -62,7 +63,7 @@ namespace LibHac.Fs.Shim
|
||||
.AppendFormat(Handle.Value, 'x', (byte)handleDigitCount)
|
||||
.Append(StringTraits.DriveSeparator);
|
||||
|
||||
Assert.SdkEqual(sb.Length, neededSize - 1);
|
||||
Assert.SdkEqual(sb.Length, requiredNameBufferSize - 1);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
@ -72,23 +73,16 @@ namespace LibHac.Fs.Shim
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out handle);
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||
|
||||
ReferenceCountedDisposable<IDeviceOperator> deviceOperator = null;
|
||||
try
|
||||
{
|
||||
Result rc = fsProxy.Target.OpenDeviceOperator(out deviceOperator);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = deviceOperator.Target.GetGameCardHandle(out handle);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
finally
|
||||
{
|
||||
deviceOperator?.Dispose();
|
||||
}
|
||||
rc = deviceOperator.Get.GetGameCardHandle(out handle);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
public static Result MountGameCardPartition(this FileSystemClient fs, U8Span mountName, GameCardHandle handle,
|
||||
@ -116,6 +110,7 @@ namespace LibHac.Fs.Shim
|
||||
{
|
||||
rc = Mount(fs, mountName, handle, partitionId);
|
||||
}
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
@ -130,69 +125,61 @@ namespace LibHac.Fs.Shim
|
||||
Result rc = fs.Impl.CheckMountNameAcceptingReservedMountName(mountName);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using var fileSystem = new SharedRef<IFileSystemSf>();
|
||||
|
||||
ReferenceCountedDisposable<IFileSystemSf> fileSystem = null;
|
||||
try
|
||||
{
|
||||
rc = fsProxy.Target.OpenGameCardFileSystem(out fileSystem, handle, partitionId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
rc = fileSystemProxy.Get.OpenGameCardFileSystem(ref fileSystem.Ref(), handle, partitionId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
var fileSystemAdapter = new FileSystemServiceObjectAdapter(fileSystem);
|
||||
var mountNameGenerator = new GameCardCommonMountNameGenerator(handle, partitionId);
|
||||
return fs.Register(mountName, fileSystemAdapter, mountNameGenerator);
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileSystem?.Dispose();
|
||||
}
|
||||
using var fileSystemAdapter =
|
||||
new UniqueRef<IFileSystem>(new FileSystemServiceObjectAdapter(ref fileSystem.Ref()));
|
||||
|
||||
if (!fileSystemAdapter.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInGameCardC.Log();
|
||||
|
||||
using var mountNameGenerator =
|
||||
new UniqueRef<ICommonMountNameGenerator>(new GameCardCommonMountNameGenerator(handle, partitionId));
|
||||
|
||||
if (!mountNameGenerator.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInGameCardD.Log();
|
||||
|
||||
return fs.Register(mountName, ref fileSystemAdapter.Ref(), ref mountNameGenerator.Ref());
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsGameCardInserted(this FileSystemClient fs)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||
|
||||
ReferenceCountedDisposable<IDeviceOperator> deviceOperator = null;
|
||||
try
|
||||
{
|
||||
Result rc = fsProxy.Target.OpenDeviceOperator(out deviceOperator);
|
||||
fs.Impl.LogResultErrorMessage(rc);
|
||||
Abort.DoAbortUnless(rc.IsSuccess());
|
||||
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||
fs.Impl.LogResultErrorMessage(rc);
|
||||
Abort.DoAbortUnless(rc.IsSuccess());
|
||||
|
||||
rc = deviceOperator.Target.IsGameCardInserted(out bool isInserted);
|
||||
fs.Impl.LogResultErrorMessage(rc);
|
||||
Abort.DoAbortUnless(rc.IsSuccess());
|
||||
rc = deviceOperator.Get.IsGameCardInserted(out bool isInserted);
|
||||
fs.Impl.LogResultErrorMessage(rc);
|
||||
Abort.DoAbortUnless(rc.IsSuccess());
|
||||
|
||||
return isInserted;
|
||||
}
|
||||
finally
|
||||
{
|
||||
deviceOperator?.Dispose();
|
||||
}
|
||||
return isInserted;
|
||||
}
|
||||
|
||||
public static Result OpenGameCardPartition(this FileSystemClient fs, out IStorage storage,
|
||||
public static Result OpenGameCardPartition(this FileSystemClient fs, ref UniqueRef<IStorage> outStorage,
|
||||
GameCardHandle handle, GameCardPartitionRaw partitionType)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out storage);
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using var storage = new SharedRef<IStorageSf>();
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
Result rc = fileSystemProxy.Get.OpenGameCardStorage(ref storage.Ref(), handle, partitionType);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
ReferenceCountedDisposable<IStorageSf> sfStorage = null;
|
||||
try
|
||||
{
|
||||
Result rc = fsProxy.Target.OpenGameCardStorage(out sfStorage, handle, partitionType);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
using var storageAdapter = new UniqueRef<IStorage>(new StorageServiceObjectAdapter(ref storage.Ref()));
|
||||
|
||||
storage = new StorageServiceObjectAdapter(sfStorage);
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
sfStorage?.Dispose();
|
||||
}
|
||||
if (!storageAdapter.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInGameCardB.Log();
|
||||
|
||||
outStorage.Set(ref storageAdapter.Ref());
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,44 +26,41 @@ namespace LibHac.Fs.Shim
|
||||
private static ReadOnlySpan<byte> HostRootFileSystemPath => // "@Host:/"
|
||||
new[] { (byte)'@', (byte)'H', (byte)'o', (byte)'s', (byte)'t', (byte)':', (byte)'/' };
|
||||
|
||||
private const int HostRootFileSystemPathLength = 8;
|
||||
private const int HostRootFileSystemPathLength = 7;
|
||||
|
||||
/// <summary>
|
||||
/// Opens a host file system via <see cref="IFileSystemProxy"/>.
|
||||
/// </summary>
|
||||
/// <param name="fs">The <see cref="FileSystemClient"/> to use.</param>
|
||||
/// <param name="fileSystem">If successful, the opened host file system.</param>
|
||||
/// <param name="outFileSystem">If successful, the opened host file system.</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>
|
||||
/// <returns>The <see cref="Result"/> of the operation.</returns>
|
||||
private static Result OpenHostFileSystemImpl(FileSystemClient fs, out IFileSystem fileSystem, in FspPath path,
|
||||
MountHostOption option)
|
||||
private static Result OpenHostFileSystemImpl(FileSystemClient fs, ref UniqueRef<IFileSystem> outFileSystem,
|
||||
in FspPath path, MountHostOption option)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using var fileSystem = new SharedRef<IFileSystemSf>();
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
ReferenceCountedDisposable<IFileSystemSf> hostFs = null;
|
||||
try
|
||||
if (option.Flags != MountHostOptionFlag.None)
|
||||
{
|
||||
if (option.Flags != MountHostOptionFlag.None)
|
||||
{
|
||||
Result rc = fsProxy.Target.OpenHostFileSystemWithOption(out hostFs, in path, option);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
Result rc = fsProxy.Target.OpenHostFileSystem(out hostFs, in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
|
||||
fileSystem = new FileSystemServiceObjectAdapter(hostFs);
|
||||
return Result.Success;
|
||||
Result rc = fileSystemProxy.Get.OpenHostFileSystemWithOption(ref fileSystem.Ref(), in path, option);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
finally
|
||||
else
|
||||
{
|
||||
hostFs?.Dispose();
|
||||
Result rc = fileSystemProxy.Get.OpenHostFileSystem(ref fileSystem.Ref(), in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
|
||||
using var fileSystemAdapter =
|
||||
new UniqueRef<IFileSystem>(new FileSystemServiceObjectAdapter(ref fileSystem.Ref()));
|
||||
|
||||
if (!fileSystemAdapter.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInHostA.Log();
|
||||
|
||||
outFileSystem.Set(ref fileSystemAdapter.Ref());
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private class HostCommonMountNameGenerator : ICommonMountNameGenerator
|
||||
@ -72,13 +69,7 @@ namespace LibHac.Fs.Shim
|
||||
|
||||
public HostCommonMountNameGenerator(U8Span path)
|
||||
{
|
||||
StringUtils.Copy(_path.Str, path);
|
||||
|
||||
int pathLength = StringUtils.GetLength(_path.Str);
|
||||
if (pathLength != 0 && _path.Str[pathLength - 1] == DirectorySeparator)
|
||||
{
|
||||
_path.Str[pathLength - 1] = NullTerminator;
|
||||
}
|
||||
StringUtils.Strlcpy(_path.Str, path, FsPath.MaxLength + 1);
|
||||
}
|
||||
|
||||
public void Dispose() { }
|
||||
@ -86,7 +77,7 @@ namespace LibHac.Fs.Shim
|
||||
public Result GenerateCommonMountName(Span<byte> nameBuffer)
|
||||
{
|
||||
int requiredNameBufferSize =
|
||||
StringUtils.GetLength(_path.Str, FsPath.MaxLength) + HostRootFileSystemPathLength;
|
||||
StringUtils.GetLength(_path.Str, FsPath.MaxLength + 1) + HostRootFileSystemPathLength;
|
||||
|
||||
if (nameBuffer.Length < requiredNameBufferSize)
|
||||
return ResultFs.TooLongPath.Log();
|
||||
@ -123,16 +114,14 @@ namespace LibHac.Fs.Shim
|
||||
/// Verifies parameters and opens a host file system.
|
||||
/// </summary>
|
||||
/// <param name="fs">The <see cref="FileSystemClient"/> to use.</param>
|
||||
/// <param name="fileSystem">If successful, the opened host file system.</param>
|
||||
/// <param name="outFileSystem">If successful, the opened host file system.</param>
|
||||
/// <param name="mountName">The mount name to be verified.</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>
|
||||
/// <returns>The <see cref="Result"/> of the operation.</returns>
|
||||
private static Result OpenHostFileSystem(FileSystemClient fs, out IFileSystem fileSystem, U8Span mountName,
|
||||
U8Span path, MountHostOption option)
|
||||
private static Result OpenHostFileSystem(FileSystemClient fs, ref UniqueRef<IFileSystem> outFileSystem,
|
||||
U8Span mountName, U8Span path, MountHostOption option)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
|
||||
if (mountName.IsNull())
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
|
||||
@ -145,44 +134,22 @@ namespace LibHac.Fs.Shim
|
||||
if (fs.Impl.IsUsedReservedMountName(mountName))
|
||||
return ResultFs.InvalidMountName.Log();
|
||||
|
||||
bool needsTrailingSeparator = false;
|
||||
int pathLength = StringUtils.GetLength(path, PathTools.MaxPathLength + 1);
|
||||
Result rc = PathUtility.ConvertToFspPath(out FspPath sfPath, path);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
if (pathLength != 0 && path[pathLength - 1] == DirectorySeparator)
|
||||
if (sfPath.Str[0] == NullTerminator)
|
||||
{
|
||||
needsTrailingSeparator = true;
|
||||
pathLength++;
|
||||
SpanHelpers.AsByteSpan(ref sfPath)[0] = Dot;
|
||||
SpanHelpers.AsByteSpan(ref sfPath)[1] = NullTerminator;
|
||||
}
|
||||
|
||||
if (pathLength + 1 > PathTools.MaxPathLength)
|
||||
return ResultFs.TooLongPath.Log();
|
||||
using var fileSystem = new UniqueRef<IFileSystem>();
|
||||
|
||||
Unsafe.SkipInit(out FsPath fullPath);
|
||||
rc = OpenHostFileSystemImpl(fs, ref fileSystem.Ref(), in sfPath, option);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
var sb = new U8StringBuilder(fullPath.Str);
|
||||
sb.Append(DirectorySeparator).Append(path);
|
||||
|
||||
if (needsTrailingSeparator)
|
||||
{
|
||||
sb.Append(DirectorySeparator);
|
||||
}
|
||||
|
||||
if (sb.Overflowed)
|
||||
return ResultFs.TooLongPath.Log();
|
||||
|
||||
// If the input path begins with "//", change any leading '/' characters to '\'
|
||||
if (fullPath.Str[1] == DirectorySeparator && fullPath.Str[2] == DirectorySeparator)
|
||||
{
|
||||
for (int i = 1; fullPath.Str[i] == DirectorySeparator; i++)
|
||||
{
|
||||
fullPath.Str[i] = AltDirectorySeparator;
|
||||
}
|
||||
}
|
||||
|
||||
Result rc = FspPath.FromSpan(out FspPath sfPath, fullPath.Str);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return OpenHostFileSystemImpl(fs, out fileSystem, in sfPath, option);
|
||||
outFileSystem.Set(ref fileSystem.Ref());
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -190,22 +157,24 @@ namespace LibHac.Fs.Shim
|
||||
/// <paramref name="path"/>, and verifies the <paramref name="mountName"/>.
|
||||
/// </summary>
|
||||
/// <param name="fs">The <see cref="FileSystemClient"/> to use.</param>
|
||||
/// <param name="nameGenerator">If successful, the created <see cref="ICommonMountNameGenerator"/>.</param>
|
||||
/// <param name="outMountNameGenerator">If successful, the created <see cref="ICommonMountNameGenerator"/>.</param>
|
||||
/// <param name="mountName">The mount name at which the file system will be mounted.</param>
|
||||
/// <param name="path">The path that will be opened on the host computer. e.g. C:\Windows\System32</param>
|
||||
/// <returns>The <see cref="Result"/> of the operation.</returns>
|
||||
private static Result PreMountHost(FileSystemClient fs, out HostCommonMountNameGenerator nameGenerator,
|
||||
U8Span mountName, U8Span path)
|
||||
private static Result PreMountHost(FileSystemClient fs,
|
||||
ref UniqueRef<HostCommonMountNameGenerator> outMountNameGenerator, U8Span mountName, U8Span path)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out nameGenerator);
|
||||
|
||||
Result rc = fs.Impl.CheckMountName(mountName);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (path.IsNull())
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
|
||||
nameGenerator = new HostCommonMountNameGenerator(path);
|
||||
outMountNameGenerator.Reset(new HostCommonMountNameGenerator(path));
|
||||
|
||||
if (!outMountNameGenerator.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInHostB.Log();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
@ -221,12 +190,12 @@ namespace LibHac.Fs.Shim
|
||||
Result rc;
|
||||
Span<byte> logBuffer = stackalloc byte[0x300];
|
||||
|
||||
HostCommonMountNameGenerator mountNameGenerator;
|
||||
using var mountNameGenerator = new UniqueRef<HostCommonMountNameGenerator>();
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.Application))
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = PreMountHost(fs, out mountNameGenerator, mountName, path);
|
||||
rc = PreMountHost(fs, ref mountNameGenerator.Ref(), mountName, path);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
@ -239,40 +208,43 @@ namespace LibHac.Fs.Shim
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = PreMountHost(fs, out mountNameGenerator, mountName, path);
|
||||
rc = PreMountHost(fs, ref mountNameGenerator.Ref(), mountName, path);
|
||||
}
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
IFileSystem fileSystem;
|
||||
using var fileSystem = new UniqueRef<IFileSystem>();
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.Application))
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = OpenHostFileSystem(fs, out fileSystem, mountName, path, MountHostOption.None);
|
||||
rc = OpenHostFileSystem(fs, ref fileSystem.Ref(), mountName, path, MountHostOption.None);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
fs.Impl.OutputAccessLogUnlessResultSuccess(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = OpenHostFileSystem(fs, out fileSystem, mountName, path, MountHostOption.None);
|
||||
rc = OpenHostFileSystem(fs, ref fileSystem.Ref(), mountName, path, MountHostOption.None);
|
||||
}
|
||||
|
||||
// No AbortIfNeeded here
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.Application))
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fs.Register(mountName, fileSystem, mountNameGenerator);
|
||||
rc = PostMount(fs, mountName, ref fileSystem.Ref(), ref mountNameGenerator.Ref());
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fs.Register(mountName, fileSystem, mountNameGenerator);
|
||||
rc = PostMount(fs, mountName, ref fileSystem.Ref(), ref mountNameGenerator.Ref());
|
||||
}
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
@ -280,6 +252,18 @@ namespace LibHac.Fs.Shim
|
||||
fs.Impl.EnableFileSystemAccessorAccessLog(mountName);
|
||||
|
||||
return Result.Success;
|
||||
|
||||
static Result PostMount(FileSystemClient fs, U8Span mountName, ref UniqueRef<IFileSystem> fileSystem,
|
||||
ref UniqueRef<HostCommonMountNameGenerator> mountNameGenerator)
|
||||
{
|
||||
using UniqueRef<ICommonMountNameGenerator> baseMountNameGenerator =
|
||||
UniqueRef<ICommonMountNameGenerator>.Create(ref mountNameGenerator);
|
||||
|
||||
Result rc = fs.Register(mountName, ref fileSystem, ref baseMountNameGenerator.Ref());
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -295,12 +279,12 @@ namespace LibHac.Fs.Shim
|
||||
Result rc;
|
||||
Span<byte> logBuffer = stackalloc byte[0x300];
|
||||
|
||||
HostCommonMountNameGenerator mountNameGenerator;
|
||||
using var mountNameGenerator = new UniqueRef<HostCommonMountNameGenerator>();
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.Application))
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = PreMountHost(fs, out mountNameGenerator, mountName, path);
|
||||
rc = PreMountHost(fs, ref mountNameGenerator.Ref(), mountName, path);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var idString = new IdString();
|
||||
@ -316,40 +300,43 @@ namespace LibHac.Fs.Shim
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = PreMountHost(fs, out mountNameGenerator, mountName, path);
|
||||
rc = PreMountHost(fs, ref mountNameGenerator.Ref(), mountName, path);
|
||||
}
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
IFileSystem fileSystem;
|
||||
using var fileSystem = new UniqueRef<IFileSystem>();
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.Application))
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = OpenHostFileSystem(fs, out fileSystem, mountName, path, option);
|
||||
rc = OpenHostFileSystem(fs, ref fileSystem.Ref(), mountName, path, option);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
fs.Impl.OutputAccessLogUnlessResultSuccess(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = OpenHostFileSystem(fs, out fileSystem, mountName, path, MountHostOption.None);
|
||||
rc = OpenHostFileSystem(fs, ref fileSystem.Ref(), mountName, path, option);
|
||||
}
|
||||
|
||||
// No AbortIfNeeded here
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.Application))
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fs.Register(mountName, fileSystem, mountNameGenerator);
|
||||
rc = PostMount(fs, mountName, ref fileSystem.Ref(), ref mountNameGenerator.Ref());
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fs.Register(mountName, fileSystem, mountNameGenerator);
|
||||
rc = PostMount(fs, mountName, ref fileSystem.Ref(), ref mountNameGenerator.Ref());
|
||||
}
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
@ -357,6 +344,18 @@ namespace LibHac.Fs.Shim
|
||||
fs.Impl.EnableFileSystemAccessorAccessLog(mountName);
|
||||
|
||||
return Result.Success;
|
||||
|
||||
static Result PostMount(FileSystemClient fs, U8Span mountName, ref UniqueRef<IFileSystem> fileSystem,
|
||||
ref UniqueRef<HostCommonMountNameGenerator> mountNameGenerator)
|
||||
{
|
||||
using UniqueRef<ICommonMountNameGenerator> baseMountNameGenerator =
|
||||
UniqueRef<ICommonMountNameGenerator>.Create(ref mountNameGenerator);
|
||||
|
||||
Result rc = fs.Register(mountName, ref fileSystem, ref baseMountNameGenerator.Ref());
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -369,13 +368,13 @@ namespace LibHac.Fs.Shim
|
||||
Result rc;
|
||||
Span<byte> logBuffer = stackalloc byte[0x30];
|
||||
|
||||
IFileSystem fileSystem;
|
||||
using var fileSystem = new UniqueRef<IFileSystem>();
|
||||
FspPath.CreateEmpty(out FspPath sfPath);
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.Application))
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = OpenHostFileSystemImpl(fs, out fileSystem, in sfPath, MountHostOption.None);
|
||||
rc = OpenHostFileSystemImpl(fs, ref fileSystem.Ref(), in sfPath, MountHostOption.None);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
@ -386,23 +385,25 @@ namespace LibHac.Fs.Shim
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = OpenHostFileSystemImpl(fs, out fileSystem, in sfPath, MountHostOption.None);
|
||||
rc = OpenHostFileSystemImpl(fs, ref fileSystem.Ref(), in sfPath, MountHostOption.None);
|
||||
}
|
||||
|
||||
// No AbortIfNeeded here
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.Application))
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = MountHostFs(fs, fileSystem);
|
||||
rc = PostMount(fs, ref fileSystem.Ref());
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = MountHostFs(fs, fileSystem);
|
||||
rc = PostMount(fs, ref fileSystem.Ref());
|
||||
}
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
@ -411,10 +412,19 @@ namespace LibHac.Fs.Shim
|
||||
|
||||
return Result.Success;
|
||||
|
||||
static Result MountHostFs(FileSystemClient fs, IFileSystem fileSystem)
|
||||
static Result PostMount(FileSystemClient fs, ref UniqueRef<IFileSystem> fileSystem)
|
||||
{
|
||||
return fs.Register(new U8Span(HostRootFileSystemMountName), fileSystem,
|
||||
new HostRootCommonMountNameGenerator());
|
||||
using var mountNameGenerator =
|
||||
new UniqueRef<ICommonMountNameGenerator>(new HostRootCommonMountNameGenerator());
|
||||
|
||||
if (!mountNameGenerator.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInHostC.Log();
|
||||
|
||||
Result rc = fs.Register(new U8Span(HostRootFileSystemMountName), ref fileSystem,
|
||||
ref mountNameGenerator.Ref());
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
@ -429,13 +439,13 @@ namespace LibHac.Fs.Shim
|
||||
Result rc;
|
||||
Span<byte> logBuffer = stackalloc byte[0x60];
|
||||
|
||||
IFileSystem fileSystem;
|
||||
using var fileSystem = new UniqueRef<IFileSystem>();
|
||||
FspPath.CreateEmpty(out FspPath sfPath);
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.Application))
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = OpenHostFileSystemImpl(fs, out fileSystem, in sfPath, option);
|
||||
rc = OpenHostFileSystemImpl(fs, ref fileSystem.Ref(), in sfPath, option);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var idString = new IdString();
|
||||
@ -450,23 +460,25 @@ namespace LibHac.Fs.Shim
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = OpenHostFileSystemImpl(fs, out fileSystem, in sfPath, option);
|
||||
rc = OpenHostFileSystemImpl(fs, ref fileSystem.Ref(), in sfPath, option);
|
||||
}
|
||||
|
||||
// No AbortIfNeeded here
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.Application))
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = MountHostFs(fs, fileSystem);
|
||||
rc = PostMount(fs, ref fileSystem.Ref());
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = MountHostFs(fs, fileSystem);
|
||||
rc = PostMount(fs, ref fileSystem.Ref());
|
||||
}
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
@ -475,10 +487,19 @@ namespace LibHac.Fs.Shim
|
||||
|
||||
return Result.Success;
|
||||
|
||||
static Result MountHostFs(FileSystemClient fs, IFileSystem fileSystem)
|
||||
static Result PostMount(FileSystemClient fs, ref UniqueRef<IFileSystem> fileSystem)
|
||||
{
|
||||
return fs.Register(new U8Span(HostRootFileSystemMountName), fileSystem,
|
||||
new HostRootCommonMountNameGenerator());
|
||||
using var mountNameGenerator =
|
||||
new UniqueRef<ICommonMountNameGenerator>(new HostRootCommonMountNameGenerator());
|
||||
|
||||
if (!mountNameGenerator.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInHostC.Log();
|
||||
|
||||
Result rc = fs.Register(new U8Span(HostRootFileSystemMountName), ref fileSystem,
|
||||
ref mountNameGenerator.Ref());
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
@ -508,6 +529,7 @@ namespace LibHac.Fs.Shim
|
||||
{
|
||||
rc = fs.Impl.Unmount(mountName);
|
||||
}
|
||||
|
||||
fs.Impl.LogResultErrorMessage(rc);
|
||||
Abort.DoAbortUnless(rc.IsSuccess());
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.Common;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.Os;
|
||||
|
||||
namespace LibHac.Fs.Shim
|
||||
@ -7,10 +8,10 @@ namespace LibHac.Fs.Shim
|
||||
{
|
||||
public static Result IsArchivedProgram(this FileSystemClient fs, out bool isArchived, ProcessId processId)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxyForLoader> fsProxy =
|
||||
using SharedRef<IFileSystemProxyForLoader> fileSystemProxy =
|
||||
fs.Impl.GetFileSystemProxyForLoaderServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.IsArchivedProgram(out isArchived, processId.Value);
|
||||
Result rc = fileSystemProxy.Get.IsArchivedProgram(out isArchived, processId.Value);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.Common;
|
||||
using LibHac.FsSrv.Sf;
|
||||
|
||||
namespace LibHac.Fs.Shim
|
||||
{
|
||||
@ -7,9 +8,9 @@ namespace LibHac.Fs.Shim
|
||||
public static Result SetCurrentPosixTime(this FileSystemClient fs, Time.PosixTime currentPosixTime,
|
||||
int timeDifferenceSeconds)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.SetCurrentPosixTimeWithTimeDifference(currentPosixTime.Value,
|
||||
Result rc = fileSystemProxy.Get.SetCurrentPosixTimeWithTimeDifference(currentPosixTime.Value,
|
||||
timeDifferenceSeconds);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.Sf;
|
||||
|
||||
@ -20,11 +21,11 @@ namespace LibHac.Fs.Shim
|
||||
if (mapInfo.IsEmpty)
|
||||
return Result.Success;
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
var mapInfoBuffer = new InBuffer(MemoryMarshal.Cast<ProgramIndexMapInfo, byte>(mapInfo));
|
||||
|
||||
Result rc = fsProxy.Target.RegisterProgramIndexMapInfo(mapInfoBuffer, mapInfo.Length);
|
||||
Result rc = fileSystemProxy.Get.RegisterProgramIndexMapInfo(mapInfoBuffer, mapInfo.Length);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.FsSrv;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.Ncm;
|
||||
@ -12,28 +13,33 @@ namespace LibHac.Fs.Shim
|
||||
public static Result RegisterProgram(this FileSystemClient fs, ulong processId, ProgramId programId,
|
||||
StorageId storageId, ReadOnlySpan<byte> accessControlData, ReadOnlySpan<byte> accessControlDescriptor)
|
||||
{
|
||||
using ReferenceCountedDisposable<IProgramRegistry> registry = fs.Impl.GetProgramRegistryServiceObject();
|
||||
using SharedRef<IProgramRegistry> programRegistry = fs.Impl.GetProgramRegistryServiceObject();
|
||||
|
||||
Result rc = registry.Target.SetCurrentProcess(fs.Hos.Os.GetCurrentProcessId().Value);
|
||||
Result rc = programRegistry.Get.SetCurrentProcess(fs.Hos.Os.GetCurrentProcessId().Value);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
rc = registry.Target.RegisterProgram(processId, programId, storageId, new InBuffer(accessControlData),
|
||||
rc = programRegistry.Get.RegisterProgram(processId, programId, storageId, new InBuffer(accessControlData),
|
||||
new InBuffer(accessControlDescriptor));
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ProgramRegistryImpl.UnregisterProgram"/>
|
||||
public static Result UnregisterProgram(this FileSystemClient fs, ulong processId)
|
||||
{
|
||||
using ReferenceCountedDisposable<IProgramRegistry> registry = fs.Impl.GetProgramRegistryServiceObject();
|
||||
using SharedRef<IProgramRegistry> programRegistry = fs.Impl.GetProgramRegistryServiceObject();
|
||||
|
||||
Result rc = registry.Target.SetCurrentProcess(fs.Hos.Os.GetCurrentProcessId().Value);
|
||||
if (rc.IsFailure()) return rc;
|
||||
Result rc = programRegistry.Get.SetCurrentProcess(fs.Hos.Os.GetCurrentProcessId().Value);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return registry.Target.UnregisterProgram(processId);
|
||||
rc = programRegistry.Get.UnregisterProgram(processId);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,63 +2,88 @@
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.Ncm;
|
||||
using LibHac.Spl;
|
||||
using FsRightsId = LibHac.Fs.RightsId;
|
||||
|
||||
namespace LibHac.Fs.Shim
|
||||
{
|
||||
public static class RightsId
|
||||
public static class RightsIdShim
|
||||
{
|
||||
public static Result GetRightsId(this FileSystemClient fs, out FsRightsId rightsId, ProgramId programId,
|
||||
public static Result GetRightsId(this FileSystemClient fs, out RightsId rightsId, ProgramId programId,
|
||||
StorageId storageId)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
return fsProxy.Target.GetRightsId(out rightsId, programId, storageId);
|
||||
Result rc = fileSystemProxy.Get.GetRightsId(out rightsId, programId, storageId);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result GetRightsId(this FileSystemClient fs, out FsRightsId rightsId, U8Span path)
|
||||
public static Result GetRightsId(this FileSystemClient fs, out RightsId rightsId, U8Span path)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out rightsId);
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
Result rc = PathUtility.ConvertToFspPath(out FspPath sfPath, path);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
Result rc = FspPath.FromSpan(out FspPath sfPath, path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
return fsProxy.Target.GetRightsIdByPath(out rightsId, in sfPath);
|
||||
rc = fileSystemProxy.Get.GetRightsIdByPath(out rightsId, in sfPath);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result GetRightsId(this FileSystemClient fs, out FsRightsId rightsId, out byte keyGeneration, U8Span path)
|
||||
public static Result GetRightsId(this FileSystemClient fs, out RightsId rightsId, out byte keyGeneration, U8Span path)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out rightsId, out keyGeneration);
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
Result rc = PathUtility.ConvertToFspPath(out FspPath sfPath, path);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
Result rc = FspPath.FromSpan(out FspPath sfPath, path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
return fsProxy.Target.GetRightsIdAndKeyGenerationByPath(out rightsId, out keyGeneration, in sfPath);
|
||||
rc = fileSystemProxy.Get.GetRightsIdAndKeyGenerationByPath(out rightsId, out keyGeneration, in sfPath);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result RegisterExternalKey(this FileSystemClient fs, in FsRightsId rightsId, in AccessKey key)
|
||||
public static Result RegisterExternalKey(this FileSystemClient fs, in RightsId rightsId, in AccessKey key)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
return fsProxy.Target.RegisterExternalKey(in rightsId, in key);
|
||||
Result rc = fileSystemProxy.Get.RegisterExternalKey(in rightsId, in key);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result UnregisterExternalKey(this FileSystemClient fs, ref FsRightsId rightsId)
|
||||
public static Result UnregisterExternalKey(this FileSystemClient fs, ref RightsId rightsId)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
return fsProxy.Target.UnregisterExternalKey(in rightsId);
|
||||
Result rc = fileSystemProxy.Get.UnregisterExternalKey(in rightsId);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result UnregisterAllExternalKey(this FileSystemClient fs)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
return fsProxy.Target.UnregisterAllExternalKey();
|
||||
Result rc = fileSystemProxy.Get.UnregisterAllExternalKey();
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ using LibHac.FsSrv.Sf;
|
||||
using LibHac.Ncm;
|
||||
using LibHac.Os;
|
||||
using static LibHac.Fs.Impl.AccessLogStrings;
|
||||
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
|
||||
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
|
||||
|
||||
namespace LibHac.Fs.Shim
|
||||
@ -20,33 +21,39 @@ namespace LibHac.Fs.Shim
|
||||
Result rc = fs.CheckMountName(mountName);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
|
||||
rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, programId, type, userId, 0, index);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
ReferenceCountedDisposable<IFileSystemSf> fileSystem = null;
|
||||
try
|
||||
{
|
||||
if (openReadOnly)
|
||||
{
|
||||
rc = fsProxy.Target.OpenReadOnlySaveDataFileSystem(out fileSystem, spaceId, in attribute);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fsProxy.Target.OpenSaveDataFileSystem(out fileSystem, spaceId, in attribute);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
using var fileSystem = new SharedRef<IFileSystemSf>();
|
||||
|
||||
var fileSystemAdapter = new FileSystemServiceObjectAdapter(fileSystem);
|
||||
|
||||
return fs.Fs.Register(mountName, fileSystemAdapter, fileSystemAdapter, null, false, true);
|
||||
}
|
||||
finally
|
||||
if (openReadOnly)
|
||||
{
|
||||
fileSystem?.Dispose();
|
||||
rc = fileSystemProxy.Get.OpenReadOnlySaveDataFileSystem(ref fileSystem.Ref(), spaceId, in attribute);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystemProxy.Get.OpenSaveDataFileSystem(ref fileSystem.Ref(), spaceId, in attribute);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
|
||||
// Note: Nintendo does pass in the same object both as a unique_ptr and as a raw pointer.
|
||||
// Both of these are tied to the lifetime of the created FileSystemServiceObjectAdapter so it shouldn't be an issue.
|
||||
var fileSystemAdapterRaw = new FileSystemServiceObjectAdapter(ref fileSystem.Ref());
|
||||
using var fileSystemAdapter = new UniqueRef<IFileSystem>(fileSystemAdapterRaw);
|
||||
|
||||
if (!fileSystemAdapter.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedNew.Log();
|
||||
|
||||
using var mountNameGenerator = new UniqueRef<ICommonMountNameGenerator>();
|
||||
|
||||
rc = fs.Fs.Register(mountName, fileSystemAdapterRaw, ref fileSystemAdapter.Ref(),
|
||||
ref mountNameGenerator.Ref(), false, true);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result MountSaveData(this FileSystemClient fs, U8Span mountName, Ncm.ApplicationId applicationId,
|
||||
|
@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Diag;
|
||||
using LibHac.Fs.Fsa;
|
||||
@ -15,27 +14,34 @@ using static LibHac.Fs.Impl.AccessLogStrings;
|
||||
|
||||
namespace LibHac.Fs.Shim
|
||||
{
|
||||
public readonly struct SaveDataIterator : IDisposable
|
||||
public class SaveDataIterator : IDisposable
|
||||
{
|
||||
private FileSystemClient FsClient { get; }
|
||||
private ReferenceCountedDisposable<ISaveDataInfoReader> Reader { get; }
|
||||
private readonly FileSystemClient _fsClient;
|
||||
private SharedRef<ISaveDataInfoReader> _reader;
|
||||
|
||||
internal SaveDataIterator(FileSystemClient fsClient, ref ReferenceCountedDisposable<ISaveDataInfoReader> reader)
|
||||
internal SaveDataIterator(FileSystemClient fsClient, ref SharedRef<ISaveDataInfoReader> reader)
|
||||
{
|
||||
FsClient = fsClient;
|
||||
Reader = Shared.Move(ref reader);
|
||||
_reader = SharedRef<ISaveDataInfoReader>.CreateMove(ref reader);
|
||||
_fsClient = fsClient;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_reader.Destroy();
|
||||
}
|
||||
|
||||
private Result ReadSaveDataInfoImpl(out long readCount, Span<SaveDataInfo> buffer)
|
||||
{
|
||||
var outBuffer = new OutBuffer(MemoryMarshal.Cast<SaveDataInfo, byte>(buffer));
|
||||
return Reader.Target.Read(out readCount, outBuffer);
|
||||
Result rc = _reader.Get.Read(out readCount, OutBuffer.FromSpan(buffer));
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result ReadSaveDataInfo(out long readCount, Span<SaveDataInfo> buffer)
|
||||
{
|
||||
Result rc;
|
||||
FileSystemClient fs = FsClient;
|
||||
FileSystemClient fs = _fsClient;
|
||||
Span<byte> logBuffer = stackalloc byte[0x50];
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
|
||||
@ -55,12 +61,9 @@ namespace LibHac.Fs.Shim
|
||||
}
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Reader?.Dispose();
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,9 +75,9 @@ namespace LibHac.Fs.Shim
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out extraData);
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.ReadSaveDataFileSystemExtraData(OutBuffer.FromStruct(ref extraData), saveDataId);
|
||||
Result rc = fileSystemProxy.Get.ReadSaveDataFileSystemExtraData(OutBuffer.FromStruct(ref extraData), saveDataId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
@ -85,9 +88,9 @@ namespace LibHac.Fs.Shim
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out extraData);
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.ReadSaveDataFileSystemExtraDataBySaveDataSpaceId(
|
||||
Result rc = fileSystemProxy.Get.ReadSaveDataFileSystemExtraDataBySaveDataSpaceId(
|
||||
OutBuffer.FromStruct(ref extraData), spaceId, saveDataId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
@ -99,9 +102,9 @@ namespace LibHac.Fs.Shim
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out extraData);
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.ReadSaveDataFileSystemExtraDataBySaveDataAttribute(
|
||||
Result rc = fileSystemProxy.Get.ReadSaveDataFileSystemExtraDataBySaveDataAttribute(
|
||||
OutBuffer.FromStruct(ref extraData), spaceId, in attribute);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
@ -114,9 +117,9 @@ namespace LibHac.Fs.Shim
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out extraData);
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute(
|
||||
Result rc = fileSystemProxy.Get.ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute(
|
||||
OutBuffer.FromStruct(ref extraData), spaceId, in attribute, InBuffer.FromStruct(in extraDataMask));
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
@ -137,12 +140,14 @@ namespace LibHac.Fs.Shim
|
||||
public static Result WriteSaveDataFileSystemExtraData(this FileSystemClientImpl fs, SaveDataSpaceId spaceId,
|
||||
ulong saveDataId, in SaveDataExtraData extraData)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.WriteSaveDataFileSystemExtraData(saveDataId, spaceId,
|
||||
Result rc = fileSystemProxy.Get.WriteSaveDataFileSystemExtraData(saveDataId, spaceId,
|
||||
InBuffer.FromStruct(in extraData));
|
||||
fs.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -166,12 +171,14 @@ namespace LibHac.Fs.Shim
|
||||
public static Result WriteSaveDataFileSystemExtraData(this FileSystemClientImpl fs, SaveDataSpaceId spaceId,
|
||||
ulong saveDataId, in SaveDataExtraData extraData, in SaveDataExtraData extraDataMask)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.WriteSaveDataFileSystemExtraDataWithMask(saveDataId, spaceId,
|
||||
Result rc = fileSystemProxy.Get.WriteSaveDataFileSystemExtraDataWithMask(saveDataId, spaceId,
|
||||
InBuffer.FromStruct(in extraData), InBuffer.FromStruct(in extraDataMask));
|
||||
fs.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -198,12 +205,14 @@ namespace LibHac.Fs.Shim
|
||||
public static Result WriteSaveDataFileSystemExtraData(this FileSystemClientImpl fs, SaveDataSpaceId spaceId,
|
||||
in SaveDataAttribute attribute, in SaveDataExtraData extraData, in SaveDataExtraData extraDataMask)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.WriteSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute(in attribute,
|
||||
Result rc = fileSystemProxy.Get.WriteSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute(in attribute,
|
||||
spaceId, InBuffer.FromStruct(in extraData), InBuffer.FromStruct(in extraDataMask));
|
||||
fs.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result FindSaveDataWithFilter(this FileSystemClientImpl fs, out SaveDataInfo saveInfo,
|
||||
@ -211,12 +220,12 @@ namespace LibHac.Fs.Shim
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out saveInfo);
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
|
||||
Unsafe.SkipInit(out SaveDataInfo tempInfo);
|
||||
OutBuffer saveInfoBuffer = OutBuffer.FromStruct(ref tempInfo);
|
||||
|
||||
Result rc = fsProxy.Target.FindSaveDataWithFilter(out long count, saveInfoBuffer, spaceId, in filter);
|
||||
Result rc = fileSystemProxy.Get.FindSaveDataWithFilter(out long count, saveInfoBuffer, spaceId, in filter);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (count == 0)
|
||||
@ -229,7 +238,7 @@ namespace LibHac.Fs.Shim
|
||||
public static Result CreateSaveData(this FileSystemClientImpl fs, Ncm.ApplicationId applicationId,
|
||||
UserId userId, ulong ownerId, long size, long journalSize, SaveDataFlags flags)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Account,
|
||||
userId, 0);
|
||||
@ -242,13 +251,16 @@ namespace LibHac.Fs.Shim
|
||||
var metaPolicy = new SaveDataMetaPolicy(SaveDataType.Account);
|
||||
metaPolicy.GenerateMetaInfo(out SaveDataMetaInfo metaInfo);
|
||||
|
||||
return fsProxy.Target.CreateSaveDataFileSystem(in attribute, in creationInfo, in metaInfo);
|
||||
rc = fileSystemProxy.Get.CreateSaveDataFileSystem(in attribute, in creationInfo, in metaInfo);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result CreateBcatSaveData(this FileSystemClientImpl fs, Ncm.ApplicationId applicationId,
|
||||
long size)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Bcat,
|
||||
Fs.SaveData.InvalidUserId, 0);
|
||||
@ -265,13 +277,16 @@ namespace LibHac.Fs.Shim
|
||||
Size = 0
|
||||
};
|
||||
|
||||
return fsProxy.Target.CreateSaveDataFileSystem(in attribute, in creationInfo, in metaInfo);
|
||||
rc = fileSystemProxy.Get.CreateSaveDataFileSystem(in attribute, in creationInfo, in metaInfo);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result CreateDeviceSaveData(this FileSystemClientImpl fs, Ncm.ApplicationId applicationId,
|
||||
ulong ownerId, long size, long journalSize, SaveDataFlags flags)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Device,
|
||||
Fs.SaveData.InvalidUserId, 0);
|
||||
@ -284,13 +299,16 @@ namespace LibHac.Fs.Shim
|
||||
var metaPolicy = new SaveDataMetaPolicy(SaveDataType.Device);
|
||||
metaPolicy.GenerateMetaInfo(out SaveDataMetaInfo metaInfo);
|
||||
|
||||
return fsProxy.Target.CreateSaveDataFileSystem(in attribute, in creationInfo, in metaInfo);
|
||||
rc = fileSystemProxy.Get.CreateSaveDataFileSystem(in attribute, in creationInfo, in metaInfo);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result CreateCacheStorage(this FileSystemClientImpl fs, Ncm.ApplicationId applicationId,
|
||||
SaveDataSpaceId spaceId, ulong ownerId, ushort index, long size, long journalSize, SaveDataFlags flags)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Cache,
|
||||
Fs.SaveData.InvalidUserId, 0, index);
|
||||
@ -306,27 +324,30 @@ namespace LibHac.Fs.Shim
|
||||
Size = 0
|
||||
};
|
||||
|
||||
return fsProxy.Target.CreateSaveDataFileSystem(in attribute, in creationInfo, in metaInfo);
|
||||
rc = fileSystemProxy.Get.CreateSaveDataFileSystem(in attribute, in creationInfo, in metaInfo);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result CreateSaveData(this FileSystemClientImpl fs, in SaveDataAttribute attribute,
|
||||
in SaveDataCreationInfo creationInfo, in SaveDataMetaInfo metaInfo, in HashSalt hashSalt)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
return fsProxy.Target.CreateSaveDataFileSystemWithHashSalt(in attribute, in creationInfo,
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
return fileSystemProxy.Get.CreateSaveDataFileSystemWithHashSalt(in attribute, in creationInfo,
|
||||
in metaInfo, in hashSalt);
|
||||
}
|
||||
|
||||
public static Result DeleteSaveData(this FileSystemClientImpl fs, ulong saveDataId)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
return fsProxy.Target.DeleteSaveDataFileSystem(saveDataId);
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
return fileSystemProxy.Get.DeleteSaveDataFileSystem(saveDataId);
|
||||
}
|
||||
|
||||
public static Result DeleteSaveData(this FileSystemClientImpl fs, SaveDataSpaceId spaceId, ulong saveDataId)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
return fsProxy.Target.DeleteSaveDataFileSystemBySaveDataSpaceId(spaceId, saveDataId);
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
return fileSystemProxy.Get.DeleteSaveDataFileSystemBySaveDataSpaceId(spaceId, saveDataId);
|
||||
}
|
||||
|
||||
public static Result DeleteSaveData(this FileSystemClient fs, ulong saveDataId)
|
||||
@ -413,13 +434,13 @@ namespace LibHac.Fs.Shim
|
||||
|
||||
static Result Delete(FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId, UserId userId)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, Fs.SaveData.InvalidProgramId,
|
||||
SaveDataType.System, userId, saveDataId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return fsProxy.Target.DeleteSaveDataFileSystemBySaveDataAttribute(spaceId, in attribute);
|
||||
return fileSystemProxy.Get.DeleteSaveDataFileSystemBySaveDataAttribute(spaceId, in attribute);
|
||||
}
|
||||
}
|
||||
|
||||
@ -449,70 +470,62 @@ namespace LibHac.Fs.Shim
|
||||
|
||||
static Result Delete(FileSystemClient fs, ApplicationId applicationId)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, new ProgramId(applicationId.Value),
|
||||
SaveDataType.Device, Fs.SaveData.InvalidUserId, 0);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return fsProxy.Target.DeleteSaveDataFileSystemBySaveDataAttribute(SaveDataSpaceId.User, in attribute);
|
||||
return fileSystemProxy.Get.DeleteSaveDataFileSystemBySaveDataAttribute(SaveDataSpaceId.User, in attribute);
|
||||
}
|
||||
}
|
||||
|
||||
public static Result RegisterSaveDataAtomicDeletion(this FileSystemClient fs,
|
||||
ReadOnlySpan<ulong> saveDataIdList)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
var listBytes = new InBuffer(MemoryMarshal.Cast<ulong, byte>(saveDataIdList));
|
||||
|
||||
Result rc = fsProxy.Target.RegisterSaveDataFileSystemAtomicDeletion(listBytes);
|
||||
Result rc = fileSystemProxy.Get.RegisterSaveDataFileSystemAtomicDeletion(InBuffer.FromSpan(saveDataIdList));
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
public static Result OpenSaveDataIterator(this FileSystemClientImpl fs, out SaveDataIterator iterator,
|
||||
SaveDataSpaceId spaceId)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out iterator);
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
|
||||
ReferenceCountedDisposable<ISaveDataInfoReader> reader = null;
|
||||
try
|
||||
{
|
||||
Result rc = fsProxy.Target.OpenSaveDataInfoReaderBySaveDataSpaceId(out reader, spaceId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
iterator = new SaveDataIterator(fs.Fs, ref reader);
|
||||
}
|
||||
finally
|
||||
{
|
||||
reader?.Dispose();
|
||||
}
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result OpenSaveDataIterator(this FileSystemClientImpl fs, out SaveDataIterator iterator,
|
||||
SaveDataSpaceId spaceId, in SaveDataFilter filter)
|
||||
public static Result OpenSaveDataIterator(this FileSystemClientImpl fs,
|
||||
ref UniqueRef<SaveDataIterator> outIterator, SaveDataSpaceId spaceId)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out iterator);
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
using var reader = new SharedRef<ISaveDataInfoReader>();
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
Result rc = fileSystemProxy.Get.OpenSaveDataInfoReaderBySaveDataSpaceId(ref reader.Ref(), spaceId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
ReferenceCountedDisposable<ISaveDataInfoReader> reader = null;
|
||||
try
|
||||
{
|
||||
Result rc = fsProxy.Target.OpenSaveDataInfoReaderWithFilter(out reader, spaceId, in filter);
|
||||
if (rc.IsFailure()) return rc;
|
||||
var iterator = new UniqueRef<SaveDataIterator>(new SaveDataIterator(fs.Fs, ref reader.Ref()));
|
||||
|
||||
iterator = new SaveDataIterator(fs.Fs, ref reader);
|
||||
}
|
||||
finally
|
||||
{
|
||||
reader?.Dispose();
|
||||
}
|
||||
if (!iterator.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInSaveDataManagementA.Log();
|
||||
|
||||
outIterator.Set(ref iterator);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result OpenSaveDataIterator(this FileSystemClientImpl fs,
|
||||
ref UniqueRef<SaveDataIterator> outIterator, SaveDataSpaceId spaceId, in SaveDataFilter filter)
|
||||
{
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
using var reader = new SharedRef<ISaveDataInfoReader>();
|
||||
|
||||
Result rc = fileSystemProxy.Get.OpenSaveDataInfoReaderWithFilter(ref reader.Ref(), spaceId, in filter);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
var iterator = new UniqueRef<SaveDataIterator>(new SaveDataIterator(fs.Fs, ref reader.Ref()));
|
||||
|
||||
if (!iterator.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInSaveDataManagementA.Log();
|
||||
|
||||
outIterator.Set(ref iterator);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
@ -520,10 +533,13 @@ namespace LibHac.Fs.Shim
|
||||
public static Result ReadSaveDataIteratorSaveDataInfo(out long readCount, Span<SaveDataInfo> buffer,
|
||||
in SaveDataIterator iterator)
|
||||
{
|
||||
return iterator.ReadSaveDataInfo(out readCount, buffer);
|
||||
Result rc = iterator.ReadSaveDataInfo(out readCount, buffer);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result OpenSaveDataIterator(this FileSystemClient fs, out SaveDataIterator iterator,
|
||||
public static Result OpenSaveDataIterator(this FileSystemClient fs, ref UniqueRef<SaveDataIterator> outIterator,
|
||||
SaveDataSpaceId spaceId)
|
||||
{
|
||||
Result rc;
|
||||
@ -532,7 +548,7 @@ namespace LibHac.Fs.Shim
|
||||
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fs.Impl.OpenSaveDataIterator(out iterator, spaceId);
|
||||
rc = fs.Impl.OpenSaveDataIterator(ref outIterator, spaceId);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var idString = new IdString();
|
||||
@ -543,14 +559,14 @@ namespace LibHac.Fs.Shim
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fs.Impl.OpenSaveDataIterator(out iterator, spaceId);
|
||||
rc = fs.Impl.OpenSaveDataIterator(ref outIterator, spaceId);
|
||||
}
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
public static Result OpenSaveDataIterator(this FileSystemClient fs, out SaveDataIterator iterator,
|
||||
public static Result OpenSaveDataIterator(this FileSystemClient fs, ref UniqueRef<SaveDataIterator> outIterator,
|
||||
SaveDataSpaceId spaceId, in SaveDataFilter filter)
|
||||
{
|
||||
Result rc;
|
||||
@ -559,7 +575,7 @@ namespace LibHac.Fs.Shim
|
||||
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fs.Impl.OpenSaveDataIterator(out iterator, spaceId, in filter);
|
||||
rc = fs.Impl.OpenSaveDataIterator(ref outIterator, spaceId, in filter);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var idString = new IdString();
|
||||
@ -570,7 +586,7 @@ namespace LibHac.Fs.Shim
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fs.Impl.OpenSaveDataIterator(out iterator, spaceId, in filter);
|
||||
rc = fs.Impl.OpenSaveDataIterator(ref outIterator, spaceId, in filter);
|
||||
}
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
@ -668,7 +684,7 @@ namespace LibHac.Fs.Shim
|
||||
static Result CreateSave(FileSystemClient fs, Ncm.ApplicationId applicationId, UserId userId,
|
||||
ulong ownerId, long size, long journalSize, in HashSalt hashSalt, SaveDataFlags flags)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Account,
|
||||
userId, 0);
|
||||
@ -681,7 +697,7 @@ namespace LibHac.Fs.Shim
|
||||
var metaPolicy = new SaveDataMetaPolicy(SaveDataType.Account);
|
||||
metaPolicy.GenerateMetaInfo(out SaveDataMetaInfo metaInfo);
|
||||
|
||||
return fsProxy.Target.CreateSaveDataFileSystemWithHashSalt(in attribute, in creationInfo, in metaInfo,
|
||||
return fileSystemProxy.Get.CreateSaveDataFileSystemWithHashSalt(in attribute, in creationInfo, in metaInfo,
|
||||
in hashSalt);
|
||||
}
|
||||
}
|
||||
@ -745,7 +761,7 @@ namespace LibHac.Fs.Shim
|
||||
public static Result CreateTemporaryStorage(this FileSystemClientImpl fs, Ncm.ApplicationId applicationId,
|
||||
ulong ownerId, long size, SaveDataFlags flags)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Temporary,
|
||||
Fs.SaveData.InvalidUserId, 0);
|
||||
@ -761,7 +777,7 @@ namespace LibHac.Fs.Shim
|
||||
Size = 0
|
||||
};
|
||||
|
||||
return fsProxy.Target.CreateSaveDataFileSystem(in attribute, in creationInfo, in metaInfo);
|
||||
return fileSystemProxy.Get.CreateSaveDataFileSystem(in attribute, in creationInfo, in metaInfo);
|
||||
}
|
||||
|
||||
public static Result CreateTemporaryStorage(this FileSystemClient fs, Ncm.ApplicationId applicationId,
|
||||
@ -872,7 +888,7 @@ namespace LibHac.Fs.Shim
|
||||
static Result CreateSave(FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId, UserId userId,
|
||||
ulong ownerId, long size, long journalSize, SaveDataFlags flags)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, Fs.SaveData.InvalidProgramId,
|
||||
SaveDataType.System, userId, saveDataId);
|
||||
@ -882,7 +898,7 @@ namespace LibHac.Fs.Shim
|
||||
spaceId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return fsProxy.Target.CreateSaveDataFileSystemBySystemSaveDataId(in attribute, in creationInfo);
|
||||
return fileSystemProxy.Get.CreateSaveDataFileSystemBySystemSaveDataId(in attribute, in creationInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@ -921,9 +937,9 @@ namespace LibHac.Fs.Shim
|
||||
public static Result ExtendSaveData(this FileSystemClientImpl fs, SaveDataSpaceId spaceId, ulong saveDataId,
|
||||
long saveDataSize, long journalSize)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
|
||||
return fsProxy.Target.ExtendSaveDataFileSystem(spaceId, saveDataId, saveDataSize, journalSize);
|
||||
return fileSystemProxy.Get.ExtendSaveDataFileSystem(spaceId, saveDataId, saveDataSize, journalSize);
|
||||
}
|
||||
|
||||
public static Result ExtendSaveData(this FileSystemClient fs, ulong saveDataId, long saveDataSize,
|
||||
@ -995,13 +1011,13 @@ namespace LibHac.Fs.Shim
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out totalSize);
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.QuerySaveDataTotalSize(out long tempTotalSize, size, journalSize);
|
||||
if (rc.IsSuccess())
|
||||
totalSize = tempTotalSize;
|
||||
Result rc = fileSystemProxy.Get.QuerySaveDataTotalSize(out long tempTotalSize, size, journalSize);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return rc;
|
||||
totalSize = tempTotalSize;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result QuerySaveDataTotalSize(this FileSystemClient fs, out long totalSize, long size,
|
||||
@ -1295,9 +1311,9 @@ namespace LibHac.Fs.Shim
|
||||
var idString = new IdString();
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
|
||||
sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
|
||||
.Append(LogSaveDataId).AppendFormat(saveDataId, 'X')
|
||||
sb.Append(LogSaveDataId).AppendFormat(saveDataId, 'X')
|
||||
.Append(LogUserId).AppendFormat(userId.Id.High, 'X', 16).AppendFormat(userId.Id.Low, 'X', 16)
|
||||
.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
|
||||
.Append(LogSaveDataFlags).AppendFormat((int)flags, 'X', 8);
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
|
||||
@ -1636,9 +1652,9 @@ namespace LibHac.Fs.Shim
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out commitId);
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
return fsProxy.Target.GetSaveDataCommitId(out commitId, spaceId, saveDataId);
|
||||
return fileSystemProxy.Get.GetSaveDataCommitId(out commitId, spaceId, saveDataId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1688,9 +1704,9 @@ namespace LibHac.Fs.Shim
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out size);
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
|
||||
return fsProxy.Target.QuerySaveDataInternalStorageTotalSize(out size, spaceId, saveDataId);
|
||||
return fileSystemProxy.Get.QuerySaveDataInternalStorageTotalSize(out size, spaceId, saveDataId);
|
||||
}
|
||||
|
||||
public static Result QuerySaveDataInternalStorageTotalSize(this FileSystemClient fs, out long size,
|
||||
@ -1733,9 +1749,9 @@ namespace LibHac.Fs.Shim
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out isValid);
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.VerifySaveDataFileSystemBySaveDataSpaceId(spaceId, saveDataId,
|
||||
Result rc = fileSystemProxy.Get.VerifySaveDataFileSystemBySaveDataSpaceId(spaceId, saveDataId,
|
||||
new OutBuffer(workBuffer));
|
||||
|
||||
if (ResultFs.DataCorrupted.Includes(rc))
|
||||
@ -1763,9 +1779,9 @@ namespace LibHac.Fs.Shim
|
||||
public static Result CorruptSaveDataForDebug(this FileSystemClient fs, SaveDataSpaceId spaceId,
|
||||
ulong saveDataId)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.CorruptSaveDataFileSystemBySaveDataSpaceId(spaceId, saveDataId);
|
||||
Result rc = fileSystemProxy.Get.CorruptSaveDataFileSystemBySaveDataSpaceId(spaceId, saveDataId);
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
@ -1774,9 +1790,9 @@ namespace LibHac.Fs.Shim
|
||||
public static Result CorruptSaveDataForDebug(this FileSystemClient fs, SaveDataSpaceId spaceId,
|
||||
ulong saveDataId, long offset)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.CorruptSaveDataFileSystemByOffset(spaceId, saveDataId, offset);
|
||||
Result rc = fileSystemProxy.Get.CorruptSaveDataFileSystemByOffset(spaceId, saveDataId, offset);
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
@ -1784,9 +1800,9 @@ namespace LibHac.Fs.Shim
|
||||
|
||||
public static void DisableAutoSaveDataCreation(this FileSystemClient fs)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.DisableAutoSaveDataCreation();
|
||||
Result rc = fileSystemProxy.Get.DisableAutoSaveDataCreation();
|
||||
|
||||
fs.Impl.LogResultErrorMessage(rc);
|
||||
Abort.DoAbortUnless(rc.IsSuccess());
|
||||
@ -1821,9 +1837,9 @@ namespace LibHac.Fs.Shim
|
||||
if (index < 0)
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
return fsProxy.Target.DeleteCacheStorage((ushort)index);
|
||||
return fileSystemProxy.Get.DeleteCacheStorage((ushort)index);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1863,18 +1879,18 @@ namespace LibHac.Fs.Shim
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
// Note: Nintendo gets the service object in the outer function and captures it for the inner function
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
return fsProxy.Target.GetCacheStorageSize(out saveSize, out journalSize, (ushort)index);
|
||||
return fileSystemProxy.Get.GetCacheStorageSize(out saveSize, out journalSize, (ushort)index);
|
||||
}
|
||||
}
|
||||
|
||||
public static Result UpdateSaveDataMacForDebug(this FileSystemClient fs, SaveDataSpaceId spaceId,
|
||||
ulong saveDataId)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
return fsProxy.Target.UpdateSaveDataMacForDebug(spaceId, saveDataId);
|
||||
return fileSystemProxy.Get.UpdateSaveDataMacForDebug(spaceId, saveDataId);
|
||||
}
|
||||
|
||||
public static Result ListApplicationAccessibleSaveDataOwnerId(this FileSystemClient fs, out int readCount,
|
||||
@ -1886,12 +1902,12 @@ namespace LibHac.Fs.Shim
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
var programId = new ProgramId(applicationId.Value + (uint)programIndex);
|
||||
var idOutBuffer = new OutBuffer(MemoryMarshal.Cast<Ncm.ApplicationId, byte>(idBuffer));
|
||||
OutBuffer idOutBuffer = OutBuffer.FromSpan(idBuffer);
|
||||
|
||||
Result rc = fsProxy.Target.ListAccessibleSaveDataOwnerId(out readCount, idOutBuffer, programId, startIndex,
|
||||
Result rc = fileSystemProxy.Get.ListAccessibleSaveDataOwnerId(out readCount, idOutBuffer, programId, startIndex,
|
||||
idBuffer.Length);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
@ -1913,7 +1929,7 @@ namespace LibHac.Fs.Shim
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
sb.Append(LogName).Append(mountName).Append((byte)'"');
|
||||
sb.Append(LogName).Append(mountName).Append(LogQuote);
|
||||
|
||||
fs.Impl.OutputAccessLogUnlessResultSuccess(rc, start, end, null, new U8Span(sb.Buffer));
|
||||
}
|
||||
@ -1936,7 +1952,7 @@ namespace LibHac.Fs.Shim
|
||||
AccessLogImpl.DereferenceOutValue(in isRestoreFlagSet, rc));
|
||||
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
sb.Append(LogName).Append(mountName).Append((byte)'"')
|
||||
sb.Append(LogName).Append(mountName).Append(LogQuote)
|
||||
.Append(LogRestoreFlag).Append(isSetString);
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
|
||||
@ -1975,13 +1991,13 @@ namespace LibHac.Fs.Shim
|
||||
}
|
||||
}
|
||||
|
||||
public static Result GetDeviceSaveDataSize(this FileSystemClientImpl fs, out long saveSize,
|
||||
public static Result GetDeviceSaveDataSize(this FileSystemClient fs, out long saveSize,
|
||||
out long journalSize, ApplicationId applicationId)
|
||||
{
|
||||
Result rc;
|
||||
Span<byte> logBuffer = stackalloc byte[0x70];
|
||||
|
||||
if (fs.IsEnabledAccessLog() && fs.IsEnabledHandleAccessLog(null))
|
||||
if (fs.Impl.IsEnabledAccessLog() && fs.Impl.IsEnabledHandleAccessLog(null))
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = GetSize(fs, out saveSize, out journalSize, applicationId);
|
||||
@ -1993,17 +2009,17 @@ namespace LibHac.Fs.Shim
|
||||
.Append(LogSaveDataJournalSize)
|
||||
.AppendFormat(AccessLogImpl.DereferenceOutValue(in journalSize, rc), 'd');
|
||||
|
||||
fs.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = GetSize(fs, out saveSize, out journalSize, applicationId);
|
||||
}
|
||||
|
||||
fs.AbortIfNeeded(rc);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
|
||||
static Result GetSize(FileSystemClientImpl fs, out long saveSize, out long journalSize,
|
||||
static Result GetSize(FileSystemClient fs, out long saveSize, out long journalSize,
|
||||
ApplicationId applicationId)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out saveSize, out journalSize);
|
||||
@ -2016,7 +2032,7 @@ namespace LibHac.Fs.Shim
|
||||
SaveDataType.Device, Fs.SaveData.InvalidUserId, 0);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = fs.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, SaveDataSpaceId.User,
|
||||
rc = fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, SaveDataSpaceId.User,
|
||||
in attribute, in extraDataMask);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
|
@ -7,6 +7,7 @@ using LibHac.Fs.Impl;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.Os;
|
||||
using static LibHac.Fs.Impl.AccessLogStrings;
|
||||
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
|
||||
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
|
||||
|
||||
namespace LibHac.Fs.Shim
|
||||
@ -14,25 +15,22 @@ namespace LibHac.Fs.Shim
|
||||
[SkipLocalsInit]
|
||||
public static class SdCard
|
||||
{
|
||||
private static Result OpenSdCardFileSystem(FileSystemClient fs,
|
||||
out ReferenceCountedDisposable<IFileSystemSf> fileSystem)
|
||||
private static Result OpenSdCardFileSystem(FileSystemClient fs, ref SharedRef<IFileSystemSf> outFileSystem)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
return OpenFileSystem(fs, fsProxy, out fileSystem);
|
||||
return OpenFileSystem(fs, ref fileSystemProxy.Ref(), ref outFileSystem);
|
||||
|
||||
static Result OpenFileSystem(FileSystemClient fs, ReferenceCountedDisposable<IFileSystemProxy> fsProxy,
|
||||
out ReferenceCountedDisposable<IFileSystemSf> fileSystem)
|
||||
static Result OpenFileSystem(FileSystemClient fs, ref SharedRef<IFileSystemProxy> fileSystemProxy,
|
||||
ref SharedRef<IFileSystemSf> outFileSystem)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
|
||||
// Retry a few times if the storage device isn't ready yet
|
||||
const int maxRetries = 10;
|
||||
const int retryInterval = 1000;
|
||||
|
||||
for (int i = 0; i < maxRetries; i++)
|
||||
{
|
||||
Result rc = fsProxy.Target.OpenSdCardFileSystem(out fileSystem);
|
||||
Result rc = fileSystemProxy.Get.OpenSdCardFileSystem(ref outFileSystem);
|
||||
|
||||
if (rc.IsSuccess())
|
||||
break;
|
||||
@ -51,10 +49,15 @@ namespace LibHac.Fs.Shim
|
||||
}
|
||||
|
||||
private static Result RegisterFileSystem(FileSystemClient fs, U8Span mountName,
|
||||
ReferenceCountedDisposable<IFileSystemSf> fileSystem)
|
||||
ref SharedRef<IFileSystemSf> fileSystem)
|
||||
{
|
||||
var fileSystemAdapter = new FileSystemServiceObjectAdapter(fileSystem);
|
||||
return fs.Register(mountName, fileSystemAdapter);
|
||||
using var fileSystemAdapter =
|
||||
new UniqueRef<IFileSystem>(new FileSystemServiceObjectAdapter(ref fileSystem));
|
||||
|
||||
if (!fileSystemAdapter.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInSdCardA.Log();
|
||||
|
||||
return fs.Register(mountName, ref fileSystemAdapter.Ref());
|
||||
}
|
||||
|
||||
public static Result MountSdCard(this FileSystemClient fs, U8Span mountName)
|
||||
@ -79,79 +82,69 @@ namespace LibHac.Fs.Shim
|
||||
{
|
||||
rc = fs.Impl.CheckMountName(mountName);
|
||||
}
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
// Open the SD card file system
|
||||
ReferenceCountedDisposable<IFileSystemSf> fileSystem = null;
|
||||
try
|
||||
using var fileSystem = new SharedRef<IFileSystemSf>();
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System))
|
||||
{
|
||||
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System))
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = OpenSdCardFileSystem(fs, out fileSystem);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = OpenSdCardFileSystem(fs, ref fileSystem.Ref());
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
fs.Impl.OutputAccessLogUnlessResultSuccess(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = OpenSdCardFileSystem(fs, out fileSystem);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
// Mount the file system
|
||||
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System))
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = RegisterFileSystem(fs, mountName, fileSystem);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = RegisterFileSystem(fs, mountName, fileSystem);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System))
|
||||
fs.Impl.EnableFileSystemAccessorAccessLog(mountName);
|
||||
|
||||
return Result.Success;
|
||||
fs.Impl.OutputAccessLogUnlessResultSuccess(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
finally
|
||||
else
|
||||
{
|
||||
fileSystem?.Dispose();
|
||||
rc = OpenSdCardFileSystem(fs, ref fileSystem.Ref());
|
||||
}
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
// Mount the file system
|
||||
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System))
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = RegisterFileSystem(fs, mountName, ref fileSystem.Ref());
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = RegisterFileSystem(fs, mountName, ref fileSystem.Ref());
|
||||
}
|
||||
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System))
|
||||
fs.Impl.EnableFileSystemAccessorAccessLog(mountName);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static bool IsSdCardInserted(this FileSystemClient fs)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||
|
||||
ReferenceCountedDisposable<IDeviceOperator> deviceOperator = null;
|
||||
try
|
||||
{
|
||||
Result rc = fsProxy.Target.OpenDeviceOperator(out deviceOperator);
|
||||
fs.Impl.LogResultErrorMessage(rc);
|
||||
Abort.DoAbortUnless(rc.IsSuccess());
|
||||
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||
fs.Impl.LogResultErrorMessage(rc);
|
||||
Abort.DoAbortUnless(rc.IsSuccess());
|
||||
|
||||
rc = CheckIfInserted(fs, deviceOperator, out bool isInserted);
|
||||
fs.Impl.LogResultErrorMessage(rc);
|
||||
Abort.DoAbortUnless(rc.IsSuccess());
|
||||
rc = CheckIfInserted(fs, ref deviceOperator.Ref(), out bool isInserted);
|
||||
fs.Impl.LogResultErrorMessage(rc);
|
||||
Abort.DoAbortUnless(rc.IsSuccess());
|
||||
|
||||
return isInserted;
|
||||
}
|
||||
finally
|
||||
{
|
||||
deviceOperator?.Dispose();
|
||||
}
|
||||
return isInserted;
|
||||
|
||||
static Result CheckIfInserted(FileSystemClient fs,
|
||||
ReferenceCountedDisposable<IDeviceOperator> deviceOperator, out bool isInserted)
|
||||
static Result CheckIfInserted(FileSystemClient fs, ref SharedRef<IDeviceOperator> deviceOperator,
|
||||
out bool isInserted)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out isInserted);
|
||||
|
||||
@ -161,7 +154,7 @@ namespace LibHac.Fs.Shim
|
||||
|
||||
for (int i = 0; i < maxRetries; i++)
|
||||
{
|
||||
Result rc = deviceOperator.Target.IsSdCardInserted(out isInserted);
|
||||
Result rc = deviceOperator.Get.IsSdCardInserted(out isInserted);
|
||||
|
||||
if (rc.IsSuccess())
|
||||
break;
|
||||
@ -181,9 +174,9 @@ namespace LibHac.Fs.Shim
|
||||
|
||||
public static Result SetSdCardEncryptionSeed(this FileSystemClient fs, in EncryptionSeed seed)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.SetSdCardEncryptionSeed(in seed);
|
||||
Result rc = fileSystemProxy.Get.SetSdCardEncryptionSeed(in seed);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
@ -197,9 +190,9 @@ namespace LibHac.Fs.Shim
|
||||
|
||||
public static bool IsSdCardAccessible(this FileSystemClient fs)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.IsSdCardAccessible(out bool isAccessible);
|
||||
Result rc = fileSystemProxy.Get.IsSdCardAccessible(out bool isAccessible);
|
||||
fs.Impl.LogResultErrorMessage(rc);
|
||||
Abort.DoAbortUnless(rc.IsSuccess());
|
||||
|
||||
@ -208,9 +201,9 @@ namespace LibHac.Fs.Shim
|
||||
|
||||
public static Result SetSdCardAccessibility(this FileSystemClientImpl fs, bool isAccessible)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.SetSdCardAccessibility(isAccessible);
|
||||
Result rc = fileSystemProxy.Get.SetSdCardAccessibility(isAccessible);
|
||||
fs.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ using LibHac.Fs.Impl;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.Os;
|
||||
using static LibHac.Fs.Impl.AccessLogStrings;
|
||||
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
|
||||
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
|
||||
|
||||
namespace LibHac.Fs.Shim
|
||||
@ -65,32 +66,32 @@ namespace LibHac.Fs.Shim
|
||||
Result rc = fs.Impl.CheckMountName(mountName);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, Fs.SaveData.InvalidProgramId,
|
||||
SaveDataType.System, userId, saveDataId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
ReferenceCountedDisposable<IFileSystemSf> fileSystem = null;
|
||||
try
|
||||
using var fileSystem = new SharedRef<IFileSystemSf>();
|
||||
|
||||
rc = fileSystemProxy.Get.OpenSaveDataFileSystemBySystemSaveDataId(ref fileSystem.Ref(), spaceId, in attribute);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
var fileSystemAdapterRaw = new FileSystemServiceObjectAdapter(ref fileSystem.Ref());
|
||||
using var fileSystemAdapter = new UniqueRef<IFileSystem>(fileSystemAdapterRaw);
|
||||
|
||||
if (!fileSystemAdapter.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInSystemSaveDataA.Log();
|
||||
|
||||
if (spaceId == SaveDataSpaceId.System)
|
||||
{
|
||||
rc = fsProxy.Target.OpenSaveDataFileSystemBySystemSaveDataId(out fileSystem, spaceId, in attribute);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
var fileSystemAdapter = new FileSystemServiceObjectAdapter(fileSystem);
|
||||
|
||||
if (spaceId == SaveDataSpaceId.System)
|
||||
{
|
||||
return fs.Register(mountName, fileSystemAdapter, fileSystemAdapter, null, false, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
return fs.Register(mountName, fileSystemAdapter);
|
||||
}
|
||||
using var mountNameGenerator = new UniqueRef<ICommonMountNameGenerator>();
|
||||
return fs.Register(mountName, fileSystemAdapterRaw, ref fileSystemAdapter.Ref(),
|
||||
ref mountNameGenerator.Ref(), false, false);
|
||||
}
|
||||
finally
|
||||
else
|
||||
{
|
||||
fileSystem?.Dispose();
|
||||
return fs.Register(mountName, ref fileSystemAdapter.Ref());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,51 +21,35 @@ namespace LibHac.Fs
|
||||
/// </remarks>
|
||||
public class SubStorage : IStorage
|
||||
{
|
||||
private ReferenceCountedDisposable<IStorage> SharedBaseStorage { get; set; }
|
||||
protected IStorage BaseStorage { get; private set; }
|
||||
private long Offset { get; set; }
|
||||
private long Size { get; set; }
|
||||
private bool IsResizable { get; set; }
|
||||
private SharedRef<IStorage> _sharedBaseStorage;
|
||||
protected IStorage BaseStorage;
|
||||
private long _offset;
|
||||
private long _size;
|
||||
private bool _isResizable;
|
||||
|
||||
/// <summary>
|
||||
/// Creates an uninitialized <see cref="SubStorage"/>. It must be initialized with <see cref="InitializeFrom"/> before using.
|
||||
/// Creates an uninitialized <see cref="SubStorage"/>. It must be initialized with <see cref="Set"/> before using.
|
||||
/// </summary>
|
||||
public SubStorage()
|
||||
{
|
||||
BaseStorage = null;
|
||||
Offset = 0;
|
||||
Size = 0;
|
||||
IsResizable = false;
|
||||
_offset = 0;
|
||||
_size = 0;
|
||||
_isResizable = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a copy of <paramref name="other"/>.
|
||||
/// Initializes a new <see cref="SubStorage"/> as a copy of <paramref name="other"/>.
|
||||
/// <paramref name="other"/> will not be disposed when the created <see cref="SubStorage"/> is disposed.
|
||||
/// </summary>
|
||||
/// <param name="other">The <see cref="SubStorage"/> to create a copy of. Caller retains ownership.</param>
|
||||
/// <param name="other">The <see cref="SubStorage"/> to create a copy of.</param>
|
||||
public SubStorage(SubStorage other)
|
||||
{
|
||||
BaseStorage = other.BaseStorage;
|
||||
Offset = other.Offset;
|
||||
Size = other.Size;
|
||||
IsResizable = other.IsResizable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes or reinitializes this <see cref="SubStorage"/> as a copy of <paramref name="other"/>.
|
||||
/// Any shared references in <paramref name="other"/> will be copied.
|
||||
/// </summary>
|
||||
/// <param name="other">The <see cref="SubStorage"/> used to initialize this one.</param>
|
||||
public void InitializeFrom(SubStorage other)
|
||||
{
|
||||
if (this != other)
|
||||
{
|
||||
SharedBaseStorage = other.SharedBaseStorage.AddReference();
|
||||
BaseStorage = other.BaseStorage;
|
||||
Offset = other.Offset;
|
||||
Size = other.Size;
|
||||
IsResizable = other.IsResizable;
|
||||
}
|
||||
_offset = other._offset;
|
||||
_size = other._size;
|
||||
_isResizable = other._isResizable;
|
||||
_sharedBaseStorage = SharedRef<IStorage>.CreateCopy(ref other._sharedBaseStorage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -74,46 +58,27 @@ namespace LibHac.Fs
|
||||
/// </summary>
|
||||
/// <param name="baseStorage">The base <see cref="IStorage"/>. Caller retains ownership.</param>
|
||||
/// <param name="offset">The offset in the base storage at which to begin the created SubStorage.</param>
|
||||
/// <param name="size">The size of the SubStorage.</param>
|
||||
/// <param name="size">The size of the created SubStorage.</param>
|
||||
public SubStorage(IStorage baseStorage, long offset, long size)
|
||||
{
|
||||
BaseStorage = baseStorage;
|
||||
Offset = offset;
|
||||
Size = size;
|
||||
IsResizable = false;
|
||||
_offset = offset;
|
||||
_size = size;
|
||||
_isResizable = false;
|
||||
|
||||
Assert.SdkRequiresNotNull(baseStorage);
|
||||
Assert.SdkRequiresLessEqual(0, Offset);
|
||||
Assert.SdkRequiresLessEqual(0, Size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="SubStorage"/> from a subsection of another <see cref="IStorage"/>.
|
||||
/// Holds a reference to <paramref name="sharedBaseStorage"/> until disposed.
|
||||
/// </summary>
|
||||
/// <param name="sharedBaseStorage">The base IStorage.</param>
|
||||
/// <param name="offset">The offset in the base storage at which to begin the created SubStorage.</param>
|
||||
/// <param name="size">The size of the SubStorage.</param>
|
||||
public SubStorage(ReferenceCountedDisposable<IStorage> sharedBaseStorage, long offset, long size)
|
||||
{
|
||||
SharedBaseStorage = sharedBaseStorage.AddReference();
|
||||
BaseStorage = SharedBaseStorage.Target;
|
||||
Offset = offset;
|
||||
Size = size;
|
||||
IsResizable = false;
|
||||
|
||||
Assert.SdkRequiresNotNull(sharedBaseStorage);
|
||||
Assert.SdkRequiresLessEqual(0, Offset);
|
||||
Assert.SdkRequiresLessEqual(0, Size);
|
||||
Assert.SdkRequiresLessEqual(0, offset);
|
||||
Assert.SdkRequiresLessEqual(0, size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="SubStorage"/> from a subsection of another <see cref="SubStorage"/>.
|
||||
/// <paramref name="other"/> will not be disposed when the created <see cref="SubStorage"/> is disposed.
|
||||
/// Any shared references to the base <see cref="IStorage"/> will be copied over.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The created SubStorage will directly use the base SubStorage of <paramref name="other"/> and will
|
||||
/// adjust the <paramref name="offset"/> and <paramref name="size"/> accordingly.
|
||||
/// The created SubStorage will directly use the base <see cref="IStorage"/> of <paramref name="other"/>
|
||||
/// and will adjust the <paramref name="offset"/> and <paramref name="size"/> accordingly.
|
||||
/// This avoids the overhead of going through two SubStorage layers.
|
||||
/// </remarks>
|
||||
/// <param name="other">The base SubStorage.</param>
|
||||
@ -122,14 +87,58 @@ namespace LibHac.Fs
|
||||
public SubStorage(SubStorage other, long offset, long size)
|
||||
{
|
||||
BaseStorage = other.BaseStorage;
|
||||
Offset = other.Offset + offset;
|
||||
Size = size;
|
||||
IsResizable = false;
|
||||
_offset = other._offset + offset;
|
||||
_size = size;
|
||||
_isResizable = false;
|
||||
_sharedBaseStorage = SharedRef<IStorage>.CreateCopy(ref other._sharedBaseStorage);
|
||||
|
||||
Assert.SdkRequiresLessEqual(0, offset);
|
||||
Assert.SdkRequiresLessEqual(0, size);
|
||||
Assert.SdkRequires(other.IsValid());
|
||||
Assert.SdkRequiresLessEqual(0, Offset);
|
||||
Assert.SdkRequiresLessEqual(0, Size);
|
||||
Assert.SdkRequiresGreaterEqual(other.Size, offset + size);
|
||||
Assert.SdkRequiresGreaterEqual(other._size, offset + size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="SubStorage"/> from a subsection of another <see cref="IStorage"/>.
|
||||
/// Holds a reference to <paramref name="baseStorage"/> until disposed.
|
||||
/// </summary>
|
||||
/// <param name="baseStorage">The base <see cref="IStorage"/>.</param>
|
||||
/// <param name="offset">The offset in the base storage at which to begin the created SubStorage.</param>
|
||||
/// <param name="size">The size of the created SubStorage.</param>
|
||||
public SubStorage(ref SharedRef<IStorage> baseStorage, long offset, long size)
|
||||
{
|
||||
BaseStorage = _sharedBaseStorage.Get;
|
||||
_offset = offset;
|
||||
_size = size;
|
||||
_isResizable = false;
|
||||
_sharedBaseStorage = SharedRef<IStorage>.CreateCopy(ref baseStorage);
|
||||
|
||||
Assert.SdkRequiresNotNull(baseStorage.Get);
|
||||
Assert.SdkRequiresLessEqual(0, _offset);
|
||||
Assert.SdkRequiresLessEqual(0, _size);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
_sharedBaseStorage.Destroy();
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets this <see cref="SubStorage"/> to be a copy of <paramref name="other"/>.
|
||||
/// Any shared references in <paramref name="other"/> will be copied.
|
||||
/// </summary>
|
||||
/// <param name="other">The <see cref="SubStorage"/> used to initialize this one.</param>
|
||||
public void Set(SubStorage other)
|
||||
{
|
||||
if (this != other)
|
||||
{
|
||||
BaseStorage = other.BaseStorage;
|
||||
_offset = other._offset;
|
||||
_size = other._size;
|
||||
_isResizable = other._isResizable;
|
||||
_sharedBaseStorage.SetByCopy(ref other._sharedBaseStorage);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsValid() => BaseStorage != null;
|
||||
@ -141,7 +150,7 @@ namespace LibHac.Fs
|
||||
/// be resizable. <see langword="false"/> if not.</param>
|
||||
public void SetResizable(bool isResizable)
|
||||
{
|
||||
IsResizable = isResizable;
|
||||
_isResizable = isResizable;
|
||||
}
|
||||
|
||||
protected override Result DoRead(long offset, Span<byte> destination)
|
||||
@ -149,9 +158,10 @@ namespace LibHac.Fs
|
||||
if (!IsValid()) return ResultFs.NotInitialized.Log();
|
||||
if (destination.Length == 0) return Result.Success;
|
||||
|
||||
if (!IsRangeValid(offset, destination.Length, Size)) return ResultFs.OutOfRange.Log();
|
||||
if (!CheckAccessRange(offset, destination.Length, _size))
|
||||
return ResultFs.OutOfRange.Log();
|
||||
|
||||
return BaseStorage.Read(Offset + offset, destination);
|
||||
return BaseStorage.Read(_offset + offset, destination);
|
||||
}
|
||||
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
@ -159,9 +169,10 @@ namespace LibHac.Fs
|
||||
if (!IsValid()) return ResultFs.NotInitialized.Log();
|
||||
if (source.Length == 0) return Result.Success;
|
||||
|
||||
if (!IsRangeValid(offset, source.Length, Size)) return ResultFs.OutOfRange.Log();
|
||||
if (!CheckAccessRange(offset, source.Length, _size))
|
||||
return ResultFs.OutOfRange.Log();
|
||||
|
||||
return BaseStorage.Write(Offset + offset, source);
|
||||
return BaseStorage.Write(_offset + offset, source);
|
||||
}
|
||||
|
||||
protected override Result DoFlush()
|
||||
@ -174,22 +185,22 @@ namespace LibHac.Fs
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
if (!IsValid()) return ResultFs.NotInitialized.Log();
|
||||
if (!IsResizable) return ResultFs.UnsupportedSetSizeForNotResizableSubStorage.Log();
|
||||
if (!IsOffsetAndSizeValid(Offset, size)) return ResultFs.InvalidSize.Log();
|
||||
if (!_isResizable) return ResultFs.UnsupportedSetSizeForNotResizableSubStorage.Log();
|
||||
if (!CheckOffsetAndSize(_offset, size)) return ResultFs.InvalidSize.Log();
|
||||
|
||||
Result rc = BaseStorage.GetSize(out long currentSize);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (currentSize != Offset + Size)
|
||||
if (currentSize != _offset + _size)
|
||||
{
|
||||
// SubStorage cannot be resized unless it is located at the end of the base storage.
|
||||
return ResultFs.UnsupportedSetSizeForResizableSubStorage.Log();
|
||||
}
|
||||
|
||||
rc = BaseStorage.SetSize(Offset + size);
|
||||
rc = BaseStorage.SetSize(_offset + size);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
Size = size;
|
||||
_size = size;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
@ -199,30 +210,17 @@ namespace LibHac.Fs
|
||||
|
||||
if (!IsValid()) return ResultFs.NotInitialized.Log();
|
||||
|
||||
size = Size;
|
||||
size = _size;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size, ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
if (!IsValid()) return ResultFs.NotInitialized.Log();
|
||||
|
||||
if (size == 0) return Result.Success;
|
||||
if (!CheckOffsetAndSize(_offset, size)) return ResultFs.OutOfRange.Log();
|
||||
|
||||
if (!IsOffsetAndSizeValid(Offset, size)) return ResultFs.OutOfRange.Log();
|
||||
|
||||
return base.DoOperateRange(outBuffer, operationId, Offset + offset, size, inBuffer);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
SharedBaseStorage?.Dispose();
|
||||
SharedBaseStorage = null;
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
return base.DoOperateRange(outBuffer, operationId, _offset + offset, size, inBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,23 +22,21 @@ namespace LibHac.FsSrv
|
||||
return _serviceImpl.GetProgramInfo(out programInfo, _processId);
|
||||
}
|
||||
|
||||
public Result OpenAccessFailureDetectionEventNotifier(out ReferenceCountedDisposable<IEventNotifier> notifier,
|
||||
public Result OpenAccessFailureDetectionEventNotifier(ref SharedRef<IEventNotifier> outNotifier,
|
||||
ulong processId, bool notifyOnDeepRetry)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out notifier);
|
||||
|
||||
Result rc = GetProgramInfo(out ProgramInfo programInfo);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (!programInfo.AccessControl.CanCall(OperationType.OpenAccessFailureDetectionEventNotifier))
|
||||
return ResultFs.PermissionDenied.Log();
|
||||
|
||||
using var tempNotifier = new UniqueRef<IEventNotifier>();
|
||||
using var notifier = new UniqueRef<IEventNotifier>();
|
||||
|
||||
rc = _serviceImpl.CreateNotifier(ref tempNotifier.Ref(), processId, notifyOnDeepRetry);
|
||||
rc = _serviceImpl.CreateNotifier(ref notifier.Ref(), processId, notifyOnDeepRetry);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
notifier = new ReferenceCountedDisposable<IEventNotifier>(tempNotifier.Release());
|
||||
outNotifier.Set(ref notifier.Ref());
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ using LibHac.Sf;
|
||||
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
|
||||
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
|
||||
using Path = LibHac.Fs.Path;
|
||||
using Utility = LibHac.FsSrv.Impl.Utility;
|
||||
|
||||
namespace LibHac.FsSrv
|
||||
{
|
||||
@ -57,38 +58,36 @@ namespace LibHac.FsSrv
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenBaseFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem,
|
||||
BaseFileSystemId fileSystemId)
|
||||
public Result OpenBaseFileSystem(ref SharedRef<IFileSystemSf> outFileSystem, BaseFileSystemId fileSystemId)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
|
||||
Result rc = CheckCapabilityById(fileSystemId, _processId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
ReferenceCountedDisposable<IFileSystem> fs = null;
|
||||
// Open the file system
|
||||
using var fileSystem = new SharedRef<IFileSystem>();
|
||||
rc = _serviceImpl.OpenBaseFileSystem(ref fileSystem.Ref(), fileSystemId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
try
|
||||
{
|
||||
// Open the file system
|
||||
rc = _serviceImpl.OpenBaseFileSystem(out fs, fileSystemId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
// Create an SF adapter for the file system
|
||||
using SharedRef<IFileSystemSf> fileSystemAdapter =
|
||||
FileSystemInterfaceAdapter.CreateShared(ref fileSystem.Ref(), false);
|
||||
|
||||
// Create an SF adapter for the file system
|
||||
fileSystem = FileSystemInterfaceAdapter.CreateShared(ref fs, false);
|
||||
outFileSystem.SetByMove(ref fileSystemAdapter.Ref());
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
fs?.Dispose();
|
||||
}
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenBisFileSystem(out ReferenceCountedDisposable<IFileSystemSf> outFileSystem, in FspPath rootPath,
|
||||
public Result FormatBaseFileSystem(BaseFileSystemId fileSystemId)
|
||||
{
|
||||
Result rc = CheckCapabilityById(fileSystemId, _processId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return _serviceImpl.FormatBaseFileSystem(fileSystemId);
|
||||
}
|
||||
|
||||
public Result OpenBisFileSystem(ref SharedRef<IFileSystemSf> outFileSystem, in FspPath rootPath,
|
||||
BisPartitionId partitionId)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out outFileSystem);
|
||||
|
||||
Result rc = GetProgramInfo(out ProgramInfo programInfo);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
@ -126,32 +125,29 @@ namespace LibHac.FsSrv
|
||||
rc = pathNormalized.Normalize(pathFlags);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
ReferenceCountedDisposable<IFileSystem> baseFileSystem = null;
|
||||
ReferenceCountedDisposable<IFileSystem> fileSystem = null;
|
||||
// Open the file system
|
||||
using var fileSystem = new SharedRef<IFileSystem>();
|
||||
rc = _serviceImpl.OpenBisFileSystem(ref fileSystem.Ref(), partitionId, false);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
try
|
||||
{
|
||||
// Open the file system
|
||||
rc = _serviceImpl.OpenBisFileSystem(out baseFileSystem, partitionId, false);
|
||||
if (rc.IsFailure()) return rc;
|
||||
using var subDirFileSystem = new SharedRef<IFileSystem>();
|
||||
rc = Utility.CreateSubDirectoryFileSystem(ref subDirFileSystem.Ref(), ref fileSystem.Ref(),
|
||||
in pathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = Utility.CreateSubDirectoryFileSystem(out fileSystem, ref baseFileSystem, in pathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
// Add all the file system wrappers
|
||||
using var typeSetFileSystem =
|
||||
new SharedRef<IFileSystem>(new StorageLayoutTypeSetFileSystem(ref subDirFileSystem.Ref(), storageFlag));
|
||||
|
||||
// Add all the file system wrappers
|
||||
fileSystem = StorageLayoutTypeSetFileSystem.CreateShared(ref fileSystem, storageFlag);
|
||||
fileSystem = AsynchronousAccessFileSystem.CreateShared(ref fileSystem);
|
||||
using var asyncFileSystem =
|
||||
new SharedRef<IFileSystem>(new AsynchronousAccessFileSystem(ref typeSetFileSystem.Ref()));
|
||||
|
||||
// Create an SF adapter for the file system
|
||||
outFileSystem = FileSystemInterfaceAdapter.CreateShared(ref fileSystem, false);
|
||||
using SharedRef<IFileSystemSf> fileSystemAdapter =
|
||||
FileSystemInterfaceAdapter.CreateShared(ref asyncFileSystem.Ref(), false);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
baseFileSystem?.Dispose();
|
||||
fileSystem?.Dispose();
|
||||
}
|
||||
outFileSystem.SetByMove(ref fileSystemAdapter.Ref());
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result SetBisRootForHost(BisPartitionId partitionId, in FspPath path)
|
||||
@ -187,39 +183,33 @@ namespace LibHac.FsSrv
|
||||
return _serviceImpl.DeleteAllPaddingFiles();
|
||||
}
|
||||
|
||||
public Result OpenGameCardFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, GameCardHandle handle,
|
||||
public Result OpenGameCardFileSystem(ref SharedRef<IFileSystemSf> outFileSystem, GameCardHandle handle,
|
||||
GameCardPartition partitionId)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
|
||||
Result rc = GetProgramInfo(out ProgramInfo programInfo);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (!programInfo.AccessControl.GetAccessibilityFor(AccessibilityType.MountGameCard).CanRead)
|
||||
return ResultFs.PermissionDenied.Log();
|
||||
|
||||
ReferenceCountedDisposable<IFileSystem> fs = null;
|
||||
using var fileSystem = new SharedRef<IFileSystem>();
|
||||
|
||||
try
|
||||
{
|
||||
rc = _serviceImpl.OpenGameCardFileSystem(out fs, handle, partitionId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
rc = _serviceImpl.OpenGameCardFileSystem(ref fileSystem.Ref(), handle, partitionId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
// Create an SF adapter for the file system
|
||||
fileSystem = FileSystemInterfaceAdapter.CreateShared(ref fs, false);
|
||||
using var asyncFileSystem =
|
||||
new SharedRef<IFileSystem>(new AsynchronousAccessFileSystem(ref fileSystem.Ref()));
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
fs?.Dispose();
|
||||
}
|
||||
using SharedRef<IFileSystemSf> fileSystemAdapter =
|
||||
FileSystemInterfaceAdapter.CreateShared(ref asyncFileSystem.Ref(), false);
|
||||
|
||||
outFileSystem.SetByMove(ref fileSystemAdapter.Ref());
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenSdCardFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem)
|
||||
public Result OpenSdCardFileSystem(ref SharedRef<IFileSystemSf> outFileSystem)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
|
||||
Result rc = GetProgramInfo(out ProgramInfo programInfo);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
@ -228,22 +218,26 @@ namespace LibHac.FsSrv
|
||||
if (!accessibility.CanRead || !accessibility.CanWrite)
|
||||
return ResultFs.PermissionDenied.Log();
|
||||
|
||||
ReferenceCountedDisposable<IFileSystem> fs = null;
|
||||
const StorageType storageFlag = StorageType.Bis;
|
||||
using var scopedContext = new ScopedStorageLayoutTypeSetter(storageFlag);
|
||||
|
||||
try
|
||||
{
|
||||
rc = _serviceImpl.OpenSdCardProxyFileSystem(out fs);
|
||||
if (rc.IsFailure()) return rc;
|
||||
using var fileSystem = new SharedRef<IFileSystem>();
|
||||
rc = _serviceImpl.OpenSdCardProxyFileSystem(ref fileSystem.Ref());
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
// Create an SF adapter for the file system
|
||||
fileSystem = FileSystemInterfaceAdapter.CreateShared(ref fs, false);
|
||||
// Add all the file system wrappers
|
||||
using var typeSetFileSystem =
|
||||
new SharedRef<IFileSystem>(new StorageLayoutTypeSetFileSystem(ref fileSystem.Ref(), storageFlag));
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
fs?.Dispose();
|
||||
}
|
||||
using var asyncFileSystem =
|
||||
new SharedRef<IFileSystem>(new AsynchronousAccessFileSystem(ref typeSetFileSystem.Ref()));
|
||||
|
||||
using SharedRef<IFileSystemSf> fileSystemAdapter =
|
||||
FileSystemInterfaceAdapter.CreateShared(ref asyncFileSystem.Ref(), false);
|
||||
|
||||
outFileSystem.SetByMove(ref fileSystemAdapter.Ref());
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result FormatSdCardFileSystem()
|
||||
@ -273,11 +267,9 @@ namespace LibHac.FsSrv
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenImageDirectoryFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem,
|
||||
public Result OpenImageDirectoryFileSystem(ref SharedRef<IFileSystemSf> outFileSystem,
|
||||
ImageDirectoryId directoryId)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
|
||||
// Caller must have the MountImageAndVideoStorage permission
|
||||
Result rc = GetProgramInfo(out ProgramInfo programInfo);
|
||||
if (rc.IsFailure()) return rc;
|
||||
@ -301,28 +293,22 @@ namespace LibHac.FsSrv
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
ReferenceCountedDisposable<IFileSystem> fs = null;
|
||||
|
||||
try
|
||||
{
|
||||
rc = _serviceImpl.OpenBaseFileSystem(out fs, fileSystemId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
using var baseFileSystem = new SharedRef<IFileSystem>();
|
||||
rc = _serviceImpl.OpenBaseFileSystem(ref baseFileSystem.Ref(), fileSystemId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
// Create an SF adapter for the file system
|
||||
fileSystem = FileSystemInterfaceAdapter.CreateShared(ref fs, false);
|
||||
using SharedRef<IFileSystemSf> fileSystemAdapter =
|
||||
FileSystemInterfaceAdapter.CreateShared(ref baseFileSystem.Ref(), false);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
fs?.Dispose();
|
||||
}
|
||||
outFileSystem.SetByMove(ref fileSystemAdapter.Ref());
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenBisWiper(out ReferenceCountedDisposable<IWiper> bisWiper, NativeHandle transferMemoryHandle, ulong transferMemorySize)
|
||||
public Result OpenBisWiper(ref SharedRef<IWiper> outBisWiper, NativeHandle transferMemoryHandle,
|
||||
ulong transferMemorySize)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out bisWiper);
|
||||
|
||||
// Caller must have the OpenBisWiper permission
|
||||
Result rc = GetProgramInfo(out ProgramInfo programInfo);
|
||||
if (rc.IsFailure()) return rc;
|
||||
@ -330,10 +316,12 @@ namespace LibHac.FsSrv
|
||||
if (!programInfo.AccessControl.CanCall(OperationType.OpenBisWiper))
|
||||
return ResultFs.PermissionDenied.Log();
|
||||
|
||||
rc = _serviceImpl.OpenBisWiper(out IWiper wiper, transferMemoryHandle, transferMemorySize);
|
||||
using var bisWiper = new UniqueRef<IWiper>();
|
||||
rc = _serviceImpl.OpenBisWiper(ref bisWiper.Ref(), transferMemoryHandle, transferMemorySize);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
bisWiper = new ReferenceCountedDisposable<IWiper>(wiper);
|
||||
outBisWiper.Set(ref bisWiper.Ref());
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsSrv.FsCreator;
|
||||
using LibHac.FsSrv.Impl;
|
||||
@ -12,7 +13,7 @@ namespace LibHac.FsSrv
|
||||
{
|
||||
private Configuration _config;
|
||||
|
||||
public delegate Result BisWiperCreator(out IWiper wiper, NativeHandle transferMemoryHandle,
|
||||
public delegate Result BisWiperCreator(ref UniqueRef<IWiper> outWiper, NativeHandle transferMemoryHandle,
|
||||
ulong transferMemorySize);
|
||||
|
||||
public BaseFileSystemServiceImpl(in Configuration configuration)
|
||||
@ -34,23 +35,26 @@ namespace LibHac.FsSrv
|
||||
public FileSystemServer FsServer;
|
||||
}
|
||||
|
||||
public Result OpenBaseFileSystem(out ReferenceCountedDisposable<IFileSystem> fileSystem,
|
||||
BaseFileSystemId fileSystemId)
|
||||
public Result OpenBaseFileSystem(ref SharedRef<IFileSystem> outFileSystem, BaseFileSystemId fileSystemId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result OpenBisFileSystem(out ReferenceCountedDisposable<IFileSystem> fileSystem,
|
||||
BisPartitionId partitionId)
|
||||
public Result FormatBaseFileSystem(BaseFileSystemId fileSystemId)
|
||||
{
|
||||
return OpenBisFileSystem(out fileSystem, partitionId, false);
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result OpenBisFileSystem(out ReferenceCountedDisposable<IFileSystem> fileSystem,
|
||||
BisPartitionId partitionId, bool caseSensitive)
|
||||
public Result OpenBisFileSystem(ref SharedRef<IFileSystem> outFileSystem, BisPartitionId partitionId)
|
||||
{
|
||||
Result rc = _config.BisFileSystemCreator.Create(out fileSystem, partitionId, caseSensitive);
|
||||
if (rc.IsFailure()) return rc;
|
||||
return OpenBisFileSystem(ref outFileSystem, partitionId, false);
|
||||
}
|
||||
|
||||
public Result OpenBisFileSystem(ref SharedRef<IFileSystem> outFileSystem, BisPartitionId partitionId,
|
||||
bool caseSensitive)
|
||||
{
|
||||
Result rc = _config.BisFileSystemCreator.Create(ref outFileSystem, partitionId, caseSensitive);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
@ -65,33 +69,31 @@ namespace LibHac.FsSrv
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result OpenGameCardFileSystem(out ReferenceCountedDisposable<IFileSystem> fileSystem, GameCardHandle handle,
|
||||
public Result OpenGameCardFileSystem(ref SharedRef<IFileSystem> outFileSystem, GameCardHandle handle,
|
||||
GameCardPartition partitionId)
|
||||
{
|
||||
Result rc;
|
||||
int tries = 0;
|
||||
const int maxTries = 2;
|
||||
Result rc = Result.Success;
|
||||
|
||||
do
|
||||
for (int i = 0; i < maxTries; i++)
|
||||
{
|
||||
rc = _config.GameCardFileSystemCreator.Create(out fileSystem, handle, partitionId);
|
||||
rc = _config.GameCardFileSystemCreator.Create(ref outFileSystem, handle, partitionId);
|
||||
|
||||
if (!ResultFs.DataCorrupted.Includes(rc))
|
||||
break;
|
||||
|
||||
tries++;
|
||||
} while (tries < 2);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result OpenSdCardProxyFileSystem(out ReferenceCountedDisposable<IFileSystem> fileSystem)
|
||||
public Result OpenSdCardProxyFileSystem(ref SharedRef<IFileSystem> outFileSystem)
|
||||
{
|
||||
return OpenSdCardProxyFileSystem(out fileSystem, false);
|
||||
return OpenSdCardProxyFileSystem(ref outFileSystem, false);
|
||||
}
|
||||
|
||||
public Result OpenSdCardProxyFileSystem(out ReferenceCountedDisposable<IFileSystem> fileSystem, bool openCaseSensitive)
|
||||
public Result OpenSdCardProxyFileSystem(ref SharedRef<IFileSystem> outFileSystem, bool openCaseSensitive)
|
||||
{
|
||||
return _config.SdCardFileSystemCreator.Create(out fileSystem, openCaseSensitive);
|
||||
return _config.SdCardFileSystemCreator.Create(ref outFileSystem, openCaseSensitive);
|
||||
}
|
||||
|
||||
public Result FormatSdCardProxyFileSystem()
|
||||
@ -110,9 +112,10 @@ namespace LibHac.FsSrv
|
||||
return false;
|
||||
}
|
||||
|
||||
public Result OpenBisWiper(out IWiper wiper, NativeHandle transferMemoryHandle, ulong transferMemorySize)
|
||||
public Result OpenBisWiper(ref UniqueRef<IWiper> outBisWiper, NativeHandle transferMemoryHandle,
|
||||
ulong transferMemorySize)
|
||||
{
|
||||
return _config.BisWiperCreator(out wiper, transferMemoryHandle, transferMemorySize);
|
||||
return _config.BisWiperCreator(ref outBisWiper, transferMemoryHandle, transferMemorySize);
|
||||
}
|
||||
|
||||
internal Result GetProgramInfo(out ProgramInfo programInfo, ulong processId)
|
||||
|
@ -21,135 +21,9 @@ namespace LibHac.FsSrv
|
||||
_processId = processId;
|
||||
}
|
||||
|
||||
public Result OpenBisStorage(out ReferenceCountedDisposable<IStorageSf> storage, BisPartitionId id)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out storage);
|
||||
|
||||
var storageFlag = StorageType.Bis;
|
||||
using var scopedLayoutType = new ScopedStorageLayoutTypeSetter(storageFlag);
|
||||
|
||||
Result rc = GetProgramInfo(out ProgramInfo programInfo);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = GetAccessibilityForOpenBisPartition(out Accessibility accessibility, programInfo, id);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
bool canAccess = accessibility.CanRead && accessibility.CanWrite;
|
||||
|
||||
if (!canAccess)
|
||||
return ResultFs.PermissionDenied.Log();
|
||||
|
||||
ReferenceCountedDisposable<IStorage> tempStorage = null;
|
||||
try
|
||||
{
|
||||
rc = _serviceImpl.OpenBisStorage(out tempStorage, id);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
tempStorage = StorageLayoutTypeSetStorage.CreateShared(ref tempStorage, storageFlag);
|
||||
|
||||
// Todo: Async storage
|
||||
|
||||
storage = StorageInterfaceAdapter.CreateShared(ref tempStorage);
|
||||
return Result.Success;
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
tempStorage?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public Result InvalidateBisCache()
|
||||
{
|
||||
Result rc = GetProgramInfo(out ProgramInfo programInfo);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (!programInfo.AccessControl.CanCall(OperationType.InvalidateBisCache))
|
||||
return ResultFs.PermissionDenied.Log();
|
||||
|
||||
return _serviceImpl.InvalidateBisCache();
|
||||
}
|
||||
|
||||
public Result OpenGameCardStorage(out ReferenceCountedDisposable<IStorageSf> storage, GameCardHandle handle,
|
||||
GameCardPartitionRaw partitionId)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out storage);
|
||||
|
||||
Result rc = GetProgramInfo(out ProgramInfo programInfo);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
Accessibility accessibility =
|
||||
programInfo.AccessControl.GetAccessibilityFor(AccessibilityType.OpenGameCardStorage);
|
||||
|
||||
bool canAccess = accessibility.CanRead && accessibility.CanWrite;
|
||||
|
||||
if (!canAccess)
|
||||
return ResultFs.PermissionDenied.Log();
|
||||
|
||||
ReferenceCountedDisposable<IStorage> tempStorage = null;
|
||||
try
|
||||
{
|
||||
rc = _serviceImpl.OpenGameCardPartition(out tempStorage, handle, partitionId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
// Todo: Async storage
|
||||
|
||||
storage = StorageInterfaceAdapter.CreateShared(ref tempStorage);
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
tempStorage?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public Result OpenDeviceOperator(out ReferenceCountedDisposable<IDeviceOperator> deviceOperator)
|
||||
{
|
||||
deviceOperator = _serviceImpl.Config.DeviceOperator.AddReference();
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenSdCardDetectionEventNotifier(out ReferenceCountedDisposable<IEventNotifier> eventNotifier)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out eventNotifier);
|
||||
|
||||
Result rc = GetProgramInfo(out ProgramInfo programInfo);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (!programInfo.AccessControl.CanCall(OperationType.OpenSdCardDetectionEventNotifier))
|
||||
return ResultFs.PermissionDenied.Log();
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result OpenGameCardDetectionEventNotifier(out ReferenceCountedDisposable<IEventNotifier> eventNotifier)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out eventNotifier);
|
||||
|
||||
Result rc = GetProgramInfo(out ProgramInfo programInfo);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (!programInfo.AccessControl.CanCall(OperationType.OpenGameCardDetectionEventNotifier))
|
||||
return ResultFs.PermissionDenied.Log();
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result SimulateDeviceDetectionEvent(SdmmcPort port, SimulatingDeviceDetectionMode mode, bool signalEvent)
|
||||
{
|
||||
Result rc = GetProgramInfo(out ProgramInfo programInfo);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (!programInfo.AccessControl.CanCall(OperationType.SimulateDevice))
|
||||
return ResultFs.PermissionDenied.Log();
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private Result GetProgramInfo(out ProgramInfo programInfo)
|
||||
{
|
||||
var registry = new ProgramRegistryImpl(_serviceImpl.Config.FsServer);
|
||||
return registry.GetProgramInfo(out programInfo, _processId);
|
||||
return _serviceImpl.GetProgramInfo(out programInfo, _processId);
|
||||
}
|
||||
|
||||
private static Result GetAccessibilityForOpenBisPartition(out Accessibility accessibility, ProgramInfo programInfo,
|
||||
@ -184,15 +58,131 @@ namespace LibHac.FsSrv
|
||||
accessibility = programInfo.AccessControl.GetAccessibilityFor(type);
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenBisStorage(ref SharedRef<IStorageSf> outStorage, BisPartitionId id)
|
||||
{
|
||||
var storageFlag = StorageType.Bis;
|
||||
using var scopedLayoutType = new ScopedStorageLayoutTypeSetter(storageFlag);
|
||||
|
||||
Result rc = GetProgramInfo(out ProgramInfo programInfo);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = GetAccessibilityForOpenBisPartition(out Accessibility accessibility, programInfo, id);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
bool canAccess = accessibility.CanRead && accessibility.CanWrite;
|
||||
|
||||
if (!canAccess)
|
||||
return ResultFs.PermissionDenied.Log();
|
||||
|
||||
using var storage = new SharedRef<IStorage>();
|
||||
rc = _serviceImpl.OpenBisStorage(ref storage.Ref(), id);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
using var typeSetStorage =
|
||||
new SharedRef<IStorage>(new StorageLayoutTypeSetStorage(ref storage.Ref(), storageFlag));
|
||||
|
||||
// Todo: Async storage
|
||||
|
||||
using var storageAdapter =
|
||||
new SharedRef<IStorageSf>(new StorageInterfaceAdapter(ref typeSetStorage.Ref()));
|
||||
|
||||
outStorage.SetByMove(ref storageAdapter.Ref());
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result InvalidateBisCache()
|
||||
{
|
||||
Result rc = GetProgramInfo(out ProgramInfo programInfo);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (!programInfo.AccessControl.CanCall(OperationType.InvalidateBisCache))
|
||||
return ResultFs.PermissionDenied.Log();
|
||||
|
||||
return _serviceImpl.InvalidateBisCache();
|
||||
}
|
||||
|
||||
public Result OpenGameCardStorage(ref SharedRef<IStorageSf> outStorage, GameCardHandle handle,
|
||||
GameCardPartitionRaw partitionId)
|
||||
{
|
||||
Result rc = GetProgramInfo(out ProgramInfo programInfo);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
Accessibility accessibility =
|
||||
programInfo.AccessControl.GetAccessibilityFor(AccessibilityType.OpenGameCardStorage);
|
||||
|
||||
bool canAccess = accessibility.CanRead && accessibility.CanWrite;
|
||||
|
||||
if (!canAccess)
|
||||
return ResultFs.PermissionDenied.Log();
|
||||
|
||||
using var storage = new SharedRef<IStorage>();
|
||||
rc = _serviceImpl.OpenGameCardPartition(ref storage.Ref(), handle, partitionId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
// Todo: Async storage
|
||||
|
||||
using var storageAdapter =
|
||||
new SharedRef<IStorageSf>(new StorageInterfaceAdapter(ref storage.Ref()));
|
||||
|
||||
outStorage.SetByMove(ref storageAdapter.Ref());
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenDeviceOperator(ref SharedRef<IDeviceOperator> outDeviceOperator)
|
||||
{
|
||||
Result rc = GetProgramInfo(out ProgramInfo programInfo);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
rc = _serviceImpl.OpenDeviceOperator(ref outDeviceOperator, programInfo.AccessControl);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenSdCardDetectionEventNotifier(ref SharedRef<IEventNotifier> outEventNotifier)
|
||||
{
|
||||
Result rc = GetProgramInfo(out ProgramInfo programInfo);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (!programInfo.AccessControl.CanCall(OperationType.OpenSdCardDetectionEventNotifier))
|
||||
return ResultFs.PermissionDenied.Log();
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result OpenGameCardDetectionEventNotifier(ref SharedRef<IEventNotifier> outEventNotifier)
|
||||
{
|
||||
Result rc = GetProgramInfo(out ProgramInfo programInfo);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (!programInfo.AccessControl.CanCall(OperationType.OpenGameCardDetectionEventNotifier))
|
||||
return ResultFs.PermissionDenied.Log();
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result SimulateDeviceDetectionEvent(SdmmcPort port, SimulatingDeviceDetectionMode mode, bool signalEvent)
|
||||
{
|
||||
Result rc = GetProgramInfo(out ProgramInfo programInfo);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (!programInfo.AccessControl.CanCall(OperationType.SimulateDevice))
|
||||
return ResultFs.PermissionDenied.Log();
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class BaseStorageServiceImpl
|
||||
{
|
||||
internal Configuration Config;
|
||||
private Configuration _config;
|
||||
|
||||
public BaseStorageServiceImpl(in Configuration configuration)
|
||||
{
|
||||
Config = configuration;
|
||||
_config = configuration;
|
||||
}
|
||||
|
||||
public struct Configuration
|
||||
@ -203,34 +193,47 @@ namespace LibHac.FsSrv
|
||||
// LibHac additions
|
||||
public FileSystemServer FsServer;
|
||||
// Todo: The DeviceOperator in FS uses mostly global state. Decide how to handle this.
|
||||
public ReferenceCountedDisposable<IDeviceOperator> DeviceOperator;
|
||||
public SharedRef<IDeviceOperator> DeviceOperator;
|
||||
}
|
||||
|
||||
public Result OpenBisStorage(out ReferenceCountedDisposable<IStorage> storage, BisPartitionId partitionId)
|
||||
internal Result GetProgramInfo(out ProgramInfo programInfo, ulong processId)
|
||||
{
|
||||
return Config.BisStorageCreator.Create(out storage, partitionId);
|
||||
var registry = new ProgramRegistryImpl(_config.FsServer);
|
||||
return registry.GetProgramInfo(out programInfo, processId);
|
||||
}
|
||||
|
||||
public Result OpenBisStorage(ref SharedRef<IStorage> outStorage, BisPartitionId partitionId)
|
||||
{
|
||||
return _config.BisStorageCreator.Create(ref outStorage, partitionId);
|
||||
}
|
||||
|
||||
public Result InvalidateBisCache()
|
||||
{
|
||||
return Config.BisStorageCreator.InvalidateCache();
|
||||
return _config.BisStorageCreator.InvalidateCache();
|
||||
}
|
||||
|
||||
public Result OpenGameCardPartition(out ReferenceCountedDisposable<IStorage> storage, GameCardHandle handle,
|
||||
public Result OpenGameCardPartition(ref SharedRef<IStorage> outStorage, GameCardHandle handle,
|
||||
GameCardPartitionRaw partitionId)
|
||||
{
|
||||
switch (partitionId)
|
||||
{
|
||||
case GameCardPartitionRaw.NormalReadOnly:
|
||||
return Config.GameCardStorageCreator.CreateReadOnly(handle, out storage);
|
||||
return _config.GameCardStorageCreator.CreateReadOnly(handle, ref outStorage);
|
||||
case GameCardPartitionRaw.SecureReadOnly:
|
||||
return Config.GameCardStorageCreator.CreateSecureReadOnly(handle, out storage);
|
||||
return _config.GameCardStorageCreator.CreateSecureReadOnly(handle, ref outStorage);
|
||||
case GameCardPartitionRaw.RootWriteOnly:
|
||||
return Config.GameCardStorageCreator.CreateWriteOnly(handle, out storage);
|
||||
return _config.GameCardStorageCreator.CreateWriteOnly(handle, ref outStorage);
|
||||
default:
|
||||
UnsafeHelpers.SkipParamInit(out storage);
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
}
|
||||
|
||||
// LibHac addition
|
||||
internal Result OpenDeviceOperator(ref SharedRef<IDeviceOperator> outDeviceOperator,
|
||||
AccessControl accessControl)
|
||||
{
|
||||
outDeviceOperator.SetByCopy(ref _config.DeviceOperator);
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using LibHac.Common.Keys;
|
||||
using LibHac.Common;
|
||||
using LibHac.Common.Keys;
|
||||
using LibHac.FsSrv.FsCreator;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
|
||||
@ -21,6 +22,10 @@ namespace LibHac.FsSrv
|
||||
|
||||
var gcStorageCreator = new EmulatedGameCardStorageCreator(gameCard);
|
||||
|
||||
using var sharedRootFileSystem = new SharedRef<IFileSystem>(rootFileSystem);
|
||||
using SharedRef<IFileSystem> sharedRootFileSystemCopy =
|
||||
SharedRef<IFileSystem>.CreateCopy(ref sharedRootFileSystem.Ref());
|
||||
|
||||
creators.RomFileSystemCreator = new RomFileSystemCreator();
|
||||
creators.PartitionFileSystemCreator = new PartitionFileSystemCreator();
|
||||
creators.StorageOnNcaCreator = new StorageOnNcaCreator(keySet);
|
||||
@ -30,8 +35,8 @@ namespace LibHac.FsSrv
|
||||
creators.GameCardStorageCreator = gcStorageCreator;
|
||||
creators.GameCardFileSystemCreator = new EmulatedGameCardFsCreator(gcStorageCreator, gameCard);
|
||||
creators.EncryptedFileSystemCreator = new EncryptedFileSystemCreator(keySet);
|
||||
creators.BuiltInStorageFileSystemCreator = new EmulatedBisFileSystemCreator(rootFileSystem);
|
||||
creators.SdCardFileSystemCreator = new EmulatedSdCardFileSystemCreator(sdCard, rootFileSystem);
|
||||
creators.BuiltInStorageFileSystemCreator = new EmulatedBisFileSystemCreator(ref sharedRootFileSystem.Ref());
|
||||
creators.SdCardFileSystemCreator = new EmulatedSdCardFileSystemCreator(sdCard, ref sharedRootFileSystemCopy.Ref());
|
||||
|
||||
var deviceOperator = new EmulatedDeviceOperator(gameCard, sdCard);
|
||||
|
||||
|
@ -11,116 +11,103 @@ namespace LibHac.FsSrv
|
||||
{
|
||||
public class FileSystemProxyCoreImpl
|
||||
{
|
||||
private FileSystemCreatorInterfaces FsCreators { get; }
|
||||
private BaseFileSystemServiceImpl BaseFileSystemService { get; }
|
||||
private EncryptionSeed SdEncryptionSeed { get; set; }
|
||||
private FileSystemCreatorInterfaces _fsCreators;
|
||||
private BaseFileSystemServiceImpl _baseFileSystemService;
|
||||
private EncryptionSeed _sdEncryptionSeed;
|
||||
|
||||
public FileSystemProxyCoreImpl(FileSystemCreatorInterfaces fsCreators, BaseFileSystemServiceImpl baseFsService)
|
||||
{
|
||||
FsCreators = fsCreators;
|
||||
BaseFileSystemService = baseFsService;
|
||||
_fsCreators = fsCreators;
|
||||
_baseFileSystemService = baseFsService;
|
||||
}
|
||||
|
||||
public Result OpenCloudBackupWorkStorageFileSystem(out ReferenceCountedDisposable<IFileSystem> fileSystem,
|
||||
public Result OpenCloudBackupWorkStorageFileSystem(ref SharedRef<IFileSystem> outFileSystem,
|
||||
CloudBackupWorkStorageId storageId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result OpenCustomStorageFileSystem(out ReferenceCountedDisposable<IFileSystem> outFileSystem,
|
||||
CustomStorageId storageId)
|
||||
public Result OpenCustomStorageFileSystem(ref SharedRef<IFileSystem> outFileSystem, CustomStorageId storageId)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out outFileSystem);
|
||||
// Hack around error CS8350.
|
||||
const int pathBufferLength = 0x40;
|
||||
Span<byte> buffer = stackalloc byte[pathBufferLength];
|
||||
ref byte bufferRef = ref MemoryMarshal.GetReference(buffer);
|
||||
Span<byte> pathBuffer = MemoryMarshal.CreateSpan(ref bufferRef, pathBufferLength);
|
||||
|
||||
ReferenceCountedDisposable<IFileSystem> fileSystem = null;
|
||||
ReferenceCountedDisposable<IFileSystem> tempFs = null;
|
||||
try
|
||||
using var fileSystem = new SharedRef<IFileSystem>();
|
||||
|
||||
if (storageId == CustomStorageId.System)
|
||||
{
|
||||
// Hack around error CS8350.
|
||||
const int pathBufferLength = 0x40;
|
||||
Span<byte> buffer = stackalloc byte[pathBufferLength];
|
||||
ref byte bufferRef = ref MemoryMarshal.GetReference(buffer);
|
||||
Span<byte> pathBuffer = MemoryMarshal.CreateSpan(ref bufferRef, pathBufferLength);
|
||||
Result rc = _baseFileSystemService.OpenBisFileSystem(ref fileSystem.Ref(), BisPartitionId.User);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (storageId == CustomStorageId.System)
|
||||
{
|
||||
Result rc = BaseFileSystemService.OpenBisFileSystem(out fileSystem, BisPartitionId.User);
|
||||
if (rc.IsFailure()) return rc;
|
||||
using var path = new Path();
|
||||
rc = PathFunctions.SetUpFixedPathSingleEntry(ref path.Ref(), pathBuffer,
|
||||
CustomStorage.GetCustomStorageDirectoryName(CustomStorageId.System));
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
using var path = new Path();
|
||||
rc = PathFunctions.SetUpFixedPathSingleEntry(ref path.Ref(), pathBuffer,
|
||||
CustomStorage.GetCustomStorageDirectoryName(CustomStorageId.System));
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
tempFs = Shared.Move(ref fileSystem);
|
||||
rc = Utility.WrapSubDirectory(out fileSystem, ref tempFs, in path, true);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
else if (storageId == CustomStorageId.SdCard)
|
||||
{
|
||||
Result rc = BaseFileSystemService.OpenSdCardProxyFileSystem(out fileSystem);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
using var path = new Path();
|
||||
rc = PathFunctions.SetUpFixedPathDoubleEntry(ref path.Ref(), pathBuffer,
|
||||
CommonPaths.SdCardNintendoRootDirectoryName,
|
||||
CustomStorage.GetCustomStorageDirectoryName(CustomStorageId.System));
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
tempFs = Shared.Move(ref fileSystem);
|
||||
rc = Utility.WrapSubDirectory(out fileSystem, ref tempFs, in path, true);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
tempFs = Shared.Move(ref fileSystem);
|
||||
rc = FsCreators.EncryptedFileSystemCreator.Create(out fileSystem, ref tempFs,
|
||||
IEncryptedFileSystemCreator.KeyId.CustomStorage, SdEncryptionSeed);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
|
||||
outFileSystem = Shared.Move(ref fileSystem);
|
||||
return Result.Success;
|
||||
using SharedRef<IFileSystem> tempFs = SharedRef<IFileSystem>.CreateMove(ref fileSystem.Ref());
|
||||
rc = Utility.WrapSubDirectory(ref fileSystem.Ref(), ref tempFs.Ref(), in path, createIfMissing: true);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
finally
|
||||
else if (storageId == CustomStorageId.SdCard)
|
||||
{
|
||||
fileSystem?.Dispose();
|
||||
tempFs?.Dispose();
|
||||
Result rc = _baseFileSystemService.OpenSdCardProxyFileSystem(ref fileSystem.Ref());
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
using var path = new Path();
|
||||
rc = PathFunctions.SetUpFixedPathDoubleEntry(ref path.Ref(), pathBuffer,
|
||||
CommonPaths.SdCardNintendoRootDirectoryName,
|
||||
CustomStorage.GetCustomStorageDirectoryName(CustomStorageId.System));
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
using SharedRef<IFileSystem> tempFs = SharedRef<IFileSystem>.CreateMove(ref fileSystem.Ref());
|
||||
rc = Utility.WrapSubDirectory(ref fileSystem.Ref(), ref tempFs.Ref(), in path, createIfMissing: true);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
tempFs.SetByMove(ref fileSystem.Ref());
|
||||
rc = _fsCreators.EncryptedFileSystemCreator.Create(ref fileSystem.Ref(), ref tempFs.Ref(),
|
||||
IEncryptedFileSystemCreator.KeyId.CustomStorage, in _sdEncryptionSeed);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
|
||||
outFileSystem.SetByMove(ref fileSystem.Ref());
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private Result OpenHostFileSystem(out ReferenceCountedDisposable<IFileSystem> fileSystem, in Path path)
|
||||
private Result OpenHostFileSystem(ref SharedRef<IFileSystem> outFileSystem, in Path path)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
|
||||
using var pathHost = new Path();
|
||||
Result rc = pathHost.Initialize(in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = FsCreators.TargetManagerFileSystemCreator.NormalizeCaseOfPath(out bool isSupported, ref pathHost.Ref());
|
||||
rc = _fsCreators.TargetManagerFileSystemCreator.NormalizeCaseOfPath(out bool isSupported, ref pathHost.Ref());
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = FsCreators.TargetManagerFileSystemCreator.Create(out fileSystem, in pathHost, isSupported, false,
|
||||
Result.Success);
|
||||
rc = _fsCreators.TargetManagerFileSystemCreator.Create(ref outFileSystem, in pathHost, isSupported,
|
||||
ensureRootPathExists: false, Result.Success);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenHostFileSystem(out ReferenceCountedDisposable<IFileSystem> fileSystem, in Path path,
|
||||
public Result OpenHostFileSystem(ref SharedRef<IFileSystem> outFileSystem, in Path path,
|
||||
bool openCaseSensitive)
|
||||
{
|
||||
if (!path.IsEmpty() && openCaseSensitive)
|
||||
{
|
||||
Result rc = OpenHostFileSystem(out fileSystem, in path);
|
||||
Result rc = OpenHostFileSystem(ref outFileSystem, in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
Result rc = FsCreators.TargetManagerFileSystemCreator.Create(out fileSystem, in path, openCaseSensitive,
|
||||
false, Result.Success);
|
||||
Result rc = _fsCreators.TargetManagerFileSystemCreator.Create(ref outFileSystem, in path,
|
||||
openCaseSensitive, ensureRootPathExists: false, Result.Success);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
|
||||
@ -129,7 +116,7 @@ namespace LibHac.FsSrv
|
||||
|
||||
public Result SetSdCardEncryptionSeed(in EncryptionSeed seed)
|
||||
{
|
||||
SdEncryptionSeed = seed;
|
||||
_sdEncryptionSeed = seed;
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
@ -52,78 +52,83 @@ namespace LibHac.FsSrv
|
||||
public Optional<FileSystemProxyCoreImpl> FileSystemProxyCoreImpl;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispatches calls to the main file system service interface.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
public class FileSystemProxyImpl : IFileSystemProxy, IFileSystemProxyForLoader
|
||||
{
|
||||
private FileSystemServer FsServer { get; }
|
||||
private ref FileSystemProxyImplGlobals Globals => ref FsServer.Globals.FileSystemProxyImpl;
|
||||
private FileSystemProxyCoreImpl _fsProxyCore;
|
||||
private SharedRef<NcaFileSystemService> _ncaFsService;
|
||||
private SharedRef<SaveDataFileSystemService> _saveFsService;
|
||||
private ulong _currentProcess;
|
||||
|
||||
private FileSystemProxyCoreImpl FsProxyCore { get; }
|
||||
private ReferenceCountedDisposable<NcaFileSystemService> NcaFsService { get; set; }
|
||||
private ReferenceCountedDisposable<SaveDataFileSystemService> SaveFsService { get; set; }
|
||||
private ulong CurrentProcess { get; set; }
|
||||
// LibHac addition
|
||||
private FileSystemServer _fsServer;
|
||||
private ref FileSystemProxyImplGlobals Globals => ref _fsServer.Globals.FileSystemProxyImpl;
|
||||
|
||||
internal FileSystemProxyImpl(FileSystemServer server)
|
||||
{
|
||||
FsServer = server;
|
||||
_fsServer = server;
|
||||
|
||||
FsProxyCore = Globals.FileSystemProxyCoreImpl.Value;
|
||||
CurrentProcess = ulong.MaxValue;
|
||||
_fsProxyCore = Globals.FileSystemProxyCoreImpl.Value;
|
||||
_currentProcess = ulong.MaxValue;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
NcaFsService?.Dispose();
|
||||
SaveFsService?.Dispose();
|
||||
_ncaFsService.Destroy();
|
||||
_saveFsService.Destroy();
|
||||
}
|
||||
|
||||
private Result GetProgramInfo(out ProgramInfo programInfo)
|
||||
{
|
||||
var registry = new ProgramRegistryImpl(FsServer);
|
||||
return registry.GetProgramInfo(out programInfo, CurrentProcess);
|
||||
var registry = new ProgramRegistryImpl(_fsServer);
|
||||
return registry.GetProgramInfo(out programInfo, _currentProcess);
|
||||
}
|
||||
|
||||
private Result GetNcaFileSystemService(out NcaFileSystemService ncaFsService)
|
||||
{
|
||||
if (NcaFsService is null)
|
||||
if (!_ncaFsService.HasValue)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out ncaFsService);
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
}
|
||||
|
||||
ncaFsService = NcaFsService.Target;
|
||||
ncaFsService = _ncaFsService.Get;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private Result GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService)
|
||||
{
|
||||
if (SaveFsService is null)
|
||||
if (!_saveFsService.HasValue)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out saveFsService);
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
}
|
||||
|
||||
saveFsService = SaveFsService.Target;
|
||||
saveFsService = _saveFsService.Get;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private BaseStorageService GetBaseStorageService()
|
||||
{
|
||||
return new BaseStorageService(Globals.BaseStorageServiceImpl, CurrentProcess);
|
||||
return new BaseStorageService(Globals.BaseStorageServiceImpl, _currentProcess);
|
||||
}
|
||||
|
||||
private BaseFileSystemService GetBaseFileSystemService()
|
||||
{
|
||||
return new BaseFileSystemService(Globals.BaseFileSystemServiceImpl, CurrentProcess);
|
||||
return new BaseFileSystemService(Globals.BaseFileSystemServiceImpl, _currentProcess);
|
||||
}
|
||||
|
||||
private AccessFailureManagementService GetAccessFailureManagementService()
|
||||
{
|
||||
return new AccessFailureManagementService(Globals.AccessFailureManagementServiceImpl, CurrentProcess);
|
||||
return new AccessFailureManagementService(Globals.AccessFailureManagementServiceImpl, _currentProcess);
|
||||
}
|
||||
|
||||
private TimeService GetTimeService()
|
||||
{
|
||||
return new TimeService(Globals.TimeServiceImpl, CurrentProcess);
|
||||
return new TimeService(Globals.TimeServiceImpl, _currentProcess);
|
||||
}
|
||||
|
||||
private StatusReportService GetStatusReportService()
|
||||
@ -133,62 +138,50 @@ namespace LibHac.FsSrv
|
||||
|
||||
private ProgramIndexRegistryService GetProgramIndexRegistryService()
|
||||
{
|
||||
return new ProgramIndexRegistryService(Globals.ProgramRegistryServiceImpl, CurrentProcess);
|
||||
return new ProgramIndexRegistryService(Globals.ProgramRegistryServiceImpl, _currentProcess);
|
||||
}
|
||||
|
||||
private AccessLogService GetAccessLogService()
|
||||
{
|
||||
return new AccessLogService(Globals.AccessLogServiceImpl, CurrentProcess);
|
||||
return new AccessLogService(Globals.AccessLogServiceImpl, _currentProcess);
|
||||
}
|
||||
|
||||
public Result OpenFileSystemWithId(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, in FspPath path,
|
||||
public Result OpenFileSystemWithId(ref SharedRef<IFileSystemSf> outFileSystem, in FspPath path,
|
||||
ulong id, FileSystemProxyType fsType)
|
||||
{
|
||||
Result rc = GetNcaFileSystemService(out NcaFileSystemService ncaFsService);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return ncaFsService.OpenFileSystemWithId(out fileSystem, in path, id, fsType);
|
||||
return ncaFsService.OpenFileSystemWithId(ref outFileSystem, in path, id, fsType);
|
||||
}
|
||||
|
||||
public Result OpenFileSystemWithPatch(out ReferenceCountedDisposable<IFileSystemSf> fileSystem,
|
||||
public Result OpenFileSystemWithPatch(ref SharedRef<IFileSystemSf> outFileSystem,
|
||||
ProgramId programId, FileSystemProxyType fsType)
|
||||
{
|
||||
Result rc = GetNcaFileSystemService(out NcaFileSystemService ncaFsService);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return ncaFsService.OpenFileSystemWithPatch(out fileSystem, programId, fsType);
|
||||
return ncaFsService.OpenFileSystemWithPatch(ref outFileSystem, programId, fsType);
|
||||
}
|
||||
|
||||
public Result OpenCodeFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem,
|
||||
public Result OpenCodeFileSystem(ref SharedRef<IFileSystemSf> fileSystem,
|
||||
out CodeVerificationData verificationData, in FspPath path, ProgramId programId)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out verificationData);
|
||||
|
||||
Result rc = GetNcaFileSystemService(out NcaFileSystemService ncaFsService);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return ncaFsService.OpenCodeFileSystem(out fileSystem, out verificationData, in path, programId);
|
||||
return ncaFsService.OpenCodeFileSystem(ref fileSystem, out verificationData, in path, programId);
|
||||
}
|
||||
|
||||
public Result SetCurrentProcess(ulong processId)
|
||||
{
|
||||
CurrentProcess = processId;
|
||||
_currentProcess = processId;
|
||||
|
||||
// Initialize the NCA file system service
|
||||
NcaFsService = NcaFileSystemService.CreateShared(Globals.NcaFileSystemServiceImpl, processId);
|
||||
SaveFsService = SaveDataFileSystemService.CreateShared(Globals.SaveDataFileSystemServiceImpl, processId);
|
||||
_ncaFsService = NcaFileSystemService.CreateShared(Globals.NcaFileSystemServiceImpl, processId);
|
||||
_saveFsService = SaveDataFileSystemService.CreateShared(Globals.SaveDataFileSystemServiceImpl, processId);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
@ -203,99 +196,70 @@ namespace LibHac.FsSrv
|
||||
return saveFsService.GetFreeSpaceSizeForSaveData(out freeSpaceSize, spaceId);
|
||||
}
|
||||
|
||||
public Result OpenDataFileSystemByCurrentProcess(out ReferenceCountedDisposable<IFileSystemSf> fileSystem)
|
||||
public Result OpenDataFileSystemByCurrentProcess(ref SharedRef<IFileSystemSf> outFileSystem)
|
||||
{
|
||||
Result rc = GetNcaFileSystemService(out NcaFileSystemService ncaFsService);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return ncaFsService.OpenDataFileSystemByCurrentProcess(out fileSystem);
|
||||
return ncaFsService.OpenDataFileSystemByCurrentProcess(ref outFileSystem);
|
||||
}
|
||||
|
||||
public Result OpenDataFileSystemByProgramId(out ReferenceCountedDisposable<IFileSystemSf> fileSystem,
|
||||
public Result OpenDataFileSystemByProgramId(ref SharedRef<IFileSystemSf> outFileSystem,
|
||||
ProgramId programId)
|
||||
{
|
||||
Result rc = GetNcaFileSystemService(out NcaFileSystemService ncaFsService);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return ncaFsService.OpenDataFileSystemByProgramId(out fileSystem, programId);
|
||||
return ncaFsService.OpenDataFileSystemByProgramId(ref outFileSystem, programId);
|
||||
}
|
||||
|
||||
public Result OpenDataStorageByCurrentProcess(out ReferenceCountedDisposable<IStorageSf> storage)
|
||||
public Result OpenDataStorageByCurrentProcess(ref SharedRef<IStorageSf> outStorage)
|
||||
{
|
||||
Result rc = GetNcaFileSystemService(out NcaFileSystemService ncaFsService);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out storage);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return ncaFsService.OpenDataStorageByCurrentProcess(out storage);
|
||||
return ncaFsService.OpenDataStorageByCurrentProcess(ref outStorage);
|
||||
}
|
||||
|
||||
public Result OpenDataStorageByProgramId(out ReferenceCountedDisposable<IStorageSf> storage,
|
||||
public Result OpenDataStorageByProgramId(ref SharedRef<IStorageSf> outStorage,
|
||||
ProgramId programId)
|
||||
{
|
||||
Result rc = GetNcaFileSystemService(out NcaFileSystemService ncaFsService);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out storage);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return ncaFsService.OpenDataStorageByProgramId(out storage, programId);
|
||||
return ncaFsService.OpenDataStorageByProgramId(ref outStorage, programId);
|
||||
}
|
||||
|
||||
public Result OpenDataStorageByDataId(out ReferenceCountedDisposable<IStorageSf> storage, DataId dataId,
|
||||
public Result OpenDataStorageByDataId(ref SharedRef<IStorageSf> outStorage, DataId dataId,
|
||||
StorageId storageId)
|
||||
{
|
||||
Result rc = GetNcaFileSystemService(out NcaFileSystemService ncaFsService);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out storage);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return ncaFsService.OpenDataStorageByDataId(out storage, dataId, storageId);
|
||||
return ncaFsService.OpenDataStorageByDataId(ref outStorage, dataId, storageId);
|
||||
}
|
||||
|
||||
public Result OpenPatchDataStorageByCurrentProcess(out ReferenceCountedDisposable<IStorageSf> storage)
|
||||
public Result OpenPatchDataStorageByCurrentProcess(ref SharedRef<IStorageSf> outStorage)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out storage);
|
||||
return ResultFs.TargetNotFound.Log();
|
||||
}
|
||||
|
||||
public Result OpenDataFileSystemWithProgramIndex(out ReferenceCountedDisposable<IFileSystemSf> fileSystem,
|
||||
public Result OpenDataFileSystemWithProgramIndex(ref SharedRef<IFileSystemSf> outFileSystem,
|
||||
byte programIndex)
|
||||
{
|
||||
Result rc = GetNcaFileSystemService(out NcaFileSystemService ncaFsService);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return ncaFsService.OpenDataFileSystemWithProgramIndex(out fileSystem, programIndex);
|
||||
return ncaFsService.OpenDataFileSystemWithProgramIndex(ref outFileSystem, programIndex);
|
||||
}
|
||||
|
||||
public Result OpenDataStorageWithProgramIndex(out ReferenceCountedDisposable<IStorageSf> storage,
|
||||
public Result OpenDataStorageWithProgramIndex(ref SharedRef<IStorageSf> outStorage,
|
||||
byte programIndex)
|
||||
{
|
||||
Result rc = GetNcaFileSystemService(out NcaFileSystemService ncaFsService);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out storage);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return ncaFsService.OpenDataStorageWithProgramIndex(out storage, programIndex);
|
||||
return ncaFsService.OpenDataStorageWithProgramIndex(ref outStorage, programIndex);
|
||||
}
|
||||
|
||||
public Result RegisterSaveDataFileSystemAtomicDeletion(InBuffer saveDataIds)
|
||||
@ -376,43 +340,31 @@ namespace LibHac.FsSrv
|
||||
return saveFsService.ExtendSaveDataFileSystem(spaceId, saveDataId, dataSize, journalSize);
|
||||
}
|
||||
|
||||
public Result OpenSaveDataFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem,
|
||||
SaveDataSpaceId spaceId, in SaveDataAttribute attribute)
|
||||
public Result OpenSaveDataFileSystem(ref SharedRef<IFileSystemSf> outFileSystem, SaveDataSpaceId spaceId,
|
||||
in SaveDataAttribute attribute)
|
||||
{
|
||||
Result rc = GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return saveFsService.OpenSaveDataFileSystem(out fileSystem, spaceId, in attribute);
|
||||
return saveFsService.OpenSaveDataFileSystem(ref outFileSystem, spaceId, in attribute);
|
||||
}
|
||||
|
||||
public Result OpenReadOnlySaveDataFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem,
|
||||
public Result OpenReadOnlySaveDataFileSystem(ref SharedRef<IFileSystemSf> outFileSystem,
|
||||
SaveDataSpaceId spaceId, in SaveDataAttribute attribute)
|
||||
{
|
||||
Result rc = GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return saveFsService.OpenReadOnlySaveDataFileSystem(out fileSystem, spaceId, in attribute);
|
||||
return saveFsService.OpenReadOnlySaveDataFileSystem(ref outFileSystem, spaceId, in attribute);
|
||||
}
|
||||
|
||||
public Result OpenSaveDataFileSystemBySystemSaveDataId(out ReferenceCountedDisposable<IFileSystemSf> fileSystem,
|
||||
public Result OpenSaveDataFileSystemBySystemSaveDataId(ref SharedRef<IFileSystemSf> outFileSystem,
|
||||
SaveDataSpaceId spaceId, in SaveDataAttribute attribute)
|
||||
{
|
||||
Result rc = GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return saveFsService.OpenSaveDataFileSystemBySystemSaveDataId(out fileSystem, spaceId, in attribute);
|
||||
return saveFsService.OpenSaveDataFileSystemBySystemSaveDataId(ref outFileSystem, spaceId, in attribute);
|
||||
}
|
||||
|
||||
public Result ReadSaveDataFileSystemExtraData(OutBuffer extraDataBuffer, ulong saveDataId)
|
||||
@ -481,27 +433,31 @@ namespace LibHac.FsSrv
|
||||
maskBuffer);
|
||||
}
|
||||
|
||||
public Result OpenImageDirectoryFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem,
|
||||
public Result OpenImageDirectoryFileSystem(ref SharedRef<IFileSystemSf> outFileSystem,
|
||||
ImageDirectoryId directoryId)
|
||||
{
|
||||
return GetBaseFileSystemService().OpenImageDirectoryFileSystem(out fileSystem, directoryId);
|
||||
return GetBaseFileSystemService().OpenImageDirectoryFileSystem(ref outFileSystem, directoryId);
|
||||
}
|
||||
|
||||
public Result OpenBaseFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem,
|
||||
BaseFileSystemId fileSystemId)
|
||||
public Result OpenBaseFileSystem(ref SharedRef<IFileSystemSf> outFileSystem, BaseFileSystemId fileSystemId)
|
||||
{
|
||||
return GetBaseFileSystemService().OpenBaseFileSystem(out fileSystem, fileSystemId);
|
||||
return GetBaseFileSystemService().OpenBaseFileSystem(ref outFileSystem, fileSystemId);
|
||||
}
|
||||
|
||||
public Result OpenBisFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, in FspPath rootPath,
|
||||
public Result FormatBaseFileSystem(BaseFileSystemId fileSystemId)
|
||||
{
|
||||
return GetBaseFileSystemService().FormatBaseFileSystem(fileSystemId);
|
||||
}
|
||||
|
||||
public Result OpenBisFileSystem(ref SharedRef<IFileSystemSf> outFileSystem, in FspPath rootPath,
|
||||
BisPartitionId partitionId)
|
||||
{
|
||||
return GetBaseFileSystemService().OpenBisFileSystem(out fileSystem, in rootPath, partitionId);
|
||||
return GetBaseFileSystemService().OpenBisFileSystem(ref outFileSystem, in rootPath, partitionId);
|
||||
}
|
||||
|
||||
public Result OpenBisStorage(out ReferenceCountedDisposable<IStorageSf> storage, BisPartitionId partitionId)
|
||||
public Result OpenBisStorage(ref SharedRef<IStorageSf> outStorage, BisPartitionId partitionId)
|
||||
{
|
||||
return GetBaseStorageService().OpenBisStorage(out storage, partitionId);
|
||||
return GetBaseStorageService().OpenBisStorage(ref outStorage, partitionId);
|
||||
}
|
||||
|
||||
public Result InvalidateBisCache()
|
||||
@ -509,16 +465,14 @@ namespace LibHac.FsSrv
|
||||
return GetBaseStorageService().InvalidateBisCache();
|
||||
}
|
||||
|
||||
public Result OpenHostFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, in FspPath path)
|
||||
public Result OpenHostFileSystem(ref SharedRef<IFileSystemSf> outFileSystem, in FspPath path)
|
||||
{
|
||||
return OpenHostFileSystemWithOption(out fileSystem, in path, MountHostOption.None);
|
||||
return OpenHostFileSystemWithOption(ref outFileSystem, in path, MountHostOption.None);
|
||||
}
|
||||
|
||||
public Result OpenHostFileSystemWithOption(out ReferenceCountedDisposable<IFileSystemSf> fileSystem,
|
||||
public Result OpenHostFileSystemWithOption(ref SharedRef<IFileSystemSf> outFileSystem,
|
||||
in FspPath path, MountHostOption option)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
|
||||
Result rc = GetProgramInfo(out ProgramInfo programInfo);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
@ -527,52 +481,48 @@ namespace LibHac.FsSrv
|
||||
if (!accessibility.CanRead || !accessibility.CanWrite)
|
||||
return ResultFs.PermissionDenied.Log();
|
||||
|
||||
ReferenceCountedDisposable<IFileSystem> hostFileSystem = null;
|
||||
try
|
||||
using var hostFileSystem = new SharedRef<IFileSystem>();
|
||||
using var pathNormalized = new Path();
|
||||
|
||||
if (path.Str.At(0) == DirectorySeparator && path.Str.At(1) != DirectorySeparator)
|
||||
{
|
||||
using var pathNormalized = new Path();
|
||||
|
||||
if (path.Str.At(0) == DirectorySeparator && path.Str.At(1) != DirectorySeparator)
|
||||
{
|
||||
rc = pathNormalized.Initialize(path.Str.Slice(1));
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = pathNormalized.InitializeWithReplaceUnc(path.Str);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
|
||||
var flags = new PathFlags();
|
||||
flags.AllowWindowsPath();
|
||||
flags.AllowRelativePath();
|
||||
flags.AllowEmptyPath();
|
||||
|
||||
rc = pathNormalized.Normalize(flags);
|
||||
rc = pathNormalized.Initialize(path.Str.Slice(1));
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
bool isCaseSensitive = option.Flags.HasFlag(MountHostOptionFlag.PseudoCaseSensitive);
|
||||
|
||||
rc = FsProxyCore.OpenHostFileSystem(out hostFileSystem, in pathNormalized, isCaseSensitive);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
var adapterFlags = new PathFlags();
|
||||
if (path.Str.At(0) == NullTerminator)
|
||||
adapterFlags.AllowWindowsPath();
|
||||
|
||||
fileSystem = FileSystemInterfaceAdapter.CreateShared(ref hostFileSystem, adapterFlags, false);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
else
|
||||
{
|
||||
hostFileSystem?.Dispose();
|
||||
rc = pathNormalized.InitializeWithReplaceUnc(path.Str);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
|
||||
var flags = new PathFlags();
|
||||
flags.AllowWindowsPath();
|
||||
flags.AllowRelativePath();
|
||||
flags.AllowEmptyPath();
|
||||
|
||||
rc = pathNormalized.Normalize(flags);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
bool isCaseSensitive = option.Flags.HasFlag(MountHostOptionFlag.PseudoCaseSensitive);
|
||||
|
||||
rc = _fsProxyCore.OpenHostFileSystem(ref hostFileSystem.Ref(), in pathNormalized, isCaseSensitive);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
var adapterFlags = new PathFlags();
|
||||
if (path.Str.At(0) == NullTerminator)
|
||||
adapterFlags.AllowWindowsPath();
|
||||
|
||||
using SharedRef<IFileSystemSf> fileSystemAdapter =
|
||||
FileSystemInterfaceAdapter.CreateShared(ref hostFileSystem.Ref(), adapterFlags, false);
|
||||
|
||||
outFileSystem.SetByMove(ref fileSystemAdapter.Ref());
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenSdCardFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem)
|
||||
public Result OpenSdCardFileSystem(ref SharedRef<IFileSystemSf> outFileSystem)
|
||||
{
|
||||
return GetBaseFileSystemService().OpenSdCardFileSystem(out fileSystem);
|
||||
return GetBaseFileSystemService().OpenSdCardFileSystem(ref outFileSystem);
|
||||
}
|
||||
|
||||
public Result FormatSdCardFileSystem()
|
||||
@ -590,25 +540,25 @@ namespace LibHac.FsSrv
|
||||
return GetBaseFileSystemService().IsExFatSupported(out isSupported);
|
||||
}
|
||||
|
||||
public Result OpenGameCardStorage(out ReferenceCountedDisposable<IStorageSf> storage, GameCardHandle handle,
|
||||
public Result OpenGameCardStorage(ref SharedRef<IStorageSf> outStorage, GameCardHandle handle,
|
||||
GameCardPartitionRaw partitionId)
|
||||
{
|
||||
return GetBaseStorageService().OpenGameCardStorage(out storage, handle, partitionId);
|
||||
return GetBaseStorageService().OpenGameCardStorage(ref outStorage, handle, partitionId);
|
||||
}
|
||||
|
||||
public Result OpenDeviceOperator(out ReferenceCountedDisposable<IDeviceOperator> deviceOperator)
|
||||
public Result OpenDeviceOperator(ref SharedRef<IDeviceOperator> outDeviceOperator)
|
||||
{
|
||||
return GetBaseStorageService().OpenDeviceOperator(out deviceOperator);
|
||||
return GetBaseStorageService().OpenDeviceOperator(ref outDeviceOperator);
|
||||
}
|
||||
|
||||
public Result OpenSdCardDetectionEventNotifier(out ReferenceCountedDisposable<IEventNotifier> eventNotifier)
|
||||
public Result OpenSdCardDetectionEventNotifier(ref SharedRef<IEventNotifier> outEventNotifier)
|
||||
{
|
||||
return GetBaseStorageService().OpenSdCardDetectionEventNotifier(out eventNotifier);
|
||||
return GetBaseStorageService().OpenSdCardDetectionEventNotifier(ref outEventNotifier);
|
||||
}
|
||||
|
||||
public Result OpenGameCardDetectionEventNotifier(out ReferenceCountedDisposable<IEventNotifier> eventNotifier)
|
||||
public Result OpenGameCardDetectionEventNotifier(ref SharedRef<IEventNotifier> outEventNotifier)
|
||||
{
|
||||
return GetBaseStorageService().OpenGameCardDetectionEventNotifier(out eventNotifier);
|
||||
return GetBaseStorageService().OpenGameCardDetectionEventNotifier(ref outEventNotifier);
|
||||
}
|
||||
|
||||
public Result SimulateDeviceDetectionEvent(SdmmcPort port, SimulatingDeviceDetectionMode mode, bool signalEvent)
|
||||
@ -616,16 +566,12 @@ namespace LibHac.FsSrv
|
||||
return GetBaseStorageService().SimulateDeviceDetectionEvent(port, mode, signalEvent);
|
||||
}
|
||||
|
||||
public Result OpenSystemDataUpdateEventNotifier(out ReferenceCountedDisposable<IEventNotifier> eventNotifier)
|
||||
public Result OpenSystemDataUpdateEventNotifier(ref SharedRef<IEventNotifier> outEventNotifier)
|
||||
{
|
||||
Result rc = GetNcaFileSystemService(out NcaFileSystemService ncaFsService);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out eventNotifier);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return ncaFsService.OpenSystemDataUpdateEventNotifier(out eventNotifier);
|
||||
return ncaFsService.OpenSystemDataUpdateEventNotifier(ref outEventNotifier);
|
||||
}
|
||||
|
||||
public Result NotifySystemDataUpdateEvent()
|
||||
@ -636,42 +582,30 @@ namespace LibHac.FsSrv
|
||||
return ncaFsService.NotifySystemDataUpdateEvent();
|
||||
}
|
||||
|
||||
public Result OpenSaveDataInfoReader(out ReferenceCountedDisposable<ISaveDataInfoReader> infoReader)
|
||||
public Result OpenSaveDataInfoReader(ref SharedRef<ISaveDataInfoReader> outInfoReader)
|
||||
{
|
||||
Result rc = GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out infoReader);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return saveFsService.OpenSaveDataInfoReader(out infoReader);
|
||||
return saveFsService.OpenSaveDataInfoReader(ref outInfoReader);
|
||||
}
|
||||
|
||||
public Result OpenSaveDataInfoReaderBySaveDataSpaceId(
|
||||
out ReferenceCountedDisposable<ISaveDataInfoReader> infoReader, SaveDataSpaceId spaceId)
|
||||
ref SharedRef<ISaveDataInfoReader> outInfoReader, SaveDataSpaceId spaceId)
|
||||
{
|
||||
Result rc = GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out infoReader);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return saveFsService.OpenSaveDataInfoReaderBySaveDataSpaceId(out infoReader, spaceId);
|
||||
return saveFsService.OpenSaveDataInfoReaderBySaveDataSpaceId(ref outInfoReader, spaceId);
|
||||
}
|
||||
|
||||
public Result OpenSaveDataInfoReaderWithFilter(out ReferenceCountedDisposable<ISaveDataInfoReader> infoReader,
|
||||
public Result OpenSaveDataInfoReaderWithFilter(ref SharedRef<ISaveDataInfoReader> outInfoReader,
|
||||
SaveDataSpaceId spaceId, in SaveDataFilter filter)
|
||||
{
|
||||
Result rc = GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out infoReader);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return saveFsService.OpenSaveDataInfoReaderWithFilter(out infoReader, spaceId, in filter);
|
||||
return saveFsService.OpenSaveDataInfoReaderWithFilter(ref outInfoReader, spaceId, in filter);
|
||||
}
|
||||
|
||||
public Result FindSaveDataWithFilter(out long count, OutBuffer saveDataInfoBuffer, SaveDataSpaceId spaceId,
|
||||
@ -685,17 +619,13 @@ namespace LibHac.FsSrv
|
||||
return saveFsService.FindSaveDataWithFilter(out count, saveDataInfoBuffer, spaceId, in filter);
|
||||
}
|
||||
|
||||
public Result OpenSaveDataInternalStorageFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem,
|
||||
public Result OpenSaveDataInternalStorageFileSystem(ref SharedRef<IFileSystemSf> outFileSystem,
|
||||
SaveDataSpaceId spaceId, ulong saveDataId)
|
||||
{
|
||||
Result rc = GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return saveFsService.OpenSaveDataInternalStorageFileSystem(out fileSystem, spaceId, saveDataId);
|
||||
return saveFsService.OpenSaveDataInternalStorageFileSystem(ref outFileSystem, spaceId, saveDataId);
|
||||
}
|
||||
|
||||
public Result QuerySaveDataInternalStorageTotalSize(out long size, SaveDataSpaceId spaceId, ulong saveDataId)
|
||||
@ -718,30 +648,21 @@ namespace LibHac.FsSrv
|
||||
return saveFsService.GetSaveDataCommitId(out commitId, spaceId, saveDataId);
|
||||
}
|
||||
|
||||
public Result OpenSaveDataInfoReaderOnlyCacheStorage(
|
||||
out ReferenceCountedDisposable<ISaveDataInfoReader> infoReader)
|
||||
public Result OpenSaveDataInfoReaderOnlyCacheStorage(ref SharedRef<ISaveDataInfoReader> outInfoReader)
|
||||
{
|
||||
Result rc = GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out infoReader);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return saveFsService.OpenSaveDataInfoReaderOnlyCacheStorage(out infoReader);
|
||||
return saveFsService.OpenSaveDataInfoReaderOnlyCacheStorage(ref outInfoReader);
|
||||
}
|
||||
|
||||
public Result OpenSaveDataMetaFile(out ReferenceCountedDisposable<IFileSf> file, SaveDataSpaceId spaceId,
|
||||
public Result OpenSaveDataMetaFile(ref SharedRef<IFileSf> outFile, SaveDataSpaceId spaceId,
|
||||
in SaveDataAttribute attribute, SaveDataMetaType type)
|
||||
{
|
||||
Result rc = GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out file);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return saveFsService.OpenSaveDataMetaFile(out file, spaceId, in attribute, type);
|
||||
return saveFsService.OpenSaveDataMetaFile(ref outFile, spaceId, in attribute, type);
|
||||
}
|
||||
|
||||
public Result DeleteCacheStorage(ushort index)
|
||||
@ -762,58 +683,48 @@ namespace LibHac.FsSrv
|
||||
return saveFsService.GetCacheStorageSize(out dataSize, out journalSize, index);
|
||||
}
|
||||
|
||||
public Result OpenSaveDataTransferManager(out ReferenceCountedDisposable<ISaveDataTransferManager> manager)
|
||||
public Result OpenSaveDataTransferManager(ref SharedRef<ISaveDataTransferManager> outTransferManager)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out manager);
|
||||
|
||||
Result rc = GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return saveFsService.OpenSaveDataTransferManager(out manager);
|
||||
return saveFsService.OpenSaveDataTransferManager(ref outTransferManager);
|
||||
}
|
||||
|
||||
public Result OpenSaveDataTransferManagerVersion2(
|
||||
out ReferenceCountedDisposable<ISaveDataTransferManagerWithDivision> manager)
|
||||
ref SharedRef<ISaveDataTransferManagerWithDivision> outTransferManager)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out manager);
|
||||
|
||||
Result rc = GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return saveFsService.OpenSaveDataTransferManagerVersion2(out manager);
|
||||
return saveFsService.OpenSaveDataTransferManagerVersion2(ref outTransferManager);
|
||||
}
|
||||
|
||||
public Result OpenSaveDataTransferManagerForSaveDataRepair(
|
||||
out ReferenceCountedDisposable<ISaveDataTransferManagerForSaveDataRepair> manager)
|
||||
ref SharedRef<ISaveDataTransferManagerForSaveDataRepair> outTransferManager)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out manager);
|
||||
|
||||
Result rc = GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return saveFsService.OpenSaveDataTransferManagerForSaveDataRepair(out manager);
|
||||
return saveFsService.OpenSaveDataTransferManagerForSaveDataRepair(ref outTransferManager);
|
||||
}
|
||||
|
||||
public Result OpenSaveDataTransferManagerForRepair(
|
||||
out ReferenceCountedDisposable<ISaveDataTransferManagerForRepair> manager)
|
||||
ref SharedRef<ISaveDataTransferManagerForRepair> outTransferManager)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out manager);
|
||||
|
||||
Result rc = GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return saveFsService.OpenSaveDataTransferManagerForRepair(out manager);
|
||||
return saveFsService.OpenSaveDataTransferManagerForRepair(ref outTransferManager);
|
||||
}
|
||||
|
||||
public Result OpenSaveDataTransferProhibiter(
|
||||
out ReferenceCountedDisposable<ISaveDataTransferProhibiter> prohibiter, Ncm.ApplicationId applicationId)
|
||||
public Result OpenSaveDataTransferProhibiter(ref SharedRef<ISaveDataTransferProhibiter> outProhibiter,
|
||||
Ncm.ApplicationId applicationId)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out prohibiter);
|
||||
|
||||
Result rc = GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return saveFsService.OpenSaveDataTransferProhibiter(out prohibiter, applicationId);
|
||||
return saveFsService.OpenSaveDataTransferProhibiter(ref outProhibiter, applicationId);
|
||||
}
|
||||
|
||||
public Result ListAccessibleSaveDataOwnerId(out int readCount, OutBuffer idBuffer, ProgramId programId,
|
||||
@ -828,19 +739,14 @@ namespace LibHac.FsSrv
|
||||
bufferIdCount);
|
||||
}
|
||||
|
||||
public Result OpenSaveDataMover(out ReferenceCountedDisposable<ISaveDataMover> saveMover,
|
||||
SaveDataSpaceId sourceSpaceId, SaveDataSpaceId destinationSpaceId, NativeHandle workBufferHandle,
|
||||
ulong workBufferSize)
|
||||
public Result OpenSaveDataMover(ref SharedRef<ISaveDataMover> outSaveDataMover, SaveDataSpaceId sourceSpaceId,
|
||||
SaveDataSpaceId destinationSpaceId, NativeHandle workBufferHandle, ulong workBufferSize)
|
||||
{
|
||||
Result rc = GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out saveMover);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return saveFsService.OpenSaveDataMover(out saveMover, sourceSpaceId, destinationSpaceId, workBufferHandle,
|
||||
workBufferSize);
|
||||
return saveFsService.OpenSaveDataMover(ref outSaveDataMover, sourceSpaceId, destinationSpaceId,
|
||||
workBufferHandle, workBufferSize);
|
||||
}
|
||||
|
||||
public Result SetSaveDataSize(long saveDataSize, long saveDataJournalSize)
|
||||
@ -864,25 +770,20 @@ namespace LibHac.FsSrv
|
||||
return saveFsService.UnsetSaveDataRootPath();
|
||||
}
|
||||
|
||||
public Result OpenContentStorageFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem,
|
||||
public Result OpenContentStorageFileSystem(ref SharedRef<IFileSystemSf> outFileSystem,
|
||||
ContentStorageId storageId)
|
||||
{
|
||||
Result rc = GetNcaFileSystemService(out NcaFileSystemService ncaFsService);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
return ncaFsService.OpenContentStorageFileSystem(out fileSystem, storageId);
|
||||
return ncaFsService.OpenContentStorageFileSystem(ref outFileSystem, storageId);
|
||||
}
|
||||
|
||||
public Result OpenCloudBackupWorkStorageFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem,
|
||||
public Result OpenCloudBackupWorkStorageFileSystem(ref SharedRef<IFileSystemSf> outFileSystem,
|
||||
CloudBackupWorkStorageId storageId)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
var storageFlag = StorageType.NonGameCard;
|
||||
using var scopedLayoutType = new ScopedStorageLayoutTypeSetter(storageFlag);
|
||||
using var scopedContext = new ScopedStorageLayoutTypeSetter(storageFlag);
|
||||
|
||||
Result rc = GetProgramInfo(out ProgramInfo programInfo);
|
||||
if (rc.IsFailure()) return rc;
|
||||
@ -893,30 +794,29 @@ namespace LibHac.FsSrv
|
||||
if (!accessibility.CanRead || !accessibility.CanWrite)
|
||||
return ResultFs.PermissionDenied.Log();
|
||||
|
||||
ReferenceCountedDisposable<IFileSystem> tempFs = null;
|
||||
try
|
||||
{
|
||||
rc = FsProxyCore.OpenCloudBackupWorkStorageFileSystem(out tempFs, storageId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
using var fileSystem = new SharedRef<IFileSystem>();
|
||||
rc = _fsProxyCore.OpenCloudBackupWorkStorageFileSystem(ref fileSystem.Ref(), storageId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
tempFs = StorageLayoutTypeSetFileSystem.CreateShared(ref tempFs, storageFlag);
|
||||
tempFs = AsynchronousAccessFileSystem.CreateShared(ref tempFs);
|
||||
fileSystem = FileSystemInterfaceAdapter.CreateShared(ref tempFs, false);
|
||||
// Add all the wrappers for the file system
|
||||
using var typeSetFileSystem =
|
||||
new SharedRef<IFileSystem>(new StorageLayoutTypeSetFileSystem(ref fileSystem.Ref(), storageFlag));
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
tempFs?.Dispose();
|
||||
}
|
||||
using var asyncFileSystem =
|
||||
new SharedRef<IFileSystem>(new AsynchronousAccessFileSystem(ref typeSetFileSystem.Ref()));
|
||||
|
||||
using SharedRef<IFileSystemSf> fileSystemAdapter =
|
||||
FileSystemInterfaceAdapter.CreateShared(ref asyncFileSystem.Ref(), false);
|
||||
|
||||
outFileSystem.SetByMove(ref fileSystemAdapter.Ref());
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenCustomStorageFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem,
|
||||
CustomStorageId storageId)
|
||||
public Result OpenCustomStorageFileSystem(ref SharedRef<IFileSystemSf> outFileSystem, CustomStorageId storageId)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
var storageFlag = StorageType.NonGameCard;
|
||||
using var scopedLayoutType = new ScopedStorageLayoutTypeSetter(storageFlag);
|
||||
using var scopedContext = new ScopedStorageLayoutTypeSetter(storageFlag);
|
||||
|
||||
Result rc = GetProgramInfo(out ProgramInfo programInfo);
|
||||
if (rc.IsFailure()) return rc;
|
||||
@ -930,28 +830,29 @@ namespace LibHac.FsSrv
|
||||
if (!accessibility.CanRead || !accessibility.CanWrite)
|
||||
return ResultFs.PermissionDenied.Log();
|
||||
|
||||
ReferenceCountedDisposable<IFileSystem> customFs = null;
|
||||
try
|
||||
{
|
||||
rc = FsProxyCore.OpenCustomStorageFileSystem(out customFs, storageId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
using var fileSystem = new SharedRef<IFileSystem>();
|
||||
rc = _fsProxyCore.OpenCustomStorageFileSystem(ref fileSystem.Ref(), storageId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
customFs = StorageLayoutTypeSetFileSystem.CreateShared(ref customFs, storageFlag);
|
||||
customFs = AsynchronousAccessFileSystem.CreateShared(ref customFs);
|
||||
fileSystem = FileSystemInterfaceAdapter.CreateShared(ref customFs, false);
|
||||
// Add all the file system wrappers
|
||||
using var typeSetFileSystem =
|
||||
new SharedRef<IFileSystem>(new StorageLayoutTypeSetFileSystem(ref fileSystem.Ref(), storageFlag));
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
customFs?.Dispose();
|
||||
}
|
||||
using var asyncFileSystem =
|
||||
new SharedRef<IFileSystem>(new AsynchronousAccessFileSystem(ref typeSetFileSystem.Ref()));
|
||||
|
||||
using SharedRef<IFileSystemSf> fileSystemAdapter =
|
||||
FileSystemInterfaceAdapter.CreateShared(ref asyncFileSystem.Ref(), false);
|
||||
|
||||
outFileSystem.SetByMove(ref fileSystemAdapter.Ref());
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenGameCardFileSystem(out ReferenceCountedDisposable<IFileSystemSf> fileSystem,
|
||||
GameCardHandle handle, GameCardPartition partitionId)
|
||||
public Result OpenGameCardFileSystem(ref SharedRef<IFileSystemSf> outFileSystem, GameCardHandle handle,
|
||||
GameCardPartition partitionId)
|
||||
{
|
||||
return GetBaseFileSystemService().OpenGameCardFileSystem(out fileSystem, handle, partitionId);
|
||||
return GetBaseFileSystemService().OpenGameCardFileSystem(ref outFileSystem, handle, partitionId);
|
||||
}
|
||||
|
||||
public Result IsArchivedProgram(out bool isArchived, ulong processId)
|
||||
@ -1036,7 +937,7 @@ namespace LibHac.FsSrv
|
||||
if (!programInfo.AccessControl.CanCall(OperationType.SetEncryptionSeed))
|
||||
return ResultFs.PermissionDenied.Log();
|
||||
|
||||
rc = FsProxyCore.SetSdCardEncryptionSeed(in seed);
|
||||
rc = _fsProxyCore.SetSdCardEncryptionSeed(in seed);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService);
|
||||
@ -1161,16 +1062,12 @@ namespace LibHac.FsSrv
|
||||
return ncaFsService.RegisterUpdatePartition();
|
||||
}
|
||||
|
||||
public Result OpenRegisteredUpdatePartition(out ReferenceCountedDisposable<IFileSystemSf> fileSystem)
|
||||
public Result OpenRegisteredUpdatePartition(ref SharedRef<IFileSystemSf> outFileSystem)
|
||||
{
|
||||
Result rc = GetNcaFileSystemService(out NcaFileSystemService ncaFsService);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
return rc;
|
||||
}
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return ncaFsService.OpenRegisteredUpdatePartition(out fileSystem);
|
||||
return ncaFsService.OpenRegisteredUpdatePartition(ref outFileSystem);
|
||||
}
|
||||
|
||||
public Result GetAndClearMemoryReportInfo(out MemoryReportInfo reportInfo)
|
||||
@ -1209,11 +1106,11 @@ namespace LibHac.FsSrv
|
||||
return saveFsService.IsSdCardAccessible(out isAccessible);
|
||||
}
|
||||
|
||||
public Result OpenAccessFailureDetectionEventNotifier(out ReferenceCountedDisposable<IEventNotifier> notifier,
|
||||
public Result OpenAccessFailureDetectionEventNotifier(ref SharedRef<IEventNotifier> outEventNotifier,
|
||||
ulong processId, bool notifyOnDeepRetry)
|
||||
{
|
||||
return GetAccessFailureManagementService()
|
||||
.OpenAccessFailureDetectionEventNotifier(out notifier, processId, notifyOnDeepRetry);
|
||||
.OpenAccessFailureDetectionEventNotifier(ref outEventNotifier, processId, notifyOnDeepRetry);
|
||||
}
|
||||
|
||||
public Result GetAccessFailureDetectionEvent(out NativeHandle eventHandle)
|
||||
@ -1236,20 +1133,18 @@ namespace LibHac.FsSrv
|
||||
return GetAccessFailureManagementService().AbandonAccessFailure(processId);
|
||||
}
|
||||
|
||||
public Result OpenMultiCommitManager(out ReferenceCountedDisposable<IMultiCommitManager> commitManager)
|
||||
public Result OpenMultiCommitManager(ref SharedRef<IMultiCommitManager> outCommitManager)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out commitManager);
|
||||
|
||||
Result rc = GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return saveFsService.OpenMultiCommitManager(out commitManager);
|
||||
return saveFsService.OpenMultiCommitManager(ref outCommitManager);
|
||||
}
|
||||
|
||||
public Result OpenBisWiper(out ReferenceCountedDisposable<IWiper> bisWiper, NativeHandle transferMemoryHandle,
|
||||
public Result OpenBisWiper(ref SharedRef<IWiper> outBisWiper, NativeHandle transferMemoryHandle,
|
||||
ulong transferMemorySize)
|
||||
{
|
||||
return GetBaseFileSystemService().OpenBisWiper(out bisWiper, transferMemoryHandle, transferMemorySize);
|
||||
return GetBaseFileSystemService().OpenBisWiper(ref outBisWiper, transferMemoryHandle, transferMemorySize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Impl;
|
||||
using LibHac.Fs.Shim;
|
||||
using LibHac.FsSrv.FsCreator;
|
||||
@ -38,11 +39,11 @@ namespace LibHac.FsSrv
|
||||
|
||||
FileSystemProxyConfiguration fspConfig = InitializeFileSystemProxy(server, config);
|
||||
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = server.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> fileSystemProxy = server.Impl.GetFileSystemProxyServiceObject();
|
||||
ulong processId = client.Os.GetCurrentProcessId().Value;
|
||||
fsProxy.Target.SetCurrentProcess(processId).IgnoreResult();
|
||||
fileSystemProxy.Get.SetCurrentProcess(processId).IgnoreResult();
|
||||
|
||||
client.Fs.Impl.InitializeDfcFileSystemProxyServiceObject(fsProxy);
|
||||
client.Fs.Impl.InitializeDfcFileSystemProxyServiceObject(ref fileSystemProxy.Ref());
|
||||
|
||||
InitializeFileSystemProxyServer(client, server);
|
||||
|
||||
@ -76,7 +77,10 @@ namespace LibHac.FsSrv
|
||||
var saveDataIndexerManager = new SaveDataIndexerManager(server.Hos.Fs, Fs.SaveData.SaveIndexerId,
|
||||
new ArrayPoolMemoryResource(), new SdHandleManager(), false);
|
||||
|
||||
var programRegistryService = new ProgramRegistryServiceImpl(server);
|
||||
var programRegistryConfig = new ProgramRegistryServiceImpl.Configuration();
|
||||
programRegistryConfig.FsServer = server;
|
||||
|
||||
var programRegistryService = new ProgramRegistryServiceImpl(in programRegistryConfig);
|
||||
|
||||
server.InitializeProgramRegistryImpl(programRegistryService);
|
||||
|
||||
@ -84,7 +88,7 @@ namespace LibHac.FsSrv
|
||||
baseStorageConfig.BisStorageCreator = config.FsCreators.BuiltInStorageCreator;
|
||||
baseStorageConfig.GameCardStorageCreator = config.FsCreators.GameCardStorageCreator;
|
||||
baseStorageConfig.FsServer = server;
|
||||
baseStorageConfig.DeviceOperator = new ReferenceCountedDisposable<IDeviceOperator>(config.DeviceOperator);
|
||||
baseStorageConfig.DeviceOperator = new SharedRef<IDeviceOperator>(config.DeviceOperator);
|
||||
var baseStorageService = new BaseStorageServiceImpl(in baseStorageConfig);
|
||||
|
||||
var timeService = new TimeServiceImpl(server);
|
||||
@ -194,9 +198,10 @@ namespace LibHac.FsSrv
|
||||
_server = server;
|
||||
}
|
||||
|
||||
public Result GetServiceObject(out object serviceObject)
|
||||
public Result GetServiceObject(ref SharedRef<IDisposable> serviceObject)
|
||||
{
|
||||
serviceObject = _server.Impl.GetFileSystemProxyServiceObject();
|
||||
using SharedRef<IFileSystemProxy> derivedObject = _server.Impl.GetFileSystemProxyServiceObject();
|
||||
serviceObject.SetByMove(ref derivedObject.Ref());
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
@ -210,9 +215,10 @@ namespace LibHac.FsSrv
|
||||
_server = server;
|
||||
}
|
||||
|
||||
public Result GetServiceObject(out object serviceObject)
|
||||
public Result GetServiceObject(ref SharedRef<IDisposable> serviceObject)
|
||||
{
|
||||
serviceObject = _server.Impl.GetFileSystemProxyForLoaderServiceObject();
|
||||
using SharedRef<IFileSystemProxyForLoader> derivedObject = _server.Impl.GetFileSystemProxyForLoaderServiceObject();
|
||||
serviceObject.SetByMove(ref derivedObject.Ref());
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
@ -226,9 +232,10 @@ namespace LibHac.FsSrv
|
||||
_server = server;
|
||||
}
|
||||
|
||||
public Result GetServiceObject(out object serviceObject)
|
||||
public Result GetServiceObject(ref SharedRef<IDisposable> serviceObject)
|
||||
{
|
||||
serviceObject = _server.Impl.GetProgramRegistryServiceObject();
|
||||
using SharedRef<IProgramRegistry> derivedObject = _server.Impl.GetProgramRegistryServiceObject();
|
||||
serviceObject.SetByMove(ref derivedObject.Ref());
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
@ -39,10 +39,10 @@ namespace LibHac.FsSrv.FsCreator
|
||||
/// Each partition will be located at their default paths in this IFileSystem.
|
||||
/// </summary>
|
||||
/// <param name="rootFileSystem">The <see cref="IFileSystem"/> to use as the root file system.</param>
|
||||
public EmulatedBisFileSystemCreator(IFileSystem rootFileSystem)
|
||||
public EmulatedBisFileSystemCreator(ref SharedRef<IFileSystem> rootFileSystem)
|
||||
{
|
||||
Config = new EmulatedBisFileSystemCreatorConfig();
|
||||
Config.RootFileSystem = rootFileSystem;
|
||||
Config.SetRootFileSystem(ref rootFileSystem).ThrowIfFailure();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -55,20 +55,20 @@ namespace LibHac.FsSrv.FsCreator
|
||||
}
|
||||
|
||||
// Todo: Make case sensitive
|
||||
public Result Create(out ReferenceCountedDisposable<IFileSystem> fileSystem, BisPartitionId partitionId,
|
||||
bool caseSensitive)
|
||||
public Result Create(ref SharedRef<IFileSystem> outFileSystem, BisPartitionId partitionId, bool caseSensitive)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
|
||||
if (!IsValidPartitionId(partitionId)) return ResultFs.InvalidArgument.Log();
|
||||
|
||||
if (Config.TryGetFileSystem(out IFileSystem fs, partitionId))
|
||||
using var fileSystem = new SharedRef<IFileSystem>();
|
||||
if (Config.TryGetFileSystem(ref fileSystem.Ref(), partitionId))
|
||||
{
|
||||
fileSystem = new ReferenceCountedDisposable<IFileSystem>(fs);
|
||||
outFileSystem.SetByMove(ref fileSystem.Ref());
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
if (Config.RootFileSystem == null)
|
||||
using var rootFileSystem = new SharedRef<IFileSystem>();
|
||||
|
||||
if (!Config.TryGetRootFileSystem(ref rootFileSystem.Ref()))
|
||||
{
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
}
|
||||
@ -82,23 +82,12 @@ namespace LibHac.FsSrv.FsCreator
|
||||
rc = bisRootPath.Normalize(pathFlags);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
ReferenceCountedDisposable<IFileSystem> partitionFileSystem = null;
|
||||
ReferenceCountedDisposable<IFileSystem> sharedRootFs = null;
|
||||
try
|
||||
{
|
||||
sharedRootFs = new ReferenceCountedDisposable<IFileSystem>(Config.RootFileSystem);
|
||||
using var partitionFileSystem = new SharedRef<IFileSystem>();
|
||||
rc = Utility.WrapSubDirectory(ref partitionFileSystem.Ref(), ref rootFileSystem.Ref(), in bisRootPath, true);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = Utility.WrapSubDirectory(out partitionFileSystem, ref sharedRootFs, in bisRootPath, true);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
Shared.Move(out fileSystem, ref partitionFileSystem);
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
partitionFileSystem?.Dispose();
|
||||
sharedRootFs?.Dispose();
|
||||
}
|
||||
outFileSystem.SetByMove(ref partitionFileSystem.Ref());
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result SetBisRoot(BisPartitionId partitionId, string rootPath)
|
||||
|
@ -13,17 +13,27 @@ namespace LibHac.FsSrv.FsCreator
|
||||
{
|
||||
private const int ValidPartitionCount = 4;
|
||||
|
||||
public IFileSystem RootFileSystem { get; set; }
|
||||
private SharedRef<IFileSystem> _rootFileSystem;
|
||||
|
||||
private IFileSystem[] PartitionFileSystems { get; } = new IFileSystem[ValidPartitionCount];
|
||||
private SharedRef<IFileSystem>[] PartitionFileSystems { get; } = new SharedRef<IFileSystem>[ValidPartitionCount];
|
||||
private string[] PartitionPaths { get; } = new string[ValidPartitionCount];
|
||||
|
||||
public Result SetFileSystem(IFileSystem fileSystem, BisPartitionId partitionId)
|
||||
public Result SetRootFileSystem(ref SharedRef<IFileSystem> fileSystem)
|
||||
{
|
||||
if (fileSystem == null) return ResultFs.NullptrArgument.Log();
|
||||
if (!fileSystem.HasValue) return ResultFs.NullptrArgument.Log();
|
||||
if (_rootFileSystem.HasValue) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
_rootFileSystem.SetByMove(ref fileSystem);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result SetFileSystem(ref UniqueRef<IFileSystem> fileSystem, BisPartitionId partitionId)
|
||||
{
|
||||
if (!fileSystem.HasValue) return ResultFs.NullptrArgument.Log();
|
||||
if (!IsValidPartitionId(partitionId)) return ResultFs.InvalidArgument.Log();
|
||||
|
||||
PartitionFileSystems[GetArrayIndex(partitionId)] = fileSystem;
|
||||
PartitionFileSystems[GetArrayIndex(partitionId)].Set(ref fileSystem);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
@ -38,17 +48,21 @@ namespace LibHac.FsSrv.FsCreator
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public bool TryGetFileSystem(out IFileSystem fileSystem, BisPartitionId partitionId)
|
||||
public bool TryGetRootFileSystem(ref SharedRef<IFileSystem> outFileSystem)
|
||||
{
|
||||
outFileSystem.SetByCopy(ref _rootFileSystem);
|
||||
|
||||
return outFileSystem.HasValue;
|
||||
}
|
||||
|
||||
public bool TryGetFileSystem(ref SharedRef<IFileSystem> outFileSystem, BisPartitionId partitionId)
|
||||
{
|
||||
if (!IsValidPartitionId(partitionId))
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
return false;
|
||||
}
|
||||
|
||||
fileSystem = PartitionFileSystems[GetArrayIndex(partitionId)];
|
||||
outFileSystem.SetByCopy(ref PartitionFileSystems[GetArrayIndex(partitionId)]);
|
||||
|
||||
return fileSystem != null;
|
||||
return outFileSystem.HasValue;
|
||||
}
|
||||
|
||||
public bool TryGetPartitionPath(out string path, BisPartitionId partitionId)
|
||||
|
@ -6,41 +6,22 @@ namespace LibHac.FsSrv.FsCreator
|
||||
{
|
||||
public class EmulatedGameCardFsCreator : IGameCardFileSystemCreator
|
||||
{
|
||||
// ReSharper disable once UnusedAutoPropertyAccessor.Local
|
||||
private EmulatedGameCardStorageCreator StorageCreator { get; }
|
||||
private EmulatedGameCard GameCard { get; }
|
||||
// ReSharper disable once NotAccessedField.Local
|
||||
private EmulatedGameCardStorageCreator _storageCreator;
|
||||
private EmulatedGameCard _gameCard;
|
||||
|
||||
public EmulatedGameCardFsCreator(EmulatedGameCardStorageCreator storageCreator, EmulatedGameCard gameCard)
|
||||
{
|
||||
StorageCreator = storageCreator;
|
||||
GameCard = gameCard;
|
||||
_storageCreator = storageCreator;
|
||||
_gameCard = gameCard;
|
||||
}
|
||||
|
||||
public Result Create(out IFileSystem fileSystem, GameCardHandle handle, GameCardPartition partitionType)
|
||||
public Result Create(ref SharedRef<IFileSystem> outFileSystem, GameCardHandle handle,
|
||||
GameCardPartition partitionType)
|
||||
{
|
||||
// Use the old xci code temporarily
|
||||
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
|
||||
Result rc = GameCard.GetXci(out Xci xci, handle);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (!xci.HasPartition((XciPartitionType)partitionType))
|
||||
{
|
||||
return ResultFs.PartitionNotFound.Log();
|
||||
}
|
||||
|
||||
fileSystem = xci.OpenPartition((XciPartitionType)partitionType);
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result Create(out ReferenceCountedDisposable<IFileSystem> fileSystem, GameCardHandle handle, GameCardPartition partitionType)
|
||||
{
|
||||
// Use the old xci code temporarily
|
||||
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
|
||||
Result rc = GameCard.GetXci(out Xci xci, handle);
|
||||
Result rc = _gameCard.GetXci(out Xci xci, handle);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (!xci.HasPartition((XciPartitionType)partitionType))
|
||||
@ -49,7 +30,7 @@ namespace LibHac.FsSrv.FsCreator
|
||||
}
|
||||
|
||||
XciPartition fs = xci.OpenPartition((XciPartitionType)partitionType);
|
||||
fileSystem = new ReferenceCountedDisposable<IFileSystem>(fs);
|
||||
outFileSystem.Reset(fs);
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
@ -13,29 +13,24 @@ namespace LibHac.FsSrv.FsCreator
|
||||
GameCard = gameCard;
|
||||
}
|
||||
|
||||
public Result CreateReadOnly(GameCardHandle handle, out ReferenceCountedDisposable<IStorage> storage)
|
||||
public Result CreateReadOnly(GameCardHandle handle, ref SharedRef<IStorage> outStorage)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out storage);
|
||||
|
||||
if (GameCard.IsGameCardHandleInvalid(handle))
|
||||
{
|
||||
return ResultFs.InvalidGameCardHandleOnOpenNormalPartition.Log();
|
||||
}
|
||||
|
||||
var baseStorage = new ReferenceCountedDisposable<IStorage>(new ReadOnlyGameCardStorage(GameCard, handle));
|
||||
using var baseStorage = new SharedRef<IStorage>(new ReadOnlyGameCardStorage(GameCard, handle));
|
||||
|
||||
Result rc = GameCard.GetCardInfo(out GameCardInfo cardInfo, handle);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
storage = new ReferenceCountedDisposable<IStorage>(
|
||||
new SubStorage(baseStorage, 0, cardInfo.SecureAreaOffset));
|
||||
outStorage.Reset(new SubStorage(ref baseStorage.Ref(), 0, cardInfo.SecureAreaOffset));
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result CreateSecureReadOnly(GameCardHandle handle, out ReferenceCountedDisposable<IStorage> storage)
|
||||
public Result CreateSecureReadOnly(GameCardHandle handle, ref SharedRef<IStorage> outStorage)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out storage);
|
||||
|
||||
if (GameCard.IsGameCardHandleInvalid(handle))
|
||||
{
|
||||
return ResultFs.InvalidGameCardHandleOnOpenSecurePartition.Log();
|
||||
@ -50,19 +45,17 @@ namespace LibHac.FsSrv.FsCreator
|
||||
rc = GameCard.GetGameCardImageHash(imageHash);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
var baseStorage =
|
||||
new ReferenceCountedDisposable<IStorage>(new ReadOnlyGameCardStorage(GameCard, handle, deviceId,
|
||||
imageHash));
|
||||
using var baseStorage =
|
||||
new SharedRef<IStorage>(new ReadOnlyGameCardStorage(GameCard, handle, deviceId, imageHash));
|
||||
|
||||
rc = GameCard.GetCardInfo(out GameCardInfo cardInfo, handle);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
storage = new ReferenceCountedDisposable<IStorage>(new SubStorage(baseStorage, cardInfo.SecureAreaOffset,
|
||||
cardInfo.SecureAreaSize));
|
||||
outStorage.Reset(new SubStorage(ref baseStorage.Ref(), cardInfo.SecureAreaOffset, cardInfo.SecureAreaSize));
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result CreateWriteOnly(GameCardHandle handle, out ReferenceCountedDisposable<IStorage> storage)
|
||||
public Result CreateWriteOnly(GameCardHandle handle, ref SharedRef<IStorage> outStorage)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
@ -11,62 +11,50 @@ namespace LibHac.FsSrv.FsCreator
|
||||
{
|
||||
private const string DefaultPath = "/sdcard";
|
||||
|
||||
private EmulatedSdCard SdCard { get; }
|
||||
private ReferenceCountedDisposable<IFileSystem> _rootFileSystem;
|
||||
private string Path { get; }
|
||||
private EmulatedSdCard _sdCard;
|
||||
private SharedRef<IFileSystem> _rootFileSystem;
|
||||
private SharedRef<IFileSystem> _sdCardFileSystem;
|
||||
private string _path;
|
||||
|
||||
private ReferenceCountedDisposable<IFileSystem> _sdCardFileSystem;
|
||||
|
||||
public EmulatedSdCardFileSystemCreator(EmulatedSdCard sdCard, IFileSystem rootFileSystem)
|
||||
public EmulatedSdCardFileSystemCreator(EmulatedSdCard sdCard, ref SharedRef<IFileSystem> rootFileSystem)
|
||||
{
|
||||
SdCard = sdCard;
|
||||
_rootFileSystem = new ReferenceCountedDisposable<IFileSystem>(rootFileSystem);
|
||||
_sdCard = sdCard;
|
||||
_rootFileSystem = SharedRef<IFileSystem>.CreateMove(ref rootFileSystem);
|
||||
}
|
||||
|
||||
public EmulatedSdCardFileSystemCreator(EmulatedSdCard sdCard, IFileSystem rootFileSystem, string path)
|
||||
public EmulatedSdCardFileSystemCreator(EmulatedSdCard sdCard, ref SharedRef<IFileSystem> rootFileSystem, string path)
|
||||
{
|
||||
SdCard = sdCard;
|
||||
_rootFileSystem = new ReferenceCountedDisposable<IFileSystem>(rootFileSystem);
|
||||
Path = path;
|
||||
_sdCard = sdCard;
|
||||
_rootFileSystem = SharedRef<IFileSystem>.CreateMove(ref rootFileSystem);
|
||||
_path = path;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_rootFileSystem is not null)
|
||||
{
|
||||
_rootFileSystem.Dispose();
|
||||
_rootFileSystem = null;
|
||||
}
|
||||
|
||||
if (_sdCardFileSystem is not null)
|
||||
{
|
||||
_sdCardFileSystem.Dispose();
|
||||
_sdCardFileSystem = null;
|
||||
}
|
||||
_rootFileSystem.Destroy();
|
||||
_sdCardFileSystem.Destroy();
|
||||
}
|
||||
|
||||
public Result Create(out ReferenceCountedDisposable<IFileSystem> outFileSystem, bool isCaseSensitive)
|
||||
public Result Create(ref SharedRef<IFileSystem> outFileSystem, bool openCaseSensitive)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out outFileSystem);
|
||||
|
||||
if (!SdCard.IsSdCardInserted())
|
||||
if (!_sdCard.IsSdCardInserted())
|
||||
{
|
||||
return ResultFs.PortSdCardNoDevice.Log();
|
||||
}
|
||||
|
||||
if (_sdCardFileSystem is not null)
|
||||
if (_sdCardFileSystem.HasValue)
|
||||
{
|
||||
outFileSystem = _sdCardFileSystem.AddReference();
|
||||
outFileSystem.SetByCopy(ref _sdCardFileSystem);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
if (_rootFileSystem is null)
|
||||
if (!_rootFileSystem.HasValue)
|
||||
{
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
}
|
||||
|
||||
string path = Path ?? DefaultPath;
|
||||
string path = _path ?? DefaultPath;
|
||||
|
||||
using var sdCardPath = new Path();
|
||||
Result rc = sdCardPath.Initialize(StringUtils.StringToUtf8(path));
|
||||
@ -79,21 +67,13 @@ namespace LibHac.FsSrv.FsCreator
|
||||
|
||||
// Todo: Add ProxyFileSystem?
|
||||
|
||||
ReferenceCountedDisposable<IFileSystem> tempFs = null;
|
||||
try
|
||||
{
|
||||
tempFs = _rootFileSystem.AddReference();
|
||||
rc = Utility.WrapSubDirectory(out _sdCardFileSystem, ref tempFs, in sdCardPath, true);
|
||||
if (rc.IsFailure()) return rc;
|
||||
using SharedRef<IFileSystem> fileSystem = SharedRef<IFileSystem>.CreateCopy(ref _rootFileSystem);
|
||||
rc = Utility.WrapSubDirectory(ref _sdCardFileSystem, ref fileSystem.Ref(), in sdCardPath, true);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
outFileSystem = _sdCardFileSystem.AddReference();
|
||||
outFileSystem.SetByCopy(ref _sdCardFileSystem);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
tempFs?.Dispose();
|
||||
}
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result Format(bool removeFromFatFsCache)
|
||||
|
@ -16,12 +16,8 @@ namespace LibHac.FsSrv.FsCreator
|
||||
KeySet = keySet;
|
||||
}
|
||||
|
||||
public Result Create(out ReferenceCountedDisposable<IFileSystem> encryptedFileSystem,
|
||||
ref ReferenceCountedDisposable<IFileSystem> baseFileSystem, KeyId idIndex,
|
||||
in EncryptionSeed encryptionSeed)
|
||||
public Result Create(ref SharedRef<IFileSystem> outEncryptedFileSystem, ref SharedRef<IFileSystem> baseFileSystem, KeyId idIndex, in EncryptionSeed encryptionSeed)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out encryptedFileSystem);
|
||||
|
||||
if (idIndex < KeyId.Save || idIndex > KeyId.CustomStorage)
|
||||
{
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
@ -30,10 +26,10 @@ namespace LibHac.FsSrv.FsCreator
|
||||
// todo: "proper" key generation instead of a lazy hack
|
||||
KeySet.SetSdSeed(encryptionSeed.Value);
|
||||
|
||||
// Todo: pass ReferenceCountedDisposable to AesXtsFileSystem
|
||||
var fs = new AesXtsFileSystem(baseFileSystem, KeySet.SdCardEncryptionKeys[(int)idIndex].DataRo.ToArray(),
|
||||
0x4000);
|
||||
encryptedFileSystem = new ReferenceCountedDisposable<IFileSystem>(fs);
|
||||
using var encryptedFileSystem = new SharedRef<AesXtsFileSystem>(new AesXtsFileSystem(ref baseFileSystem,
|
||||
KeySet.SdCardEncryptionKeys[(int)idIndex].DataRo.ToArray(), 0x4000));
|
||||
|
||||
outEncryptedFileSystem.SetByMove(ref encryptedFileSystem.Ref());
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsSrv.FsCreator
|
||||
{
|
||||
public interface IBuiltInStorageCreator
|
||||
{
|
||||
Result Create(out ReferenceCountedDisposable<IStorage> storage, BisPartitionId partitionId);
|
||||
Result Create(ref SharedRef<IStorage> outStorage, BisPartitionId partitionId);
|
||||
Result InvalidateCache();
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSrv.FsCreator
|
||||
{
|
||||
public interface IBuiltInStorageFileSystemCreator
|
||||
{
|
||||
Result Create(out ReferenceCountedDisposable<IFileSystem> fileSystem, BisPartitionId partitionId, bool caseSensitive);
|
||||
Result Create(ref SharedRef<IFileSystem> outFileSystem, BisPartitionId partitionId, bool caseSensitive);
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSrv.FsCreator
|
||||
@ -12,15 +13,7 @@ namespace LibHac.FsSrv.FsCreator
|
||||
CustomStorage = 2
|
||||
}
|
||||
|
||||
Result Create(out ReferenceCountedDisposable<IFileSystem> encryptedFileSystem,
|
||||
ref ReferenceCountedDisposable<IFileSystem> baseFileSystem, KeyId idIndex,
|
||||
in EncryptionSeed encryptionSeed);
|
||||
}
|
||||
|
||||
public enum EncryptedFsKeyId
|
||||
{
|
||||
Save = 0,
|
||||
Content = 1,
|
||||
CustomStorage = 2
|
||||
Result Create(ref SharedRef<IFileSystem> outEncryptedFileSystem, ref SharedRef<IFileSystem> baseFileSystem,
|
||||
KeyId idIndex, in EncryptionSeed encryptionSeed);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using LibHac.Fat;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fat;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
@ -6,11 +7,10 @@ namespace LibHac.FsSrv.FsCreator
|
||||
{
|
||||
public interface IFatFileSystemCreator
|
||||
{
|
||||
Result Create(out ReferenceCountedDisposable<IFileSystem> fileSystem,
|
||||
ReferenceCountedDisposable<IStorage> baseStorage, FatAttribute attribute, int driveId,
|
||||
Result invalidFatFormatResult, Result usableSpaceNotEnoughResult);
|
||||
Result Create(ref SharedRef<IFileSystem> outFileSystem, ref SharedRef<IStorage> baseStorage,
|
||||
FatAttribute attribute, int driveId, Result invalidFatFormatResult, Result usableSpaceNotEnoughResult);
|
||||
|
||||
Result Format(ReferenceCountedDisposable<IStorage> partitionStorage, FatAttribute attribute,
|
||||
FatFormatParam formatParam, int driveId, Result invalidFatFormatResult, Result usableSpaceNotEnoughResult);
|
||||
Result Format(ref SharedRef<IStorage> partitionStorage, FatAttribute attribute, FatFormatParam formatParam,
|
||||
int driveId, Result invalidFatFormatResult, Result usableSpaceNotEnoughResult);
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSrv.FsCreator
|
||||
{
|
||||
public interface IGameCardFileSystemCreator
|
||||
{
|
||||
Result Create(out IFileSystem fileSystem, GameCardHandle handle, GameCardPartition partitionType);
|
||||
Result Create(out ReferenceCountedDisposable<IFileSystem> fileSystem, GameCardHandle handle, GameCardPartition partitionType);
|
||||
Result Create(ref SharedRef<IFileSystem> outFileSystem, GameCardHandle handle, GameCardPartition partitionType);
|
||||
}
|
||||
}
|
@ -1,11 +1,12 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsSrv.FsCreator
|
||||
{
|
||||
public interface IGameCardStorageCreator
|
||||
{
|
||||
Result CreateReadOnly(GameCardHandle handle, out ReferenceCountedDisposable<IStorage> storage);
|
||||
Result CreateSecureReadOnly(GameCardHandle handle, out ReferenceCountedDisposable<IStorage> storage);
|
||||
Result CreateWriteOnly(GameCardHandle handle, out ReferenceCountedDisposable<IStorage> storage);
|
||||
Result CreateReadOnly(GameCardHandle handle, ref SharedRef<IStorage> outStorage);
|
||||
Result CreateSecureReadOnly(GameCardHandle handle, ref SharedRef<IStorage> outStorage);
|
||||
Result CreateWriteOnly(GameCardHandle handle, ref SharedRef<IStorage> outStorage);
|
||||
}
|
||||
}
|
@ -1,12 +1,11 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSrv.FsCreator
|
||||
{
|
||||
public interface IPartitionFileSystemCreator
|
||||
{
|
||||
// Todo: Remove non-shared overload
|
||||
Result Create(out IFileSystem fileSystem, IStorage pFsStorage);
|
||||
Result Create(out ReferenceCountedDisposable<IFileSystem> fileSystem, ReferenceCountedDisposable<IStorage> pFsStorage);
|
||||
Result Create(ref SharedRef<IFileSystem> outFileSystem, ref SharedRef<IStorage> baseStorage);
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSrv.FsCreator
|
||||
{
|
||||
public interface IRomFileSystemCreator
|
||||
{
|
||||
Result Create(out ReferenceCountedDisposable<IFileSystem> fileSystem, ReferenceCountedDisposable<IStorage> romFsStorage);
|
||||
Result Create(ref SharedRef<IFileSystem> outFileSystem, ref SharedRef<IStorage> romFsStorage);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSystem;
|
||||
@ -9,15 +10,15 @@ namespace LibHac.FsSrv.FsCreator
|
||||
{
|
||||
Result CreateFile(out IFile file, IFileSystem sourceFileSystem, ulong saveDataId, OpenMode openMode);
|
||||
|
||||
Result Create(out ReferenceCountedDisposable<IFileSystem> fileSystem,
|
||||
out ReferenceCountedDisposable<ISaveDataExtraDataAccessor> extraDataAccessor,
|
||||
ISaveDataFileSystemCacheManager cacheManager, ref ReferenceCountedDisposable<IFileSystem> baseFileSystem,
|
||||
Result Create(ref SharedRef<IFileSystem> outFileSystem,
|
||||
ref SharedRef<ISaveDataExtraDataAccessor> outExtraDataAccessor,
|
||||
ISaveDataFileSystemCacheManager cacheManager, ref SharedRef<IFileSystem> baseFileSystem,
|
||||
SaveDataSpaceId spaceId, ulong saveDataId, bool allowDirectorySaveData, bool useDeviceUniqueMac,
|
||||
bool isJournalingSupported, bool isMultiCommitSupported, bool openReadOnly, bool openShared,
|
||||
ISaveDataCommitTimeStampGetter timeStampGetter);
|
||||
|
||||
Result CreateExtraDataAccessor(out ReferenceCountedDisposable<ISaveDataExtraDataAccessor> extraDataAccessor,
|
||||
ReferenceCountedDisposable<IFileSystem> sourceFileSystem);
|
||||
Result CreateExtraDataAccessor(ref SharedRef<ISaveDataExtraDataAccessor> outExtraDataAccessor,
|
||||
ref SharedRef<IFileSystem> baseFileSystem);
|
||||
|
||||
void SetSdCardEncryptionSeed(ReadOnlySpan<byte> seed);
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSrv.FsCreator
|
||||
{
|
||||
public interface ISdCardProxyFileSystemCreator
|
||||
{
|
||||
Result Create(out ReferenceCountedDisposable<IFileSystem> outFileSystem, bool isCaseSensitive);
|
||||
Result Create(ref SharedRef<IFileSystem> outFileSystem, bool openCaseSensitive);
|
||||
|
||||
/// <summary>
|
||||
/// Formats the SD card.
|
||||
|
@ -1,4 +1,5 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSystem.NcaUtils;
|
||||
|
||||
@ -6,8 +7,8 @@ namespace LibHac.FsSrv.FsCreator
|
||||
{
|
||||
public interface IStorageOnNcaCreator
|
||||
{
|
||||
Result Create(out ReferenceCountedDisposable<IStorage> storage, out NcaFsHeader fsHeader, Nca nca, int fsIndex, bool isCodeFs);
|
||||
Result CreateWithPatch(out ReferenceCountedDisposable<IStorage> storage, out NcaFsHeader fsHeader, Nca baseNca, Nca patchNca, int fsIndex, bool isCodeFs);
|
||||
Result Create(ref SharedRef<IStorage> outStorage, out NcaFsHeader fsHeader, Nca nca, int fsIndex, bool isCodeFs);
|
||||
Result CreateWithPatch(ref SharedRef<IStorage> outStorage, out NcaFsHeader fsHeader, Nca baseNca, Nca patchNca, int fsIndex, bool isCodeFs);
|
||||
Result OpenNca(out Nca nca, IStorage ncaStorage);
|
||||
Result VerifyAcidSignature(IFileSystem codeFileSystem, Nca nca);
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSrv.FsCreator
|
||||
{
|
||||
public interface ISubDirectoryFileSystemCreator
|
||||
{
|
||||
Result Create(out ReferenceCountedDisposable<IFileSystem> subDirFileSystem, ref ReferenceCountedDisposable<IFileSystem> baseFileSystem, in Path path);
|
||||
Result Create(ref SharedRef<IFileSystem> outSubDirFileSystem, ref SharedRef<IFileSystem> baseFileSystem, in Path path);
|
||||
}
|
||||
}
|
@ -1,11 +1,12 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSrv.FsCreator
|
||||
{
|
||||
public interface ITargetManagerFileSystemCreator
|
||||
{
|
||||
Result Create(out ReferenceCountedDisposable<IFileSystem> fileSystem, in Path rootPath, bool openCaseSensitive, bool ensureRootPathExists, Result pathNotFoundResult);
|
||||
Result Create(ref SharedRef<IFileSystem> outFileSystem, in Path rootPath, bool openCaseSensitive, bool ensureRootPathExists, Result pathNotFoundResult);
|
||||
Result NormalizeCaseOfPath(out bool isSupported, ref Path path);
|
||||
}
|
||||
}
|
@ -8,33 +8,15 @@ namespace LibHac.FsSrv.FsCreator
|
||||
{
|
||||
public class PartitionFileSystemCreator : IPartitionFileSystemCreator
|
||||
{
|
||||
public Result Create(out IFileSystem fileSystem, IStorage pFsStorage)
|
||||
public Result Create(ref SharedRef<IFileSystem> outFileSystem, ref SharedRef<IStorage> baseStorage)
|
||||
{
|
||||
var partitionFs = new PartitionFileSystemCore<StandardEntry>();
|
||||
using var partitionFs =
|
||||
new SharedRef<PartitionFileSystemCore<StandardEntry>>(new PartitionFileSystemCore<StandardEntry>());
|
||||
|
||||
Result rc = partitionFs.Initialize(pFsStorage);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
return rc;
|
||||
}
|
||||
Result rc = partitionFs.Get.Initialize(ref baseStorage);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
fileSystem = partitionFs;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result Create(out ReferenceCountedDisposable<IFileSystem> fileSystem, ReferenceCountedDisposable<IStorage> pFsStorage)
|
||||
{
|
||||
var partitionFs = new PartitionFileSystemCore<StandardEntry>();
|
||||
|
||||
Result rc = partitionFs.Initialize(pFsStorage);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem);
|
||||
return rc;
|
||||
}
|
||||
|
||||
fileSystem = new ReferenceCountedDisposable<IFileSystem>(partitionFs);
|
||||
outFileSystem.SetByMove(ref partitionFs.Ref());
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSystem.RomFs;
|
||||
|
||||
@ -7,10 +8,9 @@ namespace LibHac.FsSrv.FsCreator
|
||||
public class RomFileSystemCreator : IRomFileSystemCreator
|
||||
{
|
||||
// todo: Implement properly
|
||||
public Result Create(out ReferenceCountedDisposable<IFileSystem> fileSystem, ReferenceCountedDisposable<IStorage> romFsStorage)
|
||||
public Result Create(ref SharedRef<IFileSystem> outFileSystem, ref SharedRef<IStorage> romFsStorage)
|
||||
{
|
||||
// Todo: Properly use shared references
|
||||
fileSystem = new ReferenceCountedDisposable<IFileSystem>(new RomFsFileSystem(romFsStorage.AddReference().Target));
|
||||
outFileSystem.Reset(new RomFsFileSystem(ref romFsStorage));
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
@ -36,9 +36,9 @@ namespace LibHac.FsSrv.FsCreator
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result Create(out ReferenceCountedDisposable<IFileSystem> fileSystem,
|
||||
out ReferenceCountedDisposable<ISaveDataExtraDataAccessor> extraDataAccessor,
|
||||
ISaveDataFileSystemCacheManager cacheManager, ref ReferenceCountedDisposable<IFileSystem> baseFileSystem,
|
||||
public Result Create(ref SharedRef<IFileSystem> outFileSystem,
|
||||
ref SharedRef<ISaveDataExtraDataAccessor> outExtraDataAccessor,
|
||||
ISaveDataFileSystemCacheManager cacheManager, ref SharedRef<IFileSystem> baseFileSystem,
|
||||
SaveDataSpaceId spaceId, ulong saveDataId, bool allowDirectorySaveData, bool useDeviceUniqueMac,
|
||||
bool isJournalingSupported, bool isMultiCommitSupported, bool openReadOnly, bool openShared,
|
||||
ISaveDataCommitTimeStampGetter timeStampGetter)
|
||||
@ -48,15 +48,13 @@ namespace LibHac.FsSrv.FsCreator
|
||||
ref byte bufferRef = ref MemoryMarshal.GetReference(buffer);
|
||||
Span<byte> saveImageNameBuffer = MemoryMarshal.CreateSpan(ref bufferRef, 0x12);
|
||||
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem, out extraDataAccessor);
|
||||
|
||||
Assert.SdkRequiresNotNull(cacheManager);
|
||||
|
||||
using var saveImageName = new Path();
|
||||
Result rc = PathFunctions.SetUpFixedPathSaveId(ref saveImageName.Ref(), saveImageNameBuffer, saveDataId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = baseFileSystem.Target.GetEntryType(out DirectoryEntryType type, in saveImageName);
|
||||
rc = baseFileSystem.Get.GetEntryType(out DirectoryEntryType type, in saveImageName);
|
||||
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
@ -68,40 +66,36 @@ namespace LibHac.FsSrv.FsCreator
|
||||
if (!allowDirectorySaveData)
|
||||
return ResultFs.InvalidSaveDataEntryType.Log();
|
||||
|
||||
SubdirectoryFileSystem subDirFs = null;
|
||||
ReferenceCountedDisposable<DirectorySaveDataFileSystem> saveFs = null;
|
||||
try
|
||||
{
|
||||
subDirFs = new SubdirectoryFileSystem(ref baseFileSystem);
|
||||
using var baseFs =
|
||||
new UniqueRef<SubdirectoryFileSystem>(new SubdirectoryFileSystem(ref baseFileSystem));
|
||||
|
||||
rc = subDirFs.Initialize(in saveImageName);
|
||||
if (rc.IsFailure()) return rc;
|
||||
if (!baseFs.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInSaveDataFileSystemCreatorA.Log();
|
||||
|
||||
saveFs = DirectorySaveDataFileSystem.CreateShared(Shared.Move(ref subDirFs), _fsServer.Hos.Fs);
|
||||
rc = baseFs.Get.Initialize(in saveImageName);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = saveFs.Target.Initialize(timeStampGetter, _randomGenerator, isJournalingSupported,
|
||||
isMultiCommitSupported, !openReadOnly);
|
||||
if (rc.IsFailure()) return rc;
|
||||
using UniqueRef<IFileSystem> tempFs = UniqueRef<IFileSystem>.Create(ref baseFs.Ref());
|
||||
using var saveDirFs = new SharedRef<DirectorySaveDataFileSystem>(
|
||||
new DirectorySaveDataFileSystem(ref tempFs.Ref(), _fsServer.Hos.Fs));
|
||||
|
||||
fileSystem = saveFs.AddReference<IFileSystem>();
|
||||
extraDataAccessor = saveFs.AddReference<ISaveDataExtraDataAccessor>();
|
||||
rc = saveDirFs.Get.Initialize(timeStampGetter, _randomGenerator, isJournalingSupported,
|
||||
isMultiCommitSupported, !openReadOnly);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
subDirFs?.Dispose();
|
||||
saveFs?.Dispose();
|
||||
}
|
||||
outFileSystem.SetByCopy(ref saveDirFs.Ref());
|
||||
outExtraDataAccessor.SetByCopy(ref saveDirFs.Ref());
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
ReferenceCountedDisposable<IStorage> fileStorage = null;
|
||||
try
|
||||
else
|
||||
{
|
||||
using var fileStorage = new SharedRef<IStorage>();
|
||||
|
||||
Optional<OpenType> openType =
|
||||
openShared ? new Optional<OpenType>(OpenType.Normal) : new Optional<OpenType>();
|
||||
|
||||
rc = _fsServer.OpenSaveDataStorage(out fileStorage, ref baseFileSystem, spaceId, saveDataId,
|
||||
rc = _fsServer.OpenSaveDataStorage(ref fileStorage.Ref(), ref baseFileSystem, spaceId, saveDataId,
|
||||
OpenMode.ReadWrite, openType);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
@ -110,23 +104,17 @@ namespace LibHac.FsSrv.FsCreator
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
// Todo: Properly handle shared storage
|
||||
fileSystem = new ReferenceCountedDisposable<IFileSystem>(new SaveDataFileSystem(_keySet,
|
||||
fileStorage.Target, IntegrityCheckLevel.ErrorOnInvalid, false));
|
||||
using var saveFs = new SharedRef<SaveDataFileSystem>(new SaveDataFileSystem(_keySet, fileStorage.Get,
|
||||
IntegrityCheckLevel.ErrorOnInvalid, false));
|
||||
|
||||
// Todo: ISaveDataExtraDataAccessor
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileStorage?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public Result CreateExtraDataAccessor(
|
||||
out ReferenceCountedDisposable<ISaveDataExtraDataAccessor> extraDataAccessor,
|
||||
ReferenceCountedDisposable<IFileSystem> sourceFileSystem)
|
||||
public Result CreateExtraDataAccessor(ref SharedRef<ISaveDataExtraDataAccessor> outExtraDataAccessor,
|
||||
ref SharedRef<IFileSystem> baseFileSystem)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
@ -21,10 +21,10 @@ namespace LibHac.FsSrv.FsCreator
|
||||
}
|
||||
|
||||
// todo: Implement NcaReader and other Nca classes
|
||||
public Result Create(out ReferenceCountedDisposable<IStorage> storage, out NcaFsHeader fsHeader, Nca nca,
|
||||
public Result Create(ref SharedRef<IStorage> outStorage, out NcaFsHeader fsHeader, Nca nca,
|
||||
int fsIndex, bool isCodeFs)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out storage, out fsHeader);
|
||||
UnsafeHelpers.SkipParamInit(out fsHeader);
|
||||
|
||||
Result rc = OpenStorage(out IStorage storageTemp, nca, fsIndex);
|
||||
if (rc.IsFailure()) return rc;
|
||||
@ -41,13 +41,13 @@ namespace LibHac.FsSrv.FsCreator
|
||||
}
|
||||
}
|
||||
|
||||
storage = new ReferenceCountedDisposable<IStorage>(storageTemp);
|
||||
outStorage.Reset(storageTemp);
|
||||
fsHeader = nca.GetFsHeader(fsIndex);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result CreateWithPatch(out ReferenceCountedDisposable<IStorage> storage, out NcaFsHeader fsHeader,
|
||||
public Result CreateWithPatch(ref SharedRef<IStorage> outStorage, out NcaFsHeader fsHeader,
|
||||
Nca baseNca, Nca patchNca, int fsIndex, bool isCodeFs)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
@ -7,34 +7,26 @@ namespace LibHac.FsSrv.FsCreator
|
||||
{
|
||||
public class SubDirectoryFileSystemCreator : ISubDirectoryFileSystemCreator
|
||||
{
|
||||
public Result Create(out ReferenceCountedDisposable<IFileSystem> subDirFileSystem,
|
||||
ref ReferenceCountedDisposable<IFileSystem> baseFileSystem, in Path path)
|
||||
public Result Create(ref SharedRef<IFileSystem> outSubDirFileSystem, ref SharedRef<IFileSystem> baseFileSystem,
|
||||
in Path path)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out subDirFileSystem);
|
||||
|
||||
using var directory = new UniqueRef<IDirectory>();
|
||||
|
||||
Result rc = baseFileSystem.Target.OpenDirectory(ref directory.Ref(), in path, OpenDirectoryMode.Directory);
|
||||
Result rc = baseFileSystem.Get.OpenDirectory(ref directory.Ref(), in path, OpenDirectoryMode.Directory);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
directory.Reset();
|
||||
|
||||
ReferenceCountedDisposable<SubdirectoryFileSystem> subFs = null;
|
||||
try
|
||||
{
|
||||
subFs = new ReferenceCountedDisposable<SubdirectoryFileSystem>(
|
||||
new SubdirectoryFileSystem(ref baseFileSystem));
|
||||
using var subFs = new SharedRef<SubdirectoryFileSystem>(new SubdirectoryFileSystem(ref baseFileSystem));
|
||||
|
||||
rc = subFs.Target.Initialize(in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
if (!subFs.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInSubDirectoryFileSystemCreatorA.Log();
|
||||
|
||||
subDirFileSystem = subFs.AddReference<IFileSystem>();
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
subFs?.Dispose();
|
||||
}
|
||||
rc = subFs.Get.Initialize(in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
outSubDirFileSystem.SetByMove(ref subFs.Ref());
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
@ -6,7 +7,8 @@ namespace LibHac.FsSrv.FsCreator
|
||||
{
|
||||
public class TargetManagerFileSystemCreator : ITargetManagerFileSystemCreator
|
||||
{
|
||||
public Result Create(out ReferenceCountedDisposable<IFileSystem> fileSystem, in Path rootPath, bool openCaseSensitive, bool ensureRootPathExists, Result pathNotFoundResult)
|
||||
public Result Create(ref SharedRef<IFileSystem> outFileSystem, in Path rootPath, bool openCaseSensitive,
|
||||
bool ensureRootPathExists, Result pathNotFoundResult)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsSrv
|
||||
@ -141,8 +142,8 @@ namespace LibHac.FsSrv
|
||||
/// <summary>
|
||||
/// Returns an <see cref="SaveDataInfoReaderImpl"/> that iterates through the <see cref="SaveDataIndexer"/>.
|
||||
/// </summary>
|
||||
/// <param name="infoReader">If the method returns successfully, contains the created <see cref="SaveDataInfoReaderImpl"/>.</param>
|
||||
/// <param name="outInfoReader">If the method returns successfully, contains the created <see cref="SaveDataInfoReaderImpl"/>.</param>
|
||||
/// <returns>The <see cref="Result"/> of the operation.</returns>
|
||||
Result OpenSaveDataInfoReader(out ReferenceCountedDisposable<SaveDataInfoReaderImpl> infoReader);
|
||||
Result OpenSaveDataInfoReader(ref SharedRef<SaveDataInfoReaderImpl> outInfoReader);
|
||||
}
|
||||
}
|
@ -7,16 +7,10 @@ namespace LibHac.FsSrv.Impl
|
||||
{
|
||||
public class AsynchronousAccessFileSystem : ForwardingFileSystem
|
||||
{
|
||||
protected AsynchronousAccessFileSystem(ref ReferenceCountedDisposable<IFileSystem> baseFileSystem) : base(
|
||||
public AsynchronousAccessFileSystem(ref SharedRef<IFileSystem> baseFileSystem) : base(
|
||||
ref baseFileSystem)
|
||||
{ }
|
||||
|
||||
public static ReferenceCountedDisposable<IFileSystem> CreateShared(
|
||||
ref ReferenceCountedDisposable<IFileSystem> fileSystem)
|
||||
{
|
||||
return new ReferenceCountedDisposable<IFileSystem>(new AsynchronousAccessFileSystem(ref fileSystem));
|
||||
}
|
||||
|
||||
// ReSharper disable once RedundantOverriddenMember
|
||||
protected override Result DoOpenFile(ref UniqueRef<IFile> outFile, in Path path, OpenMode mode)
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.Sf;
|
||||
|
||||
@ -20,9 +21,9 @@ namespace LibHac.FsSrv.Impl
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static Result CreateWiper(out IWiper wiper, NativeHandle memoryHandle, ulong memorySize)
|
||||
public static Result CreateWiper(ref UniqueRef<IWiper> outWiper, NativeHandle memoryHandle, ulong memorySize)
|
||||
{
|
||||
wiper = new BisWiper(memoryHandle, memorySize);
|
||||
outWiper.Reset(new BisWiper(memoryHandle, memorySize));
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
|
@ -7,41 +7,30 @@ namespace LibHac.FsSrv.Impl
|
||||
{
|
||||
public class DeepRetryFileSystem : ForwardingFileSystem
|
||||
{
|
||||
// ReSharper disable once UnusedAutoPropertyAccessor.Local
|
||||
private ReferenceCountedDisposable<DeepRetryFileSystem>.WeakReference SelfReference { get; set; }
|
||||
private ReferenceCountedDisposable<IRomFileSystemAccessFailureManager> AccessFailureManager { get; set; }
|
||||
// ReSharper disable once NotAccessedField.Local
|
||||
private WeakRef<DeepRetryFileSystem> _selfReference;
|
||||
private SharedRef<IRomFileSystemAccessFailureManager> _accessFailureManager;
|
||||
|
||||
protected DeepRetryFileSystem(ref ReferenceCountedDisposable<IFileSystem> baseFileSystem,
|
||||
ref ReferenceCountedDisposable<IRomFileSystemAccessFailureManager> accessFailureManager) : base(
|
||||
ref baseFileSystem)
|
||||
protected DeepRetryFileSystem(ref SharedRef<IFileSystem> baseFileSystem,
|
||||
ref SharedRef<IRomFileSystemAccessFailureManager> accessFailureManager) : base(ref baseFileSystem)
|
||||
{
|
||||
AccessFailureManager = Shared.Move(ref accessFailureManager);
|
||||
_accessFailureManager = Shared.Move(ref accessFailureManager);
|
||||
}
|
||||
|
||||
public static ReferenceCountedDisposable<IFileSystem> CreateShared(
|
||||
ref ReferenceCountedDisposable<IFileSystem> fileSystem,
|
||||
ref ReferenceCountedDisposable<IRomFileSystemAccessFailureManager> accessFailureManager)
|
||||
public static SharedRef<IFileSystem> CreateShared(ref SharedRef<IFileSystem> baseFileSystem,
|
||||
ref SharedRef<IRomFileSystemAccessFailureManager> accessFailureManager)
|
||||
{
|
||||
ReferenceCountedDisposable<DeepRetryFileSystem> sharedRetryFileSystem = null;
|
||||
try
|
||||
{
|
||||
var retryFileSystem = new DeepRetryFileSystem(ref fileSystem, ref accessFailureManager);
|
||||
sharedRetryFileSystem = new ReferenceCountedDisposable<DeepRetryFileSystem>(retryFileSystem);
|
||||
using var retryFileSystem = new SharedRef<DeepRetryFileSystem>(
|
||||
new DeepRetryFileSystem(ref baseFileSystem, ref accessFailureManager));
|
||||
|
||||
retryFileSystem.SelfReference =
|
||||
new ReferenceCountedDisposable<DeepRetryFileSystem>.WeakReference(sharedRetryFileSystem);
|
||||
retryFileSystem.Get._selfReference = new WeakRef<DeepRetryFileSystem>(ref retryFileSystem.Ref());
|
||||
|
||||
return sharedRetryFileSystem.AddReference<IFileSystem>();
|
||||
}
|
||||
finally
|
||||
{
|
||||
sharedRetryFileSystem?.Dispose();
|
||||
}
|
||||
return SharedRef<IFileSystem>.CreateMove(ref retryFileSystem.Ref());
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
AccessFailureManager?.Dispose();
|
||||
_accessFailureManager.Destroy();
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
|
@ -4,23 +4,25 @@ using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsSrv.Impl
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="IStorage"/> for simulating device failures
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
internal class DeviceEventSimulationStorage : IStorage
|
||||
{
|
||||
private ReferenceCountedDisposable<IStorage> _baseStorage;
|
||||
private SharedRef<IStorage> _baseStorage;
|
||||
private IDeviceEventSimulator _eventSimulator;
|
||||
|
||||
private DeviceEventSimulationStorage(ref ReferenceCountedDisposable<IStorage> baseStorage,
|
||||
IDeviceEventSimulator eventSimulator)
|
||||
public DeviceEventSimulationStorage(ref SharedRef<IStorage> baseStorage, IDeviceEventSimulator eventSimulator)
|
||||
{
|
||||
_baseStorage = Shared.Move(ref baseStorage);
|
||||
_baseStorage = SharedRef<IStorage>.CreateMove(ref baseStorage);
|
||||
_eventSimulator = eventSimulator;
|
||||
}
|
||||
|
||||
public static ReferenceCountedDisposable<IStorage> CreateShared(
|
||||
ref ReferenceCountedDisposable<IStorage> baseStorage, IDeviceEventSimulator eventSimulator)
|
||||
public override void Dispose()
|
||||
{
|
||||
var storage = new DeviceEventSimulationStorage(ref baseStorage, eventSimulator);
|
||||
return new ReferenceCountedDisposable<IStorage>(storage);
|
||||
_baseStorage.Destroy();
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
protected override Result DoRead(long offset, Span<byte> destination)
|
||||
@ -28,7 +30,7 @@ namespace LibHac.FsSrv.Impl
|
||||
Result rc = _eventSimulator.CheckSimulatedAccessFailureEvent(SimulatingDeviceTargetOperation.Read);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return _baseStorage.Target.Read(offset, destination);
|
||||
return _baseStorage.Get.Read(offset, destination);
|
||||
}
|
||||
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
@ -36,28 +38,28 @@ namespace LibHac.FsSrv.Impl
|
||||
Result rc = _eventSimulator.CheckSimulatedAccessFailureEvent(SimulatingDeviceTargetOperation.Write);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return _baseStorage.Target.Write(offset, source);
|
||||
return _baseStorage.Get.Write(offset, source);
|
||||
}
|
||||
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return _baseStorage.Target.Flush();
|
||||
return _baseStorage.Get.Flush();
|
||||
}
|
||||
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
return _baseStorage.Target.SetSize(size);
|
||||
return _baseStorage.Get.SetSize(size);
|
||||
}
|
||||
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
return _baseStorage.Target.GetSize(out size);
|
||||
return _baseStorage.Get.GetSize(out size);
|
||||
}
|
||||
|
||||
protected override Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size,
|
||||
ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
return _baseStorage.Target.OperateRange(outBuffer, operationId, offset, size, inBuffer);
|
||||
return _baseStorage.Get.OperateRange(outBuffer, operationId, offset, size, inBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,25 +20,25 @@ namespace LibHac.FsSrv.Impl
|
||||
/// <summary>
|
||||
/// Wraps an <see cref="IFile"/> to allow interfacing with it via the <see cref="IFileSf"/> interface over IPC.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.0.3 (nnSdk 12.3.1)</remarks>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
public class FileInterfaceAdapter : IFileSf
|
||||
{
|
||||
private ReferenceCountedDisposable<FileSystemInterfaceAdapter> _parentFs;
|
||||
private SharedRef<FileSystemInterfaceAdapter> _parentFs;
|
||||
private UniqueRef<IFile> _baseFile;
|
||||
private bool _allowAllOperations;
|
||||
|
||||
public FileInterfaceAdapter(ref UniqueRef<IFile> baseFile,
|
||||
ref ReferenceCountedDisposable<FileSystemInterfaceAdapter> parentFileSystem, bool allowAllOperations)
|
||||
ref SharedRef<FileSystemInterfaceAdapter> parentFileSystem, bool allowAllOperations)
|
||||
{
|
||||
_parentFs = SharedRef<FileSystemInterfaceAdapter>.CreateMove(ref parentFileSystem);
|
||||
_baseFile = new UniqueRef<IFile>(ref baseFile);
|
||||
_parentFs = Shared.Move(ref parentFileSystem);
|
||||
_allowAllOperations = allowAllOperations;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_baseFile.Destroy();
|
||||
_parentFs?.Dispose();
|
||||
_parentFs.Destroy();
|
||||
}
|
||||
|
||||
public Result Read(out long bytesRead, long offset, OutBuffer destination, long size, ReadOption option)
|
||||
@ -175,23 +175,23 @@ namespace LibHac.FsSrv.Impl
|
||||
/// <summary>
|
||||
/// Wraps an <see cref="IDirectory"/> to allow interfacing with it via the <see cref="IDirectorySf"/> interface over IPC.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.0.3 (nnSdk 12.3.1)</remarks>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
public class DirectoryInterfaceAdapter : IDirectorySf
|
||||
{
|
||||
private ReferenceCountedDisposable<FileSystemInterfaceAdapter> _parentFs;
|
||||
private SharedRef<FileSystemInterfaceAdapter> _parentFs;
|
||||
private UniqueRef<IDirectory> _baseDirectory;
|
||||
|
||||
public DirectoryInterfaceAdapter(ref UniqueRef<IDirectory> baseDirectory,
|
||||
ref ReferenceCountedDisposable<FileSystemInterfaceAdapter> parentFileSystem)
|
||||
ref SharedRef<FileSystemInterfaceAdapter> parentFileSystem)
|
||||
{
|
||||
_parentFs = SharedRef<FileSystemInterfaceAdapter>.CreateMove(ref parentFileSystem);
|
||||
_baseDirectory = new UniqueRef<IDirectory>(ref baseDirectory);
|
||||
_parentFs = Shared.Move(ref parentFileSystem);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_baseDirectory.Destroy();
|
||||
_parentFs?.Dispose();
|
||||
_parentFs.Destroy();
|
||||
}
|
||||
|
||||
public Result Read(out long entriesRead, OutBuffer entryBuffer)
|
||||
@ -235,10 +235,10 @@ namespace LibHac.FsSrv.Impl
|
||||
/// Wraps an <see cref="IFileSystem"/> to allow interfacing with it via the <see cref="IFileSystemSf"/> interface over IPC.
|
||||
/// All incoming paths are normalized before they are passed to the base <see cref="IFileSystem"/>.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.0.3 (nnSdk 12.3.1)</remarks>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
public class FileSystemInterfaceAdapter : IFileSystemSf
|
||||
{
|
||||
private ReferenceCountedDisposable<IFileSystem> _baseFileSystem;
|
||||
private SharedRef<IFileSystem> _baseFileSystem;
|
||||
private PathFlags _pathFlags;
|
||||
|
||||
// This field is always false in FS 12.0.0. Not sure what it's actually used for.
|
||||
@ -246,67 +246,47 @@ namespace LibHac.FsSrv.Impl
|
||||
|
||||
// In FS, FileSystemInterfaceAdapter is derived from ISharedObject, so that's used for ref-counting when
|
||||
// creating files and directories. We don't have an ISharedObject, so a self-reference is used instead.
|
||||
private ReferenceCountedDisposable<FileSystemInterfaceAdapter>.WeakReference _selfReference;
|
||||
private WeakRef<FileSystemInterfaceAdapter> _selfReference;
|
||||
|
||||
private FileSystemInterfaceAdapter(ref ReferenceCountedDisposable<IFileSystem> fileSystem,
|
||||
private FileSystemInterfaceAdapter(ref SharedRef<IFileSystem> fileSystem,
|
||||
bool allowAllOperations)
|
||||
{
|
||||
_baseFileSystem = Shared.Move(ref fileSystem);
|
||||
_baseFileSystem = SharedRef<IFileSystem>.CreateMove(ref fileSystem);
|
||||
_allowAllOperations = allowAllOperations;
|
||||
}
|
||||
|
||||
private FileSystemInterfaceAdapter(ref ReferenceCountedDisposable<IFileSystem> fileSystem, PathFlags flags,
|
||||
private FileSystemInterfaceAdapter(ref SharedRef<IFileSystem> fileSystem, PathFlags flags,
|
||||
bool allowAllOperations)
|
||||
{
|
||||
_baseFileSystem = Shared.Move(ref fileSystem);
|
||||
_baseFileSystem = SharedRef<IFileSystem>.CreateMove(ref fileSystem);
|
||||
_pathFlags = flags;
|
||||
_allowAllOperations = allowAllOperations;
|
||||
}
|
||||
|
||||
public static ReferenceCountedDisposable<IFileSystemSf> CreateShared(
|
||||
ref ReferenceCountedDisposable<IFileSystem> baseFileSystem, bool allowAllOperations)
|
||||
public static SharedRef<IFileSystemSf> CreateShared(ref SharedRef<IFileSystem> baseFileSystem, bool allowAllOperations)
|
||||
{
|
||||
ReferenceCountedDisposable<FileSystemInterfaceAdapter> sharedAdapter = null;
|
||||
try
|
||||
{
|
||||
var adapter = new FileSystemInterfaceAdapter(ref baseFileSystem, allowAllOperations);
|
||||
sharedAdapter = new ReferenceCountedDisposable<FileSystemInterfaceAdapter>(adapter);
|
||||
var adapter = new FileSystemInterfaceAdapter(ref baseFileSystem, allowAllOperations);
|
||||
using var sharedAdapter = new SharedRef<FileSystemInterfaceAdapter>(adapter);
|
||||
|
||||
adapter._selfReference =
|
||||
new ReferenceCountedDisposable<FileSystemInterfaceAdapter>.WeakReference(sharedAdapter);
|
||||
adapter._selfReference = new WeakRef<FileSystemInterfaceAdapter>(ref sharedAdapter.Ref());
|
||||
|
||||
return sharedAdapter.AddReference<IFileSystemSf>();
|
||||
}
|
||||
finally
|
||||
{
|
||||
sharedAdapter?.Dispose();
|
||||
}
|
||||
return SharedRef<IFileSystemSf>.CreateMove(ref sharedAdapter.Ref());
|
||||
}
|
||||
|
||||
public static ReferenceCountedDisposable<IFileSystemSf> CreateShared(
|
||||
ref ReferenceCountedDisposable<IFileSystem> baseFileSystem, PathFlags flags, bool allowAllOperations)
|
||||
public static SharedRef<IFileSystemSf> CreateShared(
|
||||
ref SharedRef<IFileSystem> baseFileSystem, PathFlags flags, bool allowAllOperations)
|
||||
{
|
||||
ReferenceCountedDisposable<FileSystemInterfaceAdapter> sharedAdapter = null;
|
||||
try
|
||||
{
|
||||
var adapter = new FileSystemInterfaceAdapter(ref baseFileSystem, flags, allowAllOperations);
|
||||
sharedAdapter = new ReferenceCountedDisposable<FileSystemInterfaceAdapter>(adapter);
|
||||
var adapter = new FileSystemInterfaceAdapter(ref baseFileSystem, flags, allowAllOperations);
|
||||
using var sharedAdapter = new SharedRef<FileSystemInterfaceAdapter>(adapter);
|
||||
|
||||
adapter._selfReference =
|
||||
new ReferenceCountedDisposable<FileSystemInterfaceAdapter>.WeakReference(sharedAdapter);
|
||||
adapter._selfReference = new WeakRef<FileSystemInterfaceAdapter>(ref sharedAdapter.Ref());
|
||||
|
||||
return sharedAdapter.AddReference<IFileSystemSf>();
|
||||
}
|
||||
finally
|
||||
{
|
||||
sharedAdapter?.Dispose();
|
||||
}
|
||||
return SharedRef<IFileSystemSf>.CreateMove(ref sharedAdapter.Ref());
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ReferenceCountedDisposable<IFileSystem> tempFs = Shared.Move(ref _baseFileSystem);
|
||||
tempFs?.Dispose();
|
||||
_baseFileSystem.Destroy();
|
||||
}
|
||||
|
||||
private static ReadOnlySpan<byte> RootDir => new[] { (byte)'/' };
|
||||
@ -341,7 +321,7 @@ namespace LibHac.FsSrv.Impl
|
||||
Result rc = SetUpPath(ref pathNormalized.Ref(), in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = _baseFileSystem.Target.CreateFile(in pathNormalized, size, (CreateFileOptions)option);
|
||||
rc = _baseFileSystem.Get.CreateFile(in pathNormalized, size, (CreateFileOptions)option);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
@ -353,7 +333,7 @@ namespace LibHac.FsSrv.Impl
|
||||
Result rc = SetUpPath(ref pathNormalized.Ref(), in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = _baseFileSystem.Target.DeleteFile(in pathNormalized);
|
||||
rc = _baseFileSystem.Get.DeleteFile(in pathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
@ -368,7 +348,7 @@ namespace LibHac.FsSrv.Impl
|
||||
if (pathNormalized == RootDir)
|
||||
return ResultFs.PathAlreadyExists.Log();
|
||||
|
||||
rc = _baseFileSystem.Target.CreateDirectory(in pathNormalized);
|
||||
rc = _baseFileSystem.Get.CreateDirectory(in pathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
@ -383,7 +363,7 @@ namespace LibHac.FsSrv.Impl
|
||||
if (pathNormalized == RootDir)
|
||||
return ResultFs.DirectoryNotDeletable.Log();
|
||||
|
||||
rc = _baseFileSystem.Target.DeleteDirectory(in pathNormalized);
|
||||
rc = _baseFileSystem.Get.DeleteDirectory(in pathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
@ -398,7 +378,7 @@ namespace LibHac.FsSrv.Impl
|
||||
if (pathNormalized == RootDir)
|
||||
return ResultFs.DirectoryNotDeletable.Log();
|
||||
|
||||
rc = _baseFileSystem.Target.DeleteDirectoryRecursively(in pathNormalized);
|
||||
rc = _baseFileSystem.Get.DeleteDirectoryRecursively(in pathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
@ -410,7 +390,7 @@ namespace LibHac.FsSrv.Impl
|
||||
Result rc = SetUpPath(ref pathNormalized.Ref(), in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = _baseFileSystem.Target.CleanDirectoryRecursively(in pathNormalized);
|
||||
rc = _baseFileSystem.Get.CleanDirectoryRecursively(in pathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
@ -426,7 +406,7 @@ namespace LibHac.FsSrv.Impl
|
||||
rc = SetUpPath(ref newPathNormalized.Ref(), in newPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = _baseFileSystem.Target.RenameFile(in currentPathNormalized, in newPathNormalized);
|
||||
rc = _baseFileSystem.Get.RenameFile(in currentPathNormalized, in newPathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
@ -445,7 +425,7 @@ namespace LibHac.FsSrv.Impl
|
||||
if (PathUtility.IsSubPath(currentPathNormalized.GetString(), newPathNormalized.GetString()))
|
||||
return ResultFs.DirectoryNotRenamable.Log();
|
||||
|
||||
rc = _baseFileSystem.Target.RenameDirectory(in currentPathNormalized, in newPathNormalized);
|
||||
rc = _baseFileSystem.Get.RenameDirectory(in currentPathNormalized, in newPathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
@ -459,7 +439,7 @@ namespace LibHac.FsSrv.Impl
|
||||
Result rc = SetUpPath(ref pathNormalized.Ref(), in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = _baseFileSystem.Target.GetEntryType(out DirectoryEntryType type, in pathNormalized);
|
||||
rc = _baseFileSystem.Get.GetEntryType(out DirectoryEntryType type, in pathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
entryType = (uint)type;
|
||||
@ -474,7 +454,7 @@ namespace LibHac.FsSrv.Impl
|
||||
Result rc = SetUpPath(ref pathNormalized.Ref(), in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = _baseFileSystem.Target.GetFreeSpaceSize(out long space, in pathNormalized);
|
||||
rc = _baseFileSystem.Get.GetFreeSpaceSize(out long space, in pathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
freeSpace = space;
|
||||
@ -489,17 +469,16 @@ namespace LibHac.FsSrv.Impl
|
||||
Result rc = SetUpPath(ref pathNormalized.Ref(), in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = _baseFileSystem.Target.GetTotalSpaceSize(out long space, in pathNormalized);
|
||||
rc = _baseFileSystem.Get.GetTotalSpaceSize(out long space, in pathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
totalSpace = space;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenFile(out ReferenceCountedDisposable<IFileSf> outFile, in PathSf path, uint mode)
|
||||
public Result OpenFile(ref SharedRef<IFileSf> outFile, in PathSf path, uint mode)
|
||||
{
|
||||
const int maxTryCount = 2;
|
||||
UnsafeHelpers.SkipParamInit(out outFile);
|
||||
|
||||
using var pathNormalized = new Path();
|
||||
Result rc = SetUpPath(ref pathNormalized.Ref(), in path);
|
||||
@ -509,7 +488,7 @@ namespace LibHac.FsSrv.Impl
|
||||
|
||||
for (int tryNum = 0; tryNum < maxTryCount; tryNum++)
|
||||
{
|
||||
rc = _baseFileSystem.Target.OpenFile(ref file.Ref(), in pathNormalized, (OpenMode)mode);
|
||||
rc = _baseFileSystem.Get.OpenFile(ref file.Ref(), in pathNormalized, (OpenMode)mode);
|
||||
|
||||
// Retry on ResultDataCorrupted
|
||||
if (!ResultFs.DataCorrupted.Includes(rc))
|
||||
@ -518,17 +497,18 @@ namespace LibHac.FsSrv.Impl
|
||||
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
ReferenceCountedDisposable<FileSystemInterfaceAdapter> selfReference = _selfReference.AddReference();
|
||||
var adapter = new FileInterfaceAdapter(ref file.Ref(), ref selfReference, _allowAllOperations);
|
||||
outFile = new ReferenceCountedDisposable<IFileSf>(adapter);
|
||||
using SharedRef<FileSystemInterfaceAdapter> selfReference =
|
||||
SharedRef<FileSystemInterfaceAdapter>.Create(ref _selfReference);
|
||||
|
||||
var adapter = new FileInterfaceAdapter(ref file.Ref(), ref selfReference.Ref(), _allowAllOperations);
|
||||
outFile.Reset(adapter);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenDirectory(out ReferenceCountedDisposable<IDirectorySf> outDirectory, in PathSf path, uint mode)
|
||||
public Result OpenDirectory(ref SharedRef<IDirectorySf> outDirectory, in PathSf path, uint mode)
|
||||
{
|
||||
const int maxTryCount = 2;
|
||||
UnsafeHelpers.SkipParamInit(out outDirectory);
|
||||
|
||||
using var pathNormalized = new Path();
|
||||
Result rc = SetUpPath(ref pathNormalized.Ref(), in path);
|
||||
@ -538,7 +518,7 @@ namespace LibHac.FsSrv.Impl
|
||||
|
||||
for (int tryNum = 0; tryNum < maxTryCount; tryNum++)
|
||||
{
|
||||
rc = _baseFileSystem.Target.OpenDirectory(ref directory.Ref(), in pathNormalized,
|
||||
rc = _baseFileSystem.Get.OpenDirectory(ref directory.Ref(), in pathNormalized,
|
||||
(OpenDirectoryMode)mode);
|
||||
|
||||
// Retry on ResultDataCorrupted
|
||||
@ -548,16 +528,18 @@ namespace LibHac.FsSrv.Impl
|
||||
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
ReferenceCountedDisposable<FileSystemInterfaceAdapter> selfReference = _selfReference.AddReference();
|
||||
var adapter = new DirectoryInterfaceAdapter(ref directory.Ref(), ref selfReference);
|
||||
outDirectory = new ReferenceCountedDisposable<IDirectorySf>(adapter);
|
||||
using SharedRef<FileSystemInterfaceAdapter> selfReference =
|
||||
SharedRef<FileSystemInterfaceAdapter>.Create(ref _selfReference);
|
||||
|
||||
var adapter = new DirectoryInterfaceAdapter(ref directory.Ref(), ref selfReference.Ref());
|
||||
outDirectory.Reset(adapter);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result Commit()
|
||||
{
|
||||
return _baseFileSystem.Target.Commit();
|
||||
return _baseFileSystem.Get.Commit();
|
||||
}
|
||||
|
||||
public Result GetFileTimeStampRaw(out FileTimeStampRaw timeStamp, in PathSf path)
|
||||
@ -568,7 +550,7 @@ namespace LibHac.FsSrv.Impl
|
||||
Result rc = SetUpPath(ref pathNormalized.Ref(), in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = _baseFileSystem.Target.GetFileTimeStampRaw(out FileTimeStampRaw tempTimeStamp, in pathNormalized);
|
||||
rc = _baseFileSystem.Get.GetFileTimeStampRaw(out FileTimeStampRaw tempTimeStamp, in pathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
timeStamp = tempTimeStamp;
|
||||
@ -599,16 +581,16 @@ namespace LibHac.FsSrv.Impl
|
||||
rc = SetUpPath(ref pathNormalized.Ref(), in path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = _baseFileSystem.Target.QueryEntry(outBuffer.Buffer, inBuffer.Buffer, (QueryId)queryId,
|
||||
rc = _baseFileSystem.Get.QueryEntry(outBuffer.Buffer, inBuffer.Buffer, (QueryId)queryId,
|
||||
in pathNormalized);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result GetImpl(out ReferenceCountedDisposable<IFileSystem> fileSystem)
|
||||
public Result GetImpl(ref SharedRef<IFileSystem> fileSystem)
|
||||
{
|
||||
fileSystem = _baseFileSystem.AddReference();
|
||||
fileSystem.SetByCopy(ref _baseFileSystem);
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
@ -8,34 +8,32 @@ namespace LibHac.FsSrv.Impl
|
||||
{
|
||||
public static class FileSystemProxyServiceObject
|
||||
{
|
||||
public static ReferenceCountedDisposable<IFileSystemProxy> GetFileSystemProxyServiceObject(
|
||||
this FileSystemServerImpl fsSrv)
|
||||
public static SharedRef<IFileSystemProxy> GetFileSystemProxyServiceObject(this FileSystemServerImpl fsSrv)
|
||||
{
|
||||
return new ReferenceCountedDisposable<IFileSystemProxy>(new FileSystemProxyImpl(fsSrv.FsSrv));
|
||||
return new SharedRef<IFileSystemProxy>(new FileSystemProxyImpl(fsSrv.FsSrv));
|
||||
}
|
||||
|
||||
public static ReferenceCountedDisposable<IFileSystemProxyForLoader> GetFileSystemProxyForLoaderServiceObject(
|
||||
public static SharedRef<IFileSystemProxyForLoader> GetFileSystemProxyForLoaderServiceObject(
|
||||
this FileSystemServerImpl fsSrv)
|
||||
{
|
||||
return new ReferenceCountedDisposable<IFileSystemProxyForLoader>(new FileSystemProxyImpl(fsSrv.FsSrv));
|
||||
return new SharedRef<IFileSystemProxyForLoader>(new FileSystemProxyImpl(fsSrv.FsSrv));
|
||||
}
|
||||
|
||||
public static ReferenceCountedDisposable<IFileSystemProxyForLoader>
|
||||
GetInvalidFileSystemProxyForLoaderServiceObject(this FileSystemServerImpl fsSrv)
|
||||
{
|
||||
return new ReferenceCountedDisposable<IFileSystemProxyForLoader>(new InvalidFileSystemProxyImplForLoader());
|
||||
}
|
||||
|
||||
public static ReferenceCountedDisposable<IProgramRegistry> GetProgramRegistryServiceObject(
|
||||
public static SharedRef<IFileSystemProxyForLoader> GetInvalidFileSystemProxyForLoaderServiceObject(
|
||||
this FileSystemServerImpl fsSrv)
|
||||
{
|
||||
return new ReferenceCountedDisposable<IProgramRegistry>(new ProgramRegistryImpl(fsSrv.FsSrv));
|
||||
return new SharedRef<IFileSystemProxyForLoader>(new InvalidFileSystemProxyImplForLoader());
|
||||
}
|
||||
|
||||
public static ReferenceCountedDisposable<IProgramRegistry> GetInvalidProgramRegistryServiceObject(
|
||||
public static SharedRef<IProgramRegistry> GetProgramRegistryServiceObject(this FileSystemServerImpl fsSrv)
|
||||
{
|
||||
return new SharedRef<IProgramRegistry>(new ProgramRegistryImpl(fsSrv.FsSrv));
|
||||
}
|
||||
|
||||
public static SharedRef<IProgramRegistry> GetInvalidProgramRegistryServiceObject(
|
||||
this FileSystemServerImpl fsSrv)
|
||||
{
|
||||
return new ReferenceCountedDisposable<IProgramRegistry>(new InvalidProgramRegistryImpl());
|
||||
return new SharedRef<IProgramRegistry>(new InvalidProgramRegistryImpl());
|
||||
}
|
||||
|
||||
private class InvalidFileSystemProxyImplForLoader : IFileSystemProxyForLoader
|
||||
@ -49,10 +47,10 @@ namespace LibHac.FsSrv.Impl
|
||||
return ResultFs.PortAcceptableCountLimited.Log();
|
||||
}
|
||||
|
||||
public Result OpenCodeFileSystem(out ReferenceCountedDisposable<IFileSystem> fileSystem,
|
||||
public Result OpenCodeFileSystem(ref SharedRef<IFileSystem> fileSystem,
|
||||
out CodeVerificationData verificationData, in FspPath path, ProgramId programId)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out fileSystem, out verificationData);
|
||||
UnsafeHelpers.SkipParamInit(out verificationData);
|
||||
|
||||
return ResultFs.PortAcceptableCountLimited.Log();
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ namespace LibHac.FsSrv.Impl
|
||||
public void SetDeviceEvent(SimulatingDeviceTargetOperation operation,
|
||||
SimulatingDeviceAccessFailureEventType failureType, Result failureResult, bool isRecurringEvent)
|
||||
{
|
||||
using ScopedLock<SdkRecursiveMutex> lk = ScopedLock.Lock(ref _mutex);
|
||||
using ScopedLock<SdkRecursiveMutex> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
if (failureResult.IsFailure())
|
||||
_failureResult = failureResult;
|
||||
@ -82,7 +82,7 @@ namespace LibHac.FsSrv.Impl
|
||||
|
||||
public void ClearDeviceEvent()
|
||||
{
|
||||
using ScopedLock<SdkRecursiveMutex> lk = ScopedLock.Lock(ref _mutex);
|
||||
using ScopedLock<SdkRecursiveMutex> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
_isEventSet = false;
|
||||
_simulatedFailureType = SimulatingDeviceAccessFailureEventType.None;
|
||||
@ -93,7 +93,7 @@ namespace LibHac.FsSrv.Impl
|
||||
|
||||
public void SetDetectionSimulationMode(SimulatingDeviceDetectionMode mode)
|
||||
{
|
||||
using ScopedLock<SdkRecursiveMutex> lk = ScopedLock.Lock(ref _mutex);
|
||||
using ScopedLock<SdkRecursiveMutex> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
_isDetectionSimulationEnabled = mode != SimulatingDeviceDetectionMode.NoSimulation;
|
||||
_detectionSimulationMode = mode;
|
||||
@ -109,7 +109,7 @@ namespace LibHac.FsSrv.Impl
|
||||
if (_isEventSet)
|
||||
return Result.Success;
|
||||
|
||||
using ScopedLock<SdkRecursiveMutex> lk = ScopedLock.Lock(ref _mutex);
|
||||
using ScopedLock<SdkRecursiveMutex> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
if ((_simulatedOperation & operation) == 0)
|
||||
return Result.Success;
|
||||
|
@ -87,63 +87,62 @@ namespace LibHac.FsSrv.Impl
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public abstract class IResultConvertFileSystem : IFileSystem
|
||||
{
|
||||
protected ReferenceCountedDisposable<IFileSystem> BaseFileSystem;
|
||||
protected SharedRef<IFileSystem> BaseFileSystem;
|
||||
|
||||
protected IResultConvertFileSystem(ref ReferenceCountedDisposable<IFileSystem> baseFileSystem)
|
||||
protected IResultConvertFileSystem(ref SharedRef<IFileSystem> baseFileSystem)
|
||||
{
|
||||
BaseFileSystem = Shared.Move(ref baseFileSystem);
|
||||
BaseFileSystem = SharedRef<IFileSystem>.CreateMove(ref baseFileSystem);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
BaseFileSystem?.Dispose();
|
||||
BaseFileSystem = null;
|
||||
BaseFileSystem.Destroy();
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
protected override Result DoCreateFile(in Path path, long size, CreateFileOptions option)
|
||||
{
|
||||
return ConvertResult(BaseFileSystem.Target.CreateFile(path, size, option));
|
||||
return ConvertResult(BaseFileSystem.Get.CreateFile(path, size, option));
|
||||
}
|
||||
|
||||
protected override Result DoDeleteFile(in Path path)
|
||||
{
|
||||
return ConvertResult(BaseFileSystem.Target.DeleteFile(path));
|
||||
return ConvertResult(BaseFileSystem.Get.DeleteFile(path));
|
||||
}
|
||||
|
||||
protected override Result DoCreateDirectory(in Path path)
|
||||
{
|
||||
return ConvertResult(BaseFileSystem.Target.CreateDirectory(path));
|
||||
return ConvertResult(BaseFileSystem.Get.CreateDirectory(path));
|
||||
}
|
||||
|
||||
protected override Result DoDeleteDirectory(in Path path)
|
||||
{
|
||||
return ConvertResult(BaseFileSystem.Target.DeleteDirectory(path));
|
||||
return ConvertResult(BaseFileSystem.Get.DeleteDirectory(path));
|
||||
}
|
||||
|
||||
protected override Result DoDeleteDirectoryRecursively(in Path path)
|
||||
{
|
||||
return ConvertResult(BaseFileSystem.Target.DeleteDirectoryRecursively(path));
|
||||
return ConvertResult(BaseFileSystem.Get.DeleteDirectoryRecursively(path));
|
||||
}
|
||||
|
||||
protected override Result DoCleanDirectoryRecursively(in Path path)
|
||||
{
|
||||
return ConvertResult(BaseFileSystem.Target.CleanDirectoryRecursively(path));
|
||||
return ConvertResult(BaseFileSystem.Get.CleanDirectoryRecursively(path));
|
||||
}
|
||||
|
||||
protected override Result DoRenameFile(in Path currentPath, in Path newPath)
|
||||
{
|
||||
return ConvertResult(BaseFileSystem.Target.RenameFile(currentPath, newPath));
|
||||
return ConvertResult(BaseFileSystem.Get.RenameFile(currentPath, newPath));
|
||||
}
|
||||
|
||||
protected override Result DoRenameDirectory(in Path currentPath, in Path newPath)
|
||||
{
|
||||
return ConvertResult(BaseFileSystem.Target.RenameDirectory(currentPath, newPath));
|
||||
return ConvertResult(BaseFileSystem.Get.RenameDirectory(currentPath, newPath));
|
||||
}
|
||||
|
||||
protected override Result DoGetEntryType(out DirectoryEntryType entryType, in Path path)
|
||||
{
|
||||
return ConvertResult(BaseFileSystem.Target.GetEntryType(out entryType, path));
|
||||
return ConvertResult(BaseFileSystem.Get.GetEntryType(out entryType, path));
|
||||
}
|
||||
|
||||
protected abstract override Result DoOpenFile(ref UniqueRef<IFile> outFile, in Path path, OpenMode mode);
|
||||
@ -153,43 +152,43 @@ namespace LibHac.FsSrv.Impl
|
||||
|
||||
protected override Result DoCommit()
|
||||
{
|
||||
return ConvertResult(BaseFileSystem.Target.Commit());
|
||||
return ConvertResult(BaseFileSystem.Get.Commit());
|
||||
}
|
||||
|
||||
protected override Result DoCommitProvisionally(long counter)
|
||||
{
|
||||
return ConvertResult(BaseFileSystem.Target.CommitProvisionally(counter));
|
||||
return ConvertResult(BaseFileSystem.Get.CommitProvisionally(counter));
|
||||
}
|
||||
|
||||
protected override Result DoRollback()
|
||||
{
|
||||
return ConvertResult(BaseFileSystem.Target.Rollback());
|
||||
return ConvertResult(BaseFileSystem.Get.Rollback());
|
||||
}
|
||||
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return ConvertResult(BaseFileSystem.Target.Flush());
|
||||
return ConvertResult(BaseFileSystem.Get.Flush());
|
||||
}
|
||||
|
||||
protected override Result DoGetFileTimeStampRaw(out FileTimeStampRaw timeStamp, in Path path)
|
||||
{
|
||||
return ConvertResult(BaseFileSystem.Target.GetFileTimeStampRaw(out timeStamp, path));
|
||||
return ConvertResult(BaseFileSystem.Get.GetFileTimeStampRaw(out timeStamp, path));
|
||||
}
|
||||
|
||||
protected override Result DoQueryEntry(Span<byte> outBuffer, ReadOnlySpan<byte> inBuffer, QueryId queryId,
|
||||
in Path path)
|
||||
{
|
||||
return ConvertResult(BaseFileSystem.Target.QueryEntry(outBuffer, inBuffer, queryId, path));
|
||||
return ConvertResult(BaseFileSystem.Get.QueryEntry(outBuffer, inBuffer, queryId, path));
|
||||
}
|
||||
|
||||
protected override Result DoGetFreeSpaceSize(out long freeSpace, in Path path)
|
||||
{
|
||||
return ConvertResult(BaseFileSystem.Target.GetFreeSpaceSize(out freeSpace, path));
|
||||
return ConvertResult(BaseFileSystem.Get.GetFreeSpaceSize(out freeSpace, path));
|
||||
}
|
||||
|
||||
protected override Result DoGetTotalSpaceSize(out long totalSpace, in Path path)
|
||||
{
|
||||
return ConvertResult(BaseFileSystem.Target.GetTotalSpaceSize(out totalSpace, path));
|
||||
return ConvertResult(BaseFileSystem.Get.GetTotalSpaceSize(out totalSpace, path));
|
||||
}
|
||||
|
||||
protected abstract Result ConvertResult(Result result);
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.Ncm;
|
||||
@ -7,9 +8,7 @@ namespace LibHac.FsSrv.Impl
|
||||
{
|
||||
public interface IRomFileSystemAccessFailureManager : IDisposable
|
||||
{
|
||||
Result OpenDataStorageCore(out ReferenceCountedDisposable<IStorage> storage, out Hash ncaHeaderDigest, ulong id,
|
||||
StorageId storageId);
|
||||
|
||||
Result OpenDataStorageCore(ref SharedRef<IStorage> outStorage, out Hash ncaHeaderDigest, ulong id, StorageId storageId);
|
||||
Result HandleResolubleAccessFailure(out bool wasDeferred, Result resultForNoFailureDetected);
|
||||
void IncrementRomFsRemountForDataCorruptionCount();
|
||||
void IncrementRomFsUnrecoverableDataCorruptionByRemountCount();
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
@ -9,6 +10,6 @@ namespace LibHac.FsSrv.Impl
|
||||
Result RecoverMultiCommit();
|
||||
Result IsProvisionallyCommittedSaveData(out bool isProvisionallyCommitted, in SaveDataInfo saveInfo);
|
||||
Result RecoverProvisionallyCommittedSaveData(in SaveDataInfo saveInfo, bool doRollback);
|
||||
Result OpenMultiCommitContext(out ReferenceCountedDisposable<IFileSystem> contextFileSystem);
|
||||
Result OpenMultiCommitContext(ref SharedRef<IFileSystem> contextFileSystem);
|
||||
}
|
||||
}
|
||||
|
@ -18,9 +18,9 @@ namespace LibHac.FsSrv.Impl
|
||||
Result WriteSaveDataFileSystemExtraDataCore(SaveDataSpaceId spaceId, ulong saveDataId, in SaveDataExtraData extraData, SaveDataType type, bool updateTimeStamp);
|
||||
Result FinalizeSaveDataCreation(ulong saveDataId, SaveDataSpaceId spaceId);
|
||||
Result CancelSaveDataCreation(ulong saveDataId, SaveDataSpaceId spaceId);
|
||||
Result OpenSaveDataFile(out ReferenceCountedDisposable<IFileSf> file, SaveDataSpaceId spaceId, in SaveDataAttribute attribute, SaveDataMetaType metaType);
|
||||
Result OpenSaveDataMetaFileRaw(out ReferenceCountedDisposable<IFile> file, SaveDataSpaceId spaceId, ulong saveDataId, SaveDataMetaType metaType, OpenMode mode);
|
||||
Result OpenSaveDataInternalStorageFileSystemCore(out ReferenceCountedDisposable<IFileSystem> fileSystem, SaveDataSpaceId spaceId, ulong saveDataId, bool useSecondMacKey);
|
||||
Result OpenSaveDataFile(ref SharedRef<IFileSf> file, SaveDataSpaceId spaceId, in SaveDataAttribute attribute, SaveDataMetaType metaType);
|
||||
Result OpenSaveDataMetaFileRaw(ref SharedRef<IFile> file, SaveDataSpaceId spaceId, ulong saveDataId, SaveDataMetaType metaType, OpenMode mode);
|
||||
Result OpenSaveDataInternalStorageFileSystemCore(ref SharedRef<IFileSystem> fileSystem, SaveDataSpaceId spaceId, ulong saveDataId, bool useSecondMacKey);
|
||||
Result ExtendSaveDataFileSystem(SaveDataSpaceId spaceId, ulong saveDataId, long dataSize, long journalSize);
|
||||
Result DeleteSaveDataFileSystemBySaveDataSpaceId(SaveDataSpaceId spaceId, ulong saveDataId);
|
||||
Result SwapSaveDataKeyAndState(SaveDataSpaceId spaceId, ulong saveDataId1, ulong saveDataId2);
|
||||
|
@ -1,10 +1,12 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Common.FixedArrays;
|
||||
using LibHac.Diag;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Lr;
|
||||
using LibHac.Ncm;
|
||||
using LibHac.Os;
|
||||
using LibHac.Util;
|
||||
|
||||
namespace LibHac.FsSrv.Impl
|
||||
{
|
||||
@ -37,34 +39,39 @@ namespace LibHac.FsSrv.Impl
|
||||
/// <summary>
|
||||
/// Manages resolving the location of NCAs via the <c>lr</c> service.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 12.0.3 (nnSdk 12.3.1)</remarks>
|
||||
/// <remarks>Based on FS 12.1.0 (nnSdk 12.3.1)</remarks>
|
||||
internal class LocationResolverSet : IDisposable
|
||||
{
|
||||
private const int LocationResolverCount = 5;
|
||||
|
||||
// Todo: Use Optional<T>
|
||||
private LocationResolver[] _resolvers;
|
||||
private AddOnContentLocationResolver _aocResolver;
|
||||
private Array5<Optional<LocationResolver>> _resolvers;
|
||||
private Optional<AddOnContentLocationResolver> _aocResolver;
|
||||
private SdkMutexType _mutex;
|
||||
|
||||
// LibHac addition
|
||||
private FileSystemServer _fsServer;
|
||||
private HorizonClient Hos => _fsServer.Hos;
|
||||
|
||||
public LocationResolverSet(FileSystemServer fsServer)
|
||||
{
|
||||
_resolvers = new LocationResolver[LocationResolverCount];
|
||||
_mutex.Initialize();
|
||||
_fsServer = fsServer;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (LocationResolver resolver in _resolvers)
|
||||
for (int i = 0; i < Array5<SharedRef<LocationResolver>>.Length; i++)
|
||||
{
|
||||
resolver?.Dispose();
|
||||
if (_resolvers[i].HasValue)
|
||||
{
|
||||
_resolvers[i].Value.Dispose();
|
||||
_resolvers[i].Clear();
|
||||
}
|
||||
}
|
||||
|
||||
_aocResolver?.Dispose();
|
||||
if (_aocResolver.HasValue)
|
||||
{
|
||||
_aocResolver.Value.Dispose();
|
||||
_aocResolver.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private static Result SetUpFsPath(ref Fs.Path outPath, in Lr.Path lrPath)
|
||||
@ -90,48 +97,43 @@ namespace LibHac.FsSrv.Impl
|
||||
|
||||
_fsServer.InitializeLocationResolverSet();
|
||||
|
||||
if (!IsValidStorageId(storageId))
|
||||
return ResultLr.LocationResolverNotFound.Log();
|
||||
|
||||
using ScopedLock<SdkMutexType> lk = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
int index = GetResolverIndexFromStorageId(storageId);
|
||||
if (index == -1)
|
||||
return ResultLr.ApplicationNotFound.Log();
|
||||
|
||||
if (index < 0)
|
||||
return ResultLr.LocationResolverNotFound.Log();
|
||||
|
||||
ref LocationResolver lr = ref _resolvers[index];
|
||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
// Open the location resolver if it hasn't been already
|
||||
if (lr is null && Hos.Lr.OpenLocationResolver(out lr, storageId).IsFailure())
|
||||
return ResultLr.LocationResolverNotFound.Log();
|
||||
if (!_resolvers[index].HasValue)
|
||||
{
|
||||
_resolvers[index].Set(null);
|
||||
Result rc = Hos.Lr.OpenLocationResolver(out _resolvers[index].Value, storageId);
|
||||
|
||||
resolver = lr;
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
_resolvers[index].Clear();
|
||||
return ResultLr.ApplicationNotFound.Log();
|
||||
}
|
||||
}
|
||||
|
||||
resolver = _resolvers[index].Value;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private Result GetRegisteredLocationResolver(out RegisteredLocationResolver resolver)
|
||||
{
|
||||
Result rc = Hos.Lr.OpenRegisteredLocationResolver(out RegisteredLocationResolver lr);
|
||||
_fsServer.InitializeLocationResolverSet();
|
||||
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
lr?.Dispose();
|
||||
UnsafeHelpers.SkipParamInit(out resolver);
|
||||
return rc;
|
||||
}
|
||||
|
||||
resolver = lr;
|
||||
return Result.Success;
|
||||
return Hos.Lr.OpenRegisteredLocationResolver(out resolver);
|
||||
}
|
||||
|
||||
private Result GetAddOnContentLocationResolver(out AddOnContentLocationResolver resolver)
|
||||
{
|
||||
_fsServer.InitializeLocationResolverSet();
|
||||
|
||||
using ScopedLock<SdkMutexType> lk = ScopedLock.Lock(ref _mutex);
|
||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
if (_aocResolver is null)
|
||||
if (!_aocResolver.HasValue)
|
||||
{
|
||||
Result rc = Hos.Lr.OpenAddOnContentLocationResolver(out AddOnContentLocationResolver lr);
|
||||
if (rc.IsFailure())
|
||||
@ -143,7 +145,7 @@ namespace LibHac.FsSrv.Impl
|
||||
_aocResolver = lr;
|
||||
}
|
||||
|
||||
resolver = _aocResolver;
|
||||
resolver = _aocResolver.Value;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
@ -230,8 +232,6 @@ namespace LibHac.FsSrv.Impl
|
||||
|
||||
public Result ResolveRegisteredProgramPath(ref Fs.Path outPath, ulong id)
|
||||
{
|
||||
_fsServer.InitializeLocationResolverSet();
|
||||
|
||||
RegisteredLocationResolver resolver = null;
|
||||
try
|
||||
{
|
||||
@ -251,8 +251,6 @@ namespace LibHac.FsSrv.Impl
|
||||
|
||||
public Result ResolveRegisteredHtmlDocumentPath(ref Fs.Path outPath, ulong id)
|
||||
{
|
||||
_fsServer.InitializeLocationResolverSet();
|
||||
|
||||
RegisteredLocationResolver resolver = null;
|
||||
try
|
||||
{
|
||||
|
@ -40,9 +40,8 @@ namespace LibHac.FsSrv.Impl
|
||||
/// Even though multi-commits are supposed to be atomic, issues can arise from errors during the process of fully committing the save data.
|
||||
/// Save data image files are designed so that minimal changes are made when fully committing a provisionally committed save.
|
||||
/// However if any commit fails for any reason, all other saves in the multi-commit will still be committed.
|
||||
/// This can especially cause issues with directory save data where finishing a commit is much more involved.<br/>
|
||||
/// <br/>
|
||||
/// Based on FS 12.0.3 (nnSdk 12.3.1)
|
||||
/// This can especially cause issues with directory save data where finishing a commit is much more involved.
|
||||
/// <para>Based on FS 12.1.0 (nnSdk 12.3.1)</para>
|
||||
/// </remarks>
|
||||
internal class MultiCommitManager : IMultiCommitManager
|
||||
{
|
||||
@ -60,40 +59,39 @@ namespace LibHac.FsSrv.Impl
|
||||
private static ReadOnlySpan<byte> CommitContextFileName =>
|
||||
new[] { (byte)'/', (byte)'c', (byte)'o', (byte)'m', (byte)'m', (byte)'i', (byte)'t', (byte)'i', (byte)'n', (byte)'f', (byte)'o' };
|
||||
|
||||
private ReferenceCountedDisposable<ISaveDataMultiCommitCoreInterface> _multiCommitInterface;
|
||||
private readonly ReferenceCountedDisposable<IFileSystem>[] _fileSystems;
|
||||
private SharedRef<ISaveDataMultiCommitCoreInterface> _multiCommitInterface;
|
||||
private readonly SharedRef<IFileSystem>[] _fileSystems;
|
||||
private int _fileSystemCount;
|
||||
private long _counter;
|
||||
|
||||
// Extra field used in LibHac
|
||||
// LibHac additions
|
||||
private readonly FileSystemServer _fsServer;
|
||||
private ref MultiCommitManagerGlobals Globals => ref _fsServer.Globals.MultiCommitManager;
|
||||
|
||||
public MultiCommitManager(FileSystemServer fsServer, ref ReferenceCountedDisposable<ISaveDataMultiCommitCoreInterface> multiCommitInterface)
|
||||
public MultiCommitManager(FileSystemServer fsServer, ref SharedRef<ISaveDataMultiCommitCoreInterface> multiCommitInterface)
|
||||
{
|
||||
_fsServer = fsServer;
|
||||
|
||||
_multiCommitInterface = Shared.Move(ref multiCommitInterface);
|
||||
_fileSystems = new ReferenceCountedDisposable<IFileSystem>[MaxFileSystemCount];
|
||||
_multiCommitInterface = SharedRef<ISaveDataMultiCommitCoreInterface>.CreateMove(ref multiCommitInterface);
|
||||
_fileSystems = new SharedRef<IFileSystem>[MaxFileSystemCount];
|
||||
_fileSystemCount = 0;
|
||||
_counter = 0;
|
||||
}
|
||||
|
||||
public static ReferenceCountedDisposable<IMultiCommitManager> CreateShared(FileSystemServer fsServer,
|
||||
ref ReferenceCountedDisposable<ISaveDataMultiCommitCoreInterface> multiCommitInterface)
|
||||
public static SharedRef<IMultiCommitManager> CreateShared(FileSystemServer fsServer,
|
||||
ref SharedRef<ISaveDataMultiCommitCoreInterface> multiCommitInterface)
|
||||
{
|
||||
var manager = new MultiCommitManager(fsServer, ref multiCommitInterface);
|
||||
return new ReferenceCountedDisposable<IMultiCommitManager>(manager);
|
||||
return new SharedRef<IMultiCommitManager>(new MultiCommitManager(fsServer, ref multiCommitInterface));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (ReferenceCountedDisposable<IFileSystem> fs in _fileSystems)
|
||||
for (int i = 0; i < _fileSystems.Length; i++)
|
||||
{
|
||||
fs?.Dispose();
|
||||
_fileSystems[i].Destroy();
|
||||
}
|
||||
|
||||
_multiCommitInterface?.Dispose();
|
||||
_multiCommitInterface.Destroy();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -102,26 +100,19 @@ namespace LibHac.FsSrv.Impl
|
||||
/// <returns>The <see cref="Result"/> of the operation.</returns>
|
||||
private Result EnsureSaveDataForContext()
|
||||
{
|
||||
ReferenceCountedDisposable<IFileSystem> contextFs = null;
|
||||
try
|
||||
using var contextFileSystem = new SharedRef<IFileSystem>();
|
||||
Result rc = _multiCommitInterface.Get.OpenMultiCommitContext(ref contextFileSystem.Ref());
|
||||
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
Result rc = _multiCommitInterface.Target.OpenMultiCommitContext(out contextFs);
|
||||
if (!ResultFs.TargetNotFound.Includes(rc))
|
||||
return rc;
|
||||
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
if (!ResultFs.TargetNotFound.Includes(rc))
|
||||
return rc;
|
||||
|
||||
rc = _fsServer.Hos.Fs.CreateSystemSaveData(SaveDataId, SaveDataSize, SaveJournalSize, SaveDataFlags.None);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
contextFs?.Dispose();
|
||||
rc = _fsServer.Hos.Fs.CreateSystemSaveData(SaveDataId, SaveDataSize, SaveJournalSize, SaveDataFlags.None);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -132,33 +123,26 @@ namespace LibHac.FsSrv.Impl
|
||||
/// <see cref="ResultFs.MultiCommitFileSystemLimit"/>: The maximum number of file systems have been added.
|
||||
/// <see cref="MaxFileSystemCount"/> file systems may be added to a single multi-commit.<br/>
|
||||
/// <see cref="ResultFs.MultiCommitFileSystemAlreadyAdded"/>: The provided file system has already been added.</returns>
|
||||
public Result Add(ReferenceCountedDisposable<IFileSystemSf> fileSystem)
|
||||
public Result Add(ref SharedRef<IFileSystemSf> fileSystem)
|
||||
{
|
||||
if (_fileSystemCount >= MaxFileSystemCount)
|
||||
return ResultFs.MultiCommitFileSystemLimit.Log();
|
||||
|
||||
ReferenceCountedDisposable<IFileSystem> fsaFileSystem = null;
|
||||
try
|
||||
using var fsaFileSystem = new SharedRef<IFileSystem>();
|
||||
Result rc = fileSystem.Get.GetImpl(ref fsaFileSystem.Ref());
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
// Check that the file system hasn't already been added
|
||||
for (int i = 0; i < _fileSystemCount; i++)
|
||||
{
|
||||
Result rc = fileSystem.Target.GetImpl(out fsaFileSystem);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
// Check that the file system hasn't already been added
|
||||
for (int i = 0; i < _fileSystemCount; i++)
|
||||
{
|
||||
if (ReferenceEquals(fsaFileSystem.Target, _fileSystems[i].Target))
|
||||
return ResultFs.MultiCommitFileSystemAlreadyAdded.Log();
|
||||
}
|
||||
|
||||
_fileSystems[_fileSystemCount] = Shared.Move(ref fsaFileSystem);
|
||||
_fileSystemCount++;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
fsaFileSystem?.Dispose();
|
||||
if (ReferenceEquals(fsaFileSystem.Get, _fileSystems[i].Get))
|
||||
return ResultFs.MultiCommitFileSystemAlreadyAdded.Log();
|
||||
}
|
||||
|
||||
_fileSystems[_fileSystemCount].SetByMove(ref fsaFileSystem.Ref());
|
||||
_fileSystemCount++;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -198,21 +182,14 @@ namespace LibHac.FsSrv.Impl
|
||||
{
|
||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref Globals.MultiCommitMutex);
|
||||
|
||||
ReferenceCountedDisposable<IFileSystem> contextFs = null;
|
||||
try
|
||||
{
|
||||
Result rc = EnsureSaveDataForContext();
|
||||
if (rc.IsFailure()) return rc;
|
||||
using var contextFileSystem = new SharedRef<IFileSystem>();
|
||||
Result rc = EnsureSaveDataForContext();
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = _multiCommitInterface.Target.OpenMultiCommitContext(out contextFs);
|
||||
if (rc.IsFailure()) return rc;
|
||||
rc = _multiCommitInterface.Get.OpenMultiCommitContext(ref contextFileSystem.Ref());
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Commit(contextFs.Target);
|
||||
}
|
||||
finally
|
||||
{
|
||||
contextFs?.Dispose();
|
||||
}
|
||||
return Commit(contextFileSystem.Get);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -227,9 +204,9 @@ namespace LibHac.FsSrv.Impl
|
||||
|
||||
for (i = 0; i < _fileSystemCount; i++)
|
||||
{
|
||||
Assert.SdkNotNull(_fileSystems[i]);
|
||||
Assert.SdkNotNull(_fileSystems[i].Get);
|
||||
|
||||
rc = _fileSystems[i].Target.CommitProvisionally(counter);
|
||||
rc = _fileSystems[i].Get.CommitProvisionally(counter);
|
||||
|
||||
if (rc.IsFailure())
|
||||
break;
|
||||
@ -240,9 +217,9 @@ namespace LibHac.FsSrv.Impl
|
||||
// Rollback all provisional commits including the failed commit
|
||||
for (int j = 0; j <= i; j++)
|
||||
{
|
||||
Assert.SdkNotNull(_fileSystems[j]);
|
||||
Assert.SdkNotNull(_fileSystems[j].Get);
|
||||
|
||||
_fileSystems[j].Target.Rollback().IgnoreResult();
|
||||
_fileSystems[j].Get.Rollback().IgnoreResult();
|
||||
}
|
||||
}
|
||||
|
||||
@ -261,17 +238,19 @@ namespace LibHac.FsSrv.Impl
|
||||
|
||||
for (int i = 0; i < _fileSystemCount; i++)
|
||||
{
|
||||
Assert.SdkNotNull(_fileSystems[i]);
|
||||
Assert.SdkNotNull(_fileSystems[i].Get);
|
||||
|
||||
Result rc = _fileSystems[i].Target.Commit();
|
||||
Result resultLast = _fileSystems[i].Get.Commit();
|
||||
|
||||
// If the commit failed, set the overall result if it hasn't been set yet.
|
||||
if (result.IsSuccess() && rc.IsFailure())
|
||||
if (result.IsSuccess() && resultLast.IsFailure())
|
||||
{
|
||||
result = rc;
|
||||
result = resultLast;
|
||||
}
|
||||
}
|
||||
|
||||
if (result.IsFailure()) return result.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
@ -319,14 +298,14 @@ namespace LibHac.FsSrv.Impl
|
||||
int saveCount = 0;
|
||||
Span<SaveDataInfo> savesToRecover = stackalloc SaveDataInfo[MaxFileSystemCount];
|
||||
|
||||
ReferenceCountedDisposable<SaveDataInfoReaderImpl> infoReader = null;
|
||||
try
|
||||
{
|
||||
using var reader = new SharedRef<SaveDataInfoReaderImpl>();
|
||||
using var accessor = new UniqueRef<SaveDataIndexerAccessor>();
|
||||
|
||||
rc = saveService.OpenSaveDataIndexerAccessor(ref accessor.Ref(), out _, SaveDataSpaceId.User);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = accessor.Get.Indexer.OpenSaveDataInfoReader(out infoReader);
|
||||
rc = accessor.Get.Indexer.OpenSaveDataInfoReader(ref reader.Ref());
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
// Iterate through all the saves to find any provisionally committed save data
|
||||
@ -334,7 +313,7 @@ namespace LibHac.FsSrv.Impl
|
||||
{
|
||||
Unsafe.SkipInit(out SaveDataInfo info);
|
||||
|
||||
rc = infoReader.Target.Read(out long readCount, OutBuffer.FromStruct(ref info));
|
||||
rc = reader.Get.Read(out long readCount, OutBuffer.FromStruct(ref info));
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
// Break once we're done iterating all save data
|
||||
@ -344,8 +323,10 @@ namespace LibHac.FsSrv.Impl
|
||||
rc = multiCommitInterface.IsProvisionallyCommittedSaveData(out bool isProvisionallyCommitted,
|
||||
in info);
|
||||
|
||||
// Note: Some saves could be missed if there are more than MaxFileSystemCount
|
||||
// provisionally committed saves. Not sure why Nintendo doesn't catch this.
|
||||
// Note: Multi-commits are only recovered at boot time, so some saves could be missed if there
|
||||
// are more than MaxFileSystemCount provisionally committed saves.
|
||||
// In theory this shouldn't happen because a multi-commit should only be interrupted if the
|
||||
// entire OS is brought down.
|
||||
if (rc.IsSuccess() && isProvisionallyCommitted && saveCount < MaxFileSystemCount)
|
||||
{
|
||||
savesToRecover[saveCount] = info;
|
||||
@ -353,10 +334,6 @@ namespace LibHac.FsSrv.Impl
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
infoReader?.Dispose();
|
||||
}
|
||||
|
||||
// Recover the saves by finishing their commits.
|
||||
// All file systems will try to be recovered, even if one fails.
|
||||
@ -402,14 +379,14 @@ namespace LibHac.FsSrv.Impl
|
||||
int saveCount = 0;
|
||||
Span<SaveDataInfo> savesToRecover = stackalloc SaveDataInfo[MaxFileSystemCount];
|
||||
|
||||
ReferenceCountedDisposable<SaveDataInfoReaderImpl> infoReader = null;
|
||||
try
|
||||
{
|
||||
using var reader = new SharedRef<SaveDataInfoReaderImpl>();
|
||||
using var accessor = new UniqueRef<SaveDataIndexerAccessor>();
|
||||
|
||||
rc = saveService.OpenSaveDataIndexerAccessor(ref accessor.Ref(), out _, SaveDataSpaceId.User);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = accessor.Get.Indexer.OpenSaveDataInfoReader(out infoReader);
|
||||
rc = accessor.Get.Indexer.OpenSaveDataInfoReader(ref reader.Ref());
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
// Iterate through all the saves to find any provisionally committed save data
|
||||
@ -417,7 +394,7 @@ namespace LibHac.FsSrv.Impl
|
||||
{
|
||||
Unsafe.SkipInit(out SaveDataInfo info);
|
||||
|
||||
rc = infoReader.Target.Read(out long readCount, OutBuffer.FromStruct(ref info));
|
||||
rc = reader.Get.Read(out long readCount, OutBuffer.FromStruct(ref info));
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
// Break once we're done iterating all save data
|
||||
@ -427,8 +404,10 @@ namespace LibHac.FsSrv.Impl
|
||||
rc = multiCommitInterface.IsProvisionallyCommittedSaveData(out bool isProvisionallyCommitted,
|
||||
in info);
|
||||
|
||||
// Note: Some saves could be missed if there are more than MaxFileSystemCount
|
||||
// provisionally committed saves. Not sure why Nintendo doesn't catch this.
|
||||
// Note: Multi-commits are only recovered at boot time, so some saves could be missed if there
|
||||
// are more than MaxFileSystemCount provisionally committed saves.
|
||||
// In theory this shouldn't happen because a multi-commit should only be interrupted if the
|
||||
// entire OS is brought down.
|
||||
if (rc.IsSuccess() && isProvisionallyCommitted && saveCount < MaxFileSystemCount)
|
||||
{
|
||||
savesToRecover[saveCount] = info;
|
||||
@ -436,10 +415,6 @@ namespace LibHac.FsSrv.Impl
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
infoReader?.Dispose();
|
||||
}
|
||||
|
||||
// Recover the saves by rolling them back to the previous commit.
|
||||
// All file systems will try to be recovered, even if one fails.
|
||||
@ -448,7 +423,7 @@ namespace LibHac.FsSrv.Impl
|
||||
{
|
||||
rc = multiCommitInterface.RecoverProvisionallyCommittedSaveData(in savesToRecover[i], true);
|
||||
|
||||
if (recoveryResult.IsSuccess() && rc.IsFailure())
|
||||
if (rc.IsFailure() && !recoveryResult.IsFailure())
|
||||
{
|
||||
recoveryResult = rc;
|
||||
}
|
||||
@ -481,53 +456,46 @@ namespace LibHac.FsSrv.Impl
|
||||
public static Result Recover(FileSystemServer fsServer, ISaveDataMultiCommitCoreInterface multiCommitInterface,
|
||||
SaveDataFileSystemServiceImpl saveService)
|
||||
{
|
||||
ref MultiCommitManagerGlobals globals = ref fsServer.Globals.MultiCommitManager;
|
||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref globals.MultiCommitMutex);
|
||||
using ScopedLock<SdkMutexType> scopedLock =
|
||||
ScopedLock.Lock(ref fsServer.Globals.MultiCommitManager.MultiCommitMutex);
|
||||
|
||||
bool needsRecovery = true;
|
||||
ReferenceCountedDisposable<IFileSystem> fileSystem = null;
|
||||
using var fileSystem = new SharedRef<IFileSystem>();
|
||||
|
||||
try
|
||||
// Check if a multi-commit was interrupted by checking if there's a commit context file.
|
||||
Result rc = multiCommitInterface.OpenMultiCommitContext(ref fileSystem.Ref());
|
||||
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
// Check if a multi-commit was interrupted by checking if there's a commit context file.
|
||||
Result rc = multiCommitInterface.OpenMultiCommitContext(out fileSystem);
|
||||
if (!ResultFs.PathNotFound.Includes(rc) && !ResultFs.TargetNotFound.Includes(rc))
|
||||
return rc;
|
||||
|
||||
// Unable to open the multi-commit context file system, so there's nothing to recover
|
||||
needsRecovery = false;
|
||||
}
|
||||
|
||||
if (needsRecovery)
|
||||
{
|
||||
using var contextFilePath = new Fs.Path();
|
||||
rc = PathFunctions.SetUpFixedPath(ref contextFilePath.Ref(), CommitContextFileName);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
using var file = new UniqueRef<IFile>();
|
||||
rc = fileSystem.Get.OpenFile(ref file.Ref(), in contextFilePath, OpenMode.Read);
|
||||
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
if (!ResultFs.PathNotFound.Includes(rc) && !ResultFs.TargetNotFound.Includes(rc))
|
||||
return rc;
|
||||
|
||||
// Unable to open the multi-commit context file system, so there's nothing to recover
|
||||
needsRecovery = false;
|
||||
// Unable to open the context file. No multi-commit to recover.
|
||||
if (ResultFs.PathNotFound.Includes(rc))
|
||||
needsRecovery = false;
|
||||
}
|
||||
|
||||
if (needsRecovery)
|
||||
{
|
||||
using var contextFilePath = new Fs.Path();
|
||||
rc = PathFunctions.SetUpFixedPath(ref contextFilePath.Ref(), CommitContextFileName);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
using var file = new UniqueRef<IFile>();
|
||||
rc = fileSystem.Target.OpenFile(ref file.Ref(), in contextFilePath, OpenMode.Read);
|
||||
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
// Unable to open the context file. No multi-commit to recover.
|
||||
if (ResultFs.PathNotFound.Includes(rc))
|
||||
needsRecovery = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!needsRecovery)
|
||||
return Result.Success;
|
||||
|
||||
// There was a context file. Recover the unfinished commit.
|
||||
return Recover(multiCommitInterface, fileSystem.Target, saveService);
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileSystem?.Dispose();
|
||||
}
|
||||
|
||||
if (!needsRecovery)
|
||||
return Result.Success;
|
||||
|
||||
// There was a context file. Recover the unfinished commit.
|
||||
return Recover(multiCommitInterface, fileSystem.Get, saveService);
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Size = 0x18)]
|
||||
|
@ -7,43 +7,42 @@ namespace LibHac.FsSrv.Impl
|
||||
{
|
||||
internal class OpenCountFileSystem : ForwardingFileSystem
|
||||
{
|
||||
private ReferenceCountedDisposable<IEntryOpenCountSemaphoreManager> _entryCountSemaphore;
|
||||
private SharedRef<IEntryOpenCountSemaphoreManager> _entryCountSemaphore;
|
||||
private UniqueRef<IUniqueLock> _mountCountSemaphore;
|
||||
|
||||
public OpenCountFileSystem(ref ReferenceCountedDisposable<IFileSystem> baseFileSystem,
|
||||
ref ReferenceCountedDisposable<IEntryOpenCountSemaphoreManager> entryCountSemaphore) : base(
|
||||
ref baseFileSystem)
|
||||
public OpenCountFileSystem(ref SharedRef<IFileSystem> baseFileSystem,
|
||||
ref SharedRef<IEntryOpenCountSemaphoreManager> entryCountSemaphore) : base(ref baseFileSystem)
|
||||
{
|
||||
Shared.Move(out _entryCountSemaphore, ref entryCountSemaphore);
|
||||
_entryCountSemaphore = SharedRef<IEntryOpenCountSemaphoreManager>.CreateMove(ref entryCountSemaphore);
|
||||
}
|
||||
|
||||
public OpenCountFileSystem(ref ReferenceCountedDisposable<IFileSystem> baseFileSystem,
|
||||
ref ReferenceCountedDisposable<IEntryOpenCountSemaphoreManager> entryCountSemaphore,
|
||||
public OpenCountFileSystem(ref SharedRef<IFileSystem> baseFileSystem,
|
||||
ref SharedRef<IEntryOpenCountSemaphoreManager> entryCountSemaphore,
|
||||
ref UniqueRef<IUniqueLock> mountCountSemaphore) : base(ref baseFileSystem)
|
||||
{
|
||||
Shared.Move(out _entryCountSemaphore, ref entryCountSemaphore);
|
||||
_entryCountSemaphore = SharedRef<IEntryOpenCountSemaphoreManager>.CreateMove(ref entryCountSemaphore);
|
||||
_mountCountSemaphore = new UniqueRef<IUniqueLock>(ref mountCountSemaphore);
|
||||
}
|
||||
|
||||
public static ReferenceCountedDisposable<IFileSystem> CreateShared(
|
||||
ref ReferenceCountedDisposable<IFileSystem> baseFileSystem,
|
||||
ref ReferenceCountedDisposable<IEntryOpenCountSemaphoreManager> entryCountSemaphore,
|
||||
public static SharedRef<IFileSystem> CreateShared(
|
||||
ref SharedRef<IFileSystem> baseFileSystem,
|
||||
ref SharedRef<IEntryOpenCountSemaphoreManager> entryCountSemaphore,
|
||||
ref UniqueRef<IUniqueLock> mountCountSemaphore)
|
||||
{
|
||||
var filesystem =
|
||||
new OpenCountFileSystem(ref baseFileSystem, ref entryCountSemaphore, ref mountCountSemaphore);
|
||||
|
||||
return new ReferenceCountedDisposable<IFileSystem>(filesystem);
|
||||
return new SharedRef<IFileSystem>(filesystem);
|
||||
}
|
||||
|
||||
public static ReferenceCountedDisposable<IFileSystem> CreateShared(
|
||||
ref ReferenceCountedDisposable<IFileSystem> baseFileSystem,
|
||||
ref ReferenceCountedDisposable<IEntryOpenCountSemaphoreManager> entryCountSemaphore)
|
||||
public static SharedRef<IFileSystem> CreateShared(
|
||||
ref SharedRef<IFileSystem> baseFileSystem,
|
||||
ref SharedRef<IEntryOpenCountSemaphoreManager> entryCountSemaphore)
|
||||
{
|
||||
var filesystem =
|
||||
new OpenCountFileSystem(ref baseFileSystem, ref entryCountSemaphore);
|
||||
|
||||
return new ReferenceCountedDisposable<IFileSystem>(filesystem);
|
||||
return new SharedRef<IFileSystem>(filesystem);
|
||||
}
|
||||
|
||||
// ReSharper disable once RedundantOverriddenMember
|
||||
@ -63,7 +62,7 @@ namespace LibHac.FsSrv.Impl
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
_entryCountSemaphore?.Dispose();
|
||||
_entryCountSemaphore.Destroy();
|
||||
_mountCountSemaphore.Destroy();
|
||||
base.Dispose();
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsSystem;
|
||||
@ -11,32 +12,37 @@ namespace LibHac.FsSrv.Impl
|
||||
/// </summary>
|
||||
public class SaveDataExtraDataAccessorCacheManager : ISaveDataExtraDataAccessorCacheObserver
|
||||
{
|
||||
private struct Cache
|
||||
private struct Cache : IDisposable
|
||||
{
|
||||
private ReferenceCountedDisposable<ISaveDataExtraDataAccessor>.WeakReference _accessor;
|
||||
private WeakRef<ISaveDataExtraDataAccessor> _accessor;
|
||||
private readonly SaveDataSpaceId _spaceId;
|
||||
private readonly ulong _saveDataId;
|
||||
|
||||
public Cache(ReferenceCountedDisposable<ISaveDataExtraDataAccessor> accessor, SaveDataSpaceId spaceId,
|
||||
public Cache(ref SharedRef<ISaveDataExtraDataAccessor> accessor, SaveDataSpaceId spaceId,
|
||||
ulong saveDataId)
|
||||
{
|
||||
_accessor = new ReferenceCountedDisposable<ISaveDataExtraDataAccessor>.WeakReference(accessor);
|
||||
_accessor = new WeakRef<ISaveDataExtraDataAccessor>(ref accessor);
|
||||
_spaceId = spaceId;
|
||||
_saveDataId = saveDataId;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_accessor.Destroy();
|
||||
}
|
||||
|
||||
public bool Contains(SaveDataSpaceId spaceId, ulong saveDataId)
|
||||
{
|
||||
return _spaceId == spaceId && _saveDataId == saveDataId;
|
||||
}
|
||||
|
||||
public ReferenceCountedDisposable<ISaveDataExtraDataAccessor> Lock()
|
||||
public SharedRef<ISaveDataExtraDataAccessor> Lock()
|
||||
{
|
||||
return _accessor.TryAddReference();
|
||||
return _accessor.Lock();
|
||||
}
|
||||
}
|
||||
|
||||
private readonly LinkedList<Cache> _accessorList;
|
||||
private LinkedList<Cache> _accessorList;
|
||||
private SdkRecursiveMutexType _mutex;
|
||||
|
||||
public SaveDataExtraDataAccessorCacheManager()
|
||||
@ -47,17 +53,33 @@ namespace LibHac.FsSrv.Impl
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
using ScopedLock<SdkRecursiveMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
LinkedListNode<Cache> currentEntry = _accessorList.First;
|
||||
|
||||
while (currentEntry is not null)
|
||||
{
|
||||
ref Cache entry = ref currentEntry.ValueRef;
|
||||
_accessorList.Remove(entry);
|
||||
entry.Dispose();
|
||||
|
||||
currentEntry = _accessorList.First;
|
||||
}
|
||||
|
||||
_accessorList.Clear();
|
||||
}
|
||||
|
||||
public Result Register(ReferenceCountedDisposable<ISaveDataExtraDataAccessor> accessor,
|
||||
public Result Register(ref SharedRef<ISaveDataExtraDataAccessor> accessor,
|
||||
SaveDataSpaceId spaceId, ulong saveDataId)
|
||||
{
|
||||
var cache = new Cache(accessor, spaceId, saveDataId);
|
||||
var cache = new Cache(ref accessor, spaceId, saveDataId);
|
||||
|
||||
using ScopedLock<SdkRecursiveMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
using (ScopedLock.Lock(ref _mutex))
|
||||
{
|
||||
UnregisterImpl(spaceId, saveDataId);
|
||||
_accessorList.AddLast(cache);
|
||||
}
|
||||
|
||||
_accessorList.AddLast(cache);
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
@ -84,11 +106,9 @@ namespace LibHac.FsSrv.Impl
|
||||
}
|
||||
}
|
||||
|
||||
public Result GetCache(out ReferenceCountedDisposable<ISaveDataExtraDataAccessor> accessor,
|
||||
SaveDataSpaceId spaceId, ulong saveDataId)
|
||||
public Result GetCache(ref SharedRef<ISaveDataExtraDataAccessor> outAccessor, SaveDataSpaceId spaceId,
|
||||
ulong saveDataId)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out accessor);
|
||||
|
||||
using ScopedLock<SdkRecursiveMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
LinkedListNode<Cache> currentNode = _accessorList.First;
|
||||
@ -104,31 +124,18 @@ namespace LibHac.FsSrv.Impl
|
||||
currentNode = currentNode.Next;
|
||||
}
|
||||
|
||||
ReferenceCountedDisposable<ISaveDataExtraDataAccessor> tempAccessor = null;
|
||||
try
|
||||
{
|
||||
tempAccessor = currentNode.ValueRef.Lock();
|
||||
using SharedRef<ISaveDataExtraDataAccessor> accessor = currentNode.ValueRef.Lock();
|
||||
|
||||
// Return early if the accessor was already disposed
|
||||
if (tempAccessor is null)
|
||||
{
|
||||
// Note: Nintendo doesn't remove the accessor from the list in this case
|
||||
_accessorList.Remove(currentNode);
|
||||
return ResultFs.TargetNotFound.Log();
|
||||
}
|
||||
if (!accessor.HasValue)
|
||||
return ResultFs.TargetNotFound.Log();
|
||||
|
||||
accessor = SaveDataExtraDataResultConvertAccessor.CreateShared(ref tempAccessor);
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
tempAccessor?.Dispose();
|
||||
}
|
||||
outAccessor.Reset(new SaveDataExtraDataResultConvertAccessor(ref accessor.Ref()));
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public ScopedLock<SdkRecursiveMutexType> GetScopedLock()
|
||||
public UniqueLockRef<SdkRecursiveMutexType> GetScopedLock()
|
||||
{
|
||||
return new ScopedLock<SdkRecursiveMutexType>(ref _mutex);
|
||||
return new UniqueLockRef<SdkRecursiveMutexType>(ref _mutex);
|
||||
}
|
||||
}
|
||||
}
|
@ -164,22 +164,15 @@ namespace LibHac.FsSrv.Impl
|
||||
/// </summary>
|
||||
public class SaveDataResultConvertFileSystem : IResultConvertFileSystem
|
||||
{
|
||||
public SaveDataResultConvertFileSystem(ref ReferenceCountedDisposable<IFileSystem> baseFileSystem)
|
||||
public SaveDataResultConvertFileSystem(ref SharedRef<IFileSystem> baseFileSystem)
|
||||
: base(ref baseFileSystem)
|
||||
{
|
||||
}
|
||||
|
||||
public static ReferenceCountedDisposable<IFileSystem> CreateShared(
|
||||
ref ReferenceCountedDisposable<IFileSystem> baseFileSystem)
|
||||
{
|
||||
var resultConvertFileSystem = new SaveDataResultConvertFileSystem(ref baseFileSystem);
|
||||
return new ReferenceCountedDisposable<IFileSystem>(resultConvertFileSystem);
|
||||
}
|
||||
|
||||
protected override Result DoOpenFile(ref UniqueRef<IFile> outFile, in Path path, OpenMode mode)
|
||||
{
|
||||
using var file = new UniqueRef<IFile>();
|
||||
Result rc = ConvertResult(BaseFileSystem.Target.OpenFile(ref file.Ref(), path, mode));
|
||||
Result rc = ConvertResult(BaseFileSystem.Get.OpenFile(ref file.Ref(), path, mode));
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
outFile.Reset(new SaveDataResultConvertFile(ref file.Ref()));
|
||||
@ -190,7 +183,7 @@ namespace LibHac.FsSrv.Impl
|
||||
OpenDirectoryMode mode)
|
||||
{
|
||||
using var directory = new UniqueRef<IDirectory>();
|
||||
Result rc = ConvertResult(BaseFileSystem.Target.OpenDirectory(ref directory.Ref(), path, mode));
|
||||
Result rc = ConvertResult(BaseFileSystem.Get.OpenDirectory(ref directory.Ref(), path, mode));
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
outDirectory.Reset(new SaveDataResultConvertDirectory(ref directory.Ref()));
|
||||
@ -209,49 +202,40 @@ namespace LibHac.FsSrv.Impl
|
||||
/// </summary>
|
||||
public class SaveDataExtraDataResultConvertAccessor : ISaveDataExtraDataAccessor
|
||||
{
|
||||
private ReferenceCountedDisposable<ISaveDataExtraDataAccessor> _accessor;
|
||||
private SharedRef<ISaveDataExtraDataAccessor> _accessor;
|
||||
|
||||
public SaveDataExtraDataResultConvertAccessor(
|
||||
ref ReferenceCountedDisposable<ISaveDataExtraDataAccessor> accessor)
|
||||
public SaveDataExtraDataResultConvertAccessor(ref SharedRef<ISaveDataExtraDataAccessor> accessor)
|
||||
{
|
||||
_accessor = Shared.Move(ref accessor);
|
||||
}
|
||||
|
||||
public static ReferenceCountedDisposable<ISaveDataExtraDataAccessor> CreateShared(
|
||||
ref ReferenceCountedDisposable<ISaveDataExtraDataAccessor> accessor)
|
||||
{
|
||||
var resultConvertAccessor = new SaveDataExtraDataResultConvertAccessor(ref accessor);
|
||||
return new ReferenceCountedDisposable<ISaveDataExtraDataAccessor>(resultConvertAccessor);
|
||||
_accessor = SharedRef<ISaveDataExtraDataAccessor>.CreateMove(ref accessor);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_accessor?.Dispose();
|
||||
_accessor = null;
|
||||
_accessor.Destroy();
|
||||
}
|
||||
|
||||
public Result WriteExtraData(in SaveDataExtraData extraData)
|
||||
{
|
||||
Result rc = _accessor.Target.WriteExtraData(in extraData);
|
||||
Result rc = _accessor.Get.WriteExtraData(in extraData);
|
||||
return SaveDataResultConvert.ConvertSaveFsDriverPublicResult(rc);
|
||||
}
|
||||
|
||||
public Result CommitExtraData(bool updateTimeStamp)
|
||||
{
|
||||
Result rc = _accessor.Target.CommitExtraData(updateTimeStamp);
|
||||
Result rc = _accessor.Get.CommitExtraData(updateTimeStamp);
|
||||
return SaveDataResultConvert.ConvertSaveFsDriverPublicResult(rc);
|
||||
}
|
||||
|
||||
public Result ReadExtraData(out SaveDataExtraData extraData)
|
||||
{
|
||||
Result rc = _accessor.Target.ReadExtraData(out extraData);
|
||||
Result rc = _accessor.Get.ReadExtraData(out extraData);
|
||||
return SaveDataResultConvert.ConvertSaveFsDriverPublicResult(rc);
|
||||
}
|
||||
|
||||
public void RegisterCacheObserver(ISaveDataExtraDataAccessorCacheObserver observer, SaveDataSpaceId spaceId,
|
||||
ulong saveDataId)
|
||||
{
|
||||
_accessor.Target.RegisterCacheObserver(observer, spaceId, saveDataId);
|
||||
_accessor.Get.RegisterCacheObserver(observer, spaceId, saveDataId);
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user