mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Remove the old FileBase class
This commit is contained in:
parent
6a449b7da1
commit
fd40b2fd77
15 changed files with 188 additions and 178 deletions
|
@ -3,7 +3,7 @@ using System.Threading;
|
||||||
|
|
||||||
namespace LibHac.Fs
|
namespace LibHac.Fs
|
||||||
{
|
{
|
||||||
public abstract class FileBase2 : IFile
|
public abstract class FileBase : IFile
|
||||||
{
|
{
|
||||||
// 0 = not disposed; 1 = disposed
|
// 0 = not disposed; 1 = disposed
|
||||||
private int _disposedState;
|
private int _disposedState;
|
|
@ -3,7 +3,7 @@
|
||||||
namespace LibHac.FsService
|
namespace LibHac.FsService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Permissions that control which storages or filesystems can be mounted or opened.
|
/// Permissions that control which filesystems or storages can be mounted or opened.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum AccessPermissions
|
public enum AccessPermissions
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,6 +10,7 @@ namespace LibHac.FsSystem
|
||||||
private byte[] KekSeed { get; }
|
private byte[] KekSeed { get; }
|
||||||
private byte[] VerificationKey { get; }
|
private byte[] VerificationKey { get; }
|
||||||
private int BlockSize { get; }
|
private int BlockSize { get; }
|
||||||
|
private OpenMode Mode { get; }
|
||||||
|
|
||||||
private AesXtsFileHeader Header { get; }
|
private AesXtsFileHeader Header { get; }
|
||||||
private IStorage BaseStorage { get; }
|
private IStorage BaseStorage { get; }
|
||||||
|
@ -52,23 +53,31 @@ namespace LibHac.FsSystem
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Read(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
public override Result ReadImpl(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
||||||
{
|
{
|
||||||
bytesRead = default;
|
bytesRead = default;
|
||||||
|
|
||||||
int toRead = ValidateReadParamsAndGetSize(destination, offset);
|
Result rc = ValidateReadParams(out long toRead, offset, destination.Length, Mode);
|
||||||
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
Result rc = BaseStorage.Read(offset, destination.Slice(0, toRead));
|
rc = BaseStorage.Read(offset, destination.Slice(0, (int)toRead));
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Write(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
public override Result WriteImpl(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
||||||
{
|
{
|
||||||
ValidateWriteParams(source, offset);
|
Result rc = ValidateWriteParams(offset, source.Length, Mode, out bool isResizeNeeded);
|
||||||
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
Result rc = BaseStorage.Write(offset, source);
|
if (isResizeNeeded)
|
||||||
|
{
|
||||||
|
rc = SetSizeImpl(offset + source.Length);
|
||||||
|
if (rc.IsFailure()) return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = BaseStorage.Write(offset, source);
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
if ((options & WriteOption.Flush) != 0)
|
if ((options & WriteOption.Flush) != 0)
|
||||||
|
@ -79,18 +88,18 @@ namespace LibHac.FsSystem
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Flush()
|
public override Result FlushImpl()
|
||||||
{
|
{
|
||||||
return BaseStorage.Flush();
|
return BaseStorage.Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result GetSize(out long size)
|
public override Result GetSizeImpl(out long size)
|
||||||
{
|
{
|
||||||
size = Header.Size;
|
size = Header.Size;
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result SetSize(long size)
|
public override Result SetSizeImpl(long size)
|
||||||
{
|
{
|
||||||
Header.SetSize(size, VerificationKey);
|
Header.SetSize(size, VerificationKey);
|
||||||
|
|
||||||
|
@ -99,5 +108,13 @@ namespace LibHac.FsSystem
|
||||||
|
|
||||||
return BaseStorage.SetSize(size);
|
return BaseStorage.SetSize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
BaseFile?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,8 +107,6 @@ namespace LibHac.FsSystem
|
||||||
|
|
||||||
var xtsFile = new AesXtsFile(mode, baseFile, path, KekSource, ValidationKey, BlockSize);
|
var xtsFile = new AesXtsFile(mode, baseFile, path, KekSource, ValidationKey, BlockSize);
|
||||||
|
|
||||||
xtsFile.ToDispose.Add(baseFile);
|
|
||||||
|
|
||||||
file = xtsFile;
|
file = xtsFile;
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace LibHac.FsSystem
|
||||||
private string FilePath { get; }
|
private string FilePath { get; }
|
||||||
private List<IFile> Sources { get; }
|
private List<IFile> Sources { get; }
|
||||||
private long SubFileSize { get; }
|
private long SubFileSize { get; }
|
||||||
|
private OpenMode Mode { get; }
|
||||||
|
|
||||||
internal ConcatenationFile(IFileSystem baseFileSystem, string path, IEnumerable<IFile> sources, long subFileSize, OpenMode mode)
|
internal ConcatenationFile(IFileSystem baseFileSystem, string path, IEnumerable<IFile> sources, long subFileSize, OpenMode mode)
|
||||||
{
|
{
|
||||||
|
@ -30,17 +31,17 @@ namespace LibHac.FsSystem
|
||||||
throw new ArgumentException($"Source file must have size {subFileSize}");
|
throw new ArgumentException($"Source file must have size {subFileSize}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ToDispose.AddRange(Sources);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Read(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
public override Result ReadImpl(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
||||||
{
|
{
|
||||||
bytesRead = default;
|
bytesRead = default;
|
||||||
|
|
||||||
long inPos = offset;
|
long inPos = offset;
|
||||||
int outPos = 0;
|
int outPos = 0;
|
||||||
int remaining = ValidateReadParamsAndGetSize(destination, offset);
|
|
||||||
|
Result rc = ValidateReadParams(out long remaining, offset, destination.Length, Mode);
|
||||||
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
GetSize(out long fileSize).ThrowIfFailure();
|
GetSize(out long fileSize).ThrowIfFailure();
|
||||||
|
|
||||||
|
@ -53,12 +54,12 @@ namespace LibHac.FsSystem
|
||||||
long fileEndOffset = Math.Min((fileIndex + 1) * SubFileSize, fileSize);
|
long fileEndOffset = Math.Min((fileIndex + 1) * SubFileSize, fileSize);
|
||||||
int bytesToRead = (int)Math.Min(fileEndOffset - inPos, remaining);
|
int bytesToRead = (int)Math.Min(fileEndOffset - inPos, remaining);
|
||||||
|
|
||||||
Result rc = file.Read(out long subFileBytesRead, fileOffset, destination.Slice(outPos, bytesToRead), options);
|
rc = file.Read(out long subFileBytesRead, fileOffset, destination.Slice(outPos, bytesToRead), options);
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
outPos += (int)subFileBytesRead;
|
outPos += (int)subFileBytesRead;
|
||||||
inPos += subFileBytesRead;
|
inPos += subFileBytesRead;
|
||||||
remaining -= (int)subFileBytesRead;
|
remaining -= subFileBytesRead;
|
||||||
|
|
||||||
if (bytesRead < bytesToRead) break;
|
if (bytesRead < bytesToRead) break;
|
||||||
}
|
}
|
||||||
|
@ -68,9 +69,10 @@ namespace LibHac.FsSystem
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Write(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
public override Result WriteImpl(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
||||||
{
|
{
|
||||||
ValidateWriteParams(source, offset);
|
Result rc = ValidateWriteParams(offset, source.Length, Mode, out _);
|
||||||
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
int inPos = 0;
|
int inPos = 0;
|
||||||
long outPos = offset;
|
long outPos = offset;
|
||||||
|
@ -87,7 +89,7 @@ namespace LibHac.FsSystem
|
||||||
long fileEndOffset = Math.Min((fileIndex + 1) * SubFileSize, fileSize);
|
long fileEndOffset = Math.Min((fileIndex + 1) * SubFileSize, fileSize);
|
||||||
int bytesToWrite = (int)Math.Min(fileEndOffset - outPos, remaining);
|
int bytesToWrite = (int)Math.Min(fileEndOffset - outPos, remaining);
|
||||||
|
|
||||||
Result rc = file.Write(fileOffset, source.Slice(inPos, bytesToWrite), options);
|
rc = file.Write(fileOffset, source.Slice(inPos, bytesToWrite), options);
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
outPos += bytesToWrite;
|
outPos += bytesToWrite;
|
||||||
|
@ -95,7 +97,7 @@ namespace LibHac.FsSystem
|
||||||
remaining -= bytesToWrite;
|
remaining -= bytesToWrite;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((options & WriteOption.Flush) != 0)
|
if (options.HasFlag(WriteOption.Flush))
|
||||||
{
|
{
|
||||||
return Flush();
|
return Flush();
|
||||||
}
|
}
|
||||||
|
@ -103,7 +105,7 @@ namespace LibHac.FsSystem
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Flush()
|
public override Result FlushImpl()
|
||||||
{
|
{
|
||||||
foreach (IFile file in Sources)
|
foreach (IFile file in Sources)
|
||||||
{
|
{
|
||||||
|
@ -114,7 +116,7 @@ namespace LibHac.FsSystem
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result GetSize(out long size)
|
public override Result GetSizeImpl(out long size)
|
||||||
{
|
{
|
||||||
size = default;
|
size = default;
|
||||||
|
|
||||||
|
@ -129,7 +131,7 @@ namespace LibHac.FsSystem
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result SetSize(long size)
|
public override Result SetSizeImpl(long size)
|
||||||
{
|
{
|
||||||
Result rc = GetSize(out long currentSize);
|
Result rc = GetSize(out long currentSize);
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc;
|
||||||
|
@ -183,6 +185,19 @@ namespace LibHac.FsSystem
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
foreach (IFile file in Sources)
|
||||||
|
{
|
||||||
|
file?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
Sources.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private int GetSubFileIndexFromOffset(long offset)
|
private int GetSubFileIndexFromOffset(long offset)
|
||||||
{
|
{
|
||||||
return (int)(offset / SubFileSize);
|
return (int)(offset / SubFileSize);
|
||||||
|
|
|
@ -3,7 +3,7 @@ using LibHac.Fs;
|
||||||
|
|
||||||
namespace LibHac.FsSystem
|
namespace LibHac.FsSystem
|
||||||
{
|
{
|
||||||
public class DirectorySaveDataFile : FileBase2
|
public class DirectorySaveDataFile : FileBase
|
||||||
{
|
{
|
||||||
private IFile BaseFile { get; }
|
private IFile BaseFile { get; }
|
||||||
private DirectorySaveDataFileSystem ParentFs { get; }
|
private DirectorySaveDataFileSystem ParentFs { get; }
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using LibHac.Fs;
|
|
||||||
|
|
||||||
namespace LibHac.FsSystem
|
|
||||||
{
|
|
||||||
public abstract class FileBase : IFile
|
|
||||||
{
|
|
||||||
protected bool IsDisposed { get; private set; }
|
|
||||||
internal List<IDisposable> ToDispose { get; } = new List<IDisposable>();
|
|
||||||
|
|
||||||
public abstract Result Read(out long bytesRead, long offset, Span<byte> destination, ReadOption options);
|
|
||||||
public abstract Result Write(long offset, ReadOnlySpan<byte> source, WriteOption options);
|
|
||||||
public abstract Result Flush();
|
|
||||||
public abstract Result GetSize(out long size);
|
|
||||||
public abstract Result SetSize(long size);
|
|
||||||
|
|
||||||
public OpenMode Mode { get; protected set; }
|
|
||||||
|
|
||||||
protected int ValidateReadParamsAndGetSize(ReadOnlySpan<byte> span, long offset)
|
|
||||||
{
|
|
||||||
if (IsDisposed) throw new ObjectDisposedException(null);
|
|
||||||
|
|
||||||
if ((Mode & OpenMode.Read) == 0) ThrowHelper.ThrowResult(ResultFs.InvalidOpenModeForRead, "File does not allow reading.");
|
|
||||||
if (span == null) throw new ArgumentNullException(nameof(span));
|
|
||||||
if (offset < 0) ThrowHelper.ThrowResult(ResultFs.ValueOutOfRange, "Offset must be non-negative.");
|
|
||||||
|
|
||||||
Result sizeResult = GetSize(out long fileSize);
|
|
||||||
sizeResult.ThrowIfFailure();
|
|
||||||
|
|
||||||
int size = span.Length;
|
|
||||||
|
|
||||||
if (offset > fileSize) ThrowHelper.ThrowResult(ResultFs.ValueOutOfRange, "Offset must be less than the file size.");
|
|
||||||
|
|
||||||
return (int)Math.Min(fileSize - offset, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void ValidateWriteParams(ReadOnlySpan<byte> span, long offset)
|
|
||||||
{
|
|
||||||
if (IsDisposed) throw new ObjectDisposedException(null);
|
|
||||||
|
|
||||||
if ((Mode & OpenMode.Write) == 0) ThrowHelper.ThrowResult(ResultFs.InvalidOpenModeForWrite, "File does not allow writing.");
|
|
||||||
|
|
||||||
if (span == null) throw new ArgumentNullException(nameof(span));
|
|
||||||
if (offset < 0) ThrowHelper.ThrowResult(ResultFs.ValueOutOfRange, "Offset must be non-negative.");
|
|
||||||
|
|
||||||
Result sizeResult = GetSize(out long fileSize);
|
|
||||||
sizeResult.ThrowIfFailure();
|
|
||||||
|
|
||||||
int size = span.Length;
|
|
||||||
|
|
||||||
if (offset + size > fileSize)
|
|
||||||
{
|
|
||||||
if ((Mode & OpenMode.AllowAppend) == 0)
|
|
||||||
{
|
|
||||||
ThrowHelper.ThrowResult(ResultFs.AllowAppendRequiredForImplicitExtension);
|
|
||||||
}
|
|
||||||
|
|
||||||
SetSize(offset + size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (IsDisposed) return;
|
|
||||||
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
Flush();
|
|
||||||
|
|
||||||
foreach (IDisposable item in ToDispose)
|
|
||||||
{
|
|
||||||
item?.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IsDisposed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,7 +4,7 @@ using LibHac.Fs;
|
||||||
|
|
||||||
namespace LibHac.FsSystem
|
namespace LibHac.FsSystem
|
||||||
{
|
{
|
||||||
public class LocalFile : FileBase2
|
public class LocalFile : FileBase
|
||||||
{
|
{
|
||||||
private const int ErrorHandleDiskFull = unchecked((int)0x80070027);
|
private const int ErrorHandleDiskFull = unchecked((int)0x80070027);
|
||||||
private const int ErrorDiskFull = unchecked((int)0x80070070);
|
private const int ErrorDiskFull = unchecked((int)0x80070070);
|
||||||
|
|
|
@ -5,6 +5,8 @@ namespace LibHac.FsSystem
|
||||||
{
|
{
|
||||||
public class NullFile : FileBase
|
public class NullFile : FileBase
|
||||||
{
|
{
|
||||||
|
private OpenMode Mode { get; }
|
||||||
|
|
||||||
public NullFile()
|
public NullFile()
|
||||||
{
|
{
|
||||||
Mode = OpenMode.ReadWrite;
|
Mode = OpenMode.ReadWrite;
|
||||||
|
@ -14,32 +16,36 @@ namespace LibHac.FsSystem
|
||||||
|
|
||||||
private long Length { get; }
|
private long Length { get; }
|
||||||
|
|
||||||
public override Result Read(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
public override Result ReadImpl(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
||||||
{
|
{
|
||||||
int toRead = ValidateReadParamsAndGetSize(destination, offset);
|
bytesRead = 0;
|
||||||
destination.Slice(0, toRead).Clear();
|
|
||||||
|
Result rc = ValidateReadParams(out long toRead, offset, destination.Length, Mode);
|
||||||
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
|
destination.Slice(0, (int)toRead).Clear();
|
||||||
|
|
||||||
bytesRead = toRead;
|
bytesRead = toRead;
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Write(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
public override Result WriteImpl(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
||||||
{
|
{
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Flush()
|
public override Result FlushImpl()
|
||||||
{
|
{
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result GetSize(out long size)
|
public override Result GetSizeImpl(out long size)
|
||||||
{
|
{
|
||||||
size = Length;
|
size = Length;
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result SetSize(long size)
|
public override Result SetSizeImpl(long size)
|
||||||
{
|
{
|
||||||
return ResultFs.UnsupportedOperation.Log();
|
return ResultFs.UnsupportedOperation.Log();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ namespace LibHac.FsSystem
|
||||||
private IStorage BaseStorage { get; }
|
private IStorage BaseStorage { get; }
|
||||||
private long Offset { get; }
|
private long Offset { get; }
|
||||||
private long Size { get; }
|
private long Size { get; }
|
||||||
|
private OpenMode Mode { get; }
|
||||||
|
|
||||||
public PartitionFile(IStorage baseStorage, long offset, long size, OpenMode mode)
|
public PartitionFile(IStorage baseStorage, long offset, long size, OpenMode mode)
|
||||||
{
|
{
|
||||||
|
@ -17,27 +18,34 @@ namespace LibHac.FsSystem
|
||||||
Size = size;
|
Size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Read(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
public override Result ReadImpl(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
||||||
{
|
{
|
||||||
bytesRead = default;
|
bytesRead = 0;
|
||||||
|
|
||||||
int toRead = ValidateReadParamsAndGetSize(destination, offset);
|
Result rc = ValidateReadParams(out long toRead, offset, destination.Length, Mode);
|
||||||
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
long storageOffset = Offset + offset;
|
long storageOffset = Offset + offset;
|
||||||
BaseStorage.Read(storageOffset, destination.Slice(0, toRead));
|
BaseStorage.Read(storageOffset, destination.Slice(0, (int)toRead));
|
||||||
|
|
||||||
bytesRead = toRead;
|
bytesRead = toRead;
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Write(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
public override Result WriteImpl(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
||||||
{
|
{
|
||||||
ValidateWriteParams(source, offset);
|
Result rc = ValidateWriteParams(offset, source.Length, Mode, out bool isResizeNeeded);
|
||||||
|
|
||||||
Result rc = BaseStorage.Write(offset, source);
|
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
if ((options & WriteOption.Flush) != 0)
|
if (isResizeNeeded) return ResultFs.UnsupportedOperationInPartitionFileSetSize.Log();
|
||||||
|
|
||||||
|
if (offset > Size) return ResultFs.ValueOutOfRange.Log();
|
||||||
|
|
||||||
|
rc = BaseStorage.Write(offset, source);
|
||||||
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
|
// N doesn't flush if the flag is set
|
||||||
|
if (options.HasFlag(WriteOption.Flush))
|
||||||
{
|
{
|
||||||
return BaseStorage.Flush();
|
return BaseStorage.Flush();
|
||||||
}
|
}
|
||||||
|
@ -45,9 +53,9 @@ namespace LibHac.FsSystem
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Flush()
|
public override Result FlushImpl()
|
||||||
{
|
{
|
||||||
if ((Mode & OpenMode.Write) != 0)
|
if (!Mode.HasFlag(OpenMode.Write))
|
||||||
{
|
{
|
||||||
return BaseStorage.Flush();
|
return BaseStorage.Flush();
|
||||||
}
|
}
|
||||||
|
@ -55,14 +63,19 @@ namespace LibHac.FsSystem
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result GetSize(out long size)
|
public override Result GetSizeImpl(out long size)
|
||||||
{
|
{
|
||||||
size = Size;
|
size = Size;
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result SetSize(long size)
|
public override Result SetSizeImpl(long size)
|
||||||
{
|
{
|
||||||
|
if (!Mode.HasFlag(OpenMode.Write))
|
||||||
|
{
|
||||||
|
return ResultFs.InvalidOpenModeForWrite.Log();
|
||||||
|
}
|
||||||
|
|
||||||
return ResultFs.UnsupportedOperationInPartitionFileSetSize.Log();
|
return ResultFs.UnsupportedOperationInPartitionFileSetSize.Log();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,29 +12,29 @@ namespace LibHac.FsSystem
|
||||||
BaseFile = baseFile;
|
BaseFile = baseFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Read(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
public override Result ReadImpl(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
||||||
{
|
{
|
||||||
return BaseFile.Read(out bytesRead, offset, destination, options);
|
return BaseFile.Read(out bytesRead, offset, destination, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result GetSize(out long size)
|
public override Result GetSizeImpl(out long size)
|
||||||
{
|
{
|
||||||
return BaseFile.GetSize(out size);
|
return BaseFile.GetSize(out size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Flush()
|
public override Result FlushImpl()
|
||||||
{
|
{
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Write(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
public override Result WriteImpl(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
||||||
{
|
{
|
||||||
return ResultFs.UnsupportedOperationModifyReadOnlyFile.Log();
|
return ResultFs.InvalidOpenModeForWrite.Log();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result SetSize(long size)
|
public override Result SetSizeImpl(long size)
|
||||||
{
|
{
|
||||||
return ResultFs.UnsupportedOperationModifyReadOnlyFile.Log();
|
return ResultFs.InvalidOpenModeForWrite.Log();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,21 +11,21 @@ namespace LibHac.FsSystem.RomFs
|
||||||
|
|
||||||
public RomFsFile(IStorage baseStorage, long offset, long size)
|
public RomFsFile(IStorage baseStorage, long offset, long size)
|
||||||
{
|
{
|
||||||
Mode = OpenMode.Read;
|
|
||||||
BaseStorage = baseStorage;
|
BaseStorage = baseStorage;
|
||||||
Offset = offset;
|
Offset = offset;
|
||||||
Size = size;
|
Size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Read(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
public override Result ReadImpl(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
||||||
{
|
{
|
||||||
bytesRead = default;
|
bytesRead = default;
|
||||||
|
|
||||||
int toRead = ValidateReadParamsAndGetSize(destination, offset);
|
Result rc = ValidateReadParams(out long toRead, offset, destination.Length, OpenMode.Read);
|
||||||
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
long storageOffset = Offset + offset;
|
long storageOffset = Offset + offset;
|
||||||
|
|
||||||
Result rc = BaseStorage.Read(storageOffset, destination.Slice(0, toRead));
|
rc = BaseStorage.Read(storageOffset, destination.Slice(0, (int)toRead));
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
bytesRead = toRead;
|
bytesRead = toRead;
|
||||||
|
@ -33,23 +33,23 @@ namespace LibHac.FsSystem.RomFs
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Write(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
public override Result WriteImpl(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
||||||
{
|
{
|
||||||
return ResultFs.UnsupportedOperationModifyRomFsFile.Log();
|
return ResultFs.UnsupportedOperationModifyRomFsFile.Log();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Flush()
|
public override Result FlushImpl()
|
||||||
{
|
{
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result GetSize(out long size)
|
public override Result GetSizeImpl(out long size)
|
||||||
{
|
{
|
||||||
size = Size;
|
size = Size;
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result SetSize(long size)
|
public override Result SetSizeImpl(long size)
|
||||||
{
|
{
|
||||||
return ResultFs.UnsupportedOperationModifyRomFsFile.Log();
|
return ResultFs.UnsupportedOperationModifyRomFsFile.Log();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ namespace LibHac.FsSystem.Save
|
||||||
private string Path { get; }
|
private string Path { get; }
|
||||||
private HierarchicalSaveFileTable FileTable { get; }
|
private HierarchicalSaveFileTable FileTable { get; }
|
||||||
private long Size { get; set; }
|
private long Size { get; set; }
|
||||||
|
private OpenMode Mode { get; }
|
||||||
|
|
||||||
public SaveDataFile(AllocationTableStorage baseStorage, string path, HierarchicalSaveFileTable fileTable, long size, OpenMode mode)
|
public SaveDataFile(AllocationTableStorage baseStorage, string path, HierarchicalSaveFileTable fileTable, long size, OpenMode mode)
|
||||||
{
|
{
|
||||||
|
@ -20,22 +21,36 @@ namespace LibHac.FsSystem.Save
|
||||||
Size = size;
|
Size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Read(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
public override Result ReadImpl(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
||||||
{
|
{
|
||||||
bytesRead = default;
|
bytesRead = default;
|
||||||
|
|
||||||
int toRead = ValidateReadParamsAndGetSize(destination, offset);
|
Result rc = ValidateReadParams(out long toRead, offset, destination.Length, Mode);
|
||||||
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
Result rc = BaseStorage.Read(offset, destination.Slice(0, toRead));
|
if (toRead == 0)
|
||||||
|
{
|
||||||
|
bytesRead = 0;
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = BaseStorage.Read(offset, destination.Slice(0, (int)toRead));
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
bytesRead = toRead;
|
bytesRead = toRead;
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Write(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
public override Result WriteImpl(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
||||||
{
|
{
|
||||||
ValidateWriteParams(source, offset);
|
Result rc = ValidateWriteParams(offset, source.Length, Mode, out bool isResizeNeeded);
|
||||||
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
|
if (isResizeNeeded)
|
||||||
|
{
|
||||||
|
rc = SetSizeImpl(offset + source.Length);
|
||||||
|
if (rc.IsFailure()) return rc;
|
||||||
|
}
|
||||||
|
|
||||||
BaseStorage.Write(offset, source);
|
BaseStorage.Write(offset, source);
|
||||||
|
|
||||||
|
@ -47,18 +62,18 @@ namespace LibHac.FsSystem.Save
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Flush()
|
public override Result FlushImpl()
|
||||||
{
|
{
|
||||||
return BaseStorage.Flush();
|
return BaseStorage.Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result GetSize(out long size)
|
public override Result GetSizeImpl(out long size)
|
||||||
{
|
{
|
||||||
size = Size;
|
size = Size;
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result SetSize(long size)
|
public override Result SetSizeImpl(long size)
|
||||||
{
|
{
|
||||||
if (size < 0) throw new ArgumentOutOfRangeException(nameof(size));
|
if (size < 0) throw new ArgumentOutOfRangeException(nameof(size));
|
||||||
if (Size == size) return Result.Success;
|
if (Size == size) return Result.Success;
|
||||||
|
|
|
@ -6,6 +6,7 @@ namespace LibHac.FsSystem
|
||||||
public class StorageFile : FileBase
|
public class StorageFile : FileBase
|
||||||
{
|
{
|
||||||
private IStorage BaseStorage { get; }
|
private IStorage BaseStorage { get; }
|
||||||
|
private OpenMode Mode { get; }
|
||||||
|
|
||||||
public StorageFile(IStorage baseStorage, OpenMode mode)
|
public StorageFile(IStorage baseStorage, OpenMode mode)
|
||||||
{
|
{
|
||||||
|
@ -13,26 +14,41 @@ namespace LibHac.FsSystem
|
||||||
Mode = mode;
|
Mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Read(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
public override Result ReadImpl(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
||||||
{
|
{
|
||||||
bytesRead = default;
|
bytesRead = default;
|
||||||
int toRead = ValidateReadParamsAndGetSize(destination, offset);
|
|
||||||
|
|
||||||
Result rc = BaseStorage.Read(offset, destination.Slice(0, toRead));
|
Result rc = ValidateReadParams(out long toRead, offset, destination.Length, Mode);
|
||||||
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
|
if (toRead == 0)
|
||||||
|
{
|
||||||
|
bytesRead = 0;
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = BaseStorage.Read(offset, destination.Slice(0, (int)toRead));
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
bytesRead = toRead;
|
bytesRead = toRead;
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Write(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
public override Result WriteImpl(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
||||||
{
|
{
|
||||||
ValidateWriteParams(source, offset);
|
Result rc = ValidateWriteParams(offset, source.Length, Mode, out bool isResizeNeeded);
|
||||||
|
|
||||||
Result rc = BaseStorage.Write(offset, source);
|
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
if ((options & WriteOption.Flush) != 0)
|
if (isResizeNeeded)
|
||||||
|
{
|
||||||
|
rc = SetSizeImpl(offset + source.Length);
|
||||||
|
if (rc.IsFailure()) return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = BaseStorage.Write(offset, source);
|
||||||
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
|
if (options.HasFlag(WriteOption.Flush))
|
||||||
{
|
{
|
||||||
return Flush();
|
return Flush();
|
||||||
}
|
}
|
||||||
|
@ -40,18 +56,24 @@ namespace LibHac.FsSystem
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Flush()
|
public override Result FlushImpl()
|
||||||
{
|
{
|
||||||
|
if (!Mode.HasFlag(OpenMode.Write))
|
||||||
|
return Result.Success;
|
||||||
|
|
||||||
return BaseStorage.Flush();
|
return BaseStorage.Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result GetSize(out long size)
|
public override Result GetSizeImpl(out long size)
|
||||||
{
|
{
|
||||||
return BaseStorage.GetSize(out size);
|
return BaseStorage.GetSize(out size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result SetSize(long size)
|
public override Result SetSizeImpl(long size)
|
||||||
{
|
{
|
||||||
|
if (!Mode.HasFlag(OpenMode.Write))
|
||||||
|
return ResultFs.InvalidOpenModeForWrite.Log();
|
||||||
|
|
||||||
return BaseStorage.SetSize(size);
|
return BaseStorage.SetSize(size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using LibHac.Fs;
|
using LibHac.Fs;
|
||||||
|
|
||||||
#if !STREAM_SPAN
|
#if !STREAM_SPAN
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
#endif
|
#endif
|
||||||
|
@ -14,6 +15,7 @@ namespace LibHac.FsSystem
|
||||||
{
|
{
|
||||||
// todo: handle Stream exceptions
|
// todo: handle Stream exceptions
|
||||||
|
|
||||||
|
private OpenMode Mode { get; }
|
||||||
private Stream BaseStream { get; }
|
private Stream BaseStream { get; }
|
||||||
private object Locker { get; } = new object();
|
private object Locker { get; } = new object();
|
||||||
|
|
||||||
|
@ -23,8 +25,13 @@ namespace LibHac.FsSystem
|
||||||
Mode = mode;
|
Mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Read(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
public override Result ReadImpl(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
||||||
{
|
{
|
||||||
|
bytesRead = default;
|
||||||
|
|
||||||
|
Result rc = ValidateReadParams(out long toRead, offset, destination.Length, Mode);
|
||||||
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
#if STREAM_SPAN
|
#if STREAM_SPAN
|
||||||
lock (Locker)
|
lock (Locker)
|
||||||
{
|
{
|
||||||
|
@ -33,11 +40,11 @@ namespace LibHac.FsSystem
|
||||||
BaseStream.Position = offset;
|
BaseStream.Position = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
bytesRead = BaseStream.Read(destination);
|
bytesRead = BaseStream.Read(destination.Slice(0, (int)toRead));
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(destination.Length);
|
byte[] buffer = ArrayPool<byte>.Shared.Rent((int)toRead);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
lock (Locker)
|
lock (Locker)
|
||||||
|
@ -47,10 +54,10 @@ namespace LibHac.FsSystem
|
||||||
BaseStream.Position = offset;
|
BaseStream.Position = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
bytesRead = BaseStream.Read(buffer, 0, destination.Length);
|
bytesRead = BaseStream.Read(buffer, 0, (int)toRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
new Span<byte>(buffer, 0, destination.Length).CopyTo(destination);
|
new Span<byte>(buffer, 0, (int)bytesRead).CopyTo(destination);
|
||||||
|
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
@ -58,8 +65,11 @@ namespace LibHac.FsSystem
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Write(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
public override Result WriteImpl(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
||||||
{
|
{
|
||||||
|
Result rc = ValidateWriteParams(offset, source.Length, Mode, out _);
|
||||||
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
#if STREAM_SPAN
|
#if STREAM_SPAN
|
||||||
lock (Locker)
|
lock (Locker)
|
||||||
{
|
{
|
||||||
|
@ -81,7 +91,7 @@ namespace LibHac.FsSystem
|
||||||
finally { ArrayPool<byte>.Shared.Return(buffer); }
|
finally { ArrayPool<byte>.Shared.Return(buffer); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((options & WriteOption.Flush) != 0)
|
if (options.HasFlag(WriteOption.Flush))
|
||||||
{
|
{
|
||||||
return Flush();
|
return Flush();
|
||||||
}
|
}
|
||||||
|
@ -89,7 +99,7 @@ namespace LibHac.FsSystem
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result Flush()
|
public override Result FlushImpl()
|
||||||
{
|
{
|
||||||
lock (Locker)
|
lock (Locker)
|
||||||
{
|
{
|
||||||
|
@ -98,7 +108,7 @@ namespace LibHac.FsSystem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result GetSize(out long size)
|
public override Result GetSizeImpl(out long size)
|
||||||
{
|
{
|
||||||
lock (Locker)
|
lock (Locker)
|
||||||
{
|
{
|
||||||
|
@ -107,7 +117,7 @@ namespace LibHac.FsSystem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Result SetSize(long size)
|
public override Result SetSizeImpl(long size)
|
||||||
{
|
{
|
||||||
lock (Locker)
|
lock (Locker)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue