diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2021-02-18 13:43:23 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2021-02-23 10:56:53 +1000 |
commit | 671eb8cbbb4dc5c88d38c935c176d61604154584 (patch) | |
tree | 5c5c00feea0c24c16ca73d1fbc83a340dc6a96fa | |
parent | fd9d165a7724dd518f4ad2a92187637130345389 (diff) |
utils: add a safe version of basename
So we don't need to worry about the libgen.h include game.
And we can switch trunkname over to that, making it a bit simpler.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
-rw-r--r-- | src/util-strings.c | 44 | ||||
-rw-r--r-- | src/util-strings.h | 3 | ||||
-rw-r--r-- | test/test-utils.c | 31 |
3 files changed, 66 insertions, 12 deletions
diff --git a/src/util-strings.c b/src/util-strings.c index 3e174806..7d4c4628 100644 --- a/src/util-strings.c +++ b/src/util-strings.c @@ -157,6 +157,30 @@ strv_join(char **strv, const char *joiner) } /** + * Return a pointer to the basename within filename. + * If the filename the empty string or a directory (i.e. the last char of + * filename is '/') NULL is returned. + */ +const char * +safe_basename(const char *filename) +{ + const char *basename; + + if (*filename == '\0') + return NULL; + + basename = strrchr(filename, '/'); + if (basename == NULL) + return filename; + + if (*(basename + 1) == '\0') + return NULL; + + return basename + 1; +} + + +/** * Similar to basename() but returns the trunk only without the (last) * trailing suffix, so that: * @@ -170,19 +194,15 @@ strv_join(char **strv, const char *joiner) char * trunkname(const char *filename) { - /* See basename(3), there are two versions and they depend on - * whether libgen.h is included. We can't be sure which basename() - * applies here, so let's play it safe and assume it's the POSIX - * one. */ - char *tmp = strdup(filename); - char *base = basename(tmp); + const char *base = safe_basename(filename); char *suffix; - char *trunk; - if ((suffix = rindex(base, '.'))) - *suffix = '\0'; + if (base == NULL) + return strdup(""); - trunk = strdup(base); - free(tmp); - return trunk; + suffix = rindex(base, '.'); + if (suffix == NULL) + return strdup(base); + else + return strndup(base, suffix-base); } diff --git a/src/util-strings.h b/src/util-strings.h index ad007f69..9d044067 100644 --- a/src/util-strings.h +++ b/src/util-strings.h @@ -392,5 +392,8 @@ strstartswith(const char *str, const char *prefix) return prefixlen > 0 ? strneq(str, prefix, strlen(prefix)) : false; } +const char * +safe_basename(const char *filename); + char * trunkname(const char *filename); diff --git a/test/test-utils.c b/test/test-utils.c index f31b2e07..dbd58031 100644 --- a/test/test-utils.c +++ b/test/test-utils.c @@ -1292,6 +1292,35 @@ START_TEST(strneq_test) } END_TEST +START_TEST(basename_test) +{ + struct test { + const char *path; + const char *expected; + } tests[] = { + { "a", "a" }, + { "foo.c", "foo.c" }, + { "foo", "foo" }, + { "/path/to/foo.h", "foo.h" }, + { "../bar.foo", "bar.foo" }, + { "./bar.foo.baz", "bar.foo.baz" }, + { "./", NULL }, + { "/", NULL }, + { "/bar/", NULL }, + { "/bar", "bar" }, + { "", NULL }, + }; + struct test *t; + + ARRAY_FOR_EACH(tests, t) { + const char *result = safe_basename(t->path); + if (t->expected == NULL) + ck_assert(result == NULL); + else + ck_assert_str_eq(result, t->expected); + } +} +END_TEST START_TEST(trunkname_test) { struct test { @@ -1300,6 +1329,7 @@ START_TEST(trunkname_test) } tests[] = { { "foo.c", "foo" }, { "/path/to/foo.h", "foo" }, + { "/path/to/foo", "foo" }, { "../bar.foo", "bar" }, { "./bar.foo.baz", "bar.foo" }, { "./", "" }, @@ -1362,6 +1392,7 @@ litest_utils_suite(void) tcase_add_test(tc, streq_test); tcase_add_test(tc, strneq_test); tcase_add_test(tc, trunkname_test); + tcase_add_test(tc, basename_test); suite_add_tcase(s, tc); |