diff --git a/fs/fd.c b/fs/fd.c index 6bc39f5918..fbaf02c90e 100644 --- a/fs/fd.c +++ b/fs/fd.c @@ -226,21 +226,6 @@ void fdtable_do_cloexec(struct fdtable *table) { unlock(&table->lock); } -#define F_DUPFD_ 0 -#define F_GETFD_ 1 -#define F_SETFD_ 2 -#define F_GETFL_ 3 -#define F_SETFL_ 4 - -#define F_GETLK_ 5 -#define F_SETLK_ 6 -#define F_SETLKW_ 7 -#define F_GETLK64_ 12 -#define F_SETLK64_ 13 -#define F_SETLKW64_ 14 - -#define F_DUPFD_CLOEXEC_ 1030 - dword_t sys_dup(fd_t f) { STRACE("dup(%d)", f); struct fd *fd = f_get(f); diff --git a/fs/fd.h b/fs/fd.h index 4bd1f18353..b67a7f84c4 100644 --- a/fs/fd.h +++ b/fs/fd.h @@ -124,6 +124,21 @@ struct dir_entry { char name[NAME_MAX + 1]; }; +#define F_DUPFD_ 0 +#define F_GETFD_ 1 +#define F_SETFD_ 2 +#define F_GETFL_ 3 +#define F_SETFL_ 4 + +#define F_GETLK_ 5 +#define F_SETLK_ 6 +#define F_SETLKW_ 7 +#define F_GETLK64_ 12 +#define F_SETLK64_ 13 +#define F_SETLKW64_ 14 + +#define F_DUPFD_CLOEXEC_ 1030 + #define LSEEK_SET 0 #define LSEEK_CUR 1 #define LSEEK_END 2 diff --git a/fs/sock.c b/fs/sock.c index 4c62f1c485..809c2d2e58 100644 --- a/fs/sock.c +++ b/fs/sock.c @@ -450,6 +450,21 @@ int_t sys_accept(fd_t sock_fd, addr_t sockaddr_addr, addr_t sockaddr_len_addr) { return client_f; } +int_t sys_accept4(fd_t sock_fd, addr_t sockaddr_addr, addr_t sockaddr_len_addr, int_t flags) { + if (flags & ~(SOCK_NONBLOCK_ | SOCK_CLOEXEC_)) + return _EINVAL; + fd_t client = sys_accept(sock_fd, sockaddr_addr, sockaddr_len_addr); + if (client < 0) + return client; + if (flags & SOCK_NONBLOCK_) { + int_t old = sys_fcntl(client, F_GETFL_, 0); + sys_fcntl(client, F_SETFL_, old | O_NONBLOCK_); + } + if (flags & SOCK_CLOEXEC_) + sys_fcntl(client, F_SETFD_, 1); + return client; +} + static void copy_unix_name(char *sockaddr, dword_t *sockaddr_len, struct fd *sock) { struct sockaddr_ *fake_addr = (void *) sockaddr; fake_addr->family = PF_LOCAL_; @@ -1214,7 +1229,7 @@ static struct socket_call { {(syscall_t) sys_getsockopt, 5}, {(syscall_t) sys_sendmsg, 3}, {(syscall_t) sys_recvmsg, 3}, - {NULL}, // accept4 + {(syscall_t) sys_accept4, 4}, {NULL}, // recvmmsg {(syscall_t) sys_sendmmsg, 4}, }; diff --git a/fs/sock.h b/fs/sock.h index ce40ca5d6a..2df3064ea0 100644 --- a/fs/sock.h +++ b/fs/sock.h @@ -16,6 +16,7 @@ int_t sys_bind(fd_t sock_fd, addr_t sockaddr_addr, uint_t sockaddr_len); int_t sys_connect(fd_t sock_fd, addr_t sockaddr_addr, uint_t sockaddr_len); int_t sys_listen(fd_t sock_fd, int_t backlog); int_t sys_accept(fd_t sock_fd, addr_t sockaddr_addr, addr_t sockaddr_len_addr); +int_t sys_accept4(fd_t sock_fd, addr_t sockaddr_addr, addr_t sockaddr_len_addr, int_t flags); int_t sys_getsockname(fd_t sock_fd, addr_t sockaddr_addr, addr_t sockaddr_len_addr); int_t sys_getpeername(fd_t sock_fd, addr_t sockaddr_addr, addr_t sockaddr_len_addr); int_t sys_socketpair(dword_t domain, dword_t type, dword_t protocol, addr_t sockets_addr); diff --git a/tests/e2e/accept4/expected.txt b/tests/e2e/accept4/expected.txt new file mode 100644 index 0000000000..fc269290ce --- /dev/null +++ b/tests/e2e/accept4/expected.txt @@ -0,0 +1 @@ +accept4 ok \ No newline at end of file diff --git a/tests/e2e/accept4/test.sh b/tests/e2e/accept4/test.sh new file mode 100644 index 0000000000..99e018ff6e --- /dev/null +++ b/tests/e2e/accept4/test.sh @@ -0,0 +1,21 @@ +python3 -c " +import socket, ctypes, ctypes.util, threading, time + +libc = ctypes.CDLL(ctypes.util.find_library('c'), use_errno=True) +s = socket.socket() +s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +s.bind(('127.0.0.1', 19999)) +s.listen(1) + +def connect(): + time.sleep(0.3) + c = socket.socket() + c.connect(('127.0.0.1', 19999)) + +threading.Thread(target=connect).start() + +args = (ctypes.c_ulong * 4)(s.fileno(), 0, 0, 0) +result = libc.syscall(102, 18, args) +err = ctypes.get_errno() +print('accept4 ok' if result > 0 else 'accept4 failed errno=' + str(err)) +"