Cygwin: fhandler_socket: Rearrange methods
Follow the same pattern in all fhandler_socket classes. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
parent
9c593d9b39
commit
479080baec
|
@ -499,17 +499,18 @@ class fhandler_socket: public fhandler_base
|
||||||
ret |= SOCK_CLOEXEC;
|
ret |= SOCK_CLOEXEC;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
wsa_event *wsock_events;
|
wsa_event *wsock_events;
|
||||||
HANDLE wsock_mtx;
|
HANDLE wsock_mtx;
|
||||||
HANDLE wsock_evt;
|
HANDLE wsock_evt;
|
||||||
public:
|
|
||||||
bool init_events ();
|
bool init_events ();
|
||||||
int evaluate_events (const long event_mask, long &events, const bool erase);
|
|
||||||
const HANDLE wsock_event () const { return wsock_evt; }
|
|
||||||
const LONG serial_number () const { return wsock_events->serial_number; }
|
|
||||||
protected:
|
|
||||||
int wait_for_events (const long event_mask, const DWORD flags);
|
int wait_for_events (const long event_mask, const DWORD flags);
|
||||||
void release_events ();
|
void release_events ();
|
||||||
|
public:
|
||||||
|
const HANDLE wsock_event () const { return wsock_evt; }
|
||||||
|
int evaluate_events (const long event_mask, long &events, const bool erase);
|
||||||
|
const LONG serial_number () const { return wsock_events->serial_number; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int _rmem;
|
int _rmem;
|
||||||
|
@ -529,9 +530,6 @@ class fhandler_socket: public fhandler_base
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct _WSAPROTOCOL_INFOW *prot_info_ptr;
|
struct _WSAPROTOCOL_INFOW *prot_info_ptr;
|
||||||
public:
|
|
||||||
void init_fixup_before ();
|
|
||||||
bool need_fixup_before () const {return prot_info_ptr != NULL;}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct status_flags
|
struct status_flags
|
||||||
|
@ -573,6 +571,15 @@ class fhandler_socket: public fhandler_base
|
||||||
IMPLEMENT_STATUS_FLAG (conn_state, connect_state)
|
IMPLEMENT_STATUS_FLAG (conn_state, connect_state)
|
||||||
IMPLEMENT_STATUS_FLAG (bool, no_getpeereid)
|
IMPLEMENT_STATUS_FLAG (bool, no_getpeereid)
|
||||||
|
|
||||||
|
bool need_fixup_before () const {return prot_info_ptr != NULL;}
|
||||||
|
void set_close_on_exec (bool val);
|
||||||
|
void init_fixup_before ();
|
||||||
|
int fixup_before_fork_exec (DWORD);
|
||||||
|
void fixup_after_fork (HANDLE);
|
||||||
|
void fixup_after_exec ();
|
||||||
|
int dup (fhandler_base *child, int);
|
||||||
|
char *get_proc_fd_name (char *buf);
|
||||||
|
|
||||||
virtual int socket (int af, int type, int protocol, int flags) = 0;
|
virtual int socket (int af, int type, int protocol, int flags) = 0;
|
||||||
virtual int bind (const struct sockaddr *name, int namelen) = 0;
|
virtual int bind (const struct sockaddr *name, int namelen) = 0;
|
||||||
virtual int listen (int backlog) = 0;
|
virtual int listen (int backlog) = 0;
|
||||||
|
@ -583,12 +590,6 @@ class fhandler_socket: public fhandler_base
|
||||||
virtual int shutdown (int how) = 0;
|
virtual int shutdown (int how) = 0;
|
||||||
virtual int close () = 0;
|
virtual int close () = 0;
|
||||||
virtual int getpeereid (pid_t *pid, uid_t *euid, gid_t *egid);
|
virtual int getpeereid (pid_t *pid, uid_t *euid, gid_t *egid);
|
||||||
virtual int setsockopt (int level, int optname, const void *optval,
|
|
||||||
__socklen_t optlen) = 0;
|
|
||||||
virtual int getsockopt (int level, int optname, const void *optval,
|
|
||||||
__socklen_t *optlen) = 0;
|
|
||||||
|
|
||||||
int open (int flags, mode_t mode = 0);
|
|
||||||
virtual ssize_t recvfrom (void *ptr, size_t len, int flags,
|
virtual ssize_t recvfrom (void *ptr, size_t len, int flags,
|
||||||
struct sockaddr *from, int *fromlen) = 0;
|
struct sockaddr *from, int *fromlen) = 0;
|
||||||
virtual ssize_t recvmsg (struct msghdr *msg, int flags) = 0;
|
virtual ssize_t recvmsg (struct msghdr *msg, int flags) = 0;
|
||||||
|
@ -601,23 +602,28 @@ class fhandler_socket: public fhandler_base
|
||||||
virtual ssize_t sendmsg (const struct msghdr *msg, int flags) = 0;
|
virtual ssize_t sendmsg (const struct msghdr *msg, int flags) = 0;
|
||||||
virtual ssize_t __stdcall write (const void *ptr, size_t len) = 0;
|
virtual ssize_t __stdcall write (const void *ptr, size_t len) = 0;
|
||||||
virtual ssize_t __stdcall writev (const struct iovec *, int iovcnt, ssize_t tot = -1) = 0;
|
virtual ssize_t __stdcall writev (const struct iovec *, int iovcnt, ssize_t tot = -1) = 0;
|
||||||
|
virtual int setsockopt (int level, int optname, const void *optval,
|
||||||
|
__socklen_t optlen) = 0;
|
||||||
|
virtual int getsockopt (int level, int optname, const void *optval,
|
||||||
|
__socklen_t *optlen) = 0;
|
||||||
|
|
||||||
virtual int ioctl (unsigned int cmd, void *);
|
virtual int ioctl (unsigned int cmd, void *);
|
||||||
virtual int fcntl (int cmd, intptr_t);
|
virtual int fcntl (int cmd, intptr_t);
|
||||||
|
|
||||||
|
int open (int flags, mode_t mode = 0);
|
||||||
|
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 *);
|
||||||
off_t lseek (off_t, int)
|
off_t lseek (off_t, int)
|
||||||
{
|
{
|
||||||
set_errno (ESPIPE);
|
set_errno (ESPIPE);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
void hclose (HANDLE) {close ();}
|
|
||||||
int dup (fhandler_base *child, int);
|
|
||||||
|
|
||||||
void set_close_on_exec (bool val);
|
void hclose (HANDLE) {close ();}
|
||||||
int fixup_before_fork_exec (DWORD);
|
|
||||||
void fixup_after_fork (HANDLE);
|
|
||||||
void fixup_after_exec ();
|
|
||||||
char *get_proc_fd_name (char *buf);
|
|
||||||
|
|
||||||
select_record *select_read (select_stuff *);
|
select_record *select_read (select_stuff *);
|
||||||
select_record *select_write (select_stuff *);
|
select_record *select_write (select_stuff *);
|
||||||
|
@ -626,13 +632,6 @@ class fhandler_socket: public fhandler_base
|
||||||
int get_addr_family () {return addr_family;}
|
int get_addr_family () {return addr_family;}
|
||||||
void set_socket_type (int st) { type = st;}
|
void set_socket_type (int st) { type = st;}
|
||||||
int get_socket_type () {return type;}
|
int get_socket_type () {return type;}
|
||||||
|
|
||||||
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 *);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class fhandler_socket_inet: public fhandler_socket
|
class fhandler_socket_inet: public fhandler_socket
|
||||||
|
@ -657,10 +656,6 @@ class fhandler_socket_inet: public fhandler_socket
|
||||||
int getpeername (struct sockaddr *name, int *namelen);
|
int getpeername (struct sockaddr *name, int *namelen);
|
||||||
int shutdown (int how);
|
int shutdown (int how);
|
||||||
int close ();
|
int close ();
|
||||||
int setsockopt (int level, int optname, const void *optval,
|
|
||||||
__socklen_t optlen);
|
|
||||||
int getsockopt (int level, int optname, const void *optval,
|
|
||||||
__socklen_t *optlen);
|
|
||||||
ssize_t recvfrom (void *ptr, size_t len, int flags,
|
ssize_t recvfrom (void *ptr, size_t len, int flags,
|
||||||
struct sockaddr *from, int *fromlen);
|
struct sockaddr *from, int *fromlen);
|
||||||
ssize_t recvmsg (struct msghdr *msg, int flags);
|
ssize_t recvmsg (struct msghdr *msg, int flags);
|
||||||
|
@ -671,6 +666,11 @@ class fhandler_socket_inet: public fhandler_socket
|
||||||
ssize_t sendmsg (const struct msghdr *msg, int flags);
|
ssize_t sendmsg (const struct msghdr *msg, int flags);
|
||||||
ssize_t __stdcall write (const void *ptr, size_t len);
|
ssize_t __stdcall write (const void *ptr, size_t len);
|
||||||
ssize_t __stdcall writev (const struct iovec *, int iovcnt, ssize_t tot = -1);
|
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);
|
||||||
|
|
||||||
int ioctl (unsigned int cmd, void *);
|
int ioctl (unsigned int cmd, void *);
|
||||||
int fcntl (int cmd, intptr_t);
|
int fcntl (int cmd, intptr_t);
|
||||||
|
|
||||||
|
@ -747,10 +747,6 @@ class fhandler_socket_local: public fhandler_socket
|
||||||
int shutdown (int how);
|
int shutdown (int how);
|
||||||
int close ();
|
int close ();
|
||||||
int getpeereid (pid_t *pid, uid_t *euid, gid_t *egid);
|
int getpeereid (pid_t *pid, uid_t *euid, gid_t *egid);
|
||||||
int setsockopt (int level, int optname, const void *optval,
|
|
||||||
__socklen_t optlen);
|
|
||||||
int getsockopt (int level, int optname, const void *optval,
|
|
||||||
__socklen_t *optlen);
|
|
||||||
ssize_t recvfrom (void *ptr, size_t len, int flags,
|
ssize_t recvfrom (void *ptr, size_t len, int flags,
|
||||||
struct sockaddr *from, int *fromlen);
|
struct sockaddr *from, int *fromlen);
|
||||||
ssize_t recvmsg (struct msghdr *msg, int flags);
|
ssize_t recvmsg (struct msghdr *msg, int flags);
|
||||||
|
@ -761,6 +757,11 @@ class fhandler_socket_local: public fhandler_socket
|
||||||
ssize_t sendmsg (const struct msghdr *msg, int flags);
|
ssize_t sendmsg (const struct msghdr *msg, int flags);
|
||||||
ssize_t __stdcall write (const void *ptr, size_t len);
|
ssize_t __stdcall write (const void *ptr, size_t len);
|
||||||
ssize_t __stdcall writev (const struct iovec *, int iovcnt, ssize_t tot = -1);
|
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);
|
||||||
|
|
||||||
int ioctl (unsigned int cmd, void *);
|
int ioctl (unsigned int cmd, void *);
|
||||||
int fcntl (int cmd, intptr_t);
|
int fcntl (int cmd, intptr_t);
|
||||||
|
|
||||||
|
|
|
@ -77,20 +77,6 @@ fhandler_socket::~fhandler_socket ()
|
||||||
cfree (prot_info_ptr);
|
cfree (prot_info_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
|
||||||
fhandler_socket::get_proc_fd_name (char *buf)
|
|
||||||
{
|
|
||||||
__small_sprintf (buf, "socket:[%lu]", get_plain_ino ());
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
fhandler_socket::open (int flags, mode_t mode)
|
|
||||||
{
|
|
||||||
set_errno (ENXIO);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
fhandler_socket::set_socket_handle (SOCKET sock, int af, int type, int flags)
|
fhandler_socket::set_socket_handle (SOCKET sock, int af, int type, int flags)
|
||||||
{
|
{
|
||||||
|
@ -521,6 +507,20 @@ fhandler_socket::release_events ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fhandler_socket::set_close_on_exec (bool val)
|
||||||
|
{
|
||||||
|
set_no_inheritance (wsock_mtx, val);
|
||||||
|
set_no_inheritance (wsock_evt, val);
|
||||||
|
if (need_fixup_before ())
|
||||||
|
{
|
||||||
|
close_on_exec (val);
|
||||||
|
debug_printf ("set close_on_exec for %s to %d", get_name (), val);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fhandler_base::set_close_on_exec (val);
|
||||||
|
}
|
||||||
|
|
||||||
/* Called if a freshly created socket is not inheritable. In that case we
|
/* Called if a freshly created socket is not inheritable. In that case we
|
||||||
have to use fixup_before_fork_exec. See comment in set_socket_handle for
|
have to use fixup_before_fork_exec. See comment in set_socket_handle for
|
||||||
a description of the problem. */
|
a description of the problem. */
|
||||||
|
@ -629,97 +629,20 @@ fhandler_socket::dup (fhandler_base *child, int flags)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __reg2
|
char *
|
||||||
fhandler_socket::fstat (struct stat *buf)
|
fhandler_socket::get_proc_fd_name (char *buf)
|
||||||
{
|
{
|
||||||
int res;
|
__small_sprintf (buf, "socket:[%lu]", get_plain_ino ());
|
||||||
|
return buf;
|
||||||
res = fhandler_socket::fstat (buf);
|
|
||||||
if (!res)
|
|
||||||
{
|
|
||||||
buf->st_dev = FHDEV (DEV_TCP_MAJOR, 0);
|
|
||||||
if (!(buf->st_ino = get_plain_ino ()))
|
|
||||||
sscanf (get_name (), "/proc/%*d/fd/socket:[%lld]",
|
|
||||||
(long long *) &buf->st_ino);
|
|
||||||
buf->st_uid = uid;
|
|
||||||
buf->st_gid = gid;
|
|
||||||
buf->st_mode = mode;
|
|
||||||
buf->st_size = 0;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
int __reg2
|
|
||||||
fhandler_socket::fstatvfs (struct statvfs *sfs)
|
|
||||||
{
|
|
||||||
memset (sfs, 0, sizeof (*sfs));
|
|
||||||
sfs->f_bsize = sfs->f_frsize = 4096;
|
|
||||||
sfs->f_namemax = NAME_MAX;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
fhandler_socket::fchmod (mode_t newmode)
|
fhandler_socket::getpeereid (pid_t *pid, uid_t *euid, gid_t *egid)
|
||||||
{
|
{
|
||||||
mode = (newmode & ~S_IFMT) | S_IFSOCK;
|
set_errno (EINVAL);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
fhandler_socket::fchown (uid_t newuid, gid_t newgid)
|
|
||||||
{
|
|
||||||
bool perms = check_token_membership (&well_known_admins_sid);
|
|
||||||
|
|
||||||
/* Admin rulez */
|
|
||||||
if (!perms)
|
|
||||||
{
|
|
||||||
/* Otherwise, new uid == old uid or current uid is fine */
|
|
||||||
if (newuid == ILLEGAL_UID || newuid == uid || newuid == myself->uid)
|
|
||||||
perms = true;
|
|
||||||
/* Otherwise, new gid == old gid or current gid is fine */
|
|
||||||
else if (newgid == ILLEGAL_GID || newgid == gid || newgid == myself->gid)
|
|
||||||
perms = true;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Last but not least, newgid in supplementary group list is fine */
|
|
||||||
tmp_pathbuf tp;
|
|
||||||
gid_t *gids = (gid_t *) tp.w_get ();
|
|
||||||
int num = getgroups (65536 / sizeof (*gids), gids);
|
|
||||||
|
|
||||||
for (int idx = 0; idx < num; ++idx)
|
|
||||||
if (newgid == gids[idx])
|
|
||||||
{
|
|
||||||
perms = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (perms)
|
|
||||||
{
|
|
||||||
if (newuid != ILLEGAL_UID)
|
|
||||||
uid = newuid;
|
|
||||||
if (newgid != ILLEGAL_GID)
|
|
||||||
gid = newgid;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
set_errno (EPERM);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
fhandler_socket::facl (int cmd, int nentries, aclent_t *aclbufp)
|
|
||||||
{
|
|
||||||
set_errno (EOPNOTSUPP);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
fhandler_socket::link (const char *newpath)
|
|
||||||
{
|
|
||||||
return fhandler_base::link (newpath);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Definitions of old ifreq stuff used prior to Cygwin 1.7.0. */
|
/* Definitions of old ifreq stuff used prior to Cygwin 1.7.0. */
|
||||||
#define OLD_SIOCGIFFLAGS _IOW('s', 101, struct __old_ifreq)
|
#define OLD_SIOCGIFFLAGS _IOW('s', 101, struct __old_ifreq)
|
||||||
#define OLD_SIOCGIFADDR _IOW('s', 102, struct __old_ifreq)
|
#define OLD_SIOCGIFADDR _IOW('s', 102, struct __old_ifreq)
|
||||||
|
@ -933,23 +856,100 @@ fhandler_socket::fcntl (int cmd, intptr_t arg)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
fhandler_socket::set_close_on_exec (bool val)
|
fhandler_socket::open (int flags, mode_t mode)
|
||||||
{
|
{
|
||||||
set_no_inheritance (wsock_mtx, val);
|
set_errno (ENXIO);
|
||||||
set_no_inheritance (wsock_evt, val);
|
return 0;
|
||||||
if (need_fixup_before ())
|
}
|
||||||
|
|
||||||
|
int __reg2
|
||||||
|
fhandler_socket::fstat (struct stat *buf)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
res = fhandler_socket::fstat (buf);
|
||||||
|
if (!res)
|
||||||
{
|
{
|
||||||
close_on_exec (val);
|
buf->st_dev = FHDEV (DEV_TCP_MAJOR, 0);
|
||||||
debug_printf ("set close_on_exec for %s to %d", get_name (), val);
|
if (!(buf->st_ino = get_plain_ino ()))
|
||||||
|
sscanf (get_name (), "/proc/%*d/fd/socket:[%lld]",
|
||||||
|
(long long *) &buf->st_ino);
|
||||||
|
buf->st_uid = uid;
|
||||||
|
buf->st_gid = gid;
|
||||||
|
buf->st_mode = mode;
|
||||||
|
buf->st_size = 0;
|
||||||
}
|
}
|
||||||
else
|
return res;
|
||||||
fhandler_base::set_close_on_exec (val);
|
}
|
||||||
|
|
||||||
|
int __reg2
|
||||||
|
fhandler_socket::fstatvfs (struct statvfs *sfs)
|
||||||
|
{
|
||||||
|
memset (sfs, 0, sizeof (*sfs));
|
||||||
|
sfs->f_bsize = sfs->f_frsize = 4096;
|
||||||
|
sfs->f_namemax = NAME_MAX;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
fhandler_socket::getpeereid (pid_t *pid, uid_t *euid, gid_t *egid)
|
fhandler_socket::fchmod (mode_t newmode)
|
||||||
{
|
{
|
||||||
set_errno (EINVAL);
|
mode = (newmode & ~S_IFMT) | S_IFSOCK;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
fhandler_socket::fchown (uid_t newuid, gid_t newgid)
|
||||||
|
{
|
||||||
|
bool perms = check_token_membership (&well_known_admins_sid);
|
||||||
|
|
||||||
|
/* Admin rulez */
|
||||||
|
if (!perms)
|
||||||
|
{
|
||||||
|
/* Otherwise, new uid == old uid or current uid is fine */
|
||||||
|
if (newuid == ILLEGAL_UID || newuid == uid || newuid == myself->uid)
|
||||||
|
perms = true;
|
||||||
|
/* Otherwise, new gid == old gid or current gid is fine */
|
||||||
|
else if (newgid == ILLEGAL_GID || newgid == gid || newgid == myself->gid)
|
||||||
|
perms = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Last but not least, newgid in supplementary group list is fine */
|
||||||
|
tmp_pathbuf tp;
|
||||||
|
gid_t *gids = (gid_t *) tp.w_get ();
|
||||||
|
int num = getgroups (65536 / sizeof (*gids), gids);
|
||||||
|
|
||||||
|
for (int idx = 0; idx < num; ++idx)
|
||||||
|
if (newgid == gids[idx])
|
||||||
|
{
|
||||||
|
perms = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (perms)
|
||||||
|
{
|
||||||
|
if (newuid != ILLEGAL_UID)
|
||||||
|
uid = newuid;
|
||||||
|
if (newgid != ILLEGAL_GID)
|
||||||
|
gid = newgid;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
set_errno (EPERM);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
fhandler_socket::facl (int cmd, int nentries, aclent_t *aclbufp)
|
||||||
|
{
|
||||||
|
set_errno (EOPNOTSUPP);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
fhandler_socket::link (const char *newpath)
|
||||||
|
{
|
||||||
|
return fhandler_base::link (newpath);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue