delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2003/03/11/14:02:14

Date: Tue, 11 Mar 2003 19:04:59 +0000
From: "Richard Dawe" <rich AT phekda DOT freeserve DOT co DOT uk>
Sender: rich AT phekda DOT freeserve DOT co DOT uk
To: djgpp-workers AT delorie DOT com
X-Mailer: Emacs 21.3.50 (via feedmail 8.3.emacs20_6 I) and Blat ver 1.8.6
Subject: readv, writev, revision 2 [PATCH]
Message-Id: <E18sp0e-0000aG-00@phekda.freeserve.co.uk>
Reply-To: djgpp-workers AT delorie DOT com

Hello.

Below is revision of the implementation of readv, writev for DJGPP.
Unlike revision 1, this does not use a temporary buffer - it writes
out the data chunk-by-chunk.

OK to commit?

Bye, Rich =]

Index: src/docs/kb/wc204.txi
===================================================================
RCS file: /cvs/djgpp/djgpp/src/docs/kb/wc204.txi,v
retrieving revision 1.147
diff -p -c -3 -r1.147 wc204.txi
*** src/docs/kb/wc204.txi	8 Mar 2003 01:19:20 -0000	1.147
--- src/docs/kb/wc204.txi	11 Mar 2003 19:00:29 -0000
***************
*** 1,4 ****
- 
  @node Changes in 2.04, , Changes in 2.03, What Changed
  @section Changes in 2.04
  
--- 1,3 ----
*************** The function @code{fchmod} was added.
*** 911,913 ****
--- 910,916 ----
  @findex _tolower
  @findex _toupper
  The functions @code{_tolower} and @code{_toupper} were added.
