summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLudwig Nussel <ludwig.nussel@suse.de>2023-01-09 17:58:57 +0100
committerLudwig Nussel <ludwig.nussel@suse.de>2023-01-19 14:11:12 +0100
commit1132fd73b32a06c6349f20c0cfb235cc854a1a3a (patch)
tree9fd3b9cbd81c6d04b84b4d78de089d8d691bfafb /src
parenttest: update Ubuntu CI docs (diff)
downloadsystemd-1132fd73b32a06c6349f20c0cfb235cc854a1a3a.tar.xz
systemd-1132fd73b32a06c6349f20c0cfb235cc854a1a3a.zip
chase-symlinks: new chase_symlinks_and_unlink()
Diffstat (limited to 'src')
-rw-r--r--src/basic/chase-symlinks.c39
-rw-r--r--src/basic/chase-symlinks.h1
-rw-r--r--src/test/test-fs-util.c7
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");