1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-16 03:23:15 +01:00

Fix #5507: RCT1 path check is case-sensitive on Linux

If the csg path does not exist, find the first file in the directory that matches (case insensitive).
This commit is contained in:
Ted John
2017-06-30 20:38:51 +01:00
parent 9b2777bc56
commit e9519d2d8b
3 changed files with 90 additions and 23 deletions

View File

@@ -14,6 +14,10 @@
*****************************************************************************/
#pragma endregion
#ifndef _WIN32
#include <dirent.h>
#endif
extern "C"
{
#include "../platform/platform.h"
@@ -21,6 +25,7 @@ extern "C"
#include "../util/util.h"
}
#include "File.h"
#include "Math.hpp"
#include "Memory.hpp"
#include "Path.hpp"
@@ -218,4 +223,45 @@ namespace Path
#endif
return String::Equals(a, b, ignoreCase);
}
std::string ResolveCasing(const std::string &path)
{
std::string result;
if (File::Exists(path))
{
// Windows is case insensitive so it will exist and that is all that matters
// for now. We can properly resolve the casing if we ever need to.
result = path;
}
#ifndef _WIN32
else
{
std::string fileName = Path::GetFileName(path);
std::string directory = Path::GetDirectory(path);
struct dirent * * files;
auto count = scandir(directory.c_str(), &files, nullptr, alphasort);
if (count != -1)
{
// Find a file which matches by name (case insensitive)
for (sint32 i = 0; i < count; i++)
{
if (String::Equals(files[i]->d_name, fileName.c_str(), true))
{
result = Path::Combine(directory, std::string(files[i]->d_name));
break;
}
}
// Free memory
for (sint32 i = 0; i < count; i++)
{
free(files[i]);
}
free(files);
}
}
#endif
return result;
}
}

View File

@@ -43,4 +43,12 @@ namespace Path
utf8 * GetAbsolute(utf8 * buffer, size_t bufferSize, const utf8 * relativePath);
bool Equals(const std::string &a, const std::string &b);
bool Equals(const utf8 * a, const utf8 * b);
/**
* Checks if the given path is a file. If not, checks to see if
* there are any files with different casing and selects the first
* one found based on a straight forward character sort.
* Note: This will not resolve the case for Windows.
*/
std::string ResolveCasing(const std::string &path);
}

View File

@@ -21,6 +21,7 @@
#include "../core/File.h"
#include "../core/FileStream.hpp"
#include "../core/Memory.hpp"
#include "../core/Path.hpp"
#include "../core/Util.hpp"
#include "../OpenRCT2.h"
#include "../sprites.h"
@@ -188,6 +189,37 @@ extern "C"
return false;
}
static utf8 * gfx_get_csg_header_path()
{
char path[MAX_PATH];
safe_strcpy(path, gConfigGeneral.rct1_path, sizeof(path));
safe_strcat_path(path, "Data", sizeof(path));
safe_strcat_path(path, "csg1i.dat", sizeof(path));
return String::Duplicate(Path::ResolveCasing(path));
}
static utf8 * gfx_get_csg_data_path()
{
// csg1.1 and csg1.dat are the same file.
// In the CD version, it's called csg1.1 on the CD and csg1.dat on the disk.
// In the GOG version, it's always called csg1.1.
// In the Steam version, it's always called csg1.dat.
char path[MAX_PATH];
safe_strcpy(path, gConfigGeneral.rct1_path, sizeof(path));
safe_strcat_path(path, "Data", sizeof(path));
safe_strcat_path(path, "csg1.1", sizeof(path));
auto fixedPath = Path::ResolveCasing(path);
if (fixedPath.empty())
{
safe_strcpy(path, gConfigGeneral.rct1_path, sizeof(path));
safe_strcat_path(path, "Data", sizeof(path));
safe_strcat_path(path, "csg1.dat", sizeof(path));
fixedPath = Path::ResolveCasing(path);
}
return String::Duplicate(fixedPath);
}
bool gfx_load_csg()
{
log_verbose("gfx_load_csg()");
@@ -198,31 +230,12 @@ extern "C"
return false;
}
char pathHeader[MAX_PATH];
safe_strcpy(pathHeader, gConfigGeneral.rct1_path, sizeof(pathHeader));
safe_strcat_path(pathHeader, "Data", sizeof(pathHeader));
safe_strcat_path(pathHeader, "csg1i.dat", sizeof(pathHeader));
// csg1.1 and csg1.dat are the same file.
// In the CD version, it's called csg1.1 on the CD and csg1.dat on the disk.
// In the GOG version, it's always called csg1.1.
// In the Steam version, it's always called csg1.dat.
char pathData[MAX_PATH];
safe_strcpy(pathData, gConfigGeneral.rct1_path, sizeof(pathData));
safe_strcat_path(pathData, "Data", sizeof(pathData));
safe_strcat_path(pathData, "csg1.1", sizeof(pathData));
if (!File::Exists(pathData))
{
safe_strcpy(pathData, gConfigGeneral.rct1_path, sizeof(pathData));
safe_strcat_path(pathData, "Data", sizeof(pathData));
safe_strcat_path(pathData, "csg1.dat", sizeof(pathData));
}
auto pathHeaderPath = std::unique_ptr<utf8>(gfx_get_csg_header_path());
auto pathDataPath = std::unique_ptr<utf8>(gfx_get_csg_data_path());
try
{
auto fileHeader = FileStream(pathHeader, FILE_MODE_OPEN);
auto fileData = FileStream(pathData, FILE_MODE_OPEN);
auto fileHeader = FileStream(pathHeaderPath.get(), FILE_MODE_OPEN);
auto fileData = FileStream(pathDataPath.get(), FILE_MODE_OPEN);
size_t fileHeaderSize = fileHeader.GetLength();
size_t fileDataSize = fileData.GetLength();