Cygwin: fhandler_socket: Add derived ioctl methods
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
		
							parent
							
								
									233bde3125
								
							
						
					
					
						commit
						79598f94f7
					
				|  | @ -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); | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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; | ||||
| } | ||||
|  |  | |||
|  | @ -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; | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue