From 046a82c1b20f765a8aa704ddea87e1b906d8ded0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 26 Oct 2017 18:45:54 +0200 Subject: [PATCH] fd-util: add new helper move_fd() and make use of it We are using the same pattern at various places: call dup2() on an fd, and close the old fd, usually in combination with some O_CLOEXEC fiddling. Let's add a little helper for this, and port a few obvious cases over. --- src/basic/fd-util.c | 44 ++++++++++++++++++++++++++++++++++++++ src/basic/fd-util.h | 2 ++ src/core/execute.c | 38 ++++++-------------------------- src/import/import-common.c | 32 +++++++++++---------------- src/import/pull-common.c | 16 ++++++-------- 5 files changed, 71 insertions(+), 61 deletions(-) diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c index 9d61044c89..0fd271318f 100644 --- a/src/basic/fd-util.c +++ b/src/basic/fd-util.c @@ -377,3 +377,47 @@ int fd_get_path(int fd, char **ret) { return r; } + +int move_fd(int from, int to, int cloexec) { + int r; + + /* Move fd 'from' to 'to', make sure FD_CLOEXEC remains equal if requested, and release the old fd. If + * 'cloexec' is passed as -1, the original FD_CLOEXEC is inherited for the new fd. If it is 0, it is turned + * off, if it is > 0 it is turned on. */ + + if (from < 0) + return -EBADF; + if (to < 0) + return -EBADF; + + if (from == to) { + + if (cloexec >= 0) { + r = fd_cloexec(to, cloexec); + if (r < 0) + return r; + } + + return to; + } + + if (cloexec < 0) { + int fl; + + fl = fcntl(from, F_GETFD, 0); + if (fl < 0) + return -errno; + + cloexec = !!(fl & FD_CLOEXEC); + } + + r = dup3(from, to, cloexec ? O_CLOEXEC : 0); + if (r < 0) + return -errno; + + assert(r == to); + + safe_close(from); + + return to; +} diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h index 34b98d4aec..7c527850ed 100644 --- a/src/basic/fd-util.h +++ b/src/basic/fd-util.h @@ -75,6 +75,8 @@ bool fdname_is_valid(const char *s); int fd_get_path(int fd, char **ret); +int move_fd(int from, int to, int cloexec); + /* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */ #define ERRNO_IS_DISCONNECT(r) \ IN_SET(r, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, ENETUNREACH) diff --git a/src/core/execute.c b/src/core/execute.c index 45df0318e0..8083cccab2 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -275,7 +275,7 @@ static bool exec_context_needs_term(const ExecContext *c) { } static int open_null_as(int flags, int nfd) { - int fd, r; + int fd; assert(nfd >= 0); @@ -283,13 +283,7 @@ static int open_null_as(int flags, int nfd) { if (fd < 0) return -errno; - if (fd != nfd) { - r = dup2(fd, nfd) < 0 ? -errno : nfd; - safe_close(fd); - } else - r = nfd; - - return r; + return move_fd(fd, nfd, false); } static int connect_journal_socket(int fd, uid_t uid, gid_t gid) { @@ -381,16 +375,10 @@ static int connect_logger_as( is_kmsg_output(output), is_terminal_output(output)); - if (fd == nfd) - return nfd; - - r = dup2(fd, nfd) < 0 ? -errno : nfd; - safe_close(fd); - - return r; + return move_fd(fd, nfd, false); } static int open_terminal_as(const char *path, mode_t mode, int nfd) { - int fd, r; + int fd; assert(path); assert(nfd >= 0); @@ -399,13 +387,7 @@ static int open_terminal_as(const char *path, mode_t mode, int nfd) { if (fd < 0) return fd; - if (fd != nfd) { - r = dup2(fd, nfd) < 0 ? -errno : nfd; - safe_close(fd); - } else - r = nfd; - - return r; + return move_fd(fd, nfd, false); } static int fixup_input(ExecInput std_input, int socket_fd, bool apply_tty_stdin) { @@ -459,7 +441,7 @@ static int setup_input( case EXEC_INPUT_TTY: case EXEC_INPUT_TTY_FORCE: case EXEC_INPUT_TTY_FAIL: { - int fd, r; + int fd; fd = acquire_terminal(exec_context_tty_path(context), i == EXEC_INPUT_TTY_FAIL, @@ -469,13 +451,7 @@ static int setup_input( if (fd < 0) return fd; - if (fd != STDIN_FILENO) { - r = dup2(fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO; - safe_close(fd); - } else - r = STDIN_FILENO; - - return r; + return move_fd(fd, STDIN_FILENO, false); } case EXEC_INPUT_SOCKET: diff --git a/src/import/import-common.c b/src/import/import-common.c index ae71682988..900c0f9591 100644 --- a/src/import/import-common.c +++ b/src/import/import-common.c @@ -103,28 +103,24 @@ int import_fork_tar_x(const char *path, pid_t *ret) { pipefd[1] = safe_close(pipefd[1]); - if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) { - log_error_errno(errno, "Failed to dup2() fd: %m"); + r = move_fd(pipefd[0], STDIN_FILENO, false); + if (r < 0) { + log_error_errno(r, "Failed to move fd: %m"); _exit(EXIT_FAILURE); } - if (pipefd[0] != STDIN_FILENO) - pipefd[0] = safe_close(pipefd[0]); - null_fd = open("/dev/null", O_WRONLY|O_NOCTTY); if (null_fd < 0) { log_error_errno(errno, "Failed to open /dev/null: %m"); _exit(EXIT_FAILURE); } - if (dup2(null_fd, STDOUT_FILENO) != STDOUT_FILENO) { - log_error_errno(errno, "Failed to dup2() fd: %m"); + r = move_fd(null_fd, STDOUT_FILENO, false); + if (r < 0) { + log_error_errno(r, "Failed to move fd: %m"); _exit(EXIT_FAILURE); } - if (null_fd != STDOUT_FILENO) - null_fd = safe_close(null_fd); - stdio_unset_cloexec(); if (unshare(CLONE_NEWNET) < 0) @@ -175,28 +171,24 @@ int import_fork_tar_c(const char *path, pid_t *ret) { pipefd[0] = safe_close(pipefd[0]); - if (dup2(pipefd[1], STDOUT_FILENO) != STDOUT_FILENO) { - log_error_errno(errno, "Failed to dup2() fd: %m"); + r = move_fd(pipefd[1], STDOUT_FILENO, false); + if (r < 0) { + log_error_errno(r, "Failed to move fd: %m"); _exit(EXIT_FAILURE); } - if (pipefd[1] != STDOUT_FILENO) - pipefd[1] = safe_close(pipefd[1]); - null_fd = open("/dev/null", O_RDONLY|O_NOCTTY); if (null_fd < 0) { log_error_errno(errno, "Failed to open /dev/null: %m"); _exit(EXIT_FAILURE); } - if (dup2(null_fd, STDIN_FILENO) != STDIN_FILENO) { - log_error_errno(errno, "Failed to dup2() fd: %m"); + r = move_fd(null_fd, STDIN_FILENO, false); + if (r < 0) { + log_error_errno(errno, "Failed to move fd: %m"); _exit(EXIT_FAILURE); } - if (null_fd != STDIN_FILENO) - null_fd = safe_close(null_fd); - stdio_unset_cloexec(); if (unshare(CLONE_NEWNET) < 0) diff --git a/src/import/pull-common.c b/src/import/pull-common.c index 78840dd882..d7f7a7e29b 100644 --- a/src/import/pull-common.c +++ b/src/import/pull-common.c @@ -492,28 +492,24 @@ int pull_verify(PullJob *main_job, gpg_pipe[1] = safe_close(gpg_pipe[1]); - if (dup2(gpg_pipe[0], STDIN_FILENO) != STDIN_FILENO) { - log_error_errno(errno, "Failed to dup2() fd: %m"); + r = move_fd(gpg_pipe[0], STDIN_FILENO, false); + if (r < 0) { + log_error_errno(errno, "Failed to move fd: %m"); _exit(EXIT_FAILURE); } - if (gpg_pipe[0] != STDIN_FILENO) - gpg_pipe[0] = safe_close(gpg_pipe[0]); - null_fd = open("/dev/null", O_WRONLY|O_NOCTTY); if (null_fd < 0) { log_error_errno(errno, "Failed to open /dev/null: %m"); _exit(EXIT_FAILURE); } - if (dup2(null_fd, STDOUT_FILENO) != STDOUT_FILENO) { - log_error_errno(errno, "Failed to dup2() fd: %m"); + r = move_fd(null_fd, STDOUT_FILENO, false); + if (r < 0) { + log_error_errno(errno, "Failed to move fd: %m"); _exit(EXIT_FAILURE); } - if (null_fd != STDOUT_FILENO) - null_fd = safe_close(null_fd); - cmd[k++] = strjoina("--homedir=", gpg_home); /* We add the user keyring only to the command line -- 2.25.1