static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp, int flags, int send) { abi_long ret, len; struct msghdr msg; int count; struct iovec *vec; abi_ulong target_vec; if (msgp->msg_name) { msg.msg_namelen = tswap32(msgp->msg_namelen); msg.msg_name = alloca(msg.msg_namelen+1); ret = target_to_host_sockaddr(fd, msg.msg_name, tswapal(msgp->msg_name), msg.msg_namelen); if (ret) { goto out2; } } else { msg.msg_name = NULL; msg.msg_namelen = 0; } msg.msg_controllen = 2 * tswapal(msgp->msg_controllen); msg.msg_control = alloca(msg.msg_controllen); msg.msg_flags = tswap32(msgp->msg_flags); count = tswapal(msgp->msg_iovlen); target_vec = tswapal(msgp->msg_iov); vec = lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, target_vec, count, send); if (vec == NULL) { ret = -host_to_target_errno(errno); goto out2; } msg.msg_iovlen = count; msg.msg_iov = vec; if (send) { ret = target_to_host_cmsg(&msg, msgp); if (ret == 0) ret = get_errno(sendmsg(fd, &msg, flags)); } else { ret = get_errno(recvmsg(fd, &msg, flags)); if (!is_error(ret)) { len = ret; ret = host_to_target_cmsg(msgp, &msg); if (!is_error(ret)) { msgp->msg_namelen = tswap32(msg.msg_namelen); if (msg.msg_name != NULL) { ret = host_to_target_sockaddr(tswapal(msgp->msg_name), msg.msg_name, msg.msg_namelen); if (ret) { goto out; } } ret = len; } } } out: unlock_iovec(vec, target_vec, count, !send); out2: return ret; }