diff --git a/Core/Util/GameManager.cpp b/Core/Util/GameManager.cpp index 4aefcd6217..7adb56cb84 100644 --- a/Core/Util/GameManager.cpp +++ b/Core/Util/GameManager.cpp @@ -200,6 +200,7 @@ bool GameManager::InstallGame(std::string zipfile, bool deleteAfter) { } // Now, loop through again in a second pass, writing files. + std::vector createdFiles; for (int i = 0; i < numFiles; i++) { const char *fn = zip_get_name(z, i, 0); // Note that we do NOT write files that are not in a directory, to avoid random @@ -232,7 +233,13 @@ bool GameManager::InstallGame(std::string zipfile, bool deleteAfter) { size_t written = fwrite(buffer, 1, bs, f); if (written != bs) { ERROR_LOG(HLE, "Wrote %i bytes out of %i - Disk full?", (int)written, (int)bs); - // TODO: What do we do? + delete [] buffer; + buffer = 0; + fclose(f); + zip_fclose(zf); + deleteFile(outFilename.c_str()); + // Yes it's a goto. Sue me. I think it's appropriate here. + goto bail; } pos += bs; @@ -242,6 +249,7 @@ bool GameManager::InstallGame(std::string zipfile, bool deleteAfter) { } zip_fclose(zf); fclose(f); + createdFiles.push_back(outFilename); delete [] buffer; } else { ERROR_LOG(HLE, "Failed to open file for writing"); @@ -251,13 +259,33 @@ bool GameManager::InstallGame(std::string zipfile, bool deleteAfter) { INFO_LOG(HLE, "Extracted %i files (%i bytes).", numFiles, (int)bytesCopied); zip_close(z); + z = 0; installProgress_ = 1.0f; installInProgress_ = false; + installError_ = ""; if (deleteAfter) { deleteFile(zipfile.c_str()); } InstallDone(); return true; + +bail: + zip_close(z); + // We end up here if disk is full or couldn't write to storage for some other reason. + installProgress_ = 0.0f; + installInProgress_ = false; + installError_ = "Storage full"; + if (deleteAfter) { + deleteFile(zipfile.c_str()); + } + for (size_t i = 0; i < createdFiles.size(); i++) { + deleteFile(createdFiles[i].c_str()); + } + for (auto iter = createdDirs.begin(); iter != createdDirs.end(); ++iter) { + deleteDir(iter->c_str()); + } + InstallDone(); + return false; } bool GameManager::InstallGameOnThread(std::string zipFile, bool deleteAfter) { diff --git a/Core/Util/GameManager.h b/Core/Util/GameManager.h index 0a115e0822..d5053a1446 100644 --- a/Core/Util/GameManager.h +++ b/Core/Util/GameManager.h @@ -46,6 +46,9 @@ public: float GetCurrentInstallProgress() const { return installProgress_; } + std::string GetInstallError() const { + return installError_; + } // Only returns false if there's already an installation in progress. bool InstallGameOnThread(std::string zipFile, bool deleteAfter); @@ -59,6 +62,7 @@ private: std::shared_ptr installThread_; bool installInProgress_; float installProgress_; + std::string installError_; }; extern GameManager g_GameManager; diff --git a/UI/InstallZipScreen.cpp b/UI/InstallZipScreen.cpp index 872560d4af..7f6b5c01f8 100644 --- a/UI/InstallZipScreen.cpp +++ b/UI/InstallZipScreen.cpp @@ -45,6 +45,8 @@ void InstallZipScreen::CreateViews() { leftColumn->Add(new TextView(iz->T("Install game from ZIP file?"), ALIGN_LEFT, false, new AnchorLayoutParams(10, 10, NONE, NONE))); leftColumn->Add(new TextView(zipPath_, ALIGN_LEFT, false, new AnchorLayoutParams(10, 60, NONE, NONE))); + + doneView_ = leftColumn->Add(new TextView("", new AnchorLayoutParams(10, 120, NONE, NONE))); progressBar_ = leftColumn->Add(new ProgressBar(new AnchorLayoutParams(10, 200, 200, NONE))); ViewGroup *rightColumnItems = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(300, FILL_PARENT, actionMenuMargins)); @@ -75,6 +77,8 @@ UI::EventReturn InstallZipScreen::OnInstall(UI::EventParams ¶ms) { } void InstallZipScreen::update(InputState &input) { + I18NCategory *iz = GetI18NCategory("InstallZip"); + using namespace UI; if (g_GameManager.IsInstallInProgress()) { progressBar_->SetVisibility(V_VISIBLE); @@ -83,6 +87,10 @@ void InstallZipScreen::update(InputState &input) { } else { progressBar_->SetVisibility(V_GONE); backChoice_->SetEnabled(true); + std::string err = g_GameManager.GetInstallError(); + if (!err.empty()) { + doneView_->SetText(iz->T(err.c_str())); + } } UIScreen::update(input); } diff --git a/UI/InstallZipScreen.h b/UI/InstallZipScreen.h index e6ab6b86c3..a4fb41960e 100644 --- a/UI/InstallZipScreen.h +++ b/UI/InstallZipScreen.h @@ -25,7 +25,7 @@ class InstallZipScreen : public UIDialogScreenWithBackground { public: - InstallZipScreen(std::string zipPath) : installChoice_(0), zipPath_(zipPath), installStarted_(false), deleteZipFile_(false) {} + InstallZipScreen(std::string zipPath) : installChoice_(0), doneView_(0), zipPath_(zipPath), installStarted_(false), deleteZipFile_(false) {} virtual void update(InputState &input); virtual void key(const KeyInput &key);