This is the mail archive of the cygwin-cvs@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[newlib-cygwin] Cygwin: Create empty fhandler_socket_unix


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=7f7532fafb0e9787bc9c789f14e9344b8da16244

commit 7f7532fafb0e9787bc9c789f14e9344b8da16244
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Fri Feb 23 20:59:21 2018 +0100

    Cygwin: Create empty fhandler_socket_unix
    
    * Make distinct from AF_LOCAL for testing purposes.  This will have
      to be reverted as soon as fhandler_socket_unix goes life.
    
    * Move saw_reuseaddr flag back to fhandler_socket status
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 winsup/cygwin/Makefile.in             |   1 +
 winsup/cygwin/devices.cc              |   3 +
 winsup/cygwin/devices.h               |   3 +
 winsup/cygwin/devices.in              |   3 +
 winsup/cygwin/dtable.cc               |   3 +
 winsup/cygwin/fhandler.h              | 102 +++++-
 winsup/cygwin/fhandler_socket_inet.cc |   8 +-
 winsup/cygwin/fhandler_socket_unix.cc | 671 ++++++++++++++++++++++++++++++++++
 winsup/cygwin/include/cygwin/socket.h |   6 +
 winsup/cygwin/net.cc                  |   6 +-
 winsup/cygwin/select.cc               |  45 +++
 11 files changed, 832 insertions(+), 19 deletions(-)

diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in
index 75ec297..ac22cfb 100644
--- a/winsup/cygwin/Makefile.in
+++ b/winsup/cygwin/Makefile.in
@@ -298,6 +298,7 @@ DLL_OFILES:= \
 	fhandler_socket.o \
 	fhandler_socket_inet.o \
 	fhandler_socket_local.o \
+	fhandler_socket_unix.o \
 	fhandler_tape.o \
 	fhandler_termios.o \
 	fhandler_tty.o \
diff --git a/winsup/cygwin/devices.cc b/winsup/cygwin/devices.cc
index 8ba199d..963069b 100644
--- a/winsup/cygwin/devices.cc
+++ b/winsup/cygwin/devices.cc
@@ -126,6 +126,9 @@ const _device dev_socket_storage =
 const _device dev_af_inet_storage =
   {"", {FH_INET}, "", exists_internal};
 
+const _device dev_af_unix_storage =
+  {"", {FH_UNIX}, "", exists_internal};
+
 const _device dev_af_local_storage =
   {"", {FH_LOCAL}, "", exists_internal};
 
diff --git a/winsup/cygwin/devices.h b/winsup/cygwin/devices.h
index 87e0330..3b67300 100644
--- a/winsup/cygwin/devices.h
+++ b/winsup/cygwin/devices.h
@@ -244,6 +244,7 @@ enum fh_devices
   DEV_SOCK_MAJOR = 30,
   FH_SOCKET = FHDEV (DEV_SOCK_MAJOR, 0),
   FH_INET = FHDEV (DEV_SOCK_MAJOR, 36),
+  FH_UNIX = FHDEV (DEV_SOCK_MAJOR, 42),
   FH_LOCAL = FHDEV (DEV_SOCK_MAJOR, 120),
 
   FH_NADA     = FHDEV (0, 0),
@@ -397,6 +398,8 @@ extern const _device dev_af_inet_storage;
 #define af_inet_dev ((device *) &dev_af_inet_storage)
 extern const _device dev_af_local_storage;
 #define af_local_dev ((device *) &dev_af_local_storage)
+extern const _device dev_af_unix_storage;
+#define af_unix_dev ((device *) &dev_af_unix_storage)
 
 extern const _device dev_piper_storage;
 #define piper_dev ((device *) &dev_piper_storage)
diff --git a/winsup/cygwin/devices.in b/winsup/cygwin/devices.in
index c0108b8..ed99b44 100644
--- a/winsup/cygwin/devices.in
+++ b/winsup/cygwin/devices.in
@@ -122,6 +122,9 @@ const _device dev_socket_storage =
 const _device dev_af_inet_storage =
   {"", {FH_INET}, "", exists_internal};
 
+const _device dev_af_unix_storage =
+  {"", {FH_UNIX}, "", exists_internal};
+
 const _device dev_af_local_storage =
   {"", {FH_LOCAL}, "", exists_internal};
 
diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc
index ae0315c..5a263f5 100644
--- a/winsup/cygwin/dtable.cc
+++ b/winsup/cygwin/dtable.cc
@@ -520,6 +520,9 @@ fh_alloc (path_conv& pc)
 	case FH_LOCAL:
 	  fh = cnew (fhandler_socket_local);
 	  break;
+	case FH_UNIX:
+	  fh = cnew (fhandler_socket_unix);
+	  break;
 	case FH_FS:
 	  fh = cnew (fhandler_disk_file);
 	  break;
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 3816110..863cd31 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -521,17 +521,19 @@ class fhandler_socket: public fhandler_base
     unsigned async_io		   : 1; /* async I/O */
     unsigned saw_shutdown_read     : 1; /* Socket saw a SHUT_RD */
     unsigned saw_shutdown_write    : 1; /* Socket saw a SHUT_WR */
+    unsigned saw_reuseaddr	   : 1; /* Socket saw SO_REUSEADDR call */
     unsigned connect_state	   : 3;
    public:
     status_flags () :
       async_io (0), saw_shutdown_read (0), saw_shutdown_write (0),
-      connect_state (unconnected)
+      saw_reuseaddr (0), connect_state (unconnected)
       {}
   } status;
  public:
   IMPLEMENT_STATUS_FLAG (bool, async_io)
   IMPLEMENT_STATUS_FLAG (bool, saw_shutdown_read)
   IMPLEMENT_STATUS_FLAG (bool, saw_shutdown_write)
+  IMPLEMENT_STATUS_FLAG (bool, saw_reuseaddr)
   IMPLEMENT_STATUS_FLAG (conn_state, connect_state)
 
  public:
@@ -640,16 +642,6 @@ class fhandler_socket_wsock: public fhandler_socket
 #endif
 
  protected:
-  struct status_flags
-  {
-    unsigned saw_reuseaddr	   : 1; /* Socket saw SO_REUSEADDR call */
-   public:
-    status_flags () : saw_reuseaddr (0) {}
-  } status;
- public:
-  IMPLEMENT_STATUS_FLAG (bool, saw_reuseaddr)
-
- protected:
   virtual ssize_t recv_internal (struct _WSAMSG *wsamsg, bool use_recvmsg) = 0;
   ssize_t send_internal (struct _WSAMSG *wsamsg, int flags);
 
@@ -819,6 +811,94 @@ class fhandler_socket_local: public fhandler_socket_wsock
   }
 };
 
+class fhandler_socket_unix : public fhandler_socket
+{
+ protected:
+  char *sun_path;
+  char *peer_sun_path;
+  void set_sun_path (const char *path);
+  char *get_sun_path () {return sun_path;}
+  void set_peer_sun_path (const char *path);
+  char *get_peer_sun_path () {return peer_sun_path;}
+  void set_cred ();
+
+ protected:
+  pid_t sec_pid;
+  uid_t sec_uid;
+  gid_t sec_gid;
+  pid_t sec_peer_pid;
+  uid_t sec_peer_uid;
+  gid_t sec_peer_gid;
+
+ public:
+  fhandler_socket_unix ();
+  ~fhandler_socket_unix ();
+
+  int dup (fhandler_base *child, int);
+
+  int socket (int af, int type, int protocol, int flags);
+  int socketpair (int af, int type, int protocol, int flags,
+		  fhandler_socket_unix *fh_out);
+  int bind (const struct sockaddr *name, int namelen);
+  int listen (int backlog);
+  int accept4 (struct sockaddr *peer, int *len, int flags);
+  int connect (const struct sockaddr *name, int namelen);
+  int getsockname (struct sockaddr *name, int *namelen);
+  int getpeername (struct sockaddr *name, int *namelen);
+  int shutdown (int how);
+  int close ();
+  int getpeereid (pid_t *pid, uid_t *euid, gid_t *egid);
+  ssize_t recvfrom (void *ptr, size_t len, int flags,
+		    struct sockaddr *from, int *fromlen);
+  ssize_t recvmsg (struct msghdr *msg, int flags);
+  void __reg3 read (void *ptr, size_t& len);
+  ssize_t __stdcall readv (const struct iovec *, int iovcnt,
+			   ssize_t tot = -1);
+
+  ssize_t sendto (const void *ptr, size_t len, int flags,
+		  const struct sockaddr *to, int tolen);
+  ssize_t sendmsg (const struct msghdr *msg, int flags);
+  ssize_t __stdcall write (const void *ptr, size_t len);
+  ssize_t __stdcall writev (const struct iovec *, int iovcnt, ssize_t tot = -1);
+  int setsockopt (int level, int optname, const void *optval,
+		  __socklen_t optlen);
+  int getsockopt (int level, int optname, const void *optval,
+		  __socklen_t *optlen);
+
+  virtual int ioctl (unsigned int cmd, void *);
+  virtual int fcntl (int cmd, intptr_t);
+
+  int __reg2 fstat (struct stat *buf);
+  int __reg2 fstatvfs (struct statvfs *buf);
+  int __reg1 fchmod (mode_t newmode);
+  int __reg2 fchown (uid_t newuid, gid_t newgid);
+  int __reg3 facl (int, int, struct acl *);
+  int __reg2 link (const char *);
+
+  /* select.cc */
+  select_record *select_read (select_stuff *);
+  select_record *select_write (select_stuff *);
+  select_record *select_except (select_stuff *);
+
+  /* from here on: CLONING */
+  fhandler_socket_unix (void *) {}
+
+  void copyto (fhandler_base *x)
+  {
+    x->pc.free_strings ();
+    *reinterpret_cast<fhandler_socket_unix *> (x) = *this;
+    x->reset (this);
+  }
+
+  fhandler_socket_unix *clone (cygheap_types malloc_type = HEAP_FHANDLER)
+  {
+    void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_socket_unix));
+    fhandler_socket_unix *fh = new (ptr) fhandler_socket_unix (ptr);
+    copyto (fh);
+    return fh;
+  }
+};
+
 class fhandler_base_overlapped: public fhandler_base
 {
   static HANDLE asio_done;
diff --git a/winsup/cygwin/fhandler_socket_inet.cc b/winsup/cygwin/fhandler_socket_inet.cc
index 0668c10..aa3ead7 100644
--- a/winsup/cygwin/fhandler_socket_inet.cc
+++ b/winsup/cygwin/fhandler_socket_inet.cc
@@ -211,8 +211,7 @@ fhandler_socket_wsock::fhandler_socket_wsock () :
   wsock_events (NULL),
   wsock_mtx (NULL),
   wsock_evt (NULL),
-  prot_info_ptr (NULL),
-  status ()
+  prot_info_ptr (NULL)
 {
   need_fork_fixup (true);
 }
@@ -1429,8 +1428,6 @@ fhandler_socket_inet::sendto (const void *in_ptr, size_t len, int flags,
 ssize_t
 fhandler_socket_inet::sendmsg (const struct msghdr *msg, int flags)
 {
-  /* TODO: Descriptor passing on AF_LOCAL sockets. */
-
   struct sockaddr_storage sst;
   int len = 0;
 
@@ -1449,8 +1446,7 @@ fhandler_socket_inet::sendmsg (const struct msghdr *msg, int flags)
     }
   /* Disappointing but true:  Even if WSASendMsg is supported, it's only
      supported for datagram and raw sockets. */
-  DWORD controllen = (DWORD) (get_socket_type () == SOCK_STREAM
-			      || get_addr_family () == AF_LOCAL
+  DWORD controllen = (DWORD) ((get_socket_type () == SOCK_STREAM)
 			      ? 0 : msg->msg_controllen);
   WSAMSG wsamsg = { msg->msg_name ? (struct sockaddr *) &sst : NULL, len,
 		    wsabuf, (DWORD) msg->msg_iovlen,
diff --git a/winsup/cygwin/fhandler_socket_unix.cc b/winsup/cygwin/fhandler_socket_unix.cc
new file mode 100644
index 0000000..21d2ad6
--- /dev/null
+++ b/winsup/cygwin/fhandler_socket_unix.cc
@@ -0,0 +1,671 @@
+/* fhandler_socket_unix.cc.
+
+   See fhandler.h for a description of the fhandler classes.
+
+   This file is part of Cygwin.
+
+   This software is a copyrighted work licensed under the terms of the
+   Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
+   details. */
+
+#include "winsup.h"
+#include <ntsecapi.h>
+#include "cygerrno.h"
+#include "security.h"
+#include "path.h"
+#include "fhandler.h"
+#include "dtable.h"
+#include "cygheap.h"
+#include <asm/byteorder.h>
+#include "cygwin/version.h"
+#include "perprocess.h"
+#include "shared_info.h"
+#include "sigproc.h"
+#include "wininfo.h"
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/statvfs.h>
+#include <cygwin/acl.h>
+#include "cygtls.h"
+#include <sys/un.h>
+#include "ntdll.h"
+#include "miscfuncs.h"
+#include "tls_pbuf.h"
+
+extern "C" {
+  int sscanf (const char *, const char *, ...);
+} /* End of "C" section */
+
+#define ASYNC_MASK (FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT)
+#define EVENT_MASK (FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT|FD_CLOSE)
+
+#define LOCK_EVENTS	\
+  if (wsock_mtx && \
+      WaitForSingleObject (wsock_mtx, INFINITE) != WAIT_FAILED) \
+    {
+
+#define UNLOCK_EVENTS \
+      ReleaseMutex (wsock_mtx); \
+    }
+
+static inline mode_t
+adjust_socket_file_mode (mode_t mode)
+{
+  /* Kludge: Don't allow to remove read bit on socket files for
+     user/group/other, if the accompanying write bit is set.  It would
+     be nice to have exact permissions on a socket file, but it's
+     necessary that somebody able to access the socket can always read
+     the contents of the socket file to avoid spurious "permission
+     denied" messages. */
+  return mode | ((mode & (S_IWUSR | S_IWGRP | S_IWOTH)) << 1);
+}
+
+/* cygwin internal: map sockaddr into internet domain address */
+static int __unused
+get_inet_addr_unix (const struct sockaddr *in, int inlen,
+		    struct sockaddr_storage *out, int *outlen,
+		    int *type = NULL)
+{
+  /* Check for abstract socket. */
+  if (inlen >= (int) sizeof (in->sa_family) + 7
+      && in->sa_data[0] == '\0' && in->sa_data[1] == 'd'
+      && in->sa_data[6] == '\0')
+    {
+      /* TODO */
+      return 0;
+    }
+
+  path_conv pc (in->sa_data, PC_SYM_FOLLOW);
+  if (pc.error)
+    {
+      set_errno (pc.error);
+      return -1;
+    }
+  if (!pc.exists ())
+    {
+      set_errno (ENOENT);
+      return -1;
+    }
+  /* Do NOT test for the file being a socket file here.  The socket file
+     creation is not an atomic operation, so there is a chance that socket
+     files which are just in the process of being created are recognized
+     as non-socket files.  To work around this problem we now create the
+     file with all sharing disabled.  If the below NtOpenFile fails
+     with STATUS_SHARING_VIOLATION we know that the file already exists,
+     but the creating process isn't finished yet.  So we yield and try
+     again, until we can either open the file successfully, or some error
+     other than STATUS_SHARING_VIOLATION occurs.
+     Since we now don't know if the file is actually a socket file, we
+     perform this check here explicitely. */
+  NTSTATUS status;
+  HANDLE fh;
+  OBJECT_ATTRIBUTES attr;
+  IO_STATUS_BLOCK io;
+
+  pc.get_object_attr (attr, sec_none_nih);
+  do
+    {
+      status = NtOpenFile (&fh, GENERIC_READ | SYNCHRONIZE, &attr, &io,
+			   FILE_SHARE_VALID_FLAGS,
+			   FILE_SYNCHRONOUS_IO_NONALERT
+			   | FILE_OPEN_FOR_BACKUP_INTENT
+			   | FILE_NON_DIRECTORY_FILE);
+      if (status == STATUS_SHARING_VIOLATION)
+	{
+	  /* While we hope that the sharing violation is only temporary, we
+	     also could easily get stuck here, waiting for a file in use by
+	     some greedy Win32 application.  Therefore we should never wait
+	     endlessly without checking for signals and thread cancel event. */
+	  pthread_testcancel ();
+	  if (cygwait (NULL, cw_nowait, cw_sig_eintr) == WAIT_SIGNALED
+	      && !_my_tls.call_signal_handler ())
+	    {
+	      set_errno (EINTR);
+	      return -1;
+	    }
+	  yield ();
+	}
+      else if (!NT_SUCCESS (status))
+	{
+	  __seterrno_from_nt_status (status);
+	  return -1;
+	}
+    }
+  while (status == STATUS_SHARING_VIOLATION);
+  /* Now test for the SYSTEM bit. */
+  FILE_BASIC_INFORMATION fbi;
+  status = NtQueryInformationFile (fh, &io, &fbi, sizeof fbi,
+				   FileBasicInformation);
+  if (!NT_SUCCESS (status))
+    {
+      __seterrno_from_nt_status (status);
+      return -1;
+    }
+  if (!(fbi.FileAttributes & FILE_ATTRIBUTE_SYSTEM))
+    {
+      NtClose (fh);
+      set_errno (EBADF);
+      return -1;
+    }
+  /* Eventually check the content and fetch the required information. */
+  char buf[128];
+  memset (buf, 0, sizeof buf);
+  status = NtReadFile (fh, NULL, NULL, NULL, &io, buf, 128, NULL, NULL);
+  NtClose (fh);
+  if (NT_SUCCESS (status))
+    {
+#if 0 /* TODO */
+      struct sockaddr_in sin;
+      char ctype;
+      sin.sin_family = AF_INET;
+      if (strncmp (buf, SOCKET_COOKIE, strlen (SOCKET_COOKIE)))
+	{
+	  set_errno (EBADF);
+	  return -1;
+	}
+      sscanf (buf + strlen (SOCKET_COOKIE), "%hu %c", &sin.sin_port, &ctype);
+      sin.sin_port = htons (sin.sin_port);
+      sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+      memcpy (out, &sin, sizeof sin);
+      *outlen = sizeof sin;
+      if (type)
+	*type = (ctype == 's' ? SOCK_STREAM :
+		 ctype == 'd' ? SOCK_DGRAM
+			      : 0);
+#endif
+      return 0;
+    }
+  __seterrno_from_nt_status (status);
+  return -1;
+}
+
+fhandler_socket_unix::fhandler_socket_unix () :
+  sun_path (NULL),
+  peer_sun_path (NULL)
+{
+  set_cred ();
+}
+
+fhandler_socket_unix::~fhandler_socket_unix ()
+{
+  if (sun_path)
+    cfree (sun_path);
+  if (peer_sun_path)
+    cfree (peer_sun_path);
+}
+
+void
+fhandler_socket_unix::set_sun_path (const char *path)
+{
+  sun_path = path ? cstrdup (path) : NULL;
+}
+
+void
+fhandler_socket_unix::set_peer_sun_path (const char *path)
+{
+  peer_sun_path = path ? cstrdup (path) : NULL;
+}
+
+void
+fhandler_socket_unix::set_cred ()
+{
+  sec_pid = getpid ();
+  sec_uid = geteuid32 ();
+  sec_gid = getegid32 ();
+  sec_peer_pid = (pid_t) 0;
+  sec_peer_uid = (uid_t) -1;
+  sec_peer_gid = (gid_t) -1;
+}
+
+int
+fhandler_socket_unix::dup (fhandler_base *child, int flags)
+{
+  fhandler_socket_unix *fhs = (fhandler_socket_unix *) child;
+  fhs->set_sun_path (get_sun_path ());
+  fhs->set_peer_sun_path (get_peer_sun_path ());
+  return fhandler_socket::dup (child, flags);
+}
+
+int
+fhandler_socket_unix::socket (int af, int type, int protocol, int flags)
+{
+  set_errno (EAFNOSUPPORT);
+  return -1;
+}
+
+int
+fhandler_socket_unix::socketpair (int af, int type, int protocol, int flags,
+				  fhandler_socket_unix *fh_out)
+{
+  set_errno (EAFNOSUPPORT);
+  return -1;
+}
+
+int
+fhandler_socket_unix::bind (const struct sockaddr *name, int namelen)
+{
+  set_errno (EAFNOSUPPORT);
+  return -1;
+}
+
+int
+fhandler_socket_unix::listen (int backlog)
+{
+  set_errno (EAFNOSUPPORT);
+  return -1;
+}
+
+int
+fhandler_socket_unix::accept4 (struct sockaddr *peer, int *len, int flags)
+{
+  set_errno (EAFNOSUPPORT);
+  return -1;
+}
+
+int
+fhandler_socket_unix::connect (const struct sockaddr *name, int namelen)
+{
+  set_errno (EAFNOSUPPORT);
+  return -1;
+}
+
+int
+fhandler_socket_unix::getsockname (struct sockaddr *name, int *namelen)
+{
+  struct sockaddr_un sun;
+
+  sun.sun_family = AF_UNIX;
+  sun.sun_path[0] = '\0';
+  if (get_sun_path ())
+    strncat (sun.sun_path, get_sun_path (), UNIX_PATH_MAX - 1);
+  memcpy (name, &sun, MIN (*namelen, (int) SUN_LEN (&sun) + 1));
+  *namelen = (int) SUN_LEN (&sun) + (get_sun_path () ? 1 : 0);
+  return 0;
+}
+
+int
+fhandler_socket_unix::getpeername (struct sockaddr *name, int *namelen)
+{
+  struct sockaddr_un sun;
+  memset (&sun, 0, sizeof sun);
+  sun.sun_family = AF_UNIX;
+  sun.sun_path[0] = '\0';
+  if (get_peer_sun_path ())
+    strncat (sun.sun_path, get_peer_sun_path (), UNIX_PATH_MAX - 1);
+  memcpy (name, &sun, MIN (*namelen, (int) SUN_LEN (&sun) + 1));
+  *namelen = (int) SUN_LEN (&sun) + (get_peer_sun_path () ? 1 : 0);
+  return 0;
+}
+
+int
+fhandler_socket_unix::shutdown (int how)
+{
+  set_errno (EAFNOSUPPORT);
+  return -1;
+}
+
+int
+fhandler_socket_unix::close ()
+{
+  set_errno (EAFNOSUPPORT);
+  return -1;
+}
+
+int
+fhandler_socket_unix::getpeereid (pid_t *pid, uid_t *euid, gid_t *egid)
+{
+  if (get_socket_type () != SOCK_STREAM)
+    {
+      set_errno (EINVAL);
+      return -1;
+    }
+  if (connect_state () != connected)
+    {
+      set_errno (ENOTCONN);
+      return -1;
+    }
+
+  __try
+    {
+      if (pid)
+	*pid = sec_peer_pid;
+      if (euid)
+	*euid = sec_peer_uid;
+      if (egid)
+	*egid = sec_peer_gid;
+      return 0;
+    }
+  __except (EFAULT) {}
+  __endtry
+  return -1;
+}
+
+ssize_t
+fhandler_socket_unix::recvfrom (void *ptr, size_t len, int flags,
+				struct sockaddr *from, int *fromlen)
+{
+  set_errno (EAFNOSUPPORT);
+  return -1;
+}
+
+ssize_t
+fhandler_socket_unix::recvmsg (struct msghdr *msg, int flags)
+{
+  set_errno (EAFNOSUPPORT);
+  return -1;
+}
+
+void __reg3
+fhandler_socket_unix::read (void *ptr, size_t& len)
+{
+  set_errno (EAFNOSUPPORT);
+  len = 0;
+}
+
+ssize_t __stdcall
+fhandler_socket_unix::readv (const struct iovec *, int iovcnt, ssize_t tot)
+{
+  set_errno (EAFNOSUPPORT);
+  return -1;
+}
+
+ssize_t
+fhandler_socket_unix::sendto (const void *in_ptr, size_t len, int flags,
+			       const struct sockaddr *to, int tolen)
+{
+  set_errno (EAFNOSUPPORT);
+  return -1;
+}
+
+ssize_t
+fhandler_socket_unix::sendmsg (const struct msghdr *msg, int flags)
+{
+  set_errno (EAFNOSUPPORT);
+  return -1;
+}
+
+ssize_t __stdcall
+fhandler_socket_unix::write (const void *ptr, size_t len)
+{
+  set_errno (EAFNOSUPPORT);
+  return -1;
+}
+
+ssize_t __stdcall
+fhandler_socket_unix::writev (const struct iovec *, int iovcnt, ssize_t tot)
+{
+  set_errno (EAFNOSUPPORT);
+  return -1;
+}
+
+int
+fhandler_socket_unix::setsockopt (int level, int optname, const void *optval,
+				   socklen_t optlen)
+{
+  /* Preprocessing setsockopt. */
+  switch (level)
+    {
+    case SOL_SOCKET:
+      switch (optname)
+	{
+	case SO_PASSCRED:
+	  break;
+
+	case SO_REUSEADDR:
+	  saw_reuseaddr (*(int *) optval);
+	  break;
+
+	case SO_RCVBUF:
+	  rmem (*(int *) optval);
+	  break;
+
+	case SO_SNDBUF:
+	  wmem (*(int *) optval);
+	  break;
+
+	case SO_RCVTIMEO:
+	case SO_SNDTIMEO:
+	  if (optlen < (socklen_t) sizeof (struct timeval))
+	    {
+	      set_errno (EINVAL);
+	      return -1;
+	    }
+	  if (!timeval_to_ms ((struct timeval *) optval,
+			      (optname == SO_RCVTIMEO) ? rcvtimeo ()
+						       : sndtimeo ()))
+	  {
+	    set_errno (EDOM);
+	    return -1;
+	  }
+	  break;
+
+	default:
+	  /* AF_UNIX sockets simply ignore all other SOL_SOCKET options. */
+	  break;
+	}
+      break;
+
+    default:
+      set_errno (ENOPROTOOPT);
+      return -1;
+    }
+
+  return 0;
+}
+
+int
+fhandler_socket_unix::getsockopt (int level, int optname, const void *optval,
+				   socklen_t *optlen)
+{
+  /* Preprocessing getsockopt.*/
+  switch (level)
+    {
+    case SOL_SOCKET:
+      switch (optname)
+	{
+	case SO_ERROR:
+	  {
+	    int *e = (int *) optval;
+	    *e = 0;
+	    break;
+	  }
+
+	case SO_PASSCRED:
+	  break;
+
+	case SO_PEERCRED:
+	  {
+	    struct ucred *cred = (struct ucred *) optval;
+
+	    if (*optlen < (socklen_t) sizeof *cred)
+	      {
+		set_errno (EINVAL);
+		return -1;
+	      }
+	    int ret = getpeereid (&cred->pid, &cred->uid, &cred->gid);
+	    if (!ret)
+	      *optlen = (socklen_t) sizeof *cred;
+	    return ret;
+	  }
+
+	case SO_REUSEADDR:
+	  {
+	    unsigned int *reuseaddr = (unsigned int *) optval;
+
+	    if (*optlen < (socklen_t) sizeof *reuseaddr)
+	      {
+		set_errno (EINVAL);
+		return -1;
+	      }
+	    *reuseaddr = saw_reuseaddr();
+	    *optlen = (socklen_t) sizeof *reuseaddr;
+	    break;
+	  }
+
+	case SO_RCVTIMEO:
+	case SO_SNDTIMEO:
+	  {
+	    struct timeval *time_out = (struct timeval *) optval;
+
+	    if (*optlen < (socklen_t) sizeof *time_out)
+	      {
+		set_errno (EINVAL);
+		return -1;
+	      }
+	    DWORD ms = (optname == SO_RCVTIMEO) ? rcvtimeo () : sndtimeo ();
+	    if (ms == 0 || ms == INFINITE)
+	      {
+		time_out->tv_sec = 0;
+		time_out->tv_usec = 0;
+	      }
+	    else
+	      {
+		time_out->tv_sec = ms / MSPERSEC;
+		time_out->tv_usec = ((ms % MSPERSEC) * USPERSEC) / MSPERSEC;
+	      }
+	    *optlen = (socklen_t) sizeof *time_out;
+	    break;
+	  }
+
+	case SO_TYPE:
+	  {
+	    unsigned int *type = (unsigned int *) optval;
+	    *type = get_socket_type ();
+	    *optlen = (socklen_t) sizeof *type;
+	    break;
+	  }
+
+	/* AF_UNIX sockets simply ignore all other SOL_SOCKET options. */
+
+	case SO_LINGER:
+	  {
+	    struct linger *linger = (struct linger *) optval;
+	    memset (linger, 0, sizeof *linger);
+	    *optlen = (socklen_t) sizeof *linger;
+	    break;
+	  }
+
+	default:
+	  {
+	    unsigned int *val = (unsigned int *) optval;
+	    *val = 0;
+	    *optlen = (socklen_t) sizeof *val;
+	    break;
+	  }
+	}
+      break;
+
+    default:
+      set_errno (ENOPROTOOPT);
+      return -1;
+    }
+
+  return 0;
+}
+
+int
+fhandler_socket_unix::ioctl (unsigned int cmd, void *p)
+{
+  int ret;
+
+  switch (cmd)
+    {
+    case FIOASYNC:
+#ifdef __x86_64__
+    case _IOW('f', 125, int):
+#endif
+      break;
+    case FIONREAD:
+#ifdef __x86_64__
+    case _IOR('f', 127, int):
+#endif
+    case FIONBIO:
+    case SIOCATMARK:
+      break;
+    default:
+      ret = fhandler_socket::ioctl (cmd, p);
+      break;
+    }
+  return ret;
+}
+
+int
+fhandler_socket_unix::fcntl (int cmd, intptr_t arg)
+{
+  int ret;
+
+  switch (cmd)
+    {
+    case F_SETOWN:
+      break;
+    case F_GETOWN:
+      break;
+    default:
+      ret = fhandler_socket::fcntl (cmd, arg);
+      break;
+    }
+  return ret;
+}
+
+int __reg2
+fhandler_socket_unix::fstat (struct stat *buf)
+{
+  int ret;
+
+  if (!get_sun_path () || get_sun_path ()[0] == '\0')
+    return fhandler_socket::fstat (buf);
+  ret = fhandler_base::fstat_fs (buf);
+  if (!ret)
+    {
+      buf->st_mode = (buf->st_mode & ~S_IFMT) | S_IFSOCK;
+      buf->st_size = 0;
+    }
+  return ret;
+}
+
+int __reg2
+fhandler_socket_unix::fstatvfs (struct statvfs *sfs)
+{
+  if (!get_sun_path () || get_sun_path ()[0] == '\0')
+    return fhandler_socket::fstatvfs (sfs);
+  fhandler_disk_file fh (pc);
+  fh.get_device () = FH_FS;
+  return fh.fstatvfs (sfs);
+}
+
+int
+fhandler_socket_unix::fchmod (mode_t newmode)
+{
+  if (!get_sun_path () || get_sun_path ()[0] == '\0')
+    return fhandler_socket::fchmod (newmode);
+  fhandler_disk_file fh (pc);
+  fh.get_device () = FH_FS;
+  return fh.fchmod (S_IFSOCK | adjust_socket_file_mode (newmode));
+}
+
+int
+fhandler_socket_unix::fchown (uid_t uid, gid_t gid)
+{
+  if (!get_sun_path () || get_sun_path ()[0] == '\0')
+    return fhandler_socket::fchown (uid, gid);
+  fhandler_disk_file fh (pc);
+  return fh.fchown (uid, gid);
+}
+
+int
+fhandler_socket_unix::facl (int cmd, int nentries, aclent_t *aclbufp)
+{
+  if (!get_sun_path () || get_sun_path ()[0] == '\0')
+    return fhandler_socket::facl (cmd, nentries, aclbufp);
+  fhandler_disk_file fh (pc);
+  return fh.facl (cmd, nentries, aclbufp);
+}
+
+int
+fhandler_socket_unix::link (const char *newpath)
+{
+  if (!get_sun_path () || get_sun_path ()[0] == '\0')
+    return fhandler_socket::link (newpath);
+  fhandler_disk_file fh (pc);
+  return fh.link (newpath);
+}
diff --git a/winsup/cygwin/include/cygwin/socket.h b/winsup/cygwin/include/cygwin/socket.h
index b1ab5c2..15e1327 100644
--- a/winsup/cygwin/include/cygwin/socket.h
+++ b/winsup/cygwin/include/cygwin/socket.h
@@ -138,7 +138,13 @@ struct OLD_msghdr
  * Address families.
  */
 #define AF_UNSPEC       0               /* unspecified */
+/* FIXME: This is for testing only, while developing the new
+          fhandler_socket_unix class. */
+#ifdef __INSIDE_CYGWIN__
+#define AF_UNIX         31
+#else
 #define AF_UNIX         1               /* local to host (pipes, portals) */
+#endif
 #define AF_LOCAL        1               /* POSIX name for AF_UNIX */
 #define AF_INET         2               /* internetwork: UDP, TCP, etc. */
 #define AF_IMPLINK      3               /* arpanet imp addresses */
diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc
index fe6576d..89945c5 100644
--- a/winsup/cygwin/net.cc
+++ b/winsup/cygwin/net.cc
@@ -516,6 +516,7 @@ cygwin_socket (int af, int type, int protocol)
   switch (af)
     {
     case AF_LOCAL:
+    case AF_UNIX:
       if (type != SOCK_STREAM && type != SOCK_DGRAM)
         {
           set_errno (EINVAL);
@@ -526,7 +527,7 @@ cygwin_socket (int af, int type, int protocol)
           set_errno (EPROTONOSUPPORT);
           goto done;
         }
-      dev = af_local_dev;
+      dev = (af == AF_LOCAL) ? af_local_dev : af_unix_dev;
       break;
     case AF_INET:
     case AF_INET6:
@@ -2312,6 +2313,7 @@ socketpair (int af, int type, int protocol, int *sb)
   switch (af)
     {
     case AF_LOCAL:
+    case AF_UNIX:
       if (type != SOCK_STREAM && type != SOCK_DGRAM)
         {
           set_errno (EINVAL);
@@ -2322,7 +2324,7 @@ socketpair (int af, int type, int protocol, int *sb)
           set_errno (EPROTONOSUPPORT);
           goto done;
         }
-      dev = af_local_dev;
+      dev = (af == AF_LOCAL) ? af_local_dev : af_unix_dev;
       break;
     default:
       set_errno (EAFNOSUPPORT);
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
index 023bec0..e489fcf 100644
--- a/winsup/cygwin/select.cc
+++ b/winsup/cygwin/select.cc
@@ -1602,6 +1602,51 @@ fhandler_socket_wsock::select_except (select_stuff *ss)
   return s;
 }
 
+select_record *
+fhandler_socket_unix::select_read (select_stuff *ss)
+{
+  select_record *s = ss->start.next;
+  if (!s->startup)
+    {
+      s->startup = no_startup;
+      s->verify = verify_ok;
+    }
+  s->h = get_io_handle_cyg ();
+  s->read_selected = true;
+  s->read_ready = true;
+  return s;
+}
+
+select_record *
+fhandler_socket_unix::select_write (select_stuff *ss)
+{
+  select_record *s = ss->start.next;
+  if (!s->startup)
+    {
+      s->startup = no_startup;
+      s->verify = verify_ok;
+    }
+  s->h = get_handle ();
+  s->write_selected = true;
+  s->write_ready = true;
+  return s;
+}
+
+select_record *
+fhandler_socket_unix::select_except (select_stuff *ss)
+{
+  select_record *s = ss->start.next;
+  if (!s->startup)
+    {
+      s->startup = no_startup;
+      s->verify = verify_ok;
+    }
+  s->h = NULL;
+  s->except_selected = true;
+  s->except_ready = false;
+  return s;
+}
+
 static int
 peek_windows (select_record *me, bool)
 {


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]