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:
parent
5acadbe8af
commit
7f7532fafb
|
@ -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 \
|
||||
|
|
|
@ -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};
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
@ -639,16 +641,6 @@ class fhandler_socket_wsock: public fhandler_socket
|
|||
SOCKET get_socket () { return (SOCKET) get_handle(); }
|
||||
#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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue