Add monitor commands to support passing file descriptors via SCM_RIGHTS. getfd assigns the passed file descriptor a name for use with other monitor commands. closefd allows passed file descriptors to be closed. If a monitor command actually uses a named file descriptor, closefd will not be required. Signed-off-by: Mark McLoughlin <markmc@xxxxxxxxxx> --- monitor.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-monitor.hx | 18 ++++++++++++++ 2 files changed, 87 insertions(+), 0 deletions(-) diff --git a/monitor.c b/monitor.c index e38c86e..817e4b7 100644 --- a/monitor.c +++ b/monitor.c @@ -70,6 +70,14 @@ typedef struct mon_cmd_t { const char *help; } mon_cmd_t; +/* file descriptors passed via SCM_RIGHTS */ +typedef struct mon_fd_t mon_fd_t; +struct mon_fd_t { + char *name; + int fd; + LIST_ENTRY(mon_fd_t) next; +}; + struct Monitor { CharDriverState *chr; int flags; @@ -80,6 +88,7 @@ struct Monitor { CPUState *mon_cpu; BlockDriverCompletionFunc *password_completion_cb; void *password_opaque; + LIST_HEAD(,mon_fd_t) fds; LIST_ENTRY(Monitor) entry; }; @@ -1705,6 +1714,66 @@ static void do_inject_mce(Monitor *mon, } #endif +static void do_getfd(Monitor *mon, const char *fdname) +{ + mon_fd_t *monfd; + int fd; + + fd = qemu_chr_get_msgfd(mon->chr); + if (fd == -1) { + monitor_printf(mon, "getfd: no file descriptor supplied via SCM_RIGHTS\n"); + return; + } + + if (qemu_isdigit(fdname[0])) { + monitor_printf(mon, "getfd: monitor names may not begin with a number\n"); + return; + } + + fd = dup(fd); + if (fd == -1) { + monitor_printf(mon, "Failed to dup() file descriptor: %s\n", + strerror(errno)); + return; + } + + LIST_FOREACH(monfd, &mon->fds, next) { + if (strcmp(monfd->name, fdname) != 0) { + continue; + } + + close(monfd->fd); + monfd->fd = fd; + return; + } + + monfd = qemu_mallocz(sizeof(mon_fd_t)); + monfd->name = qemu_strdup(fdname); + monfd->fd = fd; + + LIST_INSERT_HEAD(&mon->fds, monfd, next); +} + +static void do_closefd(Monitor *mon, const char *fdname) +{ + mon_fd_t *monfd; + + LIST_FOREACH(monfd, &mon->fds, next) { + if (strcmp(monfd->name, fdname) != 0) { + continue; + } + + LIST_REMOVE(monfd, next); + close(monfd->fd); + qemu_free(monfd->name); + qemu_free(monfd); + return; + } + + monitor_printf(mon, "Failed to find file descriptor named %s\n", + fdname); +} + static const mon_cmd_t mon_cmds[] = { #include "qemu-monitor.h" { NULL, NULL, }, diff --git a/qemu-monitor.hx b/qemu-monitor.hx index 70e2475..11bdb2c 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -628,6 +628,24 @@ STEXI Inject an MCE on the given CPU (x86 only). ETEXI + { "getfd", "s", do_getfd, "getfd name", + "receive a file descriptor via SCM rights and assign it a name" }, +STEXI +@item getfd @var{fdname} +If a file descriptor is passed alongside this command using the SCM_RIGHTS +mechanism on unix sockets, it is stored using the name @var{fdname} for +later use by other monitor commands. +ETEXI + + { "closefd", "s", do_closefd, "closefd name", + "close a file descriptor previously passed via SCM rights" }, +STEXI +@item closefd @var{fdname} +Close the file descriptor previously assigned to @var{fdname} using the +@code{getfd} command. This is only needed if the file descriptor was never +used by another monitor command. +ETEXI + STEXI @end table ETEXI -- 1.6.2.5 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list