From 3951d4da6fc4885dd450e5257d7273ab6a392492 Mon Sep 17 00:00:00 2001 From: Ryan Long Date: Mon, 23 Aug 2021 12:43:23 -0400 Subject: pxcdevctl: Adjust for standard psxdevctl is supposed to return the value in errno. Before, it was returning -1 and setting errno. Changed the tests to reflect these changes. Added code from RRADE's posix_devctl.c. Closes #4506 --- cpukit/libcsupport/src/posix_devctl.c | 80 ++++++++++++++++++++++++++++++---- testsuites/psxtests/psxdevctl01/test.c | 69 +++++++++++++++++++---------- 2 files changed, 118 insertions(+), 31 deletions(-) diff --git a/cpukit/libcsupport/src/posix_devctl.c b/cpukit/libcsupport/src/posix_devctl.c index 3ff9dd929f..fd190744e9 100644 --- a/cpukit/libcsupport/src/posix_devctl.c +++ b/cpukit/libcsupport/src/posix_devctl.c @@ -35,6 +35,7 @@ #include #include +#include int posix_devctl( int fd, @@ -44,6 +45,15 @@ int posix_devctl( int *__restrict dev_info_ptr ) { + int rv = 0; + + /* + * posix_devctl() is supposed to return an errno. errno needs to be + * preserved in spite of calling methods (e.g., close, fcntl, and ioctl) + * that set it. + */ + int errno_copy = errno; + /* * The POSIX 1003.26 standard allows for library implementations * that implement posix_devctl() using ioctl(). In this case, @@ -72,15 +82,69 @@ int posix_devctl( } /* - * The FACE Technical Standard Edition 3.0 and newer requires the SOCKCLOSE - * ioctl command. This is because the Security Profile does not include - * close() and applications need a way to close sockets. Closing sockets is - * a minimum requirement so using close() in the implementation meets that - * requirement but also lets the application close other file types. + * */ - if (dcmd == SOCKCLOSE ) { - return close(fd); + switch (dcmd) { + + /* + * The FACE Technical Standard Edition 3.0 and newer requires the SOCKCLOSE + * ioctl command. This is because the Security Profile does not include + * close() and applications need a way to close sockets. Closing sockets is + * a minimum requirement so using close() in the implementation meets that + * requirement but also lets the application close other file types. + */ + case SOCKCLOSE: + if (close(fd) != 0) { + rv = errno; + errno = errno_copy; + + return rv; + } + break; + + /* + * The FACE Technical Standard Edition 3.0 and newer requires the + * posix_devctl command to support the FIONBIO subcommand. + */ + case FIONBIO: { + int tmp_flag; + int flag; + + if (nbyte != sizeof(int)) { + return EINVAL; + } + + tmp_flag = fcntl(fd, F_GETFL, 0); + if (tmp_flag == -1) { + rv = errno; + errno = errno_copy; + + return rv; + } + + flag = *(int *)dev_data_ptr; + + if (flag != 0) { + tmp_flag |= O_NONBLOCK; + } else { + tmp_flag &= ~O_NONBLOCK; + } + + (void) fcntl(fd, F_SETFL, tmp_flag); + break; + } + + default: + if (ioctl(fd, dcmd, dev_data_ptr) != 0) { + rv = errno; + errno = errno_copy; + + return rv; + } + break; } - return ioctl(fd, dcmd, dev_data_ptr); + errno = errno_copy; + + return rv; } diff --git a/testsuites/psxtests/psxdevctl01/test.c b/testsuites/psxtests/psxdevctl01/test.c index b45725cb58..2fe7df1834 100644 --- a/testsuites/psxtests/psxdevctl01/test.c +++ b/testsuites/psxtests/psxdevctl01/test.c @@ -53,37 +53,16 @@ int main( int dev_data; void *dev_data_ptr; size_t nbyte; - int dev_info; TEST_BEGIN(); - puts( "posix_devctl() FIONBIO on stdin return dev_info -- EBADF" ); - fd = 0; - dcmd = FIONBIO; - dev_data_ptr = &dev_data; - nbyte = sizeof(dev_data); - status = posix_devctl( fd, dcmd, dev_data_ptr, nbyte, &dev_info ); - rtems_test_assert( status == -1 ); - rtems_test_assert( errno == EBADF ); - rtems_test_assert( dev_info == 0 ); - - puts( "posix_devctl() FIONBIO on stdin NULL dev_info -- EBADF" ); - fd = 0; - dcmd = FIONBIO; - dev_data_ptr = NULL; - nbyte = 0; - status = posix_devctl( fd, dcmd, dev_data_ptr, nbyte, NULL ); - rtems_test_assert( status == -1 ); - rtems_test_assert( errno == EBADF ); - puts( "posix_devctl() SOCKCLOSE on invalid file descriptor -- EBADF" ); - fd = 21; + fd = -1; dcmd = SOCKCLOSE; dev_data_ptr = NULL; nbyte = 0; status = posix_devctl( fd, dcmd, dev_data_ptr, nbyte, NULL ); - rtems_test_assert( status == -1 ); - rtems_test_assert( errno == EBADF ); + rtems_test_assert( status == EBADF ); /* * Create a file, open it, and close it via posix_devctl(). @@ -102,6 +81,50 @@ int main( status = close( fd ); rtems_test_assert( status == -1 ); rtems_test_assert( errno == EBADF ); + + puts( "posix_devctl() FIONBIO with invalid nbyte -- EINVAL" ); + fd = 0; + dcmd = FIONBIO; + dev_data_ptr = NULL; + nbyte = 0; + status = posix_devctl( fd, dcmd, dev_data_ptr, nbyte, NULL ); + rtems_test_assert( status == EINVAL ); + + puts( "posix_devctl() FIONBIO with invalid file descriptor -- EBADF" ); + fd = -1; + dcmd = FIONBIO; + dev_data_ptr = NULL; + nbyte = sizeof(int); + status = posix_devctl( fd, dcmd, dev_data_ptr, nbyte, NULL ); + rtems_test_assert( status == EBADF ); + + puts( "posix_devctl() FIONBIO flag not zero -- 0" ); + fd = 0; + dcmd = FIONBIO; + dev_data = 1; + dev_data_ptr = &dev_data; + nbyte = sizeof(int); + status = posix_devctl( fd, dcmd, dev_data_ptr, nbyte, NULL ); + rtems_test_assert( status == 0 ); + + puts( "posix_devctl() FIONBIO flag is zero -- 0" ); + fd = 0; + dcmd = FIONBIO; + dev_data = 0; + dev_data_ptr = &dev_data; + nbyte = sizeof(int); + status = posix_devctl( fd, dcmd, dev_data_ptr, nbyte, NULL ); + rtems_test_assert( status == 0 ); + + puts( "posix_devctl() dcmd not valid value -- EBADF" ); + fd = 0; + dcmd = 1; + dev_data = 0; + dev_data_ptr = &dev_data; + nbyte = sizeof(int); + status = posix_devctl( fd, dcmd, dev_data_ptr, nbyte, NULL ); + rtems_test_assert( status == EBADF ); + TEST_END(); exit(0); } -- cgit v1.2.3