systemd: merge branch systemd into master
This commit is contained in:
@@ -4,13 +4,9 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <linux/falloc.h>
|
||||
#include <linux/magic.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
@@ -20,7 +16,9 @@
|
||||
#include "locale-util.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "missing.h"
|
||||
#include "missing_fcntl.h"
|
||||
#include "missing_fs.h"
|
||||
#include "missing_syscall.h"
|
||||
#include "mkdir.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
@@ -669,6 +667,18 @@ int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
|
||||
}
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
int inotify_add_watch_and_warn(int fd, const char *pathname, uint32_t mask) {
|
||||
|
||||
if (inotify_add_watch(fd, pathname, mask) < 0) {
|
||||
if (errno == ENOSPC)
|
||||
return log_error_errno(errno, "Failed to add a watch for %s: inotify watch limit reached", pathname);
|
||||
|
||||
return log_error_errno(errno, "Failed to add a watch for %s: %m", pathname);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool unsafe_transition(const struct stat *a, const struct stat *b) {
|
||||
/* Returns true if the transition from a to b is safe, i.e. that we never transition from unprivileged to
|
||||
* privileged files or directories. Why bother? So that unprivileged code can't symlink to privileged files
|
||||
@@ -707,7 +717,7 @@ static int log_autofs_mount_point(int fd, const char *path, unsigned flags) {
|
||||
n1, path);
|
||||
}
|
||||
|
||||
int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret) {
|
||||
int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret_path, int *ret_fd) {
|
||||
_cleanup_free_ char *buffer = NULL, *done = NULL, *root = NULL;
|
||||
_cleanup_close_ int fd = -1;
|
||||
unsigned max_follow = CHASE_SYMLINKS_MAX; /* how many symlinks to follow before giving up and returning ELOOP */
|
||||
@@ -719,10 +729,10 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
|
||||
assert(path);
|
||||
|
||||
/* Either the file may be missing, or we return an fd to the final object, but both make no sense */
|
||||
if (FLAGS_SET(flags, CHASE_NONEXISTENT | CHASE_OPEN))
|
||||
if ((flags & CHASE_NONEXISTENT) && ret_fd)
|
||||
return -EINVAL;
|
||||
|
||||
if (FLAGS_SET(flags, CHASE_STEP | CHASE_OPEN))
|
||||
if ((flags & CHASE_STEP) && ret_fd)
|
||||
return -EINVAL;
|
||||
|
||||
if (isempty(path))
|
||||
@@ -748,17 +758,17 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
|
||||
* function what to do when encountering a symlink with an absolute path as directory: prefix it by the
|
||||
* specified path.
|
||||
*
|
||||
* There are three ways to invoke this function:
|
||||
* There are five ways to invoke this function:
|
||||
*
|
||||
* 1. Without CHASE_STEP or CHASE_OPEN: in this case the path is resolved and the normalized path is returned
|
||||
* in `ret`. The return value is < 0 on error. If CHASE_NONEXISTENT is also set, 0 is returned if the file
|
||||
* doesn't exist, > 0 otherwise. If CHASE_NONEXISTENT is not set, >= 0 is returned if the destination was
|
||||
* found, -ENOENT if it wasn't.
|
||||
* 1. Without CHASE_STEP or ret_fd: in this case the path is resolved and the normalized path is
|
||||
* returned in `ret_path`. The return value is < 0 on error. If CHASE_NONEXISTENT is also set, 0
|
||||
* is returned if the file doesn't exist, > 0 otherwise. If CHASE_NONEXISTENT is not set, >= 0 is
|
||||
* returned if the destination was found, -ENOENT if it wasn't.
|
||||
*
|
||||
* 2. With CHASE_OPEN: in this case the destination is opened after chasing it as O_PATH and this file
|
||||
* 2. With ret_fd: in this case the destination is opened after chasing it as O_PATH and this file
|
||||
* descriptor is returned as return value. This is useful to open files relative to some root
|
||||
* directory. Note that the returned O_PATH file descriptors must be converted into a regular one (using
|
||||
* fd_reopen() or such) before it can be used for reading/writing. CHASE_OPEN may not be combined with
|
||||
* fd_reopen() or such) before it can be used for reading/writing. ret_fd may not be combined with
|
||||
* CHASE_NONEXISTENT.
|
||||
*
|
||||
* 3. With CHASE_STEP: in this case only a single step of the normalization is executed, i.e. only the first
|
||||
@@ -774,21 +784,21 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
|
||||
* 5. With CHASE_NO_AUTOFS: in this case if an autofs mount point is encountered, path normalization
|
||||
* is aborted and -EREMOTE is returned. If CHASE_WARN is also set, a warning showing the path of
|
||||
* the mount point is emitted.
|
||||
*
|
||||
*/
|
||||
|
||||
/* A root directory of "/" or "" is identical to none */
|
||||
if (empty_or_root(original_root))
|
||||
original_root = NULL;
|
||||
|
||||
if (!original_root && !ret && (flags & (CHASE_NONEXISTENT|CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_OPEN|CHASE_STEP)) == CHASE_OPEN) {
|
||||
/* Shortcut the CHASE_OPEN case if the caller isn't interested in the actual path and has no root set
|
||||
if (!original_root && !ret_path && !(flags & (CHASE_NONEXISTENT|CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_STEP)) && ret_fd) {
|
||||
/* Shortcut the ret_fd case if the caller isn't interested in the actual path and has no root set
|
||||
* and doesn't care about any of the other special features we provide either. */
|
||||
r = open(path, O_PATH|O_CLOEXEC|((flags & CHASE_NOFOLLOW) ? O_NOFOLLOW : 0));
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
return r;
|
||||
*ret_fd = r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (original_root) {
|
||||
@@ -797,7 +807,6 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
|
||||
return r;
|
||||
|
||||
if (flags & CHASE_PREFIX_ROOT) {
|
||||
|
||||
/* We don't support relative paths in combination with a root directory */
|
||||
if (!path_is_absolute(path))
|
||||
return -EINVAL;
|
||||
@@ -942,7 +951,6 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
|
||||
|
||||
if (S_ISLNK(st.st_mode) && !((flags & CHASE_NOFOLLOW) && isempty(todo))) {
|
||||
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
|
||||
@@ -1028,15 +1036,15 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
*ret = TAKE_PTR(done);
|
||||
if (ret_path)
|
||||
*ret_path = TAKE_PTR(done);
|
||||
|
||||
if (flags & CHASE_OPEN) {
|
||||
/* Return the O_PATH fd we currently are looking to the caller. It can translate it to a proper fd by
|
||||
* opening /proc/self/fd/xyz. */
|
||||
if (ret_fd) {
|
||||
/* Return the O_PATH fd we currently are looking to the caller. It can translate it to a
|
||||
* proper fd by opening /proc/self/fd/xyz. */
|
||||
|
||||
assert(fd >= 0);
|
||||
return TAKE_FD(fd);
|
||||
*ret_fd = TAKE_FD(fd);
|
||||
}
|
||||
|
||||
if (flags & CHASE_STEP)
|
||||
@@ -1045,14 +1053,14 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
|
||||
return exists;
|
||||
|
||||
chased_one:
|
||||
if (ret) {
|
||||
if (ret_path) {
|
||||
char *c;
|
||||
|
||||
c = strjoin(strempty(done), todo);
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret = c;
|
||||
*ret_path = c;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1081,9 +1089,10 @@ int chase_symlinks_and_open(
|
||||
return r;
|
||||
}
|
||||
|
||||
path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL);
|
||||
if (path_fd < 0)
|
||||
return path_fd;
|
||||
r = chase_symlinks(path, root, chase_flags, ret_path ? &p : NULL, &path_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
assert(path_fd >= 0);
|
||||
|
||||
r = fd_reopen(path_fd, open_flags);
|
||||
if (r < 0)
|
||||
@@ -1106,6 +1115,7 @@ int chase_symlinks_and_opendir(
|
||||
_cleanup_close_ int path_fd = -1;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
DIR *d;
|
||||
int r;
|
||||
|
||||
if (!ret_dir)
|
||||
return -EINVAL;
|
||||
@@ -1122,9 +1132,10 @@ int chase_symlinks_and_opendir(
|
||||
return 0;
|
||||
}
|
||||
|
||||
path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL);
|
||||
if (path_fd < 0)
|
||||
return path_fd;
|
||||
r = chase_symlinks(path, root, chase_flags, ret_path ? &p : NULL, &path_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
assert(path_fd >= 0);
|
||||
|
||||
xsprintf(procfs_path, "/proc/self/fd/%i", path_fd);
|
||||
d = opendir(procfs_path);
|
||||
@@ -1143,10 +1154,12 @@ int chase_symlinks_and_stat(
|
||||
const char *root,
|
||||
unsigned chase_flags,
|
||||
char **ret_path,
|
||||
struct stat *ret_stat) {
|
||||
struct stat *ret_stat,
|
||||
int *ret_fd) {
|
||||
|
||||
_cleanup_close_ int path_fd = -1;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
assert(ret_stat);
|
||||
@@ -1162,18 +1175,18 @@ int chase_symlinks_and_stat(
|
||||
return 1;
|
||||
}
|
||||
|
||||
path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL);
|
||||
if (path_fd < 0)
|
||||
return path_fd;
|
||||
r = chase_symlinks(path, root, chase_flags, ret_path ? &p : NULL, &path_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
assert(path_fd >= 0);
|
||||
|
||||
if (fstat(path_fd, ret_stat) < 0)
|
||||
return -errno;
|
||||
|
||||
if (ret_path)
|
||||
*ret_path = TAKE_PTR(p);
|
||||
|
||||
if (chase_flags & CHASE_OPEN)
|
||||
return TAKE_FD(path_fd);
|
||||
if (ret_fd)
|
||||
*ret_fd = TAKE_FD(path_fd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
Reference in New Issue
Block a user