From bdcad22e8e508308032cba5f8c2d5c093adb7d87 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Tue, 28 Mar 2023 11:17:23 +0200
Subject: [PATCH] fdset: add new helper to convert an fdset to an array

Conflict:fdset_close_others removes different code, but the end result is the same.
Reference:https://github.com/systemd/systemd/commit/bdcad22e8e508308032cba5f8c2d5c093adb7d87

---
 src/shared/fdset.c | 39 ++++++++++++++++++++++++++++++---------
 src/shared/fdset.h |  2 ++
 2 files changed, 32 insertions(+), 9 deletions(-)

diff --git a/src/shared/fdset.c b/src/shared/fdset.c
index 443aa7f..cb7a340 100644
--- a/src/shared/fdset.c
+++ b/src/shared/fdset.c
@@ -236,22 +236,43 @@ fail:
         return r;
 }
 
-int fdset_close_others(FDSet *fds) {
+int fdset_to_array(FDSet *fds, int **ret) {
+        unsigned j = 0, m;
         void *e;
-        int *a = NULL;
-        size_t j = 0, m;
+        int *a;
 
-        m = fdset_size(fds);
+        assert(ret);
 
-        if (m > 0) {
-                a = newa(int, m);
-                SET_FOREACH(e, MAKE_SET(fds))
-                        a[j++] = PTR_TO_FD(e);
+        m = fdset_size(fds);
+        if (m > INT_MAX) /* We want to be able to return an "int" */
+                return -ENOMEM;
+        if (m == 0) {
+                *ret = NULL; /* suppress array allocation if empty */
+                return 0;
         }
 
+        a = new(int, m);
+        if (!a)
+                return -ENOMEM;
+
+        SET_FOREACH(e, MAKE_SET(fds))
+                a[j++] = PTR_TO_FD(e);
+
         assert(j == m);
 
-        return close_all_fds(a, j);
+        *ret = TAKE_PTR(a);
+        return (int) m;
+}
+
+int fdset_close_others(FDSet *fds) {
+        _cleanup_free_ int *a = NULL;
+        int n;
+
+        n = fdset_to_array(fds, &a);
+        if (n < 0)
+                return n;
+
+        return close_all_fds(a, n);
 }
 
 unsigned fdset_size(FDSet *fds) {
diff --git a/src/shared/fdset.h b/src/shared/fdset.h
index e8a6b48..5f4304e 100644
--- a/src/shared/fdset.h
+++ b/src/shared/fdset.h
@@ -24,6 +24,8 @@ int fdset_new_listen_fds(FDSet **ret, bool unset);
 
 int fdset_cloexec(FDSet *fds, bool b);
 
+int fdset_to_array(FDSet *fds, int **ret);
+
 int fdset_close_others(FDSet *fds);
 
 unsigned fdset_size(FDSet *fds);
-- 
2.33.0

