diff options
author | scottc <scottc> | 2002-06-27 11:30:10 +0000 |
---|---|---|
committer | scottc <scottc> | 2002-06-27 11:30:10 +0000 |
commit | 73bda4ad3dc1efcd899432d78427d7aae798aba5 (patch) | |
tree | fc742e6a58746a5f68ebe28f464cf586d8201456 | |
parent | 20a9a636fcb9ce2638e71763cc027a564c75a568 (diff) | |
download | gdb-73bda4ad3dc1efcd899432d78427d7aae798aba5.tar.gz |
Merged changes from HEAD
-rw-r--r-- | winsup/cygwin/ChangeLog | 94 | ||||
-rw-r--r-- | winsup/cygwin/autoload.cc | 6 | ||||
-rw-r--r-- | winsup/cygwin/cygheap.cc | 14 | ||||
-rw-r--r-- | winsup/cygwin/dcrt0.cc | 8 | ||||
-rw-r--r-- | winsup/cygwin/environ.cc | 12 | ||||
-rw-r--r-- | winsup/cygwin/fhandler.h | 15 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_console.cc | 16 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_disk_file.cc | 45 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_socket.cc | 530 | ||||
-rw-r--r-- | winsup/cygwin/include/cygwin/version.h | 2 | ||||
-rw-r--r-- | winsup/cygwin/miscfuncs.cc | 20 | ||||
-rw-r--r-- | winsup/cygwin/net.cc | 556 | ||||
-rw-r--r-- | winsup/cygwin/path.h | 1 | ||||
-rw-r--r-- | winsup/cygwin/pwdgrp.h | 3 | ||||
-rw-r--r-- | winsup/cygwin/syscalls.cc | 22 | ||||
-rw-r--r-- | winsup/cygwin/winsup.h | 13 |
16 files changed, 813 insertions, 544 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index eac8abe4891..1e1958f2013 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,97 @@ +2002-06-26 Christopher Faylor <cgf@redhat.com> + + * fhandler_disk_file.cc (fhandler_disk_file::fstat_by_name): Force + FindFirstFile on first file of directory when asking for x:\ . + +2002-06-26 Christopher Faylor <cgf@redhat.com> + + * cygheap.cc (cygheap_user::set_name): Correct thinko in below change. + +2002-06-26 Christopher Faylor <cgf@redhat.com> + + * cygheap.cc (cygheap_user::set_name): Avoid clearing things when just + setting name to itself or during first time initialization. + + * environ.cc (check_case_init): Make case insensitive. + +2002-06-26 Corinna Vinschen <corinna@vinschen.de> + + * fhandler.h (fhandler_socket::bind): Add method definition. + (fhandler_socket::connect): Ditto. + (fhandler_socket::listen): Ditto. + (fhandler_socket::accept): Ditto. + (fhandler_socket::getsockname): Ditto. + (fhandler_socket::getpeername): Ditto. + (fhandler_socket::recvfrom): Ditto. + (fhandler_socket::recvmsg): Ditto. + (fhandler_socket::sendto): Ditto. + (fhandler_socket::sendmsg): Ditto. + (fhandler_socket::shutdown): Ditto. + * fhandler_socket.cc (get_inet_addr): Move here from net.cc. + (fhandler_socket::bind): New method. + (fhandler_socket::connect): Ditto. + (fhandler_socket::listen): Ditto. + (fhandler_socket::accept): Ditto. + (fhandler_socket::getsockname): Ditto. + (fhandler_socket::getpeername): Ditto. + (fhandler_socket::recvfrom): Ditto. + (fhandler_socket::recvmsg): Ditto. + (fhandler_socket::sendto): Ditto. + (fhandler_socket::sendmsg): Ditto. + (fhandler_socket::shutdown): Ditto. + * net.cc: Various formatting cleanups throughout. + (get_inet_addr): Move to fhandler_socket.cc. + (cygwin_bind): Move base functionality to appropriate fhandler_socket + method. + (cygwin_connect): Ditto. + (cygwin_listen): Ditto. + (cygwin_accept): Ditto. + (cygwin_getsockname): Ditto. + (cygwin_getpeername): Ditto. + (cygwin_recvfrom): Ditto. + (cygwin_recvmsg): Ditto. + (cygwin_sendto): Ditto. + (cygwin_sendmsg): Ditto. + (cygwin_shutdown): Ditto. + +2002-06-26 Corinna Vinschen <corinna@vinschen.de> + + * pwdgrp.h (pwdgrp_read::~pwdgrp_read): Avoid compiler warning. + +2002-06-26 Christopher Faylor <cgf@redhat.com> + + * dcrt0.cc (_dcrt0): Be more defensive when reserved block is used and + it's not cygwin info. + +2002-06-26 Christopher Faylor <cgf@redhat.com> + + * autoload (noload): Avoid clobbering bx register. + + * environ.cc (codepage_init): Use case insensitive match. + + * fhandler_console.cc (cp_get_internal): Delete. + (con_to_str): Use get_cp to derive code page. + (str_to_con): Ditto. + * miscfuncs.cc (get_cp): New function. + (sys_wcstombs): New function. Converted from macro. + (sys_mbstowcs): Ditto. + * winsup.h: Reflect above changes. + +2002-06-26 Christopher Faylor <cgf@redhat.com> + + * winsup.h: Minor cleanup. + * path.h (path_conv::[]): New operator. + * syscalls.cc (_link): Use path_conv operators rather than methods, + where appropriate. Minor white space cleanup. + +2002-06-26 Christopher Faylor <cgf@redhat.com> + + * include/cygwin/version.h: Bump DLL minor number. + +2002-06-25 Christopher Faylor <cgf@redhat.com> + + * dcrt0.cc (sm): Make NO_COPY. + 2002-06-25 Corinna Vinschen <corinna@vinschen.de> * syscalls.cc (chown): Convert uid to 32 bit. diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 9bae17deb5c..d910b43ed1f 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -122,10 +122,10 @@ noload: \n\ jz 1f # Nope. \n\ decl %eax # Yes. This is the # of bytes + 1 \n\ popl %edx # Caller's caller \n\ - movl %eax,%ebx # For manipulation \n\ - andl $0xffff,%eax # Only want lower word \n\ addl %eax,%esp # Pop off bytes \n\ - pushl %ebx # Save for later \n\ + andl $0xffff0000,%eax# upper word \n\ + subl %eax,%esp # adjust for possible return value \n\ + pushl %eax # Save for later \n\ movl $127,%eax # ERROR_PROC_NOT_FOUND \n\ pushl %eax # First argument \n\ call _SetLastError@4 # Set it \n\ diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc index 0522255f654..561e9330f17 100644 --- a/winsup/cygwin/cygheap.cc +++ b/winsup/cygwin/cygheap.cc @@ -440,9 +440,19 @@ cygheap_user::~cygheap_user () void cygheap_user::set_name (const char *new_name) { - if (pname) - cfree (pname); + bool allocated = !!pname; + + if (allocated) + { + if (strcasematch (new_name, pname)) + return; + cfree (pname); + } + pname = cstrdup (new_name ? new_name : ""); + if (!allocated) + return; /* Initializing. Don't bother with other stuff. */ + homedrive = NULL; homepath = NULL; if (plogsrv) diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index afec2173e4e..854e52585a4 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -451,7 +451,7 @@ check_sanity_and_sync (per_process *p) } child_info NO_COPY *child_proc_info = NULL; -static MEMORY_BASIC_INFORMATION sm; +static MEMORY_BASIC_INFORMATION NO_COPY sm; #define CYGWIN_GUARD ((wincap.has_page_guard ()) ? PAGE_GUARD : PAGE_NOACCESS) @@ -820,8 +820,10 @@ _dll_crt0 () GetStartupInfo (&si); child_proc_info = (child_info *) si.lpReserved2; - if (si.cbReserved2 >= EXEC_MAGIC_SIZE && - memcmp (child_proc_info->zero, zeros, sizeof (zeros)) == 0) + if (si.cbReserved2 < EXEC_MAGIC_SIZE || !child_proc_info + || memcmp (child_proc_info->zero, zeros, sizeof (zeros)) != 0) + child_proc_info = NULL; + else { if ((child_proc_info->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC) multiple_cygwin_problem ("proc", child_proc_info->intro, 0); diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc index 9fc4d0ab81a..114fce7f032 100644 --- a/winsup/cygwin/environ.cc +++ b/winsup/cygwin/environ.cc @@ -411,12 +411,12 @@ check_case_init (const char *buf) pcheck_case = PCHECK_RELAXED; debug_printf ("File case checking set to RELAXED"); } - else if (strcmp (buf, "adjust")== 0) + else if (strcasematch (buf, "adjust")) { pcheck_case = PCHECK_ADJUST; debug_printf ("File case checking set to ADJUST"); } - else if (strcmp (buf, "strict")== 0) + else if (strcasematch (buf, "strict")) { pcheck_case = PCHECK_STRICT; debug_printf ("File case checking set to STRICT"); @@ -448,20 +448,18 @@ codepage_init (const char *buf) if (!buf || !*buf) return; - if (strcmp (buf, "oem")== 0) + if (strcasematch (buf, "oem")) { current_codepage = oem_cp; set_file_api_mode (current_codepage); } - else if (strcmp (buf, "ansi")== 0) + else if (strcasematch (buf, "ansi")) { current_codepage = ansi_cp; set_file_api_mode (current_codepage); } else - { - debug_printf ("Wrong codepage name: %s", buf); - } + debug_printf ("Wrong codepage name: %s", buf); } static void diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 08bb273a46c..e0521d4efe7 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -380,15 +380,30 @@ class fhandler_socket: public fhandler_base void set_shutdown_read () {FHSETF (SHUTRD);} void set_shutdown_write () {FHSETF (SHUTWR);} + 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 getsockname (struct sockaddr *name, int *namelen); + int getpeername (struct sockaddr *name, int *namelen); + int recv (void *ptr, size_t len, unsigned int flags); int __stdcall read (void *ptr, size_t len) __attribute__ ((regparm (3))); + int recvfrom (void *ptr, size_t len, unsigned int flags, + struct sockaddr *from, int *fromlen); + int recvmsg (struct msghdr *msg, int flags); int send (const void *ptr, size_t len, unsigned int flags); int write (const void *ptr, size_t len); + int sendto (const void *ptr, size_t len, unsigned int flags, + const struct sockaddr *to, int tolen); + int sendmsg (const struct msghdr *msg, int flags); + int ioctl (unsigned int cmd, void *); int fcntl (int cmd, void *); __off64_t lseek (__off64_t, int) { return 0; } + int shutdown (int how); int close (); void hclose (HANDLE) {close ();} int dup (fhandler_base *child); diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc index cc948d3d0f7..458c5a3374e 100644 --- a/winsup/cygwin/fhandler_console.cc +++ b/winsup/cygwin/fhandler_console.cc @@ -17,7 +17,7 @@ details. */ #include <wingdi.h> #include <winuser.h> #include <wincon.h> -#include <winnls.h> // MultiByteToWideChar () and friends +#include <winnls.h> #include <ctype.h> #include <sys/cygwin.h> #include "cygerrno.h" @@ -32,16 +32,8 @@ details. */ #define CONVERT_LIMIT 4096 -/* The codepages are resolved here instead of using CP_ACP and - CP_OEMCP, so that they can later be compared for equality. */ -inline UINT -cp_get_internal () -{ - return current_codepage == ansi_cp ? GetACP() : GetOEMCP(); -} - static BOOL -cp_convert (UINT destcp, char * dest, UINT srccp, const char * src, DWORD size) +cp_convert (UINT destcp, char *dest, UINT srccp, const char *src, DWORD size) { if (!size) /* no action */; @@ -68,13 +60,13 @@ cp_convert (UINT destcp, char * dest, UINT srccp, const char * src, DWORD size) inline BOOL con_to_str (char *d, const char *s, DWORD sz) { - return cp_convert (cp_get_internal (), d, GetConsoleCP (), s, sz); + return cp_convert (get_cp (), d, GetConsoleCP (), s, sz); } inline BOOL str_to_con (char *d, const char *s, DWORD sz) { - return cp_convert (GetConsoleOutputCP (), d, cp_get_internal (), s, sz); + return cp_convert (GetConsoleOutputCP (), d, get_cp (), s, sz); } /* diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index 443612ff410..db843a41c08 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -25,6 +25,7 @@ details. */ #include "shared_info.h" #include "pinfo.h" #include <assert.h> +#include <ctype.h> #define _COMPILING_NEWLIB #include <dirent.h> @@ -103,23 +104,43 @@ fhandler_disk_file::fstat_by_name (struct __stat64 *buf, path_conv *pc) if (!pc->exists ()) { + debug_printf ("already determined that pc does not exist"); set_errno (ENOENT); res = -1; } - else if ((handle = FindFirstFile (pc->get_win32 (), &local)) == INVALID_HANDLE_VALUE) - { - __seterrno (); - res = -1; - } else { - FindClose (handle); - res = fstat_helper (buf, pc, - local.ftCreationTime, - local.ftLastAccessTime, - local.ftLastWriteTime, - local.nFileSizeHigh, - local.nFileSizeLow); + char drivebuf[5]; + char *name; + if ((*pc)[3] != '\0' || !isalpha ((*pc)[0]) || (*pc)[1] != ':' || (*pc)[2] != '\\') + name = *pc; + else + { + /* FIXME: Does this work on empty disks? */ + drivebuf[0] = (*pc)[0]; + drivebuf[1] = (*pc)[1]; + drivebuf[2] = (*pc)[2]; + drivebuf[3] = '*'; + drivebuf[4] = '\0'; + name = drivebuf; + } + + if ((handle = FindFirstFile (name, &local)) == INVALID_HANDLE_VALUE) + { + debug_printf ("FindFirstFile failed for '%s', %E", name); + __seterrno (); + res = -1; + } + else + { + FindClose (handle); + res = fstat_helper (buf, pc, + local.ftCreationTime, + local.ftLastAccessTime, + local.ftLastWriteTime, + local.nFileSizeHigh, + local.nFileSizeLow); + } } return res; } diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index 6a6e0eeba3f..24e68566e8f 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -15,6 +15,8 @@ #include "winsup.h" #include <errno.h> #include <sys/socket.h> +#include <sys/un.h> +#include <sys/uio.h> #include <asm/byteorder.h> #include <stdlib.h> @@ -36,8 +38,59 @@ #define ENTROPY_SOURCE_NAME "/dev/urandom" #define ENTROPY_SOURCE_DEV_UNIT 9 +extern fhandler_socket *fdsock (int& fd, const char *name, SOCKET soc); +extern "C" { +int sscanf (const char *, const char *, ...); +} /* End of "C" section */ + fhandler_dev_random* entropy_source; +/* cygwin internal: map sockaddr into internet domain address */ +static int +get_inet_addr (const struct sockaddr *in, int inlen, + struct sockaddr_in *out, int *outlen, int* secret = 0) +{ + int secret_buf [4]; + int* secret_ptr = (secret ? : secret_buf); + + if (in->sa_family == AF_INET) + { + *out = * (sockaddr_in *)in; + *outlen = inlen; + return 1; + } + else if (in->sa_family == AF_LOCAL) + { + int fd = _open (in->sa_data, O_RDONLY); + if (fd == -1) + return 0; + + int ret = 0; + char buf[128]; + memset (buf, 0, sizeof buf); + if (read (fd, buf, sizeof buf) != -1) + { + sockaddr_in sin; + sin.sin_family = AF_INET; + sscanf (buf + strlen (SOCKET_COOKIE), "%hu %08x-%08x-%08x-%08x", + &sin.sin_port, + secret_ptr, secret_ptr + 1, secret_ptr + 2, secret_ptr + 3); + sin.sin_port = htons (sin.sin_port); + sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + *out = sin; + *outlen = sizeof sin; + ret = 1; + } + _close (fd); + return ret; + } + else + { + set_errno (EAFNOSUPPORT); + return 0; + } +} + /**********************************************************************/ /* fhandler_socket */ @@ -93,7 +146,7 @@ fhandler_socket::create_secret_event (int* secret) struct sockaddr_in sin; int sin_len = sizeof (sin); - if (getsockname (get_socket (), (struct sockaddr*) &sin, &sin_len)) + if (::getsockname (get_socket (), (struct sockaddr*) &sin, &sin_len)) { debug_printf ("error getting local socket name (%d)", WSAGetLastError ()); return NULL; @@ -257,6 +310,293 @@ fhandler_socket::fstat (struct __stat64 *buf, path_conv *pc) } int +fhandler_socket::bind (const struct sockaddr *name, int namelen) +{ + int res = -1; + + if (name->sa_family == AF_LOCAL) + { +#define un_addr ((struct sockaddr_un *) name) + struct sockaddr_in sin; + int len = sizeof sin; + int fd; + + if (strlen (un_addr->sun_path) >= UNIX_PATH_LEN) + { + set_errno (ENAMETOOLONG); + goto out; + } + sin.sin_family = AF_INET; + sin.sin_port = 0; + sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + if (::bind (get_socket (), (sockaddr *) &sin, len)) + { + syscall_printf ("AF_LOCAL: bind failed %d", get_errno ()); + set_winsock_errno (); + goto out; + } + if (::getsockname (get_socket (), (sockaddr *) &sin, &len)) + { + syscall_printf ("AF_LOCAL: getsockname failed %d", get_errno ()); + set_winsock_errno (); + goto out; + } + + sin.sin_port = ntohs (sin.sin_port); + debug_printf ("AF_LOCAL: socket bound to port %u", sin.sin_port); + + /* bind must fail if file system socket object already exists + so _open () is called with O_EXCL flag. */ + fd = _open (un_addr->sun_path, + O_WRONLY | O_CREAT | O_EXCL | O_BINARY, + 0); + if (fd < 0) + { + if (get_errno () == EEXIST) + set_errno (EADDRINUSE); + goto out; + } + + set_connect_secret (); + + char buf[sizeof (SOCKET_COOKIE) + 80]; + __small_sprintf (buf, "%s%u ", SOCKET_COOKIE, sin.sin_port); + get_connect_secret (strchr (buf, '\0')); + len = strlen (buf) + 1; + + /* Note that the terminating nul is written. */ + if (_write (fd, buf, len) != len) + { + save_errno here; + _close (fd); + _unlink (un_addr->sun_path); + } + else + { + _close (fd); + chmod (un_addr->sun_path, + (S_IFSOCK | S_IRWXU | S_IRWXG | S_IRWXO) & ~cygheap->umask); + set_sun_path (un_addr->sun_path); + res = 0; + } +#undef un_addr + } + else if (::bind (get_socket (), name, namelen)) + set_winsock_errno (); + else + res = 0; + +out: + return res; +} + +int +fhandler_socket::connect (const struct sockaddr *name, int namelen) +{ + int res = -1; + BOOL secret_check_failed = FALSE; + BOOL in_progress = FALSE; + sockaddr_in sin; + int secret [4]; + + sigframe thisframe (mainthread); + + if (!get_inet_addr (name, namelen, &sin, &namelen, secret)) + return -1; + + res = ::connect (get_socket (), (sockaddr *) &sin, namelen); + if (res) + { + /* Special handling for connect to return the correct error code + when called on a non-blocking socket. */ + if (is_nonblocking ()) + { + DWORD err = WSAGetLastError (); + if (err == WSAEWOULDBLOCK || err == WSAEALREADY) + { + WSASetLastError (WSAEINPROGRESS); + in_progress = TRUE; + } + else if (err == WSAEINVAL) + WSASetLastError (WSAEISCONN); + } + set_winsock_errno (); + } + if (get_addr_family () == AF_LOCAL && get_socket_type () == SOCK_STREAM) + { + if (!res || in_progress) + { + if (!create_secret_event (secret)) + { + secret_check_failed = TRUE; + } + else if (in_progress) + signal_secret_event (); + } + + if (!secret_check_failed && !res) + { + if (!check_peer_secret_event (&sin, secret)) + { + debug_printf ( "accept from unauthorized server" ); + secret_check_failed = TRUE; + } + } + + if (secret_check_failed) + { + close_secret_event (); + if (res) + closesocket (res); + set_errno (ECONNREFUSED); + res = -1; + } + } + + return res; +} + +int +fhandler_socket::listen (int backlog) +{ + int res = ::listen (get_socket (), backlog); + if (res) + set_winsock_errno (); + return res; +} + +int +fhandler_socket::accept (struct sockaddr *peer, int *len) +{ + int res = -1; + BOOL secret_check_failed = FALSE; + BOOL in_progress = FALSE; + + sigframe thisframe (mainthread); + + /* Allows NULL peer and len parameters. */ + struct sockaddr_in peer_dummy; + int len_dummy; + if (!peer) + peer = (struct sockaddr *) &peer_dummy; + if (!len) + { + len_dummy = sizeof (struct sockaddr_in); + len = &len_dummy; + } + + /* accept on NT fails if len < sizeof (sockaddr_in) + * some programs set len to + * sizeof (name.sun_family) + strlen (name.sun_path) for UNIX domain + */ + if (len && ((unsigned) *len < sizeof (struct sockaddr_in))) + *len = sizeof (struct sockaddr_in); + + res = ::accept (get_socket (), peer, len); // can't use a blocking call inside a lock + + if ((SOCKET) res == (SOCKET) INVALID_SOCKET && + WSAGetLastError () == WSAEWOULDBLOCK) + in_progress = TRUE; + + if (get_addr_family () == AF_LOCAL && get_socket_type () == SOCK_STREAM) + { + if ((SOCKET) res != (SOCKET) INVALID_SOCKET || in_progress) + { + if (!create_secret_event ()) + secret_check_failed = TRUE; + else if (in_progress) + signal_secret_event (); + } + + if (!secret_check_failed && + (SOCKET) res != (SOCKET) INVALID_SOCKET) + { + if (!check_peer_secret_event ((struct sockaddr_in*) peer)) + { + debug_printf ("connect from unauthorized client"); + secret_check_failed = TRUE; + } + } + + if (secret_check_failed) + { + close_secret_event (); + if ((SOCKET) res != (SOCKET) INVALID_SOCKET) + closesocket (res); + set_errno (ECONNABORTED); + res = -1; + return res; + } + } + + cygheap_fdnew res_fd; + if (res_fd < 0) + /* FIXME: what is correct errno? */; + else if ((SOCKET) res == (SOCKET) INVALID_SOCKET) + set_winsock_errno (); + else + { + fhandler_socket* res_fh = fdsock (res_fd, get_name (), res); + if (get_addr_family () == AF_LOCAL) + res_fh->set_sun_path (get_sun_path ()); + res_fh->set_addr_family (get_addr_family ()); + res_fh->set_socket_type (get_socket_type ()); + res = res_fd; + } + + return res; +} + +int +fhandler_socket::getsockname (struct sockaddr *name, int *namelen) +{ + int res = -1; + + sigframe thisframe (mainthread); + + if (get_addr_family () == AF_LOCAL) + { + struct sockaddr_un *sun = (struct sockaddr_un *) name; + memset (sun, 0, *namelen); + sun->sun_family = AF_LOCAL; + + if (!get_sun_path ()) + sun->sun_path[0] = '\0'; + else + /* According to SUSv2 "If the actual length of the address is + greater than the length of the supplied sockaddr structure, the + stored address will be truncated." We play it save here so + that the path always has a trailing 0 even if it's truncated. */ + strncpy (sun->sun_path, get_sun_path (), + *namelen - sizeof *sun + sizeof sun->sun_path - 1); + + *namelen = sizeof *sun - sizeof sun->sun_path + + strlen (sun->sun_path) + 1; + res = 0; + } + else + { + res = ::getsockname (get_socket (), name, namelen); + if (res) + set_winsock_errno (); + } + + return res; +} + +int +fhandler_socket::getpeername (struct sockaddr *name, int *namelen) +{ + sigframe thisframe (mainthread); + + int res = ::getpeername (get_socket (), name, namelen); + if (res) + set_winsock_errno (); + + return res; +} + +int fhandler_socket::recv (void *ptr, size_t len, unsigned int flags) { int res = -1; @@ -264,6 +604,7 @@ fhandler_socket::recv (void *ptr, size_t len, unsigned int flags) LPWSAOVERLAPPED ovr; sigframe thisframe (mainthread); + if (is_nonblocking () || !(ovr = wsock_evt.prepare ())) { debug_printf ("Fallback to winsock 1 recv call"); @@ -299,6 +640,88 @@ fhandler_socket::read (void *ptr, size_t len) } int +fhandler_socket::recvfrom (void *ptr, size_t len, unsigned int flags, + struct sockaddr *from, int *fromlen) +{ + int res = -1; + wsock_event wsock_evt; + LPWSAOVERLAPPED ovr; + + sigframe thisframe (mainthread); + + if (is_nonblocking () || !(ovr = wsock_evt.prepare ())) + { + debug_printf ("Fallback to winsock 1 recvfrom call"); + if ((res = ::recvfrom (get_socket (), (char *) ptr, len, flags, from, + fromlen)) + == SOCKET_ERROR) + { + set_winsock_errno (); + res = -1; + } + } + else + { + WSABUF wsabuf = { len, (char *) ptr }; + DWORD ret = 0; + if (WSARecvFrom (get_socket (), &wsabuf, 1, &ret, (DWORD *)&flags, + from, fromlen, ovr, NULL) != SOCKET_ERROR) + res = ret; + else if ((res = WSAGetLastError ()) != WSA_IO_PENDING) + { + set_winsock_errno (); + res = -1; + } + else if ((res = wsock_evt.wait (get_socket (), (DWORD *)&flags)) == -1) + set_winsock_errno (); + } + + return res; +} + +int +fhandler_socket::recvmsg (struct msghdr *msg, int flags) +{ + int res = -1; + int nb; + size_t tot = 0; + char *buf, *p; + struct iovec *iov = msg->msg_iov; + + sigframe thisframe (mainthread); + + if (get_addr_family () == AF_LOCAL) + { + /* On AF_LOCAL sockets the (fixed-size) name of the shared memory + area used for descriptor passing is transmitted first. + If this string is empty, no descriptors are passed and we can + go ahead recv'ing the normal data blocks. Otherwise start + special handling for descriptor passing. */ + /*TODO*/ + } + for (int i = 0; i < msg->msg_iovlen; ++i) + tot += iov[i].iov_len; + buf = (char *) alloca (tot); + if (tot != 0 && buf == NULL) + { + set_errno (ENOMEM); + return -1; + } + nb = res = recvfrom (buf, tot, flags, (struct sockaddr *) msg->msg_name, + (int *) &msg->msg_namelen); + p = buf; + while (nb > 0) + { + ssize_t cnt = min(nb, iov->iov_len); + memcpy (iov->iov_base, p, cnt); + p += cnt; + nb -= cnt; + ++iov; + } + return res; +} + +int fhandler_socket::send (const void *ptr, size_t len, unsigned int flags) { int res = -1; @@ -306,6 +729,7 @@ fhandler_socket::send (const void *ptr, size_t len, unsigned int flags) LPWSAOVERLAPPED ovr; sigframe thisframe (mainthread); + if (is_nonblocking () || !(ovr = wsock_evt.prepare ())) { debug_printf ("Fallback to winsock 1 send call"); @@ -340,11 +764,111 @@ fhandler_socket::write (const void *ptr, size_t len) return send (ptr, len, 0); } -/* Cygwin internal */ +int +fhandler_socket::sendto (const void *ptr, size_t len, unsigned int flags, + const struct sockaddr *to, int tolen) +{ + int res = -1; + wsock_event wsock_evt; + LPWSAOVERLAPPED ovr; + sockaddr_in sin; + + sigframe thisframe (mainthread); + + if (!get_inet_addr (to, tolen, &sin, &tolen)) + return -1; + + if (is_nonblocking () || !(ovr = wsock_evt.prepare ())) + { + debug_printf ("Fallback to winsock 1 sendto call"); + if ((res = ::sendto (get_socket (), (const char *) ptr, len, flags, + (sockaddr *) &sin, tolen)) == SOCKET_ERROR) + { + set_winsock_errno (); + res = -1; + } + } + else + { + WSABUF wsabuf = { len, (char *) ptr }; + DWORD ret = 0; + if (WSASendTo (get_socket (), &wsabuf, 1, &ret, (DWORD)flags, + (sockaddr *) &sin, tolen, ovr, NULL) != SOCKET_ERROR) + res = ret; + else if ((res = WSAGetLastError ()) != WSA_IO_PENDING) + { + set_winsock_errno (); + res = -1; + } + else if ((res = wsock_evt.wait (get_socket (), (DWORD *)&flags)) == -1) + set_winsock_errno (); + } + + return res; +} + +int +fhandler_socket::sendmsg (const struct msghdr *msg, int flags) +{ + size_t tot = 0; + char *buf, *p; + struct iovec *iov = msg->msg_iov; + + if (get_addr_family () == AF_LOCAL) + { + /* For AF_LOCAL/AF_UNIX sockets, if descriptors are given, start + the special handling for descriptor passing. Otherwise just + transmit an empty string to tell the receiver that no + descriptor passing is done. */ + /*TODO*/ + } + for(int i = 0; i < msg->msg_iovlen; ++i) + tot += iov[i].iov_len; + buf = (char *) alloca (tot); + if (tot != 0 && buf == NULL) + { + set_errno (ENOMEM); + return -1; + } + p = buf; + for (int i = 0; i < msg->msg_iovlen; ++i) + { + memcpy (p, iov[i].iov_base, iov[i].iov_len); + p += iov[i].iov_len; + } + return sendto (buf, tot, flags, (struct sockaddr *) msg->msg_name, + msg->msg_namelen); +} + +int +fhandler_socket::shutdown (int how) +{ + int res = ::shutdown (get_socket (), how); + + if (res) + set_winsock_errno (); + else + switch (how) + { + case SHUT_RD: + set_shutdown_read (); + break; + case SHUT_WR: + set_shutdown_write (); + break; + case SHUT_RDWR: + set_shutdown_read (); + set_shutdown_write (); + break; + } + return res; +} + int fhandler_socket::close () { int res = 0; + sigframe thisframe (mainthread); /* HACK to allow a graceful shutdown even if shutdown() hasn't been @@ -381,7 +905,6 @@ fhandler_socket::close () #define ASYNC_MASK (FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT) -/* Cygwin internal */ int fhandler_socket::ioctl (unsigned int cmd, void *p) { @@ -389,6 +912,7 @@ fhandler_socket::ioctl (unsigned int cmd, void *p) int res; struct ifconf ifc, *ifcp; struct ifreq *ifr, *ifrp; + sigframe thisframe (mainthread); switch (cmd) diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h index 6ab596e094f..4c1437bc2f7 100644 --- a/winsup/cygwin/include/cygwin/version.h +++ b/winsup/cygwin/include/cygwin/version.h @@ -44,7 +44,7 @@ details. */ /* The current cygwin version is 1.3.6 */ #define CYGWIN_VERSION_DLL_MAJOR 1003 -#define CYGWIN_VERSION_DLL_MINOR 11 +#define CYGWIN_VERSION_DLL_MINOR 12 /* Major numbers before CYGWIN_VERSION_DLL_EPOCH are incompatible. */ diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc index 5d301047093..6fd9ffc9183 100644 --- a/winsup/cygwin/miscfuncs.cc +++ b/winsup/cygwin/miscfuncs.cc @@ -11,6 +11,8 @@ details. */ #include "winsup.h" #include "cygerrno.h" #include <sys/errno.h> +#include <winbase.h> +#include <winnls.h> long tls_ix = -1; @@ -176,3 +178,21 @@ __check_invalid_read_ptr_errno (const void *s, unsigned sz) return 0; return set_errno (EFAULT); } + +UINT +get_cp () +{ + return current_codepage == ansi_cp ? GetACP() : GetOEMCP(); +} + +int __stdcall +sys_wcstombs (char *tgt, const WCHAR *src, int len) +{ + return WideCharToMultiByte (get_cp (), 0, src, -1, tgt, len, NULL, NULL); +} + +int __stdcall +sys_mbstowcs (WCHAR *tgt, const char *src, int len) +{ + return MultiByteToWideChar (get_cp (), 0, src, -1, tgt, len); +} diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index 32e930392c8..d3eba725c1d 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -33,7 +33,6 @@ details. */ #include "pinfo.h" #include "registry.h" #include "wsock_event.h" -#include <sys/uio.h> extern "C" { int h_errno; @@ -558,104 +557,20 @@ done: return res; } -/* cygwin internal: map sockaddr into internet domain address */ - -static int get_inet_addr (const struct sockaddr *in, int inlen, - struct sockaddr_in *out, int *outlen, int* secret = 0) -{ - int secret_buf [4]; - int* secret_ptr = (secret ? : secret_buf); - - if (in->sa_family == AF_INET) - { - *out = * (sockaddr_in *)in; - *outlen = inlen; - return 1; - } - else if (in->sa_family == AF_LOCAL) - { - int fd = _open (in->sa_data, O_RDONLY); - if (fd == -1) - return 0; - - int ret = 0; - char buf[128]; - memset (buf, 0, sizeof buf); - if (read (fd, buf, sizeof buf) != -1) - { - sockaddr_in sin; - sin.sin_family = AF_INET; - sscanf (buf + strlen (SOCKET_COOKIE), "%hu %08x-%08x-%08x-%08x", - &sin.sin_port, - secret_ptr, secret_ptr + 1, secret_ptr + 2, secret_ptr + 3); - sin.sin_port = htons (sin.sin_port); - sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - *out = sin; - *outlen = sizeof sin; - ret = 1; - } - _close (fd); - return ret; - } - else - { - set_errno (EAFNOSUPPORT); - return 0; - } -} - /* exported as sendto: standards? */ extern "C" int -cygwin_sendto (int fd, - const void *buf, - int len, - unsigned int flags, - const struct sockaddr *to, - int tolen) +cygwin_sendto (int fd, const void *buf, int len, unsigned int flags, + const struct sockaddr *to, int tolen) { int res; - wsock_event wsock_evt; - LPWSAOVERLAPPED ovr; - fhandler_socket *h = get (fd); + fhandler_socket *fh = get (fd); if ((len && __check_invalid_read_ptr_errno (buf, (unsigned) len)) || __check_null_invalid_struct_errno (to, tolen) - || !h) + || !fh) res = -1; else - { - sockaddr_in sin; - sigframe thisframe (mainthread); - - if (get_inet_addr (to, tolen, &sin, &tolen) == 0) - return -1; - - if (h->is_nonblocking () || !(ovr = wsock_evt.prepare ())) - { - debug_printf ("Fallback to winsock 1 sendto call"); - if ((res = sendto (h->get_socket (), (const char *) buf, len, flags, - (sockaddr *) &sin, tolen)) == SOCKET_ERROR) - { - set_winsock_errno (); - res = -1; - } - } - else - { - WSABUF wsabuf = { len, (char *) buf }; - DWORD ret = 0; - if (WSASendTo (h->get_socket (), &wsabuf, 1, &ret, (DWORD)flags, - (sockaddr *) &sin, tolen, ovr, NULL) != SOCKET_ERROR) - res = ret; - else if ((res = WSAGetLastError ()) != WSA_IO_PENDING) - { - set_winsock_errno (); - res = -1; - } - else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1) - set_winsock_errno (); - } - } + res = fh->sendto (buf, len, flags, to, tolen); syscall_printf ("%d = sendto (%d, %x, %x, %x)", res, fd, buf, len, flags); @@ -664,53 +579,19 @@ cygwin_sendto (int fd, /* exported as recvfrom: standards? */ extern "C" int -cygwin_recvfrom (int fd, - char *buf, - int len, - int flags, - struct sockaddr *from, - int *fromlen) +cygwin_recvfrom (int fd, char *buf, int len, int flags, struct sockaddr *from, + int *fromlen) { int res; - wsock_event wsock_evt; - LPWSAOVERLAPPED ovr; - fhandler_socket *h = get (fd); + fhandler_socket *fh = get (fd); if (__check_null_invalid_struct_errno (buf, (unsigned) len) || check_null_invalid_struct_errno (fromlen) || (from && __check_null_invalid_struct_errno (from, (unsigned) *fromlen)) - || !h) + || !fh) res = -1; else - { - sigframe thisframe (mainthread); - - if (h->is_nonblocking () ||!(ovr = wsock_evt.prepare ())) - { - debug_printf ("Fallback to winsock 1 recvfrom call"); - if ((res = recvfrom (h->get_socket (), buf, len, flags, from, fromlen)) - == SOCKET_ERROR) - { - set_winsock_errno (); - res = -1; - } - } - else - { - WSABUF wsabuf = { len, (char *) buf }; - DWORD ret = 0; - if (WSARecvFrom (h->get_socket (), &wsabuf, 1, &ret, (DWORD *)&flags, - from, fromlen, ovr, NULL) != SOCKET_ERROR) - res = ret; - else if ((res = WSAGetLastError ()) != WSA_IO_PENDING) - { - set_winsock_errno (); - res = -1; - } - else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1) - set_winsock_errno (); - } - } + res = fh->recvfrom (buf, len, flags, from, fromlen); syscall_printf ("%d = recvfrom (%d, %x, %x, %x)", res, fd, buf, len, flags); @@ -719,17 +600,14 @@ cygwin_recvfrom (int fd, /* exported as setsockopt: standards? */ extern "C" int -cygwin_setsockopt (int fd, - int level, - int optname, - const void *optval, - int optlen) +cygwin_setsockopt (int fd, int level, int optname, const void *optval, + int optlen) { - fhandler_socket *h = get (fd); + fhandler_socket *fh = get (fd); int res = -1; const char *name = "error"; - if ((!optval || !__check_invalid_read_ptr_errno (optval, optlen)) && h) + if ((!optval || !__check_invalid_read_ptr_errno (optval, optlen)) && fh) { /* For the following debug_printf */ switch (optname) @@ -766,8 +644,8 @@ cygwin_setsockopt (int fd, break; } - res = setsockopt (h->get_socket (), level, optname, - (const char *) optval, optlen); + res = setsockopt (fh->get_socket (), level, optname, + (const char *) optval, optlen); if (optlen == 4) syscall_printf ("setsockopt optval=%x", *(long *) optval); @@ -783,18 +661,15 @@ cygwin_setsockopt (int fd, /* exported as getsockopt: standards? */ extern "C" int -cygwin_getsockopt (int fd, - int level, - int optname, - void *optval, - int *optlen) +cygwin_getsockopt (int fd, int level, int optname, void *optval, int *optlen) { - fhandler_socket *h = get (fd); + fhandler_socket *fh = get (fd); int res = -1; const char *name = "error"; if (!check_null_invalid_struct_errno (optlen) - && (!optval || !__check_null_invalid_struct_errno (optval, (unsigned) *optlen)) - && h) + && (!optval + || !__check_null_invalid_struct_errno (optval, (unsigned) *optlen)) + && fh) { /* For the following debug_printf */ switch (optname) @@ -831,8 +706,8 @@ cygwin_getsockopt (int fd, break; } - res = getsockopt (h->get_socket (), level, optname, - (char *) optval, (int *) optlen); + res = getsockopt (fh->get_socket (), level, optname, (char *) optval, + (int *) optlen); if (optname == SO_ERROR) { @@ -851,78 +726,21 @@ cygwin_getsockopt (int fd, /* exported as connect: standards? */ extern "C" int -cygwin_connect (int fd, - const struct sockaddr *name, - int namelen) +cygwin_connect (int fd, const struct sockaddr *name, int namelen) { int res; - BOOL secret_check_failed = FALSE; - BOOL in_progress = FALSE; - fhandler_socket *sock = get (fd); - sockaddr_in sin; - int secret [4]; - sigframe thisframe (mainthread); + fhandler_socket *fh = get (fd); if (__check_invalid_read_ptr_errno (name, namelen)) return -1; - if (get_inet_addr (name, namelen, &sin, &namelen, secret) == 0) - return -1; - - if (!sock) + if (!fh) res = -1; else - { - res = connect (sock->get_socket (), (sockaddr *) &sin, namelen); - if (res) - { - /* Special handling for connect to return the correct error code - when called on a non-blocking socket. */ - if (sock->is_nonblocking ()) - { - DWORD err = WSAGetLastError (); - if (err == WSAEWOULDBLOCK || err == WSAEALREADY) - { - WSASetLastError (WSAEINPROGRESS); - in_progress = TRUE; - } - else if (err == WSAEINVAL) - WSASetLastError (WSAEISCONN); - } - set_winsock_errno (); - } - if (sock->get_addr_family () == AF_LOCAL && - sock->get_socket_type () == SOCK_STREAM) - { - if (!res || in_progress) - { - if (!sock->create_secret_event (secret)) - { - secret_check_failed = TRUE; - } - else if (in_progress) - sock->signal_secret_event (); - } + res = fh->connect (name, namelen); - if (!secret_check_failed && !res) - { - if (!sock->check_peer_secret_event (&sin, secret)) - { - debug_printf ( "accept from unauthorized server" ); - secret_check_failed = TRUE; - } - } + syscall_printf ("%d = connect (%d, %x, %x)", res, fd, name, namelen); - if (secret_check_failed) - { - sock->close_secret_event (); - if (res) - closesocket (res); - set_errno (ECONNREFUSED); - res = -1; - } - } - } return res; } @@ -1179,86 +997,11 @@ cygwin_accept (int fd, struct sockaddr *peer, int *len) return -1; int res = -1; - BOOL secret_check_failed = FALSE; - BOOL in_progress = FALSE; - sigframe thisframe (mainthread); - - fhandler_socket *sock = get (fd); - if (sock) - { - /* Allows NULL peer and len parameters. */ - struct sockaddr_in peer_dummy; - int len_dummy; - if (!peer) - peer = (struct sockaddr *) &peer_dummy; - if (!len) - { - len_dummy = sizeof (struct sockaddr_in); - len = &len_dummy; - } - - /* accept on NT fails if len < sizeof (sockaddr_in) - * some programs set len to - * sizeof (name.sun_family) + strlen (name.sun_path) for UNIX domain - */ - if (len && ((unsigned) *len < sizeof (struct sockaddr_in))) - *len = sizeof (struct sockaddr_in); - - res = accept (sock->get_socket (), peer, len); // can't use a blocking call inside a lock - - if ((SOCKET) res == (SOCKET) INVALID_SOCKET && - WSAGetLastError () == WSAEWOULDBLOCK) - in_progress = TRUE; - - if (sock->get_addr_family () == AF_LOCAL && - sock->get_socket_type () == SOCK_STREAM) - { - if ((SOCKET) res != (SOCKET) INVALID_SOCKET || in_progress) - { - if (!sock->create_secret_event ()) - secret_check_failed = TRUE; - else if (in_progress) - sock->signal_secret_event (); - } - - if (!secret_check_failed && - (SOCKET) res != (SOCKET) INVALID_SOCKET) - { - if (!sock->check_peer_secret_event ((struct sockaddr_in*) peer)) - { - debug_printf ("connect from unauthorized client"); - secret_check_failed = TRUE; - } - } - - if (secret_check_failed) - { - sock->close_secret_event (); - if ((SOCKET) res != (SOCKET) INVALID_SOCKET) - closesocket (res); - set_errno (ECONNABORTED); - res = -1; - goto done; - } - } + fhandler_socket *fh = get (fd); + if (fh) + res = fh->accept (peer, len); - cygheap_fdnew res_fd; - if (res_fd < 0) - /* FIXME: what is correct errno? */; - else if ((SOCKET) res == (SOCKET) INVALID_SOCKET) - set_winsock_errno (); - else - { - fhandler_socket* res_fh = fdsock (res_fd, sock->get_name (), res); - if (sock->get_addr_family () == AF_LOCAL) - res_fh->set_sun_path (sock->get_sun_path ()); - res_fh->set_addr_family (sock->get_addr_family ()); - res_fh->set_socket_type (sock->get_socket_type ()); - res = res_fd; - } - } - done: syscall_printf ("%d = accept (%d, %x, %x)", res, fd, peer, len); return res; } @@ -1272,83 +1015,10 @@ cygwin_bind (int fd, const struct sockaddr *my_addr, int addrlen) int res = -1; - fhandler_socket *sock = get (fd); - if (sock) - { - if (my_addr->sa_family == AF_LOCAL) - { -#define un_addr ((struct sockaddr_un *) my_addr) - struct sockaddr_in sin; - int len = sizeof sin; - int fd; - - if (strlen (un_addr->sun_path) >= UNIX_PATH_LEN) - { - set_errno (ENAMETOOLONG); - goto out; - } - sin.sin_family = AF_INET; - sin.sin_port = 0; - sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - if (bind (sock->get_socket (), (sockaddr *) &sin, len)) - { - syscall_printf ("AF_LOCAL: bind failed %d", get_errno ()); - set_winsock_errno (); - goto out; - } - if (getsockname (sock->get_socket (), (sockaddr *) &sin, &len)) - { - syscall_printf ("AF_LOCAL: getsockname failed %d", get_errno ()); - set_winsock_errno (); - goto out; - } - - sin.sin_port = ntohs (sin.sin_port); - debug_printf ("AF_LOCAL: socket bound to port %u", sin.sin_port); - - /* bind must fail if file system socket object already exists - so _open () is called with O_EXCL flag. */ - fd = _open (un_addr->sun_path, - O_WRONLY | O_CREAT | O_EXCL | O_BINARY, - 0); - if (fd < 0) - { - if (get_errno () == EEXIST) - set_errno (EADDRINUSE); - goto out; - } - - sock->set_connect_secret (); - - char buf[sizeof (SOCKET_COOKIE) + 80]; - __small_sprintf (buf, "%s%u ", SOCKET_COOKIE, sin.sin_port); - sock->get_connect_secret (strchr (buf, '\0')); - len = strlen (buf) + 1; - - /* Note that the terminating nul is written. */ - if (_write (fd, buf, len) != len) - { - save_errno here; - _close (fd); - _unlink (un_addr->sun_path); - } - else - { - _close (fd); - chmod (un_addr->sun_path, - (S_IFSOCK | S_IRWXU | S_IRWXG | S_IRWXO) & ~cygheap->umask); - sock->set_sun_path (un_addr->sun_path); - res = 0; - } -#undef un_addr - } - else if (bind (sock->get_socket (), my_addr, addrlen)) - set_winsock_errno (); - else - res = 0; - } + fhandler_socket *fh = get (fd); + if (fh) + res = fh->bind (my_addr, addrlen); -out: syscall_printf ("%d = bind (%d, %x, %d)", res, fd, my_addr, addrlen); return res; } @@ -1363,36 +1033,10 @@ cygwin_getsockname (int fd, struct sockaddr *addr, int *namelen) int res = -1; - fhandler_socket *sock = get (fd); - if (sock) - { - if (sock->get_addr_family () == AF_LOCAL) - { - struct sockaddr_un *sun = (struct sockaddr_un *) addr; - memset (sun, 0, *namelen); - sun->sun_family = AF_LOCAL; - - if (!sock->get_sun_path ()) - sun->sun_path[0] = '\0'; - else - /* According to SUSv2 "If the actual length of the address is - greater than the length of the supplied sockaddr structure, the - stored address will be truncated." We play it save here so - that the path always has a trailing 0 even if it's truncated. */ - strncpy (sun->sun_path, sock->get_sun_path (), - *namelen - sizeof *sun + sizeof sun->sun_path - 1); - - *namelen = sizeof *sun - sizeof sun->sun_path - + strlen (sun->sun_path) + 1; - res = 0; - } - else - { - res = getsockname (sock->get_socket (), addr, namelen); - if (res) - set_winsock_errno (); - } - } + fhandler_socket *fh = get (fd); + if (fh) + res = fh->getsockname (addr, namelen); + syscall_printf ("%d = getsockname (%d, %x, %d)", res, fd, addr, namelen); return res; } @@ -1403,14 +1047,10 @@ cygwin_listen (int fd, int backlog) { int res = -1; + fhandler_socket *fh = get (fd); + if (fh) + res = fh->listen (backlog); - fhandler_socket *sock = get (fd); - if (sock) - { - res = listen (sock->get_socket (), backlog); - if (res) - set_winsock_errno (); - } syscall_printf ("%d = listen (%d, %d)", res, fd, backlog); return res; } @@ -1422,27 +1062,10 @@ cygwin_shutdown (int fd, int how) int res = -1; sigframe thisframe (mainthread); - fhandler_socket *sock = get (fd); - if (sock) - { - res = shutdown (sock->get_socket (), how); - if (res) - set_winsock_errno (); - else - switch (how) - { - case SHUT_RD: - sock->set_shutdown_read (); - break; - case SHUT_WR: - sock->set_shutdown_write (); - break; - case SHUT_RDWR: - sock->set_shutdown_read (); - sock->set_shutdown_write (); - break; - } - } + fhandler_socket *fh = get (fd); + if (fh) + res = fh->shutdown (how); + syscall_printf ("%d = shutdown (%d, %d)", res, fd, how); return res; } @@ -1498,23 +1121,18 @@ cygwin_herror (const char *s) extern "C" int cygwin_getpeername (int fd, struct sockaddr *name, int *len) { - int res; + int res = -1; + if (check_null_invalid_struct_errno (len) || __check_null_invalid_struct_errno (name, (unsigned) *len)) return -1; - fhandler_socket *h = get (fd); + fhandler_socket *fh = get (fd); + if (fh) + res = fh->getpeername (name, len); - if (!h) - res = -1; - else - { - res = getpeername (h->get_socket (), name, len); - if (res) - set_winsock_errno (); - } + syscall_printf ("%d = getpeername %d", res, fh->get_socket ()); - debug_printf ("%d = getpeername %d", res, h->get_socket ()); return res; } @@ -2476,64 +2094,32 @@ endhostent (void) /* exported as recvmsg: standards? */ extern "C" int -cygwin_recvmsg(int s, struct msghdr *msg, int flags) -{ - int ret, nb; - size_t tot = 0; - int i; - char *buf, *p; - struct iovec *iov = msg->msg_iov; - - for(i = 0; i < msg->msg_iovlen; ++i) - tot += iov[i].iov_len; - buf = (char *) malloc(tot); - if (tot != 0 && buf == NULL) - { - errno = ENOMEM; - return -1; - } - nb = ret = cygwin_recvfrom (s, buf, tot, flags, - (struct sockaddr *) msg->msg_name, (int *) &msg->msg_namelen); - p = buf; - while (nb > 0) - { - ssize_t cnt = min(nb, iov->iov_len); +cygwin_recvmsg (int s, struct msghdr *msg, int flags) +{ + if (check_null_invalid_struct_errno (msg)) + return -1; - memcpy (iov->iov_base, p, cnt); - p += cnt; - nb -= cnt; - ++iov; - } - free(buf); - return ret; + fhandler_socket *fh = get (s); + if (!fh) + { + set_errno (EINVAL); + return -1; + } + return fh->recvmsg (msg, flags); } /* exported as sendmsg: standards? */ extern "C" int -cygwin_sendmsg(int s, const struct msghdr *msg, int flags) -{ - int ret; - size_t tot = 0; - int i; - char *buf, *p; - struct iovec *iov = msg->msg_iov; - - for(i = 0; i < msg->msg_iovlen; ++i) - tot += iov[i].iov_len; - buf = (char *) malloc(tot); - if (tot != 0 && buf == NULL) +cygwin_sendmsg (int s, const struct msghdr *msg, int flags) +{ + if (__check_invalid_read_ptr_errno (msg, sizeof msg)) + return -1; + + fhandler_socket *fh = get (s); + if (!fh) { - errno = ENOMEM; + set_errno (EINVAL); return -1; } - p = buf; - for (i = 0; i < msg->msg_iovlen; ++i) - { - memcpy (p, iov[i].iov_base, iov[i].iov_len); - p += iov[i].iov_len; - } - ret = cygwin_sendto (s, buf, tot, flags, - (struct sockaddr *) msg->msg_name, msg->msg_namelen); - free (buf); - return ret; + return fh->sendmsg (msg, flags); } diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index 50c5a743c41..3d9b86c150f 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -147,6 +147,7 @@ class path_conv operator const char *() {return path;} operator DWORD &() {return fileattr;} operator int &() {return (int) fileattr; } + char operator [](int i) const {return path[i];} BOOL is_device () {return devn != FH_BAD && devn != FH_DISK;} DWORD get_devn () {return devn == FH_BAD ? (DWORD) FH_DISK : devn;} short get_unitn () {return devn == FH_BAD ? 0 : unit;} diff --git a/winsup/cygwin/pwdgrp.h b/winsup/cygwin/pwdgrp.h index d2dcfcd1a54..bab2da86377 100644 --- a/winsup/cygwin/pwdgrp.h +++ b/winsup/cygwin/pwdgrp.h @@ -63,7 +63,8 @@ public: : fh (INVALID_HANDLE_VALUE), buf (NULL), lptr (NULL), eptr (NULL) {} virtual ~pwdgrp_read () { - close (); + if (fh != INVALID_HANDLE_VALUE) + CloseHandle (fh); if (buf) free (buf); } diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 54c238e48ad..65f06d90dd8 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -615,14 +615,15 @@ _link (const char *a, const char *b) { int res = -1; sigframe thisframe (mainthread); - path_conv real_a (a, PC_SYM_NOFOLLOW | PC_FULL); path_conv real_b (b, PC_SYM_NOFOLLOW | PC_FULL); - + path_conv real_a (a, PC_SYM_NOFOLLOW | PC_FULL); + if (real_a.error) { set_errno (real_a.error); goto done; } + if (real_b.error) { set_errno (real_b.case_clash ? ECASECLASH : real_b.error); @@ -631,11 +632,12 @@ _link (const char *a, const char *b) if (real_b.exists ()) { - syscall_printf ("file '%s' exists?", (char *)real_b); + syscall_printf ("file '%s' exists?", (char *) real_b); set_errno (EEXIST); goto done; } - if (real_b.get_win32 ()[strlen (real_b.get_win32 ()) - 1] == '.') + + if (real_b[strlen (real_b) - 1] == '.') { syscall_printf ("trailing dot, bailing out"); set_errno (EINVAL); @@ -645,7 +647,7 @@ _link (const char *a, const char *b) /* Try to make hard link first on Windows NT */ if (wincap.has_hard_links ()) { - if (CreateHardLinkA (real_b.get_win32 (), real_a.get_win32 (), NULL)) + if (CreateHardLinkA (real_b, real_a, NULL)) { res = 0; goto done; @@ -663,7 +665,7 @@ _link (const char *a, const char *b) BOOL bSuccess; hFileSource = CreateFile ( - real_a.get_win32 (), + real_a, FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE /*| FILE_SHARE_DELETE*/, &sec_none_nih, // sa @@ -678,8 +680,7 @@ _link (const char *a, const char *b) goto docopy; } - lpContext = NULL; - cbPathLen = sys_mbstowcs (wbuf, real_b.get_win32 (), MAX_PATH) * sizeof (WCHAR); + cbPathLen = sys_mbstowcs (wbuf, real_b, MAX_PATH) * sizeof (WCHAR); StreamId.dwStreamId = BACKUP_LINK; StreamId.dwStreamAttributes = 0; @@ -688,8 +689,9 @@ _link (const char *a, const char *b) StreamId.Size.LowPart = cbPathLen; StreamSize = sizeof (WIN32_STREAM_ID) - sizeof (WCHAR**) + - StreamId.dwStreamNameSize; + StreamId.dwStreamNameSize; + lpContext = NULL; /* Write the WIN32_STREAM_ID */ bSuccess = BackupWrite ( hFileSource, @@ -741,7 +743,7 @@ _link (const char *a, const char *b) } docopy: /* do this with a copy */ - if (CopyFileA (real_a.get_win32 (), real_b.get_win32 (), 1)) + if (CopyFileA (real_a, real_b, 1)) res = 0; else __seterrno (); diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 5735985c71d..4cfce5d4cda 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -68,15 +68,18 @@ extern "C" DWORD WINAPI GetLastError (void); enum codepage_type {ansi_cp, oem_cp}; extern codepage_type current_codepage; -extern int cygserver_running; +UINT get_cp (); + +int __stdcall sys_wcstombs(char *, const WCHAR *, int) + __attribute__ ((regparm(3))); + +int __stdcall sys_mbstowcs(WCHAR *, const char *, int) + __attribute__ ((regparm(3))); /* Used to check if Cygwin DLL is dynamically loaded. */ extern int dynamically_loaded; -#define sys_wcstombs(tgt,src,len) \ - WideCharToMultiByte((current_codepage==ansi_cp?CP_ACP:CP_OEMCP),0,(src),-1,(tgt),(len),NULL,NULL) -#define sys_mbstowcs(tgt,src,len) \ - MultiByteToWideChar((current_codepage==ansi_cp?CP_ACP:CP_OEMCP),0,(src),-1,(tgt),(len)) +extern int cygserver_running; #define TITLESIZE 1024 |