diff --git a/src/LibHac/Fs/Accessors/FileSystemAccessor.cs b/src/LibHac/Fs/Accessors/FileSystemAccessor.cs index f89b4d61..a51f1e6e 100644 --- a/src/LibHac/Fs/Accessors/FileSystemAccessor.cs +++ b/src/LibHac/Fs/Accessors/FileSystemAccessor.cs @@ -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 OpenFiles { get; } = new HashSet(); @@ -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; } diff --git a/src/LibHac/Fs/DirectoryHandle.cs b/src/LibHac/Fs/DirectoryHandle.cs index e76ac017..1a8f606b 100644 --- a/src/LibHac/Fs/DirectoryHandle.cs +++ b/src/LibHac/Fs/DirectoryHandle.cs @@ -16,7 +16,7 @@ namespace LibHac.Fs public void Dispose() { - Directory.Parent.FsManager.CloseDirectory(this); + Directory.Parent.FsClient.CloseDirectory(this); } } } diff --git a/src/LibHac/Fs/FileHandle.cs b/src/LibHac/Fs/FileHandle.cs index acb4e211..eb927d5b 100644 --- a/src/LibHac/Fs/FileHandle.cs +++ b/src/LibHac/Fs/FileHandle.cs @@ -16,7 +16,7 @@ namespace LibHac.Fs public void Dispose() { - File.Parent.FsManager.CloseFile(this); + File.Parent.FsClient.CloseFile(this); } } } diff --git a/src/LibHac/Fs/FileHandleStorage.cs b/src/LibHac/Fs/FileHandleStorage.cs index 04052833..729e2d78 100644 --- a/src/LibHac/Fs/FileHandleStorage.cs +++ b/src/LibHac/Fs/FileHandleStorage.cs @@ -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 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); } } } diff --git a/src/LibHac/Fs/FileSystemClient.Directory.cs b/src/LibHac/Fs/FileSystemClient.Directory.cs index 90253dfe..499b7150 100644 --- a/src/LibHac/Fs/FileSystemClient.Directory.cs +++ b/src/LibHac/Fs/FileSystemClient.Directory.cs @@ -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 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(); + } } } } diff --git a/src/LibHac/Fs/FileSystemClient.File.cs b/src/LibHac/Fs/FileSystemClient.File.cs index 83cd3760..3e508426 100644 --- a/src/LibHac/Fs/FileSystemClient.File.cs +++ b/src/LibHac/Fs/FileSystemClient.File.cs @@ -6,52 +6,135 @@ namespace LibHac.Fs { public Result ReadFile(FileHandle handle, long offset, Span destination) { - return FsManager.ReadFile(handle, offset, destination); + return ReadFile(handle, offset, destination, ReadOption.None); } - public Result ReadFile(FileHandle handle, long offset, Span destination, ReadOption options) + public Result ReadFile(FileHandle handle, long offset, Span 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 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 destination, ReadOption options) + public Result ReadFile(out long bytesRead, FileHandle handle, long offset, Span 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 source, WriteOption options) + public Result WriteFile(FileHandle handle, long offset, ReadOnlySpan source) { - return FsManager.WriteFile(handle, offset, source, options); + return WriteFile(handle, offset, source, WriteOption.None); + } + + public Result WriteFile(FileHandle handle, long offset, ReadOnlySpan 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(); + } } } } diff --git a/src/LibHac/Fs/FileSystemClient.FileSystem.cs b/src/LibHac/Fs/FileSystemClient.FileSystem.cs index 2f5707f1..7ed7e6a9 100644 --- a/src/LibHac/Fs/FileSystemClient.FileSystem.cs +++ b/src/LibHac/Fs/FileSystemClient.FileSystem.cs @@ -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 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 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 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 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 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 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 oldSubPath); + if (rc.IsFailure()) return rc; + + rc = FindFileSystem(newPath.AsSpan(), out FileSystemAccessor newFileSystem, out ReadOnlySpan 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 oldSubPath); + if (rc.IsFailure()) return rc; + + rc = FindFileSystem(newPath.AsSpan(), out FileSystemAccessor newFileSystem, out ReadOnlySpan 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 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 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 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 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 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 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; } } -} \ No newline at end of file +} diff --git a/src/LibHac/Fs/FileSystemClient.cs b/src/LibHac/Fs/FileSystemClient.cs index 76ce211b..8ac67876 100644 --- a/src/LibHac/Fs/FileSystemClient.cs +++ b/src/LibHac/Fs/FileSystemClient.cs @@ -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 path, out FileSystemAccessor fileSystem, out ReadOnlySpan subPath) + { + fileSystem = default; + + Result rc = GetMountName(path, out ReadOnlySpan 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 path, out ReadOnlySpan mountName, out ReadOnlySpan 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); } } } diff --git a/src/LibHac/Fs/FileSystemManagerUtils.cs b/src/LibHac/Fs/FileSystemClientUtils.cs similarity index 90% rename from src/LibHac/Fs/FileSystemManagerUtils.cs rename to src/LibHac/Fs/FileSystemClientUtils.cs index be795316..0165f354 100644 --- a/src/LibHac/Fs/FileSystemManagerUtils.cs +++ b/src/LibHac/Fs/FileSystemClientUtils.cs @@ -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 EnumerateEntries(this FileSystemManager fs, string path) + public static IEnumerable EnumerateEntries(this FileSystemClient fs, string path) { return fs.EnumerateEntries(path, "*"); } - public static IEnumerable EnumerateEntries(this FileSystemManager fs, string path, string searchPattern) + public static IEnumerable EnumerateEntries(this FileSystemClient fs, string path, string searchPattern) { return fs.EnumerateEntries(path, searchPattern, SearchOptions.RecurseSubdirectories); } - public static IEnumerable EnumerateEntries(this FileSystemManager fs, string path, string searchPattern, SearchOptions searchOptions) + public static IEnumerable 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()) { diff --git a/src/LibHac/Fs/FileSystemManager.cs b/src/LibHac/Fs/FileSystemManager.cs deleted file mode 100644 index 0a685f34..00000000 --- a/src/LibHac/Fs/FileSystemManager.cs +++ /dev/null @@ -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 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 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 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 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 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 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 oldSubPath); - if (rc.IsFailure()) return rc; - - rc = FindFileSystem(newPath.AsSpan(), out FileSystemAccessor newFileSystem, out ReadOnlySpan 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 oldSubPath); - if (rc.IsFailure()) return rc; - - rc = FindFileSystem(newPath.AsSpan(), out FileSystemAccessor newFileSystem, out ReadOnlySpan 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 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 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 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 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 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 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 destination) - { - return ReadFile(handle, offset, destination, ReadOption.None); - } - - public Result ReadFile(FileHandle handle, long offset, Span 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 destination) - { - return ReadFile(out bytesRead, handle, offset, destination, ReadOption.None); - } - - public Result ReadFile(out long bytesRead, FileHandle handle, long offset, Span 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 source) - { - return WriteFile(handle, offset, source, WriteOption.None); - } - - public Result WriteFile(FileHandle handle, long offset, ReadOnlySpan 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 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 path, out FileSystemAccessor fileSystem, out ReadOnlySpan subPath) - { - fileSystem = default; - - Result rc = GetMountName(path, out ReadOnlySpan 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 path, out ReadOnlySpan mountName, out ReadOnlySpan 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); - } - } -} diff --git a/src/LibHac/Horizon.cs b/src/LibHac/Horizon.cs index cd9da365..d93fc1df 100644 --- a/src/LibHac/Horizon.cs +++ b/src/LibHac/Horizon.cs @@ -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) diff --git a/src/hactoolnet/FsUtils.cs b/src/hactoolnet/FsUtils.cs index 05cfaa33..e7d06748 100644 --- a/src/hactoolnet/FsUtils.cs +++ b/src/hactoolnet/FsUtils.cs @@ -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); diff --git a/src/hactoolnet/ProcessNca.cs b/src/hactoolnet/ProcessNca.cs index 311b14a1..dc640f5d 100644 --- a/src/hactoolnet/ProcessNca.cs +++ b/src/hactoolnet/ProcessNca.cs @@ -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)); diff --git a/src/hactoolnet/ProcessSave.cs b/src/hactoolnet/ProcessSave.cs index 4f067a7c..a225d382 100644 --- a/src/hactoolnet/ProcessSave.cs +++ b/src/hactoolnet/ProcessSave.cs @@ -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);