mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2025-02-09 13:14:46 +01:00
Merge pull request #146 from Thealexbarney/fs-classes
Change the file system accessor interfaces to abstract classes
This commit is contained in:
commit
9ec00eed3b
@ -169,6 +169,8 @@ Module,DescriptionStart,DescriptionEnd,Name,Summary
|
||||
2,6069,,InvalidCacheStorageSize,
|
||||
2,6070,,InvalidCacheStorageIndex,
|
||||
2,6071,,InvalidCommitNameCount,Up to 10 file systems can be committed at the same time.
|
||||
2,6072,,InvalidOpenMode,
|
||||
2,6074,,InvalidDirectoryOpenMode,
|
||||
|
||||
2,6080,6099,InvalidEnumValue,
|
||||
2,6081,,InvalidSaveDataState,
|
||||
@ -198,6 +200,7 @@ Module,DescriptionStart,DescriptionEnd,Name,Summary
|
||||
2,6369,,UnsupportedOperationModifyReadOnlyFileSystem,
|
||||
2,6371,,UnsupportedOperationReadOnlyFileSystemGetSpace,
|
||||
2,6372,,UnsupportedOperationModifyReadOnlyFile,
|
||||
2,6373,,UnsupportedOperationInReadOnlyFile,
|
||||
2,6374,,UnsupportedOperationModifyPartitionFileSystem,
|
||||
2,6375,,UnsupportedOperationInPartitionFileSystem,Called PartitionFileSystemCore::CommitProvisionally.
|
||||
2,6376,,UnsupportedOperationInPartitionFileSetSize,
|
||||
|
Can't render this file because it has a wrong number of fields in line 136.
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.Fs.Accessors
|
||||
{
|
||||
|
@ -1,8 +1,9 @@
|
||||
using System;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.Fs.Accessors
|
||||
{
|
||||
public class FileAccessor : FileBase
|
||||
public class FileAccessor : IFile
|
||||
{
|
||||
private IFile File { get; set; }
|
||||
|
||||
@ -17,35 +18,36 @@ namespace LibHac.Fs.Accessors
|
||||
OpenMode = mode;
|
||||
}
|
||||
|
||||
protected override Result ReadImpl(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
||||
protected override Result DoRead(out long bytesRead, long offset, Span<byte> destination,
|
||||
in ReadOption option)
|
||||
{
|
||||
CheckIfDisposed();
|
||||
|
||||
return File.Read(out bytesRead, offset, destination, options);
|
||||
return File.Read(out bytesRead, offset, destination, in option);
|
||||
}
|
||||
|
||||
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source, in WriteOption option)
|
||||
{
|
||||
CheckIfDisposed();
|
||||
|
||||
if (source.Length == 0)
|
||||
{
|
||||
WriteState = (WriteState)(~options & WriteOption.Flush);
|
||||
WriteState = (WriteState)(~option.Flags & WriteOptionFlag.Flush);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
Result rc = File.Write(offset, source, options);
|
||||
Result rc = File.Write(offset, source, in option);
|
||||
|
||||
if (rc.IsSuccess())
|
||||
{
|
||||
WriteState = (WriteState)(~options & WriteOption.Flush);
|
||||
WriteState = (WriteState)(~option.Flags & WriteOptionFlag.Flush);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
protected override Result FlushImpl()
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
CheckIfDisposed();
|
||||
|
||||
@ -59,14 +61,19 @@ namespace LibHac.Fs.Accessors
|
||||
return rc;
|
||||
}
|
||||
|
||||
protected override Result GetSizeImpl(out long size)
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
CheckIfDisposed();
|
||||
|
||||
return File.GetSize(out size);
|
||||
}
|
||||
|
||||
protected override Result SetSizeImpl(long size)
|
||||
protected override Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size, ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
CheckIfDisposed();
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.Fs.Accessors
|
||||
{
|
||||
|
@ -1,48 +0,0 @@
|
||||
using LibHac.Common;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
public abstract class AttributeFileSystemBase : FileSystemBase, IAttributeFileSystem
|
||||
{
|
||||
protected abstract Result CreateDirectoryImpl(U8Span path, NxFileAttributes archiveAttribute);
|
||||
protected abstract Result GetFileAttributesImpl(out NxFileAttributes attributes, U8Span path);
|
||||
protected abstract Result SetFileAttributesImpl(U8Span path, NxFileAttributes attributes);
|
||||
protected abstract Result GetFileSizeImpl(out long fileSize, U8Span path);
|
||||
|
||||
public Result CreateDirectory(U8Span path, NxFileAttributes archiveAttribute)
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return CreateDirectoryImpl(path, archiveAttribute);
|
||||
}
|
||||
|
||||
public Result GetFileAttributes(out NxFileAttributes attributes, U8Span path)
|
||||
{
|
||||
if (IsDisposed)
|
||||
{
|
||||
attributes = default;
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
}
|
||||
|
||||
return GetFileAttributesImpl(out attributes, path);
|
||||
}
|
||||
|
||||
public Result SetFileAttributes(U8Span path, NxFileAttributes attributes)
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return SetFileAttributesImpl(path, attributes);
|
||||
}
|
||||
|
||||
public Result GetFileSize(out long fileSize, U8Span path)
|
||||
{
|
||||
if (IsDisposed)
|
||||
{
|
||||
fileSize = default;
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
}
|
||||
|
||||
return GetFileSizeImpl(out fileSize, path);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,150 +0,0 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
public abstract class FileBase : IFile
|
||||
{
|
||||
// 0 = not disposed; 1 = disposed
|
||||
private int _disposedState;
|
||||
private bool IsDisposed => _disposedState != 0;
|
||||
|
||||
protected abstract Result ReadImpl(out long bytesRead, long offset, Span<byte> destination, ReadOption options);
|
||||
protected abstract Result WriteImpl(long offset, ReadOnlySpan<byte> source, WriteOption options);
|
||||
protected abstract Result FlushImpl();
|
||||
protected abstract Result SetSizeImpl(long size);
|
||||
protected abstract Result GetSizeImpl(out long size);
|
||||
|
||||
protected virtual Result OperateRangeImpl(Span<byte> outBuffer, OperationId operationId, long offset, long size,
|
||||
ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
public Result Read(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
||||
{
|
||||
bytesRead = default;
|
||||
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
if (destination.Length == 0) return Result.Success;
|
||||
if (offset < 0) return ResultFs.OutOfRange.Log();
|
||||
if (long.MaxValue - offset < destination.Length) return ResultFs.OutOfRange.Log();
|
||||
|
||||
return ReadImpl(out bytesRead, offset, destination, options);
|
||||
}
|
||||
|
||||
public Result Write(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
if (source.Length == 0)
|
||||
{
|
||||
if (options.HasFlag(WriteOption.Flush))
|
||||
{
|
||||
return FlushImpl();
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
if (offset < 0) return ResultFs.OutOfRange.Log();
|
||||
if (long.MaxValue - offset < source.Length) return ResultFs.OutOfRange.Log();
|
||||
|
||||
return WriteImpl(offset, source, options);
|
||||
}
|
||||
|
||||
public Result Flush()
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return FlushImpl();
|
||||
}
|
||||
|
||||
public Result SetSize(long size)
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
if (size < 0) return ResultFs.OutOfRange.Log();
|
||||
|
||||
return SetSizeImpl(size);
|
||||
}
|
||||
|
||||
public Result GetSize(out long size)
|
||||
{
|
||||
if (IsDisposed)
|
||||
{
|
||||
size = default;
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
}
|
||||
|
||||
return GetSizeImpl(out size);
|
||||
}
|
||||
|
||||
public Result OperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size,
|
||||
ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return OperateRangeImpl(outBuffer, operationId, offset, size, inBuffer);
|
||||
}
|
||||
|
||||
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) { }
|
||||
|
||||
protected Result ValidateReadParams(out long bytesToRead, long offset, int size, OpenMode openMode)
|
||||
{
|
||||
bytesToRead = default;
|
||||
|
||||
if (!openMode.HasFlag(OpenMode.Read))
|
||||
{
|
||||
return ResultFs.InvalidOpenModeForRead.Log();
|
||||
}
|
||||
|
||||
Result rc = GetSize(out long fileSize);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (offset > fileSize)
|
||||
{
|
||||
return ResultFs.OutOfRange.Log();
|
||||
}
|
||||
|
||||
bytesToRead = Math.Min(fileSize - offset, size);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected Result ValidateWriteParams(long offset, int size, OpenMode openMode, out bool isResizeNeeded)
|
||||
{
|
||||
isResizeNeeded = false;
|
||||
|
||||
if (!openMode.HasFlag(OpenMode.Write))
|
||||
{
|
||||
return ResultFs.InvalidOpenModeForWrite.Log();
|
||||
}
|
||||
|
||||
Result rc = GetSize(out long fileSize);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (offset + size > fileSize)
|
||||
{
|
||||
isResizeNeeded = true;
|
||||
|
||||
if (!openMode.HasFlag(OpenMode.AllowAppend))
|
||||
{
|
||||
return ResultFs.FileExtensionWithoutOpenModeAllowAppend.Log();
|
||||
}
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
public class FileHandleStorage : StorageBase
|
||||
public class FileHandleStorage : IStorage
|
||||
{
|
||||
private const long InvalidSize = -1;
|
||||
private readonly object _locker = new object();
|
||||
@ -21,7 +21,7 @@ namespace LibHac.Fs
|
||||
FsClient = Handle.File.Parent.FsClient;
|
||||
}
|
||||
|
||||
protected override Result ReadImpl(long offset, Span<byte> destination)
|
||||
protected override Result DoRead(long offset, Span<byte> destination)
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
@ -36,7 +36,7 @@ namespace LibHac.Fs
|
||||
}
|
||||
}
|
||||
|
||||
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
@ -51,19 +51,19 @@ namespace LibHac.Fs
|
||||
}
|
||||
}
|
||||
|
||||
protected override Result FlushImpl()
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return FsClient.FlushFile(Handle);
|
||||
}
|
||||
|
||||
protected override Result SetSizeImpl(long size)
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
FileSize = InvalidSize;
|
||||
|
||||
return FsClient.SetFileSize(Handle, size);
|
||||
}
|
||||
|
||||
protected override Result GetSizeImpl(out long size)
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
size = default;
|
||||
|
||||
|
@ -1,10 +1,11 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
public class FileStorage2 : StorageBase
|
||||
public class FileStorage2 : IStorage
|
||||
{
|
||||
protected const long SizeNotInitialized = -1;
|
||||
|
||||
@ -39,7 +40,7 @@ namespace LibHac.Fs
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result ReadImpl(long offset, Span<byte> destination)
|
||||
protected override Result DoRead(long offset, Span<byte> destination)
|
||||
{
|
||||
if (destination.Length == 0)
|
||||
return Result.Success;
|
||||
@ -53,7 +54,7 @@ namespace LibHac.Fs
|
||||
return BaseFile.Read(out _, offset, destination, ReadOption.None);
|
||||
}
|
||||
|
||||
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
if (source.Length == 0)
|
||||
return Result.Success;
|
||||
@ -67,12 +68,12 @@ namespace LibHac.Fs
|
||||
return BaseFile.Write(offset, source, WriteOption.None);
|
||||
}
|
||||
|
||||
protected override Result FlushImpl()
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return BaseFile.Flush();
|
||||
}
|
||||
|
||||
protected override Result GetSizeImpl(out long size)
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
Result rc = UpdateSize();
|
||||
if (rc.IsFailure())
|
||||
@ -85,13 +86,13 @@ namespace LibHac.Fs
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result SetSizeImpl(long size)
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
FileSize = SizeNotInitialized;
|
||||
return BaseFile.SetSize(size);
|
||||
}
|
||||
|
||||
protected override Result OperateRangeImpl(Span<byte> outBuffer, OperationId operationId, long offset, long size, ReadOnlySpan<byte> inBuffer)
|
||||
protected override Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size, ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
switch (operationId)
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
|
@ -1,258 +0,0 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using LibHac.Common;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
public abstract class FileSystemBase : IFileSystem
|
||||
{
|
||||
// 0 = not disposed; 1 = disposed
|
||||
private int _disposedState;
|
||||
protected bool IsDisposed => _disposedState != 0;
|
||||
|
||||
protected abstract Result CreateDirectoryImpl(U8Span path);
|
||||
protected abstract Result CreateFileImpl(U8Span path, long size, CreateFileOptions options);
|
||||
protected abstract Result DeleteDirectoryImpl(U8Span path);
|
||||
protected abstract Result DeleteDirectoryRecursivelyImpl(U8Span path);
|
||||
protected abstract Result CleanDirectoryRecursivelyImpl(U8Span path);
|
||||
protected abstract Result DeleteFileImpl(U8Span path);
|
||||
protected abstract Result OpenDirectoryImpl(out IDirectory directory, U8Span path, OpenDirectoryMode mode);
|
||||
protected abstract Result OpenFileImpl(out IFile file, U8Span path, OpenMode mode);
|
||||
protected abstract Result RenameDirectoryImpl(U8Span oldPath, U8Span newPath);
|
||||
protected abstract Result RenameFileImpl(U8Span oldPath, U8Span newPath);
|
||||
protected abstract Result GetEntryTypeImpl(out DirectoryEntryType entryType, U8Span path);
|
||||
protected abstract Result CommitImpl();
|
||||
|
||||
protected virtual Result GetFreeSpaceSizeImpl(out long freeSpace, U8Span path)
|
||||
{
|
||||
freeSpace = default;
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
protected virtual Result GetTotalSpaceSizeImpl(out long totalSpace, U8Span path)
|
||||
{
|
||||
totalSpace = default;
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
protected virtual Result CommitProvisionallyImpl(long commitCount)
|
||||
{
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
protected virtual Result RollbackImpl()
|
||||
{
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
protected virtual Result FlushImpl()
|
||||
{
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
protected virtual Result GetFileTimeStampRawImpl(out FileTimeStampRaw timeStamp, U8Span path)
|
||||
{
|
||||
timeStamp = default;
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
protected virtual Result QueryEntryImpl(Span<byte> outBuffer, ReadOnlySpan<byte> inBuffer, QueryId queryId,
|
||||
U8Span path)
|
||||
{
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
public Result CreateDirectory(U8Span path)
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return CreateDirectoryImpl(path);
|
||||
}
|
||||
|
||||
public Result CreateFile(U8Span path, long size, CreateFileOptions options)
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return CreateFileImpl(path, size, options);
|
||||
}
|
||||
|
||||
public Result DeleteDirectory(U8Span path)
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return DeleteDirectoryImpl(path);
|
||||
}
|
||||
|
||||
public Result DeleteDirectoryRecursively(U8Span path)
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return DeleteDirectoryRecursivelyImpl(path);
|
||||
}
|
||||
|
||||
public Result CleanDirectoryRecursively(U8Span path)
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return CleanDirectoryRecursivelyImpl(path);
|
||||
}
|
||||
|
||||
public Result DeleteFile(U8Span path)
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return DeleteFileImpl(path);
|
||||
}
|
||||
|
||||
public Result OpenDirectory(out IDirectory directory, U8Span path, OpenDirectoryMode mode)
|
||||
{
|
||||
if (IsDisposed)
|
||||
{
|
||||
directory = default;
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
}
|
||||
|
||||
if (path.IsNull())
|
||||
{
|
||||
directory = default;
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
}
|
||||
|
||||
if ((mode & ~OpenDirectoryMode.All) != 0 || (mode & OpenDirectoryMode.All) == 0)
|
||||
{
|
||||
directory = default;
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
|
||||
return OpenDirectoryImpl(out directory, path, mode);
|
||||
}
|
||||
|
||||
public Result OpenFile(out IFile file, U8Span path, OpenMode mode)
|
||||
{
|
||||
if (IsDisposed)
|
||||
{
|
||||
file = default;
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
}
|
||||
|
||||
if (path.IsNull())
|
||||
{
|
||||
file = default;
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
}
|
||||
|
||||
if ((mode & ~OpenMode.All) != 0 || (mode & OpenMode.ReadWrite) == 0)
|
||||
{
|
||||
file = default;
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
|
||||
return OpenFileImpl(out file, path, mode);
|
||||
}
|
||||
|
||||
public Result RenameDirectory(U8Span oldPath, U8Span newPath)
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return RenameDirectoryImpl(oldPath, newPath);
|
||||
}
|
||||
|
||||
public Result RenameFile(U8Span oldPath, U8Span newPath)
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return RenameFileImpl(oldPath, newPath);
|
||||
}
|
||||
|
||||
public Result GetEntryType(out DirectoryEntryType entryType, U8Span path)
|
||||
{
|
||||
if (IsDisposed)
|
||||
{
|
||||
entryType = default;
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
}
|
||||
|
||||
return GetEntryTypeImpl(out entryType, path);
|
||||
}
|
||||
|
||||
public Result GetFreeSpaceSize(out long freeSpace, U8Span path)
|
||||
{
|
||||
if (IsDisposed)
|
||||
{
|
||||
freeSpace = default;
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
}
|
||||
|
||||
return GetFreeSpaceSizeImpl(out freeSpace, path);
|
||||
}
|
||||
|
||||
public Result GetTotalSpaceSize(out long totalSpace, U8Span path)
|
||||
{
|
||||
if (IsDisposed)
|
||||
{
|
||||
totalSpace = default;
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
}
|
||||
|
||||
return GetTotalSpaceSizeImpl(out totalSpace, path);
|
||||
}
|
||||
|
||||
public Result GetFileTimeStampRaw(out FileTimeStampRaw timeStamp, U8Span path)
|
||||
{
|
||||
if (IsDisposed)
|
||||
{
|
||||
timeStamp = default;
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
}
|
||||
|
||||
return GetFileTimeStampRawImpl(out timeStamp, path);
|
||||
}
|
||||
|
||||
public Result Commit()
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return CommitImpl();
|
||||
}
|
||||
|
||||
public Result CommitProvisionally(long commitCount)
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return CommitProvisionallyImpl(commitCount);
|
||||
}
|
||||
|
||||
public Result Rollback()
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return RollbackImpl();
|
||||
}
|
||||
|
||||
public Result Flush()
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return FlushImpl();
|
||||
}
|
||||
|
||||
public Result QueryEntry(Span<byte> outBuffer, ReadOnlySpan<byte> inBuffer, QueryId queryId, U8Span path)
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return QueryEntryImpl(outBuffer, inBuffer, queryId, path);
|
||||
}
|
||||
|
||||
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) { }
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@ namespace LibHac.Fs
|
||||
return ReadFile(handle, offset, destination, ReadOption.None);
|
||||
}
|
||||
|
||||
public Result ReadFile(FileHandle handle, long offset, Span<byte> destination, ReadOption option)
|
||||
public Result ReadFile(FileHandle handle, long offset, Span<byte> destination, in ReadOption option)
|
||||
{
|
||||
Result rc = ReadFile(out long bytesRead, handle, offset, destination, option);
|
||||
if (rc.IsFailure()) return rc;
|
||||
@ -24,21 +24,21 @@ namespace LibHac.Fs
|
||||
return ReadFile(out bytesRead, handle, offset, destination, ReadOption.None);
|
||||
}
|
||||
|
||||
public Result ReadFile(out long bytesRead, FileHandle handle, long offset, Span<byte> destination, ReadOption option)
|
||||
public Result ReadFile(out long bytesRead, FileHandle handle, long offset, Span<byte> destination, in ReadOption option)
|
||||
{
|
||||
Result rc;
|
||||
|
||||
if (IsEnabledAccessLog() && IsEnabledHandleAccessLog(handle))
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = handle.File.Read(out bytesRead, offset, destination, option);
|
||||
rc = handle.File.Read(out bytesRead, offset, destination, in option);
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, handle, $", offset: {offset}, size: {destination.Length}");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = handle.File.Read(out bytesRead, offset, destination, option);
|
||||
rc = handle.File.Read(out bytesRead, offset, destination, in option);
|
||||
}
|
||||
|
||||
return rc;
|
||||
@ -49,23 +49,23 @@ namespace LibHac.Fs
|
||||
return WriteFile(handle, offset, source, WriteOption.None);
|
||||
}
|
||||
|
||||
public Result WriteFile(FileHandle handle, long offset, ReadOnlySpan<byte> source, WriteOption option)
|
||||
public Result WriteFile(FileHandle handle, long offset, ReadOnlySpan<byte> source, in WriteOption option)
|
||||
{
|
||||
Result rc;
|
||||
|
||||
if (IsEnabledAccessLog() && IsEnabledHandleAccessLog(handle))
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = handle.File.Write(offset, source, option);
|
||||
rc = handle.File.Write(offset, source, in option);
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
string optionString = (option & WriteOption.Flush) == 0 ? "" : $", write_option: {option}";
|
||||
string optionString = option.HasFlushFlag() ? "" : $", write_option: {option}";
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, handle, $", offset: {offset}, size: {source.Length}{optionString}");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = handle.File.Write(offset, source, option);
|
||||
rc = handle.File.Write(offset, source, in option);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Accessors;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
|
@ -3,6 +3,7 @@ using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Accessors;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsService;
|
||||
using LibHac.FsSystem;
|
||||
|
||||
|
@ -3,6 +3,7 @@ using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Accessors;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSystem;
|
||||
|
||||
namespace LibHac.Fs
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
@ -127,18 +128,11 @@ namespace LibHac.Fs
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ReadOption
|
||||
public enum ReadOptionFlag
|
||||
{
|
||||
None = 0
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum WriteOption
|
||||
{
|
||||
None = 0,
|
||||
Flush = 1
|
||||
}
|
||||
|
||||
public enum OperationId
|
||||
{
|
||||
Clear = 0,
|
||||
|
51
src/LibHac/Fs/Fsa/IAttributeFileSystem.cs
Normal file
51
src/LibHac/Fs/Fsa/IAttributeFileSystem.cs
Normal file
@ -0,0 +1,51 @@
|
||||
using LibHac.Common;
|
||||
|
||||
namespace LibHac.Fs.Fsa
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public abstract class IAttributeFileSystem : IFileSystem
|
||||
{
|
||||
public Result CreateDirectory(U8Span path, NxFileAttributes archiveAttribute)
|
||||
{
|
||||
if (path.IsNull())
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
|
||||
return DoCreateDirectory(path, archiveAttribute);
|
||||
}
|
||||
|
||||
public Result GetFileAttributes(out NxFileAttributes attributes, U8Span path)
|
||||
{
|
||||
if (path.IsNull())
|
||||
{
|
||||
attributes = default;
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
}
|
||||
|
||||
return DoGetFileAttributes(out attributes, path);
|
||||
}
|
||||
|
||||
public Result SetFileAttributes(U8Span path, NxFileAttributes attributes)
|
||||
{
|
||||
if (path.IsNull())
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
|
||||
return DoSetFileAttributes(path, attributes);
|
||||
}
|
||||
|
||||
public Result GetFileSize(out long fileSize, U8Span path)
|
||||
{
|
||||
if (path.IsNull())
|
||||
{
|
||||
fileSize = default;
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
}
|
||||
|
||||
return DoGetFileSize(out fileSize, path);
|
||||
}
|
||||
|
||||
protected abstract Result DoCreateDirectory(U8Span path, NxFileAttributes archiveAttribute);
|
||||
protected abstract Result DoGetFileAttributes(out NxFileAttributes attributes, U8Span path);
|
||||
protected abstract Result DoSetFileAttributes(U8Span path, NxFileAttributes attributes);
|
||||
protected abstract Result DoGetFileSize(out long fileSize, U8Span path);
|
||||
}
|
||||
}
|
@ -1,11 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace LibHac.Fs
|
||||
namespace LibHac.Fs.Fsa
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
/// <summary>
|
||||
/// Provides an interface for enumerating the child entries of a directory.
|
||||
/// </summary>
|
||||
public interface IDirectory
|
||||
public abstract class IDirectory : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves the next entries that this directory contains. Does not search subdirectories.
|
||||
@ -19,13 +20,36 @@ namespace LibHac.Fs
|
||||
/// Each call will attempt to read as many entries as the buffer can contain.
|
||||
/// Once all the entries have been read, all subsequent calls to <see cref="Read"/> will
|
||||
/// read 0 entries into the buffer.</remarks>
|
||||
Result Read(out long entriesRead, Span<DirectoryEntry> entryBuffer);
|
||||
public Result Read(out long entriesRead, Span<DirectoryEntry> entryBuffer)
|
||||
{
|
||||
if (entryBuffer.IsEmpty)
|
||||
{
|
||||
entriesRead = 0;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
return DoRead(out entriesRead, entryBuffer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the number of file system entries that this directory contains. Does not search subdirectories.
|
||||
/// </summary>
|
||||
/// <param name="entryCount">The number of child entries the directory contains.</param>
|
||||
/// <returns>The <see cref="Result"/> of the requested operation.</returns>
|
||||
Result GetEntryCount(out long entryCount);
|
||||
public Result GetEntryCount(out long entryCount)
|
||||
{
|
||||
return DoGetEntryCount(out entryCount);
|
||||
}
|
||||
|
||||
protected abstract Result DoRead(out long entriesRead, Span<DirectoryEntry> entryBuffer);
|
||||
protected abstract Result DoGetEntryCount(out long entryCount);
|
||||
|
||||
protected virtual void Dispose(bool disposing) { }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
248
src/LibHac/Fs/Fsa/IFile.cs
Normal file
248
src/LibHac/Fs/Fsa/IFile.cs
Normal file
@ -0,0 +1,248 @@
|
||||
using System;
|
||||
using LibHac.Diag;
|
||||
|
||||
namespace LibHac.Fs.Fsa
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
/// <summary>
|
||||
/// Provides an interface for reading and writing a sequence of bytes.
|
||||
/// </summary>
|
||||
/// <remarks><see cref="IFile"/> is similar to <see cref="IStorage"/>, and has a few main differences:
|
||||
///
|
||||
/// - <see cref="IFile"/> allows an <see cref="OpenMode"/> to be set that controls read, write
|
||||
/// and append permissions for the file.
|
||||
///
|
||||
/// - If the <see cref="IFile"/> cannot read or write as many bytes as requested, it will read
|
||||
/// or write as many bytes as it can and return that number of bytes to the caller.
|
||||
///
|
||||
/// - If <see cref="Write"/> is called on an offset past the end of the <see cref="IFile"/>,
|
||||
/// the <see cref="OpenMode.AllowAppend"/> mode is set and the file supports expansion,
|
||||
/// the file will be expanded so that it is large enough to contain the written data.</remarks>
|
||||
public abstract class IFile : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Reads a sequence of bytes from the current <see cref="IFile"/>.
|
||||
/// </summary>
|
||||
/// <param name="bytesRead">If the operation returns successfully, The total number of bytes read into
|
||||
/// the buffer. This can be less than the size of the buffer if the IFile is too short to fulfill the request.</param>
|
||||
/// <param name="offset">The offset in the <see cref="IFile"/> at which to begin reading.</param>
|
||||
/// <param name="destination">The buffer where the read bytes will be stored.
|
||||
/// The number of bytes read will be no larger than the length of the buffer.</param>
|
||||
/// <param name="option">Options for reading from the <see cref="IFile"/>.</param>
|
||||
/// <returns>The <see cref="Result"/> of the requested operation.</returns>
|
||||
public Result Read(out long bytesRead, long offset, Span<byte> destination, in ReadOption option)
|
||||
{
|
||||
if (destination.IsEmpty)
|
||||
{
|
||||
bytesRead = 0;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
if (offset < 0)
|
||||
{
|
||||
bytesRead = 0;
|
||||
return ResultFs.OutOfRange.Log();
|
||||
}
|
||||
|
||||
if (long.MaxValue - offset < destination.Length)
|
||||
{
|
||||
bytesRead = 0;
|
||||
return ResultFs.OutOfRange.Log();
|
||||
}
|
||||
|
||||
return DoRead(out bytesRead, offset, destination, in option);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a sequence of bytes from the current <see cref="IFile"/> with no <see cref="ReadOption"/>s.
|
||||
/// </summary>
|
||||
/// <param name="bytesRead">If the operation returns successfully, The total number of bytes read into
|
||||
/// the buffer. This can be less than the size of the buffer if the IFile is too short to fulfill the request.</param>
|
||||
/// <param name="offset">The offset in the <see cref="IFile"/> at which to begin reading.</param>
|
||||
/// <param name="destination">The buffer where the read bytes will be stored.
|
||||
/// The number of bytes read will be no larger than the length of the buffer.</param>
|
||||
/// <returns>The <see cref="Result"/> of the requested operation.</returns>
|
||||
public Result Read(out long bytesRead, long offset, Span<byte> destination)
|
||||
{
|
||||
return Read(out bytesRead, offset, destination, ReadOption.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a sequence of bytes to the current <see cref="IFile"/>.
|
||||
/// </summary>
|
||||
/// <param name="offset">The offset in the <see cref="IStorage"/> at which to begin writing.</param>
|
||||
/// <param name="source">The buffer containing the bytes to be written.</param>
|
||||
/// <param name="option">Options for writing to the <see cref="IFile"/>.</param>
|
||||
/// <returns>The <see cref="Result"/> of the requested operation.</returns>
|
||||
public Result Write(long offset, ReadOnlySpan<byte> source, in WriteOption option)
|
||||
{
|
||||
if (source.IsEmpty)
|
||||
{
|
||||
if (option.HasFlushFlag())
|
||||
{
|
||||
Result rc = Flush();
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
if (offset < 0)
|
||||
return ResultFs.OutOfRange.Log();
|
||||
|
||||
if (long.MaxValue - offset < source.Length)
|
||||
return ResultFs.OutOfRange.Log();
|
||||
|
||||
return DoWrite(offset, source, in option);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Causes any buffered data to be written to the underlying device.
|
||||
/// </summary>
|
||||
public Result Flush()
|
||||
{
|
||||
return DoFlush();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the size of the file in bytes.
|
||||
/// </summary>
|
||||
/// <param name="size">The desired size of the file in bytes.</param>
|
||||
/// <returns>The <see cref="Result"/> of the requested operation.</returns>
|
||||
public Result SetSize(long size)
|
||||
{
|
||||
if (size < 0)
|
||||
return ResultFs.OutOfRange.Log();
|
||||
|
||||
return DoSetSize(size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of bytes in the file.
|
||||
/// </summary>
|
||||
/// <param name="size">If the operation returns successfully, the length of the file in bytes.</param>
|
||||
/// <returns>The <see cref="Result"/> of the requested operation.</returns>
|
||||
public Result GetSize(out long size)
|
||||
{
|
||||
return DoGetSize(out size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs various operations on the file. Used to extend the functionality of the <see cref="IFile"/> interface.
|
||||
/// </summary>
|
||||
/// <param name="outBuffer">A buffer that will contain the response from the operation.</param>
|
||||
/// <param name="operationId">The operation to be performed.</param>
|
||||
/// <param name="offset">The offset of the range to operate on.</param>
|
||||
/// <param name="size">The size of the range to operate on.</param>
|
||||
/// <param name="inBuffer">An input buffer. Size may vary depending on the operation performed.</param>
|
||||
/// <returns>The <see cref="Result"/> of the requested operation.</returns>
|
||||
public Result OperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size,
|
||||
ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
return DoOperateRange(outBuffer, operationId, offset, size, inBuffer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs various operations on the file. Used to extend the functionality of the <see cref="IFile"/> interface.
|
||||
/// </summary>
|
||||
/// <param name="operationId">The operation to be performed.</param>
|
||||
/// <param name="offset">The offset of the range to operate on.</param>
|
||||
/// <param name="size">The size of the range to operate on.</param>
|
||||
/// <returns>The <see cref="Result"/> of the requested operation.</returns>
|
||||
public Result OperateRange(OperationId operationId, long offset, long size)
|
||||
{
|
||||
return DoOperateRange(Span<byte>.Empty, operationId, offset, size, ReadOnlySpan<byte>.Empty);
|
||||
}
|
||||
|
||||
protected Result DryRead(out long readableBytes, long offset, long size, in ReadOption option,
|
||||
OpenMode openMode)
|
||||
{
|
||||
// Check that we can read.
|
||||
if (!openMode.HasFlag(OpenMode.Read))
|
||||
{
|
||||
readableBytes = default;
|
||||
return ResultFs.InvalidOpenModeForRead.Log();
|
||||
}
|
||||
|
||||
// Get the file size, and validate our offset.
|
||||
Result rc = GetSize(out long fileSize);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
readableBytes = default;
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (offset > fileSize)
|
||||
{
|
||||
readableBytes = default;
|
||||
return ResultFs.OutOfRange.Log();
|
||||
}
|
||||
|
||||
readableBytes = Math.Min(fileSize - offset, size);
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected Result DrySetSize(long size, OpenMode openMode)
|
||||
{
|
||||
// Check that we can write.
|
||||
if (!openMode.HasFlag(OpenMode.Write))
|
||||
return ResultFs.InvalidOpenModeForWrite.Log();
|
||||
|
||||
Assert.AssertTrue(size >= 0);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected Result DryWrite(out bool needsAppend, long offset, long size, in WriteOption option,
|
||||
OpenMode openMode)
|
||||
{
|
||||
// Check that we can write.
|
||||
if (!openMode.HasFlag(OpenMode.Write))
|
||||
{
|
||||
needsAppend = default;
|
||||
return ResultFs.InvalidOpenModeForWrite.Log();
|
||||
}
|
||||
|
||||
// Get the file size.
|
||||
Result rc = GetSize(out long fileSize);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
needsAppend = default;
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (fileSize < offset + size)
|
||||
{
|
||||
if (!openMode.HasFlag(OpenMode.AllowAppend))
|
||||
{
|
||||
needsAppend = default;
|
||||
return ResultFs.FileExtensionWithoutOpenModeAllowAppend.Log();
|
||||
}
|
||||
|
||||
needsAppend = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
needsAppend = false;
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected abstract Result DoRead(out long bytesRead, long offset, Span<byte> destination, in ReadOption option);
|
||||
protected abstract Result DoWrite(long offset, ReadOnlySpan<byte> source, in WriteOption option);
|
||||
protected abstract Result DoFlush();
|
||||
protected abstract Result DoSetSize(long size);
|
||||
protected abstract Result DoGetSize(out long size);
|
||||
protected abstract Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size,
|
||||
ReadOnlySpan<byte> inBuffer);
|
||||
|
||||
protected virtual void Dispose(bool disposing) { }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
@ -2,19 +2,20 @@
|
||||
using LibHac.Common;
|
||||
using LibHac.FsSystem;
|
||||
|
||||
namespace LibHac.Fs
|
||||
namespace LibHac.Fs.Fsa
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
/// <summary>
|
||||
/// Provides an interface for accessing a file system. <c>/</c> is used as the path delimiter.
|
||||
/// </summary>
|
||||
public interface IFileSystem : IDisposable
|
||||
public abstract class IFileSystem : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates or overwrites a file at the specified path.
|
||||
/// </summary>
|
||||
/// <param name="path">The full path of the file to create.</param>
|
||||
/// <param name="size">The initial size of the created file.</param>
|
||||
/// <param name="options">Flags to control how the file is created.
|
||||
/// <param name="option">Flags to control how the file is created.
|
||||
/// Should usually be <see cref="CreateFileOptions.None"/></param>
|
||||
/// <returns>The <see cref="Result"/> of the requested operation.</returns>
|
||||
/// <remarks>
|
||||
@ -24,7 +25,16 @@ namespace LibHac.Fs
|
||||
/// Specified path already exists as either a file or directory: <see cref="ResultFs.PathAlreadyExists"/>
|
||||
/// Insufficient free space to create the file: <see cref="ResultFs.InsufficientFreeSpace"/>
|
||||
/// </remarks>
|
||||
Result CreateFile(U8Span path, long size, CreateFileOptions options);
|
||||
public Result CreateFile(U8Span path, long size, CreateFileOptions option)
|
||||
{
|
||||
if (path.IsNull())
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
|
||||
if (size < 0)
|
||||
return ResultFs.OutOfRange.Log();
|
||||
|
||||
return DoCreateFile(path, size, option);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the specified file.
|
||||
@ -36,7 +46,13 @@ namespace LibHac.Fs
|
||||
///
|
||||
/// The specified path does not exist or is a directory: <see cref="ResultFs.PathNotFound"/>
|
||||
/// </remarks>
|
||||
Result DeleteFile(U8Span path);
|
||||
public Result DeleteFile(U8Span path)
|
||||
{
|
||||
if (path.IsNull())
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
|
||||
return DoDeleteFile(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates all directories and subdirectories in the specified path unless they already exist.
|
||||
@ -50,7 +66,13 @@ namespace LibHac.Fs
|
||||
/// Specified path already exists as either a file or directory: <see cref="ResultFs.PathAlreadyExists"/>
|
||||
/// Insufficient free space to create the directory: <see cref="ResultFs.InsufficientFreeSpace"/>
|
||||
/// </remarks>
|
||||
Result CreateDirectory(U8Span path);
|
||||
public Result CreateDirectory(U8Span path)
|
||||
{
|
||||
if (path.IsNull())
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
|
||||
return DoCreateDirectory(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the specified directory.
|
||||
@ -63,7 +85,13 @@ namespace LibHac.Fs
|
||||
/// The specified path does not exist or is a file: <see cref="ResultFs.PathNotFound"/>
|
||||
/// The specified directory is not empty: <see cref="ResultFs.DirectoryNotEmpty"/>
|
||||
/// </remarks>
|
||||
Result DeleteDirectory(U8Span path);
|
||||
public Result DeleteDirectory(U8Span path)
|
||||
{
|
||||
if (path.IsNull())
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
|
||||
return DoDeleteDirectory(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the specified directory and any subdirectories and files in the directory.
|
||||
@ -75,7 +103,13 @@ namespace LibHac.Fs
|
||||
///
|
||||
/// The specified path does not exist or is a file: <see cref="ResultFs.PathNotFound"/>
|
||||
/// </remarks>
|
||||
Result DeleteDirectoryRecursively(U8Span path);
|
||||
public Result DeleteDirectoryRecursively(U8Span path)
|
||||
{
|
||||
if (path.IsNull())
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
|
||||
return DoDeleteDirectoryRecursively(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes any subdirectories and files in the specified directory.
|
||||
@ -87,7 +121,13 @@ namespace LibHac.Fs
|
||||
///
|
||||
/// The specified path does not exist or is a file: <see cref="ResultFs.PathNotFound"/>
|
||||
/// </remarks>
|
||||
Result CleanDirectoryRecursively(U8Span path);
|
||||
public Result CleanDirectoryRecursively(U8Span path)
|
||||
{
|
||||
if (path.IsNull())
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
|
||||
return DoCleanDirectoryRecursively(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renames or moves a file to a new location.
|
||||
@ -103,7 +143,16 @@ namespace LibHac.Fs
|
||||
/// <paramref name="newPath"/>'s parent directory does not exist: <see cref="ResultFs.PathNotFound"/>
|
||||
/// <paramref name="newPath"/> already exists as either a file or directory: <see cref="ResultFs.PathAlreadyExists"/>
|
||||
/// </remarks>
|
||||
Result RenameFile(U8Span oldPath, U8Span newPath);
|
||||
public Result RenameFile(U8Span oldPath, U8Span newPath)
|
||||
{
|
||||
if (oldPath.IsNull())
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
|
||||
if (newPath.IsNull())
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
|
||||
return DoRenameFile(oldPath, newPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renames or moves a directory to a new location.
|
||||
@ -120,7 +169,16 @@ namespace LibHac.Fs
|
||||
/// <paramref name="newPath"/> already exists as either a file or directory: <see cref="ResultFs.PathAlreadyExists"/>
|
||||
/// Either <paramref name="oldPath"/> or <paramref name="newPath"/> is a subpath of the other: <see cref="ResultFs.DestinationIsSubPathOfSource"/>
|
||||
/// </remarks>
|
||||
Result RenameDirectory(U8Span oldPath, U8Span newPath);
|
||||
public Result RenameDirectory(U8Span oldPath, U8Span newPath)
|
||||
{
|
||||
if (oldPath.IsNull())
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
|
||||
if (newPath.IsNull())
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
|
||||
return DoRenameDirectory(oldPath, newPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified path is a file or directory, or does not exist.
|
||||
@ -128,7 +186,16 @@ namespace LibHac.Fs
|
||||
/// <param name="entryType">If the operation returns successfully, the <see cref="DirectoryEntryType"/> of the file.</param>
|
||||
/// <param name="path">The full path to check.</param>
|
||||
/// <returns>The <see cref="Result"/> of the requested operation.</returns>
|
||||
Result GetEntryType(out DirectoryEntryType entryType, U8Span path);
|
||||
public Result GetEntryType(out DirectoryEntryType entryType, U8Span path)
|
||||
{
|
||||
if (path.IsNull())
|
||||
{
|
||||
entryType = default;
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
}
|
||||
|
||||
return DoGetEntryType(out entryType, path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the amount of available free space on a drive, in bytes.
|
||||
@ -136,7 +203,16 @@ namespace LibHac.Fs
|
||||
/// <param name="freeSpace">If the operation returns successfully, the amount of free space available on the drive, in bytes.</param>
|
||||
/// <param name="path">The path of the drive to query. Unused in almost all cases.</param>
|
||||
/// <returns>The <see cref="Result"/> of the requested operation.</returns>
|
||||
Result GetFreeSpaceSize(out long freeSpace, U8Span path);
|
||||
public Result GetFreeSpaceSize(out long freeSpace, U8Span path)
|
||||
{
|
||||
if (path.IsNull())
|
||||
{
|
||||
freeSpace = default;
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
}
|
||||
|
||||
return DoGetFreeSpaceSize(out freeSpace, path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total size of storage space on a drive, in bytes.
|
||||
@ -144,7 +220,16 @@ namespace LibHac.Fs
|
||||
/// <param name="totalSpace">If the operation returns successfully, the total size of the drive, in bytes.</param>
|
||||
/// <param name="path">The path of the drive to query. Unused in almost all cases.</param>
|
||||
/// <returns>The <see cref="Result"/> of the requested operation.</returns>
|
||||
Result GetTotalSpaceSize(out long totalSpace, U8Span path);
|
||||
public Result GetTotalSpaceSize(out long totalSpace, U8Span path)
|
||||
{
|
||||
if (path.IsNull())
|
||||
{
|
||||
totalSpace = default;
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
}
|
||||
|
||||
return DoGetTotalSpaceSize(out totalSpace, path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens an <see cref="IFile"/> instance for the specified path.
|
||||
@ -159,7 +244,28 @@ namespace LibHac.Fs
|
||||
///
|
||||
/// The specified path does not exist or is a directory: <see cref="ResultFs.PathNotFound"/>
|
||||
/// </remarks>
|
||||
Result OpenFile(out IFile file, U8Span path, OpenMode mode);
|
||||
public Result OpenFile(out IFile file, U8Span path, OpenMode mode)
|
||||
{
|
||||
if (path.IsNull())
|
||||
{
|
||||
file = default;
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
}
|
||||
|
||||
if ((mode & OpenMode.ReadWrite) == 0)
|
||||
{
|
||||
file = default;
|
||||
return ResultFs.InvalidOpenMode.Log();
|
||||
}
|
||||
|
||||
if ((mode & ~OpenMode.All) != 0)
|
||||
{
|
||||
file = default;
|
||||
return ResultFs.InvalidOpenMode.Log();
|
||||
}
|
||||
|
||||
return DoOpenFile(out file, path, mode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="IDirectory"/> instance for enumerating the specified directory.
|
||||
@ -174,20 +280,41 @@ namespace LibHac.Fs
|
||||
///
|
||||
/// The specified path does not exist or is a file: <see cref="ResultFs.PathNotFound"/>
|
||||
/// </remarks>
|
||||
Result OpenDirectory(out IDirectory directory, U8Span path, OpenDirectoryMode mode);
|
||||
public Result OpenDirectory(out IDirectory directory, U8Span path, OpenDirectoryMode mode)
|
||||
{
|
||||
if (path.IsNull())
|
||||
{
|
||||
directory = default;
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
}
|
||||
|
||||
if ((mode & OpenDirectoryMode.All) == 0)
|
||||
{
|
||||
directory = default;
|
||||
return ResultFs.InvalidOpenMode.Log();
|
||||
}
|
||||
|
||||
if ((mode & ~(OpenDirectoryMode.All | OpenDirectoryMode.NoFileSize)) != 0)
|
||||
{
|
||||
directory = default;
|
||||
return ResultFs.InvalidOpenMode.Log();
|
||||
}
|
||||
|
||||
return DoOpenDirectory(out directory, path, mode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Commits any changes to a transactional file system.
|
||||
/// Does nothing if called on a non-transactional file system.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="Result"/> of the requested operation.</returns>
|
||||
Result Commit();
|
||||
public Result Commit() => DoCommit();
|
||||
|
||||
Result CommitProvisionally(long commitCount);
|
||||
public Result CommitProvisionally(long counter) => DoCommitProvisionally(counter);
|
||||
|
||||
Result Rollback();
|
||||
public Result Rollback() => DoRollback();
|
||||
|
||||
Result Flush();
|
||||
public Result Flush() => DoFlush();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the creation, last accessed, and last modified timestamps of a file or directory.
|
||||
@ -201,7 +328,16 @@ namespace LibHac.Fs
|
||||
///
|
||||
/// The specified path does not exist: <see cref="ResultFs.PathNotFound"/>
|
||||
/// </remarks>
|
||||
Result GetFileTimeStampRaw(out FileTimeStampRaw timeStamp, U8Span path);
|
||||
public Result GetFileTimeStampRaw(out FileTimeStampRaw timeStamp, U8Span path)
|
||||
{
|
||||
if (path.IsNull())
|
||||
{
|
||||
timeStamp = default;
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
}
|
||||
|
||||
return DoGetFileTimeStampRaw(out timeStamp, path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a query on the specified file.
|
||||
@ -215,7 +351,60 @@ namespace LibHac.Fs
|
||||
/// <param name="queryId">The type of query to perform.</param>
|
||||
/// <param name="path">The full path of the file to query.</param>
|
||||
/// <returns>The <see cref="Result"/> of the requested operation.</returns>
|
||||
Result QueryEntry(Span<byte> outBuffer, ReadOnlySpan<byte> inBuffer, QueryId queryId, U8Span path);
|
||||
public Result QueryEntry(Span<byte> outBuffer, ReadOnlySpan<byte> inBuffer, QueryId queryId, U8Span path)
|
||||
{
|
||||
if (path.IsNull())
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
|
||||
return DoQueryEntry(outBuffer, inBuffer, queryId, path);
|
||||
}
|
||||
|
||||
protected abstract Result DoCreateFile(U8Span path, long size, CreateFileOptions option);
|
||||
protected abstract Result DoDeleteFile(U8Span path);
|
||||
protected abstract Result DoCreateDirectory(U8Span path);
|
||||
protected abstract Result DoDeleteDirectory(U8Span path);
|
||||
protected abstract Result DoDeleteDirectoryRecursively(U8Span path);
|
||||
protected abstract Result DoCleanDirectoryRecursively(U8Span path);
|
||||
protected abstract Result DoRenameFile(U8Span oldPath, U8Span newPath);
|
||||
protected abstract Result DoRenameDirectory(U8Span oldPath, U8Span newPath);
|
||||
protected abstract Result DoGetEntryType(out DirectoryEntryType entryType, U8Span path);
|
||||
|
||||
protected virtual Result DoGetFreeSpaceSize(out long freeSpace, U8Span path)
|
||||
{
|
||||
freeSpace = default;
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
protected virtual Result DoGetTotalSpaceSize(out long totalSpace, U8Span path)
|
||||
{
|
||||
totalSpace = default;
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
protected abstract Result DoOpenFile(out IFile file, U8Span path, OpenMode mode);
|
||||
protected abstract Result DoOpenDirectory(out IDirectory directory, U8Span path, OpenDirectoryMode mode);
|
||||
protected abstract Result DoCommit();
|
||||
|
||||
protected virtual Result DoCommitProvisionally(long counter) => ResultFs.NotImplemented.Log();
|
||||
protected virtual Result DoRollback() => ResultFs.NotImplemented.Log();
|
||||
protected virtual Result DoFlush() => ResultFs.NotImplemented.Log();
|
||||
|
||||
protected virtual Result DoGetFileTimeStampRaw(out FileTimeStampRaw timeStamp, U8Span path)
|
||||
{
|
||||
timeStamp = default;
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
protected virtual Result DoQueryEntry(Span<byte> outBuffer, ReadOnlySpan<byte> inBuffer, QueryId queryId,
|
||||
U8Span path) => ResultFs.NotImplemented.Log();
|
||||
|
||||
protected virtual void Dispose(bool disposing) { }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
@ -1,12 +0,0 @@
|
||||
using LibHac.Common;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
public interface IAttributeFileSystem : IFileSystem
|
||||
{
|
||||
Result CreateDirectory(U8Span path, NxFileAttributes archiveAttribute);
|
||||
Result GetFileAttributes(out NxFileAttributes attributes, U8Span path);
|
||||
Result SetFileAttributes(U8Span path, NxFileAttributes attributes);
|
||||
Result GetFileSize(out long fileSize, U8Span path);
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an interface for reading and writing a sequence of bytes.
|
||||
/// </summary>
|
||||
/// <remarks><see cref="IFile"/> is similar to <see cref="IStorage"/>, and has a few main differences:
|
||||
///
|
||||
/// - <see cref="IFile"/> allows an <see cref="OpenMode"/> to be set that controls read, write
|
||||
/// and append permissions for the file.
|
||||
///
|
||||
/// - If the <see cref="IFile"/> cannot read or write as many bytes as requested, it will read
|
||||
/// or write as many bytes as it can and return that number of bytes to the caller.
|
||||
///
|
||||
/// - If <see cref="Write"/> is called on an offset past the end of the <see cref="IFile"/>,
|
||||
/// the <see cref="OpenMode.AllowAppend"/> mode is set and the file supports expansion,
|
||||
/// the file will be expanded so that it is large enough to contain the written data.</remarks>
|
||||
public interface IFile : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Reads a sequence of bytes from the current <see cref="IFile"/>.
|
||||
/// </summary>
|
||||
/// <param name="bytesRead">If the operation returns successfully, The total number of bytes read into
|
||||
/// the buffer. This can be less than the size of the buffer if the IFile is too short to fulfill the request.</param>
|
||||
/// <param name="offset">The offset in the <see cref="IFile"/> at which to begin reading.</param>
|
||||
/// <param name="destination">The buffer where the read bytes will be stored.
|
||||
/// The number of bytes read will be no larger than the length of the buffer.</param>
|
||||
/// <param name="options">Options for reading from the <see cref="IFile"/>.</param>
|
||||
/// <returns>The <see cref="Result"/> of the requested operation.</returns>
|
||||
Result Read(out long bytesRead, long offset, Span<byte> destination, ReadOption options);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a sequence of bytes to the current <see cref="IFile"/>.
|
||||
/// </summary>
|
||||
/// <param name="offset">The offset in the <see cref="IStorage"/> at which to begin writing.</param>
|
||||
/// <param name="source">The buffer containing the bytes to be written.</param>
|
||||
/// <param name="options">Options for writing to the <see cref="IFile"/>.</param>
|
||||
/// <returns>The <see cref="Result"/> of the requested operation.</returns>
|
||||
Result Write(long offset, ReadOnlySpan<byte> source, WriteOption options);
|
||||
|
||||
/// <summary>
|
||||
/// Causes any buffered data to be written to the underlying device.
|
||||
/// </summary>
|
||||
Result Flush();
|
||||
|
||||
/// <summary>
|
||||
/// Sets the size of the file in bytes.
|
||||
/// </summary>
|
||||
/// <param name="size">The desired size of the file in bytes.</param>
|
||||
/// <returns>The <see cref="Result"/> of the requested operation.</returns>
|
||||
Result SetSize(long size);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of bytes in the file.
|
||||
/// </summary>
|
||||
/// <param name="size">If the operation returns successfully, the length of the file in bytes.</param>
|
||||
/// <returns>The <see cref="Result"/> of the requested operation.</returns>
|
||||
Result GetSize(out long size);
|
||||
|
||||
/// <summary>
|
||||
/// Performs various operations on the file. Used to extend the functionality of the <see cref="IFile"/> interface.
|
||||
/// </summary>
|
||||
/// <param name="outBuffer">A buffer that will contain the response from the operation.</param>
|
||||
/// <param name="operationId">The operation to be performed.</param>
|
||||
/// <param name="offset">The offset of the range to operate on.</param>
|
||||
/// <param name="size">The size of the range to operate on.</param>
|
||||
/// <param name="inBuffer">An input buffer. Size may vary depending on the operation performed.</param>
|
||||
/// <returns>The <see cref="Result"/> of the requested operation.</returns>
|
||||
Result OperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size,
|
||||
ReadOnlySpan<byte> inBuffer);
|
||||
}
|
||||
}
|
39
src/LibHac/Fs/IFile2.cs
Normal file
39
src/LibHac/Fs/IFile2.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using System;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
public readonly struct ReadOption
|
||||
{
|
||||
public readonly int Value;
|
||||
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
private ReadOption(int value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public static ReadOption None => default;
|
||||
}
|
||||
|
||||
public readonly struct WriteOption
|
||||
{
|
||||
public readonly WriteOptionFlag Flags;
|
||||
|
||||
private WriteOption(WriteOptionFlag flags)
|
||||
{
|
||||
Flags = flags;
|
||||
}
|
||||
|
||||
public bool HasFlushFlag() => Flags.HasFlag(WriteOptionFlag.Flush);
|
||||
|
||||
public static WriteOption None => default;
|
||||
public static WriteOption Flush => new WriteOption(WriteOptionFlag.Flush);
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum WriteOptionFlag
|
||||
{
|
||||
None = 0,
|
||||
Flush = 1
|
||||
}
|
||||
}
|
@ -1,47 +1,97 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
/// <summary>
|
||||
/// Provides an interface for reading and writing a sequence of bytes.
|
||||
/// </summary>
|
||||
public interface IStorage : IDisposable
|
||||
/// <remarks>
|
||||
/// The official IStorage makes the <c>Read</c> etc. methods abstract and doesn't
|
||||
/// have <c>DoRead</c> etc. methods. We're using them here so we can make sure
|
||||
/// the object isn't disposed before calling the method implementation.
|
||||
/// </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>
|
||||
/// <param name="offset">The offset in the <see cref="IStorage"/> at which to begin reading.</param>
|
||||
/// <param name="destination">The buffer where the read bytes will be stored.
|
||||
/// The number of bytes read will be equal to the length of the buffer.</param>
|
||||
/// <param name="offset">The offset in the <see cref="IStorage"/> at which to begin reading.</param>
|
||||
/// <exception cref="ArgumentException">Invalid offset or the IStorage contains fewer bytes than requested. </exception>
|
||||
Result Read(long offset, Span<byte> destination);
|
||||
/// <returns>The <see cref="Result"/> of the operation.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Result Read(long offset, Span<byte> destination)
|
||||
{
|
||||
if (IsDisposed)
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return DoRead(offset, destination);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a sequence of bytes to the current <see cref="IStorage"/>.
|
||||
/// </summary>
|
||||
/// <param name="source">The buffer containing the bytes to be written.</param>
|
||||
/// <param name="offset">The offset in the <see cref="IStorage"/> at which to begin writing.</param>
|
||||
/// <exception cref="ArgumentException">Invalid offset or <paramref name="source"/>
|
||||
/// is too large to be written to the IStorage. </exception>
|
||||
Result Write(long offset, ReadOnlySpan<byte> source);
|
||||
/// <param name="source">The buffer containing the bytes to be written.</param>
|
||||
/// <returns>The <see cref="Result"/> of the operation.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Result Write(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
if (IsDisposed)
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return DoWrite(offset, source);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Causes any buffered data to be written to the underlying device.
|
||||
/// </summary>
|
||||
Result Flush();
|
||||
/// <returns>The <see cref="Result"/> of the operation.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Result Flush()
|
||||
{
|
||||
if (IsDisposed)
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return DoFlush();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the size of the current IStorage.
|
||||
/// Sets the size of the current <see cref="IStorage"/>.
|
||||
/// </summary>
|
||||
/// <param name="size">The desired size of the current IStorage in bytes.</param>
|
||||
Result SetSize(long size);
|
||||
/// <param name="size">The desired size of the <see cref="IStorage"/> in bytes.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Result SetSize(long size)
|
||||
{
|
||||
if (IsDisposed)
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return DoSetSize(size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The size of the<see cref="IStorage"/>. -1 will be returned if
|
||||
/// the <see cref="IStorage"/> cannot be represented as a sequence of contiguous bytes.
|
||||
/// Gets the number of bytes in the <see cref="IStorage"/>.
|
||||
/// </summary>
|
||||
/// <returns>The size of the <see cref="IStorage"/> in bytes.</returns>
|
||||
Result GetSize(out long size);
|
||||
/// <param name="size">If the operation returns successfully, the length of the file in bytes.</param>
|
||||
/// <returns>The <see cref="Result"/> of the operation.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Result GetSize(out long size)
|
||||
{
|
||||
if (IsDisposed)
|
||||
{
|
||||
size = default;
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
}
|
||||
|
||||
return DoGetSize(out size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs various operations on the file. Used to extend the functionality of the <see cref="IStorage"/> interface.
|
||||
@ -51,8 +101,56 @@ namespace LibHac.Fs
|
||||
/// <param name="offset">The offset of the range to operate on.</param>
|
||||
/// <param name="size">The size of the range to operate on.</param>
|
||||
/// <param name="inBuffer">An input buffer. Size may vary depending on the operation performed.</param>
|
||||
/// <returns>The <see cref="Result"/> of the requested operation.</returns>
|
||||
Result OperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size,
|
||||
ReadOnlySpan<byte> inBuffer);
|
||||
/// <returns>The <see cref="Result"/> of the operation.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
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)
|
||||
{
|
||||
return offset >= 0 &&
|
||||
size >= 0 &&
|
||||
size <= totalSize &&
|
||||
offset <= totalSize - size;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsOffsetAndSizeValid(long offset, long size)
|
||||
{
|
||||
return offset >= 0 &&
|
||||
size >= 0 &&
|
||||
offset <= offset - size;
|
||||
}
|
||||
|
||||
protected abstract Result DoRead(long offset, Span<byte> destination);
|
||||
protected abstract Result DoWrite(long offset, ReadOnlySpan<byte> source);
|
||||
protected abstract Result DoFlush();
|
||||
protected abstract Result DoGetSize(out long size);
|
||||
protected abstract Result DoSetSize(long size);
|
||||
|
||||
protected virtual Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size,
|
||||
ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
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) { }
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSystem;
|
||||
|
||||
namespace LibHac.Fs
|
||||
@ -9,7 +10,7 @@ namespace LibHac.Fs
|
||||
/// <summary>
|
||||
/// A filesystem stored in-memory. Mainly used for testing.
|
||||
/// </summary>
|
||||
public class InMemoryFileSystem : AttributeFileSystemBase
|
||||
public class InMemoryFileSystem : IAttributeFileSystem
|
||||
{
|
||||
private FileTable FsTable { get; }
|
||||
|
||||
@ -18,12 +19,12 @@ namespace LibHac.Fs
|
||||
FsTable = new FileTable();
|
||||
}
|
||||
|
||||
protected override Result CreateDirectoryImpl(U8Span path)
|
||||
protected override Result DoCreateDirectory(U8Span path)
|
||||
{
|
||||
return FsTable.AddDirectory(new U8Span(path));
|
||||
}
|
||||
|
||||
protected override Result CreateDirectoryImpl(U8Span path, NxFileAttributes archiveAttribute)
|
||||
protected override Result DoCreateDirectory(U8Span path, NxFileAttributes archiveAttribute)
|
||||
{
|
||||
Result rc = FsTable.AddDirectory(path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
@ -35,7 +36,7 @@ namespace LibHac.Fs
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result CreateFileImpl(U8Span path, long size, CreateFileOptions options)
|
||||
protected override Result DoCreateFile(U8Span path, long size, CreateFileOptions options)
|
||||
{
|
||||
Result rc = FsTable.AddFile(path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
@ -46,27 +47,27 @@ namespace LibHac.Fs
|
||||
return file.File.SetSize(size);
|
||||
}
|
||||
|
||||
protected override Result DeleteDirectoryImpl(U8Span path)
|
||||
protected override Result DoDeleteDirectory(U8Span path)
|
||||
{
|
||||
return FsTable.DeleteDirectory(new U8Span(path), false);
|
||||
}
|
||||
|
||||
protected override Result DeleteDirectoryRecursivelyImpl(U8Span path)
|
||||
protected override Result DoDeleteDirectoryRecursively(U8Span path)
|
||||
{
|
||||
return FsTable.DeleteDirectory(new U8Span(path), true);
|
||||
}
|
||||
|
||||
protected override Result CleanDirectoryRecursivelyImpl(U8Span path)
|
||||
protected override Result DoCleanDirectoryRecursively(U8Span path)
|
||||
{
|
||||
return FsTable.CleanDirectory(new U8Span(path));
|
||||
}
|
||||
|
||||
protected override Result DeleteFileImpl(U8Span path)
|
||||
protected override Result DoDeleteFile(U8Span path)
|
||||
{
|
||||
return FsTable.DeleteFile(new U8Span(path));
|
||||
}
|
||||
|
||||
protected override Result OpenDirectoryImpl(out IDirectory directory, U8Span path, OpenDirectoryMode mode)
|
||||
protected override Result DoOpenDirectory(out IDirectory directory, U8Span path, OpenDirectoryMode mode)
|
||||
{
|
||||
directory = default;
|
||||
|
||||
@ -77,7 +78,7 @@ namespace LibHac.Fs
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result OpenFileImpl(out IFile file, U8Span path, OpenMode mode)
|
||||
protected override Result DoOpenFile(out IFile file, U8Span path, OpenMode mode)
|
||||
{
|
||||
file = default;
|
||||
|
||||
@ -89,17 +90,17 @@ namespace LibHac.Fs
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result RenameDirectoryImpl(U8Span oldPath, U8Span newPath)
|
||||
protected override Result DoRenameDirectory(U8Span oldPath, U8Span newPath)
|
||||
{
|
||||
return FsTable.RenameDirectory(new U8Span(oldPath), new U8Span(newPath));
|
||||
}
|
||||
|
||||
protected override Result RenameFileImpl(U8Span oldPath, U8Span newPath)
|
||||
protected override Result DoRenameFile(U8Span oldPath, U8Span newPath)
|
||||
{
|
||||
return FsTable.RenameFile(new U8Span(oldPath), new U8Span(newPath));
|
||||
}
|
||||
|
||||
protected override Result GetEntryTypeImpl(out DirectoryEntryType entryType, U8Span path)
|
||||
protected override Result DoGetEntryType(out DirectoryEntryType entryType, U8Span path)
|
||||
{
|
||||
if (FsTable.GetFile(path, out _).IsSuccess())
|
||||
{
|
||||
@ -117,12 +118,12 @@ namespace LibHac.Fs
|
||||
return ResultFs.PathNotFound.Log();
|
||||
}
|
||||
|
||||
protected override Result CommitImpl()
|
||||
protected override Result DoCommit()
|
||||
{
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result GetFileAttributesImpl(out NxFileAttributes attributes, U8Span path)
|
||||
protected override Result DoGetFileAttributes(out NxFileAttributes attributes, U8Span path)
|
||||
{
|
||||
if (FsTable.GetFile(path, out FileNode file).IsSuccess())
|
||||
{
|
||||
@ -140,7 +141,7 @@ namespace LibHac.Fs
|
||||
return ResultFs.PathNotFound.Log();
|
||||
}
|
||||
|
||||
protected override Result SetFileAttributesImpl(U8Span path, NxFileAttributes attributes)
|
||||
protected override Result DoSetFileAttributes(U8Span path, NxFileAttributes attributes)
|
||||
{
|
||||
if (FsTable.GetFile(path, out FileNode file).IsSuccess())
|
||||
{
|
||||
@ -157,7 +158,7 @@ namespace LibHac.Fs
|
||||
return ResultFs.PathNotFound.Log();
|
||||
}
|
||||
|
||||
protected override Result GetFileSizeImpl(out long fileSize, U8Span path)
|
||||
protected override Result DoGetFileSize(out long fileSize, U8Span path)
|
||||
{
|
||||
if (FsTable.GetFile(path, out FileNode file).IsSuccess())
|
||||
{
|
||||
@ -169,7 +170,7 @@ namespace LibHac.Fs
|
||||
}
|
||||
|
||||
// todo: Make a more generic MemoryFile-type class
|
||||
private class MemoryFile : FileBase
|
||||
private class MemoryFile : IFile
|
||||
{
|
||||
private OpenMode Mode { get; }
|
||||
private MemoryStreamAccessor BaseStream { get; }
|
||||
@ -180,7 +181,8 @@ namespace LibHac.Fs
|
||||
Mode = mode;
|
||||
}
|
||||
|
||||
protected override Result ReadImpl(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
||||
protected override Result DoRead(out long bytesRead, long offset, Span<byte> destination,
|
||||
in ReadOption option)
|
||||
{
|
||||
if (!Mode.HasFlag(OpenMode.Read))
|
||||
{
|
||||
@ -191,7 +193,7 @@ namespace LibHac.Fs
|
||||
return BaseStream.Read(out bytesRead, offset, destination);
|
||||
}
|
||||
|
||||
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source, in WriteOption option)
|
||||
{
|
||||
if (!Mode.HasFlag(OpenMode.Write))
|
||||
{
|
||||
@ -201,20 +203,25 @@ namespace LibHac.Fs
|
||||
return BaseStream.Write(offset, source, Mode.HasFlag(OpenMode.AllowAppend));
|
||||
}
|
||||
|
||||
protected override Result FlushImpl()
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return BaseStream.Flush();
|
||||
}
|
||||
|
||||
protected override Result SetSizeImpl(long size)
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
return BaseStream.SetSize(size);
|
||||
}
|
||||
|
||||
protected override Result GetSizeImpl(out long size)
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
return BaseStream.GetSize(out size);
|
||||
}
|
||||
|
||||
protected override Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size, ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
private class MemoryDirectory : IDirectory
|
||||
@ -232,7 +239,7 @@ namespace LibHac.Fs
|
||||
CurrentFile = directory.ChildFile;
|
||||
}
|
||||
|
||||
public Result Read(out long entriesRead, Span<DirectoryEntry> entryBuffer)
|
||||
protected override Result DoRead(out long entriesRead, Span<DirectoryEntry> entryBuffer)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
@ -283,7 +290,7 @@ namespace LibHac.Fs
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result GetEntryCount(out long entryCount)
|
||||
protected override Result DoGetEntryCount(out long entryCount)
|
||||
{
|
||||
long count = 0;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
public class MemoryStorage : StorageBase
|
||||
public class MemoryStorage : IStorage
|
||||
{
|
||||
private byte[] StorageBuffer { get; }
|
||||
|
||||
@ -11,7 +11,7 @@ namespace LibHac.Fs
|
||||
StorageBuffer = buffer;
|
||||
}
|
||||
|
||||
protected override Result ReadImpl(long offset, Span<byte> destination)
|
||||
protected override Result DoRead(long offset, Span<byte> destination)
|
||||
{
|
||||
if (destination.Length == 0)
|
||||
return Result.Success;
|
||||
@ -24,7 +24,7 @@ namespace LibHac.Fs
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
if (source.Length == 0)
|
||||
return Result.Success;
|
||||
@ -37,17 +37,17 @@ namespace LibHac.Fs
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result FlushImpl()
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result SetSizeImpl(long size)
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
return ResultFs.UnsupportedOperationInMemoryStorageSetSize.Log();
|
||||
}
|
||||
|
||||
protected override Result GetSizeImpl(out long size)
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
size = StorageBuffer.Length;
|
||||
|
||||
|
@ -331,6 +331,10 @@ namespace LibHac.Fs
|
||||
public static Result.Base InvalidCacheStorageIndex => new Result.Base(ModuleFs, 6070);
|
||||
/// <summary>Up to 10 file systems can be committed at the same time.<br/>Error code: 2002-6071; Inner value: 0x2f6e02</summary>
|
||||
public static Result.Base InvalidCommitNameCount => new Result.Base(ModuleFs, 6071);
|
||||
/// <summary>Error code: 2002-6072; Inner value: 0x2f7002</summary>
|
||||
public static Result.Base InvalidOpenMode => new Result.Base(ModuleFs, 6072);
|
||||
/// <summary>Error code: 2002-6074; Inner value: 0x2f7402</summary>
|
||||
public static Result.Base InvalidDirectoryOpenMode => new Result.Base(ModuleFs, 6074);
|
||||
|
||||
/// <summary>Error code: 2002-6080; Range: 6080-6099; Inner value: 0x2f8002</summary>
|
||||
public static Result.Base InvalidEnumValue { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 6080, 6099); }
|
||||
@ -386,6 +390,8 @@ namespace LibHac.Fs
|
||||
public static Result.Base UnsupportedOperationReadOnlyFileSystemGetSpace => new Result.Base(ModuleFs, 6371);
|
||||
/// <summary>Error code: 2002-6372; Inner value: 0x31c802</summary>
|
||||
public static Result.Base UnsupportedOperationModifyReadOnlyFile => new Result.Base(ModuleFs, 6372);
|
||||
/// <summary>Error code: 2002-6373; Inner value: 0x31ca02</summary>
|
||||
public static Result.Base UnsupportedOperationInReadOnlyFile => new Result.Base(ModuleFs, 6373);
|
||||
/// <summary>Error code: 2002-6374; Inner value: 0x31cc02</summary>
|
||||
public static Result.Base UnsupportedOperationModifyPartitionFileSystem => new Result.Base(ModuleFs, 6374);
|
||||
/// <summary>Called PartitionFileSystemCore::CommitProvisionally.<br/>Error code: 2002-6375; Inner value: 0x31ce02</summary>
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsService;
|
||||
using LibHac.FsSystem;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsService;
|
||||
using LibHac.Ncm;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsService;
|
||||
using LibHac.FsSystem;
|
||||
using static LibHac.Fs.CommonMountNames;
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsService;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.Ncm;
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsService;
|
||||
|
||||
namespace LibHac.Fs.Shim
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsService;
|
||||
|
||||
namespace LibHac.Fs.Shim
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsService;
|
||||
|
||||
namespace LibHac.Fs.Shim
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsService;
|
||||
using LibHac.FsSystem;
|
||||
using static LibHac.Fs.CommonMountNames;
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsService;
|
||||
using LibHac.Ncm;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsService;
|
||||
|
||||
namespace LibHac.Fs.Shim
|
||||
|
@ -1,4 +1,5 @@
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsService;
|
||||
|
||||
namespace LibHac.Fs.Shim
|
||||
|
@ -1,87 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
public abstract class StorageBase : IStorage
|
||||
{
|
||||
// 0 = not disposed; 1 = disposed
|
||||
private int _disposedState;
|
||||
private bool IsDisposed => _disposedState != 0;
|
||||
|
||||
protected abstract Result ReadImpl(long offset, Span<byte> destination);
|
||||
protected abstract Result WriteImpl(long offset, ReadOnlySpan<byte> source);
|
||||
protected abstract Result FlushImpl();
|
||||
protected abstract Result GetSizeImpl(out long size);
|
||||
protected abstract Result SetSizeImpl(long size);
|
||||
|
||||
protected virtual Result OperateRangeImpl(Span<byte> outBuffer, OperationId operationId, long offset, long size,
|
||||
ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
public Result Read(long offset, Span<byte> destination)
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return ReadImpl(offset, destination);
|
||||
}
|
||||
|
||||
public Result Write(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return WriteImpl(offset, source);
|
||||
}
|
||||
|
||||
public Result Flush()
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return FlushImpl();
|
||||
}
|
||||
|
||||
public Result SetSize(long size)
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return SetSizeImpl(size);
|
||||
}
|
||||
|
||||
public Result GetSize(out long size)
|
||||
{
|
||||
size = default;
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return GetSizeImpl(out size);
|
||||
}
|
||||
|
||||
public Result OperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size,
|
||||
ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
return OperateRange(outBuffer, operationId, offset, size, inBuffer);
|
||||
}
|
||||
|
||||
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) { }
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsRangeValid(long offset, long size, long totalSize)
|
||||
{
|
||||
return offset >= 0 && size >= 0 && size <= totalSize && offset <= totalSize - size;
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
public class SubStorage2 : StorageBase
|
||||
public class SubStorage2 : IStorage
|
||||
{
|
||||
private IStorage BaseStorage { get; }
|
||||
private long Offset { get; }
|
||||
@ -23,7 +23,7 @@ namespace LibHac.Fs
|
||||
Size = size;
|
||||
}
|
||||
|
||||
protected override Result ReadImpl(long offset, Span<byte> destination)
|
||||
protected override Result DoRead(long offset, Span<byte> destination)
|
||||
{
|
||||
if (BaseStorage == null) return ResultFs.SubStorageNotInitialized.Log();
|
||||
if (destination.Length == 0) return Result.Success;
|
||||
@ -33,7 +33,7 @@ namespace LibHac.Fs
|
||||
return BaseStorage.Read(Offset + offset, destination);
|
||||
}
|
||||
|
||||
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
if (BaseStorage == null) return ResultFs.SubStorageNotInitialized.Log();
|
||||
if (source.Length == 0) return Result.Success;
|
||||
@ -43,14 +43,14 @@ namespace LibHac.Fs
|
||||
return BaseStorage.Write(Offset + offset, source);
|
||||
}
|
||||
|
||||
protected override Result FlushImpl()
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
if (BaseStorage == null) return ResultFs.SubStorageNotInitialized.Log();
|
||||
|
||||
return BaseStorage.Flush();
|
||||
}
|
||||
|
||||
protected override Result SetSizeImpl(long size)
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
if (BaseStorage == null) return ResultFs.SubStorageNotInitialized.Log();
|
||||
if (!IsResizable) return ResultFs.SubStorageNotResizable.Log();
|
||||
@ -72,7 +72,7 @@ namespace LibHac.Fs
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result GetSizeImpl(out long size)
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
size = default;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.Diagnostics;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
{
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.Diagnostics;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
{
|
||||
|
@ -62,7 +62,7 @@ namespace LibHac.FsService.Creators
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private class ReadOnlyGameCardStorage : StorageBase
|
||||
private class ReadOnlyGameCardStorage : IStorage
|
||||
{
|
||||
private EmulatedGameCard GameCard { get; }
|
||||
private GameCardHandle Handle { get; set; }
|
||||
@ -87,7 +87,7 @@ namespace LibHac.FsService.Creators
|
||||
imageHash.CopyTo(ImageHash);
|
||||
}
|
||||
|
||||
protected override Result ReadImpl(long offset, Span<byte> destination)
|
||||
protected override Result DoRead(long offset, Span<byte> destination)
|
||||
{
|
||||
// In secure mode, if Handle is old and the card's device ID and
|
||||
// header hash are still the same, Handle is updated to the new handle
|
||||
@ -95,22 +95,22 @@ namespace LibHac.FsService.Creators
|
||||
return GameCard.Read(Handle, offset, destination);
|
||||
}
|
||||
|
||||
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
return ResultFs.UnsupportedOperationInRoGameCardStorageWrite.Log();
|
||||
}
|
||||
|
||||
protected override Result FlushImpl()
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result SetSizeImpl(long size)
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
return ResultFs.UnsupportedOperationInRoGameCardStorageSetSize.Log();
|
||||
}
|
||||
|
||||
protected override Result GetSizeImpl(out long size)
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
size = 0;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
{
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSystem;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
|
@ -1,4 +1,5 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSystem.Save;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
|
@ -1,4 +1,4 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSystem.NcaUtils;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
|
@ -1,5 +1,5 @@
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.FsSystem.Detail;
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSystem.RomFs;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.FsSystem.Save;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.FsSystem.Detail;
|
||||
using LibHac.FsSystem.NcaUtils;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSystem;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
|
@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsService.Creators;
|
||||
|
||||
namespace LibHac.FsService
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsService.Impl;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.Kvdb;
|
||||
|
@ -3,6 +3,7 @@ using System.Buffers.Text;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.Fs.Shim;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.FsService.Creators;
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.Ncm;
|
||||
using LibHac.Spl;
|
||||
|
@ -1,4 +1,4 @@
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsService
|
||||
{
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.Fs.Shim;
|
||||
|
||||
namespace LibHac.FsService.Impl
|
||||
|
@ -1,5 +1,6 @@
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSystem;
|
||||
|
||||
namespace LibHac.FsService
|
||||
|
@ -31,7 +31,7 @@ namespace LibHac.FsSystem
|
||||
SubsectionOffsets = SubsectionEntries.Select(x => x.Offset).ToList();
|
||||
}
|
||||
|
||||
protected override Result ReadImpl(long offset, Span<byte> destination)
|
||||
protected override Result DoRead(long offset, Span<byte> destination)
|
||||
{
|
||||
AesSubsectionEntry entry = GetSubsectionEntry(offset);
|
||||
|
||||
@ -47,7 +47,7 @@ namespace LibHac.FsSystem
|
||||
{
|
||||
UpdateCounterSubsection(entry.Counter);
|
||||
|
||||
Result rc = base.ReadImpl(inPos, destination.Slice(outPos, bytesToRead));
|
||||
Result rc = base.DoRead(inPos, destination.Slice(outPos, bytesToRead));
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
|
||||
@ -64,12 +64,12 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
return ResultFs.UnsupportedOperationInAesCtrExStorageWrite.Log();
|
||||
}
|
||||
|
||||
protected override Result FlushImpl()
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return Result.Success;
|
||||
}
|
||||
|
@ -59,9 +59,9 @@ namespace LibHac.FsSystem
|
||||
Counter = _decryptor.Counter;
|
||||
}
|
||||
|
||||
protected override Result ReadImpl(long offset, Span<byte> destination)
|
||||
protected override Result DoRead(long offset, Span<byte> destination)
|
||||
{
|
||||
Result rc = base.ReadImpl(offset, destination);
|
||||
Result rc = base.DoRead(offset, destination);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
lock (_locker)
|
||||
@ -73,7 +73,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
byte[] encrypted = ArrayPool<byte>.Shared.Rent(source.Length);
|
||||
try
|
||||
@ -87,7 +87,7 @@ namespace LibHac.FsSystem
|
||||
_decryptor.TransformBlock(encryptedSpan);
|
||||
}
|
||||
|
||||
Result rc = base.WriteImpl(offset, encryptedSpan);
|
||||
Result rc = base.DoWrite(offset, encryptedSpan);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
finally
|
||||
|
@ -38,14 +38,14 @@ namespace LibHac.FsSystem
|
||||
_key2 = key2.ToArray();
|
||||
}
|
||||
|
||||
protected override Result ReadImpl(long offset, Span<byte> destination)
|
||||
protected override Result DoRead(long offset, Span<byte> destination)
|
||||
{
|
||||
int size = destination.Length;
|
||||
long sectorIndex = offset / SectorSize;
|
||||
|
||||
if (_decryptor == null) _decryptor = new Aes128XtsTransform(_key1, _key2, true);
|
||||
|
||||
Result rc = base.ReadImpl(offset, _tempBuffer.AsSpan(0, size));
|
||||
Result rc = base.DoRead(offset, _tempBuffer.AsSpan(0, size));
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
_decryptor.TransformBlock(_tempBuffer, 0, size, (ulong)sectorIndex);
|
||||
@ -54,7 +54,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
int size = source.Length;
|
||||
long sectorIndex = offset / SectorSize;
|
||||
@ -64,10 +64,10 @@ namespace LibHac.FsSystem
|
||||
source.CopyTo(_tempBuffer);
|
||||
_encryptor.TransformBlock(_tempBuffer, 0, size, (ulong)sectorIndex);
|
||||
|
||||
return base.WriteImpl(offset, _tempBuffer.AsSpan(0, size));
|
||||
return base.DoWrite(offset, _tempBuffer.AsSpan(0, size));
|
||||
}
|
||||
|
||||
protected override Result FlushImpl()
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return BaseStorage.Flush();
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
@ -20,7 +21,7 @@ namespace LibHac.FsSystem
|
||||
Path = path;
|
||||
}
|
||||
|
||||
public Result Read(out long entriesRead, Span<DirectoryEntry> entryBuffer)
|
||||
protected override Result DoRead(out long entriesRead, Span<DirectoryEntry> entryBuffer)
|
||||
{
|
||||
Result rc = BaseDirectory.Read(out entriesRead, entryBuffer);
|
||||
if (rc.IsFailure()) return rc;
|
||||
@ -46,7 +47,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result GetEntryCount(out long entryCount)
|
||||
protected override Result DoGetEntryCount(out long entryCount)
|
||||
{
|
||||
return BaseDirectory.GetEntryCount(out entryCount);
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
public class AesXtsFile : FileBase
|
||||
public class AesXtsFile : IFile
|
||||
{
|
||||
private IFile BaseFile { get; }
|
||||
private U8String Path { get; }
|
||||
@ -54,11 +55,11 @@ namespace LibHac.FsSystem
|
||||
return key;
|
||||
}
|
||||
|
||||
protected override Result ReadImpl(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
||||
protected override Result DoRead(out long bytesRead, long offset, Span<byte> destination, in ReadOption option)
|
||||
{
|
||||
bytesRead = default;
|
||||
|
||||
Result rc = ValidateReadParams(out long toRead, offset, destination.Length, Mode);
|
||||
Result rc = DryRead(out long toRead, offset, destination.Length, in option, Mode);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = BaseStorage.Read(offset, destination.Slice(0, (int)toRead));
|
||||
@ -68,21 +69,21 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source, in WriteOption option)
|
||||
{
|
||||
Result rc = ValidateWriteParams(offset, source.Length, Mode, out bool isResizeNeeded);
|
||||
Result rc = DryWrite(out bool isResizeNeeded, offset, source.Length, in option, Mode);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (isResizeNeeded)
|
||||
{
|
||||
rc = SetSizeImpl(offset + source.Length);
|
||||
rc = DoSetSize(offset + source.Length);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
|
||||
rc = BaseStorage.Write(offset, source);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if ((options & WriteOption.Flush) != 0)
|
||||
if (option.HasFlushFlag())
|
||||
{
|
||||
return Flush();
|
||||
}
|
||||
@ -90,18 +91,24 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result FlushImpl()
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return BaseStorage.Flush();
|
||||
}
|
||||
|
||||
protected override Result GetSizeImpl(out long size)
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
size = Header.Size;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result SetSizeImpl(long size)
|
||||
protected override Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size,
|
||||
ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
Header.SetSize(size, VerificationKey);
|
||||
|
||||
|
@ -3,6 +3,7 @@ using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
|
@ -2,10 +2,11 @@
|
||||
using System.Diagnostics;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
public class AesXtsFileSystem : FileSystemBase
|
||||
public class AesXtsFileSystem : IFileSystem
|
||||
{
|
||||
public int BlockSize { get; }
|
||||
|
||||
@ -29,12 +30,12 @@ namespace LibHac.FsSystem
|
||||
BlockSize = blockSize;
|
||||
}
|
||||
|
||||
protected override Result CreateDirectoryImpl(U8Span path)
|
||||
protected override Result DoCreateDirectory(U8Span path)
|
||||
{
|
||||
return BaseFileSystem.CreateDirectory(path);
|
||||
}
|
||||
|
||||
protected override Result CreateFileImpl(U8Span path, long size, CreateFileOptions options)
|
||||
protected override Result DoCreateFile(U8Span path, long size, CreateFileOptions options)
|
||||
{
|
||||
return CreateFile(path, size, options, new byte[0x20]);
|
||||
}
|
||||
@ -68,27 +69,27 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result DeleteDirectoryImpl(U8Span path)
|
||||
protected override Result DoDeleteDirectory(U8Span path)
|
||||
{
|
||||
return BaseFileSystem.DeleteDirectory(path);
|
||||
}
|
||||
|
||||
protected override Result DeleteDirectoryRecursivelyImpl(U8Span path)
|
||||
protected override Result DoDeleteDirectoryRecursively(U8Span path)
|
||||
{
|
||||
return BaseFileSystem.DeleteDirectoryRecursively(path);
|
||||
}
|
||||
|
||||
protected override Result CleanDirectoryRecursivelyImpl(U8Span path)
|
||||
protected override Result DoCleanDirectoryRecursively(U8Span path)
|
||||
{
|
||||
return BaseFileSystem.CleanDirectoryRecursively(path);
|
||||
}
|
||||
|
||||
protected override Result DeleteFileImpl(U8Span path)
|
||||
protected override Result DoDeleteFile(U8Span path)
|
||||
{
|
||||
return BaseFileSystem.DeleteFile(path);
|
||||
}
|
||||
|
||||
protected override Result OpenDirectoryImpl(out IDirectory directory, U8Span path, OpenDirectoryMode mode)
|
||||
protected override Result DoOpenDirectory(out IDirectory directory, U8Span path, OpenDirectoryMode mode)
|
||||
{
|
||||
directory = default;
|
||||
|
||||
@ -99,7 +100,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result OpenFileImpl(out IFile file, U8Span path, OpenMode mode)
|
||||
protected override Result DoOpenFile(out IFile file, U8Span path, OpenMode mode)
|
||||
{
|
||||
file = default;
|
||||
|
||||
@ -112,7 +113,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result RenameDirectoryImpl(U8Span oldPath, U8Span newPath)
|
||||
protected override Result DoRenameDirectory(U8Span oldPath, U8Span newPath)
|
||||
{
|
||||
// todo: Return proper result codes
|
||||
|
||||
@ -172,7 +173,7 @@ namespace LibHac.FsSystem
|
||||
}
|
||||
}
|
||||
|
||||
protected override Result RenameFileImpl(U8Span oldPath, U8Span newPath)
|
||||
protected override Result DoRenameFile(U8Span oldPath, U8Span newPath)
|
||||
{
|
||||
// todo: Return proper result codes
|
||||
|
||||
@ -196,42 +197,42 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result GetEntryTypeImpl(out DirectoryEntryType entryType, U8Span path)
|
||||
protected override Result DoGetEntryType(out DirectoryEntryType entryType, U8Span path)
|
||||
{
|
||||
return BaseFileSystem.GetEntryType(out entryType, path);
|
||||
}
|
||||
|
||||
protected override Result GetFileTimeStampRawImpl(out FileTimeStampRaw timeStamp, U8Span path)
|
||||
protected override Result DoGetFileTimeStampRaw(out FileTimeStampRaw timeStamp, U8Span path)
|
||||
{
|
||||
return BaseFileSystem.GetFileTimeStampRaw(out timeStamp, path);
|
||||
}
|
||||
|
||||
protected override Result GetFreeSpaceSizeImpl(out long freeSpace, U8Span path)
|
||||
protected override Result DoGetFreeSpaceSize(out long freeSpace, U8Span path)
|
||||
{
|
||||
return BaseFileSystem.GetFreeSpaceSize(out freeSpace, path);
|
||||
}
|
||||
|
||||
protected override Result GetTotalSpaceSizeImpl(out long totalSpace, U8Span path)
|
||||
protected override Result DoGetTotalSpaceSize(out long totalSpace, U8Span path)
|
||||
{
|
||||
return BaseFileSystem.GetTotalSpaceSize(out totalSpace, path);
|
||||
}
|
||||
|
||||
protected override Result CommitImpl()
|
||||
protected override Result DoCommit()
|
||||
{
|
||||
return BaseFileSystem.Commit();
|
||||
}
|
||||
|
||||
protected override Result CommitProvisionallyImpl(long commitCount)
|
||||
protected override Result DoCommitProvisionally(long counter)
|
||||
{
|
||||
return BaseFileSystem.CommitProvisionally(commitCount);
|
||||
return BaseFileSystem.CommitProvisionally(counter);
|
||||
}
|
||||
|
||||
protected override Result RollbackImpl()
|
||||
protected override Result DoRollback()
|
||||
{
|
||||
return BaseFileSystem.Rollback();
|
||||
}
|
||||
|
||||
protected override Result QueryEntryImpl(Span<byte> outBuffer, ReadOnlySpan<byte> inBuffer, QueryId queryId,
|
||||
protected override Result DoQueryEntry(Span<byte> outBuffer, ReadOnlySpan<byte> inBuffer, QueryId queryId,
|
||||
U8Span path)
|
||||
{
|
||||
return BaseFileSystem.QueryEntry(outBuffer, inBuffer, queryId, path);
|
||||
|
@ -4,7 +4,7 @@ using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
public class CachedStorage : StorageBase
|
||||
public class CachedStorage : IStorage
|
||||
{
|
||||
private IStorage BaseStorage { get; }
|
||||
private int BlockSize { get; }
|
||||
@ -33,7 +33,7 @@ namespace LibHac.FsSystem
|
||||
public CachedStorage(SectorStorage baseStorage, int cacheSize, bool leaveOpen)
|
||||
: this(baseStorage, baseStorage.SectorSize, cacheSize, leaveOpen) { }
|
||||
|
||||
protected override Result ReadImpl(long offset, Span<byte> destination)
|
||||
protected override Result DoRead(long offset, Span<byte> destination)
|
||||
{
|
||||
long remaining = destination.Length;
|
||||
long inOffset = offset;
|
||||
@ -63,7 +63,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
long remaining = source.Length;
|
||||
long inOffset = offset;
|
||||
@ -95,7 +95,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result FlushImpl()
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
lock (Blocks)
|
||||
{
|
||||
@ -108,13 +108,13 @@ namespace LibHac.FsSystem
|
||||
return BaseStorage.Flush();
|
||||
}
|
||||
|
||||
protected override Result GetSizeImpl(out long size)
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
size = Length;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result SetSizeImpl(long size)
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
Result rc = BaseStorage.SetSize(size);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
@ -38,7 +39,7 @@ namespace LibHac.FsSystem
|
||||
_path.Str[PathTools.MaxPathLength] = StringTraits.NullTerminator;
|
||||
}
|
||||
|
||||
public Result Read(out long entriesRead, Span<DirectoryEntry> entryBuffer)
|
||||
protected override Result DoRead(out long entriesRead, Span<DirectoryEntry> entryBuffer)
|
||||
{
|
||||
entriesRead = 0;
|
||||
var entry = new DirectoryEntry();
|
||||
@ -81,7 +82,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result GetEntryCount(out long entryCount)
|
||||
protected override Result DoGetEntryCount(out long entryCount)
|
||||
{
|
||||
entryCount = 0;
|
||||
long count = 0;
|
||||
|
@ -4,10 +4,11 @@ using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
public class ConcatenationFile : FileBase
|
||||
public class ConcatenationFile : IFile
|
||||
{
|
||||
private IFileSystem BaseFileSystem { get; }
|
||||
private U8String FilePath { get; }
|
||||
@ -34,14 +35,15 @@ namespace LibHac.FsSystem
|
||||
}
|
||||
}
|
||||
|
||||
protected override Result ReadImpl(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
||||
protected override Result DoRead(out long bytesRead, long offset, Span<byte> destination,
|
||||
in ReadOption option)
|
||||
{
|
||||
bytesRead = default;
|
||||
|
||||
long inPos = offset;
|
||||
int outPos = 0;
|
||||
|
||||
Result rc = ValidateReadParams(out long remaining, offset, destination.Length, Mode);
|
||||
Result rc = DryRead(out long remaining, offset, destination.Length, in option, Mode);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
GetSize(out long fileSize).ThrowIfFailure();
|
||||
@ -55,7 +57,7 @@ namespace LibHac.FsSystem
|
||||
long fileEndOffset = Math.Min((fileIndex + 1) * SubFileSize, fileSize);
|
||||
int bytesToRead = (int)Math.Min(fileEndOffset - inPos, remaining);
|
||||
|
||||
rc = file.Read(out long subFileBytesRead, fileOffset, destination.Slice(outPos, bytesToRead), options);
|
||||
rc = file.Read(out long subFileBytesRead, fileOffset, destination.Slice(outPos, bytesToRead), option);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
outPos += (int)subFileBytesRead;
|
||||
@ -70,9 +72,9 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source, in WriteOption option)
|
||||
{
|
||||
Result rc = ValidateWriteParams(offset, source.Length, Mode, out _);
|
||||
Result rc = DryWrite(out _, offset, source.Length, in option, Mode);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
int inPos = 0;
|
||||
@ -91,7 +93,7 @@ namespace LibHac.FsSystem
|
||||
long fileEndOffset = Math.Min((fileIndex + 1) * SubFileSize, fileSize);
|
||||
int bytesToWrite = (int)Math.Min(fileEndOffset - outPos, remaining);
|
||||
|
||||
rc = file.Write(fileOffset, source.Slice(inPos, bytesToWrite), options);
|
||||
rc = file.Write(fileOffset, source.Slice(inPos, bytesToWrite), option);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
outPos += bytesToWrite;
|
||||
@ -99,7 +101,7 @@ namespace LibHac.FsSystem
|
||||
remaining -= bytesToWrite;
|
||||
}
|
||||
|
||||
if (options.HasFlag(WriteOption.Flush))
|
||||
if (option.HasFlushFlag())
|
||||
{
|
||||
return Flush();
|
||||
}
|
||||
@ -107,7 +109,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result FlushImpl()
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
foreach (IFile file in Sources)
|
||||
{
|
||||
@ -118,7 +120,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result GetSizeImpl(out long size)
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
size = default;
|
||||
|
||||
@ -133,7 +135,12 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result SetSizeImpl(long size)
|
||||
protected override Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size, ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
Result rc = GetSize(out long currentSize);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
@ -5,6 +5,7 @@ using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
@ -22,7 +23,7 @@ namespace LibHac.FsSystem
|
||||
/// Each sub-file except the final one must have the size <see cref="SubFileSize"/> that was specified
|
||||
/// at the creation of the <see cref="ConcatenationFileSystem"/>.
|
||||
/// </remarks>
|
||||
public class ConcatenationFileSystem : FileSystemBase
|
||||
public class ConcatenationFileSystem : IFileSystem
|
||||
{
|
||||
private const long DefaultSubFileSize = 0xFFFF0000; // Hard-coded value used by FS
|
||||
private IAttributeFileSystem BaseFileSystem { get; }
|
||||
@ -96,7 +97,7 @@ namespace LibHac.FsSystem
|
||||
return BaseFileSystem.SetFileAttributes(path, NxFileAttributes.Archive);
|
||||
}
|
||||
|
||||
protected override Result CreateDirectoryImpl(U8Span path)
|
||||
protected override Result DoCreateDirectory(U8Span path)
|
||||
{
|
||||
var parent = new U8Span(PathTools.GetParentDirectory(path));
|
||||
|
||||
@ -109,7 +110,7 @@ namespace LibHac.FsSystem
|
||||
return BaseFileSystem.CreateDirectory(path);
|
||||
}
|
||||
|
||||
protected override Result CreateFileImpl(U8Span path, long size, CreateFileOptions options)
|
||||
protected override Result DoCreateFile(U8Span path, long size, CreateFileOptions options)
|
||||
{
|
||||
CreateFileOptions newOptions = options & ~CreateFileOptions.CreateConcatenationFile;
|
||||
|
||||
@ -156,7 +157,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result DeleteDirectoryImpl(U8Span path)
|
||||
protected override Result DoDeleteDirectory(U8Span path)
|
||||
{
|
||||
if (IsConcatenationFile(path))
|
||||
{
|
||||
@ -166,21 +167,21 @@ namespace LibHac.FsSystem
|
||||
return BaseFileSystem.DeleteDirectory(path);
|
||||
}
|
||||
|
||||
protected override Result DeleteDirectoryRecursivelyImpl(U8Span path)
|
||||
protected override Result DoDeleteDirectoryRecursively(U8Span path)
|
||||
{
|
||||
if (IsConcatenationFile(path)) return ResultFs.PathNotFound.Log();
|
||||
|
||||
return BaseFileSystem.DeleteDirectoryRecursively(path);
|
||||
}
|
||||
|
||||
protected override Result CleanDirectoryRecursivelyImpl(U8Span path)
|
||||
protected override Result DoCleanDirectoryRecursively(U8Span path)
|
||||
{
|
||||
if (IsConcatenationFile(path)) return ResultFs.PathNotFound.Log();
|
||||
|
||||
return BaseFileSystem.CleanDirectoryRecursively(path);
|
||||
}
|
||||
|
||||
protected override Result DeleteFileImpl(U8Span path)
|
||||
protected override Result DoDeleteFile(U8Span path)
|
||||
{
|
||||
if (!IsConcatenationFile(path))
|
||||
{
|
||||
@ -205,7 +206,7 @@ namespace LibHac.FsSystem
|
||||
return BaseFileSystem.DeleteDirectory(path);
|
||||
}
|
||||
|
||||
protected override Result OpenDirectoryImpl(out IDirectory directory, U8Span path, OpenDirectoryMode mode)
|
||||
protected override Result DoOpenDirectory(out IDirectory directory, U8Span path, OpenDirectoryMode mode)
|
||||
{
|
||||
directory = default;
|
||||
|
||||
@ -221,7 +222,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result OpenFileImpl(out IFile file, U8Span path, OpenMode mode)
|
||||
protected override Result DoOpenFile(out IFile file, U8Span path, OpenMode mode)
|
||||
{
|
||||
file = default;
|
||||
|
||||
@ -253,7 +254,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result RenameDirectoryImpl(U8Span oldPath, U8Span newPath)
|
||||
protected override Result DoRenameDirectory(U8Span oldPath, U8Span newPath)
|
||||
{
|
||||
if (IsConcatenationFile(oldPath))
|
||||
{
|
||||
@ -263,7 +264,7 @@ namespace LibHac.FsSystem
|
||||
return BaseFileSystem.RenameDirectory(oldPath, newPath);
|
||||
}
|
||||
|
||||
protected override Result RenameFileImpl(U8Span oldPath, U8Span newPath)
|
||||
protected override Result DoRenameFile(U8Span oldPath, U8Span newPath)
|
||||
{
|
||||
if (IsConcatenationFile(oldPath))
|
||||
{
|
||||
@ -275,7 +276,7 @@ namespace LibHac.FsSystem
|
||||
}
|
||||
}
|
||||
|
||||
protected override Result GetEntryTypeImpl(out DirectoryEntryType entryType, U8Span path)
|
||||
protected override Result DoGetEntryType(out DirectoryEntryType entryType, U8Span path)
|
||||
{
|
||||
if (IsConcatenationFile(path))
|
||||
{
|
||||
@ -286,37 +287,37 @@ namespace LibHac.FsSystem
|
||||
return BaseFileSystem.GetEntryType(out entryType, path);
|
||||
}
|
||||
|
||||
protected override Result GetFreeSpaceSizeImpl(out long freeSpace, U8Span path)
|
||||
protected override Result DoGetFreeSpaceSize(out long freeSpace, U8Span path)
|
||||
{
|
||||
return BaseFileSystem.GetFreeSpaceSize(out freeSpace, path);
|
||||
}
|
||||
|
||||
protected override Result GetTotalSpaceSizeImpl(out long totalSpace, U8Span path)
|
||||
protected override Result DoGetTotalSpaceSize(out long totalSpace, U8Span path)
|
||||
{
|
||||
return BaseFileSystem.GetTotalSpaceSize(out totalSpace, path);
|
||||
}
|
||||
|
||||
protected override Result GetFileTimeStampRawImpl(out FileTimeStampRaw timeStamp, U8Span path)
|
||||
protected override Result DoGetFileTimeStampRaw(out FileTimeStampRaw timeStamp, U8Span path)
|
||||
{
|
||||
return BaseFileSystem.GetFileTimeStampRaw(out timeStamp, path);
|
||||
}
|
||||
|
||||
protected override Result CommitImpl()
|
||||
protected override Result DoCommit()
|
||||
{
|
||||
return BaseFileSystem.Commit();
|
||||
}
|
||||
|
||||
protected override Result CommitProvisionallyImpl(long commitCount)
|
||||
protected override Result DoCommitProvisionally(long counter)
|
||||
{
|
||||
return BaseFileSystem.CommitProvisionally(commitCount);
|
||||
return BaseFileSystem.CommitProvisionally(counter);
|
||||
}
|
||||
|
||||
protected override Result FlushImpl()
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return BaseFileSystem.Flush();
|
||||
}
|
||||
|
||||
protected override Result QueryEntryImpl(Span<byte> outBuffer, ReadOnlySpan<byte> inBuffer, QueryId queryId,
|
||||
protected override Result DoQueryEntry(Span<byte> outBuffer, ReadOnlySpan<byte> inBuffer, QueryId queryId,
|
||||
U8Span path)
|
||||
{
|
||||
if (queryId != QueryId.MakeConcatFile) return ResultFs.UnsupportedOperationInConcatFsQueryEntry.Log();
|
||||
|
@ -4,7 +4,7 @@ using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
public class ConcatenationStorage : StorageBase
|
||||
public class ConcatenationStorage : IStorage
|
||||
{
|
||||
private ConcatSource[] Sources { get; }
|
||||
private long Length { get; }
|
||||
@ -28,7 +28,7 @@ namespace LibHac.FsSystem
|
||||
Length = length;
|
||||
}
|
||||
|
||||
protected override Result ReadImpl(long offset, Span<byte> destination)
|
||||
protected override Result DoRead(long offset, Span<byte> destination)
|
||||
{
|
||||
long inPos = offset;
|
||||
int outPos = 0;
|
||||
@ -59,7 +59,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
long inPos = offset;
|
||||
int outPos = 0;
|
||||
@ -90,7 +90,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result FlushImpl()
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
foreach (ConcatSource source in Sources)
|
||||
{
|
||||
@ -101,12 +101,12 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result SetSizeImpl(long size)
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
protected override Result GetSizeImpl(out long size)
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
size = Length;
|
||||
return Result.Success;
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
|
@ -1,9 +1,10 @@
|
||||
using System;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
public class DirectorySaveDataFile : FileBase
|
||||
public class DirectorySaveDataFile : IFile
|
||||
{
|
||||
private IFile BaseFile { get; }
|
||||
private DirectorySaveDataFileSystem ParentFs { get; }
|
||||
@ -16,31 +17,37 @@ namespace LibHac.FsSystem
|
||||
Mode = mode;
|
||||
}
|
||||
|
||||
protected override Result ReadImpl(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
||||
protected override Result DoRead(out long bytesRead, long offset, Span<byte> destination,
|
||||
in ReadOption option)
|
||||
{
|
||||
return BaseFile.Read(out bytesRead, offset, destination, options);
|
||||
return BaseFile.Read(out bytesRead, offset, destination, in option);
|
||||
}
|
||||
|
||||
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source, in WriteOption option)
|
||||
{
|
||||
return BaseFile.Write(offset, source, options);
|
||||
return BaseFile.Write(offset, source, in option);
|
||||
}
|
||||
|
||||
protected override Result FlushImpl()
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return BaseFile.Flush();
|
||||
}
|
||||
|
||||
protected override Result GetSizeImpl(out long size)
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
return BaseFile.GetSize(out size);
|
||||
}
|
||||
|
||||
protected override Result SetSizeImpl(long size)
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
return BaseFile.SetSize(size);
|
||||
}
|
||||
|
||||
protected override Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size, ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
return BaseFile.OperateRange(outBuffer, operationId, offset, size, inBuffer);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (Mode.HasFlag(OpenMode.Write))
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
@ -12,7 +13,7 @@ namespace LibHac.FsSystem
|
||||
/// underlying <see cref="IFileSystem"/> is atomic.
|
||||
/// This class is based on nn::fssystem::DirectorySaveDataFileSystem in SDK 10.4.0 used in FS 10.0.0
|
||||
/// </remarks>
|
||||
public class DirectorySaveDataFileSystem : FileSystemBase
|
||||
public class DirectorySaveDataFileSystem : IFileSystem
|
||||
{
|
||||
private const int IdealWorkBufferSize = 0x100000; // 1 MiB
|
||||
|
||||
@ -97,7 +98,7 @@ namespace LibHac.FsSystem
|
||||
return BaseFs.RenameDirectory(SynchronizingDirectoryPath, CommittedDirectoryPath);
|
||||
}
|
||||
|
||||
protected override Result CreateDirectoryImpl(U8Span path)
|
||||
protected override Result DoCreateDirectory(U8Span path)
|
||||
{
|
||||
FsPath fullPath;
|
||||
unsafe { _ = &fullPath; } // workaround for CS0165
|
||||
@ -111,7 +112,7 @@ namespace LibHac.FsSystem
|
||||
}
|
||||
}
|
||||
|
||||
protected override Result CreateFileImpl(U8Span path, long size, CreateFileOptions options)
|
||||
protected override Result DoCreateFile(U8Span path, long size, CreateFileOptions options)
|
||||
{
|
||||
FsPath fullPath;
|
||||
unsafe { _ = &fullPath; } // workaround for CS0165
|
||||
@ -125,7 +126,7 @@ namespace LibHac.FsSystem
|
||||
}
|
||||
}
|
||||
|
||||
protected override Result DeleteDirectoryImpl(U8Span path)
|
||||
protected override Result DoDeleteDirectory(U8Span path)
|
||||
{
|
||||
FsPath fullPath;
|
||||
unsafe { _ = &fullPath; } // workaround for CS0165
|
||||
@ -139,7 +140,7 @@ namespace LibHac.FsSystem
|
||||
}
|
||||
}
|
||||
|
||||
protected override Result DeleteDirectoryRecursivelyImpl(U8Span path)
|
||||
protected override Result DoDeleteDirectoryRecursively(U8Span path)
|
||||
{
|
||||
FsPath fullPath;
|
||||
unsafe { _ = &fullPath; } // workaround for CS0165
|
||||
@ -153,7 +154,7 @@ namespace LibHac.FsSystem
|
||||
}
|
||||
}
|
||||
|
||||
protected override Result CleanDirectoryRecursivelyImpl(U8Span path)
|
||||
protected override Result DoCleanDirectoryRecursively(U8Span path)
|
||||
{
|
||||
FsPath fullPath;
|
||||
unsafe { _ = &fullPath; } // workaround for CS0165
|
||||
@ -167,7 +168,7 @@ namespace LibHac.FsSystem
|
||||
}
|
||||
}
|
||||
|
||||
protected override Result DeleteFileImpl(U8Span path)
|
||||
protected override Result DoDeleteFile(U8Span path)
|
||||
{
|
||||
FsPath fullPath;
|
||||
unsafe { _ = &fullPath; } // workaround for CS0165
|
||||
@ -181,7 +182,7 @@ namespace LibHac.FsSystem
|
||||
}
|
||||
}
|
||||
|
||||
protected override Result OpenDirectoryImpl(out IDirectory directory, U8Span path, OpenDirectoryMode mode)
|
||||
protected override Result DoOpenDirectory(out IDirectory directory, U8Span path, OpenDirectoryMode mode)
|
||||
{
|
||||
FsPath fullPath;
|
||||
unsafe { _ = &fullPath; } // workaround for CS0165
|
||||
@ -199,7 +200,7 @@ namespace LibHac.FsSystem
|
||||
}
|
||||
}
|
||||
|
||||
protected override Result OpenFileImpl(out IFile file, U8Span path, OpenMode mode)
|
||||
protected override Result DoOpenFile(out IFile file, U8Span path, OpenMode mode)
|
||||
{
|
||||
file = default;
|
||||
|
||||
@ -225,7 +226,7 @@ namespace LibHac.FsSystem
|
||||
}
|
||||
}
|
||||
|
||||
protected override Result RenameDirectoryImpl(U8Span oldPath, U8Span newPath)
|
||||
protected override Result DoRenameDirectory(U8Span oldPath, U8Span newPath)
|
||||
{
|
||||
FsPath fullCurrentPath;
|
||||
FsPath fullNewPath;
|
||||
@ -244,7 +245,7 @@ namespace LibHac.FsSystem
|
||||
}
|
||||
}
|
||||
|
||||
protected override Result RenameFileImpl(U8Span oldPath, U8Span newPath)
|
||||
protected override Result DoRenameFile(U8Span oldPath, U8Span newPath)
|
||||
{
|
||||
FsPath fullCurrentPath;
|
||||
FsPath fullNewPath;
|
||||
@ -263,7 +264,7 @@ namespace LibHac.FsSystem
|
||||
}
|
||||
}
|
||||
|
||||
protected override Result GetEntryTypeImpl(out DirectoryEntryType entryType, U8Span path)
|
||||
protected override Result DoGetEntryType(out DirectoryEntryType entryType, U8Span path)
|
||||
{
|
||||
FsPath fullPath;
|
||||
unsafe { _ = &fullPath; } // workaround for CS0165
|
||||
@ -281,7 +282,7 @@ namespace LibHac.FsSystem
|
||||
}
|
||||
}
|
||||
|
||||
protected override Result CommitImpl()
|
||||
protected override Result DoCommit()
|
||||
{
|
||||
lock (Locker)
|
||||
{
|
||||
@ -315,7 +316,7 @@ namespace LibHac.FsSystem
|
||||
}
|
||||
}
|
||||
|
||||
protected override Result CommitProvisionallyImpl(long commitCount)
|
||||
protected override Result DoCommitProvisionally(long counter)
|
||||
{
|
||||
if (!CanCommitProvisionally)
|
||||
return ResultFs.UnsupportedOperationInDirectorySaveDataFileSystem.Log();
|
||||
@ -323,7 +324,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result RollbackImpl()
|
||||
protected override Result DoRollback()
|
||||
{
|
||||
// No old data is kept for temporary save data, so there's nothing to rollback to
|
||||
if (!IsPersistentSaveData)
|
||||
@ -332,7 +333,7 @@ namespace LibHac.FsSystem
|
||||
return Initialize(IsPersistentSaveData, CanCommitProvisionally);
|
||||
}
|
||||
|
||||
protected override Result GetFreeSpaceSizeImpl(out long freeSpace, U8Span path)
|
||||
protected override Result DoGetFreeSpaceSize(out long freeSpace, U8Span path)
|
||||
{
|
||||
freeSpace = default;
|
||||
|
||||
@ -348,7 +349,7 @@ namespace LibHac.FsSystem
|
||||
}
|
||||
}
|
||||
|
||||
protected override Result GetTotalSpaceSizeImpl(out long totalSpace, U8Span path)
|
||||
protected override Result DoGetTotalSpaceSize(out long totalSpace, U8Span path)
|
||||
{
|
||||
totalSpace = default;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
|
@ -2,7 +2,7 @@
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
|
@ -1,9 +1,10 @@
|
||||
using System;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
public class FileStorage : StorageBase
|
||||
public class FileStorage : IStorage
|
||||
{
|
||||
protected IFile BaseFile { get; }
|
||||
|
||||
@ -12,27 +13,27 @@ namespace LibHac.FsSystem
|
||||
BaseFile = baseFile;
|
||||
}
|
||||
|
||||
protected override Result ReadImpl(long offset, Span<byte> destination)
|
||||
protected override Result DoRead(long offset, Span<byte> destination)
|
||||
{
|
||||
return BaseFile.Read(out long _, offset, destination);
|
||||
}
|
||||
|
||||
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
return BaseFile.Write(offset, source);
|
||||
}
|
||||
|
||||
protected override Result FlushImpl()
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return BaseFile.Flush();
|
||||
}
|
||||
|
||||
protected override Result GetSizeImpl(out long size)
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
return BaseFile.GetSize(out size);
|
||||
}
|
||||
|
||||
protected override Result SetSizeImpl(long size)
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
return BaseFile.SetSize(size);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
|
@ -7,7 +7,7 @@ using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
public class HierarchicalIntegrityVerificationStorage : StorageBase
|
||||
public class HierarchicalIntegrityVerificationStorage : IStorage
|
||||
{
|
||||
public IStorage[] Levels { get; }
|
||||
public IStorage DataLevel { get; }
|
||||
@ -96,27 +96,27 @@ namespace LibHac.FsSystem
|
||||
return initInfo;
|
||||
}
|
||||
|
||||
protected override Result ReadImpl(long offset, Span<byte> destination)
|
||||
protected override Result DoRead(long offset, Span<byte> destination)
|
||||
{
|
||||
return DataLevel.Read(offset, destination);
|
||||
}
|
||||
|
||||
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
return DataLevel.Write(offset, source);
|
||||
}
|
||||
|
||||
protected override Result FlushImpl()
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return DataLevel.Flush();
|
||||
}
|
||||
|
||||
protected override Result SetSizeImpl(long size)
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
return ResultFs.UnsupportedOperationInHierarchicalIvfcStorageSetSize.Log();
|
||||
}
|
||||
|
||||
protected override Result GetSizeImpl(out long size)
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
size = Length;
|
||||
return Result.Success;
|
||||
|
@ -5,7 +5,7 @@ using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
public class IndirectStorage : StorageBase
|
||||
public class IndirectStorage : IStorage
|
||||
{
|
||||
private List<RelocationEntry> RelocationEntries { get; }
|
||||
private List<long> RelocationOffsets { get; }
|
||||
@ -29,7 +29,7 @@ namespace LibHac.FsSystem
|
||||
Length = BucketTree.BucketOffsets.OffsetEnd;
|
||||
}
|
||||
|
||||
protected override Result ReadImpl(long offset, Span<byte> destination)
|
||||
protected override Result DoRead(long offset, Span<byte> destination)
|
||||
{
|
||||
RelocationEntry entry = GetRelocationEntry(offset);
|
||||
|
||||
@ -64,23 +64,23 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
return ResultFs.UnsupportedOperationInIndirectStorageSetSize.Log();
|
||||
}
|
||||
|
||||
protected override Result FlushImpl()
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result GetSizeImpl(out long size)
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
size = Length;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result SetSizeImpl(long size)
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
return ResultFs.UnsupportedOperationInIndirectStorageSetSize.Log();
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result ReadImpl(long offset, Span<byte> destination)
|
||||
protected override Result DoRead(long offset, Span<byte> destination)
|
||||
{
|
||||
return ReadImpl(offset, destination, IntegrityCheckLevel);
|
||||
}
|
||||
@ -128,7 +128,7 @@ namespace LibHac.FsSystem
|
||||
return ReadImpl(offset, destination, integrityCheckLevel);
|
||||
}
|
||||
|
||||
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
long blockIndex = offset / SectorSize;
|
||||
long hashPos = blockIndex * DigestSize;
|
||||
@ -188,12 +188,12 @@ namespace LibHac.FsSystem
|
||||
}
|
||||
}
|
||||
|
||||
protected override Result FlushImpl()
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
Result rc = HashStorage.Flush();
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return base.FlushImpl();
|
||||
return base.DoFlush();
|
||||
}
|
||||
|
||||
public void FsTrim()
|
||||
|
@ -2,10 +2,11 @@
|
||||
using System.Collections.Generic;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
public class LayeredFileSystem : FileSystemBase
|
||||
public class LayeredFileSystem : IFileSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// List of source <see cref="IFileSystem"/>s.
|
||||
@ -35,7 +36,7 @@ namespace LibHac.FsSystem
|
||||
Sources.AddRange(sourceFileSystems);
|
||||
}
|
||||
|
||||
protected override Result OpenDirectoryImpl(out IDirectory directory, U8Span path, OpenDirectoryMode mode)
|
||||
protected override Result DoOpenDirectory(out IDirectory directory, U8Span path, OpenDirectoryMode mode)
|
||||
{
|
||||
directory = default;
|
||||
|
||||
@ -106,7 +107,7 @@ namespace LibHac.FsSystem
|
||||
return ResultFs.PathNotFound.Log();
|
||||
}
|
||||
|
||||
protected override Result OpenFileImpl(out IFile file, U8Span path, OpenMode mode)
|
||||
protected override Result DoOpenFile(out IFile file, U8Span path, OpenMode mode)
|
||||
{
|
||||
file = default;
|
||||
|
||||
@ -135,7 +136,7 @@ namespace LibHac.FsSystem
|
||||
return ResultFs.PathNotFound.Log();
|
||||
}
|
||||
|
||||
protected override Result GetEntryTypeImpl(out DirectoryEntryType entryType, U8Span path)
|
||||
protected override Result DoGetEntryType(out DirectoryEntryType entryType, U8Span path)
|
||||
{
|
||||
foreach (IFileSystem fs in Sources)
|
||||
{
|
||||
@ -152,7 +153,7 @@ namespace LibHac.FsSystem
|
||||
return ResultFs.PathNotFound.Log();
|
||||
}
|
||||
|
||||
protected override Result GetFileTimeStampRawImpl(out FileTimeStampRaw timeStamp, U8Span path)
|
||||
protected override Result DoGetFileTimeStampRaw(out FileTimeStampRaw timeStamp, U8Span path)
|
||||
{
|
||||
foreach (IFileSystem fs in Sources)
|
||||
{
|
||||
@ -168,7 +169,7 @@ namespace LibHac.FsSystem
|
||||
return ResultFs.PathNotFound.Log();
|
||||
}
|
||||
|
||||
protected override Result QueryEntryImpl(Span<byte> outBuffer, ReadOnlySpan<byte> inBuffer, QueryId queryId,
|
||||
protected override Result DoQueryEntry(Span<byte> outBuffer, ReadOnlySpan<byte> inBuffer, QueryId queryId,
|
||||
U8Span path)
|
||||
{
|
||||
foreach (IFileSystem fs in Sources)
|
||||
@ -184,19 +185,19 @@ namespace LibHac.FsSystem
|
||||
return ResultFs.PathNotFound.Log();
|
||||
}
|
||||
|
||||
protected override Result CommitImpl()
|
||||
protected override Result DoCommit()
|
||||
{
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result CreateDirectoryImpl(U8Span path) => ResultFs.UnsupportedOperation.Log();
|
||||
protected override Result CreateFileImpl(U8Span path, long size, CreateFileOptions options) => ResultFs.UnsupportedOperation.Log();
|
||||
protected override Result DeleteDirectoryImpl(U8Span path) => ResultFs.UnsupportedOperation.Log();
|
||||
protected override Result DeleteDirectoryRecursivelyImpl(U8Span path) => ResultFs.UnsupportedOperation.Log();
|
||||
protected override Result CleanDirectoryRecursivelyImpl(U8Span path) => ResultFs.UnsupportedOperation.Log();
|
||||
protected override Result DeleteFileImpl(U8Span path) => ResultFs.UnsupportedOperation.Log();
|
||||
protected override Result RenameDirectoryImpl(U8Span oldPath, U8Span newPath) => ResultFs.UnsupportedOperation.Log();
|
||||
protected override Result RenameFileImpl(U8Span oldPath, U8Span newPath) => ResultFs.UnsupportedOperation.Log();
|
||||
protected override Result DoCreateDirectory(U8Span path) => ResultFs.UnsupportedOperation.Log();
|
||||
protected override Result DoCreateFile(U8Span path, long size, CreateFileOptions options) => ResultFs.UnsupportedOperation.Log();
|
||||
protected override Result DoDeleteDirectory(U8Span path) => ResultFs.UnsupportedOperation.Log();
|
||||
protected override Result DoDeleteDirectoryRecursively(U8Span path) => ResultFs.UnsupportedOperation.Log();
|
||||
protected override Result DoCleanDirectoryRecursively(U8Span path) => ResultFs.UnsupportedOperation.Log();
|
||||
protected override Result DoDeleteFile(U8Span path) => ResultFs.UnsupportedOperation.Log();
|
||||
protected override Result DoRenameDirectory(U8Span oldPath, U8Span newPath) => ResultFs.UnsupportedOperation.Log();
|
||||
protected override Result DoRenameFile(U8Span oldPath, U8Span newPath) => ResultFs.UnsupportedOperation.Log();
|
||||
|
||||
private class MergedDirectory : IDirectory
|
||||
{
|
||||
@ -230,7 +231,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result Read(out long entriesRead, Span<DirectoryEntry> entryBuffer)
|
||||
protected override Result DoRead(out long entriesRead, Span<DirectoryEntry> entryBuffer)
|
||||
{
|
||||
entriesRead = 0;
|
||||
int entryIndex = 0;
|
||||
@ -255,7 +256,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result GetEntryCount(out long entryCount)
|
||||
protected override Result DoGetEntryCount(out long entryCount)
|
||||
{
|
||||
entryCount = 0;
|
||||
long totalEntryCount = 0;
|
||||
|
@ -4,6 +4,7 @@ using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
@ -21,7 +22,7 @@ namespace LibHac.FsSystem
|
||||
Mode = mode;
|
||||
}
|
||||
|
||||
public Result Read(out long entriesRead, Span<DirectoryEntry> entryBuffer)
|
||||
protected override Result DoRead(out long entriesRead, Span<DirectoryEntry> entryBuffer)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
@ -52,7 +53,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result GetEntryCount(out long entryCount)
|
||||
protected override Result DoGetEntryCount(out long entryCount)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
|
@ -2,10 +2,11 @@
|
||||
using System.IO;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
public class LocalFile : FileBase
|
||||
public class LocalFile : IFile
|
||||
{
|
||||
private FileStream Stream { get; }
|
||||
private StreamFile File { get; }
|
||||
@ -27,25 +28,26 @@ namespace LibHac.FsSystem
|
||||
File = new StreamFile(Stream, mode);
|
||||
}
|
||||
|
||||
protected override Result ReadImpl(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
||||
protected override Result DoRead(out long bytesRead, long offset, Span<byte> destination,
|
||||
in ReadOption option)
|
||||
{
|
||||
bytesRead = 0;
|
||||
|
||||
Result rc = ValidateReadParams(out long toRead, offset, destination.Length, Mode);
|
||||
Result rc = DryRead(out long toRead, offset, destination.Length, in option, Mode);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return File.Read(out bytesRead, offset, destination.Slice(0, (int)toRead), options);
|
||||
return File.Read(out bytesRead, offset, destination.Slice(0, (int)toRead), option);
|
||||
}
|
||||
|
||||
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source, in WriteOption option)
|
||||
{
|
||||
Result rc = ValidateWriteParams(offset, source.Length, Mode, out _);
|
||||
Result rc = DryWrite(out _, offset, source.Length, in option, Mode);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return File.Write(offset, source, options);
|
||||
return File.Write(offset, source, option);
|
||||
}
|
||||
|
||||
protected override Result FlushImpl()
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -57,7 +59,7 @@ namespace LibHac.FsSystem
|
||||
}
|
||||
}
|
||||
|
||||
protected override Result GetSizeImpl(out long size)
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -70,7 +72,12 @@ namespace LibHac.FsSystem
|
||||
}
|
||||
}
|
||||
|
||||
protected override Result SetSizeImpl(long size)
|
||||
protected override Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size, ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -4,10 +4,11 @@ using System.IO;
|
||||
using System.Threading;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
public class LocalFileSystem : AttributeFileSystemBase
|
||||
public class LocalFileSystem : IAttributeFileSystem
|
||||
{
|
||||
private string BasePath { get; }
|
||||
|
||||
@ -66,7 +67,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result GetFileAttributesImpl(out NxFileAttributes attributes, U8Span path)
|
||||
protected override Result DoGetFileAttributes(out NxFileAttributes attributes, U8Span path)
|
||||
{
|
||||
attributes = default;
|
||||
|
||||
@ -86,7 +87,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result SetFileAttributesImpl(U8Span path, NxFileAttributes attributes)
|
||||
protected override Result DoSetFileAttributes(U8Span path, NxFileAttributes attributes)
|
||||
{
|
||||
Result rc = ResolveFullPath(out string fullPath, path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
@ -114,7 +115,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result GetFileSizeImpl(out long fileSize, U8Span path)
|
||||
protected override Result DoGetFileSize(out long fileSize, U8Span path)
|
||||
{
|
||||
fileSize = default;
|
||||
|
||||
@ -127,12 +128,12 @@ namespace LibHac.FsSystem
|
||||
return GetSizeInternal(out fileSize, info);
|
||||
}
|
||||
|
||||
protected override Result CreateDirectoryImpl(U8Span path)
|
||||
protected override Result DoCreateDirectory(U8Span path)
|
||||
{
|
||||
return CreateDirectory(path, NxFileAttributes.None);
|
||||
return DoCreateDirectory(path, NxFileAttributes.None);
|
||||
}
|
||||
|
||||
protected override Result CreateDirectoryImpl(U8Span path, NxFileAttributes archiveAttribute)
|
||||
protected override Result DoCreateDirectory(U8Span path, NxFileAttributes archiveAttribute)
|
||||
{
|
||||
Result rc = ResolveFullPath(out string fullPath, path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
@ -153,7 +154,7 @@ namespace LibHac.FsSystem
|
||||
return CreateDirInternal(dir, archiveAttribute);
|
||||
}
|
||||
|
||||
protected override Result CreateFileImpl(U8Span path, long size, CreateFileOptions options)
|
||||
protected override Result DoCreateFile(U8Span path, long size, CreateFileOptions options)
|
||||
{
|
||||
Result rc = ResolveFullPath(out string fullPath, path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
@ -181,7 +182,7 @@ namespace LibHac.FsSystem
|
||||
}
|
||||
}
|
||||
|
||||
protected override Result DeleteDirectoryImpl(U8Span path)
|
||||
protected override Result DoDeleteDirectory(U8Span path)
|
||||
{
|
||||
Result rc = ResolveFullPath(out string fullPath, path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
@ -192,7 +193,7 @@ namespace LibHac.FsSystem
|
||||
return DeleteDirectoryInternal(dir, false);
|
||||
}
|
||||
|
||||
protected override Result DeleteDirectoryRecursivelyImpl(U8Span path)
|
||||
protected override Result DoDeleteDirectoryRecursively(U8Span path)
|
||||
{
|
||||
Result rc = ResolveFullPath(out string fullPath, path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
@ -203,7 +204,7 @@ namespace LibHac.FsSystem
|
||||
return DeleteDirectoryInternal(dir, true);
|
||||
}
|
||||
|
||||
protected override Result CleanDirectoryRecursivelyImpl(U8Span path)
|
||||
protected override Result DoCleanDirectoryRecursively(U8Span path)
|
||||
{
|
||||
Result rc = ResolveFullPath(out string fullPath, path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
@ -229,7 +230,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result DeleteFileImpl(U8Span path)
|
||||
protected override Result DoDeleteFile(U8Span path)
|
||||
{
|
||||
Result rc = ResolveFullPath(out string fullPath, path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
@ -240,7 +241,7 @@ namespace LibHac.FsSystem
|
||||
return DeleteFileInternal(file);
|
||||
}
|
||||
|
||||
protected override Result OpenDirectoryImpl(out IDirectory directory, U8Span path, OpenDirectoryMode mode)
|
||||
protected override Result DoOpenDirectory(out IDirectory directory, U8Span path, OpenDirectoryMode mode)
|
||||
{
|
||||
directory = default;
|
||||
Result rc = ResolveFullPath(out string fullPath, path);
|
||||
@ -267,7 +268,7 @@ namespace LibHac.FsSystem
|
||||
}
|
||||
}
|
||||
|
||||
protected override Result OpenFileImpl(out IFile file, U8Span path, OpenMode mode)
|
||||
protected override Result DoOpenFile(out IFile file, U8Span path, OpenMode mode)
|
||||
{
|
||||
file = default;
|
||||
|
||||
@ -289,7 +290,7 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result RenameDirectoryImpl(U8Span oldPath, U8Span newPath)
|
||||
protected override Result DoRenameDirectory(U8Span oldPath, U8Span newPath)
|
||||
{
|
||||
Result rc = CheckSubPath(oldPath, newPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
@ -312,7 +313,7 @@ namespace LibHac.FsSystem
|
||||
return RenameDirInternal(currentDirInfo, newDirInfo);
|
||||
}
|
||||
|
||||
protected override Result RenameFileImpl(U8Span oldPath, U8Span newPath)
|
||||
protected override Result DoRenameFile(U8Span oldPath, U8Span newPath)
|
||||
{
|
||||
Result rc = ResolveFullPath(out string fullCurrentPath, oldPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
@ -332,7 +333,7 @@ namespace LibHac.FsSystem
|
||||
return RenameFileInternal(currentFileInfo, newFileInfo);
|
||||
}
|
||||
|
||||
protected override Result GetEntryTypeImpl(out DirectoryEntryType entryType, U8Span path)
|
||||
protected override Result DoGetEntryType(out DirectoryEntryType entryType, U8Span path)
|
||||
{
|
||||
entryType = default;
|
||||
|
||||
@ -361,7 +362,7 @@ namespace LibHac.FsSystem
|
||||
return ResultFs.PathNotFound.Log();
|
||||
}
|
||||
|
||||
protected override Result GetFileTimeStampRawImpl(out FileTimeStampRaw timeStamp, U8Span path)
|
||||
protected override Result DoGetFileTimeStampRaw(out FileTimeStampRaw timeStamp, U8Span path)
|
||||
{
|
||||
timeStamp = default;
|
||||
|
||||
@ -380,24 +381,24 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result GetFreeSpaceSizeImpl(out long freeSpace, U8Span path)
|
||||
protected override Result DoGetFreeSpaceSize(out long freeSpace, U8Span path)
|
||||
{
|
||||
freeSpace = new DriveInfo(BasePath).AvailableFreeSpace;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result GetTotalSpaceSizeImpl(out long totalSpace, U8Span path)
|
||||
protected override Result DoGetTotalSpaceSize(out long totalSpace, U8Span path)
|
||||
{
|
||||
totalSpace = new DriveInfo(BasePath).TotalSize;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result CommitImpl()
|
||||
protected override Result DoCommit()
|
||||
{
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result QueryEntryImpl(Span<byte> outBuffer, ReadOnlySpan<byte> inBuffer, QueryId queryId,
|
||||
protected override Result DoQueryEntry(Span<byte> outBuffer, ReadOnlySpan<byte> inBuffer, QueryId queryId,
|
||||
U8Span path)
|
||||
{
|
||||
return ResultFs.UnsupportedOperation.Log();
|
||||
|
@ -4,7 +4,7 @@ using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
public class LocalStorage : StorageBase
|
||||
public class LocalStorage : IStorage
|
||||
{
|
||||
private string Path { get; }
|
||||
private FileStream Stream { get; }
|
||||
@ -19,27 +19,27 @@ namespace LibHac.FsSystem
|
||||
Storage = new StreamStorage(Stream, false);
|
||||
}
|
||||
|
||||
protected override Result ReadImpl(long offset, Span<byte> destination)
|
||||
protected override Result DoRead(long offset, Span<byte> destination)
|
||||
{
|
||||
return Storage.Read(offset, destination);
|
||||
}
|
||||
|
||||
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
return Storage.Write(offset, source);
|
||||
}
|
||||
|
||||
protected override Result FlushImpl()
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return Storage.Flush();
|
||||
}
|
||||
|
||||
protected override Result SetSizeImpl(long size)
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
protected override Result GetSizeImpl(out long size)
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
return Storage.GetSize(out size);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSystem.RomFs;
|
||||
using LibHac.Spl;
|
||||
|
||||
|
@ -3,6 +3,7 @@ using System.Buffers.Binary;
|
||||
using System.Diagnostics;
|
||||
using LibHac.Crypto;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSystem.NcaUtils
|
||||
{
|
||||
|
@ -1,9 +1,10 @@
|
||||
using System;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
public class NullFile : FileBase
|
||||
public class NullFile : IFile
|
||||
{
|
||||
private OpenMode Mode { get; }
|
||||
|
||||
@ -16,11 +17,12 @@ namespace LibHac.FsSystem
|
||||
|
||||
private long Length { get; }
|
||||
|
||||
protected override Result ReadImpl(out long bytesRead, long offset, Span<byte> destination, ReadOption options)
|
||||
protected override Result DoRead(out long bytesRead, long offset, Span<byte> destination,
|
||||
in ReadOption option)
|
||||
{
|
||||
bytesRead = 0;
|
||||
|
||||
Result rc = ValidateReadParams(out long toRead, offset, destination.Length, Mode);
|
||||
Result rc = DryRead(out long toRead, offset, destination.Length, in option, Mode);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
destination.Slice(0, (int)toRead).Clear();
|
||||
@ -29,23 +31,29 @@ namespace LibHac.FsSystem
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source, WriteOption options)
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source, in WriteOption option)
|
||||
{
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result FlushImpl()
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result GetSizeImpl(out long size)
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
size = Length;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result SetSizeImpl(long size)
|
||||
protected override Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size,
|
||||
ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
return ResultFs.UnsupportedOperation.Log();
|
||||
}
|
||||
|
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