Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorConrad Scott <conrad.scott@dsl.pipex.com>2002-06-27 15:30:19 +0400
committerConrad Scott <conrad.scott@dsl.pipex.com>2002-06-27 15:30:19 +0400
commita3559f55c005f161053700c1766b378df8b5d884 (patch)
tree007650fa6baf7c178a4dfdb78ec7fcf0e1797257 /winsup/cygwin
parent9a2d6fcbe28b2f793f64e25c1fa68c493baaca12 (diff)
Merged changes from HEAD
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/ChangeLog94
-rw-r--r--winsup/cygwin/autoload.cc6
-rw-r--r--winsup/cygwin/cygheap.cc14
-rw-r--r--winsup/cygwin/dcrt0.cc8
-rw-r--r--winsup/cygwin/environ.cc12
-rw-r--r--winsup/cygwin/fhandler.h15
-rw-r--r--winsup/cygwin/fhandler_console.cc16
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc45
-rw-r--r--winsup/cygwin/fhandler_socket.cc530
-rw-r--r--winsup/cygwin/include/cygwin/version.h2
-rw-r--r--winsup/cygwin/miscfuncs.cc20
-rw-r--r--winsup/cygwin/net.cc556
-rw-r--r--winsup/cygwin/path.h1
-rw-r--r--winsup/cygwin/pwdgrp.h3
-rw-r--r--winsup/cygwin/syscalls.cc22
-rw-r--r--winsup/cygwin/winsup.h13
16 files changed, 813 insertions, 544 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index eac8abe48..1e1958f20 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 9bae17deb..d910b43ed 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 0522255f6..561e9330f 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 afec2173e..854e52585 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 9fc4d0ab8..114fce7f0 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 08bb273a4..e0521d4ef 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 cc948d3d0..458c5a337 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 443612ff4..db843a41c 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 6a6e0eeba..24e68566e 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 6ab596e09..4c1437bc2 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 5d3010470..6fd9ffc91 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 32e930392..d3eba725c 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 50c5a743c..3d9b86c15 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 d2dcfcd1a..bab2da863 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 54c238e48..65f06d90d 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 5735985c7..4cfce5d4c 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