diff --git a/options/path.c b/options/path.c index a17d8b4325..9c996ce664 100644 --- a/options/path.c +++ b/options/path.c @@ -254,6 +254,23 @@ char *mp_splitext(const char *path, bstr *root) return (char *)split + 1; } +bool mp_path_is_absolute(struct bstr path) +{ + if (path.len && strchr(mp_path_separators, path.start[0])) + return true; + +#if HAVE_DOS_PATHS + // Note: "X:filename" is a path relative to the current working directory + // of drive X, and thus is not an absolute path. It needs to be + // followed by \ or /. + if (path.len >= 3 && path.start[1] == ':' && + strchr(mp_path_separators, path.start[2])) + return true; +#endif + + return false; +} + char *mp_path_join_bstr(void *talloc_ctx, struct bstr p1, struct bstr p2) { if (p1.len == 0) @@ -261,16 +278,7 @@ char *mp_path_join_bstr(void *talloc_ctx, struct bstr p1, struct bstr p2) if (p2.len == 0) return bstrdup0(talloc_ctx, p1); - bool is_absolute = strchr(mp_path_separators, p2.start[0]); -#if HAVE_DOS_PATHS - // Note: "X:filename" is a path relative to the current working directory - // of drive X, and thus is not an absolute path. It needs to be - // followed by \ or /. - if (p2.len >= 3 && p2.start[1] == ':' && - strchr(mp_path_separators, p2.start[2])) - is_absolute = true; -#endif - if (is_absolute) + if (mp_path_is_absolute(p2)) return bstrdup0(talloc_ctx, p2); bool have_separator = strchr(mp_path_separators, p1.start[p1.len - 1]); diff --git a/options/path.h b/options/path.h index c3c3699a0b..19f4fb5909 100644 --- a/options/path.h +++ b/options/path.h @@ -77,6 +77,9 @@ void mp_path_strip_trailing_separator(char *path); char *mp_path_join(void *talloc_ctx, const char *p1, const char *p2); char *mp_path_join_bstr(void *talloc_ctx, struct bstr p1, struct bstr p2); +// Return whether the path is absolute. +bool mp_path_is_absolute(struct bstr path); + char *mp_getcwd(void *talloc_ctx); bool mp_path_exists(const char *path); diff --git a/test/paths.c b/test/paths.c index 434a7996ad..66d4ee2e2d 100644 --- a/test/paths.c +++ b/test/paths.c @@ -14,11 +14,25 @@ static void test_join(char *file, int line, char *a, char *b, char *c) talloc_free(res); } +static void test_abs(char *file, int line, bool abs, char *a) +{ + if (mp_path_is_absolute(bstr0(a)) != abs) { + printf("%s:%d: mp_path_is_absolute('%s') => %d, expected %d\n", + file, line, a, !abs, abs); + abort(); + } +} + #define TEST_JOIN(a, b, c) \ test_join(__FILE__, __LINE__, a, b, c); +#define TEST_ABS(abs, a) \ + test_abs(__FILE__, __LINE__, abs, a) + static void run(struct test_ctx *ctx) { + TEST_ABS(true, "/ab"); + TEST_ABS(false, "ab"); TEST_JOIN("", "", ""); TEST_JOIN("a", "", "a"); TEST_JOIN("/a", "", "/a"); @@ -29,6 +43,12 @@ static void run(struct test_ctx *ctx) TEST_JOIN("ab/", "/cd", "/cd"); // Note: we prefer "/" on win32, but tolerate "\". #if HAVE_DOS_PATHS + TEST_ABS(true, "\\ab"); + TEST_ABS(true, "c:\\"); + TEST_ABS(true, "c:/"); + TEST_ABS(false, "c:"); + TEST_ABS(false, "c:a"); + TEST_ABS(false, "c:a\\"); TEST_JOIN("ab\\", "cd", "ab\\cd"); TEST_JOIN("ab\\", "\\cd", "\\cd"); TEST_JOIN("c:/", "de", "c:/de");