+ 
+ @findex readv
+ @findex writev
+ The functions @code{readv} and @code{writev} were added.
*** /dev/null	Tue Mar 11 19:03:42 2003
--- include/sys/uio.h	Wed Jan 22 12:05:12 2003
***************
*** 0 ****
--- 1,49 ----
+ /* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */
+ #ifndef __dj_include_sys_uio_h__
+ #define __dj_include_sys_uio_h__
+ 
+ #ifdef __cplusplus
+ extern "C"
+ {
+ #endif
+ 
+ #ifndef __dj_ENFORCE_ANSI_FREESTANDING
+ 
+ #include <sys/djtypes.h>
+ 
+ #ifndef __STRICT_ANSI__
+ 
+ #ifndef _SIZE_T
+ __DJ_size_t
+ #define _SIZE_T
+ #endif
+ 
+ #ifndef _SSIZE_T
+ __DJ_ssize_t
+ #define _SSIZE_T
+ #endif
+ 
+ #define IOV_MAX	16
+ 	
+ struct iovec {
+   void   *iov_base; /* Base address of a memory region for I/O */
+   size_t  iov_len;  /* Size of memory region                   */
+ };
+ 
+ extern ssize_t readv (int _fd, const struct iovec *_iov, int _iovcnt);
+ extern ssize_t writev (int _fd, const struct iovec *_iov, int _iovcnt);
+ 
+ #ifndef _POSIX_SOURCE
+ 
+ #endif /* !_POSIX_SOURCE */
+ #endif /* !__STRICT_ANSI__ */
+ #endif /* !__dj_ENFORCE_ANSI_FREESTANDING */
+ 
+ #ifndef __dj_ENFORCE_FUNCTION_CALLS
+ #endif /* !__dj_ENFORCE_FUNCTION_CALLS */
+ 
+ #ifdef __cplusplus
+ }
+ #endif
+ 
+ #endif /* __dj_include_sys_uio_h__ */
*** /dev/null	Tue Mar 11 19:03:42 2003
--- src/libc/posix/sys/uio/makefile	Wed Jan 22 11:54:48 2003
***************
*** 0 ****
--- 1,7 ----
+ # Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details
+ TOP=../../..
+ 
+ SRC += readv.c
+ SRC += writev.c
+ 
+ include $(TOP)/../makefile.inc
*** /dev/null	Tue Mar 11 19:03:42 2003
--- src/libc/posix/sys/uio/readv.c	Tue Mar 11 17:01:30 2003
***************
*** 0 ****
--- 1,60 ----
+ /* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */
+ #include <libc/stubs.h>
+ #include <unistd.h>
+ #include <errno.h>
+ #include <limits.h>
+ #include <sys/uio.h>
+ 
+ ssize_t
+ readv (int fd, const struct iovec *iov, int iovcnt)
+ {
+   int     old_errno = errno;
+   size_t  maxbytes;
+   ssize_t nbytes = 0;
+   ssize_t ret;
+   int     i;
+ 
+   /* Check args */
+   if ((iovcnt <= 0) || (iovcnt > IOV_MAX)) {
+     errno = EINVAL;
+     return(-1);
+   }
+ 	
+   /* Calculate total number of bytes that can be read. */
+   for (maxbytes = 0, i = 0; i < iovcnt; i++) {
+     maxbytes += iov[i].iov_len;
+     if (maxbytes > SSIZE_MAX)
+       break;
+   }
+ 
+   /* If we read the maximum number of bytes, we may overflow the return
+    * value. Return an error if this is the case. */
+   if (maxbytes > SSIZE_MAX) {
+     errno = EINVAL;
+     return(-1);
+   }
+ 
+   /* Read in the data vector-by-vector. */
+   for (i = 0; i < iovcnt; i++) {
+     ret = read(fd, iov[i].iov_base, iov[i].iov_len);
+ 
+     if (ret < 0) {
+       if (!i) {
+ 	/* Fail of the first one. Fail and pass through errno. */
+ 	return(-1); 
+       } else {
+ 	/* Hide the error and return what we've got so far. */
+ 	errno = old_errno;
+ 	return(nbytes);
+       }
+     }
+ 
+     nbytes += ret;
+ 
+     /* If we didn't read in a whole vector, stop. */
+     if ((size_t) ret < iov[i].iov_len)
+       break;
+   }
+ 	
+   return(nbytes);
+ }
*** /dev/null	Tue Mar 11 19:03:42 2003
--- src/libc/posix/sys/uio/readv.txh	Tue Mar 11 19:03:04 2003
***************
*** 0 ****
--- 1,49 ----
+ @node readv, io
+ @findex readv
+ 
+ @subheading Syntax
+ 
+ @example
+ #include <sys/uio.h>
+ 
+ ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
+ @end example
+ 
+ @subheading Description
+ 
+ @code{readv} performs a scatter-gather read from the specified file
+ descriptor @var{fd}.  The data is written into a group of buffers described
+ by the array @var{iov} with @var{iovcnt} entries in a similar way to
+ @code{read} (@pxref{read, , read, libc}).
+ 
+ @code{struct iovec} is defined as follows:
+ 
+ @example
+ struct iovec @{
+   void   *iov_base; /* Base address of a memory region for I/O */
+   size_t  iov_len;  /* Size of memory region                   */
+ @};
+ @end example
+ 
+ @subheading Return Value
+ 
+ On successful completion the function returns the number of bytes read.
+ Otherwise, a value of -1 is returned and @var{errno} is set appropriately.
+ 
+ @table @samp
+ 
+ @item EINVAL
+ One of the following conditions is true:
+ 
+ @itemize @bullet
+ @item
+ The total length to read could overflow a @code{ssize_t}.
+ @item
+ @var{iovcnt} was negative, zero or larger than @code{IOV_MAX}.
+ @end itemize
+ 
+ @end table
+ 
+ @subheading Portability
+ 
+ @portability !ansi, !posix-1003.2-1992, posix-1003.1-2001
*** /dev/null	Tue Mar 11 19:03:42 2003
--- src/libc/posix/sys/uio/writev.c	Tue Mar 11 17:00:46 2003
***************
*** 0 ****
--- 1,60 ----
+ /* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */
+ #include <libc/stubs.h>
+ #include <unistd.h>
+ #include <errno.h>
+ #include <limits.h>
+ #include <sys/uio.h>
+ 
+ ssize_t
+ writev (int fd, const struct iovec *iov, int iovcnt)
+ {
+   int     old_errno = errno;
+   size_t  maxbytes;
+   ssize_t nbytes = 0;
+   ssize_t ret;
+   int     i;
+ 
+   /* Check args */
+   if ((iovcnt <= 0) || (iovcnt > IOV_MAX)) {
+     errno = EINVAL;
+     return(-1);
+   }
+ 	
+   /* Calculate the total number of bytes needed to write data. */
+   for (maxbytes = 0, i = 0; i < iovcnt; i++) {
+     maxbytes += iov[i].iov_len;
+     if (maxbytes > SSIZE_MAX)
+       break;
+   }
+ 
+   /* If we write the maximum number of bytes, we may overflow the return
+    * value. Return an error if this is the case. */
+   if (maxbytes > SSIZE_MAX) {
+     errno = EINVAL;
+     return(-1);
+   }
+ 	
+   /* Write out the data vector-by-vector. */
+   for (i = 0; i < iovcnt; i++) {
+     ret = write(fd, iov[i].iov_base, iov[i].iov_len);
+ 
+     if (ret < 0) {
+       if (!i) {
+ 	/* Fail of the first one. Fail and pass through errno. */
+ 	return(-1); 
+       } else {
+ 	/* Hide the error and return what we've written so far. */
+ 	errno = old_errno;
+ 	return(nbytes);
+       }
+     }
+ 
+     nbytes += ret;
+ 
+     /* If we didn't write out a whole vector, stop. */
+     if ((size_t) ret < iov[i].iov_len)
+       break;
+   }
+ 	
+   return(nbytes);
+ }
*** /dev/null	Tue Mar 11 19:03:42 2003
--- src/libc/posix/sys/uio/writev.txh	Tue Mar 11 19:03:10 2003
***************
*** 0 ****
--- 1,49 ----
+ @node writev, io
+ @findex writev
+ 
+ @subheading Syntax
+ 
+ @example
+ #include <sys/uio.h>
+ 
+ ssize_t writev(int fd, const struct iovec *iov, int iovcnt);
+ @end example
+ 
+ @subheading Description
+ 
+ @code{writev} performs a scatter-gather write to the specified file
+ descriptor @var{fd}.  A group of buffers described by the array @var{iov},
+ with @var{iovcnt} entries, is written to @var{fd} in a similar
+ way to @code{write} (@pxref{write, , write, libc}).
+ 
+ @code{struct iovec} is defined as follows:
+ 
+ @example
+ struct iovec @{
+   void   *iov_base; /* Base address of a memory region for I/O */
+   size_t  iov_len;  /* Size of memory region                   */
+ @};
+ @end example
+ 
+ @subheading Return Value
+ 
+ On successful completion the function returns the number of bytes written.
+ Otherwise, a value of -1 is returned and @var{errno} is set appropriately.
+ 
+ @table @samp
+ 
+ @item EINVAL
+ One of the following conditions is true:
+ 
+ @itemize @bullet
+ @item
+ The total length to write would overflow a @code{ssize_t}.
+ @item
+ @var{iovcnt} was negative, zero or larger than @code{IOV_MAX}.
+ @end itemize
+ 
+ @end table
+ 
+ @subheading Portability
+ 
+ @portability !ansi, !posix-1003.2-1992, posix-1003.1-2001
*** /dev/null	Tue Mar 11 19:03:42 2003
--- tests/libc/posix/sys/uio/makefile	Wed Jan 22 12:16:14 2003
***************
*** 0 ****
--- 1,6 ----
+ TOP=../../..
+ 
+ SRC += t-readv.c
+ SRC += t-writev.c
+ 
+ include $(TOP)/../makefile.inc
*** /dev/null	Tue Mar 11 19:03:43 2003
--- tests/libc/posix/sys/uio/t-readv.c	Wed Jan 22 12:41:40 2003
***************
*** 0 ****
--- 1,80 ----
+ #include <assert.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
+ #include <sys/uio.h>
+ #include <fcntl.h>
+ #include <sys/stat.h>
+ 
+ #define DATA_FILENAME "t-readv.dat"
+ 
+ void
+ fail (const char *argv0)
+ {
+   perror(argv0);
+   puts("FAIL");
+   exit(EXIT_FAILURE);
+ }
+ 
+ int
+ main (int argc, char *argv[])
+ {
+   char          data[] = "somedata";
+   char          bufs[5][4];
+   const size_t  n_bufs = 5;
+   struct iovec  iov[IOV_MAX];
+   char         *p = NULL;
+   char          allbuf[128];
+   int           fd;
+   int           ret;
+   int           i;
+ 
+   assert(n_bufs <= IOV_MAX);
+ 
+   /* Construct the iovec. */
+   iov[0].iov_base = (void *) bufs[0];
+   iov[0].iov_len  = 4;
+ 
+   for (i = 1; i < 5; i++) {
+     iov[i].iov_base = (void *) bufs[i];
+     iov[i].iov_len  = 1;
+   }
+ 
+   /* Create the data file. */
+   fd = open(DATA_FILENAME, O_RDWR|O_TEXT|O_TRUNC|O_CREAT, S_IRUSR|S_IWUSR);
+ 
+   if (fd < 0)
+     fail(argv[0]);
+ 
+   /* Don't write the nul to the file. */
+   ret = write(fd, data, strlen(data));
+ 
+   close(fd);
+ 
+   /* Read the data back in. */
+   fd = open(DATA_FILENAME, O_RDONLY|O_TEXT);
+ 
+   if (fd < 0)
+     fail(argv[0]);
+ 
+   ret = readv(fd, iov, n_bufs);
+   if (ret < 0)
+     fail(argv[0]);
+ 
+   close(fd);
+ 
+   /* Reconstruct the string in bufs. */
+   for (p = allbuf, i = 0; i < n_bufs; p += iov[i].iov_len, i++) {
+     memcpy(p, bufs[i], iov[i].iov_len);
+   }
+   *p = '\0';
+ 
+   if (strcmp(allbuf, data) != 0) {
+     printf("Expected '%s' - got '%s'\nFAIL\n", data, allbuf);
+     return(EXIT_FAILURE);
+   }
+ 
+   puts("PASS");
+   return(EXIT_SUCCESS);
+ }
*** /dev/null	Tue Mar 11 19:03:43 2003
--- tests/libc/posix/sys/uio/t-writev.c	Wed Jan 22 12:38:30 2003
***************
*** 0 ****
--- 1,76 ----
+ #include <assert.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
+ #include <sys/uio.h>
+ #include <fcntl.h>
+ #include <sys/stat.h>
+ #include <libc/unconst.h>
+ 
+ #define DATA_FILENAME "t-writev.dat"
+ 
+ void
+ fail (const char *argv0)
+ {
+   perror(argv0);
+   puts("FAIL");
+   exit(EXIT_FAILURE);
+ }
+ 
+ int
+ main (int argc, char *argv[])
+ {
+   const char   *data[] = { "some", "d", "a", "t", "a" };
+   /* NB: data[0] is a pointer. */
+   const size_t  n_data = sizeof(data) / sizeof(data[0]);
+   struct iovec  iov[IOV_MAX];
+   char          alldata[128];
+   int           fd;
+   int           ret;
+   char          buf[128];
+   int           i;
+ 
+   assert(n_data <= IOV_MAX);
+ 
+   /* Construct the iovec & collapse data into one string. */
+   alldata[0] = '\0';
+   for (i = 0; i < n_data; i++) {
+     iov[i].iov_base = (void *) unconst(data[i], char *);
+     iov[i].iov_len  = strlen(data[i]);
+ 
+     strcat(alldata, data[i]);
+   }
+ 
+   /* Write out the data. */
+   fd = open(DATA_FILENAME, O_RDWR|O_TEXT|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
+   if (fd < 0)
+     fail(argv[0]);
+ 
+   ret = writev(fd, iov, n_data);
+   if (ret < 0)
+     fail(argv[0]);
+ 
+   close(fd);
+ 
+   /* Read back the data and check it. */
+   fd = open(DATA_FILENAME, O_RDONLY|O_TEXT);
+   if (fd < 0)
+     fail(argv[0]);
+ 
+   ret = read(fd, buf, sizeof(buf) - 1 /* leave space for nul */);
+   if (ret < 0)
+     fail(argv[0]);
+ 
+   close(fd);
+ 
+   buf[ret] = '\0';
+ 
+   if (strcmp(buf, alldata) != 0) {
+     printf("Expected '%s' - got '%s'\nFAIL\n", alldata, buf);
+     return(EXIT_FAILURE);
+   }
+ 
+   puts("PASS");
+   return(EXIT_SUCCESS);
+ }
*** /dev/null	Tue Mar 11 19:03:43 2003
--- tests/libc/posix/sys/uio/.cvsignore	Wed Jan 22 12:15:30 2003
***************
*** 0 ****
--- 1 ----
+ *.d

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019