]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
fd-util: add new helper move_fd() and make use of it
authorLennart Poettering <lennart@poettering.net>
Thu, 26 Oct 2017 16:45:54 +0000 (18:45 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 17 Nov 2017 10:13:44 +0000 (11:13 +0100)
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
src/basic/fd-util.h
src/core/execute.c
src/import/import-common.c
src/import/pull-common.c

index 9d61044c89e76e7922257541682371689cf7399a..0fd271318fac4916068ea96ab23b40ef6df1f162 100644 (file)
@@ -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;
+}
index 34b98d4aec546195f0495045437a638be6e51619..7c527850ed146768ed803f67aa361e49777a44c6 100644 (file)
@@ -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)
index 45df0318e0cb4f6304623504c53e5446b4f64ab0..8083cccab25809f6d063fd974ec9adf6da4275ee 100644 (file)
@@ -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:
index ae71682988341948d4a3b8a3361a6a9bed8e00bc..900c0f9591ff8159ace72eab2c45e7429e2d1e33 100644 (file)
@@ -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)
index 78840dd8822835ee851f780562f7f6ad45c6f9aa..d7f7a7e29be82fe3dfeab31862cf27c2b7107ddf 100644 (file)
@@ -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