Commit a94b4987 authored by Peter Maydell's avatar Peter Maydell Committed by Riku Voipio
Browse files

linux-user: Implement accept4



Implement the accept4 syscall (which is identical to accept
but has an additional flags argument).

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
Reviewed-by: default avatarRichard Henderson <rth@twiddle.net>
Signed-off-by: default avatarRiku Voipio <riku.voipio@linaro.org>
parent a8fd1aba
Loading
Loading
Loading
Loading
+31 −8
Original line number Diff line number Diff line
@@ -2004,16 +2004,30 @@ out2:
    return ret;
}

/* do_accept() Must return target values and target errnos. */
static abi_long do_accept(int fd, abi_ulong target_addr,
                          abi_ulong target_addrlen_addr)
/* If we don't have a system accept4() then just call accept.
 * The callsites to do_accept4() will ensure that they don't
 * pass a non-zero flags argument in this config.
 */
#ifndef CONFIG_ACCEPT4
static inline int accept4(int sockfd, struct sockaddr *addr,
                          socklen_t *addrlen, int flags)
{
    assert(flags == 0);
    return accept(sockfd, addr, addrlen);
}
#endif

/* do_accept4() Must return target values and target errnos. */
static abi_long do_accept4(int fd, abi_ulong target_addr,
                           abi_ulong target_addrlen_addr, int flags)
{
    socklen_t addrlen;
    void *addr;
    abi_long ret;

    if (target_addr == 0)
       return get_errno(accept(fd, NULL, NULL));
    if (target_addr == 0) {
        return get_errno(accept4(fd, NULL, NULL, flags));
    }

    /* linux returns EINVAL if addrlen pointer is invalid */
    if (get_user_u32(addrlen, target_addrlen_addr))
@@ -2028,7 +2042,7 @@ static abi_long do_accept(int fd, abi_ulong target_addr,

    addr = alloca(addrlen);

    ret = get_errno(accept(fd, addr, &addrlen));
    ret = get_errno(accept4(fd, addr, &addrlen, flags));
    if (!is_error(ret)) {
        host_to_target_sockaddr(target_addr, addr, addrlen);
        if (put_user_u32(addrlen, target_addrlen_addr))
@@ -2254,7 +2268,7 @@ static abi_long do_socketcall(int num, abi_ulong vptr)
                || get_user_ual(target_addrlen, vptr + 2 * n))
                return -TARGET_EFAULT;

            ret = do_accept(sockfd, target_addr, target_addrlen);
            ret = do_accept4(sockfd, target_addr, target_addrlen, 0);
        }
        break;
    case SOCKOP_getsockname:
@@ -6677,7 +6691,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#endif
#ifdef TARGET_NR_accept
    case TARGET_NR_accept:
        ret = do_accept(arg1, arg2, arg3);
        ret = do_accept4(arg1, arg2, arg3, 0);
        break;
#endif
#ifdef TARGET_NR_accept4
    case TARGET_NR_accept4:
#ifdef CONFIG_ACCEPT4
        ret = do_accept4(arg1, arg2, arg3, arg4);
#else
        goto unimplemented;
#endif
        break;
#endif
#ifdef TARGET_NR_bind