diff --git a/freebsd/sys/kern/sys_socket.c b/freebsd/sys/kern/sys_socket.c index 5318c69a..a748d8b1 100644 --- a/freebsd/sys/kern/sys_socket.c +++ b/freebsd/sys/kern/sys_socket.c @@ -71,8 +71,10 @@ struct fileops socketops = { }; #endif /* __rtems__ */ -#ifndef __rtems__ /* ARGSUSED */ +#ifdef __rtems__ +static +#endif /* __rtems__ */ int soo_read(struct file *fp, struct uio *uio, struct ucred *active_cred, int flags, struct thread *td) @@ -90,8 +92,45 @@ soo_read(struct file *fp, struct uio *uio, struct ucred *active_cred, CURVNET_RESTORE(); return (error); } +#ifdef __rtems__ +static ssize_t +rtems_bsd_soo_read(rtems_libio_t *iop, void *buffer, size_t count) +{ + struct thread *td = rtems_bsd_get_curthread_or_null(); + struct file *fp = rtems_bsd_iop_to_fp(iop); + struct iovec iov = { + .iov_base = buffer, + .iov_len = count + }; + struct uio auio = { + .uio_iov = &iov, + .uio_iovcnt = 1, + .uio_offset = 0, + .uio_resid = count, + .uio_segflg = UIO_USERSPACE, + .uio_rw = UIO_READ, + .uio_td = td + }; + int error; + + if (td != NULL) { + error = soo_read(fp, &auio, NULL, 0, NULL); + } else { + error = ENOMEM; + } + + if (error == 0) { + return (count - auio.uio_resid); + } else { + rtems_set_errno_and_return_minus_one(error); + } +} +#endif /* __rtems__ */ /* ARGSUSED */ +#ifdef __rtems__ +static +#endif /* __rtems__ */ int soo_write(struct file *fp, struct uio *uio, struct ucred *active_cred, int flags, struct thread *td) @@ -106,13 +145,52 @@ soo_write(struct file *fp, struct uio *uio, struct ucred *active_cred, #endif error = sosend(so, 0, uio, 0, 0, 0, uio->uio_td); if (error == EPIPE && (so->so_options & SO_NOSIGPIPE) == 0) { +#ifndef __rtems__ PROC_LOCK(uio->uio_td->td_proc); tdksignal(uio->uio_td, SIGPIPE, NULL); PROC_UNLOCK(uio->uio_td->td_proc); +#else /* __rtems__ */ + /* FIXME: Determine if we really want to use signals */ +#endif /* __rtems__ */ } return (error); } +#ifdef __rtems__ +static ssize_t +rtems_bsd_soo_write(rtems_libio_t *iop, const void *buffer, size_t count) +{ + struct thread *td = rtems_bsd_get_curthread_or_null(); + struct file *fp = rtems_bsd_iop_to_fp(iop); + struct iovec iov = { + .iov_base = __DECONST(void *, buffer), + .iov_len = count + }; + struct uio auio = { + .uio_iov = &iov, + .uio_iovcnt = 1, + .uio_offset = 0, + .uio_resid = count, + .uio_segflg = UIO_USERSPACE, + .uio_rw = UIO_WRITE, + .uio_td = td + }; + int error; + if (td != NULL) { + error = soo_write(fp, &auio, NULL, 0, NULL); + } else { + error = ENOMEM; + } + + if (error == 0) { + return (count - auio.uio_resid); + } else { + rtems_set_errno_and_return_minus_one(error); + } +} +#endif /* __rtems__ */ + +#ifndef __rtems__ int soo_truncate(struct file *fp, off_t length, struct ucred *active_cred, struct thread *td) @@ -132,10 +210,6 @@ soo_ioctl(struct file *fp, u_long cmd, void *data, struct ucred *active_cred, struct socket *so = fp->f_data; int error = 0; -#ifdef __rtems__ - if (td == NULL) - return (ENOMEM); -#endif /* __rtems__ */ CURVNET_SET(so->so_vnet); switch (cmd) { case FIONBIO: @@ -239,7 +313,13 @@ rtems_bsd_soo_ioctl(rtems_libio_t *iop, ioctl_command_t request, void *buffer) { struct thread *td = rtems_bsd_get_curthread_or_null(); struct file *fp = rtems_bsd_iop_to_fp(iop); - int error = soo_ioctl(fp, request, buffer, NULL, td); + int error; + + if (td != NULL) { + error = soo_ioctl(fp, request, buffer, NULL, td); + } else { + error = ENOMEM; + } return rtems_bsd_error_to_status_and_errno(error); } @@ -363,8 +443,8 @@ rtems_bsd_soo_close(rtems_libio_t *iop) const rtems_filesystem_file_handlers_r socketops = { .open_h = rtems_filesystem_default_open, .close_h = rtems_bsd_soo_close, - .read_h = rtems_filesystem_default_read, - .write_h = rtems_filesystem_default_write, + .read_h = rtems_bsd_soo_read, + .write_h = rtems_bsd_soo_write, .ioctl_h = rtems_bsd_soo_ioctl, .lseek_h = rtems_filesystem_default_lseek, .fstat_h = rtems_bsd_soo_stat, diff --git a/rtemsbsd/rtems/rtems-bsd-syscalls.c b/rtemsbsd/rtems/rtems-bsd-syscalls.c index 7dabea87..9c7605f6 100644 --- a/rtemsbsd/rtems/rtems-bsd-syscalls.c +++ b/rtemsbsd/rtems/rtems-bsd-syscalls.c @@ -618,127 +618,3 @@ done2: errno = error; return -1; } - -/* - ************************************************************************ - * RTEMS I/O HANDLER ROUTINES * - ************************************************************************ - */ -static int -rtems_bsdnet_close (rtems_libio_t *iop) -{ - struct socket *so; - int error; - - if ((so = iop->data1) == NULL) { - errno = EBADF; - return -1; - } - error = soclose (so); - if (error) { - errno = error; - return -1; - } - return 0; -} - -static ssize_t -rtems_bsdnet_read (rtems_libio_t *iop, void *buffer, size_t count) -{ - return recv (iop->data0, buffer, count, 0); -} - -static ssize_t -rtems_bsdnet_write (rtems_libio_t *iop, const void *buffer, size_t count) -{ - return send (iop->data0, buffer, count, 0); -} - -static int -so_ioctl (rtems_libio_t *iop, struct socket *so, uint32_t command, void *buffer) -{ - switch (command) { - case FIONBIO: - SOCK_LOCK(so); - if (*(int *)buffer) { - iop->flags |= O_NONBLOCK; - so->so_state |= SS_NBIO; - } - else { - iop->flags &= ~O_NONBLOCK; - so->so_state &= ~SS_NBIO; - } - SOCK_UNLOCK(so); - return 0; - - case FIONREAD: - *(int *)buffer = so->so_rcv.sb_cc; - return 0; - } - - if (IOCGROUP(command) == 'i') - return ifioctl (so, command, buffer, NULL); - if (IOCGROUP(command) == 'r') - return rtioctl (command, buffer, NULL); - return (*so->so_proto->pr_usrreqs->pru_control)(so, command, buffer, 0, curthread); -} - -static int -rtems_bsdnet_ioctl (rtems_libio_t *iop, uint32_t command, void *buffer) -{ - struct socket *so; - int error; - - if ((so = iop->data1) == NULL) { - errno = EBADF; - return -1; - } - error = so_ioctl (iop, so, command, buffer); - if (error) { - errno = error; - return -1; - } - return 0; -} - -static int -rtems_bsdnet_fcntl (int cmd, rtems_libio_t *iop) -{ - struct socket *so; - - if (cmd == F_SETFL) { - if ((so = iop->data1) == NULL) { - return EBADF; - } - SOCK_LOCK(so); - if (iop->flags & LIBIO_FLAGS_NO_DELAY) - so->so_state |= SS_NBIO; - else - so->so_state &= ~SS_NBIO; - SOCK_UNLOCK(so); - } - return 0; -} - -static int -rtems_bsdnet_fstat (rtems_filesystem_location_info_t *loc, struct stat *sp) -{ - sp->st_mode = S_IFSOCK; - return 0; -} - -static const rtems_filesystem_file_handlers_r socket_handlers = { - rtems_filesystem_default_open, /* open */ - rtems_bsdnet_close, /* close */ - rtems_bsdnet_read, /* read */ - rtems_bsdnet_write, /* write */ - rtems_bsdnet_ioctl, /* ioctl */ - rtems_filesystem_default_lseek, /* lseek */ - rtems_bsdnet_fstat, /* fstat */ - rtems_filesystem_default_fchmod, /* fchmod */ - rtems_filesystem_default_ftruncate, /* ftruncate */ - rtems_filesystem_default_fsync_or_fdatasync, /* fsync */ - rtems_filesystem_default_fsync_or_fdatasync, /* fdatasync */ - rtems_bsdnet_fcntl, /* fcntl */ - rtems_filesystem_default_rmnod /* rmnod */ -}; diff --git a/testsuite/syscalls01/test_main.c b/testsuite/syscalls01/test_main.c index 939ca451..1b2c1846 100644 --- a/testsuite/syscalls01/test_main.c +++ b/testsuite/syscalls01/test_main.c @@ -931,6 +931,71 @@ test_socket_getsockname(void) assert(rtems_resource_snapshot_check(&snapshot)); } +static void +no_mem_socket_read_and_write(int fd) +{ + ssize_t n; + char buf[1]; + + errno = 0; + n = read(fd, &buf[0], sizeof(buf)); + assert(n == -1); + assert(errno == ENOMEM); + + errno = 0; + n = write(fd, &buf[0], sizeof(buf)); + assert(n == -1); + assert(errno == ENOMEM); +} + +static void +test_socket_read_and_write(void) +{ + rtems_resource_snapshot snapshot; + int sd; + int rv; + ssize_t n; + char buf[1]; + int enable = 1; + + puts("test socket read and write"); + + rtems_resource_snapshot_take(&snapshot); + + sd = socket(PF_INET, SOCK_DGRAM, 0); + assert(sd >= 0); + + rv = ioctl(sd, FIONBIO, &enable); + assert(rv == 0); + + do_no_mem_test(no_mem_socket_read_and_write, sd); + + errno = 0; + n = read(sd, &buf[0], sizeof(buf)); + assert(n == -1); + assert(errno == EAGAIN); + + errno = 0; + n = write(sd, &buf[0], sizeof(buf)); + assert(n == -1); + assert(errno == EDESTADDRREQ); + + rv = close(sd); + assert(rv == 0); + + errno = 0; + n = read(sd, &buf[0], sizeof(buf)); + assert(n == -1); + assert(errno == EBADF); + + errno = 0; + n = write(sd, &buf[0], sizeof(buf)); + assert(n == -1); + assert(errno == EBADF); + + assert(rtems_resource_snapshot_check(&snapshot)); +} + static void test_main(void) { @@ -947,6 +1012,7 @@ test_main(void) test_socket_getsockopt_and_setsockopt(); test_socket_getpeername(); test_socket_getsockname(); + test_socket_read_and_write(); puts("*** END OF " TEST_NAME " TEST ***"); exit(0);