]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
serialize: add serialize_fd_many() helper
authorLennart Poettering <lennart@poettering.net>
Mon, 16 Oct 2023 13:56:58 +0000 (15:56 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 18 Oct 2023 11:51:02 +0000 (13:51 +0200)
src/basic/fd-util.c
src/basic/fd-util.h
src/core/execute-serialize.c
src/shared/serialize.c
src/shared/serialize.h

index 5292e41937af4c19792d39f60a663be78e075222..33c4a057adf5696dca4e029bc4a8d41abbac16bd 100644 (file)
@@ -99,6 +99,13 @@ void close_many(const int fds[], size_t n_fd) {
                 safe_close(fds[i]);
 }
 
+void close_many_and_free(int *fds, size_t n_fds) {
+        assert(fds || n_fds <= 0);
+
+        close_many(fds, n_fds);
+        free(fds);
+}
+
 int fclose_nointr(FILE *f) {
         assert(f);
 
index 6aecb91fab3e98ec12d05de9f89d752af1f128ad..1f5ed828b7bef1f2c61b034fec96832a15ebd4e3 100644 (file)
@@ -30,6 +30,7 @@ static inline int safe_close_above_stdio(int fd) {
 }
 
 void close_many(const int fds[], size_t n_fd);
+void close_many_and_free(int *fds, size_t n_fds);
 
 int fclose_nointr(FILE *f);
 FILE* safe_fclose(FILE *f);
index ca65ca2c421256d05e295d37436cb55d9f9021fb..55f5bdc8c97f2af31e1507157aa5e22dcbd3192d 100644 (file)
@@ -1117,33 +1117,13 @@ static int exec_runtime_serialize(const ExecRuntime *rt, FILE *f, FDSet *fds) {
                         return r;
 
                 if (rt->shared->netns_storage_socket[0] >= 0 && rt->shared->netns_storage_socket[1] >= 0) {
-                        int a, b;
-
-                        a = fdset_put_dup(fds, rt->shared->netns_storage_socket[0]);
-                        if (a < 0)
-                                return a;
-
-                        b = fdset_put_dup(fds, rt->shared->netns_storage_socket[1]);
-                        if (b < 0)
-                                return b;
-
-                        r = serialize_item_format(f, "exec-runtime-netns-storage-socket", "%d %d", a, b);
+                        r = serialize_fd_many(f, fds, "exec-runtime-netns-storage-socket", rt->shared->netns_storage_socket, 2);
                         if (r < 0)
                                 return r;
                 }
 
                 if (rt->shared->ipcns_storage_socket[0] >= 0 && rt->shared->ipcns_storage_socket[1] >= 0) {
-                        int a, b;
-
-                        a = fdset_put_dup(fds, rt->shared->ipcns_storage_socket[0]);
-                        if (a < 0)
-                                return a;
-
-                        b = fdset_put_dup(fds, rt->shared->ipcns_storage_socket[1]);
-                        if (b < 0)
-                                return b;
-
-                        r = serialize_item_format(f, "exec-runtime-ipcns-storage-socket", "%d %d", a, b);
+                        r = serialize_fd_many(f, fds, "exec-runtime-ipcns-storage-socket", rt->shared->ipcns_storage_socket, 2);
                         if (r < 0)
                                 return r;
                 }
@@ -1170,17 +1150,7 @@ static int exec_runtime_serialize(const ExecRuntime *rt, FILE *f, FDSet *fds) {
                 return r;
 
         if (rt->ephemeral_storage_socket[0] >= 0 && rt->ephemeral_storage_socket[1] >= 0) {
-                int a, b;
-
-                a = fdset_put_dup(fds, rt->ephemeral_storage_socket[0]);
-                if (a < 0)
-                        return a;
-
-                b = fdset_put_dup(fds, rt->ephemeral_storage_socket[1]);
-                if (b < 0)
-                        return b;
-
-                r = serialize_item_format(f, "exec-runtime-ephemeral-storage-socket", "%d %d", a, b);
+                r = serialize_fd_many(f, fds, "exec-runtime-ephemeral-storage-socket", rt->ephemeral_storage_socket, 2);
                 if (r < 0)
                         return r;
         }
@@ -1222,39 +1192,17 @@ static int exec_runtime_deserialize(ExecRuntime *rt, FILE *f, FDSet *fds) {
                         if (r < 0)
                                 return r;
                 } else if ((val = startswith(l, "exec-runtime-netns-storage-socket="))) {
-                        for (size_t i = 0; i < 2; ++i) {
-                                _cleanup_free_ char *w = NULL;
-                                int fd;
 
-                                r = extract_first_word(&val, &w, WHITESPACE, 0);
-                                if (r < 0)
-                                        return r;
-                                if (r == 0)
-                                        break;
-
-                                fd = deserialize_fd(fds, w);
-                                if (fd < 0)
-                                        continue;
+                        r = deserialize_fd_many(fds, val, 2, rt->shared->netns_storage_socket);
+                        if (r < 0)
+                                continue;
 
-                                rt->shared->netns_storage_socket[i] = fd;
-                        }
                 } else if ((val = startswith(l, "exec-runtime-ipcns-storage-socket="))) {
-                        for (size_t i = 0; i < 2; ++i) {
-                                _cleanup_free_ char *w = NULL;
-                                int fd;
 
-                                r = extract_first_word(&val, &w, WHITESPACE, 0);
-                                if (r < 0)
-                                        return r;
-                                if (r == 0)
-                                        break;
-
-                                fd = deserialize_fd(fds, w);
-                                if (fd < 0)
-                                        continue;
+                        r = deserialize_fd_many(fds, val, 2, rt->shared->ipcns_storage_socket);
+                        if (r < 0)
+                                continue;
 
-                                rt->shared->ipcns_storage_socket[i] = fd;
-                        }
                 } else if ((val = startswith(l, "exec-runtime-dynamic-creds-user=")))
                         dynamic_user_deserialize_one(/* m= */ NULL, val, fds, &rt->dynamic_creds->user);
                 else if ((val = startswith(l, "exec-runtime-dynamic-creds-group=")))
@@ -1275,22 +1223,10 @@ static int exec_runtime_deserialize(ExecRuntime *rt, FILE *f, FDSet *fds) {
                         if (r < 0)
                                 return r;
                 } else if ((val = startswith(l, "exec-runtime-ephemeral-storage-socket="))) {
-                        for (size_t i = 0; i < 2; ++i) {
-                                _cleanup_free_ char *w = NULL;
-                                int fd;
 
-                                r = extract_first_word(&val, &w, WHITESPACE, 0);
-                                if (r < 0)
-                                        return r;
-                                if (r == 0)
-                                        break;
-
-                                fd = deserialize_fd(fds, w);
-                                if (fd < 0)
-                                        continue;
-
-                                rt->ephemeral_storage_socket[i] = fd;
-                        }
+                        r = deserialize_fd_many(fds, val, 2, rt->ephemeral_storage_socket);
+                        if (r < 0)
+                                continue;
                 } else
                         log_warning("Failed to parse serialized line, ignoring: %s", l);
         }
@@ -1338,26 +1274,7 @@ static int exec_parameters_serialize(const ExecParameters *p, FILE *f, FDSet *fd
         }
 
         if (p->n_socket_fds + p->n_storage_fds > 0) {
-                _cleanup_free_ char *serialized_fds = NULL;
-
-                if (!p->fds)
-                        return -EINVAL;
-
-                FOREACH_ARRAY(fd, p->fds, p->n_socket_fds + p->n_storage_fds) {
-                        int copy = -EBADF;
-
-                        if (*fd >= 0) {
-                                copy = fdset_put_dup(fds, *fd);
-                                if (copy < 0)
-                                        return copy;
-                        }
-
-                        r = strextendf(&serialized_fds, "%d ", copy);
-                        if (r < 0)
-                                return r;
-                }
-
-                r = serialize_item(f, "exec-parameters-fds", serialized_fds);
+                r = serialize_fd_many(f, fds, "exec-parameters-fds", p->fds, p->n_socket_fds + p->n_storage_fds);
                 if (r < 0)
                         return r;
         }
@@ -1427,19 +1344,7 @@ static int exec_parameters_serialize(const ExecParameters *p, FILE *f, FDSet *fd
         }
 
         if (exec_parameters_is_idle_pipe_set(p)) {
-                _cleanup_free_ char *serialized_fds = NULL;
-
-                for (size_t i = 0; i < 4; ++i) {
-                        int copy = fdset_put_dup(fds, p->idle_pipe[i]);
-                        if (copy < 0)
-                                return copy;
-
-                        r = strextendf(&serialized_fds, "%d ", copy);
-                        if (r < 0)
-                                return r;
-                }
-
-                r = serialize_item(f, "exec-parameters-idle-pipe", serialized_fds);
+                r = serialize_fd_many(f, fds, "exec-parameters-idle-pipe", p->idle_pipe, 4);
                 if (r < 0)
                         return r;
         }
@@ -1587,22 +1492,10 @@ static int exec_parameters_deserialize(ExecParameters *p, FILE *f, FDSet *fds) {
                         for (size_t i = 0; i < p->n_socket_fds + p->n_storage_fds; ++i)
                                 p->fds[i] = -EBADF;
 
-                        for (size_t i = 0; i < p->n_socket_fds + p->n_storage_fds; ++i) {
-                                _cleanup_free_ char *w = NULL;
-                                int fd;
-
-                                r = extract_first_word(&val, &w, WHITESPACE, 0);
-                                if (r < 0)
-                                        return r;
-                                if (r == 0)
-                                        break;
-
-                                fd = deserialize_fd(fds, w);
-                                if (fd < 0)
-                                        continue;
+                        r = deserialize_fd_many(fds, val, p->n_socket_fds + p->n_storage_fds, p->fds);
+                        if (r < 0)
+                                continue;
 
-                                p->fds[i] = fd;
-                        }
                 } else if ((val = startswith(l, "exec-parameters-fd-names="))) {
                         r = deserialize_strv(val, &p->fd_names);
                         if (r < 0)
@@ -1691,22 +1584,10 @@ static int exec_parameters_deserialize(ExecParameters *p, FILE *f, FDSet *fds) {
 
                         p->idle_pipe[0] = p->idle_pipe[1] = p->idle_pipe[2] = p->idle_pipe[3] = -EBADF;
 
-                        for (size_t i = 0; i < 4; ++i) {
-                                _cleanup_free_ char *w = NULL;
-                                int fd;
-
-                                r = extract_first_word(&val, &w, WHITESPACE, 0);
-                                if (r < 0)
-                                        return r;
-                                if (r == 0)
-                                        break;
-
-                                fd = deserialize_fd(fds, w);
-                                if (fd < 0)
-                                        continue;
+                        r = deserialize_fd_many(fds, val, 4, p->idle_pipe);
+                        if (r < 0)
+                                continue;
 
-                                p->idle_pipe[i] = fd;
-                        }
                 } else if ((val = startswith(l, "exec-parameters-stdin-fd="))) {
                         int fd;
 
index 5fecaa8702826eb8d3eb577f92ed3a63263bd201..cb1255932bb5adf8f3d3d71bffbf280120db9a5c 100644 (file)
@@ -116,6 +116,33 @@ int serialize_fd(FILE *f, FDSet *fds, const char *key, int fd) {
         return serialize_item_format(f, key, "%i", copy);
 }
 
+int serialize_fd_many(FILE *f, FDSet *fds, const char *key, const int fd_array[], size_t n_fd_array) {
+        _cleanup_free_ char *t = NULL;
+
+        assert(f);
+
+        if (n_fd_array == 0)
+                return 0;
+
+        assert(fd_array);
+
+        for (size_t i = 0; i < n_fd_array; i++) {
+                int copy;
+
+                if (fd_array[i] < 0)
+                        return -EBADF;
+
+                copy = fdset_put_dup(fds, fd_array[i]);
+                if (copy < 0)
+                        return log_error_errno(copy, "Failed to add file descriptor to serialization set: %m");
+
+                if (strextendf_with_separator(&t, " ", "%i", copy) < 0)
+                        return log_oom();
+        }
+
+        return serialize_item(f, key, t);
+}
+
 int serialize_usec(FILE *f, const char *key, usec_t usec) {
         assert(f);
         assert(key);
@@ -302,6 +329,48 @@ int deserialize_fd(FDSet *fds, const char *value) {
         return TAKE_FD(our_fd);
 }
 
+int deserialize_fd_many(FDSet *fds, const char *value, size_t n, int *ret) {
+        int r, *fd_array = NULL;
+        size_t m = 0;
+
+        assert(value);
+
+        fd_array = new(int, n);
+        if (!fd_array)
+                return -ENOMEM;
+
+        CLEANUP_ARRAY(fd_array, m, close_many_and_free);
+
+        for (;;) {
+                _cleanup_free_ char *w = NULL;
+                int fd;
+
+                r = extract_first_word(&value, &w, NULL, 0);
+                if (r < 0)
+                        return r;
+                if (r == 0) {
+                        if (m < n) /* Too few */
+                                return -EINVAL;
+
+                        break;
+                }
+
+                if (m >= n) /* Too many */
+                        return -EINVAL;
+
+                fd = deserialize_fd(fds, w);
+                if (fd < 0)
+                        return fd;
+
+                fd_array[m++] = fd;
+        }
+
+        memcpy(ret, fd_array, m * sizeof(int));
+        fd_array = mfree(fd_array);
+
+        return 0;
+}
+
 int deserialize_strv(const char *value, char ***l) {
         ssize_t unescaped_len;
         char *unescaped;
index b2dcfd21102f0945b377443e3f199ed7715d50b9..c5211191f039ada8cac011127a286003d9acda9f 100644 (file)
@@ -17,6 +17,7 @@ int serialize_item_format(FILE *f, const char *key, const char *value, ...) _pri
 int serialize_item_hexmem(FILE *f, const char *key, const void *p, size_t l);
 int serialize_item_base64mem(FILE *f, const char *key, const void *p, size_t l);
 int serialize_fd(FILE *f, FDSet *fds, const char *key, int fd);
+int serialize_fd_many(FILE *f, FDSet *fds, const char *key, const int fd_array[], size_t n_fd_array);
 int serialize_usec(FILE *f, const char *key, usec_t usec);
 int serialize_dual_timestamp(FILE *f, const char *key, const dual_timestamp *t);
 int serialize_strv(FILE *f, const char *key, char **l);
@@ -38,6 +39,7 @@ static inline int serialize_item_tristate(FILE *f, const char *key, int value) {
 int deserialize_read_line(FILE *f, char **ret);
 
 int deserialize_fd(FDSet *fds, const char *value);
+int deserialize_fd_many(FDSet *fds, const char *value, size_t n, int *ret);
 int deserialize_usec(const char *value, usec_t *ret);
 int deserialize_dual_timestamp(const char *value, dual_timestamp *ret);
 int deserialize_environment(const char *value, char ***environment);