From af0200363e8d0a69648bd78fd5ee2d0ee5f40624 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Fri, 19 Mar 1999 21:51:58 +0000 Subject: Patch from Eric Norum that adds external fcntl support and an external fcntl handler for sockets. --- c/src/exec/libcsupport/include/rtems/libio.h | 6 +++ c/src/exec/libcsupport/src/fcntl.c | 60 +++++++++++++++----------- c/src/exec/libnetworking/rtems/rtems_syscall.c | 34 +++++++++++++-- c/src/lib/include/rtems/libio.h | 6 +++ c/src/lib/libc/fcntl.c | 60 +++++++++++++++----------- c/src/lib/libc/libio.h | 6 +++ c/src/lib/libnetworking/rtems/rtems_syscall.c | 34 +++++++++++++-- c/src/libnetworking/rtems/rtems_syscall.c | 34 +++++++++++++-- 8 files changed, 180 insertions(+), 60 deletions(-) (limited to 'c') diff --git a/c/src/exec/libcsupport/include/rtems/libio.h b/c/src/exec/libcsupport/include/rtems/libio.h index 1cbfef383b..6ded1e361d 100644 --- a/c/src/exec/libcsupport/include/rtems/libio.h +++ b/c/src/exec/libcsupport/include/rtems/libio.h @@ -115,6 +115,11 @@ typedef int (*rtems_filesystem_fdatasync_t)( rtems_libio_t *iop ); +typedef int (*rtems_filesystem_fcntl_t)( + int cmd, + rtems_libio_t *iop +); + typedef struct { rtems_filesystem_open_t open; rtems_filesystem_close_t close; @@ -128,6 +133,7 @@ typedef struct { rtems_filesystem_fpathconf_t fpathconf; rtems_filesystem_fsync_t fsync; rtems_filesystem_fdatasync_t fdatasync; + rtems_filesystem_fcntl_t fcntl; } rtems_filesystem_file_handlers_r; /* diff --git a/c/src/exec/libcsupport/src/fcntl.c b/c/src/exec/libcsupport/src/fcntl.c index 381df45f26..3a65a74574 100644 --- a/c/src/exec/libcsupport/src/fcntl.c +++ b/c/src/exec/libcsupport/src/fcntl.c @@ -30,6 +30,7 @@ int fcntl( rtems_libio_t *diop; int fd2; int flags; + int ret = 0; va_start( ap, cmd ); @@ -53,8 +54,10 @@ int fcntl( else { /* allocate a file control block */ diop = rtems_libio_allocate(); - if ( diop == 0 ) - return -1; + if ( diop == 0 ) { + ret = -1; + break; + } } diop->handlers = iop->handlers; @@ -62,12 +65,11 @@ int fcntl( diop->flags = iop->flags; diop->pathinfo = iop->pathinfo; - return 0; + break; case F_GETFD: /* get f_flags */ - if ( iop->flags & LIBIO_FLAGS_CLOSE_ON_EXEC ) - return 1; - return 0; + ret = ((iop->flags & LIBIO_FLAGS_CLOSE_ON_EXEC) != 0); + break; case F_SETFD: /* set f_flags */ /* @@ -82,46 +84,56 @@ int fcntl( iop->flags |= LIBIO_FLAGS_CLOSE_ON_EXEC; else iop->flags &= ~LIBIO_FLAGS_CLOSE_ON_EXEC; - return 0; + break; case F_GETFL: /* more flags (cloexec) */ - return rtems_libio_to_fcntl_flags( iop->flags ); + ret = rtems_libio_to_fcntl_flags( iop->flags ); case F_SETFL: flags = rtems_libio_fcntl_flags( va_arg( ap, int ) ); - /* - * XXX Double check this in the POSIX spec. According to the Linux - * XXX man page, only these flags can be added. - */ - - flags = (iop->flags & ~(O_APPEND|O_NONBLOCK)) | - (flags & (O_APPEND|O_NONBLOCK)); - /* * XXX If we are turning on append, should we seek to the end? */ - iop->flags = flags; - return 0; + iop->flags = (iop->flags & ~(O_APPEND | O_NONBLOCK)) | + (flags & (O_APPEND | O_NONBLOCK)); + break; case F_GETLK: - return -1; + errno = ENOTSUP; + ret = -1; + break; case F_SETLK: - return -1; + errno = ENOTSUP; + ret = -1; + break; case F_SETLKW: - return -1; + errno = ENOTSUP; + ret = -1; + break; case F_SETOWN: /* for sockets. */ - return -1; + errno = ENOTSUP; + ret = -1; + break; case F_GETOWN: /* for sockets. */ - return -1; + errno = ENOTSUP; + ret = -1; + break; default: break; } - return -1; + if ((ret >= 0) && iop->handlers->fcntl) { + int err = (*iop->handlers->fcntl)( cmd, iop ); + if (err) { + errno = err; + ret = -1; + } + } + return ret; } diff --git a/c/src/exec/libnetworking/rtems/rtems_syscall.c b/c/src/exec/libnetworking/rtems/rtems_syscall.c index 141b7ceeba..7797e46a2a 100644 --- a/c/src/exec/libnetworking/rtems/rtems_syscall.c +++ b/c/src/exec/libnetworking/rtems/rtems_syscall.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -644,14 +645,18 @@ rtems_bsdnet_write (rtems_libio_t *iop, const void *buffer, unsigned32 count) } static int -so_ioctl (struct socket *so, unsigned32 command, void *buffer) +so_ioctl (rtems_libio_t *iop, struct socket *so, unsigned32 command, void *buffer) { switch (command) { case FIONBIO: - if (*(int *)buffer) + if (*(int *)buffer) { + iop->flags |= O_NONBLOCK; so->so_state |= SS_NBIO; - else + } + else { + iop->flags &= ~O_NONBLOCK; so->so_state &= ~SS_NBIO; + } return 0; case FIONREAD: @@ -678,7 +683,7 @@ rtems_bsdnet_ioctl (rtems_libio_t *iop, unsigned32 command, void *buffer) rtems_bsdnet_semaphore_release (); return -1; } - error = so_ioctl (so, command, buffer); + error = so_ioctl (iop, so, command, buffer); rtems_bsdnet_semaphore_release (); if (error) { errno = error; @@ -687,6 +692,26 @@ rtems_bsdnet_ioctl (rtems_libio_t *iop, unsigned32 command, void *buffer) return 0; } +static int +rtems_bsdnet_fcntl (int cmd, rtems_libio_t *iop) +{ + struct socket *so; + + if (cmd == F_SETFL) { + rtems_bsdnet_semaphore_obtain (); + if ((so = iop->data1) == NULL) { + rtems_bsdnet_semaphore_release (); + return EBADF; + } + if (iop->flags & O_NONBLOCK) + so->so_state |= SS_NBIO; + else + so->so_state &= ~SS_NBIO; + rtems_bsdnet_semaphore_release (); + } + return 0; +} + static int rtems_bsdnet_fstat (rtems_filesystem_location_info_t *loc, struct stat *sp) { @@ -707,4 +732,5 @@ static const rtems_filesystem_file_handlers_r socket_handlers = { NULL, /* fpathconf */ NULL, /* fsync */ NULL, /* fdatasync */ + rtems_bsdnet_fcntl, /* fcntl */ }; diff --git a/c/src/lib/include/rtems/libio.h b/c/src/lib/include/rtems/libio.h index 1cbfef383b..6ded1e361d 100644 --- a/c/src/lib/include/rtems/libio.h +++ b/c/src/lib/include/rtems/libio.h @@ -115,6 +115,11 @@ typedef int (*rtems_filesystem_fdatasync_t)( rtems_libio_t *iop ); +typedef int (*rtems_filesystem_fcntl_t)( + int cmd, + rtems_libio_t *iop +); + typedef struct { rtems_filesystem_open_t open; rtems_filesystem_close_t close; @@ -128,6 +133,7 @@ typedef struct { rtems_filesystem_fpathconf_t fpathconf; rtems_filesystem_fsync_t fsync; rtems_filesystem_fdatasync_t fdatasync; + rtems_filesystem_fcntl_t fcntl; } rtems_filesystem_file_handlers_r; /* diff --git a/c/src/lib/libc/fcntl.c b/c/src/lib/libc/fcntl.c index 381df45f26..3a65a74574 100644 --- a/c/src/lib/libc/fcntl.c +++ b/c/src/lib/libc/fcntl.c @@ -30,6 +30,7 @@ int fcntl( rtems_libio_t *diop; int fd2; int flags; + int ret = 0; va_start( ap, cmd ); @@ -53,8 +54,10 @@ int fcntl( else { /* allocate a file control block */ diop = rtems_libio_allocate(); - if ( diop == 0 ) - return -1; + if ( diop == 0 ) { + ret = -1; + break; + } } diop->handlers = iop->handlers; @@ -62,12 +65,11 @@ int fcntl( diop->flags = iop->flags; diop->pathinfo = iop->pathinfo; - return 0; + break; case F_GETFD: /* get f_flags */ - if ( iop->flags & LIBIO_FLAGS_CLOSE_ON_EXEC ) - return 1; - return 0; + ret = ((iop->flags & LIBIO_FLAGS_CLOSE_ON_EXEC) != 0); + break; case F_SETFD: /* set f_flags */ /* @@ -82,46 +84,56 @@ int fcntl( iop->flags |= LIBIO_FLAGS_CLOSE_ON_EXEC; else iop->flags &= ~LIBIO_FLAGS_CLOSE_ON_EXEC; - return 0; + break; case F_GETFL: /* more flags (cloexec) */ - return rtems_libio_to_fcntl_flags( iop->flags ); + ret = rtems_libio_to_fcntl_flags( iop->flags ); case F_SETFL: flags = rtems_libio_fcntl_flags( va_arg( ap, int ) ); - /* - * XXX Double check this in the POSIX spec. According to the Linux - * XXX man page, only these flags can be added. - */ - - flags = (iop->flags & ~(O_APPEND|O_NONBLOCK)) | - (flags & (O_APPEND|O_NONBLOCK)); - /* * XXX If we are turning on append, should we seek to the end? */ - iop->flags = flags; - return 0; + iop->flags = (iop->flags & ~(O_APPEND | O_NONBLOCK)) | + (flags & (O_APPEND | O_NONBLOCK)); + break; case F_GETLK: - return -1; + errno = ENOTSUP; + ret = -1; + break; case F_SETLK: - return -1; + errno = ENOTSUP; + ret = -1; + break; case F_SETLKW: - return -1; + errno = ENOTSUP; + ret = -1; + break; case F_SETOWN: /* for sockets. */ - return -1; + errno = ENOTSUP; + ret = -1; + break; case F_GETOWN: /* for sockets. */ - return -1; + errno = ENOTSUP; + ret = -1; + break; default: break; } - return -1; + if ((ret >= 0) && iop->handlers->fcntl) { + int err = (*iop->handlers->fcntl)( cmd, iop ); + if (err) { + errno = err; + ret = -1; + } + } + return ret; } diff --git a/c/src/lib/libc/libio.h b/c/src/lib/libc/libio.h index 1cbfef383b..6ded1e361d 100644 --- a/c/src/lib/libc/libio.h +++ b/c/src/lib/libc/libio.h @@ -115,6 +115,11 @@ typedef int (*rtems_filesystem_fdatasync_t)( rtems_libio_t *iop ); +typedef int (*rtems_filesystem_fcntl_t)( + int cmd, + rtems_libio_t *iop +); + typedef struct { rtems_filesystem_open_t open; rtems_filesystem_close_t close; @@ -128,6 +133,7 @@ typedef struct { rtems_filesystem_fpathconf_t fpathconf; rtems_filesystem_fsync_t fsync; rtems_filesystem_fdatasync_t fdatasync; + rtems_filesystem_fcntl_t fcntl; } rtems_filesystem_file_handlers_r; /* diff --git a/c/src/lib/libnetworking/rtems/rtems_syscall.c b/c/src/lib/libnetworking/rtems/rtems_syscall.c index 141b7ceeba..7797e46a2a 100644 --- a/c/src/lib/libnetworking/rtems/rtems_syscall.c +++ b/c/src/lib/libnetworking/rtems/rtems_syscall.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -644,14 +645,18 @@ rtems_bsdnet_write (rtems_libio_t *iop, const void *buffer, unsigned32 count) } static int -so_ioctl (struct socket *so, unsigned32 command, void *buffer) +so_ioctl (rtems_libio_t *iop, struct socket *so, unsigned32 command, void *buffer) { switch (command) { case FIONBIO: - if (*(int *)buffer) + if (*(int *)buffer) { + iop->flags |= O_NONBLOCK; so->so_state |= SS_NBIO; - else + } + else { + iop->flags &= ~O_NONBLOCK; so->so_state &= ~SS_NBIO; + } return 0; case FIONREAD: @@ -678,7 +683,7 @@ rtems_bsdnet_ioctl (rtems_libio_t *iop, unsigned32 command, void *buffer) rtems_bsdnet_semaphore_release (); return -1; } - error = so_ioctl (so, command, buffer); + error = so_ioctl (iop, so, command, buffer); rtems_bsdnet_semaphore_release (); if (error) { errno = error; @@ -687,6 +692,26 @@ rtems_bsdnet_ioctl (rtems_libio_t *iop, unsigned32 command, void *buffer) return 0; } +static int +rtems_bsdnet_fcntl (int cmd, rtems_libio_t *iop) +{ + struct socket *so; + + if (cmd == F_SETFL) { + rtems_bsdnet_semaphore_obtain (); + if ((so = iop->data1) == NULL) { + rtems_bsdnet_semaphore_release (); + return EBADF; + } + if (iop->flags & O_NONBLOCK) + so->so_state |= SS_NBIO; + else + so->so_state &= ~SS_NBIO; + rtems_bsdnet_semaphore_release (); + } + return 0; +} + static int rtems_bsdnet_fstat (rtems_filesystem_location_info_t *loc, struct stat *sp) { @@ -707,4 +732,5 @@ static const rtems_filesystem_file_handlers_r socket_handlers = { NULL, /* fpathconf */ NULL, /* fsync */ NULL, /* fdatasync */ + rtems_bsdnet_fcntl, /* fcntl */ }; diff --git a/c/src/libnetworking/rtems/rtems_syscall.c b/c/src/libnetworking/rtems/rtems_syscall.c index 141b7ceeba..7797e46a2a 100644 --- a/c/src/libnetworking/rtems/rtems_syscall.c +++ b/c/src/libnetworking/rtems/rtems_syscall.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -644,14 +645,18 @@ rtems_bsdnet_write (rtems_libio_t *iop, const void *buffer, unsigned32 count) } static int -so_ioctl (struct socket *so, unsigned32 command, void *buffer) +so_ioctl (rtems_libio_t *iop, struct socket *so, unsigned32 command, void *buffer) { switch (command) { case FIONBIO: - if (*(int *)buffer) + if (*(int *)buffer) { + iop->flags |= O_NONBLOCK; so->so_state |= SS_NBIO; - else + } + else { + iop->flags &= ~O_NONBLOCK; so->so_state &= ~SS_NBIO; + } return 0; case FIONREAD: @@ -678,7 +683,7 @@ rtems_bsdnet_ioctl (rtems_libio_t *iop, unsigned32 command, void *buffer) rtems_bsdnet_semaphore_release (); return -1; } - error = so_ioctl (so, command, buffer); + error = so_ioctl (iop, so, command, buffer); rtems_bsdnet_semaphore_release (); if (error) { errno = error; @@ -687,6 +692,26 @@ rtems_bsdnet_ioctl (rtems_libio_t *iop, unsigned32 command, void *buffer) return 0; } +static int +rtems_bsdnet_fcntl (int cmd, rtems_libio_t *iop) +{ + struct socket *so; + + if (cmd == F_SETFL) { + rtems_bsdnet_semaphore_obtain (); + if ((so = iop->data1) == NULL) { + rtems_bsdnet_semaphore_release (); + return EBADF; + } + if (iop->flags & O_NONBLOCK) + so->so_state |= SS_NBIO; + else + so->so_state &= ~SS_NBIO; + rtems_bsdnet_semaphore_release (); + } + return 0; +} + static int rtems_bsdnet_fstat (rtems_filesystem_location_info_t *loc, struct stat *sp) { @@ -707,4 +732,5 @@ static const rtems_filesystem_file_handlers_r socket_handlers = { NULL, /* fpathconf */ NULL, /* fsync */ NULL, /* fdatasync */ + rtems_bsdnet_fcntl, /* fcntl */ }; -- cgit v1.2.3