/* SPDX-License-Identifier: BSD-2-Clause */ /** * @file * * This test exercises the following routines: * * + readv * + writev */ /* * COPYRIGHT (c) 1989-2012. * On-Line Applications Research Corporation (OAR). * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #if defined(__rtems__) #include #include #include const char rtems_test_name[] = "PSXRDWRV"; #else #define TRUE 1 #define FALSE 0 #include #define rtems_test_exit(_s) exit(_s) #endif /* forward declarations to avoid warnings */ int test_main(void); int fillPatternBuffer(void); int doFunctionalTest(void); int doErrorTest(void); #define TESTFILE "testfile1.tst" /* This buffer size is assumed in the iovec initialization below */ #define MAX_BUFFER 1000 unsigned char PatternBuffer[MAX_BUFFER]; unsigned char ReadBuffer[MAX_BUFFER]; /* * fillPatternBuffer function * * Fill the test buffer. * * Returns: TRUE if buffer filled * FALSE if buffer failed to fill * */ int fillPatternBuffer(void) { int retval = TRUE; int i; for (i=0 ; i<200 ; i++ ) PatternBuffer[i] = 'a'; for ( ; i<400 ; i++ ) PatternBuffer[i] = 'b'; for ( ; i<600 ; i++ ) PatternBuffer[i] = 'c'; for ( ; i<800 ; i++ ) PatternBuffer[i] = 'd'; for ( ; i<1000 ; i++ ) PatternBuffer[i] = 'e'; return retval; } /* * doFunctionalTest function * * Write a file with writev and then read it back with readv. * * Returns: TRUE if all operations worked as expected * FALSE if an operation did not work as expected. * */ int doFunctionalTest(void) { FILE *fp; int fd; struct iovec rdvec[4]; struct iovec wrvec[4]; int rc; /* * Setup the iovec */ wrvec[0].iov_base = &PatternBuffer[0]; wrvec[0].iov_len = 100; wrvec[1].iov_base = &PatternBuffer[100]; wrvec[1].iov_len = 200; wrvec[2].iov_base = &PatternBuffer[300]; wrvec[2].iov_len = 300; wrvec[3].iov_base = &PatternBuffer[600]; wrvec[3].iov_len = 400; rdvec[0].iov_base = &ReadBuffer[0]; rdvec[0].iov_len = 400; rdvec[1].iov_base = &ReadBuffer[400]; rdvec[1].iov_len = 300; rdvec[2].iov_base = &ReadBuffer[700]; rdvec[2].iov_len = 200; rdvec[3].iov_base = &ReadBuffer[900]; rdvec[3].iov_len = 100; /* * Write the File */ fp = fopen(TESTFILE, "wt"); if ( fp == NULL ) { printf( "fopen for write: %d=%s\n", errno, strerror(errno)); return FALSE; } fd = fileno(fp); rc = writev(fd, wrvec, 4); if ( rc <= 0 ) { printf( "writev: %d=%s\n", errno, strerror(errno) ); return FALSE; } fclose(fp); puts("File written using writev .. OK"); /* * Now read it back and check it */ fp = fopen(TESTFILE, "rt"); if ( fp == NULL ) { printf( "fopen for write: %d=%s\n", errno, strerror(errno)); return FALSE; } fd = fileno(fp); rc = readv(fd, rdvec, 4); if ( rc <= 0 ) { printf( "rd: %d=%s\n", errno, strerror(errno) ); return FALSE; } if ( memcmp( PatternBuffer, ReadBuffer, MAX_BUFFER ) ) { puts("readv .. Buffers do not match"); return FALSE; } puts("File read using readv .. OK"); return TRUE; } /* * doErrorTest function * * Hit all the error cases in readv/writev. * * Returns: TRUE if all operations worked as expected * FALSE if an operation did not work as expected. * */ int doErrorTest(void) { FILE *fp; int fd; struct iovec vec[4]; int rc; /* * Open and close the file to get a bad file descriptor */ fp = fopen(TESTFILE, "wt"); if ( fp == NULL ) { printf( "fopen for error 1: %d=%s\n", errno, strerror(errno)); return FALSE; } fd = fileno(fp); fclose(fp); /* clear out the vector to ensure it is valid */ memset(vec, 0, sizeof(vec)); /* writev -- bad file descriptor */ puts("writev bad file descriptor -- EBADF"); rc = writev(fd, vec, 4); if ( (rc != -1) || (errno != EBADF) ) { printf( "writev error 1: %d=%s\n", errno, strerror(errno) ); return FALSE; } /* readv -- bad file descriptor */ puts("readv bad file descriptor -- EBADF"); rc = read(fd, vec, 4); if ( (rc != -1) || (errno != EBADF) ) { printf( "readv error 1: %d=%s\n", errno, strerror(errno) ); return FALSE; } /* * Open the file for the rest of the tests */ fp = fopen(TESTFILE, "w+"); if ( fp == NULL ) { printf( "fopen for error 2: %d=%s\n", errno, strerror(errno)); return FALSE; } fd = fileno(fp); #ifdef __rtems__ /* writev -- bad iovec pointer */ puts("writev bad iovec pointer -- EINVAL"); rc = writev(fd, NULL, 4); if ( (rc != -1) || (errno != EINVAL) ) { printf( "writev error 2: %d=%s\n", errno, strerror(errno) ); fclose(fp); return FALSE; } /* readv -- bad iovec pointer */ puts("readv bad iovec pointer -- EINVAL"); rc = readv(fd, NULL, 4); if ( (rc != -1) || (errno != EINVAL) ) { printf( "readv error 2: %d=%s\n", errno, strerror(errno) ); fclose(fp); return FALSE; } /* writev -- bad iovcnt 0 */ puts("writev bad iovcnt of 0 -- EINVAL"); rc = writev(fd, vec, 0); if ( (rc != -1) || (errno != EINVAL) ) { printf( "writev error 3: %d=%s\n", errno, strerror(errno) ); fclose(fp); return FALSE; } /* readv -- bad iovcnt 0 */ puts("readv bad iovcnt of 0 -- EINVAL"); rc = readv(fd, vec, 0); if ( (rc != -1) || (errno != EINVAL) ) { printf( "readv error 3: %d=%s\n", errno, strerror(errno) ); fclose(fp); return FALSE; } #endif /* __rtems__ */ /* writev -- bad iovcnt negative */ puts("writev bad iovcnt negative -- EINVAL"); rc = writev(fd, vec, -2); if ( (rc != -1) || (errno != EINVAL) ) { printf( "writev error 4: %d=%s\n", errno, strerror(errno) ); fclose(fp); return FALSE; } /* readv -- bad iovcnt negative */ puts("readv bad iovcnt negative -- EINVAL"); rc = readv(fd, vec, -100); if ( (rc != -1) || (errno != EINVAL) ) { printf( "readv error 4: %d=%s\n", errno, strerror(errno) ); fclose(fp); return FALSE; } #ifdef __rtems__ /* writev -- bad iov[i].iov_base */ vec[0].iov_base = vec; vec[0].iov_len = 100; vec[1].iov_base = NULL; vec[1].iov_len = 100; puts("writev bad iov[i].iov_base -- EINVAL"); rc = writev(fd, vec, 2); if ( (rc != -1) || (errno != EINVAL) ) { printf( "writev error 5: %d=%s\n", errno, strerror(errno) ); fclose(fp); return FALSE; } /* readv -- bad iov[i].iov_base */ vec[0].iov_base = vec; vec[0].iov_len = 100; vec[1].iov_base = NULL; vec[1].iov_len = 100; puts("readv bad iov[i].iov_base -- EINVAL"); rc = readv(fd, vec, 2); if ( (rc != -1) || (errno != EINVAL) ) { printf( "readv error 5: %d=%s\n", errno, strerror(errno) ); fclose(fp); return FALSE; } #endif /* __rtems__ */ /* writev -- bad iov[i].iov_len < 0 */ vec[0].iov_base = vec; vec[0].iov_len = 100; vec[1].iov_base = vec; vec[1].iov_len = -10; puts("writev bad iov[i].iov_len < 0 -- EINVAL"); rc = writev(fd, vec, 2); if ( (rc != -1) || (errno != EINVAL) ) { printf( "writev error 6: %d=%s\n", errno, strerror(errno) ); fclose(fp); return FALSE; } /* readv -- bad iov[i].iov_len < 0 */ vec[0].iov_base = vec; vec[0].iov_len = 100; vec[1].iov_base = vec; vec[1].iov_len = -1024; puts("readv bad iov[i].iov_len < 0 -- EINVAL"); rc = readv(fd, vec, 2); if ( (rc != -1) || (errno != EINVAL) ) { printf( "readv error 6: %d=%s\n", errno, strerror(errno) ); fclose(fp); return FALSE; } /* writev -- iov_len total overflows */ vec[0].iov_base = vec; vec[0].iov_len = SIZE_MAX; vec[1].iov_base = vec; vec[1].iov_len = SIZE_MAX; vec[2].iov_base = vec; vec[2].iov_len = SIZE_MAX; puts("writev iov_len total overflows -- EINVAL"); rc = writev(fd, vec, 3); if ( (rc != -1) || (errno != EINVAL) ) { printf( "writev error 7: rc=%d %d=%s\n", rc, errno, strerror(errno) ); fclose(fp); return FALSE; } /* readv -- iov_len total overflows */ vec[0].iov_base = vec; vec[0].iov_len = SIZE_MAX; vec[1].iov_base = vec; vec[1].iov_len = SIZE_MAX; vec[2].iov_base = vec; vec[2].iov_len = SIZE_MAX; puts("readv iov_len total overflows -- EINVAL"); rc = readv(fd, vec, 3); if ( (rc != -1) || (errno != EINVAL) ) { printf( "read error 7: rc=%d %d=%s\n", rc, errno, strerror(errno) ); fclose(fp); return FALSE; } /* writev -- all zero length buffers */ vec[0].iov_base = vec; vec[0].iov_len = 0; vec[1].iov_base = NULL; vec[1].iov_len = 0; puts("writev iov_len works with no effect -- OK"); rc = writev(fd, vec, 2); if ( (rc != 0) ) { printf( "writev error 8: %d=%s\n", errno, strerror(errno) ); fclose(fp); return FALSE; } /* readv -- all zero length buffers */ vec[0].iov_base = vec; vec[0].iov_len = 0; vec[1].iov_base = NULL; vec[1].iov_len = 0; puts("readv iov_len works with no effect -- OK"); rc = readv(fd, vec, 2); if ( (rc != 0) ) { printf( "readv error 8: %d=%s\n", errno, strerror(errno) ); fclose(fp); return FALSE; } #ifdef __rtems__ puts("readv bad iovcnt of IOV_MAX + 1 -- EINVAL"); rc = readv(fd, vec, IOV_MAX + 1); if ( (rc != -1) || (errno != EINVAL) ) { printf( "readv error 9: %d=%s\n", errno, strerror(errno) ); fclose(fp); return FALSE; } puts("writev bad iovcnt of IOV_MAX + 1 -- EINVAL"); rc = writev(fd, vec, IOV_MAX + 1); if ( (rc != -1) || (errno != EINVAL) ) { printf( "writev error 9: %d=%s\n", errno, strerror(errno) ); fclose(fp); return FALSE; } #endif /* __rtems__ */ fclose(fp); return TRUE; } /* --------------------------------------------------------------- * Main function * * main entry point to the test * * --------------------------------------------------------------- */ #if defined(__rtems__) int test_main(void) #else int main( int argc, char **argv ) #endif { TEST_BEGIN(); if ( fillPatternBuffer() != TRUE ) { puts("Error filling pattern buffer" ); rtems_test_exit(0); } if (doErrorTest() != TRUE) { puts("Error during error test!!!!"); rtems_test_exit(0); } if (doFunctionalTest() != TRUE) { puts("Error during functional test!!!!"); rtems_test_exit(0); } unlink(TESTFILE); TEST_END(); rtems_test_exit(0); }