diff --git a/src/common/cd_image_cue.cpp b/src/common/cd_image_cue.cpp index a6c3e56d5..cc41ddab6 100644 --- a/src/common/cd_image_cue.cpp +++ b/src/common/cd_image_cue.cpp @@ -46,15 +46,18 @@ CDImageCueSheet::~CDImageCueSheet() bool CDImageCueSheet::OpenAndParse(const char* filename) { - std::FILE* cue_fp = FileSystem::OpenCFile(filename, "rb"); - if (!cue_fp) + std::optional cuesheet_string = FileSystem::ReadFileToString(filename); + if (!cuesheet_string.has_value()) { Log_ErrorPrintf("Failed to open cuesheet '%s': errno %d", filename, errno); return false; } - m_cd = cue_parse_file(cue_fp); - std::fclose(cue_fp); + // work around cuesheet parsing issue - ensure the last character is a newline. + if (!cuesheet_string->empty() && cuesheet_string->at(cuesheet_string->size() - 1) != '\n') + *cuesheet_string += '\n'; + + m_cd = cue_parse_string(cuesheet_string->c_str()); if (!m_cd) { Log_ErrorPrintf("Failed to parse cuesheet '%s'", filename); diff --git a/src/common/file_system.cpp b/src/common/file_system.cpp index 2cd17ba1d..358c74d21 100644 --- a/src/common/file_system.cpp +++ b/src/common/file_system.cpp @@ -452,6 +452,26 @@ std::optional> ReadBinaryFile(const char* filename) return res; } +std::optional ReadFileToString(const char* filename) +{ + ManagedCFilePtr fp = OpenManagedCFile(filename, "rb"); + if (!fp) + return std::nullopt; + + std::fseek(fp.get(), 0, SEEK_END); + long size = std::ftell(fp.get()); + std::fseek(fp.get(), 0, SEEK_SET); + if (size < 0) + return std::nullopt; + + std::string res; + res.resize(static_cast(size)); + if (size > 0 && std::fread(res.data(), 1u, static_cast(size), fp.get()) != static_cast(size)) + return std::nullopt; + + return res; +} + bool WriteBinaryFile(const char* filename, const void* data, size_t data_length) { ManagedCFilePtr fp = OpenManagedCFile(filename, "wb"); @@ -464,6 +484,18 @@ bool WriteBinaryFile(const char* filename, const void* data, size_t data_length) return true; } +bool WriteFileToString(const char* filename, const std::string_view& sv) +{ + ManagedCFilePtr fp = OpenManagedCFile(filename, "wb"); + if (!fp) + return false; + + if (sv.length() > 0 && std::fwrite(sv.data(), 1u, sv.length(), fp.get()) != sv.length()) + return false; + + return true; +} + void BuildOSPath(char* Destination, u32 cbDestination, const char* Path) { u32 i; diff --git a/src/common/file_system.h b/src/common/file_system.h index 733467fee..757c3d551 100644 --- a/src/common/file_system.h +++ b/src/common/file_system.h @@ -173,7 +173,9 @@ ManagedCFilePtr OpenManagedCFile(const char* filename, const char* mode); std::FILE* OpenCFile(const char* filename, const char* mode); std::optional> ReadBinaryFile(const char* filename); +std::optional ReadFileToString(const char* filename); bool WriteBinaryFile(const char* filename, const void* data, size_t data_length); +bool WriteFileToString(const char* filename, const std::string_view& sv); // creates a directory in the local filesystem // if the directory already exists, the return value will be true.