From b591633cb9fcda82d59221ed3c6dcc1c5d665b5a Mon Sep 17 00:00:00 2001 From: Silent Date: Sun, 6 Oct 2019 12:30:48 +0200 Subject: [PATCH] Fail pkg_install if any files fail to be created This could happen if eg. paths are too long or some files could not be overwritten. Until now, installation happily reported success regardless. --- rpcs3/Crypto/unpkg.cpp | 36 +++++++++++++++++++++++++++++------ rpcs3/rpcs3qt/main_window.cpp | 13 +++++++++++++ 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/rpcs3/Crypto/unpkg.cpp b/rpcs3/Crypto/unpkg.cpp index de3a00db84..668d2bdcd3 100644 --- a/rpcs3/Crypto/unpkg.cpp +++ b/rpcs3/Crypto/unpkg.cpp @@ -295,6 +295,8 @@ bool pkg_install(const std::string& path, atomic_t& sync) decrypt(0, header.file_count * sizeof(PKGEntry), header.pkg_platform == PKG_PLATFORM_TYPE_PSP ? PKG_AES_KEY2 : dec_key.data()); } + size_t num_failures = 0; + std::vector entries(header.file_count); std::memcpy(entries.data(), buf.get(), entries.size() * sizeof(PKGEntry)); @@ -305,6 +307,7 @@ bool pkg_install(const std::string& path, atomic_t& sync) if (entry.name_size > 256) { + num_failures++; LOG_ERROR(LOADER, "PKG name size is too big (0x%x)", entry.name_size); continue; } @@ -341,18 +344,21 @@ bool pkg_install(const std::string& path, atomic_t& sync) if (fs::file out{path, fs::rewrite}) { + bool extract_success = true; for (u64 pos = 0; pos < entry.file_size; pos += BUF_SIZE) { const u64 block_size = std::min(BUF_SIZE, entry.file_size - pos); if (decrypt(entry.file_offset + pos, block_size, is_psp ? PKG_AES_KEY2 : dec_key.data()) != block_size) { + extract_success = false; LOG_ERROR(LOADER, "Failed to extract file %s", path); break; } if (out.write(buf.get(), block_size) != block_size) { + extract_success = false; LOG_ERROR(LOADER, "Failed to write file %s", path); break; } @@ -372,17 +378,25 @@ bool pkg_install(const std::string& path, atomic_t& sync) } } - if (did_overwrite) - { - LOG_WARNING(LOADER, "Overwritten file %s", name); + if (extract_success) + { + if (did_overwrite) + { + LOG_WARNING(LOADER, "Overwritten file %s", name); + } + else + { + LOG_NOTICE(LOADER, "Created file %s", name); + } } else { - LOG_NOTICE(LOADER, "Created file %s", name); + num_failures++; } } else { + num_failures++; LOG_ERROR(LOADER, "Failed to create file %s", path); } @@ -404,6 +418,7 @@ bool pkg_install(const std::string& path, atomic_t& sync) } else { + num_failures++; LOG_ERROR(LOADER, "Failed to create directory %s", path); } @@ -412,11 +427,20 @@ bool pkg_install(const std::string& path, atomic_t& sync) default: { + num_failures++; LOG_ERROR(LOADER, "Unknown PKG entry type (0x%x) %s", entry.type, name); } } } - LOG_SUCCESS(LOADER, "Package successfully installed to %s", dir); - return true; + if (num_failures == 0) + { + LOG_SUCCESS(LOADER, "Package successfully installed to %s", dir); + } + else + { + fs::remove_all(dir, true); + LOG_ERROR(LOADER, "Package installation failed: %s", dir); + } + return num_failures == 0; } diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp index 90a5c79508..fa3ac7f68b 100644 --- a/rpcs3/rpcs3qt/main_window.cpp +++ b/rpcs3/rpcs3qt/main_window.cpp @@ -437,6 +437,8 @@ void main_window::InstallPkg(const QString& dropPath, bool is_bulk) // Synchronization variable atomic_t progress(0.); + bool cancelled = false; + // Run PKG unpacking asynchronously named_thread worker("PKG Installer", [&] { @@ -449,6 +451,7 @@ void main_window::InstallPkg(const QString& dropPath, bool is_bulk) { if (pdlg.wasCanceled()) { + cancelled = true; progress -= 1.; break; } @@ -465,6 +468,11 @@ void main_window::InstallPkg(const QString& dropPath, bool is_bulk) pdlg.SetValue(pdlg.maximum()); std::this_thread::sleep_for(100ms); } + else + { + pdlg.setHidden(true); + pdlg.SignalFailure(); + } } if (worker()) @@ -473,6 +481,11 @@ void main_window::InstallPkg(const QString& dropPath, bool is_bulk) LOG_SUCCESS(GENERAL, "Successfully installed %s.", fileName); guiSettings->ShowInfoBox(tr("Success!"), tr("Successfully installed software from package!"), gui::ib_pkg_success, this); } + else if (!cancelled) + { + LOG_ERROR(GENERAL, "Failed to install %s.", fileName); + QMessageBox::critical(this, tr("Failure!"), tr("Failed to install software from package %1!").arg(filePath)); + } } void main_window::InstallPup(const QString& dropPath)