From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56841) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VLYYU-0007ce-QJ for qemu-devel@nongnu.org; Mon, 16 Sep 2013 09:09:39 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VLYYM-00079j-Cz for qemu-devel@nongnu.org; Mon, 16 Sep 2013 09:09:30 -0400 Received: from mail-lb0-x22e.google.com ([2a00:1450:4010:c04::22e]:57332) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VLYYM-00079d-4x for qemu-devel@nongnu.org; Mon, 16 Sep 2013 09:09:22 -0400 Received: by mail-lb0-f174.google.com with SMTP id w6so4123510lbh.33 for ; Mon, 16 Sep 2013 06:09:21 -0700 (PDT) From: edgar.iglesias@gmail.com Date: Mon, 16 Sep 2013 15:08:06 +0200 Message-Id: <1379336886-14715-1-git-send-email-edgar.iglesias@gmail.com> Subject: [Qemu-devel] [PATCH] linux-user: Emulate SOCK_CLOEXEC/NONBLOCK if unavailable List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Riku Voipio From: "Edgar E. Iglesias" If the host lacks support for SOCK_CLOEXEC or SOCK_NONBLOCK, try to emulate them with fcntl() FD_CLOEXEC and O_NONBLOCK. Signed-off-by: Edgar E. Iglesias --- linux-user/syscall.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index c62d875..6aa8cd7 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1701,7 +1701,7 @@ static void unlock_iovec(struct iovec *vec, abi_ulong target_addr, free(vec); } -static inline void target_to_host_sock_type(int *type) +static inline int target_to_host_sock_type(int *type) { int host_type = 0; int target_type = *type; @@ -1718,22 +1718,64 @@ static inline void target_to_host_sock_type(int *type) break; } if (target_type & TARGET_SOCK_CLOEXEC) { +#if defined(SOCK_CLOEXEC) host_type |= SOCK_CLOEXEC; +#elif !defined(FD_CLOEXEC) + return -TARGET_EINVAL; +#endif } if (target_type & TARGET_SOCK_NONBLOCK) { +#if defined(SOCK_NONBLOCK) host_type |= SOCK_NONBLOCK; +#elif !defined(O_NONBLOCK) + return -TARGET_EINVAL; +#endif } *type = host_type; + return 0; +} + +/* Try to emulate socket type flags after socket creation. */ +static int sock_flags_fixup(int fd, int target_type) +{ +#if !defined(SOCK_CLOEXEC) && defined(FD_CLOEXEC) + if (target_type & TARGET_SOCK_CLOEXEC) { + if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { + close(fd); + return -TARGET_EINVAL; + } + } +#endif +#if !defined(SOCK_NONBLOCK) && defined(O_NONBLOCK) + if (target_type & TARGET_SOCK_NONBLOCK) { + int flags = fcntl(fd, F_GETFL); + if (fcntl(fd, F_SETFL, O_NONBLOCK | flags) == -1) { + close(fd); + return -TARGET_EINVAL; + } + } +#endif + return fd; } /* do_socket() Must return target values and target errnos. */ static abi_long do_socket(int domain, int type, int protocol) { - target_to_host_sock_type(&type); + int target_type = type; + int ret; + + ret = target_to_host_sock_type(&type); + if (ret) { + return ret; + } if (domain == PF_NETLINK) return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */ - return get_errno(socket(domain, type, protocol)); + ret = get_errno(socket(domain, type, protocol)); + if (ret >= 0) { + ret = sock_flags_fixup(ret, target_type); + } + return ret; } /* do_bind() Must return target values and target errnos. */ -- 1.7.10.4