diff --git a/source/lib/file/file_system.cpp b/source/lib/file/file_system.cpp index 0e6bdd2085..2ce98cf896 100644 --- a/source/lib/file/file_system.cpp +++ b/source/lib/file/file_system.cpp @@ -193,6 +193,24 @@ Status DeleteDirectory(const OsPath& path) return INFO::OK; } +Status RenameFile(const OsPath& path, const OsPath& newPath) +{ + if (path.empty()) + return INFO::OK; + + try + { + fs::rename(path.string8(), newPath.string8()); + } + catch (fs::filesystem_error& err) + { + debug_printf("RenameFile: failed to rename %s to %s.\n%s\n", path.string8().c_str(), path.string8().c_str(), err.what()); + return ERR::EXCEPTION; + } + + return INFO::OK; + +} Status CopyFile(const OsPath& path, const OsPath& newPath, bool override_if_exists/* = false*/) { diff --git a/source/lib/file/file_system.h b/source/lib/file/file_system.h index f51c2c64c4..3f4e8b2a77 100644 --- a/source/lib/file/file_system.h +++ b/source/lib/file/file_system.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -88,4 +88,6 @@ LIB_API Status DeleteDirectory(const OsPath& dirPath); LIB_API Status CopyFile(const OsPath& path, const OsPath& newPath, bool override_if_exists = false); +LIB_API Status RenameFile(const OsPath& path, const OsPath& newPath); + #endif // #ifndef INCLUDED_FILE_SYSTEM diff --git a/source/main.cpp b/source/main.cpp index f3f4278b40..4d92ddc8cc 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -665,7 +665,11 @@ static void RunGameOrAtlas(int argc, const char* argv[]) // Install the mods without deleting the pyromod files for (const OsPath& modPath : modsToInstall) - installer.Install(modPath, g_ScriptContext, true); + { + CModInstaller::ModInstallationResult result = installer.Install(modPath, g_ScriptContext, true); + if (result != CModInstaller::ModInstallationResult::SUCCESS) + LOGERROR("Failed to install '%s'", modPath.string8().c_str()); + } installedMods = installer.GetInstalledMods(); diff --git a/source/ps/ModInstaller.cpp b/source/ps/ModInstaller.cpp index 5457fcd24f..6831eac35a 100644 --- a/source/ps/ModInstaller.cpp +++ b/source/ps/ModInstaller.cpp @@ -49,9 +49,18 @@ CModInstaller::ModInstallationResult CModInstaller::Install( CreateDirectories(modTemp.Parent(), 0700); if (keepFile) - CopyFile(mod, modTemp, true); - else - wrename(mod, modTemp); + { + if (CopyFile(mod, modTemp, true) != INFO::OK) + { + LOGERROR("Failed to copy '%s' to '%s'", mod.string8().c_str(), modTemp.string8().c_str()); + return FAIL_ON_MOD_COPY; + } + } + else if (RenameFile(mod, modTemp) != INFO::OK) + { + LOGERROR("Failed to rename '%s' into '%s'", mod.string8().c_str(), modTemp.string8().c_str()); + return FAIL_ON_MOD_MOVE; + } // Load the mod to VFS if (m_VFS->Mount(m_CacheDir, m_TempDir / "") != INFO::OK) @@ -88,8 +97,12 @@ CModInstaller::ModInstallationResult CModInstaller::Install( // mod-name.zip // mod.json CreateDirectories(modDir, 0700); - if (wrename(modTemp, modPath) != 0) + if (RenameFile(modTemp, modPath) != INFO::OK) + { + LOGERROR("Failed to rename '%s' into '%s'", modTemp.string8().c_str(), modPath.string8().c_str()); return FAIL_ON_MOD_MOVE; + } + DeleteDirectory(modTemp.Parent()); std::ofstream mod_json((modDir / "mod.json").string8()); diff --git a/source/ps/ModInstaller.h b/source/ps/ModInstaller.h index 3121034f10..a5c3143393 100644 --- a/source/ps/ModInstaller.h +++ b/source/ps/ModInstaller.h @@ -39,7 +39,8 @@ public: FAIL_ON_PARSE_JSON, FAIL_ON_EXTRACT_NAME, FAIL_ON_MOD_MOVE, - FAIL_ON_JSON_WRITE + FAIL_ON_JSON_WRITE, + FAIL_ON_MOD_COPY }; /** diff --git a/source/ps/ModIo.cpp b/source/ps/ModIo.cpp index dfc96d202d..a1a2f14155 100644 --- a/source/ps/ModIo.cpp +++ b/source/ps/ModIo.cpp @@ -485,7 +485,9 @@ bool ModIo::AdvanceRequest(const ScriptInterface& scriptInterface) { Paths paths(g_CmdLineArgs); CModInstaller installer(paths.UserData() / "mods", paths.Cache()); - installer.Install(m_DownloadFilePath, g_ScriptContext, false); + CModInstaller::ModInstallationResult result = installer.Install(m_DownloadFilePath, g_ScriptContext, false); + if (result != CModInstaller::ModInstallationResult::SUCCESS) + LOGERROR("Failed to install '%s'", m_DownloadFilePath.string8().c_str()); g_Mods.UpdateAvailableMods(scriptInterface); } break;