path-util: add helper for extracting last filename from path
This commit is contained in:
parent
77e0a1b5e0
commit
a60c8eee10
|
@ -769,6 +769,37 @@ const char *last_path_component(const char *path) {
|
|||
return path + k;
|
||||
}
|
||||
|
||||
int path_extract_filename(const char *p, char **ret) {
|
||||
_cleanup_free_ char *a = NULL;
|
||||
const char *c, *e = NULL, *q;
|
||||
|
||||
/* Extracts the filename part (i.e. right-most component) from a path, i.e. string that passes
|
||||
* filename_is_valid(). A wrapper around last_path_component(), but eats up trailing slashes. */
|
||||
|
||||
if (!p)
|
||||
return -EINVAL;
|
||||
|
||||
c = last_path_component(p);
|
||||
|
||||
for (q = c; *q != 0; q++)
|
||||
if (*q != '/')
|
||||
e = q + 1;
|
||||
|
||||
if (!e) /* no valid character? */
|
||||
return -EINVAL;
|
||||
|
||||
a = strndup(c, e - c);
|
||||
if (!a)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!filename_is_valid(a))
|
||||
return -EINVAL;
|
||||
|
||||
*ret = TAKE_PTR(a);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool filename_is_valid(const char *p) {
|
||||
const char *e;
|
||||
|
||||
|
|
|
@ -133,6 +133,7 @@ int parse_path_argument_and_warn(const char *path, bool suppress_root, char **ar
|
|||
|
||||
char* dirname_malloc(const char *path);
|
||||
const char *last_path_component(const char *path);
|
||||
int path_extract_filename(const char *p, char **ret);
|
||||
|
||||
bool filename_is_valid(const char *p) _pure_;
|
||||
bool path_is_valid(const char *p) _pure_;
|
||||
|
|
|
@ -425,6 +425,45 @@ static void test_last_path_component(void) {
|
|||
assert_se(streq(last_path_component("/a/"), "a/"));
|
||||
}
|
||||
|
||||
static void test_path_extract_filename_one(const char *input, const char *output, int ret) {
|
||||
_cleanup_free_ char *k = NULL;
|
||||
int r;
|
||||
|
||||
r = path_extract_filename(input, &k);
|
||||
log_info("%s → %s/%s [expected: %s/%s]", strnull(input), strnull(k), strerror(-r), strnull(output), strerror(-ret));
|
||||
assert_se(streq_ptr(k, output));
|
||||
assert_se(r == ret);
|
||||
}
|
||||
|
||||
static void test_path_extract_filename(void) {
|
||||
test_path_extract_filename_one(NULL, NULL, -EINVAL);
|
||||
test_path_extract_filename_one("a/b/c", "c", 0);
|
||||
test_path_extract_filename_one("a/b/c/", "c", 0);
|
||||
test_path_extract_filename_one("/", NULL, -EINVAL);
|
||||
test_path_extract_filename_one("//", NULL, -EINVAL);
|
||||
test_path_extract_filename_one("///", NULL, -EINVAL);
|
||||
test_path_extract_filename_one(".", NULL, -EINVAL);
|
||||
test_path_extract_filename_one("./.", NULL, -EINVAL);
|
||||
test_path_extract_filename_one("././", NULL, -EINVAL);
|
||||
test_path_extract_filename_one("././/", NULL, -EINVAL);
|
||||
test_path_extract_filename_one("/foo/a", "a", 0);
|
||||
test_path_extract_filename_one("/foo/a/", "a", 0);
|
||||
test_path_extract_filename_one("", NULL, -EINVAL);
|
||||
test_path_extract_filename_one("a", "a", 0);
|
||||
test_path_extract_filename_one("a/", "a", 0);
|
||||
test_path_extract_filename_one("/a", "a", 0);
|
||||
test_path_extract_filename_one("/a/", "a", 0);
|
||||
test_path_extract_filename_one("/////////////a/////////////", "a", 0);
|
||||
test_path_extract_filename_one("xx/.", NULL, -EINVAL);
|
||||
test_path_extract_filename_one("xx/..", NULL, -EINVAL);
|
||||
test_path_extract_filename_one("..", NULL, -EINVAL);
|
||||
test_path_extract_filename_one("/..", NULL, -EINVAL);
|
||||
test_path_extract_filename_one("../", NULL, -EINVAL);
|
||||
test_path_extract_filename_one(".", NULL, -EINVAL);
|
||||
test_path_extract_filename_one("/.", NULL, -EINVAL);
|
||||
test_path_extract_filename_one("./", NULL, -EINVAL);
|
||||
}
|
||||
|
||||
static void test_filename_is_valid(void) {
|
||||
char foo[FILENAME_MAX+2];
|
||||
int i;
|
||||
|
@ -543,6 +582,7 @@ int main(int argc, char **argv) {
|
|||
test_prefix_root();
|
||||
test_file_in_same_dir();
|
||||
test_last_path_component();
|
||||
test_path_extract_filename();
|
||||
test_filename_is_valid();
|
||||
test_hidden_or_backup_file();
|
||||
test_skip_dev_prefix();
|
||||
|
|
Loading…
Reference in a new issue