diff --git a/fs/sock.c b/fs/sock.c index 4c62f1c485..761a5c2140 100644 --- a/fs/sock.c +++ b/fs/sock.c @@ -450,6 +450,24 @@ 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) { + STRACE("accept4(%d, 0x%x, 0x%x, %d) ", sock_fd, sockaddr_addr, sockaddr_len_addr, flags); + if (flags & ~(SOCK_NONBLOCK_ | SOCK_CLOEXEC_)) + return _EINVAL; + int_t client_f = sys_accept(sock_fd, sockaddr_addr, sockaddr_len_addr); + if (client_f < 0) + return client_f; + // The flags apply to the accepted fd, not the listener. + if (flags & SOCK_CLOEXEC_) + bit_set(client_f, current->files->cloexec); + if (flags & SOCK_NONBLOCK_) { + struct fd *client = f_get(client_f); + if (client != NULL) + fd_setflags(client, fd_getflags(client) | O_NONBLOCK_); + } + return client_f; +} + 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 +1232,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/kernel/calls.c b/kernel/calls.c index 23e3306b87..b215b8bfc2 100644 --- a/kernel/calls.c +++ b/kernel/calls.c @@ -234,7 +234,7 @@ syscall_t syscall_table[] = { [361] = (syscall_t) sys_bind, [362] = (syscall_t) sys_connect, [363] = (syscall_t) sys_listen, - [364] = (syscall_t) syscall_stub, // accept4 + [364] = (syscall_t) sys_accept4, [365] = (syscall_t) sys_getsockopt, [366] = (syscall_t) sys_setsockopt, [367] = (syscall_t) sys_getsockname,