From bbc86313573054e2b600aec8c0e785999003bf4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Thu, 30 Jan 2020 18:07:03 +0100 Subject: [PATCH] IOS/FS: Fix CreateFullPath to not create directories that already exist This fixes CreateFullPath to not create directories when it is known that they already exist, instead of calling CreateDirectory anyway and checking if the error is AlreadyExists. (That doesn't work now that we have an accurate implementation of CreateDirectory that performs permission checks before checking for existence.) I'm not sure what I was thinking when I wrote that function. Also adds some tests for CreateFullPath. --- Source/Core/Core/IOS/FS/FileSystem.cpp | 9 ++++++--- .../UnitTests/Core/IOS/FS/FileSystemTest.cpp | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/IOS/FS/FileSystem.cpp b/Source/Core/Core/IOS/FS/FileSystem.cpp index 66bd7659ae..512f7ae50b 100644 --- a/Source/Core/Core/IOS/FS/FileSystem.cpp +++ b/Source/Core/Core/IOS/FS/FileSystem.cpp @@ -115,9 +115,12 @@ ResultCode FileSystem::CreateFullPath(Uid uid, Gid gid, const std::string& path, if (metadata && metadata->is_file) return ResultCode::Invalid; - const ResultCode result = CreateDirectory(uid, gid, subpath, attribute, modes); - if (result != ResultCode::Success && result != ResultCode::AlreadyExists) - return result; + if (!metadata) + { + const ResultCode result = CreateDirectory(uid, gid, subpath, attribute, modes); + if (result != ResultCode::Success) + return result; + } ++position; } diff --git a/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp b/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp index 79f853f441..4152c76f4a 100644 --- a/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp +++ b/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp @@ -434,3 +434,21 @@ TEST_F(FileSystemTest, ReadDirectoryOrdering) ASSERT_EQ(result->size(), file_names.size()); EXPECT_TRUE(std::equal(result->begin(), result->end(), file_names.rbegin())); } + +TEST_F(FileSystemTest, CreateFullPath) +{ + ASSERT_EQ(m_fs->CreateFullPath(Uid{0}, Gid{0}, "/tmp/a/b/c/d", 0, modes), ResultCode::Success); + + // Parent directories should be created by CreateFullPath. + for (const std::string& path : {"/tmp", "/tmp/a", "/tmp/a/b", "/tmp/a/b/c"}) + EXPECT_TRUE(m_fs->ReadDirectory(Uid{0}, Gid{0}, path).Succeeded()); + + // If parent directories already exist, the call should still succeed. + EXPECT_EQ(m_fs->CreateFullPath(Uid{0}, Gid{0}, "/tmp/a/b/c/d", 0, modes), ResultCode::Success); + + // If parent directories already exist and are owned by a different user, + // CreateFullPath should still succeed. + // See https://github.com/dolphin-emu/dolphin/pull/8593 + EXPECT_EQ(m_fs->CreateFullPath(Uid{0x1000}, Gid{1}, "/shared2/wc24/mbox/Readme.txt", 0, modes), + ResultCode::Success); +}