This uses the cached copy of LISTEN_FDNAMES to find the first file descriptorlabel with a matching label.
Note that if two file descriptors are given the same label this will ignore all but the first. This is another step toward addressing https://gitlab.com/qemu-project/qemu/-/issues/3011 Signed-off-by: Daniel Kahn Gillmor <d...@fifthhorseman.net> --- include/qemu/systemd.h | 15 +++++++++++++++ util/systemd.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/include/qemu/systemd.h b/include/qemu/systemd.h index f0ea1266d5..6b3f9a97ff 100644 --- a/include/qemu/systemd.h +++ b/include/qemu/systemd.h @@ -23,4 +23,19 @@ */ unsigned int check_socket_activation(void); + +/* + * Check if socket activation indicates named file descriptor based on + * the colon-delimited LISTEN_FDNAMES. The "label" must not be NULL, + * and should be a simple text string that does not contain a colon, + * matching the FileDescriptorName= directive in systemd.socket(5) + * + * It is acceptable to ask for the empty string as a label. + * + * Returns -1 if no socket activation is in use, or if the label does + * not match any file descriptor. Otherwise, returns the lowest + * numeric value for a file descriptor matching the label exactly. + */ +int socket_activated_fd_by_label(const char *label); + #endif diff --git a/util/systemd.c b/util/systemd.c index 1eca2bd69f..7bf4a847b2 100644 --- a/util/systemd.c +++ b/util/systemd.c @@ -97,9 +97,44 @@ unsigned int check_socket_activation(void) return nr_fds; } +int socket_activated_fd_by_label(const char *label) +{ + int nr_fds = check_socket_activation(); + if (!nr_fds) { + return -1; + } + int curfd; + const char *nameend; + const char *nameptr; + size_t labellen, namelen; + + labellen = strlen(label); + curfd = 0; + nameptr = fdnames; + do { + nameend = strchr(nameptr, ':'); + if (nameend) { + namelen = nameend - nameptr; + nameend++; + } else { + namelen = strlen(nameptr); + } + if (labellen == namelen && memcmp(nameptr, label, namelen) == 0) { + return curfd + FIRST_SOCKET_ACTIVATION_FD; + } + curfd++; + nameptr = nameend; + } while (nameptr && curfd < nr_fds); + return -1; +} + #else /* !_WIN32 */ unsigned int check_socket_activation(void) { return 0; } +unsigned int socket_activated_fd_by_label(const char *label) +{ + return 0; +} #endif -- 2.47.2