From 20304715af524d51d73634721912055346a07710 Mon Sep 17 00:00:00 2001 From: Shalen Bennett <70249609+doctashay@users.noreply.github.com> Date: Fri, 24 Jun 2022 16:27:57 -0600 Subject: [PATCH] Replace assert with user-friendly error if ISO is invalid or not found (#1540) * Replace assert with user-friendly error if ISO not found When the extractor runs and can't detect a game folder, it will assume there is an ISO file in the directory instead. If there isn't an ISO file, or it's a different extension, it will trigger an assert. This adds an additional check to make sure the file extension is of type `.iso` and returns a more clear message to the user. Once I get home I'll iterate upon this a bit to add file size checks and reading header data as well as making sure the error code is able to be reported to the launcher. * Fix `extension` call & formatting more de-rust lol * fix extension call (again) * fix ONE extra parenthesis * argument incompatible with fmt print will fix print later * add ONE missing parenthesis never taking intellisense for granted again * Add ISO size checks and rework type check * actually print `data_dir_path` :p * Normalize extension case before verifying file type + clang-format * clang-format Co-authored-by: doctashay --- .../scripts/releases/error-code-metadata.json | 6 ++++ decompiler/extractor/main.cpp | 29 +++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/.github/scripts/releases/error-code-metadata.json b/.github/scripts/releases/error-code-metadata.json index b0654425a5..0c0c35ca2a 100644 --- a/.github/scripts/releases/error-code-metadata.json +++ b/.github/scripts/releases/error-code-metadata.json @@ -20,4 +20,10 @@ "4030": { "msg": "Decompilation Failed: An error occurred" } + "4040": { + "msg": "Extraction Failed: Provided game data file was not an ISO file" + } + "4041": { + "msg": "Extraction Failed: Provided game data file was corrupt or has unexpected size" + } } diff --git a/decompiler/extractor/main.cpp b/decompiler/extractor/main.cpp index 5f5fd7c9c6..473eb17696 100644 --- a/decompiler/extractor/main.cpp +++ b/decompiler/extractor/main.cpp @@ -23,7 +23,9 @@ enum class ExtractorErrorCode { VALIDATION_BAD_ISO_CONTENTS = 4010, VALIDATION_INCORRECT_EXTRACTION_COUNT = 4011, VALIDATION_BAD_EXTRACTION = 4020, - DECOMPILATION_GENERIC_ERROR = 4030 + DECOMPILATION_GENERIC_ERROR = 4030, + EXTRACTION_INVALID_ISO_PATH = 4040, + EXTRACTION_ISO_UNEXPECTED_SIZE = 4041 }; enum GameIsoFlags { FLAG_JAK1_BLACK_LABEL = (1 << 0) }; @@ -66,7 +68,10 @@ void setup_global_decompiler_stuff(std::optional project_ IsoFile extract_files(std::filesystem::path data_dir_path, std::filesystem::path extracted_iso_path) { - fmt::print("Note: input isn't a folder, assuming it's an ISO file...\n"); + fmt::print( + "Note: Provided game data path '{}' points to a file, not a directory. Assuming it's an ISO " + "file and attempting to extract!\n", + data_dir_path.string()); std::filesystem::create_directories(extracted_iso_path); @@ -415,7 +420,25 @@ int main(int argc, char** argv) { int flags = 0; if (std::filesystem::is_regular_file(data_dir_path)) { - // it's a file, treat it as an ISO + // it's a file, normalize extension case and verify it's an ISO file + std::string ext = data_dir_path.extension().string(); + std::transform(ext.begin(), ext.end(), ext.begin(), + [](unsigned char c) { return std::tolower(c); }); + + if (ext != ".iso") { + fmt::print(stderr, "ERROR: Provided game data path contains a file that isn't a .ISO!"); + return static_cast(ExtractorErrorCode::EXTRACTION_INVALID_ISO_PATH); + } + + // make sure the .iso is greater than 1GB in size + // to-do: verify game header data as well + if (std::filesystem::file_size(data_dir_path) < 1000000000) { + fmt::print( + stderr, + "ERROR: Provided game data file appears to be too small or corrupted! Size is {}", + std::filesystem::file_size(data_dir_path)); + return static_cast(ExtractorErrorCode::EXTRACTION_ISO_UNEXPECTED_SIZE); + } auto iso_file = extract_files(data_dir_path, path_to_iso_files); auto validation_res = validate(iso_file, path_to_iso_files); flags = validation_res.second->flags;