From 49bfc8774bf900fb2239a9b70b951aedccbfed5a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 2 Feb 2017 00:06:18 +0100 Subject: [PATCH] fs-util: unify code we use to check if dirent's d_name is "." or ".." We use different idioms at different places. Let's replace this is the one true new idiom, that is even a bit faster... --- src/basic/cgroup-util.c | 3 +-- src/basic/copy.c | 2 +- src/basic/path-util.c | 25 ++++++++++++++++----- src/basic/path-util.h | 2 ++ src/basic/rm-rf.c | 2 +- src/basic/socket-util.c | 2 +- src/gpt-auto-generator/gpt-auto-generator.c | 2 +- src/nspawn/nspawn-patch-uid.c | 2 +- src/resolve/resolved-manager.c | 2 +- src/shared/clean-ipc.c | 4 ++-- src/test/test-fs-util.c | 11 +++++++++ src/tmpfiles/tmpfiles.c | 6 ++--- 12 files changed, 43 insertions(+), 20 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index d2d18f13f0..6948ed3931 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -182,8 +182,7 @@ int cg_read_subgroup(DIR *d, char **fn) { if (de->d_type != DT_DIR) continue; - if (streq(de->d_name, ".") || - streq(de->d_name, "..")) + if (dot_or_dot_dot(de->d_name)) continue; b = strdup(de->d_name); diff --git a/src/basic/copy.c b/src/basic/copy.c index 9883f5fa31..e9a7efd232 100644 --- a/src/basic/copy.c +++ b/src/basic/copy.c @@ -331,7 +331,7 @@ static int fd_copy_directory( struct stat buf; int q; - if (STR_IN_SET(de->d_name, ".", "..")) + if (dot_or_dot_dot(de->d_name)) continue; if (fstatat(dirfd(d), de->d_name, &buf, AT_SYMLINK_NOFOLLOW) < 0) { diff --git a/src/basic/path-util.c b/src/basic/path-util.c index 9a51e0d8bc..1313a52c9c 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -699,10 +699,7 @@ bool filename_is_valid(const char *p) { if (isempty(p)) return false; - if (streq(p, ".")) - return false; - - if (streq(p, "..")) + if (dot_or_dot_dot(p)) return false; e = strchrnul(p, '/'); @@ -720,14 +717,17 @@ bool path_is_safe(const char *p) { if (isempty(p)) return false; - if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../")) + if (dot_or_dot_dot(p)) + return false; + + if (startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../")) return false; if (strlen(p)+1 > PATH_MAX) return false; /* The following two checks are not really dangerous, but hey, they still are confusing */ - if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./")) + if (startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./")) return false; if (strstr(p, "//")) @@ -892,3 +892,16 @@ int systemd_installation_has_version(const char *root, unsigned minimal_version) return false; } + +bool dot_or_dot_dot(const char *path) { + if (!path) + return false; + if (path[0] != '.') + return false; + if (path[1] == 0) + return true; + if (path[1] != '.') + return false; + + return path[2] == 0; +} diff --git a/src/basic/path-util.h b/src/basic/path-util.h index 349cdac7d6..35aef3adc8 100644 --- a/src/basic/path-util.h +++ b/src/basic/path-util.h @@ -141,3 +141,5 @@ bool is_device_path(const char *path); bool is_deviceallow_pattern(const char *path); int systemd_installation_has_version(const char *root, unsigned minimal_version); + +bool dot_or_dot_dot(const char *path); diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c index 07d42f78dd..08497af729 100644 --- a/src/basic/rm-rf.c +++ b/src/basic/rm-rf.c @@ -83,7 +83,7 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) { bool is_dir; struct stat st; - if (streq(de->d_name, ".") || streq(de->d_name, "..")) + if (dot_or_dot_dot(de->d_name)) continue; if (de->d_type == DT_UNKNOWN || diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 77f81a60ba..17e90a8994 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -877,7 +877,7 @@ bool ifname_valid(const char *p) { if (strlen(p) >= IFNAMSIZ) return false; - if (STR_IN_SET(p, ".", "..")) + if (dot_or_dot_dot(p)) return false; while (*p) { diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c index e61ef8f249..b958070c90 100644 --- a/src/gpt-auto-generator/gpt-auto-generator.c +++ b/src/gpt-auto-generator/gpt-auto-generator.c @@ -658,7 +658,7 @@ static int get_block_device_harder(const char *path, dev_t *dev) { FOREACH_DIRENT_ALL(de, d, return -errno) { - if (STR_IN_SET(de->d_name, ".", "..")) + if (dot_or_dot_dot(de->d_name)) continue; if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN)) diff --git a/src/nspawn/nspawn-patch-uid.c b/src/nspawn/nspawn-patch-uid.c index ded5866d05..1a3f129db0 100644 --- a/src/nspawn/nspawn-patch-uid.c +++ b/src/nspawn/nspawn-patch-uid.c @@ -375,7 +375,7 @@ static int recurse_fd(int fd, bool donate_fd, const struct stat *st, uid_t shift FOREACH_DIRENT_ALL(de, d, r = -errno; goto finish) { struct stat fst; - if (STR_IN_SET(de->d_name, ".", "..")) + if (dot_or_dot_dot(de->d_name)) continue; if (fstatat(dirfd(d), de->d_name, &fst, AT_SYMLINK_NOFOLLOW) < 0) { diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 0954641c20..667774b906 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -1349,7 +1349,7 @@ void manager_cleanup_saved_user(Manager *m) { if (!IN_SET(de->d_type, DT_UNKNOWN, DT_REG)) continue; - if (STR_IN_SET(de->d_name, ".", "..")) + if (dot_or_dot_dot(de->d_name)) continue; r = parse_ifindex(de->d_name, &ifindex); diff --git a/src/shared/clean-ipc.c b/src/shared/clean-ipc.c index f2d1555c13..f59f6f23ae 100644 --- a/src/shared/clean-ipc.c +++ b/src/shared/clean-ipc.c @@ -225,7 +225,7 @@ static int clean_posix_shm_internal(DIR *dir, uid_t uid, gid_t gid) { FOREACH_DIRENT_ALL(de, dir, goto fail) { struct stat st; - if (STR_IN_SET(de->d_name, "..", ".")) + if (dot_or_dot_dot(de->d_name)) continue; if (fstatat(dirfd(dir), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { @@ -310,7 +310,7 @@ static int clean_posix_mq(uid_t uid, gid_t gid) { struct stat st; char fn[1+strlen(de->d_name)+1]; - if (STR_IN_SET(de->d_name, "..", ".")) + if (dot_or_dot_dot(de->d_name)) continue; if (fstatat(dirfd(dir), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index 4cb465d0d2..e774f567e0 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -305,12 +305,23 @@ static void test_var_tmp(void) { } } +static void test_dot_or_dot_dot(void) { + assert_se(!dot_or_dot_dot(NULL)); + assert_se(!dot_or_dot_dot("")); + assert_se(!dot_or_dot_dot("xxx")); + assert_se(dot_or_dot_dot(".")); + assert_se(dot_or_dot_dot("..")); + assert_se(!dot_or_dot_dot(".foo")); + assert_se(!dot_or_dot_dot("..foo")); +} + int main(int argc, char *argv[]) { test_unlink_noerrno(); test_readlink_and_make_absolute(); test_get_files_in_directory(); test_var_tmp(); test_chase_symlinks(); + test_dot_or_dot_dot(); return 0; } diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index f4ce9791fb..c4f4d46ca1 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -385,7 +385,7 @@ static int dir_cleanup( usec_t age; _cleanup_free_ char *sub_path = NULL; - if (STR_IN_SET(dent->d_name, ".", "..")) + if (dot_or_dot_dot(dent->d_name)) continue; if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) { @@ -1070,9 +1070,7 @@ static int item_do_children(Item *i, const char *path, action_t action) { _cleanup_free_ char *p = NULL; int q; - errno = 0; - - if (STR_IN_SET(de->d_name, ".", "..")) + if (dot_or_dot_dot(de->d_name)) continue; p = strjoin(path, "/", de->d_name);