mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Move FileSystemManager into FileSystemClient
This commit is contained in:
parent
955fff8efc
commit
00eb988793
14 changed files with 564 additions and 729 deletions
|
@ -10,7 +10,7 @@ namespace LibHac.Fs.Accessors
|
|||
public string Name { get; }
|
||||
|
||||
private IFileSystem FileSystem { get; }
|
||||
internal FileSystemManager FsManager { get; }
|
||||
internal FileSystemClient FsClient { get; }
|
||||
private ICommonMountNameGenerator MountNameGenerator { get; }
|
||||
|
||||
private HashSet<FileAccessor> OpenFiles { get; } = new HashSet<FileAccessor>();
|
||||
|
@ -20,11 +20,11 @@ namespace LibHac.Fs.Accessors
|
|||
|
||||
internal bool IsAccessLogEnabled { get; set; }
|
||||
|
||||
public FileSystemAccessor(string name, IFileSystem baseFileSystem, FileSystemManager fsManager, ICommonMountNameGenerator nameGenerator)
|
||||
public FileSystemAccessor(string name, IFileSystem baseFileSystem, FileSystemClient fsClient, ICommonMountNameGenerator nameGenerator)
|
||||
{
|
||||
Name = name;
|
||||
FileSystem = baseFileSystem;
|
||||
FsManager = fsManager;
|
||||
FsClient = fsClient;
|
||||
MountNameGenerator = nameGenerator;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace LibHac.Fs
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
Directory.Parent.FsManager.CloseDirectory(this);
|
||||
Directory.Parent.FsClient.CloseDirectory(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace LibHac.Fs
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
File.Parent.FsManager.CloseFile(this);
|
||||
File.Parent.FsClient.CloseFile(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace LibHac.Fs
|
|||
private const long InvalidSize = -1;
|
||||
private readonly object _locker = new object();
|
||||
|
||||
private FileSystemManager FsManager { get; }
|
||||
private FileSystemClient FsClient { get; }
|
||||
private FileHandle Handle { get; }
|
||||
private long FileSize { get; set; } = InvalidSize;
|
||||
private bool CloseHandle { get; }
|
||||
|
@ -18,7 +18,7 @@ namespace LibHac.Fs
|
|||
{
|
||||
Handle = handle;
|
||||
CloseHandle = closeHandleOnDispose;
|
||||
FsManager = Handle.File.Parent.FsManager;
|
||||
FsClient = Handle.File.Parent.FsClient;
|
||||
}
|
||||
|
||||
public override Result Read(long offset, Span<byte> destination)
|
||||
|
@ -33,7 +33,7 @@ namespace LibHac.Fs
|
|||
if (destination.Length < 0 || offset < 0) return ResultFs.ValueOutOfRange.Log();
|
||||
if (!IsRangeValid(offset, destination.Length, FileSize)) return ResultFs.ValueOutOfRange.Log();
|
||||
|
||||
return FsManager.ReadFile(Handle, offset, destination);
|
||||
return FsClient.ReadFile(Handle, offset, destination);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,20 +49,20 @@ namespace LibHac.Fs
|
|||
if (source.Length < 0 || offset < 0) return ResultFs.ValueOutOfRange.Log();
|
||||
if (!IsRangeValid(offset, source.Length, FileSize)) return ResultFs.ValueOutOfRange.Log();
|
||||
|
||||
return FsManager.WriteFile(Handle, offset, source);
|
||||
return FsClient.WriteFile(Handle, offset, source);
|
||||
}
|
||||
}
|
||||
|
||||
public override Result Flush()
|
||||
{
|
||||
return FsManager.FlushFile(Handle);
|
||||
return FsClient.FlushFile(Handle);
|
||||
}
|
||||
|
||||
public override Result SetSize(long size)
|
||||
{
|
||||
FileSize = InvalidSize;
|
||||
|
||||
return FsManager.SetFileSize(Handle, size);
|
||||
return FsClient.SetFileSize(Handle, size);
|
||||
}
|
||||
|
||||
public override Result GetSize(out long size)
|
||||
|
@ -80,7 +80,7 @@ namespace LibHac.Fs
|
|||
{
|
||||
if (FileSize != InvalidSize) return Result.Success;
|
||||
|
||||
Result rc = FsManager.GetFileSize(out long fileSize, Handle);
|
||||
Result rc = FsClient.GetFileSize(out long fileSize, Handle);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
FileSize = fileSize;
|
||||
|
@ -91,7 +91,7 @@ namespace LibHac.Fs
|
|||
{
|
||||
if (CloseHandle)
|
||||
{
|
||||
FsManager.CloseFile(Handle);
|
||||
FsClient.CloseFile(Handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,17 +6,43 @@ namespace LibHac.Fs
|
|||
{
|
||||
public Result GetDirectoryEntryCount(out long count, DirectoryHandle handle)
|
||||
{
|
||||
return FsManager.GetDirectoryEntryCount(out count, handle);
|
||||
return handle.Directory.GetEntryCount(out count);
|
||||
}
|
||||
|
||||
public Result ReadDirectory(out long entriesRead, Span<DirectoryEntry> entryBuffer, DirectoryHandle handle)
|
||||
{
|
||||
return FsManager.ReadDirectory(out entriesRead, entryBuffer, handle);
|
||||
Result rc;
|
||||
|
||||
if (IsEnabledAccessLog() && IsEnabledHandleAccessLog(handle))
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = handle.Directory.Read(out entriesRead, entryBuffer);
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, handle, string.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = handle.Directory.Read(out entriesRead, entryBuffer);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public void CloseDirectory(DirectoryHandle handle)
|
||||
{
|
||||
FsManager.CloseDirectory(handle);
|
||||
if (IsEnabledAccessLog() && IsEnabledHandleAccessLog(handle))
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
handle.Directory.Dispose();
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(Result.Success, startTime, endTime, handle, string.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
handle.Directory.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,52 +6,135 @@ namespace LibHac.Fs
|
|||
{
|
||||
public Result ReadFile(FileHandle handle, long offset, Span<byte> destination)
|
||||
{
|
||||
return FsManager.ReadFile(handle, offset, destination);
|
||||
return ReadFile(handle, offset, destination, ReadOption.None);
|
||||
}
|
||||
|
||||
public Result ReadFile(FileHandle handle, long offset, Span<byte> destination, ReadOption options)
|
||||
public Result ReadFile(FileHandle handle, long offset, Span<byte> destination, ReadOption option)
|
||||
{
|
||||
return FsManager.ReadFile(handle, offset, destination, options);
|
||||
Result rc = ReadFile(out long bytesRead, handle, offset, destination, option);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (bytesRead == destination.Length) return Result.Success;
|
||||
|
||||
return ResultFs.ValueOutOfRange.Log();
|
||||
}
|
||||
|
||||
public Result ReadFile(out long bytesRead, FileHandle handle, long offset, Span<byte> destination)
|
||||
{
|
||||
return FsManager.ReadFile(out bytesRead, handle, offset, destination);
|
||||
return ReadFile(out bytesRead, handle, offset, destination, ReadOption.None);
|
||||
}
|
||||
|
||||
public Result ReadFile(out long bytesRead, FileHandle handle, long offset, Span<byte> destination, ReadOption options)
|
||||
public Result ReadFile(out long bytesRead, FileHandle handle, long offset, Span<byte> destination, ReadOption option)
|
||||
{
|
||||
return FsManager.ReadFile(out bytesRead, handle, offset, destination, options);
|
||||
Result rc;
|
||||
|
||||
if (IsEnabledAccessLog() && IsEnabledHandleAccessLog(handle))
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = handle.File.Read(out bytesRead, offset, destination, 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);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result WriteFile(FileHandle handle, long offset, ReadOnlySpan<byte> source, WriteOption options)
|
||||
public Result WriteFile(FileHandle handle, long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
return FsManager.WriteFile(handle, offset, source, options);
|
||||
return WriteFile(handle, offset, source, WriteOption.None);
|
||||
}
|
||||
|
||||
public Result WriteFile(FileHandle handle, long offset, ReadOnlySpan<byte> source, WriteOption option)
|
||||
{
|
||||
Result rc;
|
||||
|
||||
if (IsEnabledAccessLog() && IsEnabledHandleAccessLog(handle))
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = handle.File.Write(offset, source, option);
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
string optionString = (option & WriteOption.Flush) == 0 ? "" : $", write_option: {option}";
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, handle, $", offset: {offset}, size: {source.Length}{optionString}");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = handle.File.Write(offset, source, option);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result FlushFile(FileHandle handle)
|
||||
{
|
||||
return FsManager.FlushFile(handle);
|
||||
Result rc;
|
||||
|
||||
if (IsEnabledAccessLog() && IsEnabledHandleAccessLog(handle))
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = handle.File.Flush();
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, handle, string.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = handle.File.Flush();
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result GetFileSize(out long fileSize, FileHandle handle)
|
||||
{
|
||||
return FsManager.GetFileSize(out fileSize, handle);
|
||||
return handle.File.GetSize(out fileSize);
|
||||
}
|
||||
|
||||
public Result SetFileSize(FileHandle handle, long size)
|
||||
{
|
||||
return FsManager.SetFileSize(handle, size);
|
||||
Result rc;
|
||||
|
||||
if (IsEnabledAccessLog() && IsEnabledHandleAccessLog(handle))
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = handle.File.SetSize(size);
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, handle, $", size: {size}");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = handle.File.SetSize(size);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public OpenMode GetFileOpenMode(FileHandle handle)
|
||||
{
|
||||
return FsManager.GetFileOpenMode(handle);
|
||||
return handle.File.OpenMode;
|
||||
}
|
||||
|
||||
public void CloseFile(FileHandle handle)
|
||||
{
|
||||
FsManager.CloseFile(handle);
|
||||
if (IsEnabledAccessLog() && IsEnabledHandleAccessLog(handle))
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
handle.File.Dispose();
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(Result.Success, startTime, endTime, handle, string.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
handle.File.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,29 @@
|
|||
using System;
|
||||
using LibHac.Fs.Accessors;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
public partial class FileSystemClient
|
||||
{
|
||||
public Result CreateDirectory(string path)
|
||||
{
|
||||
return FsManager.CreateDirectory(path);
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = fileSystem.CreateDirectory(subPath.ToString());
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, $", path: \"{path}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.CreateDirectory(subPath.ToString());
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result CreateFile(string path, long size)
|
||||
|
@ -14,67 +33,289 @@ namespace LibHac.Fs
|
|||
|
||||
public Result CreateFile(string path, long size, CreateFileOptions options)
|
||||
{
|
||||
return FsManager.CreateFile(path, size, options);
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = fileSystem.CreateFile(subPath.ToString(), size, options);
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, $", path: \"{path}\", size: {size}");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.CreateFile(subPath.ToString(), size, options);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result DeleteDirectory(string path)
|
||||
{
|
||||
return FsManager.DeleteDirectory(path);
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = fileSystem.DeleteDirectory(subPath.ToString());
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, $", path: \"{path}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.DeleteDirectory(subPath.ToString());
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result DeleteDirectoryRecursively(string path)
|
||||
{
|
||||
return FsManager.DeleteDirectoryRecursively(path);
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = fileSystem.DeleteDirectoryRecursively(subPath.ToString());
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, $", path: \"{path}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.DeleteDirectoryRecursively(subPath.ToString());
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result CleanDirectoryRecursively(string path)
|
||||
{
|
||||
return FsManager.CleanDirectoryRecursively(path);
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = fileSystem.CleanDirectoryRecursively(subPath.ToString());
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, $", path: \"{path}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.CleanDirectoryRecursively(subPath.ToString());
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result DeleteFile(string path)
|
||||
{
|
||||
return FsManager.DeleteFile(path);
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = fileSystem.DeleteFile(subPath.ToString());
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, $", path: \"{path}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.DeleteFile(subPath.ToString());
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result RenameDirectory(string oldPath, string newPath)
|
||||
{
|
||||
return FsManager.RenameDirectory(oldPath, newPath);
|
||||
Result rc = FindFileSystem(oldPath.AsSpan(), out FileSystemAccessor oldFileSystem, out ReadOnlySpan<char> oldSubPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = FindFileSystem(newPath.AsSpan(), out FileSystemAccessor newFileSystem, out ReadOnlySpan<char> newSubPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (oldFileSystem != newFileSystem)
|
||||
{
|
||||
return ResultFs.DifferentDestFileSystem.Log();
|
||||
}
|
||||
|
||||
if (IsEnabledAccessLog() && oldFileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = oldFileSystem.RenameDirectory(oldSubPath.ToString(), newSubPath.ToString());
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, $", path: \"{oldPath}\", new_path: \"{newPath}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = oldFileSystem.RenameDirectory(oldSubPath.ToString(), newSubPath.ToString());
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result RenameFile(string oldPath, string newPath)
|
||||
{
|
||||
return FsManager.RenameFile(oldPath, newPath);
|
||||
Result rc = FindFileSystem(oldPath.AsSpan(), out FileSystemAccessor oldFileSystem, out ReadOnlySpan<char> oldSubPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = FindFileSystem(newPath.AsSpan(), out FileSystemAccessor newFileSystem, out ReadOnlySpan<char> newSubPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (oldFileSystem != newFileSystem)
|
||||
{
|
||||
return ResultFs.DifferentDestFileSystem.Log();
|
||||
}
|
||||
|
||||
if (IsEnabledAccessLog() && oldFileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = oldFileSystem.RenameFile(oldSubPath.ToString(), newSubPath.ToString());
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, $", path: \"{oldPath}\", new_path: \"{newPath}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = oldFileSystem.RenameFile(oldSubPath.ToString(), newSubPath.ToString());
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result GetEntryType(out DirectoryEntryType type, string path)
|
||||
{
|
||||
return FsManager.GetEntryType(out type, path);
|
||||
type = default;
|
||||
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = fileSystem.GetEntryType(out type, subPath.ToString());
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, $", path: \"{path}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.GetEntryType(out type, subPath.ToString());
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result OpenFile(out FileHandle handle, string path, OpenMode mode)
|
||||
{
|
||||
return FsManager.OpenFile(out handle, path, mode);
|
||||
handle = default;
|
||||
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = fileSystem.OpenFile(out FileAccessor file, subPath.ToString(), mode);
|
||||
handle = new FileHandle(file);
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, handle, $", path: \"{path}\", open_mode: {mode}");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.OpenFile(out FileAccessor file, subPath.ToString(), mode);
|
||||
handle = new FileHandle(file);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result OpenDirectory(out DirectoryHandle handle, string path, OpenDirectoryMode mode)
|
||||
{
|
||||
return FsManager.OpenDirectory(out handle, path, mode);
|
||||
handle = default;
|
||||
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = fileSystem.OpenDirectory(out DirectoryAccessor dir, subPath.ToString(), mode);
|
||||
handle = new DirectoryHandle(dir);
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, handle, $", path: \"{path}\", open_mode: {mode}");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.OpenDirectory(out DirectoryAccessor dir, subPath.ToString(), mode);
|
||||
handle = new DirectoryHandle(dir);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result GetFreeSpaceSize(out long freeSpace, string path)
|
||||
{
|
||||
return FsManager.GetFreeSpaceSize(out freeSpace, path);
|
||||
freeSpace = default;
|
||||
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return fileSystem.GetFreeSpaceSize(out freeSpace, subPath.ToString());
|
||||
}
|
||||
|
||||
public Result GetTotalSpaceSize(out long totalSpace, string path)
|
||||
{
|
||||
return FsManager.GetTotalSpaceSize(out totalSpace, path);
|
||||
totalSpace = default;
|
||||
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return fileSystem.GetTotalSpaceSize(out totalSpace, subPath.ToString());
|
||||
}
|
||||
|
||||
public Result GetFileTimeStamp(out FileTimeStampRaw timeStamp, string path)
|
||||
{
|
||||
timeStamp = default;
|
||||
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return fileSystem.GetFileTimeStampRaw(out timeStamp, subPath.ToString());
|
||||
}
|
||||
|
||||
public Result Commit(string mountName)
|
||||
{
|
||||
return FsManager.Commit(mountName);
|
||||
Result rc = MountTable.Find(mountName, out FileSystemAccessor fileSystem);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = fileSystem.Commit();
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, $", name: \"{mountName}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.Commit();
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
using LibHac.Common;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Accessors;
|
||||
using LibHac.FsService;
|
||||
using LibHac.FsSystem;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
|
@ -7,14 +11,24 @@ namespace LibHac.Fs
|
|||
{
|
||||
private FileSystemServer FsSrv { get; }
|
||||
private IFileSystemProxy FsProxy { get; set; }
|
||||
private FileSystemManager FsManager { get; }
|
||||
|
||||
private readonly object _fspInitLocker = new object();
|
||||
|
||||
internal ITimeSpanGenerator Time { get; }
|
||||
private IAccessLog AccessLog { get; set; }
|
||||
private bool AccessLogEnabled { get; set; }
|
||||
|
||||
internal MountTable MountTable { get; } = new MountTable();
|
||||
|
||||
public FileSystemClient(ITimeSpanGenerator timer)
|
||||
{
|
||||
Time = timer;
|
||||
}
|
||||
|
||||
public FileSystemClient(FileSystemServer fsServer, ITimeSpanGenerator timer)
|
||||
{
|
||||
FsSrv = fsServer;
|
||||
FsManager = new FileSystemManager(timer);
|
||||
Time = timer;
|
||||
}
|
||||
|
||||
public IFileSystemProxy GetFileSystemProxyServiceObject()
|
||||
|
@ -25,6 +39,11 @@ namespace LibHac.Fs
|
|||
{
|
||||
if (FsProxy != null) return FsProxy;
|
||||
|
||||
if (FsSrv == null)
|
||||
{
|
||||
throw new InvalidOperationException("Client was not initialized with a server object.");
|
||||
}
|
||||
|
||||
FsProxy = FsSrv.CreateFileSystemProxyService();
|
||||
|
||||
return FsProxy;
|
||||
|
@ -33,12 +52,135 @@ namespace LibHac.Fs
|
|||
|
||||
public Result Register(U8Span mountName, IFileSystem fileSystem)
|
||||
{
|
||||
return FsManager.Register(mountName, fileSystem);
|
||||
return Register(mountName, fileSystem, null);
|
||||
}
|
||||
|
||||
public Result Register(U8Span mountName, IFileSystem fileSystem, ICommonMountNameGenerator nameGenerator)
|
||||
{
|
||||
return FsManager.Register(mountName, fileSystem, nameGenerator);
|
||||
var accessor = new FileSystemAccessor(mountName.ToString(), fileSystem, this, nameGenerator);
|
||||
|
||||
Result rc = MountTable.Mount(accessor);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
accessor.IsAccessLogEnabled = IsEnabledAccessLog();
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public void Unmount(string mountName)
|
||||
{
|
||||
Result rc;
|
||||
|
||||
if (IsEnabledAccessLog() && IsEnabledFileSystemAccessorAccessLog(mountName))
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
|
||||
rc = MountTable.Unmount(mountName);
|
||||
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
OutputAccessLog(rc, startTime, endTime, $", name: \"{mountName}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = MountTable.Unmount(mountName);
|
||||
}
|
||||
|
||||
rc.ThrowIfFailure();
|
||||
}
|
||||
|
||||
public void SetAccessLog(bool isEnabled, IAccessLog accessLog = null)
|
||||
{
|
||||
AccessLogEnabled = isEnabled;
|
||||
|
||||
if (accessLog != null) AccessLog = accessLog;
|
||||
}
|
||||
|
||||
internal Result FindFileSystem(ReadOnlySpan<char> path, out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath)
|
||||
{
|
||||
fileSystem = default;
|
||||
|
||||
Result rc = GetMountName(path, out ReadOnlySpan<char> mountName, out subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = MountTable.Find(mountName.ToString(), out fileSystem);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
internal static Result GetMountName(ReadOnlySpan<char> path, out ReadOnlySpan<char> mountName, out ReadOnlySpan<char> subPath)
|
||||
{
|
||||
int mountLen = 0;
|
||||
int maxMountLen = Math.Min(path.Length, PathTools.MountNameLength);
|
||||
|
||||
for (int i = 0; i < maxMountLen; i++)
|
||||
{
|
||||
if (path[i] == PathTools.MountSeparator)
|
||||
{
|
||||
mountLen = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mountLen == 0)
|
||||
{
|
||||
mountName = default;
|
||||
subPath = default;
|
||||
|
||||
return ResultFs.InvalidMountName;
|
||||
}
|
||||
|
||||
mountName = path.Slice(0, mountLen);
|
||||
|
||||
if (mountLen + 1 < path.Length)
|
||||
{
|
||||
subPath = path.Slice(mountLen + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
subPath = default;
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
internal bool IsEnabledAccessLog()
|
||||
{
|
||||
return AccessLogEnabled && AccessLog != null && Time != null;
|
||||
}
|
||||
|
||||
internal bool IsEnabledFileSystemAccessorAccessLog(string mountName)
|
||||
{
|
||||
if (MountTable.Find(mountName, out FileSystemAccessor accessor).IsFailure())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return accessor.IsAccessLogEnabled;
|
||||
}
|
||||
|
||||
internal bool IsEnabledHandleAccessLog(FileHandle handle)
|
||||
{
|
||||
return handle.File.Parent.IsAccessLogEnabled;
|
||||
}
|
||||
|
||||
internal bool IsEnabledHandleAccessLog(DirectoryHandle handle)
|
||||
{
|
||||
return handle.Directory.Parent.IsAccessLogEnabled;
|
||||
}
|
||||
|
||||
internal void OutputAccessLog(Result result, TimeSpan startTime, TimeSpan endTime, string message, [CallerMemberName] string caller = "")
|
||||
{
|
||||
AccessLog.Log(result, startTime, endTime, 0, message, caller);
|
||||
}
|
||||
|
||||
internal void OutputAccessLog(Result result, TimeSpan startTime, TimeSpan endTime, FileHandle handle, string message, [CallerMemberName] string caller = "")
|
||||
{
|
||||
AccessLog.Log(result, startTime, endTime, handle.GetId(), message, caller);
|
||||
}
|
||||
|
||||
internal void OutputAccessLog(Result result, TimeSpan startTime, TimeSpan endTime, DirectoryHandle handle, string message, [CallerMemberName] string caller = "")
|
||||
{
|
||||
AccessLog.Log(result, startTime, endTime, handle.GetId(), message, caller);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@ using LibHac.FsSystem;
|
|||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
public static class FileSystemManagerUtils
|
||||
public static class FileSystemClientUtils
|
||||
{
|
||||
public static Result CopyDirectory(this FileSystemManager fs, string sourcePath, string destPath,
|
||||
public static Result CopyDirectory(this FileSystemClient fs, string sourcePath, string destPath,
|
||||
CreateFileOptions options = CreateFileOptions.None, IProgressReport logger = null)
|
||||
{
|
||||
Result rc = fs.OpenDirectory(out DirectoryHandle sourceHandle, sourcePath, OpenDirectoryMode.All);
|
||||
|
@ -44,7 +44,7 @@ namespace LibHac.Fs
|
|||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result CopyFile(this FileSystemManager fs, string sourcePath, string destPath, IProgressReport logger = null)
|
||||
public static Result CopyFile(this FileSystemClient fs, string sourcePath, string destPath, IProgressReport logger = null)
|
||||
{
|
||||
Result rc = fs.OpenFile(out FileHandle sourceHandle, sourcePath, OpenMode.Read);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
@ -96,17 +96,17 @@ namespace LibHac.Fs
|
|||
return Result.Success;
|
||||
}
|
||||
|
||||
public static IEnumerable<DirectoryEntryEx> EnumerateEntries(this FileSystemManager fs, string path)
|
||||
public static IEnumerable<DirectoryEntryEx> EnumerateEntries(this FileSystemClient fs, string path)
|
||||
{
|
||||
return fs.EnumerateEntries(path, "*");
|
||||
}
|
||||
|
||||
public static IEnumerable<DirectoryEntryEx> EnumerateEntries(this FileSystemManager fs, string path, string searchPattern)
|
||||
public static IEnumerable<DirectoryEntryEx> EnumerateEntries(this FileSystemClient fs, string path, string searchPattern)
|
||||
{
|
||||
return fs.EnumerateEntries(path, searchPattern, SearchOptions.RecurseSubdirectories);
|
||||
}
|
||||
|
||||
public static IEnumerable<DirectoryEntryEx> EnumerateEntries(this FileSystemManager fs, string path, string searchPattern, SearchOptions searchOptions)
|
||||
public static IEnumerable<DirectoryEntryEx> EnumerateEntries(this FileSystemClient fs, string path, string searchPattern, SearchOptions searchOptions)
|
||||
{
|
||||
bool ignoreCase = searchOptions.HasFlag(SearchOptions.CaseInsensitive);
|
||||
bool recurse = searchOptions.HasFlag(SearchOptions.RecurseSubdirectories);
|
||||
|
@ -141,21 +141,21 @@ namespace LibHac.Fs
|
|||
}
|
||||
}
|
||||
|
||||
public static bool DirectoryExists(this FileSystemManager fs, string path)
|
||||
public static bool DirectoryExists(this FileSystemClient fs, string path)
|
||||
{
|
||||
Result rc = fs.GetEntryType(out DirectoryEntryType type, path);
|
||||
|
||||
return (rc.IsSuccess() && type == DirectoryEntryType.Directory);
|
||||
}
|
||||
|
||||
public static bool FileExists(this FileSystemManager fs, string path)
|
||||
public static bool FileExists(this FileSystemClient fs, string path)
|
||||
{
|
||||
Result rc = fs.GetEntryType(out DirectoryEntryType type, path);
|
||||
|
||||
return (rc.IsSuccess() && type == DirectoryEntryType.File);
|
||||
}
|
||||
|
||||
public static void EnsureDirectoryExists(this FileSystemManager fs, string path)
|
||||
public static void EnsureDirectoryExists(this FileSystemClient fs, string path)
|
||||
{
|
||||
path = PathTools.Normalize(path);
|
||||
if (fs.DirectoryExists(path)) return;
|
||||
|
@ -195,12 +195,12 @@ namespace LibHac.Fs
|
|||
fs.CreateDirectory(path);
|
||||
}
|
||||
|
||||
public static void CreateOrOverwriteFile(this FileSystemManager fs, string path, long size)
|
||||
public static void CreateOrOverwriteFile(this FileSystemClient fs, string path, long size)
|
||||
{
|
||||
fs.CreateOrOverwriteFile(path, size, CreateFileOptions.None);
|
||||
}
|
||||
|
||||
public static void CreateOrOverwriteFile(this FileSystemManager fs, string path, long size, CreateFileOptions options)
|
||||
public static void CreateOrOverwriteFile(this FileSystemClient fs, string path, long size, CreateFileOptions options)
|
||||
{
|
||||
path = PathTools.Normalize(path);
|
||||
|
||||
|
@ -209,7 +209,7 @@ namespace LibHac.Fs
|
|||
fs.CreateFile(path, size, CreateFileOptions.None);
|
||||
}
|
||||
|
||||
internal static bool IsEnabledFileSystemAccessorAccessLog(this FileSystemManager fs, string mountName)
|
||||
internal static bool IsEnabledFileSystemAccessorAccessLog(this FileSystemClient fs, string mountName)
|
||||
{
|
||||
if (fs.MountTable.Find(mountName, out FileSystemAccessor accessor).IsFailure())
|
||||
{
|
|
@ -1,652 +0,0 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Accessors;
|
||||
using LibHac.FsSystem;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
// Todo: Access log for FindFileSystem
|
||||
public class FileSystemManager
|
||||
{
|
||||
internal Horizon Os { get; }
|
||||
internal ITimeSpanGenerator Time { get; }
|
||||
private IAccessLog AccessLog { get; set; }
|
||||
|
||||
internal MountTable MountTable { get; } = new MountTable();
|
||||
|
||||
private bool AccessLogEnabled { get; set; }
|
||||
|
||||
public FileSystemManager(Horizon os)
|
||||
{
|
||||
Os = os;
|
||||
}
|
||||
|
||||
public FileSystemManager(Horizon os, ITimeSpanGenerator timer)
|
||||
{
|
||||
Os = os;
|
||||
Time = timer;
|
||||
}
|
||||
|
||||
public FileSystemManager(ITimeSpanGenerator timer)
|
||||
{
|
||||
Time = timer;
|
||||
}
|
||||
|
||||
public Result Register(U8Span mountName, IFileSystem fileSystem)
|
||||
{
|
||||
return Register(mountName, fileSystem, null);
|
||||
}
|
||||
|
||||
public Result Register(U8Span mountName, IFileSystem fileSystem, ICommonMountNameGenerator nameGenerator)
|
||||
{
|
||||
var accessor = new FileSystemAccessor(mountName.ToString(), fileSystem, this, nameGenerator);
|
||||
|
||||
Result rc = MountTable.Mount(accessor);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
accessor.IsAccessLogEnabled = IsEnabledAccessLog();
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public void Unmount(string mountName)
|
||||
{
|
||||
Result rc;
|
||||
|
||||
if (IsEnabledAccessLog() && this.IsEnabledFileSystemAccessorAccessLog(mountName))
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
|
||||
rc = MountTable.Unmount(mountName);
|
||||
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
OutputAccessLog(rc, startTime, endTime, $", name: \"{mountName}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = MountTable.Unmount(mountName);
|
||||
}
|
||||
|
||||
rc.ThrowIfFailure();
|
||||
}
|
||||
|
||||
public void SetAccessLog(bool isEnabled, IAccessLog accessLog = null)
|
||||
{
|
||||
AccessLogEnabled = isEnabled;
|
||||
|
||||
if (accessLog != null) AccessLog = accessLog;
|
||||
}
|
||||
|
||||
public Result CreateDirectory(string path)
|
||||
{
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = fileSystem.CreateDirectory(subPath.ToString());
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, $", path: \"{path}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.CreateDirectory(subPath.ToString());
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result CreateFile(string path, long size)
|
||||
{
|
||||
return CreateFile(path, size, CreateFileOptions.None);
|
||||
}
|
||||
|
||||
public Result CreateFile(string path, long size, CreateFileOptions options)
|
||||
{
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = fileSystem.CreateFile(subPath.ToString(), size, options);
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, $", path: \"{path}\", size: {size}");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.CreateFile(subPath.ToString(), size, options);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result DeleteDirectory(string path)
|
||||
{
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = fileSystem.DeleteDirectory(subPath.ToString());
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, $", path: \"{path}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.DeleteDirectory(subPath.ToString());
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result DeleteDirectoryRecursively(string path)
|
||||
{
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = fileSystem.DeleteDirectoryRecursively(subPath.ToString());
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, $", path: \"{path}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.DeleteDirectoryRecursively(subPath.ToString());
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result CleanDirectoryRecursively(string path)
|
||||
{
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = fileSystem.CleanDirectoryRecursively(subPath.ToString());
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, $", path: \"{path}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.CleanDirectoryRecursively(subPath.ToString());
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result DeleteFile(string path)
|
||||
{
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = fileSystem.DeleteFile(subPath.ToString());
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, $", path: \"{path}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.DeleteFile(subPath.ToString());
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result RenameDirectory(string oldPath, string newPath)
|
||||
{
|
||||
Result rc = FindFileSystem(oldPath.AsSpan(), out FileSystemAccessor oldFileSystem, out ReadOnlySpan<char> oldSubPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = FindFileSystem(newPath.AsSpan(), out FileSystemAccessor newFileSystem, out ReadOnlySpan<char> newSubPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (oldFileSystem != newFileSystem)
|
||||
{
|
||||
return ResultFs.DifferentDestFileSystem.Log();
|
||||
}
|
||||
|
||||
if (IsEnabledAccessLog() && oldFileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = oldFileSystem.RenameDirectory(oldSubPath.ToString(), newSubPath.ToString());
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, $", path: \"{oldPath}\", new_path: \"{newPath}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = oldFileSystem.RenameDirectory(oldSubPath.ToString(), newSubPath.ToString());
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result RenameFile(string oldPath, string newPath)
|
||||
{
|
||||
Result rc = FindFileSystem(oldPath.AsSpan(), out FileSystemAccessor oldFileSystem, out ReadOnlySpan<char> oldSubPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = FindFileSystem(newPath.AsSpan(), out FileSystemAccessor newFileSystem, out ReadOnlySpan<char> newSubPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (oldFileSystem != newFileSystem)
|
||||
{
|
||||
return ResultFs.DifferentDestFileSystem.Log();
|
||||
}
|
||||
|
||||
if (IsEnabledAccessLog() && oldFileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = oldFileSystem.RenameFile(oldSubPath.ToString(), newSubPath.ToString());
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, $", path: \"{oldPath}\", new_path: \"{newPath}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = oldFileSystem.RenameFile(oldSubPath.ToString(), newSubPath.ToString());
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result GetEntryType(out DirectoryEntryType type, string path)
|
||||
{
|
||||
type = default;
|
||||
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = fileSystem.GetEntryType(out type, subPath.ToString());
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, $", path: \"{path}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.GetEntryType(out type, subPath.ToString());
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result OpenFile(out FileHandle handle, string path, OpenMode mode)
|
||||
{
|
||||
handle = default;
|
||||
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = fileSystem.OpenFile(out FileAccessor file, subPath.ToString(), mode);
|
||||
handle = new FileHandle(file);
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, handle, $", path: \"{path}\", open_mode: {mode}");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.OpenFile(out FileAccessor file, subPath.ToString(), mode);
|
||||
handle = new FileHandle(file);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result OpenDirectory(out DirectoryHandle handle, string path, OpenDirectoryMode mode)
|
||||
{
|
||||
handle = default;
|
||||
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = fileSystem.OpenDirectory(out DirectoryAccessor dir, subPath.ToString(), mode);
|
||||
handle = new DirectoryHandle(dir);
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, handle, $", path: \"{path}\", open_mode: {mode}");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.OpenDirectory(out DirectoryAccessor dir, subPath.ToString(), mode);
|
||||
handle = new DirectoryHandle(dir);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result GetFreeSpaceSize(out long freeSpace, string path)
|
||||
{
|
||||
freeSpace = default;
|
||||
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return fileSystem.GetFreeSpaceSize(out freeSpace, subPath.ToString());
|
||||
}
|
||||
|
||||
public Result GetTotalSpaceSize(out long totalSpace, string path)
|
||||
{
|
||||
totalSpace = default;
|
||||
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return fileSystem.GetTotalSpaceSize(out totalSpace, subPath.ToString());
|
||||
}
|
||||
|
||||
public Result GetFileTimeStamp(out FileTimeStampRaw timeStamp, string path)
|
||||
{
|
||||
timeStamp = default;
|
||||
|
||||
Result rc = FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return fileSystem.GetFileTimeStampRaw(out timeStamp, subPath.ToString());
|
||||
}
|
||||
|
||||
public Result Commit(string mountName)
|
||||
{
|
||||
Result rc = MountTable.Find(mountName, out FileSystemAccessor fileSystem);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = fileSystem.Commit();
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, $", name: \"{mountName}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.Commit();
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
// ==========================
|
||||
// Operations on file handles
|
||||
// ==========================
|
||||
public Result ReadFile(FileHandle handle, long offset, Span<byte> destination)
|
||||
{
|
||||
return ReadFile(handle, offset, destination, ReadOption.None);
|
||||
}
|
||||
|
||||
public Result ReadFile(FileHandle handle, long offset, Span<byte> destination, ReadOption option)
|
||||
{
|
||||
Result rc = ReadFile(out long bytesRead, handle, offset, destination, option);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (bytesRead == destination.Length) return Result.Success;
|
||||
|
||||
return ResultFs.ValueOutOfRange.Log();
|
||||
}
|
||||
|
||||
public Result ReadFile(out long bytesRead, FileHandle handle, long offset, Span<byte> destination)
|
||||
{
|
||||
return ReadFile(out bytesRead, handle, offset, destination, ReadOption.None);
|
||||
}
|
||||
|
||||
public Result ReadFile(out long bytesRead, FileHandle handle, long offset, Span<byte> destination, ReadOption option)
|
||||
{
|
||||
Result rc;
|
||||
|
||||
if (IsEnabledAccessLog() && IsEnabledHandleAccessLog(handle))
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = handle.File.Read(out bytesRead, offset, destination, 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);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result WriteFile(FileHandle handle, long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
return WriteFile(handle, offset, source, WriteOption.None);
|
||||
}
|
||||
|
||||
public Result WriteFile(FileHandle handle, long offset, ReadOnlySpan<byte> source, WriteOption option)
|
||||
{
|
||||
Result rc;
|
||||
|
||||
if (IsEnabledAccessLog() && IsEnabledHandleAccessLog(handle))
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = handle.File.Write(offset, source, option);
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
string optionString = (option & WriteOption.Flush) == 0 ? "" : $", write_option: {option}";
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, handle, $", offset: {offset}, size: {source.Length}{optionString}");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = handle.File.Write(offset, source, option);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result FlushFile(FileHandle handle)
|
||||
{
|
||||
Result rc;
|
||||
|
||||
if (IsEnabledAccessLog() && IsEnabledHandleAccessLog(handle))
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = handle.File.Flush();
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, handle, string.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = handle.File.Flush();
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result GetFileSize(out long fileSize, FileHandle handle)
|
||||
{
|
||||
return handle.File.GetSize(out fileSize);
|
||||
}
|
||||
|
||||
public Result SetFileSize(FileHandle handle, long size)
|
||||
{
|
||||
Result rc;
|
||||
|
||||
if (IsEnabledAccessLog() && IsEnabledHandleAccessLog(handle))
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = handle.File.SetSize(size);
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, handle, $", size: {size}");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = handle.File.SetSize(size);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public OpenMode GetFileOpenMode(FileHandle handle)
|
||||
{
|
||||
return handle.File.OpenMode;
|
||||
}
|
||||
|
||||
public void CloseFile(FileHandle handle)
|
||||
{
|
||||
if (IsEnabledAccessLog() && IsEnabledHandleAccessLog(handle))
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
handle.File.Dispose();
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(Result.Success, startTime, endTime, handle, string.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
handle.File.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================
|
||||
// Operations on directory handles
|
||||
// ==========================
|
||||
public Result GetDirectoryEntryCount(out long count, DirectoryHandle handle)
|
||||
{
|
||||
return handle.Directory.GetEntryCount(out count);
|
||||
}
|
||||
|
||||
public Result ReadDirectory(out long entriesRead, Span<DirectoryEntry> entryBuffer, DirectoryHandle handle)
|
||||
{
|
||||
Result rc;
|
||||
|
||||
if (IsEnabledAccessLog() && IsEnabledHandleAccessLog(handle))
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = handle.Directory.Read(out entriesRead, entryBuffer);
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, handle, string.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = handle.Directory.Read(out entriesRead, entryBuffer);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public void CloseDirectory(DirectoryHandle handle)
|
||||
{
|
||||
if (IsEnabledAccessLog() && IsEnabledHandleAccessLog(handle))
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
handle.Directory.Dispose();
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(Result.Success, startTime, endTime, handle, string.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
handle.Directory.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
internal Result FindFileSystem(ReadOnlySpan<char> path, out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath)
|
||||
{
|
||||
fileSystem = default;
|
||||
|
||||
Result rc = GetMountName(path, out ReadOnlySpan<char> mountName, out subPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = MountTable.Find(mountName.ToString(), out fileSystem);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
internal static Result GetMountName(ReadOnlySpan<char> path, out ReadOnlySpan<char> mountName, out ReadOnlySpan<char> subPath)
|
||||
{
|
||||
int mountLen = 0;
|
||||
int maxMountLen = Math.Min(path.Length, PathTools.MountNameLength);
|
||||
|
||||
for (int i = 0; i < maxMountLen; i++)
|
||||
{
|
||||
if (path[i] == PathTools.MountSeparator)
|
||||
{
|
||||
mountLen = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mountLen == 0)
|
||||
{
|
||||
mountName = default;
|
||||
subPath = default;
|
||||
|
||||
return ResultFs.InvalidMountName;
|
||||
}
|
||||
|
||||
mountName = path.Slice(0, mountLen);
|
||||
|
||||
if (mountLen + 1 < path.Length)
|
||||
{
|
||||
subPath = path.Slice(mountLen + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
subPath = default;
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
internal bool IsEnabledAccessLog()
|
||||
{
|
||||
return AccessLogEnabled && AccessLog != null && Time != null;
|
||||
}
|
||||
|
||||
internal bool IsEnabledHandleAccessLog(FileHandle handle)
|
||||
{
|
||||
return handle.File.Parent.IsAccessLogEnabled;
|
||||
}
|
||||
|
||||
internal bool IsEnabledHandleAccessLog(DirectoryHandle handle)
|
||||
{
|
||||
return handle.Directory.Parent.IsAccessLogEnabled;
|
||||
}
|
||||
|
||||
internal void OutputAccessLog(Result result, TimeSpan startTime, TimeSpan endTime, string message, [CallerMemberName] string caller = "")
|
||||
{
|
||||
AccessLog.Log(result, startTime, endTime, 0, message, caller);
|
||||
}
|
||||
|
||||
internal void OutputAccessLog(Result result, TimeSpan startTime, TimeSpan endTime, FileHandle handle, string message, [CallerMemberName] string caller = "")
|
||||
{
|
||||
AccessLog.Log(result, startTime, endTime, handle.GetId(), message, caller);
|
||||
}
|
||||
|
||||
internal void OutputAccessLog(Result result, TimeSpan startTime, TimeSpan endTime, DirectoryHandle handle, string message, [CallerMemberName] string caller = "")
|
||||
{
|
||||
AccessLog.Log(result, startTime, endTime, handle.GetId(), message, caller);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,21 +8,16 @@ namespace LibHac
|
|||
{
|
||||
internal ITimeSpanGenerator Time { get; }
|
||||
|
||||
public FileSystemManager Fs { get; }
|
||||
public FileSystemClient Fs { get; }
|
||||
public FileSystemServer FsSrv { get; private set; }
|
||||
|
||||
private readonly object _initLocker = new object();
|
||||
|
||||
public Horizon()
|
||||
{
|
||||
Fs = new FileSystemManager(this);
|
||||
}
|
||||
|
||||
public Horizon(ITimeSpanGenerator timer)
|
||||
{
|
||||
Time = timer;
|
||||
|
||||
Fs = new FileSystemManager(this, timer);
|
||||
Fs = new FileSystemClient(timer);
|
||||
}
|
||||
|
||||
public void InitializeFileSystemServer(FileSystemCreators fsCreators)
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace hactoolnet
|
|||
{
|
||||
public static class FsUtils
|
||||
{
|
||||
public static void CopyDirectoryWithProgress(FileSystemManager fs, string sourcePath, string destPath,
|
||||
public static void CopyDirectoryWithProgress(FileSystemClient fs, string sourcePath, string destPath,
|
||||
CreateFileOptions options = CreateFileOptions.None, IProgressReport logger = null)
|
||||
{
|
||||
try
|
||||
|
@ -23,7 +23,7 @@ namespace hactoolnet
|
|||
}
|
||||
}
|
||||
|
||||
private static void CopyDirectoryWithProgressInternal(FileSystemManager fs, string sourcePath, string destPath,
|
||||
private static void CopyDirectoryWithProgressInternal(FileSystemClient fs, string sourcePath, string destPath,
|
||||
CreateFileOptions options, IProgressReport logger)
|
||||
{
|
||||
fs.OpenDirectory(out DirectoryHandle sourceHandle, sourcePath, OpenDirectoryMode.All).ThrowIfFailure();
|
||||
|
@ -53,7 +53,7 @@ namespace hactoolnet
|
|||
}
|
||||
}
|
||||
|
||||
public static long GetTotalSize(FileSystemManager fs, string path, string searchPattern = "*")
|
||||
public static long GetTotalSize(FileSystemClient fs, string path, string searchPattern = "*")
|
||||
{
|
||||
long size = 0;
|
||||
|
||||
|
@ -65,7 +65,7 @@ namespace hactoolnet
|
|||
return size;
|
||||
}
|
||||
|
||||
public static Result CopyFileWithProgress(FileSystemManager fs, string sourcePath, string destPath, IProgressReport logger = null)
|
||||
public static Result CopyFileWithProgress(FileSystemClient fs, string sourcePath, string destPath, IProgressReport logger = null)
|
||||
{
|
||||
Result rc = fs.OpenFile(out FileHandle sourceHandle, sourcePath, OpenMode.Read);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
@ -95,7 +95,7 @@ namespace hactoolnet
|
|||
rc = fs.ReadFile(out long _, sourceHandle, offset, buf);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = fs.WriteFile(destHandle, buf, offset);
|
||||
rc = fs.WriteFile(destHandle, offset, buf);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
logger?.ReportAdd(toRead);
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace hactoolnet
|
|||
|
||||
if (ctx.Options.SectionOutDir[i] != null)
|
||||
{
|
||||
FileSystemManager fs = ctx.Horizon.Fs;
|
||||
FileSystemClient fs = ctx.Horizon.Fs;
|
||||
|
||||
string mountName = $"section{i}";
|
||||
|
||||
|
@ -95,7 +95,7 @@ namespace hactoolnet
|
|||
|
||||
if (ctx.Options.RomfsOutDir != null)
|
||||
{
|
||||
FileSystemManager fs = ctx.Horizon.Fs;
|
||||
FileSystemClient fs = ctx.Horizon.Fs;
|
||||
|
||||
fs.Register("rom".AsU8Span(), OpenFileSystemByType(NcaSectionType.Data));
|
||||
fs.Register("output".AsU8Span(), new LocalFileSystem(ctx.Options.RomfsOutDir));
|
||||
|
@ -152,7 +152,7 @@ namespace hactoolnet
|
|||
|
||||
if (ctx.Options.ExefsOutDir != null)
|
||||
{
|
||||
FileSystemManager fs = ctx.Horizon.Fs;
|
||||
FileSystemClient fs = ctx.Horizon.Fs;
|
||||
|
||||
fs.Register("code".AsU8Span(), OpenFileSystemByType(NcaSectionType.Code));
|
||||
fs.Register("output".AsU8Span(), new LocalFileSystem(ctx.Options.ExefsOutDir));
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace hactoolnet
|
|||
bool signNeeded = ctx.Options.SignSave;
|
||||
|
||||
var save = new SaveDataFileSystem(ctx.Keyset, file, ctx.Options.IntegrityLevel, true);
|
||||
FileSystemManager fs = ctx.Horizon.Fs;
|
||||
FileSystemClient fs = ctx.Horizon.Fs;
|
||||
|
||||
fs.Register("save".AsU8Span(), save);
|
||||
|
||||
|
|
Loading…
Reference in a new issue