mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-07-24 06:52:02 +08:00
Use socket read() and write() from FreeBSD
This commit is contained in:
parent
8989c110f5
commit
ec702abace
@ -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,
|
||||
|
@ -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 */
|
||||
};
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user