CDImage: Open all image types as shared files

This commit is contained in:
Stenzek 2024-05-17 14:42:37 +10:00
parent c03f1cfeb8
commit c057e91825
No known key found for this signature in database
7 changed files with 46 additions and 62 deletions

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com> // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "cd_image.h" #include "cd_image.h"
@ -6,11 +6,7 @@
#include "common/error.h" #include "common/error.h"
#include "common/file_system.h" #include "common/file_system.h"
#include "common/log.h" #include "common/path.h"
#include <cerrno>
Log_SetChannel(CDImageBin);
namespace { namespace {
@ -50,12 +46,10 @@ CDImageBin::~CDImageBin()
bool CDImageBin::Open(const char* filename, Error* error) bool CDImageBin::Open(const char* filename, Error* error)
{ {
m_filename = filename; m_filename = filename;
m_fp = FileSystem::OpenCFile(filename, "rb"); m_fp = FileSystem::OpenSharedCFile(filename, "rb", FileSystem::FileShareMode::DenyWrite, error);
if (!m_fp) if (!m_fp)
{ {
Log_ErrorPrintf("Failed to open binfile '%s': errno %d", filename, errno); Error::AddPrefixFmt(error, "Failed to open binfile '{}': ", Path::GetFileName(filename));
if (error)
error->SetErrno(errno);
return false; return false;
} }

View file

@ -14,7 +14,6 @@
#include "fmt/format.h" #include "fmt/format.h"
#include <algorithm> #include <algorithm>
#include <cerrno>
#include <cinttypes> #include <cinttypes>
#include <map> #include <map>
@ -60,13 +59,10 @@ CDImageCueSheet::~CDImageCueSheet()
bool CDImageCueSheet::OpenAndParse(const char* filename, Error* error) bool CDImageCueSheet::OpenAndParse(const char* filename, Error* error)
{ {
std::FILE* fp = FileSystem::OpenCFile(filename, "rb"); std::FILE* fp = FileSystem::OpenSharedCFile(filename, "rb", FileSystem::FileShareMode::DenyWrite, error);
if (!fp) if (!fp)
{ {
Log_ErrorPrintf("Failed to open cuesheet '%s': errno %d", filename, errno); Error::AddPrefixFmt(error, "Failed to open cuesheet '{}': ", Path::GetFileName(filename));
if (error)
error->SetErrno(errno);
return false; return false;
} }
@ -123,9 +119,8 @@ bool CDImageCueSheet::OpenAndParse(const char* filename, Error* error)
{ {
Log_ErrorPrintf("Failed to open track filename '%s' (from '%s' and '%s'): %s", track_full_filename.c_str(), Log_ErrorPrintf("Failed to open track filename '%s' (from '%s' and '%s'): %s", track_full_filename.c_str(),
track_filename.c_str(), filename, track_error.GetDescription().c_str()); track_filename.c_str(), filename, track_error.GetDescription().c_str());
Error::SetString(error, Error::SetStringFmt(error, "Failed to open track filename '{}' (from '{}' and '{}'): {}", track_full_filename,
fmt::format("Failed to open track filename '{}' (from '{}' and '{}'): {}", track_full_filename, track_filename, Path::GetFileName(filename), track_error.GetDescription());
track_filename, filename, track_error.GetDescription()));
return false; return false;
} }
@ -156,8 +151,8 @@ bool CDImageCueSheet::OpenAndParse(const char* filename, Error* error)
{ {
Log_ErrorPrintf("Failed to open track %u in '%s': track start is out of range (%u vs %" PRIu64 ")", track_num, Log_ErrorPrintf("Failed to open track %u in '%s': track start is out of range (%u vs %" PRIu64 ")", track_num,
filename, track_start, file_size); filename, track_start, file_size);
Error::SetString(error, fmt::format("Failed to open track {} in '{}': track start is out of range ({} vs {}))", Error::SetStringFmt(error, "Failed to open track {} in '{}': track start is out of range ({} vs {}))",
track_num, filename, track_start, file_size)); track_num, Path::GetFileName(filename), track_start, file_size);
return false; return false;
} }
@ -291,7 +286,7 @@ bool CDImageCueSheet::OpenAndParse(const char* filename, Error* error)
if (m_tracks.empty()) if (m_tracks.empty())
{ {
Log_ErrorPrintf("File '%s' contains no tracks", filename); Log_ErrorPrintf("File '%s' contains no tracks", filename);
Error::SetString(error, fmt::format("File '{}' contains no tracks", filename)); Error::SetStringFmt(error, "File '{}' contains no tracks", Path::GetFileName(filename));
return false; return false;
} }

View file

@ -1,15 +1,18 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com> // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "cd_image.h" #include "cd_image.h"
#include "cd_subchannel_replacement.h" #include "cd_subchannel_replacement.h"
#include "common/assert.h" #include "common/assert.h"
#include "common/error.h" #include "common/error.h"
#include "common/file_system.h" #include "common/file_system.h"
#include "common/log.h" #include "common/log.h"
#include "common/path.h"
#include <array> #include <array>
#include <cerrno>
#include <map> #include <map>
Log_SetChannel(CDImageEcm); Log_SetChannel(CDImageEcm);
// unecm.c by Neill Corlett (c) 2002, GPL licensed // unecm.c by Neill Corlett (c) 2002, GPL licensed
@ -232,13 +235,10 @@ CDImageEcm::~CDImageEcm()
bool CDImageEcm::Open(const char* filename, Error* error) bool CDImageEcm::Open(const char* filename, Error* error)
{ {
m_filename = filename; m_filename = filename;
m_fp = FileSystem::OpenCFile(filename, "rb"); m_fp = FileSystem::OpenSharedCFile(filename, "rb", FileSystem::FileShareMode::DenyWrite, error);
if (!m_fp) if (!m_fp)
{ {
Log_ErrorPrintf("Failed to open binfile '%s': errno %d", filename, errno); Error::AddPrefixFmt(error, "Failed to open binfile '{}': ", Path::GetFileName(filename));
if (error)
error->SetErrno(errno);
return false; return false;
} }
@ -258,7 +258,7 @@ bool CDImageEcm::Open(const char* filename, Error* error)
header[3] != 0) header[3] != 0)
{ {
Log_ErrorPrintf("Failed to read/invalid header"); Log_ErrorPrintf("Failed to read/invalid header");
Error::SetString(error, "Failed to read/invalid header"); Error::SetStringView(error, "Failed to read/invalid header");
return false; return false;
} }
@ -272,7 +272,7 @@ bool CDImageEcm::Open(const char* filename, Error* error)
if (bits == EOF) if (bits == EOF)
{ {
Log_ErrorPrintf("Unexpected EOF after %zu chunks", m_data_map.size()); Log_ErrorPrintf("Unexpected EOF after %zu chunks", m_data_map.size());
Error::SetString(error, fmt::format("Unexpected EOF after {} chunks", m_data_map.size())); Error::SetStringFmt(error, "Unexpected EOF after {} chunks", m_data_map.size());
return false; return false;
} }
@ -286,7 +286,7 @@ bool CDImageEcm::Open(const char* filename, Error* error)
if (bits == EOF) if (bits == EOF)
{ {
Log_ErrorPrintf("Unexpected EOF after %zu chunks", m_data_map.size()); Log_ErrorPrintf("Unexpected EOF after %zu chunks", m_data_map.size());
Error::SetString(error, fmt::format("Unexpected EOF after {} chunks", m_data_map.size())); Error::SetStringFmt(error, "Unexpected EOF after {} chunks", m_data_map.size());
return false; return false;
} }
@ -304,7 +304,7 @@ bool CDImageEcm::Open(const char* filename, Error* error)
if (count >= 0x80000000u) if (count >= 0x80000000u)
{ {
Log_ErrorPrintf("Corrupted header after %zu chunks", m_data_map.size()); Log_ErrorPrintf("Corrupted header after %zu chunks", m_data_map.size());
Error::SetString(error, fmt::format("Corrupted header after {} chunks", m_data_map.size())); Error::SetStringFmt(error, "Corrupted header after {} chunks", m_data_map.size());
return false; return false;
} }
@ -321,7 +321,7 @@ bool CDImageEcm::Open(const char* filename, Error* error)
if (static_cast<s64>(file_offset) > file_size) if (static_cast<s64>(file_offset) > file_size)
{ {
Log_ErrorPrintf("Out of file bounds after %zu chunks", m_data_map.size()); Log_ErrorPrintf("Out of file bounds after %zu chunks", m_data_map.size());
Error::SetString(error, fmt::format("Out of file bounds after {} chunks", m_data_map.size())); Error::SetStringFmt(error, "Out of file bounds after {} chunks", m_data_map.size());
} }
} }
} }
@ -338,7 +338,7 @@ bool CDImageEcm::Open(const char* filename, Error* error)
if (static_cast<s64>(file_offset) > file_size) if (static_cast<s64>(file_offset) > file_size)
{ {
Log_ErrorPrintf("Out of file bounds after %zu chunks", m_data_map.size()); Log_ErrorPrintf("Out of file bounds after %zu chunks", m_data_map.size());
Error::SetString(error, fmt::format("Out of file bounds after {} chunks", m_data_map.size())); Error::SetStringFmt(error, "Out of file bounds after {} chunks", m_data_map.size());
} }
} }
} }
@ -346,8 +346,7 @@ bool CDImageEcm::Open(const char* filename, Error* error)
if (std::fseek(m_fp, file_offset, SEEK_SET) != 0) if (std::fseek(m_fp, file_offset, SEEK_SET) != 0)
{ {
Log_ErrorPrintf("Failed to seek to offset %u after %zu chunks", file_offset, m_data_map.size()); Log_ErrorPrintf("Failed to seek to offset %u after %zu chunks", file_offset, m_data_map.size());
Error::SetString(error, Error::SetStringFmt(error, "Failed to seek to offset {} after {} chunks", file_offset, m_data_map.size());
fmt::format("Failed to seek to offset {} after {} chunks", file_offset, m_data_map.size()));
return false; return false;
} }
} }
@ -355,7 +354,7 @@ bool CDImageEcm::Open(const char* filename, Error* error)
if (m_data_map.empty()) if (m_data_map.empty())
{ {
Log_ErrorPrintf("No data in image '%s'", filename); Log_ErrorPrintf("No data in image '%s'", filename);
Error::SetString(error, fmt::format("No data in image '{}'", filename)); Error::SetStringFmt(error, "No data in image '{}'", filename);
return false; return false;
} }

View file

@ -61,7 +61,7 @@ CDImageM3u::~CDImageM3u() = default;
bool CDImageM3u::Open(const char* path, bool apply_patches, Error* error) bool CDImageM3u::Open(const char* path, bool apply_patches, Error* error)
{ {
std::FILE* fp = FileSystem::OpenCFile(path, "rb"); std::FILE* fp = FileSystem::OpenSharedCFile(path, "rb", FileSystem::FileShareMode::DenyWrite, error);
if (!fp) if (!fp)
return false; return false;

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com> // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "assert.h" #include "assert.h"
@ -71,10 +71,10 @@ CDImageMds::~CDImageMds()
bool CDImageMds::OpenAndParse(const char* filename, Error* error) bool CDImageMds::OpenAndParse(const char* filename, Error* error)
{ {
std::FILE* mds_fp = FileSystem::OpenCFile(filename, "rb", error); std::FILE* mds_fp = FileSystem::OpenSharedCFile(filename, "rb", FileSystem::FileShareMode::DenyWrite, error);
if (!mds_fp) if (!mds_fp)
{ {
Log_ErrorPrintf("Failed to open mds '%s': errno %d", filename, errno); Error::AddPrefixFmt(error, "Failed to open mds '{}': ", Path::GetFileName(filename));
return false; return false;
} }
@ -83,15 +83,15 @@ bool CDImageMds::OpenAndParse(const char* filename, Error* error)
if (!mds_data_opt.has_value() || mds_data_opt->size() < 0x54) if (!mds_data_opt.has_value() || mds_data_opt->size() < 0x54)
{ {
Log_ErrorPrintf("Failed to read mds file '%s'", filename); Log_ErrorPrintf("Failed to read mds file '%s'", filename);
Error::SetString(error, fmt::format("Failed to read mds file '{}'", filename)); Error::SetStringFmt(error, "Failed to read mds file '{}'", filename);
return false; return false;
} }
std::string mdf_filename(Path::ReplaceExtension(filename, "mdf")); std::string mdf_filename(Path::ReplaceExtension(filename, "mdf"));
m_mdf_file = FileSystem::OpenCFile(mdf_filename.c_str(), "rb", error); m_mdf_file = FileSystem::OpenSharedCFile(mdf_filename.c_str(), "rb", FileSystem::FileShareMode::DenyWrite, error);
if (!m_mdf_file) if (!m_mdf_file)
{ {
Log_ErrorPrintf("Failed to open mdf file '%s': errno %d", mdf_filename.c_str(), errno); Error::AddPrefixFmt(error, "Failed to open mdf file '{}': ", Path::GetFileName(mdf_filename));
return false; return false;
} }
@ -100,7 +100,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Error* error)
if (std::memcmp(&mds[0], expected_signature, sizeof(expected_signature) - 1) != 0) if (std::memcmp(&mds[0], expected_signature, sizeof(expected_signature) - 1) != 0)
{ {
Log_ErrorPrintf("Incorrect signature in '%s'", filename); Log_ErrorPrintf("Incorrect signature in '%s'", filename);
Error::SetString(error, fmt::format("Incorrect signature in '{}'", filename)); Error::SetStringFmt(error, "Incorrect signature in '{}'", Path::GetFileName(filename));
return false; return false;
} }
@ -109,7 +109,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Error* error)
if ((session_offset + 24) > mds.size()) if ((session_offset + 24) > mds.size())
{ {
Log_ErrorPrintf("Invalid session offset in '%s'", filename); Log_ErrorPrintf("Invalid session offset in '%s'", filename);
Error::SetString(error, fmt::format("Invalid session offset in '{}'", filename)); Error::SetStringFmt(error, "Invalid session offset in '{}'", Path::GetFileName(filename));
return false; return false;
} }
@ -120,8 +120,8 @@ bool CDImageMds::OpenAndParse(const char* filename, Error* error)
if (track_count > 99 || track_offset >= mds.size()) if (track_count > 99 || track_offset >= mds.size())
{ {
Log_ErrorPrintf("Invalid track count/block offset %u/%u in '%s'", track_count, track_offset, filename); Log_ErrorPrintf("Invalid track count/block offset %u/%u in '%s'", track_count, track_offset, filename);
Error::SetString( Error::SetStringFmt(error, "Invalid track count/block offset {}/{} in '{}'", track_count, track_offset,
error, fmt::format("Invalid track count/block offset {}/{} in '{}'", track_count, track_offset, filename)); Path::GetFileName(filename));
return false; return false;
} }
@ -140,7 +140,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Error* error)
if ((track_offset + sizeof(TrackEntry)) > mds.size()) if ((track_offset + sizeof(TrackEntry)) > mds.size())
{ {
Log_ErrorPrintf("End of file in '%s' at track %u", filename, track_number); Log_ErrorPrintf("End of file in '%s' at track %u", filename, track_number);
Error::SetString(error, fmt::format("End of file in '{}' at track {}", filename, track_number)); Error::SetStringFmt(error, "End of file in '{}' at track {}", Path::GetFileName(filename), track_number);
return false; return false;
} }
@ -151,8 +151,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Error* error)
if (PackedBCDToBinary(track.track_number) != track_number) if (PackedBCDToBinary(track.track_number) != track_number)
{ {
Log_ErrorPrintf("Unexpected track number 0x%02X in track %u", track.track_number, track_number); Log_ErrorPrintf("Unexpected track number 0x%02X in track %u", track.track_number, track_number);
Error::SetString(error, Error::SetStringFmt(error, "Unexpected track number 0x{:02X} in track {}", track.track_number, track_number);
fmt::format("Unexpected track number 0x{:02X} in track {}", track.track_number, track_number));
return false; return false;
} }
@ -163,7 +162,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Error* error)
if ((track.extra_offset + sizeof(u32) + sizeof(u32)) > mds.size()) if ((track.extra_offset + sizeof(u32) + sizeof(u32)) > mds.size())
{ {
Log_ErrorPrintf("Invalid extra offset %u in track %u", track.extra_offset, track_number); Log_ErrorPrintf("Invalid extra offset %u in track %u", track.extra_offset, track_number);
Error::SetString(error, fmt::format("Invalid extra offset {} in track {}", track.extra_offset, track_number)); Error::SetStringFmt(error, "Invalid extra offset {} in track {}", track.extra_offset, track_number);
return false; return false;
} }
@ -186,8 +185,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Error* error)
if (track_pregap > track_start_lba) if (track_pregap > track_start_lba)
{ {
Log_ErrorPrintf("Track pregap %u is too large for start lba %u", track_pregap, track_start_lba); Log_ErrorPrintf("Track pregap %u is too large for start lba %u", track_pregap, track_start_lba);
Error::SetString(error, Error::SetStringFmt(error, "Track pregap {} is too large for start lba {}", track_pregap, track_start_lba);
fmt::format("Track pregap {} is too large for start lba {}", track_pregap, track_start_lba));
return false; return false;
} }
@ -238,7 +236,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Error* error)
if (m_tracks.empty()) if (m_tracks.empty())
{ {
Log_ErrorPrintf("File '%s' contains no tracks", filename); Log_ErrorPrintf("File '%s' contains no tracks", filename);
Error::SetString(error, fmt::format("File '{}' contains no tracks", filename)); Error::SetStringFmt(error, "File '{}' contains no tracks", Path::GetFileName(filename));
return false; return false;
} }

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com> and contributors. // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com> and contributors.
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "cd_image.h" #include "cd_image.h"
@ -403,12 +403,10 @@ bool CDImagePBP::IsValidEboot(Error* error)
bool CDImagePBP::Open(const char* filename, Error* error) bool CDImagePBP::Open(const char* filename, Error* error)
{ {
m_file = FileSystem::OpenCFile(filename, "rb"); m_file = FileSystem::OpenSharedCFile(filename, "rb", FileSystem::FileShareMode::DenyWrite, error);
if (!m_file) if (!m_file)
{ {
if (error) Error::AddPrefixFmt(error, "Failed to open '{}': ", Path::GetFileName(filename));
error->SetErrno(errno);
return false; return false;
} }

View file

@ -66,7 +66,7 @@ CDImagePPF::~CDImagePPF() = default;
bool CDImagePPF::Open(const char* filename, std::unique_ptr<CDImage> parent_image) bool CDImagePPF::Open(const char* filename, std::unique_ptr<CDImage> parent_image)
{ {
auto fp = FileSystem::OpenManagedCFile(filename, "rb"); auto fp = FileSystem::OpenManagedSharedCFile(filename, "rb", FileSystem::FileShareMode::DenyWrite);
if (!fp) if (!fp)
{ {
Log_ErrorPrintf("Failed to open '%s'", filename); Log_ErrorPrintf("Failed to open '%s'", filename);