Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Nevada-Foxx crash on Linux/Webassembly platform #325

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

roginvs
Copy link
Contributor

@roginvs roginvs commented Oct 9, 2023

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;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant