From 0a96e8d623173c4bedfb19c8653c29e0891d4ada Mon Sep 17 00:00:00 2001 From: Alex Barney Date: Fri, 1 Apr 2022 17:32:38 -0700 Subject: [PATCH] Fix EnsureApplicationSaveData failing if the temp save already exists --- .../Fs/ApplicationSaveDataManagement.cs | 15 ++- .../ApplicationSaveDataManagementTests.cs | 117 ++++++++++++------ .../ShimTests/SaveDataManagement.cs | 31 +++++ 3 files changed, 122 insertions(+), 41 deletions(-) diff --git a/src/LibHac/Fs/ApplicationSaveDataManagement.cs b/src/LibHac/Fs/ApplicationSaveDataManagement.cs index 908b73f8..bb0dcb2d 100644 --- a/src/LibHac/Fs/ApplicationSaveDataManagement.cs +++ b/src/LibHac/Fs/ApplicationSaveDataManagement.cs @@ -677,6 +677,7 @@ public static class ApplicationSaveDataManagement if (ResultFs.PathAlreadyExists.Includes(rc)) { // Nothing to do if the save already exists. + rc.Catch().Handle(); } else if (ResultFs.UsableSpaceNotEnough.Includes(rc)) { @@ -686,6 +687,7 @@ public static class ApplicationSaveDataManagement } else { + fs.Impl.AbortIfNeeded(rc); return rc.Miss(); } } @@ -706,6 +708,7 @@ public static class ApplicationSaveDataManagement } else { + fs.Impl.AbortIfNeeded(rc); return rc.Miss(); } } @@ -742,8 +745,14 @@ public static class ApplicationSaveDataManagement requiredSize += temporaryStorageSize; } + else if (ResultFs.PathAlreadyExists.Includes(rc)) + { + // Nothing to do if the save already exists. + rc.Catch().Handle(); + } else { + fs.Impl.AbortIfNeeded(rc); return rc.Miss(); } } @@ -776,6 +785,7 @@ public static class ApplicationSaveDataManagement } else { + fs.Impl.AbortIfNeeded(rc); return rc.Miss(); } } @@ -789,7 +799,10 @@ public static class ApplicationSaveDataManagement } outRequiredSize = requiredSize; - return ResultFs.UsableSpaceNotEnough.Log(); + + rc = ResultFs.UsableSpaceNotEnough.Log(); + fs.Impl.AbortIfNeeded(rc); + return rc; } public static Result ExtendApplicationSaveData(this FileSystemClient fs, out long outRequiredSize, diff --git a/tests/LibHac.Tests/Fs/FileSystemClientTests/ApplicationSaveDataManagementTests.cs b/tests/LibHac.Tests/Fs/FileSystemClientTests/ApplicationSaveDataManagementTests.cs index 455b8dd1..4ddd3faf 100644 --- a/tests/LibHac.Tests/Fs/FileSystemClientTests/ApplicationSaveDataManagementTests.cs +++ b/tests/LibHac.Tests/Fs/FileSystemClientTests/ApplicationSaveDataManagementTests.cs @@ -26,17 +26,25 @@ public class ApplicationSaveDataManagementTests }; Assert.Success(fs.EnsureApplicationSaveData(out _, applicationId, in controlProperty, in userId)); + AssertSaveExists(); - using var iterator = new UniqueRef(); - fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User); + // EnsureApplicationSaveData should do nothing the second time it is called + Assert.Success(fs.EnsureApplicationSaveData(out _, applicationId, in controlProperty, in userId)); + AssertSaveExists(); - var info = new SaveDataInfo[2]; - Assert.Success(iterator.Get.ReadSaveDataInfo(out long entriesRead, info)); + void AssertSaveExists() + { + using var iterator = new UniqueRef(); + fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User); - Assert.Equal(1, entriesRead); - Assert.Equal(applicationId, info[0].ProgramId); - Assert.Equal(Utility.ConvertAccountUidToFsUserId(userId), info[0].UserId); - Assert.Equal(SaveDataType.Account, info[0].Type); + var info = new SaveDataInfo[2]; + Assert.Success(iterator.Get.ReadSaveDataInfo(out long entriesRead, info)); + + Assert.Equal(1, entriesRead); + Assert.Equal(applicationId, info[0].ProgramId); + Assert.Equal(Utility.ConvertAccountUidToFsUserId(userId), info[0].UserId); + Assert.Equal(SaveDataType.Account, info[0].Type); + } } [Fact] @@ -54,17 +62,24 @@ public class ApplicationSaveDataManagementTests }; Assert.Success(fs.EnsureApplicationSaveData(out _, applicationId, in controlProperty, in userId)); + AssertSaveExists(); - using var iterator = new UniqueRef(); - fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User); + Assert.Success(fs.EnsureApplicationSaveData(out _, applicationId, in controlProperty, in userId)); + AssertSaveExists(); - var info = new SaveDataInfo[2]; - Assert.Success(iterator.Get.ReadSaveDataInfo(out long entriesRead, info)); + void AssertSaveExists() + { + using var iterator = new UniqueRef(); + fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User); - Assert.Equal(1, entriesRead); - Assert.Equal(applicationId, info[0].ProgramId); - Assert.Equal(InvalidUserId, info[0].UserId); - Assert.Equal(SaveDataType.Device, info[0].Type); + var info = new SaveDataInfo[2]; + Assert.Success(iterator.Get.ReadSaveDataInfo(out long entriesRead, info)); + + Assert.Equal(1, entriesRead); + Assert.Equal(applicationId, info[0].ProgramId); + Assert.Equal(InvalidUserId, info[0].UserId); + Assert.Equal(SaveDataType.Device, info[0].Type); + } } [Fact] @@ -81,17 +96,24 @@ public class ApplicationSaveDataManagementTests }; Assert.Success(fs.EnsureApplicationSaveData(out _, applicationId, in controlProperty, in userId)); + AssertSaveExists(); - using var iterator = new UniqueRef(); - fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User); + Assert.Success(fs.EnsureApplicationSaveData(out _, applicationId, in controlProperty, in userId)); + AssertSaveExists(); - var info = new SaveDataInfo[2]; - Assert.Success(iterator.Get.ReadSaveDataInfo(out long entriesRead, info)); + void AssertSaveExists() + { + using var iterator = new UniqueRef(); + fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User); - Assert.Equal(1, entriesRead); - Assert.Equal(applicationId, info[0].ProgramId); - Assert.Equal(InvalidUserId, info[0].UserId); - Assert.Equal(SaveDataType.Bcat, info[0].Type); + var info = new SaveDataInfo[2]; + Assert.Success(iterator.Get.ReadSaveDataInfo(out long entriesRead, info)); + + Assert.Equal(1, entriesRead); + Assert.Equal(applicationId, info[0].ProgramId); + Assert.Equal(InvalidUserId, info[0].UserId); + Assert.Equal(SaveDataType.Bcat, info[0].Type); + } } [Fact] @@ -108,18 +130,26 @@ public class ApplicationSaveDataManagementTests }; Assert.Success(fs.EnsureApplicationSaveData(out _, applicationId, in controlProperty, in userId)); + AssertSaveExists(); - using var iterator = new UniqueRef(); - fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.Temporary); + Assert.Success(fs.EnsureApplicationSaveData(out _, applicationId, in controlProperty, in userId)); + AssertSaveExists(); - var info = new SaveDataInfo[2]; - Assert.Success(iterator.Get.ReadSaveDataInfo(out long entriesRead, info)); + void AssertSaveExists() + { + using var iterator = new UniqueRef(); + fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.Temporary); - Assert.Equal(1, entriesRead); - Assert.Equal(applicationId, info[0].ProgramId); - Assert.Equal(InvalidUserId, info[0].UserId); - Assert.Equal(SaveDataType.Temporary, info[0].Type); + var info = new SaveDataInfo[2]; + Assert.Success(iterator.Get.ReadSaveDataInfo(out long entriesRead, info)); + + Assert.Equal(1, entriesRead); + Assert.Equal(applicationId, info[0].ProgramId); + Assert.Equal(InvalidUserId, info[0].UserId); + Assert.Equal(SaveDataType.Temporary, info[0].Type); + } } + [Fact] public static void EnsureApplicationSaveData_NeedsExtension_IsExtended() { @@ -180,18 +210,25 @@ public class ApplicationSaveDataManagementTests Assert.Success(fs.EnsureApplicationCacheStorage(out _, out CacheStorageTargetMedia target, applicationId, in controlProperty)); + AssertSaveExists(); - Assert.Equal(CacheStorageTargetMedia.SdCard, target); + Assert.Success(fs.EnsureApplicationCacheStorage(out _, out target, applicationId, in controlProperty)); + AssertSaveExists(); - using var iterator = new UniqueRef(); - fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.SdUser); + void AssertSaveExists() + { + Assert.Equal(CacheStorageTargetMedia.SdCard, target); - var info = new SaveDataInfo[2]; - Assert.Success(iterator.Get.ReadSaveDataInfo(out long entriesRead, info)); + using var iterator = new UniqueRef(); + fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.SdUser); - Assert.Equal(1, entriesRead); - Assert.Equal(applicationId, info[0].ProgramId); - Assert.Equal(SaveDataType.Cache, info[0].Type); + var info = new SaveDataInfo[2]; + Assert.Success(iterator.Get.ReadSaveDataInfo(out long entriesRead, info)); + + Assert.Equal(1, entriesRead); + Assert.Equal(applicationId, info[0].ProgramId); + Assert.Equal(SaveDataType.Cache, info[0].Type); + } } [Fact] diff --git a/tests/LibHac.Tests/Fs/FileSystemClientTests/ShimTests/SaveDataManagement.cs b/tests/LibHac.Tests/Fs/FileSystemClientTests/ShimTests/SaveDataManagement.cs index f4c2512a..2b8af33a 100644 --- a/tests/LibHac.Tests/Fs/FileSystemClientTests/ShimTests/SaveDataManagement.cs +++ b/tests/LibHac.Tests/Fs/FileSystemClientTests/ShimTests/SaveDataManagement.cs @@ -339,6 +339,37 @@ public class SaveDataManagement Assert.Equal(mainProgramId, info[0].ProgramId); } + [Fact] + public void CreateTemporaryStorage_DoesNotExist_SaveIsCreated() + { + long availableSize = 0x220000; + + var applicationId = new Ncm.ApplicationId(1); + FileSystemClient fs = FileSystemServerFactory.CreateClient(true); + + Assert.Success(fs.CreateTemporaryStorage(applicationId, 0, availableSize, SaveDataFlags.None)); + + using var iterator = new UniqueRef(); + fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.Temporary); + + var info = new SaveDataInfo[2]; + iterator.Get.ReadSaveDataInfo(out long entriesRead, info); + + Assert.Equal(1, entriesRead); + Assert.Equal(applicationId, info[0].ProgramId); + Assert.Equal(SaveDataType.Temporary, info[0].Type); + } + + [Fact] + public void CreateTemporaryStorage_AlreadyExists_ReturnsPathAlreadyExists() + { + var applicationId = new Ncm.ApplicationId(1); + FileSystemClient fs = FileSystemServerFactory.CreateClient(true); + + Assert.Success(fs.CreateTemporaryStorage(applicationId, 0, 0x400000, SaveDataFlags.None)); + Assert.Result(ResultFs.PathAlreadyExists, fs.CreateTemporaryStorage(applicationId, 0, 0x400000, SaveDataFlags.None)); + } + [Fact] public void DeleteSaveData_DoesNotExist_ReturnsTargetNotFound() {