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.
This commit is contained in:
Silent 2019-10-06 12:30:48 +02:00 committed by Ivan
commit b591633cb9
2 changed files with 43 additions and 6 deletions

View file

@ -295,6 +295,8 @@ bool pkg_install(const std::string& path, atomic_t<double>& sync)
decrypt(0, header.file_count * sizeof(PKGEntry), header.pkg_platform == PKG_PLATFORM_TYPE_PSP ? PKG_AES_KEY2 : dec_key.data()); 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<PKGEntry> entries(header.file_count); std::vector<PKGEntry> entries(header.file_count);
std::memcpy(entries.data(), buf.get(), entries.size() * sizeof(PKGEntry)); std::memcpy(entries.data(), buf.get(), entries.size() * sizeof(PKGEntry));
@ -305,6 +307,7 @@ bool pkg_install(const std::string& path, atomic_t<double>& sync)
if (entry.name_size > 256) if (entry.name_size > 256)
{ {
num_failures++;
LOG_ERROR(LOADER, "PKG name size is too big (0x%x)", entry.name_size); LOG_ERROR(LOADER, "PKG name size is too big (0x%x)", entry.name_size);
continue; continue;
} }
@ -341,18 +344,21 @@ bool pkg_install(const std::string& path, atomic_t<double>& sync)
if (fs::file out{path, fs::rewrite}) if (fs::file out{path, fs::rewrite})
{ {
bool extract_success = true;
for (u64 pos = 0; pos < entry.file_size; pos += BUF_SIZE) for (u64 pos = 0; pos < entry.file_size; pos += BUF_SIZE)
{ {
const u64 block_size = std::min<u64>(BUF_SIZE, entry.file_size - pos); const u64 block_size = std::min<u64>(BUF_SIZE, entry.file_size - pos);
if (decrypt(entry.file_offset + pos, block_size, is_psp ? PKG_AES_KEY2 : dec_key.data()) != block_size) 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); LOG_ERROR(LOADER, "Failed to extract file %s", path);
break; break;
} }
if (out.write(buf.get(), block_size) != block_size) if (out.write(buf.get(), block_size) != block_size)
{ {
extract_success = false;
LOG_ERROR(LOADER, "Failed to write file %s", path); LOG_ERROR(LOADER, "Failed to write file %s", path);
break; break;
} }
@ -372,17 +378,25 @@ bool pkg_install(const std::string& path, atomic_t<double>& sync)
} }
} }
if (did_overwrite) if (extract_success)
{ {
LOG_WARNING(LOADER, "Overwritten file %s", name); if (did_overwrite)
{
LOG_WARNING(LOADER, "Overwritten file %s", name);
}
else
{
LOG_NOTICE(LOADER, "Created file %s", name);
}
} }
else else
{ {
LOG_NOTICE(LOADER, "Created file %s", name); num_failures++;
} }
} }
else else
{ {
num_failures++;
LOG_ERROR(LOADER, "Failed to create file %s", path); LOG_ERROR(LOADER, "Failed to create file %s", path);
} }
@ -404,6 +418,7 @@ bool pkg_install(const std::string& path, atomic_t<double>& sync)
} }
else else
{ {
num_failures++;
LOG_ERROR(LOADER, "Failed to create directory %s", path); LOG_ERROR(LOADER, "Failed to create directory %s", path);
} }
@ -412,11 +427,20 @@ bool pkg_install(const std::string& path, atomic_t<double>& sync)
default: default:
{ {
num_failures++;
LOG_ERROR(LOADER, "Unknown PKG entry type (0x%x) %s", entry.type, name); LOG_ERROR(LOADER, "Unknown PKG entry type (0x%x) %s", entry.type, name);
} }
} }
} }
LOG_SUCCESS(LOADER, "Package successfully installed to %s", dir); if (num_failures == 0)
return true; {
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;
} }

View file

@ -437,6 +437,8 @@ void main_window::InstallPkg(const QString& dropPath, bool is_bulk)
// Synchronization variable // Synchronization variable
atomic_t<double> progress(0.); atomic_t<double> progress(0.);
bool cancelled = false;
// Run PKG unpacking asynchronously // Run PKG unpacking asynchronously
named_thread worker("PKG Installer", [&] named_thread worker("PKG Installer", [&]
{ {
@ -449,6 +451,7 @@ void main_window::InstallPkg(const QString& dropPath, bool is_bulk)
{ {
if (pdlg.wasCanceled()) if (pdlg.wasCanceled())
{ {
cancelled = true;
progress -= 1.; progress -= 1.;
break; break;
} }
@ -465,6 +468,11 @@ void main_window::InstallPkg(const QString& dropPath, bool is_bulk)
pdlg.SetValue(pdlg.maximum()); pdlg.SetValue(pdlg.maximum());
std::this_thread::sleep_for(100ms); std::this_thread::sleep_for(100ms);
} }
else
{
pdlg.setHidden(true);
pdlg.SignalFailure();
}
} }
if (worker()) if (worker())
@ -473,6 +481,11 @@ void main_window::InstallPkg(const QString& dropPath, bool is_bulk)
LOG_SUCCESS(GENERAL, "Successfully installed %s.", fileName); LOG_SUCCESS(GENERAL, "Successfully installed %s.", fileName);
guiSettings->ShowInfoBox(tr("Success!"), tr("Successfully installed software from package!"), gui::ib_pkg_success, this); 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) void main_window::InstallPup(const QString& dropPath)