Use socket read() and write() from FreeBSD

This commit is contained in:
Sebastian Huber 2013-10-14 14:55:04 +02:00
parent 8989c110f5
commit ec702abace
3 changed files with 154 additions and 132 deletions

View File

@ -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,

View File

@ -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 */
};

View File

@ -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);