This is the mail archive of the
cygwin-cvs@cygwin.com
mailing list for the Cygwin project.
[newlib-cygwin] Cygwin: fhandler_socket: Add derived ioctl methods
- From: Corinna Vinschen <corinna at sourceware dot org>
- To: cygwin-cvs at sourceware dot org
- Date: 22 Feb 2018 16:01:01 -0000
- Subject: [newlib-cygwin] Cygwin: fhandler_socket: Add derived ioctl methods
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=79598f94f75d9423a382ec108291619ff45f2912
commit 79598f94f75d9423a382ec108291619ff45f2912
Author: Corinna Vinschen <corinna@vinschen.de>
Date: Thu Feb 22 16:30:08 2018 +0100
Cygwin: fhandler_socket: Add derived ioctl methods
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Diff:
---
winsup/cygwin/fhandler.h | 2 +
winsup/cygwin/fhandler_socket.cc | 51 +------------------------
winsup/cygwin/fhandler_socket_inet.cc | 68 ++++++++++++++++++++++++++++++++++
winsup/cygwin/fhandler_socket_local.cc | 57 ++++++++++++++++++++++++++++
4 files changed, 128 insertions(+), 50 deletions(-)
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 51a4a46..18de57c 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -670,6 +670,7 @@ class fhandler_socket_inet: public fhandler_socket
ssize_t sendmsg (const struct msghdr *msg, int flags);
ssize_t __stdcall write (const void *ptr, size_t len);
ssize_t __stdcall writev (const struct iovec *, int iovcnt, ssize_t tot = -1);
+ int ioctl (unsigned int cmd, void *);
/* from here on: CLONING */
fhandler_socket_inet (void *) {}
@@ -758,6 +759,7 @@ class fhandler_socket_local: public fhandler_socket
ssize_t sendmsg (const struct msghdr *msg, int flags);
ssize_t __stdcall write (const void *ptr, size_t len);
ssize_t __stdcall writev (const struct iovec *, int iovcnt, ssize_t tot = -1);
+ int ioctl (unsigned int cmd, void *);
int __reg2 fstat (struct stat *buf);
int __reg2 fstatvfs (struct statvfs *buf);
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index 98c4467..dfcb8d4 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -895,57 +895,8 @@ fhandler_socket::ioctl (unsigned int cmd, void *p)
}
break;
}
- /* From this point on we handle only ioctl commands which are understood by
- Winsock. However, we have a problem, which is, the different size of
- u_long in Windows and 64 bit Cygwin. This affects the definitions of
- FIOASYNC, etc, because they are defined in terms of sizeof(u_long).
- So we have to use case labels which are independent of the sizeof
- u_long. Since we're redefining u_long at the start of this file to
- matching Winsock's idea of u_long, we can use the real definitions in
- calls to Windows. In theory we also have to make sure to convert the
- different ideas of u_long between the application and Winsock, but
- fortunately, the parameters defined as u_long pointers are on Linux
- and BSD systems defined as int pointer, so the applications will
- use a type of the expected size. Hopefully. */
- case FIOASYNC:
-#ifdef __x86_64__
- case _IOW('f', 125, u_long):
-#endif
- res = WSAAsyncSelect (get_socket (), winmsg, WM_ASYNCIO,
- *(int *) p ? ASYNC_MASK : 0);
- syscall_printf ("Async I/O on socket %s",
- *(int *) p ? "started" : "cancelled");
- async_io (*(int *) p != 0);
- /* If async_io is switched off, revert the event handling. */
- if (*(int *) p == 0)
- WSAEventSelect (get_socket (), wsock_evt, EVENT_MASK);
- break;
- case FIONREAD:
-#ifdef __x86_64__
- case _IOR('f', 127, u_long):
-#endif
- /* Make sure to use the Winsock definition of FIONREAD. */
- res = ::ioctlsocket (get_socket (), _IOR('f', 127, u_long), (u_long *) p);
- if (res == SOCKET_ERROR)
- set_winsock_errno ();
- break;
default:
- /* Sockets are always non-blocking internally. So we just note the
- state here. */
-#ifdef __x86_64__
- /* Convert the different idea of u_long in the definition of cmd. */
- if (((cmd >> 16) & IOCPARM_MASK) == sizeof (unsigned long))
- cmd = (cmd & ~(IOCPARM_MASK << 16)) | (sizeof (u_long) << 16);
-#endif
- if (cmd == FIONBIO)
- {
- syscall_printf ("socket is now %sblocking",
- *(int *) p ? "non" : "");
- set_nonblocking (*(int *) p);
- res = 0;
- }
- else
- res = ::ioctlsocket (get_socket (), cmd, (u_long *) p);
+ res = fhandler_base::ioctl (cmd, p);
break;
}
syscall_printf ("%d = ioctl_socket(%x, %p)", res, cmd, p);
diff --git a/winsup/cygwin/fhandler_socket_inet.cc b/winsup/cygwin/fhandler_socket_inet.cc
index d180841..d5fe393 100644
--- a/winsup/cygwin/fhandler_socket_inet.cc
+++ b/winsup/cygwin/fhandler_socket_inet.cc
@@ -1217,3 +1217,71 @@ fhandler_socket_inet::getsockopt (int level, int optname, const void *optval,
return ret;
}
+
+int
+fhandler_socket_inet::ioctl (unsigned int cmd, void *p)
+{
+ int res;
+
+ switch (cmd)
+ {
+ /* Here we handle only ioctl commands which are understood by Winsock.
+ However, we have a problem, which is, the different size of u_long
+ in Windows and 64 bit Cygwin. This affects the definitions of
+ FIOASYNC, etc, because they are defined in terms of sizeof(u_long).
+ So we have to use case labels which are independent of the sizeof
+ u_long. Since we're redefining u_long at the start of this file to
+ matching Winsock's idea of u_long, we can use the real definitions in
+ calls to Windows. In theory we also have to make sure to convert the
+ different ideas of u_long between the application and Winsock, but
+ fortunately, the parameters defined as u_long pointers are on Linux
+ and BSD systems defined as int pointer, so the applications will
+ use a type of the expected size. Hopefully. */
+ case FIOASYNC:
+#ifdef __x86_64__
+ case _IOW('f', 125, u_long):
+#endif
+ res = WSAAsyncSelect (get_socket (), winmsg, WM_ASYNCIO,
+ *(int *) p ? ASYNC_MASK : 0);
+ syscall_printf ("Async I/O on socket %s",
+ *(int *) p ? "started" : "cancelled");
+ async_io (*(int *) p != 0);
+ /* If async_io is switched off, revert the event handling. */
+ if (*(int *) p == 0)
+ WSAEventSelect (get_socket (), wsock_evt, EVENT_MASK);
+ break;
+ case FIONREAD:
+#ifdef __x86_64__
+ case _IOR('f', 127, u_long):
+#endif
+ /* Make sure to use the Winsock definition of FIONREAD. */
+ res = ::ioctlsocket (get_socket (), _IOR('f', 127, u_long), (u_long *) p);
+ if (res == SOCKET_ERROR)
+ set_winsock_errno ();
+ break;
+ case FIONBIO:
+ case SIOCATMARK:
+ /* Sockets are always non-blocking internally. So we just note the
+ state here. */
+#ifdef __x86_64__
+ /* Convert the different idea of u_long in the definition of cmd. */
+ if (((cmd >> 16) & IOCPARM_MASK) == sizeof (unsigned long))
+ cmd = (cmd & ~(IOCPARM_MASK << 16)) | (sizeof (u_long) << 16);
+#endif
+ if (cmd == FIONBIO)
+ {
+ syscall_printf ("socket is now %sblocking",
+ *(int *) p ? "non" : "");
+ set_nonblocking (*(int *) p);
+ res = 0;
+ }
+ else
+ res = ::ioctlsocket (get_socket (), cmd, (u_long *) p);
+ break;
+ default:
+ res = fhandler_socket::ioctl (cmd, p);
+ break;
+ }
+ syscall_printf ("%d = ioctl_socket(%x, %p)", res, cmd, p);
+ return res;
+}
diff --git a/winsup/cygwin/fhandler_socket_local.cc b/winsup/cygwin/fhandler_socket_local.cc
index 4c8f334..bf34377 100644
--- a/winsup/cygwin/fhandler_socket_local.cc
+++ b/winsup/cygwin/fhandler_socket_local.cc
@@ -1907,3 +1907,60 @@ fhandler_socket_local::getsockopt (int level, int optname, const void *optval,
return ret;
}
+
+int
+fhandler_socket_local::ioctl (unsigned int cmd, void *p)
+{
+ int res;
+
+ switch (cmd)
+ {
+ /* FIXME: These have to be handled differently in future. */
+ case FIOASYNC:
+#ifdef __x86_64__
+ case _IOW('f', 125, u_long):
+#endif
+ res = WSAAsyncSelect (get_socket (), winmsg, WM_ASYNCIO,
+ *(int *) p ? ASYNC_MASK : 0);
+ syscall_printf ("Async I/O on socket %s",
+ *(int *) p ? "started" : "cancelled");
+ async_io (*(int *) p != 0);
+ /* If async_io is switched off, revert the event handling. */
+ if (*(int *) p == 0)
+ WSAEventSelect (get_socket (), wsock_evt, EVENT_MASK);
+ break;
+ case FIONREAD:
+#ifdef __x86_64__
+ case _IOR('f', 127, u_long):
+#endif
+ /* Make sure to use the Winsock definition of FIONREAD. */
+ res = ::ioctlsocket (get_socket (), _IOR('f', 127, u_long), (u_long *) p);
+ if (res == SOCKET_ERROR)
+ set_winsock_errno ();
+ break;
+ case FIONBIO:
+ case SIOCATMARK:
+ /* Sockets are always non-blocking internally. So we just note the
+ state here. */
+#ifdef __x86_64__
+ /* Convert the different idea of u_long in the definition of cmd. */
+ if (((cmd >> 16) & IOCPARM_MASK) == sizeof (unsigned long))
+ cmd = (cmd & ~(IOCPARM_MASK << 16)) | (sizeof (u_long) << 16);
+#endif
+ if (cmd == FIONBIO)
+ {
+ syscall_printf ("socket is now %sblocking",
+ *(int *) p ? "non" : "");
+ set_nonblocking (*(int *) p);
+ res = 0;
+ }
+ else
+ res = ::ioctlsocket (get_socket (), cmd, (u_long *) p);
+ break;
+ default:
+ res = fhandler_socket::ioctl (cmd, p);
+ break;
+ }
+ syscall_printf ("%d = ioctl_socket(%x, %p)", res, cmd, p);
+ return res;
+}