From e0af248e6f96efe7009915935407fc809eb774a9 Mon Sep 17 00:00:00 2001 From: Alex Barney Date: Fri, 20 Aug 2021 13:36:14 -0700 Subject: [PATCH] Clean the SD card save directory when opening the emulator (#2564) Cleans "sdcard:/Nintendo/save" and deletes "sdcard:/save" when opening the emulator. Works around invalid encryption when keys or the SD card encryption seed are changed. --- .../FileSystem/EncryptedFileSystemCreator.cs | 35 +------------------ Ryujinx.HLE/HOS/LibHacHorizonManager.cs | 26 ++++++++++++++ 2 files changed, 27 insertions(+), 34 deletions(-) diff --git a/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs b/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs index aaa80044..f8e59fb5 100644 --- a/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs +++ b/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs @@ -9,8 +9,6 @@ namespace Ryujinx.HLE.FileSystem { public class EncryptedFileSystemCreator : IEncryptedFileSystemCreator { - public EncryptedFileSystemCreator() { } - public Result Create(out ReferenceCountedDisposable encryptedFileSystem, ReferenceCountedDisposable baseFileSystem, EncryptedFsKeyId keyId, in EncryptionSeed encryptionSeed) { @@ -23,40 +21,9 @@ namespace Ryujinx.HLE.FileSystem // Force all-zero keys for now since people can open the emulator with different keys or sd seeds sometimes var fs = new AesXtsFileSystem(baseFileSystem, new byte[0x32], 0x4000); - var aesFileSystem = new ReferenceCountedDisposable(fs); - - // This wrapper will handle deleting files that were created with different keys - var wrappedFs = new ChangedEncryptionHandlingFileSystem(aesFileSystem); - encryptedFileSystem = new ReferenceCountedDisposable(wrappedFs); + encryptedFileSystem = new ReferenceCountedDisposable(fs); return Result.Success; } } - - public class ChangedEncryptionHandlingFileSystem : ForwardingFileSystem - { - public ChangedEncryptionHandlingFileSystem(ReferenceCountedDisposable baseFileSystem) : base(baseFileSystem) { } - - protected override Result DoOpenFile(out IFile file, U8Span path, OpenMode mode) - { - UnsafeHelpers.SkipParamInit(out file); - - try - { - return base.DoOpenFile(out file, path, mode); - } - catch (HorizonResultException ex) - { - if (ResultFs.AesXtsFileHeaderInvalidKeys.Includes(ex.ResultValue)) - { - Result rc = DeleteFile(path); - if (rc.IsFailure()) return rc; - - return base.DoOpenFile(out file, path, mode); - } - - throw; - } - } - } } diff --git a/Ryujinx.HLE/HOS/LibHacHorizonManager.cs b/Ryujinx.HLE/HOS/LibHacHorizonManager.cs index 48077aa8..61e0227f 100644 --- a/Ryujinx.HLE/HOS/LibHacHorizonManager.cs +++ b/Ryujinx.HLE/HOS/LibHacHorizonManager.cs @@ -1,5 +1,8 @@ using LibHac; using LibHac.Bcat; +using LibHac.Common; +using LibHac.Fs.Fsa; +using LibHac.Fs.Shim; using LibHac.FsSrv.Impl; using LibHac.Loader; using LibHac.Ncm; @@ -57,6 +60,8 @@ namespace Ryujinx.HLE.HOS virtualFileSystem.InitializeFsServer(Server, out var fsClient); FsClient = fsClient; + + CleanSdCardDirectory(); } public void InitializeSystemClients() @@ -80,6 +85,27 @@ namespace Ryujinx.HLE.HOS npdm.FsAccessControlData, npdm.FsAccessControlDescriptor); } + // This function was added to avoid errors that come from a user's keys or SD encryption seed changing. + // Catching these errors and recreating the file ended up not working because of the different ways + // applications respond to a file suddenly containing all zeros or having a length of zero. + // Clearing the SD card save directory was determined to be the best option for the moment since + // the saves on the SD card are meant as caches that can be deleted at any time. + private void CleanSdCardDirectory() + { + Result rc = RyujinxClient.Fs.MountSdCard("sdcard".ToU8Span()); + if (rc.IsFailure()) return; + + try + { + RyujinxClient.Fs.CleanDirectoryRecursively("sdcard:/Nintendo/save".ToU8Span()).IgnoreResult(); + RyujinxClient.Fs.DeleteDirectoryRecursively("sdcard:/save".ToU8Span()).IgnoreResult(); + } + finally + { + RyujinxClient.Fs.Unmount("sdcard".ToU8Span()); + } + } + private static AccessControlBits.Bits AccountFsPermissions => AccessControlBits.Bits.SystemSaveData | AccessControlBits.Bits.GameCard | AccessControlBits.Bits.SaveDataMeta |