17ef88b53SMarkus Armbruster /*
27ef88b53SMarkus Armbruster * QEMU monitor file descriptor passing
37ef88b53SMarkus Armbruster *
47ef88b53SMarkus Armbruster * Copyright (c) 2003-2004 Fabrice Bellard
57ef88b53SMarkus Armbruster *
67ef88b53SMarkus Armbruster * Permission is hereby granted, free of charge, to any person obtaining a copy
77ef88b53SMarkus Armbruster * of this software and associated documentation files (the "Software"), to deal
87ef88b53SMarkus Armbruster * in the Software without restriction, including without limitation the rights
97ef88b53SMarkus Armbruster * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
107ef88b53SMarkus Armbruster * copies of the Software, and to permit persons to whom the Software is
117ef88b53SMarkus Armbruster * furnished to do so, subject to the following conditions:
127ef88b53SMarkus Armbruster *
137ef88b53SMarkus Armbruster * The above copyright notice and this permission notice shall be included in
147ef88b53SMarkus Armbruster * all copies or substantial portions of the Software.
157ef88b53SMarkus Armbruster *
167ef88b53SMarkus Armbruster * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
177ef88b53SMarkus Armbruster * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
187ef88b53SMarkus Armbruster * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
197ef88b53SMarkus Armbruster * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
207ef88b53SMarkus Armbruster * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
217ef88b53SMarkus Armbruster * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
227ef88b53SMarkus Armbruster * THE SOFTWARE.
237ef88b53SMarkus Armbruster */
247ef88b53SMarkus Armbruster
257ef88b53SMarkus Armbruster #include "qemu/osdep.h"
267ef88b53SMarkus Armbruster #include "monitor-internal.h"
277ef88b53SMarkus Armbruster #include "qapi/error.h"
287ef88b53SMarkus Armbruster #include "qapi/qapi-commands-misc.h"
297ef88b53SMarkus Armbruster #include "qapi/qmp/qerror.h"
307ef88b53SMarkus Armbruster #include "qemu/ctype.h"
317ef88b53SMarkus Armbruster #include "qemu/cutils.h"
327ef88b53SMarkus Armbruster #include "sysemu/runstate.h"
337ef88b53SMarkus Armbruster
347ef88b53SMarkus Armbruster /* file descriptors passed via SCM_RIGHTS */
357ef88b53SMarkus Armbruster typedef struct mon_fd_t mon_fd_t;
367ef88b53SMarkus Armbruster struct mon_fd_t {
377ef88b53SMarkus Armbruster char *name;
387ef88b53SMarkus Armbruster int fd;
397ef88b53SMarkus Armbruster QLIST_ENTRY(mon_fd_t) next;
407ef88b53SMarkus Armbruster };
417ef88b53SMarkus Armbruster
427ef88b53SMarkus Armbruster /* file descriptor associated with a file descriptor set */
437ef88b53SMarkus Armbruster typedef struct MonFdsetFd MonFdsetFd;
447ef88b53SMarkus Armbruster struct MonFdsetFd {
457ef88b53SMarkus Armbruster int fd;
467ef88b53SMarkus Armbruster bool removed;
477ef88b53SMarkus Armbruster char *opaque;
487ef88b53SMarkus Armbruster QLIST_ENTRY(MonFdsetFd) next;
497ef88b53SMarkus Armbruster };
507ef88b53SMarkus Armbruster
517ef88b53SMarkus Armbruster /* file descriptor set containing fds passed via SCM_RIGHTS */
527ef88b53SMarkus Armbruster typedef struct MonFdset MonFdset;
537ef88b53SMarkus Armbruster struct MonFdset {
547ef88b53SMarkus Armbruster int64_t id;
557ef88b53SMarkus Armbruster QLIST_HEAD(, MonFdsetFd) fds;
567ef88b53SMarkus Armbruster QLIST_HEAD(, MonFdsetFd) dup_fds;
577ef88b53SMarkus Armbruster QLIST_ENTRY(MonFdset) next;
587ef88b53SMarkus Armbruster };
597ef88b53SMarkus Armbruster
607ef88b53SMarkus Armbruster /* Protects mon_fdsets */
617ef88b53SMarkus Armbruster static QemuMutex mon_fdsets_lock;
627ef88b53SMarkus Armbruster static QLIST_HEAD(, MonFdset) mon_fdsets;
637ef88b53SMarkus Armbruster
monitor_add_fd(Monitor * mon,int fd,const char * fdname,Error ** errp)644cda177cSMarc-André Lureau static bool monitor_add_fd(Monitor *mon, int fd, const char *fdname, Error **errp)
654cda177cSMarc-André Lureau {
664cda177cSMarc-André Lureau mon_fd_t *monfd;
674cda177cSMarc-André Lureau
684cda177cSMarc-André Lureau if (qemu_isdigit(fdname[0])) {
694cda177cSMarc-André Lureau close(fd);
704cda177cSMarc-André Lureau error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "fdname",
714cda177cSMarc-André Lureau "a name not starting with a digit");
724cda177cSMarc-André Lureau return false;
734cda177cSMarc-André Lureau }
744cda177cSMarc-André Lureau
754cda177cSMarc-André Lureau /* See close() call below. */
764cda177cSMarc-André Lureau qemu_mutex_lock(&mon->mon_lock);
774cda177cSMarc-André Lureau QLIST_FOREACH(monfd, &mon->fds, next) {
784cda177cSMarc-André Lureau int tmp_fd;
794cda177cSMarc-André Lureau
804cda177cSMarc-André Lureau if (strcmp(monfd->name, fdname) != 0) {
814cda177cSMarc-André Lureau continue;
824cda177cSMarc-André Lureau }
834cda177cSMarc-André Lureau
844cda177cSMarc-André Lureau tmp_fd = monfd->fd;
854cda177cSMarc-André Lureau monfd->fd = fd;
864cda177cSMarc-André Lureau qemu_mutex_unlock(&mon->mon_lock);
874cda177cSMarc-André Lureau /* Make sure close() is outside critical section */
884cda177cSMarc-André Lureau close(tmp_fd);
894cda177cSMarc-André Lureau return true;
904cda177cSMarc-André Lureau }
914cda177cSMarc-André Lureau
924cda177cSMarc-André Lureau monfd = g_new0(mon_fd_t, 1);
934cda177cSMarc-André Lureau monfd->name = g_strdup(fdname);
944cda177cSMarc-André Lureau monfd->fd = fd;
954cda177cSMarc-André Lureau
964cda177cSMarc-André Lureau QLIST_INSERT_HEAD(&mon->fds, monfd, next);
974cda177cSMarc-André Lureau qemu_mutex_unlock(&mon->mon_lock);
984cda177cSMarc-André Lureau return true;
994cda177cSMarc-André Lureau }
1004cda177cSMarc-André Lureau
101*4bf21c7fSMarc-André Lureau #ifdef CONFIG_POSIX
qmp_getfd(const char * fdname,Error ** errp)1027ef88b53SMarkus Armbruster void qmp_getfd(const char *fdname, Error **errp)
1037ef88b53SMarkus Armbruster {
1047ef88b53SMarkus Armbruster Monitor *cur_mon = monitor_cur();
1054cda177cSMarc-André Lureau int fd;
1067ef88b53SMarkus Armbruster
1077ef88b53SMarkus Armbruster fd = qemu_chr_fe_get_msgfd(&cur_mon->chr);
1087ef88b53SMarkus Armbruster if (fd == -1) {
1097ef88b53SMarkus Armbruster error_setg(errp, "No file descriptor supplied via SCM_RIGHTS");
1107ef88b53SMarkus Armbruster return;
1117ef88b53SMarkus Armbruster }
1127ef88b53SMarkus Armbruster
1134cda177cSMarc-André Lureau monitor_add_fd(cur_mon, fd, fdname, errp);
1147ef88b53SMarkus Armbruster }
115*4bf21c7fSMarc-André Lureau #endif
1167ef88b53SMarkus Armbruster
qmp_closefd(const char * fdname,Error ** errp)1177ef88b53SMarkus Armbruster void qmp_closefd(const char *fdname, Error **errp)
1187ef88b53SMarkus Armbruster {
1197ef88b53SMarkus Armbruster Monitor *cur_mon = monitor_cur();
1207ef88b53SMarkus Armbruster mon_fd_t *monfd;
1217ef88b53SMarkus Armbruster int tmp_fd;
1227ef88b53SMarkus Armbruster
1237ef88b53SMarkus Armbruster qemu_mutex_lock(&cur_mon->mon_lock);
1247ef88b53SMarkus Armbruster QLIST_FOREACH(monfd, &cur_mon->fds, next) {
1257ef88b53SMarkus Armbruster if (strcmp(monfd->name, fdname) != 0) {
1267ef88b53SMarkus Armbruster continue;
1277ef88b53SMarkus Armbruster }
1287ef88b53SMarkus Armbruster
1297ef88b53SMarkus Armbruster QLIST_REMOVE(monfd, next);
1307ef88b53SMarkus Armbruster tmp_fd = monfd->fd;
1317ef88b53SMarkus Armbruster g_free(monfd->name);
1327ef88b53SMarkus Armbruster g_free(monfd);
1337ef88b53SMarkus Armbruster qemu_mutex_unlock(&cur_mon->mon_lock);
1347ef88b53SMarkus Armbruster /* Make sure close() is outside critical section */
1357ef88b53SMarkus Armbruster close(tmp_fd);
1367ef88b53SMarkus Armbruster return;
1377ef88b53SMarkus Armbruster }
1387ef88b53SMarkus Armbruster
1397ef88b53SMarkus Armbruster qemu_mutex_unlock(&cur_mon->mon_lock);
1407ef88b53SMarkus Armbruster error_setg(errp, "File descriptor named '%s' not found", fdname);
1417ef88b53SMarkus Armbruster }
1427ef88b53SMarkus Armbruster
monitor_get_fd(Monitor * mon,const char * fdname,Error ** errp)1437ef88b53SMarkus Armbruster int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp)
1447ef88b53SMarkus Armbruster {
1457ef88b53SMarkus Armbruster mon_fd_t *monfd;
1467ef88b53SMarkus Armbruster
1477ef88b53SMarkus Armbruster QEMU_LOCK_GUARD(&mon->mon_lock);
1487ef88b53SMarkus Armbruster QLIST_FOREACH(monfd, &mon->fds, next) {
1497ef88b53SMarkus Armbruster int fd;
1507ef88b53SMarkus Armbruster
1517ef88b53SMarkus Armbruster if (strcmp(monfd->name, fdname) != 0) {
1527ef88b53SMarkus Armbruster continue;
1537ef88b53SMarkus Armbruster }
1547ef88b53SMarkus Armbruster
1557ef88b53SMarkus Armbruster fd = monfd->fd;
1567ef88b53SMarkus Armbruster assert(fd >= 0);
1577ef88b53SMarkus Armbruster
1587ef88b53SMarkus Armbruster /* caller takes ownership of fd */
1597ef88b53SMarkus Armbruster QLIST_REMOVE(monfd, next);
1607ef88b53SMarkus Armbruster g_free(monfd->name);
1617ef88b53SMarkus Armbruster g_free(monfd);
1627ef88b53SMarkus Armbruster
1637ef88b53SMarkus Armbruster return fd;
1647ef88b53SMarkus Armbruster }
1657ef88b53SMarkus Armbruster
1667ef88b53SMarkus Armbruster error_setg(errp, "File descriptor named '%s' has not been found", fdname);
1677ef88b53SMarkus Armbruster return -1;
1687ef88b53SMarkus Armbruster }
1697ef88b53SMarkus Armbruster
monitor_fdset_cleanup(MonFdset * mon_fdset)1707ef88b53SMarkus Armbruster static void monitor_fdset_cleanup(MonFdset *mon_fdset)
1717ef88b53SMarkus Armbruster {
1727ef88b53SMarkus Armbruster MonFdsetFd *mon_fdset_fd;
1737ef88b53SMarkus Armbruster MonFdsetFd *mon_fdset_fd_next;
1747ef88b53SMarkus Armbruster
1757ef88b53SMarkus Armbruster QLIST_FOREACH_SAFE(mon_fdset_fd, &mon_fdset->fds, next, mon_fdset_fd_next) {
1767ef88b53SMarkus Armbruster if ((mon_fdset_fd->removed ||
1777ef88b53SMarkus Armbruster (QLIST_EMPTY(&mon_fdset->dup_fds) && mon_refcount == 0)) &&
1787ef88b53SMarkus Armbruster runstate_is_running()) {
1797ef88b53SMarkus Armbruster close(mon_fdset_fd->fd);
1807ef88b53SMarkus Armbruster g_free(mon_fdset_fd->opaque);
1817ef88b53SMarkus Armbruster QLIST_REMOVE(mon_fdset_fd, next);
1827ef88b53SMarkus Armbruster g_free(mon_fdset_fd);
1837ef88b53SMarkus Armbruster }
1847ef88b53SMarkus Armbruster }
1857ef88b53SMarkus Armbruster
1867ef88b53SMarkus Armbruster if (QLIST_EMPTY(&mon_fdset->fds) && QLIST_EMPTY(&mon_fdset->dup_fds)) {
1877ef88b53SMarkus Armbruster QLIST_REMOVE(mon_fdset, next);
1887ef88b53SMarkus Armbruster g_free(mon_fdset);
1897ef88b53SMarkus Armbruster }
1907ef88b53SMarkus Armbruster }
1917ef88b53SMarkus Armbruster
monitor_fdsets_cleanup(void)1927ef88b53SMarkus Armbruster void monitor_fdsets_cleanup(void)
1937ef88b53SMarkus Armbruster {
1947ef88b53SMarkus Armbruster MonFdset *mon_fdset;
1957ef88b53SMarkus Armbruster MonFdset *mon_fdset_next;
1967ef88b53SMarkus Armbruster
1977ef88b53SMarkus Armbruster QEMU_LOCK_GUARD(&mon_fdsets_lock);
1987ef88b53SMarkus Armbruster QLIST_FOREACH_SAFE(mon_fdset, &mon_fdsets, next, mon_fdset_next) {
1997ef88b53SMarkus Armbruster monitor_fdset_cleanup(mon_fdset);
2007ef88b53SMarkus Armbruster }
2017ef88b53SMarkus Armbruster }
2027ef88b53SMarkus Armbruster
qmp_add_fd(bool has_fdset_id,int64_t fdset_id,const char * opaque,Error ** errp)2037ef88b53SMarkus Armbruster AddfdInfo *qmp_add_fd(bool has_fdset_id, int64_t fdset_id,
2047ef88b53SMarkus Armbruster const char *opaque, Error **errp)
2057ef88b53SMarkus Armbruster {
2067ef88b53SMarkus Armbruster int fd;
2077ef88b53SMarkus Armbruster Monitor *mon = monitor_cur();
2087ef88b53SMarkus Armbruster AddfdInfo *fdinfo;
2097ef88b53SMarkus Armbruster
2107ef88b53SMarkus Armbruster fd = qemu_chr_fe_get_msgfd(&mon->chr);
2117ef88b53SMarkus Armbruster if (fd == -1) {
2127ef88b53SMarkus Armbruster error_setg(errp, "No file descriptor supplied via SCM_RIGHTS");
2137ef88b53SMarkus Armbruster goto error;
2147ef88b53SMarkus Armbruster }
2157ef88b53SMarkus Armbruster
2167ef88b53SMarkus Armbruster fdinfo = monitor_fdset_add_fd(fd, has_fdset_id, fdset_id, opaque, errp);
2177ef88b53SMarkus Armbruster if (fdinfo) {
2187ef88b53SMarkus Armbruster return fdinfo;
2197ef88b53SMarkus Armbruster }
2207ef88b53SMarkus Armbruster
2217ef88b53SMarkus Armbruster error:
2227ef88b53SMarkus Armbruster if (fd != -1) {
2237ef88b53SMarkus Armbruster close(fd);
2247ef88b53SMarkus Armbruster }
2257ef88b53SMarkus Armbruster return NULL;
2267ef88b53SMarkus Armbruster }
2277ef88b53SMarkus Armbruster
2284cda177cSMarc-André Lureau #ifdef WIN32
qmp_get_win32_socket(const char * infos,const char * fdname,Error ** errp)2294cda177cSMarc-André Lureau void qmp_get_win32_socket(const char *infos, const char *fdname, Error **errp)
2304cda177cSMarc-André Lureau {
2314cda177cSMarc-André Lureau g_autofree WSAPROTOCOL_INFOW *info = NULL;
2324cda177cSMarc-André Lureau gsize len;
2334cda177cSMarc-André Lureau SOCKET sk;
2344cda177cSMarc-André Lureau int fd;
2354cda177cSMarc-André Lureau
2364cda177cSMarc-André Lureau info = (void *)g_base64_decode(infos, &len);
2374cda177cSMarc-André Lureau if (len != sizeof(*info)) {
2384cda177cSMarc-André Lureau error_setg(errp, "Invalid WSAPROTOCOL_INFOW value");
2394cda177cSMarc-André Lureau return;
2404cda177cSMarc-André Lureau }
2414cda177cSMarc-André Lureau
2424cda177cSMarc-André Lureau sk = WSASocketW(FROM_PROTOCOL_INFO,
2434cda177cSMarc-André Lureau FROM_PROTOCOL_INFO,
2444cda177cSMarc-André Lureau FROM_PROTOCOL_INFO,
2454cda177cSMarc-André Lureau info, 0, 0);
2464cda177cSMarc-André Lureau if (sk == INVALID_SOCKET) {
2474cda177cSMarc-André Lureau error_setg_win32(errp, WSAGetLastError(), "Couldn't import socket");
2484cda177cSMarc-André Lureau return;
2494cda177cSMarc-André Lureau }
2504cda177cSMarc-André Lureau
2514cda177cSMarc-André Lureau fd = _open_osfhandle(sk, _O_BINARY);
2524cda177cSMarc-André Lureau if (fd < 0) {
2534cda177cSMarc-André Lureau error_setg_errno(errp, errno, "Failed to associate a FD with the SOCKET");
2544cda177cSMarc-André Lureau closesocket(sk);
2554cda177cSMarc-André Lureau return;
2564cda177cSMarc-André Lureau }
2574cda177cSMarc-André Lureau
2584cda177cSMarc-André Lureau monitor_add_fd(monitor_cur(), fd, fdname, errp);
2594cda177cSMarc-André Lureau }
2604cda177cSMarc-André Lureau #endif
2614cda177cSMarc-André Lureau
2624cda177cSMarc-André Lureau
qmp_remove_fd(int64_t fdset_id,bool has_fd,int64_t fd,Error ** errp)2637ef88b53SMarkus Armbruster void qmp_remove_fd(int64_t fdset_id, bool has_fd, int64_t fd, Error **errp)
2647ef88b53SMarkus Armbruster {
2657ef88b53SMarkus Armbruster MonFdset *mon_fdset;
2667ef88b53SMarkus Armbruster MonFdsetFd *mon_fdset_fd;
2677ef88b53SMarkus Armbruster char fd_str[60];
2687ef88b53SMarkus Armbruster
2697ef88b53SMarkus Armbruster QEMU_LOCK_GUARD(&mon_fdsets_lock);
2707ef88b53SMarkus Armbruster QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
2717ef88b53SMarkus Armbruster if (mon_fdset->id != fdset_id) {
2727ef88b53SMarkus Armbruster continue;
2737ef88b53SMarkus Armbruster }
2747ef88b53SMarkus Armbruster QLIST_FOREACH(mon_fdset_fd, &mon_fdset->fds, next) {
2757ef88b53SMarkus Armbruster if (has_fd) {
2767ef88b53SMarkus Armbruster if (mon_fdset_fd->fd != fd) {
2777ef88b53SMarkus Armbruster continue;
2787ef88b53SMarkus Armbruster }
2797ef88b53SMarkus Armbruster mon_fdset_fd->removed = true;
2807ef88b53SMarkus Armbruster break;
2817ef88b53SMarkus Armbruster } else {
2827ef88b53SMarkus Armbruster mon_fdset_fd->removed = true;
2837ef88b53SMarkus Armbruster }
2847ef88b53SMarkus Armbruster }
2857ef88b53SMarkus Armbruster if (has_fd && !mon_fdset_fd) {
2867ef88b53SMarkus Armbruster goto error;
2877ef88b53SMarkus Armbruster }
2887ef88b53SMarkus Armbruster monitor_fdset_cleanup(mon_fdset);
2897ef88b53SMarkus Armbruster return;
2907ef88b53SMarkus Armbruster }
2917ef88b53SMarkus Armbruster
2927ef88b53SMarkus Armbruster error:
2937ef88b53SMarkus Armbruster if (has_fd) {
2947ef88b53SMarkus Armbruster snprintf(fd_str, sizeof(fd_str), "fdset-id:%" PRId64 ", fd:%" PRId64,
2957ef88b53SMarkus Armbruster fdset_id, fd);
2967ef88b53SMarkus Armbruster } else {
2977ef88b53SMarkus Armbruster snprintf(fd_str, sizeof(fd_str), "fdset-id:%" PRId64, fdset_id);
2987ef88b53SMarkus Armbruster }
2997ef88b53SMarkus Armbruster error_setg(errp, "File descriptor named '%s' not found", fd_str);
3007ef88b53SMarkus Armbruster }
3017ef88b53SMarkus Armbruster
qmp_query_fdsets(Error ** errp)3027ef88b53SMarkus Armbruster FdsetInfoList *qmp_query_fdsets(Error **errp)
3037ef88b53SMarkus Armbruster {
3047ef88b53SMarkus Armbruster MonFdset *mon_fdset;
3057ef88b53SMarkus Armbruster MonFdsetFd *mon_fdset_fd;
3067ef88b53SMarkus Armbruster FdsetInfoList *fdset_list = NULL;
3077ef88b53SMarkus Armbruster
3087ef88b53SMarkus Armbruster QEMU_LOCK_GUARD(&mon_fdsets_lock);
3097ef88b53SMarkus Armbruster QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
3107ef88b53SMarkus Armbruster FdsetInfo *fdset_info = g_malloc0(sizeof(*fdset_info));
3117ef88b53SMarkus Armbruster
3127ef88b53SMarkus Armbruster fdset_info->fdset_id = mon_fdset->id;
3137ef88b53SMarkus Armbruster
3147ef88b53SMarkus Armbruster QLIST_FOREACH(mon_fdset_fd, &mon_fdset->fds, next) {
3157ef88b53SMarkus Armbruster FdsetFdInfo *fdsetfd_info;
3167ef88b53SMarkus Armbruster
3177ef88b53SMarkus Armbruster fdsetfd_info = g_malloc0(sizeof(*fdsetfd_info));
3187ef88b53SMarkus Armbruster fdsetfd_info->fd = mon_fdset_fd->fd;
3197ef88b53SMarkus Armbruster fdsetfd_info->opaque = g_strdup(mon_fdset_fd->opaque);
3207ef88b53SMarkus Armbruster
3217ef88b53SMarkus Armbruster QAPI_LIST_PREPEND(fdset_info->fds, fdsetfd_info);
3227ef88b53SMarkus Armbruster }
3237ef88b53SMarkus Armbruster
3247ef88b53SMarkus Armbruster QAPI_LIST_PREPEND(fdset_list, fdset_info);
3257ef88b53SMarkus Armbruster }
3267ef88b53SMarkus Armbruster
3277ef88b53SMarkus Armbruster return fdset_list;
3287ef88b53SMarkus Armbruster }
3297ef88b53SMarkus Armbruster
monitor_fdset_add_fd(int fd,bool has_fdset_id,int64_t fdset_id,const char * opaque,Error ** errp)3307ef88b53SMarkus Armbruster AddfdInfo *monitor_fdset_add_fd(int fd, bool has_fdset_id, int64_t fdset_id,
3317ef88b53SMarkus Armbruster const char *opaque, Error **errp)
3327ef88b53SMarkus Armbruster {
3337ef88b53SMarkus Armbruster MonFdset *mon_fdset = NULL;
3347ef88b53SMarkus Armbruster MonFdsetFd *mon_fdset_fd;
3357ef88b53SMarkus Armbruster AddfdInfo *fdinfo;
3367ef88b53SMarkus Armbruster
3377ef88b53SMarkus Armbruster QEMU_LOCK_GUARD(&mon_fdsets_lock);
3387ef88b53SMarkus Armbruster if (has_fdset_id) {
3397ef88b53SMarkus Armbruster QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
3407ef88b53SMarkus Armbruster /* Break if match found or match impossible due to ordering by ID */
3417ef88b53SMarkus Armbruster if (fdset_id <= mon_fdset->id) {
3427ef88b53SMarkus Armbruster if (fdset_id < mon_fdset->id) {
3437ef88b53SMarkus Armbruster mon_fdset = NULL;
3447ef88b53SMarkus Armbruster }
3457ef88b53SMarkus Armbruster break;
3467ef88b53SMarkus Armbruster }
3477ef88b53SMarkus Armbruster }
3487ef88b53SMarkus Armbruster }
3497ef88b53SMarkus Armbruster
3507ef88b53SMarkus Armbruster if (mon_fdset == NULL) {
3517ef88b53SMarkus Armbruster int64_t fdset_id_prev = -1;
3527ef88b53SMarkus Armbruster MonFdset *mon_fdset_cur = QLIST_FIRST(&mon_fdsets);
3537ef88b53SMarkus Armbruster
3547ef88b53SMarkus Armbruster if (has_fdset_id) {
3557ef88b53SMarkus Armbruster if (fdset_id < 0) {
3567ef88b53SMarkus Armbruster error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "fdset-id",
3577ef88b53SMarkus Armbruster "a non-negative value");
3587ef88b53SMarkus Armbruster return NULL;
3597ef88b53SMarkus Armbruster }
3607ef88b53SMarkus Armbruster /* Use specified fdset ID */
3617ef88b53SMarkus Armbruster QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
3627ef88b53SMarkus Armbruster mon_fdset_cur = mon_fdset;
3637ef88b53SMarkus Armbruster if (fdset_id < mon_fdset_cur->id) {
3647ef88b53SMarkus Armbruster break;
3657ef88b53SMarkus Armbruster }
3667ef88b53SMarkus Armbruster }
3677ef88b53SMarkus Armbruster } else {
3687ef88b53SMarkus Armbruster /* Use first available fdset ID */
3697ef88b53SMarkus Armbruster QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
3707ef88b53SMarkus Armbruster mon_fdset_cur = mon_fdset;
3717ef88b53SMarkus Armbruster if (fdset_id_prev == mon_fdset_cur->id - 1) {
3727ef88b53SMarkus Armbruster fdset_id_prev = mon_fdset_cur->id;
3737ef88b53SMarkus Armbruster continue;
3747ef88b53SMarkus Armbruster }
3757ef88b53SMarkus Armbruster break;
3767ef88b53SMarkus Armbruster }
3777ef88b53SMarkus Armbruster }
3787ef88b53SMarkus Armbruster
3797ef88b53SMarkus Armbruster mon_fdset = g_malloc0(sizeof(*mon_fdset));
3807ef88b53SMarkus Armbruster if (has_fdset_id) {
3817ef88b53SMarkus Armbruster mon_fdset->id = fdset_id;
3827ef88b53SMarkus Armbruster } else {
3837ef88b53SMarkus Armbruster mon_fdset->id = fdset_id_prev + 1;
3847ef88b53SMarkus Armbruster }
3857ef88b53SMarkus Armbruster
3867ef88b53SMarkus Armbruster /* The fdset list is ordered by fdset ID */
3877ef88b53SMarkus Armbruster if (!mon_fdset_cur) {
3887ef88b53SMarkus Armbruster QLIST_INSERT_HEAD(&mon_fdsets, mon_fdset, next);
3897ef88b53SMarkus Armbruster } else if (mon_fdset->id < mon_fdset_cur->id) {
3907ef88b53SMarkus Armbruster QLIST_INSERT_BEFORE(mon_fdset_cur, mon_fdset, next);
3917ef88b53SMarkus Armbruster } else {
3927ef88b53SMarkus Armbruster QLIST_INSERT_AFTER(mon_fdset_cur, mon_fdset, next);
3937ef88b53SMarkus Armbruster }
3947ef88b53SMarkus Armbruster }
3957ef88b53SMarkus Armbruster
3967ef88b53SMarkus Armbruster mon_fdset_fd = g_malloc0(sizeof(*mon_fdset_fd));
3977ef88b53SMarkus Armbruster mon_fdset_fd->fd = fd;
3987ef88b53SMarkus Armbruster mon_fdset_fd->removed = false;
3997ef88b53SMarkus Armbruster mon_fdset_fd->opaque = g_strdup(opaque);
4007ef88b53SMarkus Armbruster QLIST_INSERT_HEAD(&mon_fdset->fds, mon_fdset_fd, next);
4017ef88b53SMarkus Armbruster
4027ef88b53SMarkus Armbruster fdinfo = g_malloc0(sizeof(*fdinfo));
4037ef88b53SMarkus Armbruster fdinfo->fdset_id = mon_fdset->id;
4047ef88b53SMarkus Armbruster fdinfo->fd = mon_fdset_fd->fd;
4057ef88b53SMarkus Armbruster
4067ef88b53SMarkus Armbruster return fdinfo;
4077ef88b53SMarkus Armbruster }
4087ef88b53SMarkus Armbruster
monitor_fdset_dup_fd_add(int64_t fdset_id,int flags)4097ef88b53SMarkus Armbruster int monitor_fdset_dup_fd_add(int64_t fdset_id, int flags)
4107ef88b53SMarkus Armbruster {
4117ef88b53SMarkus Armbruster #ifdef _WIN32
4127ef88b53SMarkus Armbruster return -ENOENT;
4137ef88b53SMarkus Armbruster #else
4147ef88b53SMarkus Armbruster MonFdset *mon_fdset;
4157ef88b53SMarkus Armbruster
4167ef88b53SMarkus Armbruster QEMU_LOCK_GUARD(&mon_fdsets_lock);
4177ef88b53SMarkus Armbruster QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
4187ef88b53SMarkus Armbruster MonFdsetFd *mon_fdset_fd;
4197ef88b53SMarkus Armbruster MonFdsetFd *mon_fdset_fd_dup;
4207ef88b53SMarkus Armbruster int fd = -1;
4217ef88b53SMarkus Armbruster int dup_fd;
4227ef88b53SMarkus Armbruster int mon_fd_flags;
4237ef88b53SMarkus Armbruster
4247ef88b53SMarkus Armbruster if (mon_fdset->id != fdset_id) {
4257ef88b53SMarkus Armbruster continue;
4267ef88b53SMarkus Armbruster }
4277ef88b53SMarkus Armbruster
4287ef88b53SMarkus Armbruster QLIST_FOREACH(mon_fdset_fd, &mon_fdset->fds, next) {
4297ef88b53SMarkus Armbruster mon_fd_flags = fcntl(mon_fdset_fd->fd, F_GETFL);
4307ef88b53SMarkus Armbruster if (mon_fd_flags == -1) {
4317ef88b53SMarkus Armbruster return -1;
4327ef88b53SMarkus Armbruster }
4337ef88b53SMarkus Armbruster
4347ef88b53SMarkus Armbruster if ((flags & O_ACCMODE) == (mon_fd_flags & O_ACCMODE)) {
4357ef88b53SMarkus Armbruster fd = mon_fdset_fd->fd;
4367ef88b53SMarkus Armbruster break;
4377ef88b53SMarkus Armbruster }
4387ef88b53SMarkus Armbruster }
4397ef88b53SMarkus Armbruster
4407ef88b53SMarkus Armbruster if (fd == -1) {
4417ef88b53SMarkus Armbruster errno = EACCES;
4427ef88b53SMarkus Armbruster return -1;
4437ef88b53SMarkus Armbruster }
4447ef88b53SMarkus Armbruster
4457ef88b53SMarkus Armbruster dup_fd = qemu_dup_flags(fd, flags);
4467ef88b53SMarkus Armbruster if (dup_fd == -1) {
4477ef88b53SMarkus Armbruster return -1;
4487ef88b53SMarkus Armbruster }
4497ef88b53SMarkus Armbruster
4507ef88b53SMarkus Armbruster mon_fdset_fd_dup = g_malloc0(sizeof(*mon_fdset_fd_dup));
4517ef88b53SMarkus Armbruster mon_fdset_fd_dup->fd = dup_fd;
4527ef88b53SMarkus Armbruster QLIST_INSERT_HEAD(&mon_fdset->dup_fds, mon_fdset_fd_dup, next);
4537ef88b53SMarkus Armbruster return dup_fd;
4547ef88b53SMarkus Armbruster }
4557ef88b53SMarkus Armbruster
4567ef88b53SMarkus Armbruster errno = ENOENT;
4577ef88b53SMarkus Armbruster return -1;
4587ef88b53SMarkus Armbruster #endif
4597ef88b53SMarkus Armbruster }
4607ef88b53SMarkus Armbruster
monitor_fdset_dup_fd_find_remove(int dup_fd,bool remove)4617ef88b53SMarkus Armbruster static int64_t monitor_fdset_dup_fd_find_remove(int dup_fd, bool remove)
4627ef88b53SMarkus Armbruster {
4637ef88b53SMarkus Armbruster MonFdset *mon_fdset;
4647ef88b53SMarkus Armbruster MonFdsetFd *mon_fdset_fd_dup;
4657ef88b53SMarkus Armbruster
4667ef88b53SMarkus Armbruster QEMU_LOCK_GUARD(&mon_fdsets_lock);
4677ef88b53SMarkus Armbruster QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
4687ef88b53SMarkus Armbruster QLIST_FOREACH(mon_fdset_fd_dup, &mon_fdset->dup_fds, next) {
4697ef88b53SMarkus Armbruster if (mon_fdset_fd_dup->fd == dup_fd) {
4707ef88b53SMarkus Armbruster if (remove) {
4717ef88b53SMarkus Armbruster QLIST_REMOVE(mon_fdset_fd_dup, next);
4727ef88b53SMarkus Armbruster g_free(mon_fdset_fd_dup);
4737ef88b53SMarkus Armbruster if (QLIST_EMPTY(&mon_fdset->dup_fds)) {
4747ef88b53SMarkus Armbruster monitor_fdset_cleanup(mon_fdset);
4757ef88b53SMarkus Armbruster }
4767ef88b53SMarkus Armbruster return -1;
4777ef88b53SMarkus Armbruster } else {
4787ef88b53SMarkus Armbruster return mon_fdset->id;
4797ef88b53SMarkus Armbruster }
4807ef88b53SMarkus Armbruster }
4817ef88b53SMarkus Armbruster }
4827ef88b53SMarkus Armbruster }
4837ef88b53SMarkus Armbruster
4847ef88b53SMarkus Armbruster return -1;
4857ef88b53SMarkus Armbruster }
4867ef88b53SMarkus Armbruster
monitor_fdset_dup_fd_find(int dup_fd)4877ef88b53SMarkus Armbruster int64_t monitor_fdset_dup_fd_find(int dup_fd)
4887ef88b53SMarkus Armbruster {
4897ef88b53SMarkus Armbruster return monitor_fdset_dup_fd_find_remove(dup_fd, false);
4907ef88b53SMarkus Armbruster }
4917ef88b53SMarkus Armbruster
monitor_fdset_dup_fd_remove(int dup_fd)4927ef88b53SMarkus Armbruster void monitor_fdset_dup_fd_remove(int dup_fd)
4937ef88b53SMarkus Armbruster {
4947ef88b53SMarkus Armbruster monitor_fdset_dup_fd_find_remove(dup_fd, true);
4957ef88b53SMarkus Armbruster }
4967ef88b53SMarkus Armbruster
monitor_fd_param(Monitor * mon,const char * fdname,Error ** errp)4977ef88b53SMarkus Armbruster int monitor_fd_param(Monitor *mon, const char *fdname, Error **errp)
4987ef88b53SMarkus Armbruster {
4997ef88b53SMarkus Armbruster int fd;
5007ef88b53SMarkus Armbruster
5017ef88b53SMarkus Armbruster if (!qemu_isdigit(fdname[0]) && mon) {
5027ef88b53SMarkus Armbruster fd = monitor_get_fd(mon, fdname, errp);
5037ef88b53SMarkus Armbruster } else {
5047ef88b53SMarkus Armbruster fd = qemu_parse_fd(fdname);
5057ef88b53SMarkus Armbruster if (fd < 0) {
5067ef88b53SMarkus Armbruster error_setg(errp, "Invalid file descriptor number '%s'",
5077ef88b53SMarkus Armbruster fdname);
5087ef88b53SMarkus Armbruster }
5097ef88b53SMarkus Armbruster }
5107ef88b53SMarkus Armbruster
5117ef88b53SMarkus Armbruster return fd;
5127ef88b53SMarkus Armbruster }
5137ef88b53SMarkus Armbruster
monitor_fds_init(void)5147ef88b53SMarkus Armbruster static void __attribute__((__constructor__)) monitor_fds_init(void)
5157ef88b53SMarkus Armbruster {
5167ef88b53SMarkus Armbruster qemu_mutex_init(&mon_fdsets_lock);
5177ef88b53SMarkus Armbruster }
518