From e3f791a2b35b98cddf1f140ee5c80e5403d89afd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 17 Jun 2017 12:37:16 -0400 Subject: [PATCH] basic/path-util: allow flags for path_equal_or_files_same No functional change, just a new parameters and the tests that AT_SYMLINK_NOFOLLOW works as expected. --- src/basic/path-util.c | 4 ++-- src/basic/path-util.h | 2 +- src/basic/process-util.c | 2 +- src/basic/rm-rf.c | 2 +- src/basic/socket-util.c | 2 +- src/basic/stat-util.c | 6 +++--- src/basic/stat-util.h | 2 +- src/basic/util.c | 2 +- src/basic/virt.c | 2 +- src/core/socket.c | 6 +++--- src/shared/install.c | 2 +- src/systemctl/systemctl.c | 2 +- src/test/test-path-util.c | 30 ++++++++++++++++++++---------- src/test/test-stat-util.c | 6 ++++-- 14 files changed, 41 insertions(+), 29 deletions(-) diff --git a/src/basic/path-util.c b/src/basic/path-util.c index 1313a52c9c..80fdda170f 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -442,8 +442,8 @@ bool path_equal(const char *a, const char *b) { return path_compare(a, b) == 0; } -bool path_equal_or_files_same(const char *a, const char *b) { - return path_equal(a, b) || files_same(a, b) > 0; +bool path_equal_or_files_same(const char *a, const char *b, int flags) { + return path_equal(a, b) || files_same(a, b, flags) > 0; } char* path_join(const char *root, const char *path, const char *rest) { diff --git a/src/basic/path-util.h b/src/basic/path-util.h index 35aef3adc8..26f165fc38 100644 --- a/src/basic/path-util.h +++ b/src/basic/path-util.h @@ -46,7 +46,7 @@ char* path_kill_slashes(char *path); char* path_startswith(const char *path, const char *prefix) _pure_; int path_compare(const char *a, const char *b) _pure_; bool path_equal(const char *a, const char *b) _pure_; -bool path_equal_or_files_same(const char *a, const char *b); +bool path_equal_or_files_same(const char *a, const char *b, int flags); char* path_join(const char *root, const char *path, const char *rest); static inline bool path_equal_ptr(const char *a, const char *b) { diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 0df3fed640..a21dc35baa 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -807,7 +807,7 @@ int pid_from_same_root_fs(pid_t pid) { root = procfs_file_alloca(pid, "root"); - return files_same(root, "/proc/1/root"); + return files_same(root, "/proc/1/root", 0); } bool is_main_thread(void) { diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c index ff040e7a55..421289e11b 100644 --- a/src/basic/rm-rf.c +++ b/src/basic/rm-rf.c @@ -182,7 +182,7 @@ int rm_rf(const char *path, RemoveFlags flags) { /* We refuse to clean the root file system with this * call. This is extra paranoia to never cause a really * seriously broken system. */ - if (path_equal_or_files_same(path, "/")) { + if (path_equal_or_files_same(path, "/", 0)) { log_error("Attempted to remove entire root file system, and we can't allow that."); return -EPERM; } diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 49642c2347..016e64aa03 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -412,7 +412,7 @@ bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) { return false; if (a->sockaddr.un.sun_path[0]) { - if (!path_equal_or_files_same(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path)) + if (!path_equal_or_files_same(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, 0)) return false; } else { if (a->size != b->size) diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c index 7e1914aa14..d87370e672 100644 --- a/src/basic/stat-util.c +++ b/src/basic/stat-util.c @@ -169,16 +169,16 @@ int path_is_os_tree(const char *path) { return 1; } -int files_same(const char *filea, const char *fileb) { +int files_same(const char *filea, const char *fileb, int flags) { struct stat a, b; assert(filea); assert(fileb); - if (stat(filea, &a) < 0) + if (fstatat(AT_FDCWD, filea, &a, flags) < 0) return -errno; - if (stat(fileb, &b) < 0) + if (fstatat(AT_FDCWD, fileb, &b, flags) < 0) return -errno; return a.st_dev == b.st_dev && diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h index 5d571efe18..cd204ac6cb 100644 --- a/src/basic/stat-util.h +++ b/src/basic/stat-util.h @@ -49,7 +49,7 @@ int null_or_empty_fd(int fd); int path_is_read_only_fs(const char *path); int path_is_os_tree(const char *path); -int files_same(const char *filea, const char *fileb); +int files_same(const char *filea, const char *fileb, int flags); /* The .f_type field of struct statfs is really weird defined on * different archs. Let's give its type a name. */ diff --git a/src/basic/util.c b/src/basic/util.c index 3dce0ea92e..b52a5db31b 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -541,7 +541,7 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int if (asprintf(&userns_fd_path, "/proc/self/fd/%d", userns_fd) < 0) return -ENOMEM; - r = files_same(userns_fd_path, "/proc/self/ns/user"); + r = files_same(userns_fd_path, "/proc/self/ns/user", 0); if (r < 0) return r; if (r) diff --git a/src/basic/virt.c b/src/basic/virt.c index ff4491d6d6..6011744523 100644 --- a/src/basic/virt.c +++ b/src/basic/virt.c @@ -574,7 +574,7 @@ int running_in_chroot(void) { if (getenv_bool("SYSTEMD_IGNORE_CHROOT") > 0) return 0; - ret = files_same("/proc/1/root", "/"); + ret = files_same("/proc/1/root", "/", 0); if (ret < 0) return ret; diff --git a/src/core/socket.c b/src/core/socket.c index c4da227e09..8750643d92 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -2528,7 +2528,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value, else LIST_FOREACH(port, p, s->ports) if (p->type == SOCKET_FIFO && - path_equal_or_files_same(p->path, value+skip)) { + path_equal_or_files_same(p->path, value+skip, 0)) { socket_port_take_fd(p, fds, fd); break; } @@ -2542,7 +2542,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value, else LIST_FOREACH(port, p, s->ports) if (p->type == SOCKET_SPECIAL && - path_equal_or_files_same(p->path, value+skip)) { + path_equal_or_files_same(p->path, value+skip, 0)) { socket_port_take_fd(p, fds, fd); break; } @@ -2596,7 +2596,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value, else LIST_FOREACH(port, p, s->ports) if (p->type == SOCKET_USB_FUNCTION && - path_equal_or_files_same(p->path, value+skip)) { + path_equal_or_files_same(p->path, value+skip, 0)) { socket_port_take_fd(p, fds, fd); break; } diff --git a/src/shared/install.c b/src/shared/install.c index 7f3bc0d813..d0a291b819 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -422,7 +422,7 @@ static bool chroot_symlinks_same(const char *root, const char *wd, const char *a a = strjoina(path_is_absolute(a) ? root : wd, "/", a); b = strjoina(path_is_absolute(b) ? root : wd, "/", b); - return path_equal_or_files_same(a, b); + return path_equal_or_files_same(a, b, 0); } static int create_symlink( diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 2f69e863c5..9ad74b0695 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -5654,7 +5654,7 @@ static int switch_root(int argc, char *argv[], void *userdata) { /* If the passed init is actually the same as the * systemd binary, then let's suppress it. */ - if (files_same(root_init_path, root_systemd_path) > 0) + if (files_same(root_init_path, root_systemd_path, 0) > 0) init = NULL; } diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c index ab62d0dad2..e5644246c2 100644 --- a/src/test/test-path-util.c +++ b/src/test/test-path-util.c @@ -118,23 +118,33 @@ static void test_path_equal_root(void) { /* Make sure that files_same works as expected. */ - assert_se(files_same("/", "/") > 0); - assert_se(files_same("/", "//") > 0); + assert_se(files_same("/", "/", 0) > 0); + assert_se(files_same("/", "/", AT_SYMLINK_NOFOLLOW) > 0); + assert_se(files_same("/", "//", 0) > 0); + assert_se(files_same("/", "//", AT_SYMLINK_NOFOLLOW) > 0); - assert_se(files_same("/", "/./") > 0); - assert_se(files_same("/", "/../") > 0); + assert_se(files_same("/", "/./", 0) > 0); + assert_se(files_same("/", "/./", AT_SYMLINK_NOFOLLOW) > 0); + assert_se(files_same("/", "/../", 0) > 0); + assert_se(files_same("/", "/../", AT_SYMLINK_NOFOLLOW) > 0); - assert_se(files_same("/", "/.../") == -ENOENT); + assert_se(files_same("/", "/.../", 0) == -ENOENT); + assert_se(files_same("/", "/.../", AT_SYMLINK_NOFOLLOW) == -ENOENT); /* The same for path_equal_or_files_same. */ - assert_se(path_equal_or_files_same("/", "/")); - assert_se(path_equal_or_files_same("/", "//")); + assert_se(path_equal_or_files_same("/", "/", 0)); + assert_se(path_equal_or_files_same("/", "/", AT_SYMLINK_NOFOLLOW)); + assert_se(path_equal_or_files_same("/", "//", 0)); + assert_se(path_equal_or_files_same("/", "//", AT_SYMLINK_NOFOLLOW)); - assert_se(path_equal_or_files_same("/", "/./")); - assert_se(path_equal_or_files_same("/", "/../")); + assert_se(path_equal_or_files_same("/", "/./", 0)); + assert_se(path_equal_or_files_same("/", "/./", AT_SYMLINK_NOFOLLOW)); + assert_se(path_equal_or_files_same("/", "/../", 0)); + assert_se(path_equal_or_files_same("/", "/../", AT_SYMLINK_NOFOLLOW)); - assert_se(!path_equal_or_files_same("/", "/.../")); + assert_se(!path_equal_or_files_same("/", "/.../", 0)); + assert_se(!path_equal_or_files_same("/", "/.../", AT_SYMLINK_NOFOLLOW)); } static void test_find_binary(const char *self) { diff --git a/src/test/test-stat-util.c b/src/test/test-stat-util.c index 3ff2aadea4..8e027ff26c 100644 --- a/src/test/test-stat-util.c +++ b/src/test/test-stat-util.c @@ -38,8 +38,10 @@ static void test_files_same(void) { assert_se(fd >= 0); assert_se(symlink(name, name_alias) >= 0); - assert_se(files_same(name, name)); - assert_se(files_same(name, name_alias)); + assert_se(files_same(name, name, 0)); + assert_se(files_same(name, name, AT_SYMLINK_NOFOLLOW)); + assert_se(files_same(name, name_alias, 0)); + assert_se(!files_same(name, name_alias, AT_SYMLINK_NOFOLLOW)); unlink(name); unlink(name_alias);