mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Add FileStorageBasedFileSystem
This commit is contained in:
parent
3d7ff652e0
commit
31563ad108
7 changed files with 241 additions and 1 deletions
|
@ -45,6 +45,30 @@ namespace LibHac.Common
|
|||
return i;
|
||||
}
|
||||
|
||||
public static int Compare(ReadOnlySpan<byte> s1, ReadOnlySpan<byte> s2)
|
||||
{
|
||||
int maxLen = Math.Min(s1.Length, s2.Length);
|
||||
|
||||
return Compare(s1, s2, maxLen);
|
||||
}
|
||||
|
||||
public static int Compare(ReadOnlySpan<byte> s1, ReadOnlySpan<byte> s2, int maxLen)
|
||||
{
|
||||
for (int i = 0; i < maxLen; i++)
|
||||
{
|
||||
byte c1 = s1[i];
|
||||
byte c2 = s2[i];
|
||||
|
||||
if (c1 != c2)
|
||||
return c1 - c2;
|
||||
|
||||
if (c1 == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Concatenates 2 byte strings.
|
||||
/// </summary>
|
||||
|
|
130
src/LibHac/Fs/FileStorage2.cs
Normal file
130
src/LibHac/Fs/FileStorage2.cs
Normal file
|
@ -0,0 +1,130 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
public class FileStorage2 : StorageBase
|
||||
{
|
||||
private const long InvalidSize = -1;
|
||||
|
||||
private IFile BaseFile { get; set; }
|
||||
private long FileSize { get; set; }
|
||||
|
||||
public FileStorage2(IFile baseFile)
|
||||
{
|
||||
BaseFile = baseFile;
|
||||
FileSize = InvalidSize;
|
||||
}
|
||||
|
||||
protected FileStorage2() { }
|
||||
|
||||
protected void SetFile(IFile file)
|
||||
{
|
||||
Debug.Assert(file != null);
|
||||
Debug.Assert(BaseFile == null);
|
||||
|
||||
BaseFile = file;
|
||||
}
|
||||
|
||||
private Result UpdateSize()
|
||||
{
|
||||
if (FileSize != InvalidSize)
|
||||
return Result.Success;
|
||||
|
||||
Result rc = BaseFile.GetSize(out long fileSize);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
FileSize = fileSize;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result ReadImpl(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.ValueOutOfRange.Log();
|
||||
|
||||
return BaseFile.Read(out _, offset, destination, ReadOption.None);
|
||||
}
|
||||
|
||||
protected override Result WriteImpl(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.ValueOutOfRange.Log();
|
||||
|
||||
return BaseFile.Write(offset, source, WriteOption.None);
|
||||
}
|
||||
|
||||
protected override Result FlushImpl()
|
||||
{
|
||||
return BaseFile.Flush();
|
||||
}
|
||||
|
||||
protected override Result GetSizeImpl(out long size)
|
||||
{
|
||||
Result rc = UpdateSize();
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
size = default;
|
||||
return rc;
|
||||
}
|
||||
|
||||
size = FileSize;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result SetSizeImpl(long size)
|
||||
{
|
||||
FileSize = InvalidSize;
|
||||
return BaseFile.SetSize(size);
|
||||
}
|
||||
|
||||
protected override Result OperateRangeImpl(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.ValueOutOfRange.Log();
|
||||
}
|
||||
|
||||
return BaseFile.OperateRange(outBuffer, operationId, offset, size, inBuffer);
|
||||
|
||||
default:
|
||||
return ResultFs.UnsupportedOperationInFileStorageOperateRange.Log();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
49
src/LibHac/Fs/FileStorageBasedFileSystem.cs
Normal file
49
src/LibHac/Fs/FileStorageBasedFileSystem.cs
Normal file
|
@ -0,0 +1,49 @@
|
|||
namespace LibHac.Fs
|
||||
{
|
||||
public class FileStorageBasedFileSystem : FileStorage2
|
||||
{
|
||||
private IFileSystem BaseFileSystem { get; set; }
|
||||
private IFile BaseFile { get; set; }
|
||||
|
||||
private FileStorageBasedFileSystem() : base() { }
|
||||
|
||||
public static Result CreateNew(out FileStorageBasedFileSystem created, IFileSystem baseFileSystem, string path,
|
||||
OpenMode mode)
|
||||
{
|
||||
var obj = new FileStorageBasedFileSystem();
|
||||
Result rc = obj.Initialize(baseFileSystem, path, mode);
|
||||
|
||||
if (rc.IsSuccess())
|
||||
{
|
||||
created = obj;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
obj.Dispose();
|
||||
created = default;
|
||||
return rc;
|
||||
}
|
||||
|
||||
private Result Initialize(IFileSystem baseFileSystem, string path, OpenMode mode)
|
||||
{
|
||||
Result rc = baseFileSystem.OpenFile(out IFile file, path, mode);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
SetFile(file);
|
||||
BaseFile = file;
|
||||
BaseFileSystem = baseFileSystem;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
BaseFile?.Dispose();
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -95,6 +95,18 @@ namespace LibHac.Fs
|
|||
return ResultFs.PreconditionViolation.Log();
|
||||
}
|
||||
|
||||
if (path == null)
|
||||
{
|
||||
directory = default;
|
||||
return ResultFs.NullArgument.Log();
|
||||
}
|
||||
|
||||
if ((mode & ~OpenDirectoryMode.All) != 0 || (mode & OpenDirectoryMode.All) == 0)
|
||||
{
|
||||
directory = default;
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
|
||||
return OpenDirectoryImpl(out directory, path, mode);
|
||||
}
|
||||
|
||||
|
@ -106,6 +118,18 @@ namespace LibHac.Fs
|
|||
return ResultFs.PreconditionViolation.Log();
|
||||
}
|
||||
|
||||
if (path == null)
|
||||
{
|
||||
file = default;
|
||||
return ResultFs.NullArgument.Log();
|
||||
}
|
||||
|
||||
if ((mode & ~OpenMode.All) != 0 || (mode & OpenMode.ReadWrite) == 0)
|
||||
{
|
||||
file = default;
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
|
||||
return OpenFileImpl(out file, path, mode);
|
||||
}
|
||||
|
||||
|
|
|
@ -122,7 +122,8 @@ namespace LibHac.Fs
|
|||
Read = 1,
|
||||
Write = 2,
|
||||
AllowAppend = 4,
|
||||
ReadWrite = Read | Write
|
||||
ReadWrite = Read | Write,
|
||||
All = Read | Write | AllowAppend
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
|
11
src/LibHac/Fs/QueryRangeInfo.cs
Normal file
11
src/LibHac/Fs/QueryRangeInfo.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Size = 0x40)]
|
||||
public struct QueryRangeInfo
|
||||
{
|
||||
public uint AesCtrKeyType;
|
||||
public uint SpeedEmulationType;
|
||||
}
|
||||
}
|
|
@ -109,6 +109,7 @@
|
|||
public static Result SubStorageNotResizable => new Result(ModuleFs, 6302);
|
||||
public static Result SubStorageNotResizableMiddleOfFile => new Result(ModuleFs, 6303);
|
||||
public static Result UnsupportedOperationInMemoryStorageSetSize => new Result(ModuleFs, 6304);
|
||||
public static Result UnsupportedOperationInFileStorageOperateRange => new Result(ModuleFs, 6306);
|
||||
public static Result UnsupportedOperationInAesCtrExStorageWrite => new Result(ModuleFs, 6310);
|
||||
public static Result UnsupportedOperationInHierarchicalIvfcStorageSetSize => new Result(ModuleFs, 6316);
|
||||
public static Result UnsupportedOperationInIndirectStorageWrite => new Result(ModuleFs, 6324);
|
||||
|
|
Loading…
Reference in a new issue