X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=src%2Fbasic%2Ffs-util.c;h=1eaf820afb45a636a16ce76c7522fcff19ceb8ac;hb=53e1b683907c2f12330f00feb9630150196f064d;hp=e31fa2711a436245f795fbe8984ed9b86b552e3d;hpb=5b3637b44a28d3fb2ba8b272905c64d9dbae4d26;p=thirdparty%2Fsystemd.git diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index e31fa2711a4..1eaf820afb4 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -23,6 +24,7 @@ #include #include #include +#include #include #include @@ -103,7 +105,6 @@ int rmdir_parents(const char *path, const char *stop) { return 0; } - int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) { struct stat buf; int ret; @@ -307,7 +308,7 @@ int fd_warn_permissions(const char *path, int fd) { if (st.st_mode & 0002) log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path); - if (getpid() == 1 && (st.st_mode & 0044) != 0044) + if (getpid_cached() == 1 && (st.st_mode & 0044) != 0044) log_warning("Configuration file %s is marked world-inaccessible. This has no effect as configuration data is accessible via APIs without restrictions. Proceeding anyway.", path); return 0; @@ -323,7 +324,7 @@ int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gi mkdir_parents(path, 0755); fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, - (mode == 0 || mode == MODE_INVALID) ? 0644 : mode); + IN_SET(mode, 0, MODE_INVALID) ? 0644 : mode); if (fd < 0) return -errno; @@ -358,22 +359,25 @@ int touch(const char *path) { } int symlink_idempotent(const char *from, const char *to) { - _cleanup_free_ char *p = NULL; int r; assert(from); assert(to); if (symlink(from, to) < 0) { + _cleanup_free_ char *p = NULL; + if (errno != EEXIST) return -errno; r = readlink_malloc(to, &p); - if (r < 0) + if (r == -EINVAL) /* Not a symlink? In that case return the original error we encountered: -EEXIST */ + return -EEXIST; + if (r < 0) /* Any other error? In that case propagate it as is */ return r; - if (!streq(p, from)) - return -EINVAL; + if (!streq(p, from)) /* Not the symlink we want it to be? In that case, propagate the original -EEXIST */ + return -EEXIST; } return 0; @@ -721,8 +725,13 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, if (fstat(child, &st) < 0) return -errno; + if ((flags & CHASE_NO_AUTOFS) && + fd_check_fstype(child, AUTOFS_SUPER_MAGIC) > 0) + return -EREMOTE; if (S_ISLNK(st.st_mode)) { + char *joined; + _cleanup_free_ char *destination = NULL; /* This is a symlink, in this case read the destination. But let's make sure we don't follow @@ -746,9 +755,6 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, if (fd < 0) return -errno; - free_and_replace(buffer, destination); - - todo = buffer; free(done); /* Note that we do not revalidate the root, we take it as is. */ @@ -760,19 +766,16 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, return -ENOMEM; } - } else { - char *joined; - - /* A relative destination. If so, this is what we'll prefix what's left to do with what - * we just read, and start the loop again, but remain in the current directory. */ - + /* Prefix what's left to do with what we just read, and start the loop again, but + * remain in the current directory. */ + joined = strjoin(destination, todo); + } else joined = strjoin("/", destination, todo); - if (!joined) - return -ENOMEM; + if (!joined) + return -ENOMEM; - free(buffer); - todo = buffer = joined; - } + free(buffer); + todo = buffer = joined; continue; } @@ -806,3 +809,18 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, return exists; } + +int access_fd(int fd, int mode) { + char p[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1]; + int r; + + /* Like access() but operates on an already open fd */ + + xsprintf(p, "/proc/self/fd/%i", fd); + + r = access(p, mode); + if (r < 0) + r = -errno; + + return r; +}