Implement all of AccessLogService

This commit is contained in:
Alex Barney 2024-07-02 20:33:18 -07:00
parent d0c96e7b8e
commit 86fa140865
3 changed files with 109 additions and 32 deletions

View file

@ -1,15 +1,34 @@
using System;
using LibHac.Common;
using LibHac.Fs;
using LibHac.FsSrv.Impl;
using LibHac.Sf;
using static LibHac.FsSrv.Anonymous;
namespace LibHac.FsSrv;
file static class Anonymous
{
public static Result GetProgramInfo(FileSystemServer fsServer, out ProgramInfo programInfo, ulong processId)
{
var programRegistry = new ProgramRegistryImpl(fsServer);
return programRegistry.GetProgramInfo(out programInfo, processId).Ret();
}
}
/// <summary>
/// Handles access log calls for <see cref="FileSystemProxyImpl"/>.
/// </summary>
/// <remarks><para>This struct handles checking a process' permissions before forwarding
/// requests to the <see cref="AccessLogServiceImpl"/> object.</para>
/// <para>Based on nnSdk 18.3.0 (FS 18.0.0)</para></remarks>
internal readonly struct AccessLogService
{
private readonly AccessLogServiceImpl _serviceImpl;
private readonly ulong _processId;
private FileSystemServer FsServer => _serviceImpl.FsServer;
public AccessLogService(AccessLogServiceImpl serviceImpl, ulong processId)
{
_serviceImpl = serviceImpl;
@ -18,7 +37,7 @@ internal readonly struct AccessLogService
public Result SetAccessLogMode(GlobalAccessLogMode mode)
{
Result res = GetProgramInfo(out ProgramInfo programInfo);
Result res = GetProgramInfo(FsServer, out ProgramInfo programInfo, _processId);
if (res.IsFailure()) return res.Miss();
if (!programInfo.AccessControl.CanCall(OperationType.SetGlobalAccessLogMode))
@ -36,15 +55,46 @@ internal readonly struct AccessLogService
public Result OutputAccessLogToSdCard(InBuffer textBuffer)
{
Result res = GetProgramInfo(out ProgramInfo programInfo);
Result res = GetProgramInfo(FsServer, out ProgramInfo programInfo, _processId);
if (res.IsFailure()) return res.Miss();
return _serviceImpl.OutputAccessLogToSdCard(textBuffer.Buffer, programInfo.ProgramIdValue, _processId);
return _serviceImpl.OutputAccessLogToSdCard(textBuffer.Buffer, programInfo.ProgramIdValue, _processId).Ret();
}
private static ReadOnlySpan<byte> OutputAccessLog => "FS_ACCESS: { multi_program_tag: true }\n"u8;
private static ReadOnlySpan<byte> OutputLogTagUnknown => "FS_ACCESS: { application_info_tag: { launch_type: Unknown } }\n"u8;
private static ReadOnlySpan<byte> OutputHead => "FS_ACCESS: { application_info_tag: { launch_type: "u8;
private static ReadOnlySpan<byte> OutputApplicationId => "Application, application_id: 0x"u8;
private static ReadOnlySpan<byte> OutputPatchId => "Patch, application_id: 0x"u8;
private static ReadOnlySpan<byte> OutputVersion => ", release_version: 0x"u8;
private static ReadOnlySpan<byte> OutputTail => " } }\n"u8;
public Result OutputApplicationInfoAccessLog(in ApplicationInfo applicationInfo)
{
throw new NotImplementedException();
if (applicationInfo.IsMultiProgram)
{
_serviceImpl.OutputAccessLogToSdCard(OutputAccessLog, applicationInfo.ApplicationId.Value, _processId).IgnoreResult();
}
if (applicationInfo.LaunchType == 0)
{
_serviceImpl.OutputAccessLogToSdCard(OutputLogTagUnknown, applicationInfo.ApplicationId.Value, _processId).IgnoreResult();
}
else
{
Span<byte> buffer = stackalloc byte[0x80];
ReadOnlySpan<byte> outputId = applicationInfo.LaunchType == 1 ? OutputApplicationId : OutputPatchId;
var sb = new U8StringBuilder(buffer, autoExpand: true);
sb.Append(OutputHead)
.Append(outputId).AppendFormat(applicationInfo.ApplicationId.Value, 'X', 16)
.Append(OutputVersion).AppendFormat(applicationInfo.Version >> 16, 'X', 4)
.Append(OutputTail);
_serviceImpl.OutputAccessLogToSdCard(sb.Buffer, applicationInfo.ApplicationId.Value, _processId);
}
return Result.Success;
}
public Result OutputMultiProgramTagAccessLog()
@ -55,12 +105,8 @@ internal readonly struct AccessLogService
public Result FlushAccessLogOnSdCard()
{
throw new NotImplementedException();
}
private Result GetProgramInfo(out ProgramInfo programInfo)
{
return _serviceImpl.GetProgramInfo(out programInfo, _processId);
_serviceImpl.FlushAccessLogSdCardWriter();
return Result.Success;
}
/// <summary>"<c>FS_ACCESS: { multi_program_tag: true }\n</c>"</summary>

View file

@ -1,34 +1,56 @@
using System;
using LibHac.Diag;
using LibHac.Fs;
using LibHac.FsSrv.Impl;
using LibHac.Os;
using Utility = LibHac.FsSrv.Impl.Utility;
namespace LibHac.FsSrv;
/// <summary>
/// Writes to the FS access log file on the SD card, filtering messages based on the current global log mode
/// and the sending program's ID.
/// </summary>
/// <remarks>Based on nnSdk 18.3.0 (FS 18.0.0)</remarks>
public class AccessLogServiceImpl : IDisposable
{
private Configuration _config;
private GlobalAccessLogMode _accessLogMode;
private AccessLogSdCardWriter _sdCardWriter;
private SdkMutexType _mutex;
public AccessLogServiceImpl(in Configuration configuration)
{
_config = configuration;
}
public void Dispose()
{
}
public FileSystemServer FsServer => _config.FsServer;
public struct Configuration
{
public ulong MinimumProgramIdForSdCardLog;
public ulong ProgramIdWithoutPlatformIdMinForAccessLog;
// LibHac additions
public FileSystemServer FsServer;
}
public AccessLogServiceImpl(in Configuration configuration)
{
_config = configuration;
_accessLogMode = GlobalAccessLogMode.None;
_sdCardWriter = new AccessLogSdCardWriter(configuration.FsServer.Hos.Fs);
_mutex = new SdkMutexType();
}
public void Dispose()
{
_sdCardWriter.Dispose();
}
public void SetAccessLogMode(GlobalAccessLogMode mode)
{
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
if (_accessLogMode.HasFlag(GlobalAccessLogMode.SdCard) && !mode.HasFlag(GlobalAccessLogMode.SdCard))
{
_sdCardWriter.Flush();
}
_accessLogMode = mode;
}
@ -44,22 +66,31 @@ public class AccessLogServiceImpl : IDisposable
public Result OutputAccessLogToSdCard(ReadOnlySpan<byte> text, ulong programId, ulong processId)
{
throw new NotImplementedException();
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
if (!_accessLogMode.HasFlag(GlobalAccessLogMode.SdCard))
return Result.Success;
Assert.SdkRequiresNotEqual(_config.ProgramIdWithoutPlatformIdMinForAccessLog, 0ul);
if (Utility.ClearPlatformIdInProgramId(processId) >= _config.ProgramIdWithoutPlatformIdMinForAccessLog)
{
_sdCardWriter.AppendLog(text, programId);
}
return Result.Success;
}
public Result FlushAccessLogSdCardWriter()
public void FlushAccessLogSdCardWriter()
{
throw new NotImplementedException();
if (_accessLogMode.HasFlag(GlobalAccessLogMode.SdCard))
{
_sdCardWriter.Flush();
}
}
public Result FinalizeAccessLogSdCardWriter()
public void FinalizeAccessLogSdCardWriter()
{
throw new NotImplementedException();
}
internal Result GetProgramInfo(out ProgramInfo programInfo, ulong processId)
{
var registry = new ProgramRegistryImpl(_config.FsServer);
return registry.GetProgramInfo(out programInfo, processId);
_sdCardWriter.FinalizeObject();
}
}

View file

@ -170,7 +170,7 @@ public static class FileSystemServerInitializer
var statusReportService = new StatusReportServiceImpl(in statusReportServiceConfig);
var accessLogServiceConfig = new AccessLogServiceImpl.Configuration();
accessLogServiceConfig.MinimumProgramIdForSdCardLog = 0x0100000000003000;
accessLogServiceConfig.ProgramIdWithoutPlatformIdMinForAccessLog = 0x3000;
accessLogServiceConfig.FsServer = server;
var accessLogService = new AccessLogServiceImpl(in accessLogServiceConfig);