diff --git a/common/path.c b/common/path.c index 17a6230..d0d1893 100644 --- a/common/path.c +++ b/common/path.c @@ -94,15 +94,21 @@ p11_path_base (const char *path) } static inline bool -is_path_component_or_null (char ch) +is_path_separator (char ch) { - return (ch == '\0' || ch == '/' + return (ch == '/' #ifdef OS_WIN32 || ch == '\\' #endif ); } +static inline bool +is_path_separator_or_null (char ch) +{ + return is_path_separator (ch) || ch == '\0'; +} + static char * expand_homedir (const char *remainder) { @@ -113,7 +119,7 @@ expand_homedir (const char *remainder) return NULL; } - while (remainder[0] && is_path_component_or_null (remainder[0])) + while (is_path_separator (remainder[0])) remainder++; if (remainder[0] == '\0') remainder = NULL; @@ -121,7 +127,7 @@ expand_homedir (const char *remainder) /* Expand $XDG_CONFIG_HOME */ if (remainder != NULL && strncmp (remainder, ".config", 7) == 0 && - is_path_component_or_null (remainder[7])) { + is_path_separator_or_null (remainder[7])) { env = getenv ("XDG_CONFIG_HOME"); if (env && env[0]) return p11_path_build (env, remainder + 8, NULL); @@ -174,7 +180,7 @@ p11_path_expand (const char *path) return_val_if_fail (path != NULL, NULL); if (strncmp (path, "~", 1) == 0 && - is_path_component_or_null (path[1])) { + is_path_separator_or_null (path[1])) { return expand_homedir (path + 1); } else { @@ -235,15 +241,27 @@ p11_path_build (const char *path, while (path != NULL) { num = strlen (path); + /* Trim beginning of path */ + while (is_path_separator (path[0])) { + /* But preserve the leading path component */ + if (!at && !is_path_separator (path[1])) + break; + path++; + num--; + } + /* Trim end of the path */ until = (at > 0) ? 0 : 1; - while (num > until && is_path_component_or_null (path[num - 1])) + while (num > until && is_path_separator_or_null (path[num - 1])) num--; if (at != 0) { - if (num == 0) + if (num == 0) { + path = va_arg (va, const char *); continue; - built[at++] = delim; + } + if (built[at - 1] != delim) + built[at++] = delim; } assert (at + num < len); @@ -251,10 +269,6 @@ p11_path_build (const char *path, at += num; path = va_arg (va, const char *); - - /* Trim beginning of path */ - while (path && path[0] && is_path_component_or_null (path[0])) - path++; } va_end (va); @@ -274,17 +288,17 @@ p11_path_parent (const char *path) /* Find the end of the last component */ e = path + strlen (path); - while (e != path && is_path_component_or_null (*e)) + while (e != path && is_path_separator_or_null (*e)) e--; /* Find the beginning of the last component */ - while (e != path && !is_path_component_or_null (*e)) { + while (e != path && !is_path_separator_or_null (*e)) { had = true; e--; } /* Find the end of the last component */ - while (e != path && is_path_component_or_null (*e)) + while (e != path && is_path_separator_or_null (*e)) e--; if (e == path) { @@ -313,7 +327,7 @@ p11_path_prefix (const char *string, return a > b && strncmp (string, prefix, b) == 0 && - is_path_component_or_null (string[b]); + is_path_separator_or_null (string[b]); } void diff --git a/common/test-path.c b/common/test-path.c index 2eb5444..cf4a8e3 100644 --- a/common/test-path.c +++ b/common/test-path.c @@ -88,23 +88,49 @@ static void test_build (void) { #ifdef OS_UNIX + assert_str_eq_free ("/", + p11_path_build ("/", NULL)); + assert_str_eq_free ("/", + p11_path_build ("", "//", NULL)); + assert_str_eq_free ("/root", + p11_path_build ("///root///", NULL)); + assert_str_eq_free ("/root", + p11_path_build ("/", "root", NULL)); + assert_str_eq_free ("/root", + p11_path_build ("", "/root", NULL)); + assert_str_eq_free ("/root", + p11_path_build ("/root", "", NULL)); assert_str_eq_free ("/root/second", p11_path_build ("/root", "second", NULL)); assert_str_eq_free ("/root/second", p11_path_build ("/root", "/second", NULL)); assert_str_eq_free ("/root/second", p11_path_build ("/root/", "second", NULL)); + assert_str_eq_free ("/root/second", + p11_path_build ("/root//", "//second/", NULL)); + assert_str_eq_free ("/root/second", + p11_path_build ("/root//", "", "//second/", NULL)); assert_str_eq_free ("/root/second/third", p11_path_build ("/root", "second", "third", NULL)); assert_str_eq_free ("/root/second/third", p11_path_build ("/root", "/second/third", NULL)); #else /* OS_WIN32 */ + assert_str_eq_free ("C:\\root", + p11_path_build ("C:\\", "root", NULL)); + assert_str_eq_free ("C:\\root", + p11_path_build ("", "C:\\root", NULL)); + assert_str_eq_free ("C:\\root", + p11_path_build ("C:\\root", "", NULL)); assert_str_eq_free ("C:\\root\\second", p11_path_build ("C:\\root", "second", NULL)); assert_str_eq_free ("C:\\root\\second", p11_path_build ("C:\\root", "\\second", NULL)); assert_str_eq_free ("C:\\root\\second", p11_path_build ("C:\\root\\", "second", NULL)); + assert_str_eq_free ("C:\\root\\second", + p11_path_build ("C:\\root\\\\", "\\\\second", NULL)); + assert_str_eq_free ("C:\\root\\second", + p11_path_build ("C:\\root\\\\", "", "\\\\second", NULL)); assert_str_eq_free ("C:\\root\\second\\third", p11_path_build ("C:\\root", "second", "third", NULL)); assert_str_eq_free ("C:\\root\\second/third",