From 8517528f8c094f51a3c4dab5922e894232225820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= <leo@leolam.fr> Date: Sat, 28 Dec 2019 20:44:16 +0100 Subject: [PATCH] IOS/FS: Implement CreateFile and CreateDir properly --- Source/Core/Core/IOS/FS/HostBackend/FS.cpp | 59 +++++++++++++++------- Source/Core/Core/IOS/FS/HostBackend/FS.h | 3 ++ 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/Source/Core/Core/IOS/FS/HostBackend/FS.cpp b/Source/Core/Core/IOS/FS/HostBackend/FS.cpp index 4f67a30a03..8cb9127a91 100644 --- a/Source/Core/Core/IOS/FS/HostBackend/FS.cpp +++ b/Source/Core/Core/IOS/FS/HostBackend/FS.cpp @@ -348,36 +348,57 @@ ResultCode HostFileSystem::Format(Uid uid) return ResultCode::Success; } -ResultCode HostFileSystem::CreateFile(Uid, Gid, const std::string& path, FileAttribute, Modes) +ResultCode HostFileSystem::CreateFileOrDirectory(Uid uid, Gid gid, const std::string& path, + FileAttribute attr, Modes modes, bool is_file) { - std::string file_name(BuildFilename(path)); - // check if the file already exist - if (File::Exists(file_name)) + if (!IsValidNonRootPath(path) || !std::all_of(path.begin(), path.end(), IsPrintableCharacter)) + return ResultCode::Invalid; + + if (!is_file && std::count(path.begin(), path.end(), '/') > int(MaxPathDepth)) + return ResultCode::TooManyPathComponents; + + const auto split_path = SplitPathAndBasename(path); + const std::string host_path = BuildFilename(path); + + FstEntry* parent = GetFstEntryForPath(split_path.parent); + if (!parent) + return ResultCode::NotFound; + + if (!parent->CheckPermission(uid, gid, Mode::Write)) + return ResultCode::AccessDenied; + + if (File::Exists(host_path)) return ResultCode::AlreadyExists; - // create the file - File::CreateFullPath(file_name); // just to be sure - if (!File::CreateEmptyFile(file_name)) + const bool ok = is_file ? File::CreateEmptyFile(host_path) : File::CreateDir(host_path); + if (!ok) { - ERROR_LOG(IOS_FS, "couldn't create new file"); - return ResultCode::Invalid; + ERROR_LOG(IOS_FS, "Failed to create file or directory: %s", host_path.c_str()); + return ResultCode::UnknownError; } + FstEntry* child = GetFstEntryForPath(path); + *child = {}; + child->name = split_path.file_name; + child->data.is_file = is_file; + child->data.modes = modes; + child->data.uid = uid; + child->data.gid = gid; + child->data.attribute = attr; + SaveFst(); return ResultCode::Success; } -ResultCode HostFileSystem::CreateDirectory(Uid, Gid, const std::string& path, FileAttribute, Modes) +ResultCode HostFileSystem::CreateFile(Uid uid, Gid gid, const std::string& path, FileAttribute attr, + Modes modes) { - if (!IsValidPath(path)) - return ResultCode::Invalid; + return CreateFileOrDirectory(uid, gid, path, attr, modes, true); +} - std::string name(BuildFilename(path)); - - name += "/"; - File::CreateFullPath(name); - DEBUG_ASSERT_MSG(IOS_FS, File::IsDirectory(name), "CREATE_DIR %s failed", name.c_str()); - - return ResultCode::Success; +ResultCode HostFileSystem::CreateDirectory(Uid uid, Gid gid, const std::string& path, + FileAttribute attr, Modes modes) +{ + return CreateFileOrDirectory(uid, gid, path, attr, modes, false); } ResultCode HostFileSystem::Delete(Uid, Gid, const std::string& path) diff --git a/Source/Core/Core/IOS/FS/HostBackend/FS.h b/Source/Core/Core/IOS/FS/HostBackend/FS.h index a147194c1e..fa4269d952 100644 --- a/Source/Core/Core/IOS/FS/HostBackend/FS.h +++ b/Source/Core/Core/IOS/FS/HostBackend/FS.h @@ -87,6 +87,9 @@ private: std::string BuildFilename(const std::string& wii_path) const; std::shared_ptr<File::IOFile> OpenHostFile(const std::string& host_path); + ResultCode CreateFileOrDirectory(Uid uid, Gid gid, const std::string& path, + FileAttribute attribute, Modes modes, bool is_file); + std::string GetFstFilePath() const; void ResetFst(); void LoadFst();