Commit f07918fdff76ace82b1ca3e53bbcddef069eb314
Committed by
Anthony Liguori
1 parent
7d174059
Add getfd and closefd monitor commands
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@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Showing
2 changed files
with
87 additions
and
0 deletions
monitor.c
| ... | ... | @@ -70,6 +70,14 @@ typedef struct mon_cmd_t { |
| 70 | 70 | const char *help; |
| 71 | 71 | } mon_cmd_t; |
| 72 | 72 | |
| 73 | +/* file descriptors passed via SCM_RIGHTS */ | |
| 74 | +typedef struct mon_fd_t mon_fd_t; | |
| 75 | +struct mon_fd_t { | |
| 76 | + char *name; | |
| 77 | + int fd; | |
| 78 | + LIST_ENTRY(mon_fd_t) next; | |
| 79 | +}; | |
| 80 | + | |
| 73 | 81 | struct Monitor { |
| 74 | 82 | CharDriverState *chr; |
| 75 | 83 | int flags; |
| ... | ... | @@ -80,6 +88,7 @@ struct Monitor { |
| 80 | 88 | CPUState *mon_cpu; |
| 81 | 89 | BlockDriverCompletionFunc *password_completion_cb; |
| 82 | 90 | void *password_opaque; |
| 91 | + LIST_HEAD(,mon_fd_t) fds; | |
| 83 | 92 | LIST_ENTRY(Monitor) entry; |
| 84 | 93 | }; |
| 85 | 94 | |
| ... | ... | @@ -1705,6 +1714,66 @@ static void do_inject_mce(Monitor *mon, |
| 1705 | 1714 | } |
| 1706 | 1715 | #endif |
| 1707 | 1716 | |
| 1717 | +static void do_getfd(Monitor *mon, const char *fdname) | |
| 1718 | +{ | |
| 1719 | + mon_fd_t *monfd; | |
| 1720 | + int fd; | |
| 1721 | + | |
| 1722 | + fd = qemu_chr_get_msgfd(mon->chr); | |
| 1723 | + if (fd == -1) { | |
| 1724 | + monitor_printf(mon, "getfd: no file descriptor supplied via SCM_RIGHTS\n"); | |
| 1725 | + return; | |
| 1726 | + } | |
| 1727 | + | |
| 1728 | + if (qemu_isdigit(fdname[0])) { | |
| 1729 | + monitor_printf(mon, "getfd: monitor names may not begin with a number\n"); | |
| 1730 | + return; | |
| 1731 | + } | |
| 1732 | + | |
| 1733 | + fd = dup(fd); | |
| 1734 | + if (fd == -1) { | |
| 1735 | + monitor_printf(mon, "Failed to dup() file descriptor: %s\n", | |
| 1736 | + strerror(errno)); | |
| 1737 | + return; | |
| 1738 | + } | |
| 1739 | + | |
| 1740 | + LIST_FOREACH(monfd, &mon->fds, next) { | |
| 1741 | + if (strcmp(monfd->name, fdname) != 0) { | |
| 1742 | + continue; | |
| 1743 | + } | |
| 1744 | + | |
| 1745 | + close(monfd->fd); | |
| 1746 | + monfd->fd = fd; | |
| 1747 | + return; | |
| 1748 | + } | |
| 1749 | + | |
| 1750 | + monfd = qemu_mallocz(sizeof(mon_fd_t)); | |
| 1751 | + monfd->name = qemu_strdup(fdname); | |
| 1752 | + monfd->fd = fd; | |
| 1753 | + | |
| 1754 | + LIST_INSERT_HEAD(&mon->fds, monfd, next); | |
| 1755 | +} | |
| 1756 | + | |
| 1757 | +static void do_closefd(Monitor *mon, const char *fdname) | |
| 1758 | +{ | |
| 1759 | + mon_fd_t *monfd; | |
| 1760 | + | |
| 1761 | + LIST_FOREACH(monfd, &mon->fds, next) { | |
| 1762 | + if (strcmp(monfd->name, fdname) != 0) { | |
| 1763 | + continue; | |
| 1764 | + } | |
| 1765 | + | |
| 1766 | + LIST_REMOVE(monfd, next); | |
| 1767 | + close(monfd->fd); | |
| 1768 | + qemu_free(monfd->name); | |
| 1769 | + qemu_free(monfd); | |
| 1770 | + return; | |
| 1771 | + } | |
| 1772 | + | |
| 1773 | + monitor_printf(mon, "Failed to find file descriptor named %s\n", | |
| 1774 | + fdname); | |
| 1775 | +} | |
| 1776 | + | |
| 1708 | 1777 | static const mon_cmd_t mon_cmds[] = { |
| 1709 | 1778 | #include "qemu-monitor.h" |
| 1710 | 1779 | { NULL, NULL, }, | ... | ... |
qemu-monitor.hx
| ... | ... | @@ -628,6 +628,24 @@ STEXI |
| 628 | 628 | Inject an MCE on the given CPU (x86 only). |
| 629 | 629 | ETEXI |
| 630 | 630 | |
| 631 | + { "getfd", "s", do_getfd, "getfd name", | |
| 632 | + "receive a file descriptor via SCM rights and assign it a name" }, | |
| 633 | +STEXI | |
| 634 | +@item getfd @var{fdname} | |
| 635 | +If a file descriptor is passed alongside this command using the SCM_RIGHTS | |
| 636 | +mechanism on unix sockets, it is stored using the name @var{fdname} for | |
| 637 | +later use by other monitor commands. | |
| 638 | +ETEXI | |
| 639 | + | |
| 640 | + { "closefd", "s", do_closefd, "closefd name", | |
| 641 | + "close a file descriptor previously passed via SCM rights" }, | |
| 642 | +STEXI | |
| 643 | +@item closefd @var{fdname} | |
| 644 | +Close the file descriptor previously assigned to @var{fdname} using the | |
| 645 | +@code{getfd} command. This is only needed if the file descriptor was never | |
| 646 | +used by another monitor command. | |
| 647 | +ETEXI | |
| 648 | + | |
| 631 | 649 | STEXI |
| 632 | 650 | @end table |
| 633 | 651 | ETEXI | ... | ... |