+static
+void close_raw_fd(void *ptr)
+{
+ const int raw_fd = *((const int *) ptr);
+
+ if (raw_fd >= 0) {
+ const int ret = close(raw_fd);
+
+ if (ret) {
+ PERROR("Failed to close file descriptor %d", raw_fd);
+ }
+ }
+}
+
+static
+enum lttng_error_code add_fds_to_payload(struct lttng_dynamic_array *raw_fds,
+ struct lttng_payload *payload)
+{
+ int i;
+ enum lttng_error_code ret_code = LTTNG_OK;
+ const int fd_count = lttng_dynamic_array_get_count(raw_fds);
+
+ for (i = 0; i < fd_count; i++) {
+ int ret;
+ struct fd_handle *handle;
+ int *raw_fd = (int *) lttng_dynamic_array_get_element(
+ raw_fds, i);
+
+ handle = fd_handle_create(*raw_fd);
+ if (!handle) {
+ ret_code = LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ /* FD ownership transferred to the handle. */
+ *raw_fd = -1;
+
+ ret = lttng_payload_push_fd_handle(payload, handle);
+ fd_handle_put(handle);
+ if (ret) {
+ ret_code = LTTNG_ERR_NOMEM;
+ goto end;
+ }
+ }
+
+end:
+ return ret_code;
+}
+
+static
+ssize_t _lttcomm_recv_payload_fds_unix_sock(int sock, size_t nb_fd,
+ struct lttng_payload *payload, bool blocking)
+{
+ enum lttng_error_code add_ret;
+ ssize_t ret;
+ struct lttng_dynamic_array raw_fds;
+
+ lttng_dynamic_array_init(&raw_fds, sizeof(int), close_raw_fd);
+ ret = lttng_dynamic_array_set_count(&raw_fds, nb_fd);
+ if (ret) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ if (blocking) {
+ ret = lttcomm_recv_fds_unix_sock(
+ sock, (int *) raw_fds.buffer.data, nb_fd);
+ } else {
+ ret = lttcomm_recv_fds_unix_sock_non_block(
+ sock, (int *) raw_fds.buffer.data, nb_fd);
+ }
+
+ if (ret < 0) {
+ goto end;
+ }
+
+ add_ret = add_fds_to_payload(&raw_fds, payload);
+ if (add_ret != LTTNG_OK) {
+ ret = - (int) add_ret;
+ goto end;
+ }
+
+end:
+ lttng_dynamic_array_reset(&raw_fds);
+ return ret;
+}
+
+LTTNG_HIDDEN
+ssize_t lttcomm_recv_payload_fds_unix_sock(int sock, size_t nb_fd,
+ struct lttng_payload *payload)
+{
+ return _lttcomm_recv_payload_fds_unix_sock(sock, nb_fd, payload, true);
+}
+
+LTTNG_HIDDEN
+ssize_t lttcomm_recv_payload_fds_unix_sock_non_block(int sock, size_t nb_fd,
+ struct lttng_payload *payload)
+{
+ return _lttcomm_recv_payload_fds_unix_sock(sock, nb_fd, payload, false);
+}
+