diff options
author | Ludwig Nussel <ludwig.nussel@suse.de> | 2023-01-09 17:58:57 +0100 |
---|---|---|
committer | Ludwig Nussel <ludwig.nussel@suse.de> | 2023-01-19 14:11:12 +0100 |
commit | 1132fd73b32a06c6349f20c0cfb235cc854a1a3a (patch) | |
tree | 9fd3b9cbd81c6d04b84b4d78de089d8d691bfafb /src | |
parent | test: update Ubuntu CI docs (diff) | |
download | systemd-1132fd73b32a06c6349f20c0cfb235cc854a1a3a.tar.xz systemd-1132fd73b32a06c6349f20c0cfb235cc854a1a3a.zip |
chase-symlinks: new chase_symlinks_and_unlink()
Diffstat (limited to 'src')
-rw-r--r-- | src/basic/chase-symlinks.c | 39 | ||||
-rw-r--r-- | src/basic/chase-symlinks.h | 1 | ||||
-rw-r--r-- | src/test/test-fs-util.c | 7 |
3 files changed, 47 insertions, 0 deletions
diff --git a/src/basic/chase-symlinks.c b/src/basic/chase-symlinks.c index a0134fd330..4cc0a01df8 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 af0fcf155a..be5e2bb696 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 38299ce729..668a44733b 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"); |