From: Ludwig Nussel Date: Mon, 9 Jan 2023 16:58:57 +0000 (+0100) Subject: chase-symlinks: new chase_symlinks_and_unlink() X-Git-Tag: v253-rc1~66^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1132fd73b32a06c6349f20c0cfb235cc854a1a3a;p=thirdparty%2Fsystemd.git chase-symlinks: new chase_symlinks_and_unlink() --- diff --git a/src/basic/chase-symlinks.c b/src/basic/chase-symlinks.c index a0134fd330b..4cc0a01df8e 100644 --- a/src/basic/chase-symlinks.c +++ b/src/basic/chase-symlinks.c @@ -689,3 +689,42 @@ int chase_symlinks_and_fopen_unlocked( return 0; } + +int chase_symlinks_and_unlink( + const char *path, + const char *root, + ChaseSymlinksFlags chase_flags, + int unlink_flags, + char **ret_path) { + + _cleanup_free_ char *p = NULL, *rp = NULL, *dir = NULL, *fname = NULL; + _cleanup_close_ int fd = -1; + int r; + + assert(path); + + r = path_extract_directory(path, &dir); + if (r < 0) + return r; + r = path_extract_filename(path, &fname); + if (r < 0) + return r; + + fd = chase_symlinks_and_open(dir, root, chase_flags, O_PATH|O_DIRECTORY|O_CLOEXEC, ret_path ? &p : NULL); + if (fd < 0) + return fd; + + if (p) { + rp = path_join(p, fname); + if (!rp) + return -ENOMEM; + } + + if (unlinkat(fd, fname, unlink_flags) < 0) + return -errno; + + if (ret_path) + *ret_path = TAKE_PTR(rp); + + return 0; +} diff --git a/src/basic/chase-symlinks.h b/src/basic/chase-symlinks.h index af0fcf155a2..be5e2bb6965 100644 --- a/src/basic/chase-symlinks.h +++ b/src/basic/chase-symlinks.h @@ -34,5 +34,6 @@ int chase_symlinks_and_opendir(const char *path, const char *root, ChaseSymlinks int chase_symlinks_and_stat(const char *path, const char *root, ChaseSymlinksFlags chase_flags, char **ret_path, struct stat *ret_stat, int *ret_fd); int chase_symlinks_and_access(const char *path, const char *root, ChaseSymlinksFlags chase_flags, int access_mode, char **ret_path, int *ret_fd); int chase_symlinks_and_fopen_unlocked(const char *path, const char *root, ChaseSymlinksFlags chase_flags, const char *open_flags, char **ret_path, FILE **ret_file); +int chase_symlinks_and_unlink(const char *path, const char *root, ChaseSymlinksFlags chase_flags, int unlink_flags, char **ret_path); int chase_symlinks_at(int dir_fd, const char *path, ChaseSymlinksFlags flags, char **ret_path, int *ret_fd); diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index 38299ce7298..668a44733bc 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -330,6 +330,13 @@ TEST(chase_symlinks) { assert_se(sd_id128_equal(a, b)); } + assert_se(lstat(p, &st) >= 0); + r = chase_symlinks_and_unlink(p, NULL, 0, 0, &result); + assert_se(path_equal(result, p)); + result = mfree(result); + assert_se(r == 0); + assert_se(lstat(p, &st) == -1 && errno == ENOENT); + /* Test CHASE_NOFOLLOW */ p = strjoina(temp, "/target");