Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:40

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  *  @file
0005  *
0006  *  This test exercises the following routines:
0007  *
0008  *    + readv
0009  *    + writev
0010  */
0011 
0012 /*
0013  *  COPYRIGHT (c) 1989-2012.
0014  *  On-Line Applications Research Corporation (OAR).
0015  *
0016  * Redistribution and use in source and binary forms, with or without
0017  * modification, are permitted provided that the following conditions
0018  * are met:
0019  * 1. Redistributions of source code must retain the above copyright
0020  *    notice, this list of conditions and the following disclaimer.
0021  * 2. Redistributions in binary form must reproduce the above copyright
0022  *    notice, this list of conditions and the following disclaimer in the
0023  *    documentation and/or other materials provided with the distribution.
0024  *
0025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0026  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0027  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0028  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0029  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0030  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0031  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0032  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0033  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0034  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0035  * POSSIBILITY OF SUCH DAMAGE.
0036  */
0037 
0038 
0039 #ifdef HAVE_CONFIG_H
0040 #include "config.h"
0041 #endif
0042 
0043 #include <fcntl.h>
0044 #include <unistd.h>
0045 #include <errno.h>
0046 #include <utime.h>
0047 #include <string.h>
0048 #include <inttypes.h>
0049 #include <limits.h>
0050 
0051 #include <stdio.h>
0052 #include <unistd.h>
0053 #include <sys/uio.h>
0054 
0055 #if defined(__rtems__)
0056   #include <rtems.h>
0057   #include <rtems/libio.h>
0058   #include <pmacros.h>
0059 
0060   const char rtems_test_name[] = "PSXRDWRV";
0061 #else
0062   #define TRUE  1
0063   #define FALSE 0
0064   #include <stdlib.h>
0065   #define rtems_test_exit(_s) exit(_s)
0066 #endif
0067 
0068 /* forward declarations to avoid warnings */
0069 int test_main(void);
0070 int fillPatternBuffer(void);
0071 int doFunctionalTest(void);
0072 int doErrorTest(void);
0073 
0074 #define TESTFILE "testfile1.tst"
0075 
0076 /* This buffer size is assumed in the iovec initialization below */
0077 #define MAX_BUFFER 1000
0078 unsigned char PatternBuffer[MAX_BUFFER];
0079 unsigned char ReadBuffer[MAX_BUFFER];
0080 
0081 /*
0082  * fillPatternBuffer function
0083  *
0084  * Fill the test buffer.
0085  *
0086  * Returns: TRUE if buffer filled
0087  *          FALSE if buffer failed to fill
0088  *
0089  */
0090 int fillPatternBuffer(void)
0091 {
0092   int retval = TRUE;
0093   int i;
0094 
0095   for (i=0 ; i<200  ; i++ ) PatternBuffer[i] = 'a';
0096   for (    ; i<400  ; i++ ) PatternBuffer[i] = 'b';
0097   for (    ; i<600  ; i++ ) PatternBuffer[i] = 'c';
0098   for (    ; i<800  ; i++ ) PatternBuffer[i] = 'd';
0099   for (    ; i<1000 ; i++ ) PatternBuffer[i] = 'e';
0100   return retval;
0101 }
0102 
0103 /*
0104  * doFunctionalTest function
0105  *
0106  * Write a file with writev and then read it back with readv.
0107  *
0108  * Returns: TRUE if all operations worked as expected
0109  *          FALSE if an operation did not work as expected.
0110  *
0111  */
0112 int doFunctionalTest(void)
0113 {
0114   FILE         *fp;
0115   int           fd;
0116   struct iovec  rdvec[4];
0117   struct iovec  wrvec[4];
0118   int           rc;
0119 
0120 
0121   /*
0122    * Setup the iovec
0123    */
0124   wrvec[0].iov_base = &PatternBuffer[0];
0125   wrvec[0].iov_len  = 100;
0126   wrvec[1].iov_base = &PatternBuffer[100];
0127   wrvec[1].iov_len  = 200;
0128   wrvec[2].iov_base = &PatternBuffer[300];
0129   wrvec[2].iov_len  = 300;
0130   wrvec[3].iov_base = &PatternBuffer[600];
0131   wrvec[3].iov_len  = 400;
0132 
0133   rdvec[0].iov_base = &ReadBuffer[0];
0134   rdvec[0].iov_len  = 400;
0135   rdvec[1].iov_base = &ReadBuffer[400];
0136   rdvec[1].iov_len  = 300;
0137   rdvec[2].iov_base = &ReadBuffer[700];
0138   rdvec[2].iov_len  = 200;
0139   rdvec[3].iov_base = &ReadBuffer[900];
0140   rdvec[3].iov_len  = 100;
0141 
0142   /*
0143    * Write the File
0144    */
0145   fp = fopen(TESTFILE, "wt");
0146   if ( fp == NULL ) {
0147     printf( "fopen for write: %d=%s\n", errno, strerror(errno));
0148     return FALSE;
0149   }
0150   fd = fileno(fp);
0151 
0152   rc = writev(fd, wrvec, 4);
0153   if ( rc <= 0 ) {
0154     printf( "writev: %d=%s\n", errno, strerror(errno) );
0155     return FALSE;
0156   }
0157 
0158   fclose(fp);
0159 
0160   puts("File written using writev .. OK");
0161 
0162   /*
0163    * Now read it back and check it
0164    */
0165 
0166   fp = fopen(TESTFILE, "rt");
0167   if ( fp == NULL ) {
0168     printf( "fopen for write: %d=%s\n", errno, strerror(errno));
0169     return FALSE;
0170   }
0171   fd = fileno(fp);
0172 
0173   rc = readv(fd, rdvec, 4);
0174   if ( rc <= 0 ) {
0175     printf( "rd: %d=%s\n", errno, strerror(errno) );
0176     return FALSE;
0177   }
0178 
0179   if ( memcmp( PatternBuffer, ReadBuffer, MAX_BUFFER ) ) {
0180     puts("readv .. Buffers do not match");
0181     return FALSE;
0182   }
0183 
0184   puts("File read using readv .. OK");
0185 
0186   return TRUE;
0187 }
0188 
0189 /*
0190  * doErrorTest function
0191  *
0192  * Hit all the error cases in readv/writev.
0193  *
0194  * Returns: TRUE if all operations worked as expected
0195  *          FALSE if an operation did not work as expected.
0196  *
0197  */
0198 int doErrorTest(void)
0199 {
0200   FILE         *fp;
0201   int           fd;
0202   struct iovec  vec[4];
0203   int           rc;
0204 
0205   /*
0206    * Open and close the file to get a bad file descriptor
0207    */
0208   fp = fopen(TESTFILE, "wt");
0209   if ( fp == NULL ) {
0210     printf( "fopen for error 1: %d=%s\n", errno, strerror(errno));
0211     return FALSE;
0212   }
0213   fd = fileno(fp);
0214   fclose(fp);
0215 
0216   /* clear out the vector to ensure it is valid */
0217   memset(vec, 0, sizeof(vec));
0218 
0219   /* writev -- bad file descriptor */
0220   puts("writev bad file descriptor -- EBADF");
0221   rc = writev(fd, vec, 4);
0222   if ( (rc != -1) || (errno != EBADF) ) {
0223     printf( "writev error 1: %d=%s\n", errno, strerror(errno) );
0224     return FALSE;
0225   }
0226 
0227   /* readv -- bad file descriptor */
0228   puts("readv bad file descriptor -- EBADF");
0229   rc = read(fd, vec, 4);
0230   if ( (rc != -1) || (errno != EBADF) ) {
0231     printf( "readv error 1: %d=%s\n", errno, strerror(errno) );
0232     return FALSE;
0233   }
0234 
0235   /*
0236    * Open the file for the rest of the tests
0237    */
0238   fp = fopen(TESTFILE, "w+");
0239   if ( fp == NULL ) {
0240     printf( "fopen for error 2: %d=%s\n", errno, strerror(errno));
0241     return FALSE;
0242   }
0243   fd = fileno(fp);
0244 
0245 #ifdef __rtems__
0246   /* writev --  bad iovec pointer */
0247   puts("writev bad iovec pointer -- EINVAL");
0248   rc = writev(fd, NULL, 4);
0249   if ( (rc != -1) || (errno != EINVAL) ) {
0250     printf( "writev error 2: %d=%s\n", errno, strerror(errno) );
0251     fclose(fp);
0252     return FALSE;
0253   }
0254 
0255   /* readv --  bad iovec pointer */
0256   puts("readv bad iovec pointer -- EINVAL");
0257   rc = readv(fd, NULL, 4);
0258   if ( (rc != -1) || (errno != EINVAL) ) {
0259     printf( "readv error 2: %d=%s\n", errno, strerror(errno) );
0260     fclose(fp);
0261     return FALSE;
0262   }
0263 
0264   /* writev --  bad iovcnt 0 */
0265   puts("writev bad iovcnt of 0 -- EINVAL");
0266   rc = writev(fd, vec, 0);
0267   if ( (rc != -1) || (errno != EINVAL) ) {
0268     printf( "writev error 3: %d=%s\n", errno, strerror(errno) );
0269     fclose(fp);
0270     return FALSE;
0271   }
0272 
0273   /* readv --  bad iovcnt 0 */
0274   puts("readv bad iovcnt of 0 -- EINVAL");
0275   rc = readv(fd, vec, 0);
0276   if ( (rc != -1) || (errno != EINVAL) ) {
0277     printf( "readv error 3: %d=%s\n", errno, strerror(errno) );
0278     fclose(fp);
0279     return FALSE;
0280   }
0281 #endif /* __rtems__ */
0282 
0283   /* writev --  bad iovcnt negative */
0284   puts("writev bad iovcnt negative -- EINVAL");
0285   rc = writev(fd, vec, -2);
0286   if ( (rc != -1) || (errno != EINVAL) ) {
0287     printf( "writev error 4: %d=%s\n", errno, strerror(errno) );
0288     fclose(fp);
0289     return FALSE;
0290   }
0291 
0292   /* readv --  bad iovcnt negative */
0293   puts("readv bad iovcnt negative -- EINVAL");
0294   rc = readv(fd, vec, -100);
0295   if ( (rc != -1) || (errno != EINVAL) ) {
0296     printf( "readv error 4: %d=%s\n", errno, strerror(errno) );
0297     fclose(fp);
0298     return FALSE;
0299   }
0300 
0301 #ifdef __rtems__
0302   /* writev --  bad iov[i].iov_base */
0303   vec[0].iov_base = vec;
0304   vec[0].iov_len = 100;
0305   vec[1].iov_base = NULL;
0306   vec[1].iov_len = 100;
0307   puts("writev bad iov[i].iov_base -- EINVAL");
0308   rc = writev(fd, vec, 2);
0309   if ( (rc != -1) || (errno != EINVAL) ) {
0310     printf( "writev error 5: %d=%s\n", errno, strerror(errno) );
0311     fclose(fp);
0312     return FALSE;
0313   }
0314 
0315   /*  readv --  bad iov[i].iov_base */
0316   vec[0].iov_base = vec;
0317   vec[0].iov_len = 100;
0318   vec[1].iov_base = NULL;
0319   vec[1].iov_len = 100;
0320   puts("readv bad iov[i].iov_base -- EINVAL");
0321   rc = readv(fd, vec, 2);
0322   if ( (rc != -1) || (errno != EINVAL) ) {
0323     printf( "readv error 5: %d=%s\n", errno, strerror(errno) );
0324     fclose(fp);
0325     return FALSE;
0326   }
0327 #endif /* __rtems__ */
0328 
0329   /*  writev --  bad iov[i].iov_len < 0 */
0330   vec[0].iov_base = vec;
0331   vec[0].iov_len = 100;
0332   vec[1].iov_base = vec;
0333   vec[1].iov_len = -10;
0334   puts("writev bad iov[i].iov_len < 0 -- EINVAL");
0335   rc = writev(fd, vec, 2);
0336   if ( (rc != -1) || (errno != EINVAL) ) {
0337     printf( "writev error 6: %d=%s\n", errno, strerror(errno) );
0338     fclose(fp);
0339     return FALSE;
0340   }
0341 
0342   /*  readv --  bad iov[i].iov_len < 0 */
0343   vec[0].iov_base = vec;
0344   vec[0].iov_len = 100;
0345   vec[1].iov_base = vec;
0346   vec[1].iov_len = -1024;
0347   puts("readv bad iov[i].iov_len < 0 -- EINVAL");
0348   rc = readv(fd, vec, 2);
0349   if ( (rc != -1) || (errno != EINVAL) ) {
0350     printf( "readv error 6: %d=%s\n", errno, strerror(errno) );
0351     fclose(fp);
0352     return FALSE;
0353   }
0354 
0355   /*  writev --  iov_len total overflows */
0356   vec[0].iov_base = vec;
0357   vec[0].iov_len = SIZE_MAX;
0358   vec[1].iov_base = vec;
0359   vec[1].iov_len = SIZE_MAX;
0360   vec[2].iov_base = vec;
0361   vec[2].iov_len = SIZE_MAX;
0362   puts("writev iov_len total overflows -- EINVAL");
0363   rc = writev(fd, vec, 3);
0364   if ( (rc != -1) || (errno != EINVAL) ) {
0365     printf( "writev error 7: rc=%d %d=%s\n", rc, errno, strerror(errno) );
0366     fclose(fp);
0367     return FALSE;
0368   }
0369 
0370   /*  readv --  iov_len total overflows */
0371   vec[0].iov_base = vec;
0372   vec[0].iov_len = SIZE_MAX;
0373   vec[1].iov_base = vec;
0374   vec[1].iov_len = SIZE_MAX;
0375   vec[2].iov_base = vec;
0376   vec[2].iov_len = SIZE_MAX;
0377   puts("readv iov_len total overflows -- EINVAL");
0378   rc = readv(fd, vec, 3);
0379   if ( (rc != -1) || (errno != EINVAL) ) {
0380     printf( "read error 7: rc=%d %d=%s\n", rc, errno, strerror(errno) );
0381     fclose(fp);
0382     return FALSE;
0383   }
0384 
0385   /*  writev --  all zero length buffers */
0386   vec[0].iov_base = vec;
0387   vec[0].iov_len = 0;
0388   vec[1].iov_base = NULL;
0389   vec[1].iov_len = 0;
0390   puts("writev iov_len works with no effect -- OK");
0391   rc = writev(fd, vec, 2);
0392   if ( (rc != 0) ) {
0393     printf( "writev error 8: %d=%s\n", errno, strerror(errno) );
0394     fclose(fp);
0395     return FALSE;
0396   }
0397 
0398   /*  readv --  all zero length buffers */
0399   vec[0].iov_base = vec;
0400   vec[0].iov_len = 0;
0401   vec[1].iov_base = NULL;
0402   vec[1].iov_len = 0;
0403   puts("readv iov_len works with no effect -- OK");
0404   rc = readv(fd, vec, 2);
0405   if ( (rc != 0) ) {
0406     printf( "readv error 8: %d=%s\n", errno, strerror(errno) );
0407     fclose(fp);
0408     return FALSE;
0409   }
0410 
0411 #ifdef __rtems__
0412   puts("readv bad iovcnt of IOV_MAX + 1 -- EINVAL");
0413   rc = readv(fd, vec, IOV_MAX + 1);
0414   if ( (rc != -1) || (errno != EINVAL) ) {
0415     printf( "readv error 9: %d=%s\n", errno, strerror(errno) );
0416     fclose(fp);
0417     return FALSE;
0418   }
0419 
0420   puts("writev bad iovcnt of IOV_MAX + 1 -- EINVAL");
0421   rc = writev(fd, vec, IOV_MAX + 1);
0422   if ( (rc != -1) || (errno != EINVAL) ) {
0423     printf( "writev error 9: %d=%s\n", errno, strerror(errno) );
0424     fclose(fp);
0425     return FALSE;
0426   }
0427 #endif /* __rtems__ */
0428 
0429   fclose(fp);
0430   return TRUE;
0431 }
0432 
0433 
0434 /* ---------------------------------------------------------------
0435  * Main function
0436  *
0437  *  main entry point to the test
0438  *
0439  * ---------------------------------------------------------------
0440  */
0441 
0442 #if defined(__rtems__)
0443 int test_main(void)
0444 #else
0445 int main(
0446   int    argc,
0447   char **argv
0448 )
0449 #endif
0450 {
0451   TEST_BEGIN();
0452 
0453   if ( fillPatternBuffer() != TRUE ) {
0454     puts("Error filling pattern buffer" );
0455     rtems_test_exit(0);
0456   }
0457 
0458   if (doErrorTest() != TRUE) {
0459     puts("Error during error test!!!!");
0460     rtems_test_exit(0);
0461   }
0462   if (doFunctionalTest() != TRUE) {
0463     puts("Error during functional test!!!!");
0464     rtems_test_exit(0);
0465   }
0466 
0467   unlink(TESTFILE);
0468   TEST_END();
0469   rtems_test_exit(0);
0470 }