mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Add an option to control which types of access events are logged
This commit is contained in:
parent
22bbf07c2b
commit
5011a57d3e
9 changed files with 172 additions and 137 deletions
|
@ -2,12 +2,12 @@
|
|||
{
|
||||
public static class U8StringHelpers
|
||||
{
|
||||
public static U8String AsU8String(this string value)
|
||||
public static U8String ToU8String(this string value)
|
||||
{
|
||||
return new U8String(value);
|
||||
}
|
||||
|
||||
public static U8Span AsU8Span(this string value)
|
||||
public static U8Span ToU8Span(this string value)
|
||||
{
|
||||
return new U8Span(value);
|
||||
}
|
||||
|
|
14
src/LibHac/Fs/AccessLogHelpers.cs
Normal file
14
src/LibHac/Fs/AccessLogHelpers.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
public static class AccessLogHelpers
|
||||
{
|
||||
public static string BuildDefaultLogLine(Result result, TimeSpan startTime, TimeSpan endTime, int handleId,
|
||||
string message, string caller)
|
||||
{
|
||||
return
|
||||
$"FS_ACCESS: {{ start: {(long) startTime.TotalMilliseconds,9}, end: {(long) endTime.TotalMilliseconds,9}, result: 0x{result.Value:x8}, handle: 0x{handleId:x8}, function: \"{caller}\"{message} }}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Accessors;
|
||||
using LibHac.FsService;
|
||||
|
||||
namespace LibHac.Fs
|
||||
|
@ -14,16 +16,28 @@ namespace LibHac.Fs
|
|||
|
||||
public Result GetGlobalAccessLogMode(out GlobalAccessLogMode mode)
|
||||
{
|
||||
IFileSystemProxy fsProxy = GetFileSystemProxyServiceObject();
|
||||
if (HasFileSystemServer())
|
||||
{
|
||||
IFileSystemProxy fsProxy = GetFileSystemProxyServiceObject();
|
||||
|
||||
return fsProxy.GetGlobalAccessLogMode(out mode);
|
||||
return fsProxy.GetGlobalAccessLogMode(out mode);
|
||||
}
|
||||
|
||||
mode = GlobalAccessLogMode;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result SetGlobalAccessLogMode(GlobalAccessLogMode mode)
|
||||
{
|
||||
IFileSystemProxy fsProxy = GetFileSystemProxyServiceObject();
|
||||
if (HasFileSystemServer())
|
||||
{
|
||||
IFileSystemProxy fsProxy = GetFileSystemProxyServiceObject();
|
||||
|
||||
return fsProxy.SetGlobalAccessLogMode(mode);
|
||||
return fsProxy.SetGlobalAccessLogMode(mode);
|
||||
}
|
||||
|
||||
GlobalAccessLogMode = mode;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public void SetLocalAccessLogMode(LocalAccessLogMode mode)
|
||||
|
@ -31,6 +45,11 @@ namespace LibHac.Fs
|
|||
LocalAccessLogMode = mode;
|
||||
}
|
||||
|
||||
public void SetAccessLogObject(IAccessLog accessLog)
|
||||
{
|
||||
AccessLog = accessLog;
|
||||
}
|
||||
|
||||
internal bool IsEnabledAccessLog(LocalAccessLogMode mode)
|
||||
{
|
||||
if ((LocalAccessLogMode & mode) == 0)
|
||||
|
@ -47,14 +66,21 @@ namespace LibHac.Fs
|
|||
{
|
||||
if (!AccessLogInitialized)
|
||||
{
|
||||
IFileSystemProxy fsProxy = GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.GetGlobalAccessLogMode(out GlobalAccessLogMode globalMode);
|
||||
GlobalAccessLogMode = globalMode;
|
||||
|
||||
if (rc.IsFailure())
|
||||
if (HasFileSystemServer())
|
||||
{
|
||||
throw new LibHacException("Abort");
|
||||
IFileSystemProxy fsProxy = GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.GetGlobalAccessLogMode(out GlobalAccessLogMode globalMode);
|
||||
GlobalAccessLogMode = globalMode;
|
||||
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
throw new LibHacException("Abort");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GlobalAccessLogMode = GlobalAccessLogMode.Log;
|
||||
}
|
||||
|
||||
if (GlobalAccessLogMode != GlobalAccessLogMode.None)
|
||||
|
@ -74,7 +100,65 @@ namespace LibHac.Fs
|
|||
|
||||
}
|
||||
|
||||
public Result RunOperationWithAccessLog(LocalAccessLogMode logType, Func<Result> operation, Func<string> textGenerator, [CallerMemberName] string caller = "")
|
||||
internal bool IsEnabledAccessLog()
|
||||
{
|
||||
return IsEnabledAccessLog(LocalAccessLogMode.All);
|
||||
}
|
||||
|
||||
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 = "")
|
||||
{
|
||||
OutputAccessLogImpl(result, startTime, endTime, 0, message, caller);
|
||||
}
|
||||
|
||||
internal void OutputAccessLog(Result result, TimeSpan startTime, TimeSpan endTime, FileHandle handle, string message, [CallerMemberName] string caller = "")
|
||||
{
|
||||
OutputAccessLogImpl(result, startTime, endTime, handle.GetId(), message, caller);
|
||||
}
|
||||
|
||||
internal void OutputAccessLog(Result result, TimeSpan startTime, TimeSpan endTime, DirectoryHandle handle, string message, [CallerMemberName] string caller = "")
|
||||
{
|
||||
OutputAccessLogImpl(result, startTime, endTime, handle.GetId(), message, caller);
|
||||
}
|
||||
|
||||
internal void OutputAccessLogImpl(Result result, TimeSpan startTime, TimeSpan endTime, int handleId,
|
||||
string message, [CallerMemberName] string caller = "")
|
||||
{
|
||||
if (GlobalAccessLogMode.HasFlag(GlobalAccessLogMode.Log))
|
||||
{
|
||||
AccessLog?.Log(result, startTime, endTime, handleId, message, caller);
|
||||
}
|
||||
|
||||
if (GlobalAccessLogMode.HasFlag(GlobalAccessLogMode.SdCard))
|
||||
{
|
||||
string logString = AccessLogHelpers.BuildDefaultLogLine(result, startTime, endTime, handleId, message, caller);
|
||||
|
||||
IFileSystemProxy fsProxy = GetFileSystemProxyServiceObject();
|
||||
fsProxy.OutputAccessLogToSdCard(logString.ToU8Span());
|
||||
}
|
||||
}
|
||||
|
||||
public Result RunOperationWithAccessLog(LocalAccessLogMode logType, Func<Result> operation,
|
||||
Func<string> textGenerator, [CallerMemberName] string caller = "")
|
||||
{
|
||||
Result rc;
|
||||
|
||||
|
@ -93,6 +177,27 @@ namespace LibHac.Fs
|
|||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public Result RunOperationWithAccessLog(LocalAccessLogMode logType, FileHandle handle, Func<Result> operation,
|
||||
Func<string> textGenerator, [CallerMemberName] string caller = "")
|
||||
{
|
||||
Result rc;
|
||||
|
||||
if (IsEnabledAccessLog(logType) && handle.File.Parent.IsAccessLogEnabled)
|
||||
{
|
||||
TimeSpan startTime = Time.GetCurrent();
|
||||
rc = operation();
|
||||
TimeSpan endTime = Time.GetCurrent();
|
||||
|
||||
OutputAccessLog(rc, startTime, endTime, textGenerator(), caller);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = operation();
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
|
|
@ -73,22 +73,9 @@ namespace LibHac.Fs
|
|||
|
||||
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;
|
||||
return RunOperationWithAccessLog(LocalAccessLogMode.All, handle,
|
||||
() => handle.File.Flush(),
|
||||
() => string.Empty);
|
||||
}
|
||||
|
||||
public Result GetFileSize(out long fileSize, FileHandle handle)
|
||||
|
@ -98,22 +85,9 @@ namespace LibHac.Fs
|
|||
|
||||
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;
|
||||
return RunOperationWithAccessLog(LocalAccessLogMode.All, handle,
|
||||
() => handle.File.SetSize(size),
|
||||
() => $", size: {size}");
|
||||
}
|
||||
|
||||
public OpenMode GetFileOpenMode(FileHandle handle)
|
||||
|
@ -123,18 +97,13 @@ namespace LibHac.Fs
|
|||
|
||||
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();
|
||||
}
|
||||
RunOperationWithAccessLog(LocalAccessLogMode.All, handle,
|
||||
() =>
|
||||
{
|
||||
handle.File.Dispose();
|
||||
return Result.Success;
|
||||
},
|
||||
() => string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Accessors;
|
||||
using LibHac.FsService;
|
||||
|
@ -16,19 +15,23 @@ namespace LibHac.Fs
|
|||
|
||||
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;
|
||||
Time = timer ?? new StopWatchTimeSpanGenerator();
|
||||
}
|
||||
|
||||
public FileSystemClient(FileSystemServer fsServer, ITimeSpanGenerator timer)
|
||||
{
|
||||
FsSrv = fsServer;
|
||||
Time = timer;
|
||||
Time = timer ?? new StopWatchTimeSpanGenerator();
|
||||
}
|
||||
|
||||
public bool HasFileSystemServer()
|
||||
{
|
||||
return FsSrv != null;
|
||||
}
|
||||
|
||||
public IFileSystemProxy GetFileSystemProxyServiceObject()
|
||||
|
@ -39,7 +42,7 @@ namespace LibHac.Fs
|
|||
{
|
||||
if (FsProxy != null) return FsProxy;
|
||||
|
||||
if (FsSrv == null)
|
||||
if (!HasFileSystemServer())
|
||||
{
|
||||
throw new InvalidOperationException("Client was not initialized with a server object.");
|
||||
}
|
||||
|
@ -87,18 +90,6 @@ namespace LibHac.Fs
|
|||
rc.ThrowIfFailure();
|
||||
}
|
||||
|
||||
public void SetAccessLog(bool isEnabled, IAccessLog accessLog = null)
|
||||
{
|
||||
AccessLogEnabled = isEnabled;
|
||||
|
||||
if (isEnabled && FsSrv != null)
|
||||
{
|
||||
SetGlobalAccessLogMode(GlobalAccessLogMode.All);
|
||||
}
|
||||
|
||||
if (accessLog != null) AccessLog = accessLog;
|
||||
}
|
||||
|
||||
internal Result FindFileSystem(ReadOnlySpan<char> path, out FileSystemAccessor fileSystem, out ReadOnlySpan<char> subPath)
|
||||
{
|
||||
fileSystem = default;
|
||||
|
@ -147,45 +138,5 @@ namespace LibHac.Fs
|
|||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace hactoolnet
|
|||
{
|
||||
public void Log(Result result, TimeSpan startTime, TimeSpan endTime, int handleId, string message, [CallerMemberName] string caller = "")
|
||||
{
|
||||
Console.WriteLine(CommonAccessLog.BuildLogLine(result, startTime, endTime, handleId, message, caller));
|
||||
Console.WriteLine(AccessLogHelpers.BuildDefaultLogLine(result, startTime, endTime, handleId, message, caller));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ namespace hactoolnet
|
|||
|
||||
public void Log(Result result, TimeSpan startTime, TimeSpan endTime, int handleId, string message, [CallerMemberName] string caller = "")
|
||||
{
|
||||
Logger.LogMessage(CommonAccessLog.BuildLogLine(result, startTime, endTime, handleId, message, caller));
|
||||
Logger.LogMessage(AccessLogHelpers.BuildDefaultLogLine(result, startTime, endTime, handleId, message, caller));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,16 +39,7 @@ namespace hactoolnet
|
|||
|
||||
public void Log(Result result, TimeSpan startTime, TimeSpan endTime, int handleId, string message, [CallerMemberName] string caller = "")
|
||||
{
|
||||
Logger.WriteLine(CommonAccessLog.BuildLogLine(result, startTime, endTime, handleId, message, caller));
|
||||
}
|
||||
}
|
||||
|
||||
public static class CommonAccessLog
|
||||
{
|
||||
public static string BuildLogLine(Result result, TimeSpan startTime, TimeSpan endTime, int handleId, string message,
|
||||
string caller)
|
||||
{
|
||||
return $"FS_ACCESS: {{ start: {(long)startTime.TotalMilliseconds,9}, end: {(long)endTime.TotalMilliseconds,9}, result: 0x{result.Value:x8}, handle: 0x{handleId:x8}, function: \"{caller}\"{message} }}";
|
||||
Logger.WriteLine(AccessLogHelpers.BuildDefaultLogLine(result, startTime, endTime, handleId, message, caller));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,8 +48,8 @@ namespace hactoolnet
|
|||
|
||||
string mountName = $"section{i}";
|
||||
|
||||
fs.Register(mountName.AsU8Span(), OpenFileSystem(i));
|
||||
fs.Register("output".AsU8Span(), new LocalFileSystem(ctx.Options.SectionOutDir[i]));
|
||||
fs.Register(mountName.ToU8Span(), OpenFileSystem(i));
|
||||
fs.Register("output".ToU8Span(), new LocalFileSystem(ctx.Options.SectionOutDir[i]));
|
||||
|
||||
FsUtils.CopyDirectoryWithProgress(fs, mountName + ":/", "output:/", logger: ctx.Logger);
|
||||
|
||||
|
@ -97,8 +97,8 @@ namespace hactoolnet
|
|||
{
|
||||
FileSystemClient fs = ctx.Horizon.Fs;
|
||||
|
||||
fs.Register("rom".AsU8Span(), OpenFileSystemByType(NcaSectionType.Data));
|
||||
fs.Register("output".AsU8Span(), new LocalFileSystem(ctx.Options.RomfsOutDir));
|
||||
fs.Register("rom".ToU8Span(), OpenFileSystemByType(NcaSectionType.Data));
|
||||
fs.Register("output".ToU8Span(), new LocalFileSystem(ctx.Options.RomfsOutDir));
|
||||
|
||||
FsUtils.CopyDirectoryWithProgress(fs, "rom:/", "output:/", logger: ctx.Logger);
|
||||
|
||||
|
@ -154,8 +154,8 @@ namespace hactoolnet
|
|||
{
|
||||
FileSystemClient fs = ctx.Horizon.Fs;
|
||||
|
||||
fs.Register("code".AsU8Span(), OpenFileSystemByType(NcaSectionType.Code));
|
||||
fs.Register("output".AsU8Span(), new LocalFileSystem(ctx.Options.ExefsOutDir));
|
||||
fs.Register("code".ToU8Span(), OpenFileSystemByType(NcaSectionType.Code));
|
||||
fs.Register("output".ToU8Span(), new LocalFileSystem(ctx.Options.ExefsOutDir));
|
||||
|
||||
FsUtils.CopyDirectoryWithProgress(fs, "code:/", "output:/", logger: ctx.Logger);
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace hactoolnet
|
|||
var save = new SaveDataFileSystem(ctx.Keyset, file, ctx.Options.IntegrityLevel, true);
|
||||
FileSystemClient fs = ctx.Horizon.Fs;
|
||||
|
||||
fs.Register("save".AsU8Span(), save);
|
||||
fs.Register("save".ToU8Span(), save);
|
||||
|
||||
if (ctx.Options.Validate)
|
||||
{
|
||||
|
@ -40,7 +40,7 @@ namespace hactoolnet
|
|||
|
||||
if (ctx.Options.OutDir != null)
|
||||
{
|
||||
fs.Register("output".AsU8Span(), new LocalFileSystem(ctx.Options.OutDir));
|
||||
fs.Register("output".ToU8Span(), new LocalFileSystem(ctx.Options.OutDir));
|
||||
|
||||
FsUtils.CopyDirectoryWithProgress(fs, "save:/", "output:/", logger: ctx.Logger);
|
||||
|
||||
|
@ -86,7 +86,7 @@ namespace hactoolnet
|
|||
|
||||
if (ctx.Options.RepackSource != null)
|
||||
{
|
||||
fs.Register("input".AsU8Span(), new LocalFileSystem(ctx.Options.RepackSource));
|
||||
fs.Register("input".ToU8Span(), new LocalFileSystem(ctx.Options.RepackSource));
|
||||
|
||||
fs.CleanDirectoryRecursively("save:/");
|
||||
fs.Commit("save");
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using System.IO;
|
||||
using System.Text;
|
||||
using LibHac;
|
||||
using LibHac.Fs;
|
||||
|
||||
namespace hactoolnet
|
||||
{
|
||||
|
@ -63,7 +64,11 @@ namespace hactoolnet
|
|||
{
|
||||
logWriter = new StreamWriter(ctx.Options.AccessLog);
|
||||
var accessLog = new TextWriterAccessLog(logWriter);
|
||||
ctx.Horizon.Fs.SetAccessLog(true, accessLog);
|
||||
|
||||
ctx.Horizon.Fs.SetLocalAccessLogMode(LocalAccessLogMode.All);
|
||||
ctx.Horizon.Fs.SetGlobalAccessLogMode(GlobalAccessLogMode.Log);
|
||||
|
||||
ctx.Horizon.Fs.SetAccessLogObject(accessLog);
|
||||
}
|
||||
|
||||
OpenKeyset(ctx);
|
||||
|
|
Loading…
Reference in a new issue