From 0441d265f2bb9da249c7abf333f0f771fadb4ab5 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 15 Apr 2024 19:36:47 +0200 Subject: Adding upstream version 1:2.3.21+dfsg1. Signed-off-by: Daniel Baumann --- src/master/dup2-array.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/master/dup2-array.c (limited to 'src/master/dup2-array.c') diff --git a/src/master/dup2-array.c b/src/master/dup2-array.c new file mode 100644 index 0000000..062590a --- /dev/null +++ b/src/master/dup2-array.c @@ -0,0 +1,78 @@ +/* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "array.h" +#include "dup2-array.h" + +#include + +void dup2_append(ARRAY_TYPE(dup2) *dups, int fd_src, int fd_dest) +{ + struct dup2 d; + + i_assert(fd_src >= 0); + i_assert(fd_dest >= 0); + + d.fd_src = fd_src; + d.fd_dest = fd_dest; + array_push_back(dups, &d); +} + +int dup2_array(ARRAY_TYPE(dup2) *dups_arr) +{ + struct dup2 *dups; + bool *moved, moves; + unsigned int i, j, count, conflict; + int fd; + + dups = array_get_modifiable(dups_arr, &count); + + moved = t_new(bool, count); + for (;;) { + conflict = count; + moves = FALSE; + for (i = 0; i < count; i++) { + if (moved[i]) + continue; + + for (j = 0; j < count; j++) { + if (dups[j].fd_src == dups[i].fd_dest && + !moved[j]) { + conflict = j; + break; + } + } + + if (j == count) { + /* no conflicts, move it */ + moved[i] = TRUE; + moves = TRUE; + if (dup2(dups[i].fd_src, dups[i].fd_dest) < 0) { + i_error("dup2(%d, %d) failed: %m", + dups[i].fd_src, + dups[i].fd_dest); + return -1; + } + } + } + if (conflict == count) + break; + + if (moves) { + /* it's possible that the conflicting fd was + moved already. try again. */ + continue; + } + + /* ok, we have to dup() */ + fd = dup(dups[conflict].fd_src); + if (fd == -1) { + i_error("dup(%d) failed: %m", dups[conflict].fd_src); + return -1; + } + fd_close_on_exec(fd, TRUE); + dups[conflict].fd_src = fd; + } + return 0; +} + -- cgit v1.2.3