From 0d6531551b6bf4037017c97d7f7ece5b83739601 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Fri, 15 Jan 2010 15:40:05 +0000 Subject: [PATCH] * cygwin.din (accept4): Export. * fhandler.h (fhandler_socket::accept4): Rename from accept. Take additional flag parameter. * fhandler_socket.cc (fhandler_socket::accept4): Ditto. Handle SOCK_NONBLOCK and SOCK_CLOEXEC flags. * net.cc (cygwin_socket): Handle SOCK_NONBLOCK and SOCK_CLOEXEC flags in type. Check for invalid flag values. (socketpair): Ditto. (cygwin_accept): Accommodate renaming of fhandler_socket::accept function to accept4. (accept4): New function. * posix.sgml: Mention accept4 as GNU extensions. * include/cygwin/socket.h (SOCK_NONBLOCK): Define. (SOCK_CLOEXEC): Define. (_SOCK_FLAG_MASK): Define when building Cygwin. * include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump. * include/sys/socket.h (accept4): Declare. --- winsup/cygwin/ChangeLog | 20 +++++++++ winsup/cygwin/cygwin.din | 1 + winsup/cygwin/fhandler.h | 2 +- winsup/cygwin/fhandler_socket.cc | 10 +++-- winsup/cygwin/include/cygwin/socket.h | 10 ++++- winsup/cygwin/include/cygwin/version.h | 5 ++- winsup/cygwin/include/sys/socket.h | 4 +- winsup/cygwin/net.cc | 61 ++++++++++++++++++++++++-- winsup/cygwin/posix.sgml | 1 + 9 files changed, 102 insertions(+), 12 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index fabc6f718..e68587585 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,23 @@ +2010-01-15 Corinna Vinschen + + * cygwin.din (accept4): Export. + * fhandler.h (fhandler_socket::accept4): Rename from accept. Take + additional flag parameter. + * fhandler_socket.cc (fhandler_socket::accept4): Ditto. Handle + SOCK_NONBLOCK and SOCK_CLOEXEC flags. + * net.cc (cygwin_socket): Handle SOCK_NONBLOCK and SOCK_CLOEXEC flags + in type. Check for invalid flag values. + (socketpair): Ditto. + (cygwin_accept): Accommodate renaming of fhandler_socket::accept + function to accept4. + (accept4): New function. + * posix.sgml: Mention accept4 as GNU extensions. + * include/cygwin/socket.h (SOCK_NONBLOCK): Define. + (SOCK_CLOEXEC): Define. + (_SOCK_FLAG_MASK): Define when building Cygwin. + * include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump. + * include/sys/socket.h (accept4): Declare. + 2010-01-15 Corinna Vinschen * posix.sgml: Mention dup3 and pipe2 as GNU extensions. diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din index ec485236c..b2d2b1e47 100644 --- a/winsup/cygwin/cygwin.din +++ b/winsup/cygwin/cygwin.din @@ -37,6 +37,7 @@ _abort = abort SIGFE abs NOSIGFE _abs = abs NOSIGFE accept = cygwin_accept SIGFE +accept4 SIGFE access SIGFE _access = access SIGFE acl SIGFE diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 11162cbf1..8ef56e0df 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -505,7 +505,7 @@ class fhandler_socket: public fhandler_base int bind (const struct sockaddr *name, int namelen); int connect (const struct sockaddr *name, int namelen); int listen (int backlog); - int accept (struct sockaddr *peer, int *len); + int accept4 (struct sockaddr *peer, int *len, int flags); int getsockname (struct sockaddr *name, int *namelen); int getpeername (struct sockaddr *name, int *namelen); int getpeereid (pid_t *pid, __uid32_t *euid, __gid32_t *egid); diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index f676f85ea..b5201939d 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -1,6 +1,7 @@ /* fhandler_socket.cc. See fhandler.h for a description of the fhandler classes. - Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc. + Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, + 2009, 2010 Red Hat, Inc. This file is part of Cygwin. @@ -1193,7 +1194,7 @@ fhandler_socket::listen (int backlog) } int -fhandler_socket::accept (struct sockaddr *peer, int *len) +fhandler_socket::accept4 (struct sockaddr *peer, int *len, int flags) { /* Allows NULL peer and len parameters. */ struct sockaddr_storage lpeer; @@ -1216,7 +1217,6 @@ fhandler_socket::accept (struct sockaddr *peer, int *len) sock->set_addr_family (get_addr_family ()); sock->set_socket_type (get_socket_type ()); sock->async_io (async_io ()); - sock->set_nonblocking (is_nonblocking ()); if (get_addr_family () == AF_LOCAL) { sock->set_sun_path (get_sun_path ()); @@ -1236,6 +1236,10 @@ fhandler_socket::accept (struct sockaddr *peer, int *len) } } } + sock->set_nonblocking (flags & SOCK_NONBLOCK + ? true : is_nonblocking ()); + if (flags & SOCK_CLOEXEC) + sock->set_close_on_exec (true); /* No locking necessary at this point. */ sock->wsock_events->events = wsock_events->events | FD_WRITE; sock->wsock_events->owner = wsock_events->owner; diff --git a/winsup/cygwin/include/cygwin/socket.h b/winsup/cygwin/include/cygwin/socket.h index 44b11b75a..0f099241a 100644 --- a/winsup/cygwin/include/cygwin/socket.h +++ b/winsup/cygwin/include/cygwin/socket.h @@ -1,6 +1,6 @@ /* cygwin/socket.h - Copyright 1999, 2000, 2001, 2005, 2006, 2007, 2009 Red Hat, Inc. + Copyright 1999, 2000, 2001, 2005, 2006, 2007, 2009, 2010 Red Hat, Inc. This file is part of Cygwin. @@ -129,6 +129,14 @@ struct OLD_msghdr #define SOCK_RDM 4 /* reliably-delivered message */ #define SOCK_SEQPACKET 5 /* sequential packet socket */ +/* GNU extension flags. Or them to the type parameter in calls to + socket(2) to mark socket as nonblocking and/or close-on-exec. */ +#define SOCK_NONBLOCK 0x01000000 +#define SOCK_CLOEXEC 0x02000000 +#ifdef __INSIDE_CYGWIN__ +#define _SOCK_FLAG_MASK 0xff000000 /* Bits left for more extensions */ +#endif + /* Supported address families. */ /* * Address families. diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h index 519c3a490..156d32ebd 100644 --- a/winsup/cygwin/include/cygwin/version.h +++ b/winsup/cygwin/include/cygwin/version.h @@ -1,7 +1,7 @@ /* version.h -- Cygwin version numbers and accompanying documentation. Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2005, 2006, 2007, 2008, 2009 Red Hat, Inc. + 2005, 2006, 2007, 2008, 2009, 2010 Red Hat, Inc. This file is part of Cygwin. @@ -373,12 +373,13 @@ details. */ 217: CW_GET_INSTKEY added. 218: Export get_nprocs, get_nprocs_conf, get_phys_pages, get_avphys_pages. 219: Export dup3, pipe2, O_CLOEXEC, F_DUPFD_CLOEXEC. + 220: Export accept4, SOCK_CLOEXEC, SOCK_NONBLOCK. */ /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */ #define CYGWIN_VERSION_API_MAJOR 0 -#define CYGWIN_VERSION_API_MINOR 219 +#define CYGWIN_VERSION_API_MINOR 220 /* There is also a compatibity version number associated with the shared memory regions. It is incremented when incompatible diff --git a/winsup/cygwin/include/sys/socket.h b/winsup/cygwin/include/sys/socket.h index d4b1227ba..7eaa9e477 100644 --- a/winsup/cygwin/include/sys/socket.h +++ b/winsup/cygwin/include/sys/socket.h @@ -1,6 +1,7 @@ /* sys/socket.h - Copyright 1996-2001 Red Hat, Inc. + Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2005, 2006, + 2009, 2010 Red Hat, Inc. This file is part of Cygwin. @@ -27,6 +28,7 @@ extern "C" #ifndef __INSIDE_CYGWIN_NET__ int accept (int, struct sockaddr *__peer, socklen_t *); + int accept4 (int, struct sockaddr *__peer, socklen_t *, int flags); int bind (int, const struct sockaddr *__my_addr, socklen_t __addrlen); int connect (int, const struct sockaddr *, socklen_t); int getpeername (int, struct sockaddr *__peer, socklen_t *); diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index a7f913ac5..93d39d9e5 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -1,7 +1,7 @@ /* net.cc: network-related routines. Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2005, 2006, 2007, 2008, 2009 Red Hat, Inc. + 2005, 2006, 2007, 2008, 2009, 2010 Red Hat, Inc. This file is part of Cygwin. @@ -577,7 +577,16 @@ cygwin_socket (int af, int type, int protocol) int res = -1; SOCKET soc = 0; - debug_printf ("socket (%d, %d, %d)", af, type, protocol); + int flags = type & _SOCK_FLAG_MASK; + type &= ~_SOCK_FLAG_MASK; + + debug_printf ("socket (%d, %d (flags %p), %d)", af, type, flags, protocol); + + if ((flags & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)) != 0) + { + set_errno (EINVAL); + goto done; + } soc = socket (af == AF_LOCAL ? AF_INET : af, type, af == AF_LOCAL ? 0 : protocol); @@ -603,12 +612,17 @@ cygwin_socket (int af, int type, int protocol) { ((fhandler_socket *) fd)->set_addr_family (af); ((fhandler_socket *) fd)->set_socket_type (type); + if (flags & SOCK_NONBLOCK) + ((fhandler_socket *) fd)->set_nonblocking (true); + if (flags & SOCK_CLOEXEC) + ((fhandler_socket *) fd)->set_close_on_exec (true); res = fd; } } done: - syscall_printf ("%d = socket (%d, %d, %d)", res, af, type, protocol); + syscall_printf ("%d = socket (%d, %d (flags %p), %d)", + res, af, type, flags, protocol); return res; } @@ -1242,12 +1256,35 @@ cygwin_accept (int fd, struct sockaddr *peer, socklen_t *len) if (efault.faulted (EFAULT) || !fh) res = -1; else - res = fh->accept (peer, len); + res = fh->accept4 (peer, len, 0); syscall_printf ("%d = accept (%d, %p, %p)", res, fd, peer, len); return res; } +extern "C" int +accept4 (int fd, struct sockaddr *peer, socklen_t *len, int flags) +{ + int res; + sig_dispatch_pending (); + + fhandler_socket *fh = get (fd); + + myfault efault; + if (efault.faulted (EFAULT) || !fh) + res = -1; + else if ((flags & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)) != 0) + { + set_errno (EINVAL); + res = -1; + } + else + res = fh->accept4 (peer, len, flags); + + syscall_printf ("%d = accept4 (%d, %p, %p, %p)", res, fd, peer, len, flags); + return res; +} + /* exported as bind: standards? */ extern "C" int cygwin_bind (int fd, const struct sockaddr *my_addr, socklen_t addrlen) @@ -2777,6 +2814,9 @@ socketpair (int family, int type, int protocol, int *sb) if (efault.faulted (EFAULT)) return -1; + int flags = type & _SOCK_FLAG_MASK; + type &= ~_SOCK_FLAG_MASK; + if (family != AF_LOCAL && family != AF_INET) { set_errno (EAFNOSUPPORT); @@ -2787,6 +2827,11 @@ socketpair (int family, int type, int protocol, int *sb) set_errno (EPROTOTYPE); goto done; } + if ((flags & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)) != 0) + { + set_errno (EINVAL); + goto done; + } if ((family == AF_LOCAL && protocol != PF_UNSPEC && protocol != PF_LOCAL) || (family == AF_INET && protocol != PF_UNSPEC && protocol != PF_INET)) { @@ -2921,6 +2966,10 @@ socketpair (int family, int type, int protocol, int *sb) ((fhandler_socket *) sb0)->set_addr_family (family); ((fhandler_socket *) sb0)->set_socket_type (type); ((fhandler_socket *) sb0)->connect_state (connected); + if (flags & SOCK_NONBLOCK) + ((fhandler_socket *) sb0)->set_nonblocking (true); + if (flags & SOCK_CLOEXEC) + ((fhandler_socket *) sb0)->set_close_on_exec (true); if (family == AF_LOCAL && type == SOCK_STREAM) ((fhandler_socket *) sb0)->af_local_set_sockpair_cred (); @@ -2931,6 +2980,10 @@ socketpair (int family, int type, int protocol, int *sb) ((fhandler_socket *) sb1)->set_addr_family (family); ((fhandler_socket *) sb1)->set_socket_type (type); ((fhandler_socket *) sb1)->connect_state (connected); + if (flags & SOCK_NONBLOCK) + ((fhandler_socket *) sb1)->set_nonblocking (true); + if (flags & SOCK_CLOEXEC) + ((fhandler_socket *) sb1)->set_close_on_exec (true); if (family == AF_LOCAL && type == SOCK_STREAM) ((fhandler_socket *) sb1)->af_local_set_sockpair_cred (); diff --git a/winsup/cygwin/posix.sgml b/winsup/cygwin/posix.sgml index b68d4bad8..781685f78 100644 --- a/winsup/cygwin/posix.sgml +++ b/winsup/cygwin/posix.sgml @@ -992,6 +992,7 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008). System interfaces compatible with GNU or Linux extensions: + accept4 argz_add argz_add_sep argz_append