Back to index

glibc  2.9
writev.c
Go to the documentation of this file.
00001 /* Copyright (C) 1991, 1992, 1996, 1997, 2002 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Lesser General Public
00006    License as published by the Free Software Foundation; either
00007    version 2.1 of the License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Lesser General Public License for more details.
00013 
00014    You should have received a copy of the GNU Lesser General Public
00015    License along with the GNU C Library; if not, write to the Free
00016    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00017    02111-1307 USA.  */
00018 
00019 #include <stdlib.h>
00020 #include <unistd.h>
00021 #include <string.h>
00022 #include <limits.h>
00023 #include <stdbool.h>
00024 #include <sys/param.h>
00025 #include <sys/uio.h>
00026 #include <errno.h>
00027 
00028 /* Write data pointed by the buffers described by VECTOR, which
00029    is a vector of COUNT `struct iovec's, to file descriptor FD.
00030    The data is written in the order specified.
00031    Operates just like `write' (see <unistd.h>) except that the data
00032    are taken from VECTOR instead of a contiguous buffer.  */
00033 ssize_t
00034 __libc_writev (int fd, const struct iovec *vector, int count)
00035 {
00036   char *buffer;
00037   register char *bp;
00038   size_t bytes, to_copy;
00039   ssize_t bytes_written;
00040   int i;
00041   bool use_malloc = false;
00042 
00043   /* Find the total number of bytes to be written.  */
00044   bytes = 0;
00045   for (i = 0; i < count; ++i)
00046     {
00047       /* Check for ssize_t overflow.  */
00048       if (SSIZE_MAX - bytes < vector[i].iov_len)
00049        {
00050          __set_errno (EINVAL);
00051          return -1;
00052        }
00053       bytes += vector[i].iov_len;
00054     }
00055 
00056   /* Allocate a temporary buffer to hold the data.  We should normally
00057      use alloca since it's faster and does not require synchronization
00058      with other threads.  But we cannot if the amount of memory
00059      required is too large.  */
00060   if (__libc_use_alloca (bytes))
00061     buffer = (char *) __alloca (bytes);
00062   else
00063     {
00064       buffer = (char *) malloc (bytes);
00065       if (buffer == NULL)
00066        /* XXX I don't know whether it is acceptable to try writing
00067           the data in chunks.  Probably not so we just fail here.  */
00068        return -1;
00069 
00070       use_malloc = true;
00071     }
00072 
00073   /* Copy the data into BUFFER.  */
00074   to_copy = bytes;
00075   bp = buffer;
00076   for (i = 0; i < count; ++i)
00077     {
00078       size_t copy = MIN (vector[i].iov_len, to_copy);
00079 
00080       bp = __mempcpy ((void *) bp, (void *) vector[i].iov_base, copy);
00081 
00082       to_copy -= copy;
00083       if (to_copy == 0)
00084        break;
00085     }
00086 
00087   bytes_written = __write (fd, buffer, bytes);
00088 
00089   if (use_malloc)
00090     free (buffer);
00091 
00092   return bytes_written;
00093 }
00094 #ifndef __libc_writev
00095 strong_alias (__libc_writev, __writev)
00096 weak_alias (__libc_writev, writev)
00097 #endif