diff options
Diffstat (limited to 'util')
-rw-r--r-- | util/aio-wait.c | 2 | ||||
-rw-r--r-- | util/coroutine-ucontext.c | 4 | ||||
-rw-r--r-- | util/cutils.c | 109 | ||||
-rw-r--r-- | util/qemu-sockets.c | 36 |
4 files changed, 146 insertions, 5 deletions
diff --git a/util/aio-wait.c b/util/aio-wait.c index 975afdd..b8a8f86 100644 --- a/util/aio-wait.c +++ b/util/aio-wait.c @@ -34,7 +34,7 @@ static void dummy_bh_cb(void *opaque) void aio_wait_kick(AioWait *wait) { /* The barrier (or an atomic op) is in the caller. */ - if (atomic_read(&wait->need_kick)) { + if (atomic_read(&wait->num_waiters)) { aio_bh_schedule_oneshot(qemu_get_aio_context(), dummy_bh_cb, NULL); } } diff --git a/util/coroutine-ucontext.c b/util/coroutine-ucontext.c index 926d340..090ba21 100644 --- a/util/coroutine-ucontext.c +++ b/util/coroutine-ucontext.c @@ -170,7 +170,7 @@ Coroutine *qemu_coroutine_new(void) } #ifdef CONFIG_VALGRIND_H -#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE +#if defined(CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE) && !defined(__clang__) /* Work around an unused variable in the valgrind.h macro... */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-but-set-variable" @@ -179,7 +179,7 @@ static inline void valgrind_stack_deregister(CoroutineUContext *co) { VALGRIND_STACK_DEREGISTER(co->valgrind_stack_id); } -#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE +#if defined(CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE) && !defined(__clang__) #pragma GCC diagnostic pop #endif #endif diff --git a/util/cutils.c b/util/cutils.c index b33ede8..0de69e6 100644 --- a/util/cutils.c +++ b/util/cutils.c @@ -298,6 +298,115 @@ static int check_strtox_error(const char *nptr, char *ep, } /** + * Convert string @nptr to an integer, and store it in @result. + * + * This is a wrapper around strtol() that is harder to misuse. + * Semantics of @nptr, @endptr, @base match strtol() with differences + * noted below. + * + * @nptr may be null, and no conversion is performed then. + * + * If no conversion is performed, store @nptr in *@endptr and return + * -EINVAL. + * + * If @endptr is null, and the string isn't fully converted, return + * -EINVAL. This is the case when the pointer that would be stored in + * a non-null @endptr points to a character other than '\0'. + * + * If the conversion overflows @result, store INT_MAX in @result, + * and return -ERANGE. + * + * If the conversion underflows @result, store INT_MIN in @result, + * and return -ERANGE. + * + * Else store the converted value in @result, and return zero. + */ +int qemu_strtoi(const char *nptr, const char **endptr, int base, + int *result) +{ + char *ep; + long long lresult; + + if (!nptr) { + if (endptr) { + *endptr = nptr; + } + return -EINVAL; + } + + errno = 0; + lresult = strtoll(nptr, &ep, base); + if (lresult < INT_MIN) { + *result = INT_MIN; + errno = ERANGE; + } else if (lresult > INT_MAX) { + *result = INT_MAX; + errno = ERANGE; + } else { + *result = lresult; + } + return check_strtox_error(nptr, ep, endptr, errno); +} + +/** + * Convert string @nptr to an unsigned integer, and store it in @result. + * + * This is a wrapper around strtoul() that is harder to misuse. + * Semantics of @nptr, @endptr, @base match strtoul() with differences + * noted below. + * + * @nptr may be null, and no conversion is performed then. + * + * If no conversion is performed, store @nptr in *@endptr and return + * -EINVAL. + * + * If @endptr is null, and the string isn't fully converted, return + * -EINVAL. This is the case when the pointer that would be stored in + * a non-null @endptr points to a character other than '\0'. + * + * If the conversion overflows @result, store UINT_MAX in @result, + * and return -ERANGE. + * + * Else store the converted value in @result, and return zero. + * + * Note that a number with a leading minus sign gets converted without + * the minus sign, checked for overflow (see above), then negated (in + * @result's type). This is exactly how strtoul() works. + */ +int qemu_strtoui(const char *nptr, const char **endptr, int base, + unsigned int *result) +{ + char *ep; + long long lresult; + + if (!nptr) { + if (endptr) { + *endptr = nptr; + } + return -EINVAL; + } + + errno = 0; + lresult = strtoull(nptr, &ep, base); + + /* Windows returns 1 for negative out-of-range values. */ + if (errno == ERANGE) { + *result = -1; + } else { + if (lresult > UINT_MAX) { + *result = UINT_MAX; + errno = ERANGE; + } else if (lresult < INT_MIN) { + *result = UINT_MAX; + errno = ERANGE; + } else { + *result = lresult; + } + } + return check_strtox_error(nptr, ep, endptr, errno); +} + +/** * Convert string @nptr to a long integer, and store it in @result. * * This is a wrapper around strtol() that is harder to misuse. diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c index 7f13e8a..8bd8bb6 100644 --- a/util/qemu-sockets.c +++ b/util/qemu-sockets.c @@ -91,6 +91,14 @@ NetworkAddressFamily inet_netfamily(int family) return NETWORK_ADDRESS_FAMILY_UNKNOWN; } +bool fd_is_socket(int fd) +{ + int optval; + socklen_t optlen = sizeof(optval); + return !qemu_getsockopt(fd, SOL_SOCKET, SO_TYPE, &optval, &optlen); +} + + /* * Matrix we're trying to apply * @@ -1034,6 +1042,30 @@ fail: return NULL; } +static int socket_get_fd(const char *fdstr, Error **errp) +{ + int fd; + if (cur_mon) { + fd = monitor_get_fd(cur_mon, fdstr, errp); + if (fd < 0) { + return -1; + } + } else { + if (qemu_strtoi(fdstr, NULL, 10, &fd) < 0) { + error_setg_errno(errp, errno, + "Unable to parse FD number %s", + fdstr); + return -1; + } + } + if (!fd_is_socket(fd)) { + error_setg(errp, "File descriptor '%s' is not a socket", fdstr); + close(fd); + return -1; + } + return fd; +} + int socket_connect(SocketAddress *addr, Error **errp) { int fd; @@ -1048,7 +1080,7 @@ int socket_connect(SocketAddress *addr, Error **errp) break; case SOCKET_ADDRESS_TYPE_FD: - fd = monitor_get_fd(cur_mon, addr->u.fd.str, errp); + fd = socket_get_fd(addr->u.fd.str, errp); break; case SOCKET_ADDRESS_TYPE_VSOCK: @@ -1075,7 +1107,7 @@ int socket_listen(SocketAddress *addr, Error **errp) break; case SOCKET_ADDRESS_TYPE_FD: - fd = monitor_get_fd(cur_mon, addr->u.fd.str, errp); + fd = socket_get_fd(addr->u.fd.str, errp); break; case SOCKET_ADDRESS_TYPE_VSOCK: |