Update FileStorage for 13.1.0

This commit is contained in:
Alex Barney 2021-12-19 14:07:20 -07:00
parent 634ab59742
commit c4783f4589
3 changed files with 52 additions and 149 deletions

View file

@ -8,6 +8,10 @@ using LibHac.Os;
// ReSharper disable once CheckNamespace
namespace LibHac.Fs;
/// <summary>
/// Allows interacting with an <see cref="IFile"/> via an <see cref="IStorage"/> interface.
/// </summary>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
public class FileStorage : IStorage
{
private const long InvalidSize = -1;
@ -100,18 +104,22 @@ public class FileStorage : IStorage
protected override Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size, ReadOnlySpan<byte> inBuffer)
{
if (operationId == OperationId.InvalidateCache || operationId == OperationId.QueryRange)
if (operationId == OperationId.InvalidateCache)
{
Result rc = _baseFile.OperateRange(OperationId.InvalidateCache, offset, size);
if (rc.IsFailure()) return rc.Miss();
return Result.Success;
}
if (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();
}
if (outBuffer.Length != Unsafe.SizeOf<QueryRangeInfo>())
return ResultFs.InvalidSize.Log();
SpanHelpers.AsStruct<QueryRangeInfo>(outBuffer).Clear();
return Result.Success;
}
@ -140,6 +148,12 @@ public class FileStorage : IStorage
}
}
/// <summary>
/// Opens a file from an <see cref="IFileSystem"/> and allows interacting with it through an
/// <see cref="IStorage"/> interface. The opened file will automatically be closed when the
/// <see cref="FileStorageBasedFileSystem"/> is disposed.
/// </summary>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
public class FileStorageBasedFileSystem : FileStorage
{
private SharedRef<IFileSystem> _baseFileSystem;
@ -153,6 +167,16 @@ public class FileStorageBasedFileSystem : FileStorage
base.Dispose();
}
/// <summary>
/// Initializes this <see cref="FileStorageBasedFileSystem"/> with the file at the specified path.
/// </summary>
/// <param name="baseFileSystem">The <see cref="IFileSystem"/> containing the file to open.</param>
/// <param name="path">The full path of the file to open.</param>
/// <param name="mode">Specifies the access permissions of the opened file.</param>
/// <returns><see cref="Result.Success"/>: The operation was successful.<br/>
/// <see cref="ResultFs.PathNotFound"/>: The specified path does not exist or is a directory.<br/>
/// <see cref="ResultFs.TargetLocked"/>: When opening as <see cref="OpenMode.Write"/>,
/// the file is already opened as <see cref="OpenMode.Write"/>.</returns>
public Result Initialize(ref SharedRef<IFileSystem> baseFileSystem, in Path path, OpenMode mode)
{
using var baseFile = new UniqueRef<IFile>();
@ -168,6 +192,11 @@ public class FileStorageBasedFileSystem : FileStorage
}
}
/// <summary>
/// Provides an <see cref="IStorage"/> interface for interacting with an opened file from a mounted file system.
/// The caller may choose whether or not the file will be closed when the <see cref="FileHandleStorage"/> is disposed.
/// </summary>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
public class FileHandleStorage : IStorage
{
private const long InvalidSize = -1;
@ -177,11 +206,24 @@ public class FileHandleStorage : IStorage
private long _size;
private SdkMutexType _mutex;
// LibHac addition
// LibHac addition because we don't use global state for the FS client
private FileSystemClient _fsClient;
/// <summary>
/// Initializes a new <see cref="FileHandleStorage"/> with the provided <see cref="FileHandle"/>.
/// The file will not be closed when this <see cref="FileHandleStorage"/> is disposed.
/// </summary>
/// <param name="fsClient">The <see cref="FileSystemClient"/> of the provided <see cref="FileHandle"/>.</param>
/// <param name="handle">The handle of the file to use.</param>
public FileHandleStorage(FileSystemClient fsClient, FileHandle handle) : this(fsClient, handle, false) { }
/// <summary>
/// Initializes a new <see cref="FileHandleStorage"/> with the provided <see cref="FileHandle"/>.
/// </summary>
/// <param name="fsClient">The <see cref="FileSystemClient"/> of the provided <see cref="FileHandle"/>.</param>
/// <param name="handle">The handle of the file to use.</param>
/// <param name="closeFile">Should <paramref name="handle"/> be closed when this
/// <see cref="FileHandleStorage"/> is disposed?</param>
public FileHandleStorage(FileSystemClient fsClient, FileHandle handle, bool closeFile)
{
_fsClient = fsClient;
@ -282,4 +324,4 @@ public class FileHandleStorage : IStorage
_size = size;
return Result.Success;
}
}
}

View file

@ -1,98 +0,0 @@
//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();
// 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, 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;
// Result rc = UpdateSize();
// if (rc.IsFailure()) return rc;
// if (!CheckAccessRange(offset, destination.Length, FileSize)) return ResultFs.OutOfRange.Log();
// return FsClient.ReadFile(Handle, offset, destination);
// }
// }
// 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;
// if (!CheckAccessRange(offset, source.Length, FileSize)) return ResultFs.OutOfRange.Log();
// return FsClient.WriteFile(Handle, offset, source, WriteOption.None);
// }
// }
// protected override Result DoFlush()
// {
// return FsClient.FlushFile(Handle);
// }
// protected override Result DoSetSize(long size)
// {
// FileSize = InvalidSize;
// return FsClient.SetFileSize(Handle, size);
// }
// protected override Result DoGetSize(out long size)
// {
// UnsafeHelpers.SkipParamInit(out size);
// Result rc = UpdateSize();
// if (rc.IsFailure()) return rc;
// size = FileSize;
// 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;
// FileSize = fileSize;
// return Result.Success;
// }
// protected override void Dispose(bool disposing)
// {
// if (CloseHandle)
// {
// FsClient.CloseFile(Handle);
// }
// }
// }
//}

View file

@ -1,41 +0,0 @@
//using LibHac.Common;
//using LibHac.Fs.Fsa;
//namespace LibHac.Fs
//{
// public class FileStorageBasedFileSystem : FileStorage2
// {
// private ReferenceCountedDisposable<IFileSystem> _baseFileSystem;
// private UniqueRef<IFile> _baseFile;
// 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.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());
// return Result.Success;
// }
// protected override void Dispose(bool disposing)
// {
// if (disposing)
// {
// _baseFile.Destroy();
// _baseFileSystem?.Dispose();
// }
// base.Dispose(disposing);
// }
// }
//}