mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Add FS access log
This commit is contained in:
parent
5d32150ad8
commit
1859b4ce26
8 changed files with 328 additions and 31 deletions
|
@ -11,6 +11,8 @@ namespace LibHac.Fs.Accessors
|
||||||
Directory = directory;
|
Directory = directory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int GetId() => Directory.GetHashCode();
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Directory.Dispose();
|
Directory.Dispose();
|
||||||
|
|
|
@ -11,6 +11,8 @@ namespace LibHac.Fs.Accessors
|
||||||
File = file;
|
File = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int GetId() => File.GetHashCode();
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
File.Dispose();
|
File.Dispose();
|
||||||
|
|
|
@ -11,28 +11,20 @@ namespace LibHac.Fs.Accessors
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
|
|
||||||
private IFileSystem FileSystem { get; }
|
private IFileSystem FileSystem { get; }
|
||||||
private IAccessLogger Logger { get; }
|
|
||||||
private ITimeSpanGenerator Timer { get; }
|
|
||||||
|
|
||||||
private HashSet<FileAccessor> OpenFiles { get; } = new HashSet<FileAccessor>();
|
private HashSet<FileAccessor> OpenFiles { get; } = new HashSet<FileAccessor>();
|
||||||
private HashSet<DirectoryAccessor> OpenDirectories { get; } = new HashSet<DirectoryAccessor>();
|
private HashSet<DirectoryAccessor> OpenDirectories { get; } = new HashSet<DirectoryAccessor>();
|
||||||
|
|
||||||
private readonly object _locker = new object();
|
private readonly object _locker = new object();
|
||||||
|
|
||||||
|
internal bool IsAccessLogEnabled { get; set; }
|
||||||
|
|
||||||
public FileSystemAccessor(string name, IFileSystem baseFileSystem)
|
public FileSystemAccessor(string name, IFileSystem baseFileSystem)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
FileSystem = baseFileSystem;
|
FileSystem = baseFileSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileSystemAccessor(string name, IFileSystem baseFileSystem, IAccessLogger logger, ITimeSpanGenerator timer)
|
|
||||||
{
|
|
||||||
Name = name;
|
|
||||||
FileSystem = baseFileSystem;
|
|
||||||
Logger = logger;
|
|
||||||
Timer = timer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CreateDirectory(string path)
|
public void CreateDirectory(string path)
|
||||||
{
|
{
|
||||||
FileSystem.CreateDirectory(path);
|
FileSystem.CreateDirectory(path);
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
namespace LibHac.Fs.Accessors
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace LibHac.Fs.Accessors
|
||||||
{
|
{
|
||||||
public interface IAccessLogger
|
public interface IAccessLogger
|
||||||
{
|
{
|
||||||
|
void Log(TimeSpan startTime, TimeSpan endTime, int handleId, string message, [CallerMemberName] string caller = "");
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using LibHac.Fs.Accessors;
|
using LibHac.Fs.Accessors;
|
||||||
|
|
||||||
using static LibHac.Results;
|
using static LibHac.Results;
|
||||||
|
@ -10,19 +11,32 @@ namespace LibHac.Fs
|
||||||
public class FileSystemManager
|
public class FileSystemManager
|
||||||
{
|
{
|
||||||
internal Horizon Os { get; }
|
internal Horizon Os { get; }
|
||||||
|
internal ITimeSpanGenerator Time { get; }
|
||||||
|
internal IAccessLogger Logger { get; }
|
||||||
|
|
||||||
internal MountTable MountTable { get; } = new MountTable();
|
internal MountTable MountTable { get; } = new MountTable();
|
||||||
|
|
||||||
|
private bool AccessLogEnabled { get; set; } = true;
|
||||||
|
|
||||||
public FileSystemManager(Horizon os)
|
public FileSystemManager(Horizon os)
|
||||||
{
|
{
|
||||||
Os = os;
|
Os = os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FileSystemManager(Horizon os, IAccessLogger logger, ITimeSpanGenerator timer)
|
||||||
|
{
|
||||||
|
Os = os;
|
||||||
|
Logger = logger;
|
||||||
|
Time = timer;
|
||||||
|
}
|
||||||
|
|
||||||
public void Register(string mountName, IFileSystem fileSystem)
|
public void Register(string mountName, IFileSystem fileSystem)
|
||||||
{
|
{
|
||||||
var accessor = new FileSystemAccessor(mountName, fileSystem);
|
var accessor = new FileSystemAccessor(mountName, fileSystem);
|
||||||
|
|
||||||
MountTable.Mount(accessor);
|
MountTable.Mount(accessor);
|
||||||
|
|
||||||
|
accessor.IsAccessLogEnabled = IsEnabledAccessLog();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CreateDirectory(string path)
|
public void CreateDirectory(string path)
|
||||||
|
@ -30,7 +44,18 @@ namespace LibHac.Fs
|
||||||
FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath)
|
FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath)
|
||||||
.ThrowIfFailure();
|
.ThrowIfFailure();
|
||||||
|
|
||||||
fileSystem.CreateDirectory(subPath.ToString());
|
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||||
|
{
|
||||||
|
TimeSpan startTime = Time.GetCurrent();
|
||||||
|
fileSystem.CreateDirectory(subPath.ToString());
|
||||||
|
TimeSpan endTime = Time.GetCurrent();
|
||||||
|
|
||||||
|
OutputAccessLog(startTime, endTime, $", path: \"{path}\"");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fileSystem.CreateDirectory(subPath.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CreateFile(string path, long size)
|
public void CreateFile(string path, long size)
|
||||||
|
@ -43,7 +68,18 @@ namespace LibHac.Fs
|
||||||
FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath)
|
FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath)
|
||||||
.ThrowIfFailure();
|
.ThrowIfFailure();
|
||||||
|
|
||||||
fileSystem.CreateFile(subPath.ToString(), size, options);
|
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||||
|
{
|
||||||
|
TimeSpan startTime = Time.GetCurrent();
|
||||||
|
fileSystem.CreateFile(subPath.ToString(), size, options);
|
||||||
|
TimeSpan endTime = Time.GetCurrent();
|
||||||
|
|
||||||
|
OutputAccessLog(startTime, endTime, $", path: \"{path}\", size: {size}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fileSystem.CreateFile(subPath.ToString(), size, options);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteDirectory(string path)
|
public void DeleteDirectory(string path)
|
||||||
|
@ -51,7 +87,18 @@ namespace LibHac.Fs
|
||||||
FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath)
|
FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath)
|
||||||
.ThrowIfFailure();
|
.ThrowIfFailure();
|
||||||
|
|
||||||
fileSystem.DeleteDirectory(subPath.ToString());
|
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||||
|
{
|
||||||
|
TimeSpan startTime = Time.GetCurrent();
|
||||||
|
fileSystem.DeleteDirectory(subPath.ToString());
|
||||||
|
TimeSpan endTime = Time.GetCurrent();
|
||||||
|
|
||||||
|
OutputAccessLog(startTime, endTime, $", path: \"{path}\"");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fileSystem.DeleteDirectory(subPath.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteDirectoryRecursively(string path)
|
public void DeleteDirectoryRecursively(string path)
|
||||||
|
@ -59,7 +106,18 @@ namespace LibHac.Fs
|
||||||
FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath)
|
FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath)
|
||||||
.ThrowIfFailure();
|
.ThrowIfFailure();
|
||||||
|
|
||||||
fileSystem.DeleteDirectoryRecursively(subPath.ToString());
|
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||||
|
{
|
||||||
|
TimeSpan startTime = Time.GetCurrent();
|
||||||
|
fileSystem.DeleteDirectoryRecursively(subPath.ToString());
|
||||||
|
TimeSpan endTime = Time.GetCurrent();
|
||||||
|
|
||||||
|
OutputAccessLog(startTime, endTime, $", path: \"{path}\"");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fileSystem.DeleteDirectoryRecursively(subPath.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CleanDirectoryRecursively(string path)
|
public void CleanDirectoryRecursively(string path)
|
||||||
|
@ -67,7 +125,18 @@ namespace LibHac.Fs
|
||||||
FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath)
|
FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath)
|
||||||
.ThrowIfFailure();
|
.ThrowIfFailure();
|
||||||
|
|
||||||
fileSystem.CleanDirectoryRecursively(subPath.ToString());
|
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||||
|
{
|
||||||
|
TimeSpan startTime = Time.GetCurrent();
|
||||||
|
fileSystem.CleanDirectoryRecursively(subPath.ToString());
|
||||||
|
TimeSpan endTime = Time.GetCurrent();
|
||||||
|
|
||||||
|
OutputAccessLog(startTime, endTime, $", path: \"{path}\"");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fileSystem.CleanDirectoryRecursively(subPath.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteFile(string path)
|
public void DeleteFile(string path)
|
||||||
|
@ -75,7 +144,18 @@ namespace LibHac.Fs
|
||||||
FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath)
|
FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath)
|
||||||
.ThrowIfFailure();
|
.ThrowIfFailure();
|
||||||
|
|
||||||
fileSystem.DeleteFile(subPath.ToString());
|
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||||
|
{
|
||||||
|
TimeSpan startTime = Time.GetCurrent();
|
||||||
|
fileSystem.DeleteFile(subPath.ToString());
|
||||||
|
TimeSpan endTime = Time.GetCurrent();
|
||||||
|
|
||||||
|
OutputAccessLog(startTime, endTime, $", path: \"{path}\"");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fileSystem.DeleteFile(subPath.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RenameDirectory(string oldPath, string newPath)
|
public void RenameDirectory(string oldPath, string newPath)
|
||||||
|
@ -91,7 +171,18 @@ namespace LibHac.Fs
|
||||||
ThrowHelper.ThrowResult(ResultFsDifferentDestFileSystem);
|
ThrowHelper.ThrowResult(ResultFsDifferentDestFileSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
oldFileSystem.RenameDirectory(oldSubPath.ToString(), newSubPath.ToString());
|
if (IsEnabledAccessLog() && oldFileSystem.IsAccessLogEnabled)
|
||||||
|
{
|
||||||
|
TimeSpan startTime = Time.GetCurrent();
|
||||||
|
oldFileSystem.RenameDirectory(oldSubPath.ToString(), newSubPath.ToString());
|
||||||
|
TimeSpan endTime = Time.GetCurrent();
|
||||||
|
|
||||||
|
OutputAccessLog(startTime, endTime, $", path: \"{oldPath}\", new_path: \"{newPath}\"");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oldFileSystem.RenameDirectory(oldSubPath.ToString(), newSubPath.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RenameFile(string oldPath, string newPath)
|
public void RenameFile(string oldPath, string newPath)
|
||||||
|
@ -107,7 +198,18 @@ namespace LibHac.Fs
|
||||||
ThrowHelper.ThrowResult(ResultFsDifferentDestFileSystem);
|
ThrowHelper.ThrowResult(ResultFsDifferentDestFileSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
oldFileSystem.RenameFile(oldSubPath.ToString(), newSubPath.ToString());
|
if (IsEnabledAccessLog() && oldFileSystem.IsAccessLogEnabled)
|
||||||
|
{
|
||||||
|
TimeSpan startTime = Time.GetCurrent();
|
||||||
|
oldFileSystem.RenameFile(oldSubPath.ToString(), newSubPath.ToString());
|
||||||
|
TimeSpan endTime = Time.GetCurrent();
|
||||||
|
|
||||||
|
OutputAccessLog(startTime, endTime, $", path: \"{oldPath}\", new_path: \"{newPath}\"");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oldFileSystem.RenameFile(oldSubPath.ToString(), newSubPath.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DirectoryEntryType GetEntryType(string path)
|
public DirectoryEntryType GetEntryType(string path)
|
||||||
|
@ -115,7 +217,22 @@ namespace LibHac.Fs
|
||||||
FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath)
|
FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath)
|
||||||
.ThrowIfFailure();
|
.ThrowIfFailure();
|
||||||
|
|
||||||
return fileSystem.GetEntryType(subPath.ToString());
|
DirectoryEntryType type;
|
||||||
|
|
||||||
|
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||||
|
{
|
||||||
|
TimeSpan startTime = Time.GetCurrent();
|
||||||
|
type = fileSystem.GetEntryType(subPath.ToString());
|
||||||
|
TimeSpan endTime = Time.GetCurrent();
|
||||||
|
|
||||||
|
OutputAccessLog(startTime, endTime, $", path: \"{path}\"");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
type = fileSystem.GetEntryType(subPath.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileHandle OpenFile(string path, OpenMode mode)
|
public FileHandle OpenFile(string path, OpenMode mode)
|
||||||
|
@ -123,9 +240,24 @@ namespace LibHac.Fs
|
||||||
FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath)
|
FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath)
|
||||||
.ThrowIfFailure();
|
.ThrowIfFailure();
|
||||||
|
|
||||||
FileAccessor file = fileSystem.OpenFile(subPath.ToString(), mode);
|
FileHandle handle;
|
||||||
|
|
||||||
return new FileHandle(file);
|
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||||
|
{
|
||||||
|
TimeSpan startTime = Time.GetCurrent();
|
||||||
|
FileAccessor file = fileSystem.OpenFile(subPath.ToString(), mode);
|
||||||
|
handle = new FileHandle(file);
|
||||||
|
TimeSpan endTime = Time.GetCurrent();
|
||||||
|
|
||||||
|
OutputAccessLog(startTime, endTime, handle, $", path: \"{path}\", open_mode: {mode}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FileAccessor file = fileSystem.OpenFile(subPath.ToString(), mode);
|
||||||
|
handle = new FileHandle(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DirectoryHandle OpenDirectory(string path, OpenDirectoryMode mode)
|
public DirectoryHandle OpenDirectory(string path, OpenDirectoryMode mode)
|
||||||
|
@ -133,9 +265,24 @@ namespace LibHac.Fs
|
||||||
FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath)
|
FindFileSystem(path.AsSpan(), out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath)
|
||||||
.ThrowIfFailure();
|
.ThrowIfFailure();
|
||||||
|
|
||||||
DirectoryAccessor dir = fileSystem.OpenDirectory(subPath.ToString(), mode);
|
DirectoryHandle handle;
|
||||||
|
|
||||||
return new DirectoryHandle(dir);
|
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||||
|
{
|
||||||
|
TimeSpan startTime = Time.GetCurrent();
|
||||||
|
DirectoryAccessor dir = fileSystem.OpenDirectory(subPath.ToString(), mode);
|
||||||
|
handle = new DirectoryHandle(dir);
|
||||||
|
TimeSpan endTime = Time.GetCurrent();
|
||||||
|
|
||||||
|
OutputAccessLog(startTime, endTime, handle, $", path: \"{path}\", open_mode: {mode}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DirectoryAccessor dir = fileSystem.OpenDirectory(subPath.ToString(), mode);
|
||||||
|
handle = new DirectoryHandle(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long GetFreeSpaceSize(string path)
|
public long GetFreeSpaceSize(string path)
|
||||||
|
@ -166,7 +313,18 @@ namespace LibHac.Fs
|
||||||
{
|
{
|
||||||
MountTable.Find(mountName, out FileSystemAccessor fileSystem).ThrowIfFailure();
|
MountTable.Find(mountName, out FileSystemAccessor fileSystem).ThrowIfFailure();
|
||||||
|
|
||||||
fileSystem.Commit();
|
if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
|
||||||
|
{
|
||||||
|
TimeSpan startTime = Time.GetCurrent();
|
||||||
|
fileSystem.Commit();
|
||||||
|
TimeSpan endTime = Time.GetCurrent();
|
||||||
|
|
||||||
|
OutputAccessLog(startTime, endTime, $", name: \"{mountName}\"");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fileSystem.Commit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==========================
|
// ==========================
|
||||||
|
@ -179,7 +337,22 @@ namespace LibHac.Fs
|
||||||
|
|
||||||
public int ReadFile(FileHandle handle, Span<byte> destination, long offset, ReadOption option)
|
public int ReadFile(FileHandle handle, Span<byte> destination, long offset, ReadOption option)
|
||||||
{
|
{
|
||||||
return handle.File.Read(destination, offset, option);
|
int bytesRead;
|
||||||
|
|
||||||
|
if (IsEnabledAccessLog() && IsEnabledHandleAccessLog(handle))
|
||||||
|
{
|
||||||
|
TimeSpan startTime = Time.GetCurrent();
|
||||||
|
bytesRead = handle.File.Read(destination, offset, option);
|
||||||
|
TimeSpan endTime = Time.GetCurrent();
|
||||||
|
|
||||||
|
OutputAccessLog(startTime, endTime, handle, $", offset: {offset}, size: {destination.Length}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bytesRead = handle.File.Read(destination, offset, option);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteFile(FileHandle handle, ReadOnlySpan<byte> source, long offset)
|
public void WriteFile(FileHandle handle, ReadOnlySpan<byte> source, long offset)
|
||||||
|
@ -189,12 +362,36 @@ namespace LibHac.Fs
|
||||||
|
|
||||||
public void WriteFile(FileHandle handle, ReadOnlySpan<byte> source, long offset, WriteOption option)
|
public void WriteFile(FileHandle handle, ReadOnlySpan<byte> source, long offset, WriteOption option)
|
||||||
{
|
{
|
||||||
handle.File.Write(source, offset, option);
|
if (IsEnabledAccessLog() && IsEnabledHandleAccessLog(handle))
|
||||||
|
{
|
||||||
|
TimeSpan startTime = Time.GetCurrent();
|
||||||
|
handle.File.Write(source, offset, option);
|
||||||
|
TimeSpan endTime = Time.GetCurrent();
|
||||||
|
|
||||||
|
string optionString = (option & WriteOption.Flush) == 0 ? "" : $", write_option: {option}";
|
||||||
|
|
||||||
|
OutputAccessLog(startTime, endTime, handle, $", offset: {offset}, size: {source.Length}{optionString}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
handle.File.Write(source, offset, option);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FlushFile(FileHandle handle)
|
public void FlushFile(FileHandle handle)
|
||||||
{
|
{
|
||||||
handle.File.Flush();
|
if (IsEnabledAccessLog() && IsEnabledHandleAccessLog(handle))
|
||||||
|
{
|
||||||
|
TimeSpan startTime = Time.GetCurrent();
|
||||||
|
handle.File.Flush();
|
||||||
|
TimeSpan endTime = Time.GetCurrent();
|
||||||
|
|
||||||
|
OutputAccessLog(startTime, endTime, handle, string.Empty);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
handle.File.Flush();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public long GetFileSize(FileHandle handle)
|
public long GetFileSize(FileHandle handle)
|
||||||
|
@ -204,7 +401,18 @@ namespace LibHac.Fs
|
||||||
|
|
||||||
public void SetFileSize(FileHandle handle, long size)
|
public void SetFileSize(FileHandle handle, long size)
|
||||||
{
|
{
|
||||||
handle.File.SetSize(size);
|
if (IsEnabledAccessLog() && IsEnabledHandleAccessLog(handle))
|
||||||
|
{
|
||||||
|
TimeSpan startTime = Time.GetCurrent();
|
||||||
|
handle.File.SetSize(size);
|
||||||
|
TimeSpan endTime = Time.GetCurrent();
|
||||||
|
|
||||||
|
OutputAccessLog(startTime, endTime, handle, $", size: {size}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
handle.File.SetSize(size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public OpenMode GetFileOpenMode(FileHandle handle)
|
public OpenMode GetFileOpenMode(FileHandle handle)
|
||||||
|
@ -214,7 +422,18 @@ namespace LibHac.Fs
|
||||||
|
|
||||||
public void CloseFile(FileHandle handle)
|
public void CloseFile(FileHandle handle)
|
||||||
{
|
{
|
||||||
handle.File.Dispose();
|
if (IsEnabledAccessLog() && IsEnabledHandleAccessLog(handle))
|
||||||
|
{
|
||||||
|
TimeSpan startTime = Time.GetCurrent();
|
||||||
|
handle.Dispose();
|
||||||
|
TimeSpan endTime = Time.GetCurrent();
|
||||||
|
|
||||||
|
OutputAccessLog(startTime, endTime, handle, string.Empty);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
handle.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==========================
|
// ==========================
|
||||||
|
@ -227,6 +446,16 @@ namespace LibHac.Fs
|
||||||
|
|
||||||
public IEnumerable<DirectoryEntry> ReadDirectory(DirectoryHandle handle)
|
public IEnumerable<DirectoryEntry> ReadDirectory(DirectoryHandle handle)
|
||||||
{
|
{
|
||||||
|
if (IsEnabledAccessLog() && IsEnabledHandleAccessLog(handle))
|
||||||
|
{
|
||||||
|
TimeSpan startTime = Time.GetCurrent();
|
||||||
|
IEnumerable<DirectoryEntry> entries = handle.Directory.Read();
|
||||||
|
TimeSpan endTime = Time.GetCurrent();
|
||||||
|
|
||||||
|
OutputAccessLog(startTime, endTime, handle, string.Empty);
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
return handle.Directory.Read();
|
return handle.Directory.Read();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,5 +507,35 @@ namespace LibHac.Fs
|
||||||
|
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal bool IsEnabledAccessLog()
|
||||||
|
{
|
||||||
|
return AccessLogEnabled && Logger != 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(TimeSpan startTime, TimeSpan endTime, string message, [CallerMemberName] string caller = "")
|
||||||
|
{
|
||||||
|
Logger.Log(startTime, endTime, 0, message, caller);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OutputAccessLog(TimeSpan startTime, TimeSpan endTime, FileHandle handle, string message, [CallerMemberName] string caller = "")
|
||||||
|
{
|
||||||
|
Logger.Log(startTime, endTime, handle.GetId(), message, caller);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OutputAccessLog(TimeSpan startTime, TimeSpan endTime, DirectoryHandle handle, string message, [CallerMemberName] string caller = "")
|
||||||
|
{
|
||||||
|
Logger.Log(startTime, endTime, handle.GetId(), message, caller);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using LibHac.Fs;
|
using LibHac.Fs;
|
||||||
|
using LibHac.Fs.Accessors;
|
||||||
|
|
||||||
namespace LibHac
|
namespace LibHac
|
||||||
{
|
{
|
||||||
|
@ -12,5 +13,12 @@ namespace LibHac
|
||||||
{
|
{
|
||||||
Fs = new FileSystemManager(this);
|
Fs = new FileSystemManager(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Horizon(IAccessLogger logger, ITimeSpanGenerator timer)
|
||||||
|
{
|
||||||
|
Time = timer;
|
||||||
|
|
||||||
|
Fs = new FileSystemManager(this, logger, timer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
15
src/hactoolnet/ConsoleAccessLog.cs
Normal file
15
src/hactoolnet/ConsoleAccessLog.cs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using LibHac.Fs.Accessors;
|
||||||
|
|
||||||
|
namespace hactoolnet
|
||||||
|
{
|
||||||
|
public class ConsoleAccessLog : IAccessLogger
|
||||||
|
{
|
||||||
|
public void Log(TimeSpan startTime, TimeSpan endTime, int handleId, string message, [CallerMemberName] string caller = "")
|
||||||
|
{
|
||||||
|
Console.WriteLine(
|
||||||
|
$"FS_ACCESS: {{ start: {startTime.Milliseconds,9}, end: {endTime.Milliseconds,9}, handle: 0x{handleId:x8}, function: \"{caller}\"{message} }}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
src/hactoolnet/TimeSpanTimer.cs
Normal file
16
src/hactoolnet/TimeSpanTimer.cs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using LibHac;
|
||||||
|
|
||||||
|
namespace hactoolnet
|
||||||
|
{
|
||||||
|
public class TimeSpanTimer : ITimeSpanGenerator
|
||||||
|
{
|
||||||
|
private Stopwatch Timer = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
public TimeSpan GetCurrent()
|
||||||
|
{
|
||||||
|
return Timer.Elapsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue