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>
This commit is contained in:
Corinna Vinschen 2018-02-23 20:59:21 +01:00
parent 5acadbe8af
commit 7f7532fafb
11 changed files with 832 additions and 19 deletions

View File

@ -298,6 +298,7 @@ DLL_OFILES:= \
fhandler_socket.o \ fhandler_socket.o \
fhandler_socket_inet.o \ fhandler_socket_inet.o \
fhandler_socket_local.o \ fhandler_socket_local.o \
fhandler_socket_unix.o \
fhandler_tape.o \ fhandler_tape.o \
fhandler_termios.o \ fhandler_termios.o \
fhandler_tty.o \ fhandler_tty.o \

View File

@ -126,6 +126,9 @@ const _device dev_socket_storage =
const _device dev_af_inet_storage = const _device dev_af_inet_storage =
{"", {FH_INET}, "", exists_internal}; {"", {FH_INET}, "", exists_internal};
const _device dev_af_unix_storage =
{"", {FH_UNIX}, "", exists_internal};
const _device dev_af_local_storage = const _device dev_af_local_storage =
{"", {FH_LOCAL}, "", exists_internal}; {"", {FH_LOCAL}, "", exists_internal};

View File

@ -244,6 +244,7 @@ enum fh_devices
DEV_SOCK_MAJOR = 30, DEV_SOCK_MAJOR = 30,
FH_SOCKET = FHDEV (DEV_SOCK_MAJOR, 0), FH_SOCKET = FHDEV (DEV_SOCK_MAJOR, 0),
FH_INET = FHDEV (DEV_SOCK_MAJOR, 36), FH_INET = FHDEV (DEV_SOCK_MAJOR, 36),
FH_UNIX = FHDEV (DEV_SOCK_MAJOR, 42),
FH_LOCAL = FHDEV (DEV_SOCK_MAJOR, 120), FH_LOCAL = FHDEV (DEV_SOCK_MAJOR, 120),
FH_NADA = FHDEV (0, 0), 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) #define af_inet_dev ((device *) &dev_af_inet_storage)
extern const _device dev_af_local_storage; extern const _device dev_af_local_storage;
#define af_local_dev ((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; extern const _device dev_piper_storage;
#define piper_dev ((device *) &dev_piper_storage) #define piper_dev ((device *) &dev_piper_storage)

View File

@ -122,6 +122,9 @@ const _device dev_socket_storage =
const _device dev_af_inet_storage = const _device dev_af_inet_storage =
{"", {FH_INET}, "", exists_internal}; {"", {FH_INET}, "", exists_internal};
const _device dev_af_unix_storage =
{"", {FH_UNIX}, "", exists_internal};
const _device dev_af_local_storage = const _device dev_af_local_storage =
{"", {FH_LOCAL}, "", exists_internal}; {"", {FH_LOCAL}, "", exists_internal};

View File

@ -520,6 +520,9 @@ fh_alloc (path_conv& pc)
case FH_LOCAL: case FH_LOCAL:
fh = cnew (fhandler_socket_local); fh = cnew (fhandler_socket_local);
break; break;
case FH_UNIX:
fh = cnew (fhandler_socket_unix);
break;
case FH_FS: case FH_FS:
fh = cnew (fhandler_disk_file); fh = cnew (fhandler_disk_file);
break; break;

View File

@ -521,17 +521,19 @@ class fhandler_socket: public fhandler_base
unsigned async_io : 1; /* async I/O */ unsigned async_io : 1; /* async I/O */
unsigned saw_shutdown_read : 1; /* Socket saw a SHUT_RD */ unsigned saw_shutdown_read : 1; /* Socket saw a SHUT_RD */
unsigned saw_shutdown_write : 1; /* Socket saw a SHUT_WR */ unsigned saw_shutdown_write : 1; /* Socket saw a SHUT_WR */
unsigned saw_reuseaddr : 1; /* Socket saw SO_REUSEADDR call */
unsigned connect_state : 3; unsigned connect_state : 3;
public: public:
status_flags () : status_flags () :
async_io (0), saw_shutdown_read (0), saw_shutdown_write (0), async_io (0), saw_shutdown_read (0), saw_shutdown_write (0),
connect_state (unconnected) saw_reuseaddr (0), connect_state (unconnected)
{} {}
} status; } status;
public: public:
IMPLEMENT_STATUS_FLAG (bool, async_io) IMPLEMENT_STATUS_FLAG (bool, async_io)
IMPLEMENT_STATUS_FLAG (bool, saw_shutdown_read) IMPLEMENT_STATUS_FLAG (bool, saw_shutdown_read)
IMPLEMENT_STATUS_FLAG (bool, saw_shutdown_write) IMPLEMENT_STATUS_FLAG (bool, saw_shutdown_write)
IMPLEMENT_STATUS_FLAG (bool, saw_reuseaddr)
IMPLEMENT_STATUS_FLAG (conn_state, connect_state) IMPLEMENT_STATUS_FLAG (conn_state, connect_state)
public: public:
@ -639,16 +641,6 @@ class fhandler_socket_wsock: public fhandler_socket
SOCKET get_socket () { return (SOCKET) get_handle(); } SOCKET get_socket () { return (SOCKET) get_handle(); }
#endif #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: protected:
virtual ssize_t recv_internal (struct _WSAMSG *wsamsg, bool use_recvmsg) = 0; virtual ssize_t recv_internal (struct _WSAMSG *wsamsg, bool use_recvmsg) = 0;
ssize_t send_internal (struct _WSAMSG *wsamsg, int flags); 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 class fhandler_base_overlapped: public fhandler_base
{ {
static HANDLE asio_done; static HANDLE asio_done;

View File

@ -211,8 +211,7 @@ fhandler_socket_wsock::fhandler_socket_wsock () :
wsock_events (NULL), wsock_events (NULL),
wsock_mtx (NULL), wsock_mtx (NULL),
wsock_evt (NULL), wsock_evt (NULL),
prot_info_ptr (NULL), prot_info_ptr (NULL)
status ()
{ {
need_fork_fixup (true); need_fork_fixup (true);
} }
@ -1429,8 +1428,6 @@ fhandler_socket_inet::sendto (const void *in_ptr, size_t len, int flags,
ssize_t ssize_t
fhandler_socket_inet::sendmsg (const struct msghdr *msg, int flags) fhandler_socket_inet::sendmsg (const struct msghdr *msg, int flags)
{ {
/* TODO: Descriptor passing on AF_LOCAL sockets. */
struct sockaddr_storage sst; struct sockaddr_storage sst;
int len = 0; 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 /* Disappointing but true: Even if WSASendMsg is supported, it's only
supported for datagram and raw sockets. */ supported for datagram and raw sockets. */
DWORD controllen = (DWORD) (get_socket_type () == SOCK_STREAM DWORD controllen = (DWORD) ((get_socket_type () == SOCK_STREAM)
|| get_addr_family () == AF_LOCAL
? 0 : msg->msg_controllen); ? 0 : msg->msg_controllen);
WSAMSG wsamsg = { msg->msg_name ? (struct sockaddr *) &sst : NULL, len, WSAMSG wsamsg = { msg->msg_name ? (struct sockaddr *) &sst : NULL, len,
wsabuf, (DWORD) msg->msg_iovlen, wsabuf, (DWORD) msg->msg_iovlen,

View File

@ -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);
}

View File

@ -138,7 +138,13 @@ struct OLD_msghdr
* Address families. * Address families.
*/ */
#define AF_UNSPEC 0 /* unspecified */ #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) */ #define AF_UNIX 1 /* local to host (pipes, portals) */
#endif
#define AF_LOCAL 1 /* POSIX name for AF_UNIX */ #define AF_LOCAL 1 /* POSIX name for AF_UNIX */
#define AF_INET 2 /* internetwork: UDP, TCP, etc. */ #define AF_INET 2 /* internetwork: UDP, TCP, etc. */
#define AF_IMPLINK 3 /* arpanet imp addresses */ #define AF_IMPLINK 3 /* arpanet imp addresses */

View File

@ -516,6 +516,7 @@ cygwin_socket (int af, int type, int protocol)
switch (af) switch (af)
{ {
case AF_LOCAL: case AF_LOCAL:
case AF_UNIX:
if (type != SOCK_STREAM && type != SOCK_DGRAM) if (type != SOCK_STREAM && type != SOCK_DGRAM)
{ {
set_errno (EINVAL); set_errno (EINVAL);
@ -526,7 +527,7 @@ cygwin_socket (int af, int type, int protocol)
set_errno (EPROTONOSUPPORT); set_errno (EPROTONOSUPPORT);
goto done; goto done;
} }
dev = af_local_dev; dev = (af == AF_LOCAL) ? af_local_dev : af_unix_dev;
break; break;
case AF_INET: case AF_INET:
case AF_INET6: case AF_INET6:
@ -2312,6 +2313,7 @@ socketpair (int af, int type, int protocol, int *sb)
switch (af) switch (af)
{ {
case AF_LOCAL: case AF_LOCAL:
case AF_UNIX:
if (type != SOCK_STREAM && type != SOCK_DGRAM) if (type != SOCK_STREAM && type != SOCK_DGRAM)
{ {
set_errno (EINVAL); set_errno (EINVAL);
@ -2322,7 +2324,7 @@ socketpair (int af, int type, int protocol, int *sb)
set_errno (EPROTONOSUPPORT); set_errno (EPROTONOSUPPORT);
goto done; goto done;
} }
dev = af_local_dev; dev = (af == AF_LOCAL) ? af_local_dev : af_unix_dev;
break; break;
default: default:
set_errno (EAFNOSUPPORT); set_errno (EAFNOSUPPORT);

View File

@ -1602,6 +1602,51 @@ fhandler_socket_wsock::select_except (select_stuff *ss)
return s; 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 static int
peek_windows (select_record *me, bool) peek_windows (select_record *me, bool)
{ {