Some fixes (#18686)
### FIXES + MINOR IMPROVEMENTS: - Fixed issue18685: Not a real issue. PR18648 added some logging that made evident a missing check on the validity of the paths in `games.yml` before trying to manage the path as a possible ISO file. That missing check was already present but simply invisible due to missing log - Fixed `bytes_to_hex()` function used to store file hash hex string: In some cases the integrity check wrongly reported the check as failed - Optimized `fs::get_optical_raw_device()` function: Moved under `_WIN32` block a check valid only on `Windows` and simplified the logic to detect a CDROM / BD as raw device - Used `iso_file` objects instead of `fs:file` in `ISO.cpp`: It allows to use proper `bool()` operator on some checks
This commit is contained in:
committed by
GitHub
parent
4f47fee360
commit
026297334f
+8
-26
@@ -1125,13 +1125,6 @@ bool fs::is_optical_raw_device([[maybe_unused]] const std::string& path)
|
||||
|
||||
bool fs::get_optical_raw_device(const std::string& path, std::string* raw_device)
|
||||
{
|
||||
// Skip a useless check to detect an optical raw device if navigating on subfolders (e.g. C:/subfolder_1/subfolder_2/), it means we are on a hdd/ssd.
|
||||
// A path for an optical drive should include only the drive letter (e.g. E:/)
|
||||
if (path.find_first_of(":") != path.find_last_not_of(delim))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fs::is_optical_raw_device(path))
|
||||
{
|
||||
if (raw_device)
|
||||
@@ -1143,38 +1136,27 @@ bool fs::get_optical_raw_device(const std::string& path, std::string* raw_device
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
constexpr u32 BUF_SIZE = 1000;
|
||||
WCHAR drive_list[BUF_SIZE] = {0};
|
||||
// Skip a useless check to detect an optical raw device if navigating on subfolders (e.g. C:\subfolder_1\subfolder_2\),
|
||||
// it means we are on a HDD/SSD. A path for an optical drive should include only the drive letter (e.g. E:\)
|
||||
const size_t drive_delim_pos = path.find_first_of(":");
|
||||
|
||||
// GetLogicalDriveStrings() returns a double-null terminated list of null-terminated strings.
|
||||
// E.g. A:\<nul>B:\<nul>C:\<nul><nul>
|
||||
const DWORD copied = GetLogicalDriveStrings(BUF_SIZE, drive_list);
|
||||
|
||||
if (copied == 0 || copied > BUF_SIZE)
|
||||
if (drive_delim_pos != 1 || drive_delim_pos != path.find_last_not_of(delim))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const WCHAR* drive = drive_list; drive && *drive; drive += wcslen(drive) + 1)
|
||||
{
|
||||
if (GetDriveType(drive) == DRIVE_CDROM)
|
||||
{
|
||||
const std::wstring ws(drive);
|
||||
const std::string s = std::string(ws.begin(), ws.end() - 1);
|
||||
const std::string drive_letter = path.substr(0, drive_delim_pos + 1); // e.g. "E:"
|
||||
const std::string drive_path = drive_letter + "\\"; // e.g. "E:\"
|
||||
|
||||
if (path.starts_with(s))
|
||||
if (GetDriveTypeA(drive_path.c_str()) == DRIVE_CDROM)
|
||||
{
|
||||
if (raw_device)
|
||||
{
|
||||
*raw_device = "\\\\.\\" + s;
|
||||
*raw_device = "\\\\.\\" + drive_letter;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,14 @@ void bytes_to_hex(std::string& hex_str, const unsigned char* data, unsigned int
|
||||
{
|
||||
fmt::throw_exception("Failed to read bytes: %s", std::make_error_code(err).message());
|
||||
}
|
||||
|
||||
// Padding handling for values < 0x10 (e.g. 0x05 becomes "5" instead of "05")
|
||||
// If to_chars only writes 1 character, we move to the right and put '0'
|
||||
if (ptr == &hex_str[i] + 1)
|
||||
{
|
||||
hex_str[i + 1] = hex_str[i];
|
||||
hex_str[i] = '0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-14
@@ -54,7 +54,7 @@ static void* get_aligned_buf()
|
||||
return s_aligned_buf.buf;
|
||||
}
|
||||
|
||||
static bool is_iso_file(const fs::file& file, u64* size = nullptr)
|
||||
static bool is_iso_file(iso_file& file, u64* size = nullptr)
|
||||
{
|
||||
if (!file || file.size() < 32768ULL + 6)
|
||||
{
|
||||
@@ -87,7 +87,7 @@ bool is_iso_file(const std::string& path, u64* size, bool* is_raw_device)
|
||||
// "new_path" is updated with the raw device path in case "path" points to a BD drive
|
||||
const bool raw_device = fs::get_optical_raw_device(path, &new_path);
|
||||
|
||||
if (!raw_device && fs::is_dir(path))
|
||||
if (!raw_device && !fs::is_file(path))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -97,7 +97,7 @@ bool is_iso_file(const std::string& path, u64* size, bool* is_raw_device)
|
||||
*is_raw_device = raw_device;
|
||||
}
|
||||
|
||||
fs::file file(std::make_unique<iso_file>(new_path, fs::read));
|
||||
iso_file file(new_path);
|
||||
|
||||
return is_iso_file(file, size);
|
||||
}
|
||||
@@ -337,7 +337,7 @@ iso_type_status iso_file_decryption::retrieve_key(iso_archive& archive, std::str
|
||||
return iso_type_status::ERROR_OPENING_KEY;
|
||||
}
|
||||
|
||||
iso_type_status iso_file_decryption::check_type(const std::string& path, std::string& key_path, aes_context* aes_ctx)
|
||||
iso_type_status iso_file_decryption::check_type(const std::string& path, std::string* key_path, aes_context* aes_ctx)
|
||||
{
|
||||
if (!is_iso_file(path))
|
||||
{
|
||||
@@ -363,8 +363,12 @@ iso_type_status iso_file_decryption::check_type(const std::string& path, std::st
|
||||
{
|
||||
if (fs::is_file(path))
|
||||
{
|
||||
key_path = path;
|
||||
return get_key(key_path, aes_ctx);
|
||||
if (key_path)
|
||||
{
|
||||
*key_path = path;
|
||||
}
|
||||
|
||||
return get_key(path, aes_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,7 +385,7 @@ bool iso_file_decryption::init(const std::string& path, iso_archive* archive)
|
||||
// Store the ISO region information (needed by both the "Redump" type (only on "decrypt()" method) and "3k3y" type)
|
||||
//
|
||||
|
||||
fs::file iso_file(std::make_unique<iso_file>(path, fs::read));
|
||||
iso_file iso_file(path);
|
||||
|
||||
if (!is_iso_file(iso_file))
|
||||
{
|
||||
@@ -390,7 +394,7 @@ bool iso_file_decryption::init(const std::string& path, iso_archive* archive)
|
||||
}
|
||||
|
||||
// Reset the file position after it was changed by is_iso_file()
|
||||
iso_file.seek(0);
|
||||
iso_file.seek(0, fs::seek_set);
|
||||
|
||||
std::array<u8, ISO_SECTOR_SIZE * 2> sec0_sec1;
|
||||
|
||||
@@ -447,7 +451,7 @@ bool iso_file_decryption::init(const std::string& path, iso_archive* archive)
|
||||
else
|
||||
{
|
||||
// Try to detect the Redump type. If so, the decryption context is set into "m_aes_dec"
|
||||
status = check_type(path, key_path, &m_aes_dec);
|
||||
status = check_type(path, &key_path, &m_aes_dec);
|
||||
}
|
||||
|
||||
switch (status)
|
||||
@@ -968,17 +972,14 @@ iso_archive::iso_archive(const std::string& path)
|
||||
// "m_path" is updated with the raw device path in case "path" points to a BD drive
|
||||
fs::get_optical_raw_device(path, &m_path);
|
||||
|
||||
fs::file iso_file(std::make_unique<iso_file>(m_path, fs::read));
|
||||
|
||||
if (!iso_file || !is_iso_file(iso_file))
|
||||
if (!is_iso_file(m_path))
|
||||
{
|
||||
// Not ISO... TODO: throw something?
|
||||
iso_log.error("iso_archive: Failed to recognize ISO file: '%s'", path);
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset the file position after it was changed by is_iso_file()
|
||||
iso_file.seek(0);
|
||||
fs::file iso_file(std::make_unique<iso_file>(m_path));
|
||||
|
||||
u8 descriptor_type = -2;
|
||||
bool use_ucs2_decoding = false;
|
||||
|
||||
+3
-2
@@ -71,7 +71,7 @@ private:
|
||||
static iso_type_status retrieve_key(iso_archive& archive, std::string& key_path, aes_context& aes_ctx);
|
||||
|
||||
public:
|
||||
static iso_type_status check_type(const std::string& path, std::string& key_path, aes_context* aes_ctx = nullptr);
|
||||
static iso_type_status check_type(const std::string& path, std::string* key_path = nullptr, aes_context* aes_ctx = nullptr);
|
||||
|
||||
iso_encryption_type get_enc_type() const { return m_enc_type; }
|
||||
|
||||
@@ -116,7 +116,7 @@ protected:
|
||||
u64 file_offset(u64 pos) const;
|
||||
|
||||
public:
|
||||
iso_file(const std::string& path, bs_t<fs::open_mode> mode);
|
||||
iso_file(const std::string& path, bs_t<fs::open_mode> mode = fs::read);
|
||||
iso_file(const std::string& path, bs_t<fs::open_mode> mode, const iso_fs_node& node);
|
||||
|
||||
explicit operator bool() const { return m_file.operator bool(); }
|
||||
@@ -173,6 +173,7 @@ public:
|
||||
|
||||
const std::string& path() const { return m_path; }
|
||||
const iso_fs_node& root() const { return m_root; }
|
||||
|
||||
iso_fs_node* retrieve(const std::string& path);
|
||||
bool exists(const std::string& path);
|
||||
bool is_file(const std::string& path);
|
||||
|
||||
@@ -605,8 +605,7 @@ void game_list_context_menu::show_single_selection_context_menu(const game_info&
|
||||
// Check integrity
|
||||
if (QString::fromStdString(current_game.category) == cat::cat_disc_game)
|
||||
{
|
||||
std::string key_path;
|
||||
const iso_type_status iso_type = iso_file_decryption::check_type(current_game.path, key_path);
|
||||
const iso_type_status iso_type = iso_file_decryption::check_type(current_game.path);
|
||||
|
||||
// If it's an ISO file (e.g. even a decrypted ISO), always provide the entry on the context menu but disable
|
||||
// it if the ISO does not support integrity check (e.g. non Redump ISO) or no integrity DB is found.
|
||||
|
||||
Reference in New Issue
Block a user