From b3dc972881276f0a3cec34e19fa6a79190b3dcc4 Mon Sep 17 00:00:00 2001 From: Alex Barney Date: Tue, 15 Jun 2021 01:28:49 -0700 Subject: [PATCH] Allow FS access log to be used without a backing FS server Reduces the hactoolnet build size by ~260 KB due to fssrv code no longer being used --- src/LibHac/Fs/AccessLog.cs | 26 +++++++++++++++++++ src/LibHac/FsSystem/StorageExtensions.cs | 3 ++- .../Os/Impl/ReaderWriterLockImpl-os.net.cs | 2 +- src/hactoolnet/ProcessNca.cs | 6 +++++ src/hactoolnet/ProcessSave.cs | 4 +++ src/hactoolnet/Program.cs | 12 ++++++--- 6 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/LibHac/Fs/AccessLog.cs b/src/LibHac/Fs/AccessLog.cs index 41c3d37d..8d3a21ee 100644 --- a/src/LibHac/Fs/AccessLog.cs +++ b/src/LibHac/Fs/AccessLog.cs @@ -22,6 +22,7 @@ namespace LibHac.Fs public GlobalAccessLogMode GlobalAccessLogMode; public AccessLogTarget LocalAccessLogTarget; + public bool IsServerless; public bool IsAccessLogInitialized; public SdkMutexType MutexForAccessLogInitialization; @@ -55,6 +56,13 @@ namespace LibHac.Fs { public static Result GetGlobalAccessLogMode(this FileSystemClient fs, out GlobalAccessLogMode mode) { + // Allow the access log to be used without an FS server by storing the mode locally in that situation. + if (fs.Globals.AccessLog.IsServerless) + { + mode = fs.Globals.AccessLog.GlobalAccessLogMode; + return Result.Success; + } + using ReferenceCountedDisposable fsProxy = fs.Impl.GetFileSystemProxyServiceObject(); Result rc = fsProxy.Target.GetGlobalAccessLogMode(out mode); @@ -64,6 +72,13 @@ namespace LibHac.Fs public static Result SetGlobalAccessLogMode(this FileSystemClient fs, GlobalAccessLogMode mode) { + // Allow the access log to be used without an FS server by storing the mode locally in that situation. + if (fs.Globals.AccessLog.IsServerless) + { + fs.Globals.AccessLog.GlobalAccessLogMode = mode; + return Result.Success; + } + using ReferenceCountedDisposable fsProxy = fs.Impl.GetFileSystemProxyServiceObject(); Result rc = fsProxy.Target.SetGlobalAccessLogMode(mode); @@ -93,6 +108,17 @@ namespace LibHac.Fs } } + /// + /// Sets whether the FS access log should call the FS service when getting or setting the + /// global access log mode. This allows the access log to be used when using an FS client without a server. + /// + /// The to use. + /// Does this client lack an FS server? + public static void SetServerlessAccessLog(this FileSystemClient fs, bool isServerless) + { + fs.Globals.AccessLog.IsServerless = isServerless; + } + private static void SetLocalAccessLogImpl(FileSystemClient fs, bool enabled) { if (enabled) diff --git a/src/LibHac/FsSystem/StorageExtensions.cs b/src/LibHac/FsSystem/StorageExtensions.cs index 0c0d5948..969bfe3a 100644 --- a/src/LibHac/FsSystem/StorageExtensions.cs +++ b/src/LibHac/FsSystem/StorageExtensions.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using LibHac.Common; using LibHac.Fs; @@ -181,7 +182,7 @@ namespace LibHac.FsSystem storage.GetSize(out long storageSize).ThrowIfFailure(); - var arr = new T[storageSize / Marshal.SizeOf()]; + var arr = new T[storageSize / Unsafe.SizeOf()]; Span dest = MemoryMarshal.Cast(arr.AsSpan()); storage.Read(0, dest); diff --git a/src/LibHac/Os/Impl/ReaderWriterLockImpl-os.net.cs b/src/LibHac/Os/Impl/ReaderWriterLockImpl-os.net.cs index 1c0c9f67..1f39bd2a 100644 --- a/src/LibHac/Os/Impl/ReaderWriterLockImpl-os.net.cs +++ b/src/LibHac/Os/Impl/ReaderWriterLockImpl-os.net.cs @@ -181,7 +181,7 @@ namespace LibHac.Os.Impl { using ScopedLock lk = ScopedLock.Lock(ref GetLockCount(ref rwLock).Cs); - Assert.SdkEqual(GetWriteLockCount(in rwLock), 0u); + Assert.SdkRequiresGreater(GetWriteLockCount(in rwLock), 0u); Assert.SdkNotEqual(GetWriteLocked(in GetLockCount(ref rwLock)), 0u); Assert.SdkEqual(rwLock.OwnerThread, Environment.CurrentManagedThreadId); diff --git a/src/hactoolnet/ProcessNca.cs b/src/hactoolnet/ProcessNca.cs index 5b3e82a2..ffb3c784 100644 --- a/src/hactoolnet/ProcessNca.cs +++ b/src/hactoolnet/ProcessNca.cs @@ -53,6 +53,9 @@ namespace hactoolnet fs.Register(mountName.ToU8Span(), OpenFileSystem(i)); fs.Register("output".ToU8Span(), new LocalFileSystem(ctx.Options.SectionOutDir[i])); + fs.Impl.EnableFileSystemAccessorAccessLog(mountName.ToU8Span()); + fs.Impl.EnableFileSystemAccessorAccessLog("output".ToU8Span()); + FsUtils.CopyDirectoryWithProgress(fs, (mountName + ":/").ToU8Span(), "output:/".ToU8Span(), logger: ctx.Logger).ThrowIfFailure(); fs.Unmount(mountName.ToU8Span()); @@ -162,6 +165,9 @@ namespace hactoolnet fs.Register("code".ToU8Span(), OpenFileSystemByType(NcaSectionType.Code)); fs.Register("output".ToU8Span(), new LocalFileSystem(ctx.Options.ExefsOutDir)); + fs.Impl.EnableFileSystemAccessorAccessLog("code".ToU8Span()); + fs.Impl.EnableFileSystemAccessorAccessLog("output".ToU8Span()); + FsUtils.CopyDirectoryWithProgress(fs, "code:/".ToU8Span(), "output:/".ToU8Span(), logger: ctx.Logger).ThrowIfFailure(); fs.Unmount("code".ToU8Span()); diff --git a/src/hactoolnet/ProcessSave.cs b/src/hactoolnet/ProcessSave.cs index 6ef580ac..20bd8355 100644 --- a/src/hactoolnet/ProcessSave.cs +++ b/src/hactoolnet/ProcessSave.cs @@ -8,6 +8,7 @@ using LibHac.Common; using LibHac.Common.Keys; using LibHac.Fs; using LibHac.Fs.Fsa; +using LibHac.Fs.Impl; using LibHac.FsSystem; using LibHac.FsSystem.Save; using static hactoolnet.Print; @@ -34,6 +35,7 @@ namespace hactoolnet FileSystemClient fs = ctx.Horizon.Fs; fs.Register("save".ToU8Span(), save); + fs.Impl.EnableFileSystemAccessorAccessLog("save".ToU8Span()); if (ctx.Options.Validate) { @@ -43,6 +45,7 @@ namespace hactoolnet if (ctx.Options.OutDir != null) { fs.Register("output".ToU8Span(), new LocalFileSystem(ctx.Options.OutDir)); + fs.Impl.EnableFileSystemAccessorAccessLog("output".ToU8Span()); FsUtils.CopyDirectoryWithProgress(fs, "save:/".ToU8Span(), "output:/".ToU8Span(), logger: ctx.Logger).ThrowIfFailure(); @@ -89,6 +92,7 @@ namespace hactoolnet if (ctx.Options.RepackSource != null) { fs.Register("input".ToU8Span(), new LocalFileSystem(ctx.Options.RepackSource)); + fs.Impl.EnableFileSystemAccessorAccessLog("input".ToU8Span()); fs.CleanDirectoryRecursively("save:/".ToU8Span()); fs.Commit("save".ToU8Span()); diff --git a/src/hactoolnet/Program.cs b/src/hactoolnet/Program.cs index 4679700d..54c3d765 100644 --- a/src/hactoolnet/Program.cs +++ b/src/hactoolnet/Program.cs @@ -70,10 +70,7 @@ namespace hactoolnet { ctx.Logger = logger; OpenKeySet(ctx); - - Horizon horizon = HorizonFactory.CreateWithDefaultFsConfig(new HorizonConfiguration(), - new InMemoryFileSystem(), ctx.KeySet); - ctx.Horizon = horizon.CreatePrivilegedHorizonClient(); + InitializeHorizon(ctx); if (ctx.Options.AccessLog != null) { @@ -247,6 +244,13 @@ namespace hactoolnet ctx.KeySet = keySet; } + private static void InitializeHorizon(Context ctx) + { + var horizon = new Horizon(new HorizonConfiguration()); + ctx.Horizon = horizon.CreatePrivilegedHorizonClient(); + ctx.Horizon.Fs.SetServerlessAccessLog(true); + } + private static void ProcessKeygen(Context ctx) { Console.WriteLine(ExternalKeyWriter.PrintAllKeys(ctx.KeySet));