fallout2-ce
fallout2-ce copied to clipboard
Fix Nevada-Foxx crash on Linux/Webassembly platform
In current implementation we assume that compat_splitpath will receive files with / when we are running on Linux platform. This is mostly true except cases when path is originated from ddraw.ini. Here is example from "Nevada build by Foxx":
[Scripts]
GlobalScriptPaths=scripts\gl*.int,mods\sFall\gl*.int
NOTE: One should run this on case-insensitive file system or rename folders according to configuration. No folder - no bug and no global scripts of course.
So, in this PR we use another compat_splitpath implementation which works on both / and \
Here are unit tests for this, it will be good to include them directly into codebase and setup CI check (do you have any ideas how to make it?)
#include <stdio.h>
#include <string.h>
#define COMPAT_MAX_DRIVE 3
#define COMPAT_MAX_DIR 256
#define COMPAT_MAX_FNAME 256
#define COMPAT_MAX_EXT 256
void compat_splitpath(const char* path, char* drive, char* dir, char* fname, char* ext);
// A macro to compare the expected and actual values
#define ASSERT_EQUAL_STR(expected, actual) \
if (strcmp(expected, actual) != 0) { \
printf("FAILURE: Expected '%s', got '%s'\n", expected, actual); \
return 0; \
}
int test1()
{
char drive[COMPAT_MAX_DRIVE];
char dir[COMPAT_MAX_DIR];
char fname[COMPAT_MAX_FNAME];
char ext[COMPAT_MAX_EXT];
compat_splitpath("/path/to/file.txt", drive, dir, fname, ext);
ASSERT_EQUAL_STR("", drive);
ASSERT_EQUAL_STR("/path/to/", dir);
ASSERT_EQUAL_STR("file", fname);
ASSERT_EQUAL_STR(".txt", ext);
printf("Test1 PASSED\n");
return 1;
}
int test2()
{
char drive[COMPAT_MAX_DRIVE];
char dir[COMPAT_MAX_DIR];
char fname[COMPAT_MAX_FNAME];
char ext[COMPAT_MAX_EXT];
compat_splitpath("C:\\path\\to\\file.txt", drive, dir, fname, ext);
ASSERT_EQUAL_STR("C:", drive);
ASSERT_EQUAL_STR("\\path\\to\\", dir);
ASSERT_EQUAL_STR("file", fname);
ASSERT_EQUAL_STR(".txt", ext);
printf("Test2 PASSED\n");
return 1;
}
int test3()
{
char drive[COMPAT_MAX_DRIVE];
char dir[COMPAT_MAX_DIR];
char fname[COMPAT_MAX_FNAME];
char ext[COMPAT_MAX_EXT];
compat_splitpath("file.txt", drive, dir, fname, ext);
ASSERT_EQUAL_STR("", drive);
ASSERT_EQUAL_STR("", dir);
ASSERT_EQUAL_STR("file", fname);
ASSERT_EQUAL_STR(".txt", ext);
printf("Test3 PASSED\n");
return 1;
}
int test_no_disk()
{
char drive[COMPAT_MAX_DRIVE];
char dir[COMPAT_MAX_DIR];
char fname[COMPAT_MAX_FNAME];
char ext[COMPAT_MAX_EXT];
compat_splitpath("\\path\\without\\disk\\file.txt", drive, dir, fname, ext);
ASSERT_EQUAL_STR("", drive);
ASSERT_EQUAL_STR("\\path\\without\\disk\\", dir);
ASSERT_EQUAL_STR("file", fname);
ASSERT_EQUAL_STR(".txt", ext);
printf("Test_no_disk PASSED\n");
return 1;
}
int test_no_leading_backslash()
{
char drive[COMPAT_MAX_DRIVE];
char dir[COMPAT_MAX_DIR];
char fname[COMPAT_MAX_FNAME];
char ext[COMPAT_MAX_EXT];
compat_splitpath("path\\without\\leading\\file.txt", drive, dir, fname, ext);
ASSERT_EQUAL_STR("", drive);
ASSERT_EQUAL_STR("path\\without\\leading\\", dir);
ASSERT_EQUAL_STR("file", fname);
ASSERT_EQUAL_STR(".txt", ext);
printf("Test_no_leading_backslash PASSED\n");
return 1;
}
int test_dot_in_filename()
{
char drive[COMPAT_MAX_DRIVE];
char dir[COMPAT_MAX_DIR];
char fname[COMPAT_MAX_FNAME];
char ext[COMPAT_MAX_EXT];
compat_splitpath("/path/with/dotted.file.txt", drive, dir, fname, ext);
ASSERT_EQUAL_STR("", drive);
ASSERT_EQUAL_STR("/path/with/", dir);
ASSERT_EQUAL_STR("dotted.file", fname);
ASSERT_EQUAL_STR(".txt", ext);
printf("Test_dot_in_filename PASSED\n");
return 1;
}
int test_no_extension()
{
char drive[COMPAT_MAX_DRIVE];
char dir[COMPAT_MAX_DIR];
char fname[COMPAT_MAX_FNAME];
char ext[COMPAT_MAX_EXT];
compat_splitpath("/path/with/noextensionfile", drive, dir, fname, ext);
ASSERT_EQUAL_STR("", drive);
ASSERT_EQUAL_STR("/path/with/", dir);
ASSERT_EQUAL_STR("noextensionfile", fname);
ASSERT_EQUAL_STR("", ext);
printf("Test_no_extension PASSED\n");
return 1;
}
int main()
{
if (!test1()) return 1;
if (!test2()) return 1;
if (!test3()) return 1;
if (!test_no_disk()) return 1;
if (!test_no_leading_backslash()) return 1;
if (!test_dot_in_filename()) return 1;
if (!test_no_extension()) return 1;
printf("All tests passed.\n");
return 0;
}