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...
This commit is contained in:
Lennart Poettering 2017-02-02 00:06:18 +01:00
parent 1d0106996c
commit 49bfc8774b
12 changed files with 43 additions and 20 deletions

View File

@ -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);

View File

@ -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) {

View File

@ -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;
}

View File

@ -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);

View File

@ -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 ||

View File

@ -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) {

View File

@ -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))

View File

@ -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) {

View File

@ -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);

View File

@ -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) {

View File

@ -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;
}

View File

@ -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);