INN commit: trunk (19 files)

INN Commit rra at isc.org
Sat Sep 6 08:07:28 UTC 2014


    Date: Saturday, September 6, 2014 @ 01:07:27
  Author: iulius
Revision: 9680

Sync the xwrite library with upstream rra-c-util

- New inn/macros.h, inn/xwrite.h and portable/macros.h headers (extracted
from inn/defines.h and inn/libinn.h).

- New portable/uio.h header.

- Update include headers in several files to reflect these changes.

- clibrary.h now guarantees the inclusion of limits.h (to ensure the
availability of SIZE_TYPE on older systems).

- Switch to bmalloc where the other xmalloc infrastructure is not
required.  Don't bother converting tests that use xasprintf or
concat for the time being.

- Use calloc in preference to calculating a malloc size with
multiplication everywhere.  In most places this caution was probably
not necessary, but uniformity is easier to audit and no one will ever
notice the speed difference between malloc and calloc.

- Add bail or conditionals so that clang --analyze isn't worried about
NULL pointer dereferences in our tests.

- Also make xwritev more robust by doing range checking on iovcnt
early.  It's unlikely this would have caused a real problem anywhere,
but this is more obviously correct.

- The number of iovs remaining can't actually be zero unless the
system writev call is buggy, but the math is complex enough that
clang --analyze can't figure that out.  Add an assert to make the
assumption explicit.

Added:
  trunk/include/inn/macros.h
  trunk/include/inn/xwrite.h
  trunk/include/portable/macros.h
  trunk/include/portable/uio.h
Modified:
  trunk/MANIFEST
  trunk/configure.ac
  trunk/include/clibrary.h
  trunk/include/inn/defines.h
  trunk/include/inn/libinn.h
  trunk/include/inn/vector.h
  trunk/include/inn/xmalloc.h
  trunk/include/portable/getaddrinfo.h
  trunk/include/portable/getnameinfo.h
  trunk/include/portable/socket.h
  trunk/lib/fdflag.c
  trunk/lib/xwrite.c
  trunk/tests/lib/buffer-t.c
  trunk/tests/lib/fakewrite.c
  trunk/tests/lib/xwrite-t.c

--------------------------------+
 MANIFEST                       |    4 +
 configure.ac                   |    2 
 include/clibrary.h             |   11 +--
 include/inn/defines.h          |   25 -------
 include/inn/libinn.h           |    5 -
 include/inn/macros.h           |   36 ++++++++++
 include/inn/vector.h           |    1 
 include/inn/xmalloc.h          |    1 
 include/inn/xwrite.h           |   59 ++++++++++++++++
 include/portable/getaddrinfo.h |    1 
 include/portable/getnameinfo.h |    1 
 include/portable/macros.h      |   70 ++++++++++++++++++++
 include/portable/socket.h      |    5 -
 include/portable/uio.h         |   38 ++++++++++
 lib/fdflag.c                   |    2 
 lib/xwrite.c                   |  136 ++++++++++++++++++++++++++-------------
 tests/lib/buffer-t.c           |   29 +++++---
 tests/lib/fakewrite.c          |   12 +--
 tests/lib/xwrite-t.c           |   29 ++++++--
 19 files changed, 360 insertions(+), 107 deletions(-)

Modified: MANIFEST
===================================================================
--- MANIFEST	2014-09-06 07:20:03 UTC (rev 9679)
+++ MANIFEST	2014-09-06 08:07:27 UTC (rev 9680)
@@ -390,6 +390,7 @@
 include/inn/inndcomm.h                Header file for control channel commands
 include/inn/libinn.h                  Header file for utility functions
 include/inn/list.h                    Header file for list routines
+include/inn/macros.h                  Header file for useful macros
 include/inn/md5.h                     Header file for MD5 digests
 include/inn/messages.h                Header file for message functions
 include/inn/mmap.h                    Header file for mmap() functions
@@ -409,15 +410,18 @@
 include/inn/vector.h                  Header file for vectors of strings
 include/inn/wire.h                    Header file for wire-format functions
 include/inn/xmalloc.h                 Header file for allocation functions
+include/inn/xwrite.h                  Header file for partial write functions
 include/innperl.h                     Header file for embedded Perl
 include/portable                      Portability wrappers (Directory)
 include/portable/alloca.h             alloca replacement header
 include/portable/getaddrinfo.h        getaddrinfo replacement header
 include/portable/getnameinfo.h        getnameinfo replacement header
+include/portable/macros.h             Set of portability macros
 include/portable/mmap.h               Wrapper for <sys/mman.h>
 include/portable/setproctitle.h       Portable setup for setproctitle
 include/portable/socket.h             Wrapper for <sys/socket.h> and friends
 include/portable/time.h               Wrapper for <time.h> and <sys/time.h>
+include/portable/uio.h                Wrapper for <sys/uio.h>
 include/portable/wait.h               Wrapper for <sys/wait.h>
 include/ppport.h                      Header file for Perl support
 innd                                  Server (Directory)

Modified: configure.ac
===================================================================
--- configure.ac	2014-09-06 07:20:03 UTC (rev 9679)
+++ configure.ac	2014-09-06 08:07:27 UTC (rev 9680)
@@ -384,7 +384,7 @@
 dnl Generic checks for header files.
 AC_CHECK_HEADERS([crypt.h inttypes.h limits.h stddef.h \
                   stdint.h string.h sys/bitypes.h sys/filio.h sys/loadavg.h \
-                  sys/select.h sys/time.h unistd.h])
+                  sys/select.h sys/time.h sys/uio.h syslog.h unistd.h])
 
 dnl Some Linux systems have db1/ndbm.h instead of ndbm.h.  Others have
 dnl gdbm/ndbm.h or gdbm-ndbm.h.  Detecting the last two ones is not

Modified: include/clibrary.h
===================================================================
--- include/clibrary.h	2014-09-06 07:20:03 UTC (rev 9679)
+++ include/clibrary.h	2014-09-06 08:07:27 UTC (rev 9680)
@@ -4,6 +4,8 @@
 **  Including this file is the equivalent of including all of the following
 **  headers, portably:
 **
+**      #include "inn/macros.h"
+**      #include <limits.h>
 **      #include <sys/types.h>
 **      #include <stdarg.h>
 **      #include <stdio.h>
@@ -23,6 +25,7 @@
 
 /* Make sure we have our configuration information. */
 #include "config.h"
+#include "inn/macros.h"
 
 /* Assume stdarg is available; don't bother with varargs support any more.
    We need this to be able to declare vsnprintf. */
@@ -33,6 +36,7 @@
    strrchr, and memcpy.  Note that we don't attempt to declare any of the
    functions; the number of systems left without ANSI-compatible function
    prototypes isn't high enough to be worth the trouble.  */
+#include <limits.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <stdlib.h>
@@ -182,13 +186,6 @@
 #define PIPE_READ       0
 #define PIPE_WRITE      1
 
-/* Used for iterating through arrays.  ARRAY_SIZE returns the number of
-   elements in the array (useful for a < upper bound in a for loop) and
-   ARRAY_END returns a pointer to the element past the end (ISO C99 makes it
-   legal to refer to such a pointer as long as it's never dereferenced). */
-#define ARRAY_SIZE(array)       (sizeof(array) / sizeof((array)[0]))
-#define ARRAY_END(array)        (&(array)[ARRAY_SIZE(array)])
-
 /* C99 requires va_copy.  Older versions of GCC provide __va_copy.  Per the
    Autoconf manual, memcpy is a generally portable fallback. */
 #ifndef va_copy

Modified: include/inn/defines.h
===================================================================
--- include/inn/defines.h	2014-09-06 07:20:03 UTC (rev 9679)
+++ include/inn/defines.h	2014-09-06 08:07:27 UTC (rev 9680)
@@ -20,31 +20,8 @@
 #define INN_DEFINES_H 1
 
 #include <inn/system.h>
+#include "inn/macros.h"
 
-/* BEGIN_DECLS is used at the beginning of declarations so that C++
-   compilers don't mangle their names.  END_DECLS is used at the end. */
-#undef BEGIN_DECLS
-#undef END_DECLS
-#ifdef __cplusplus
-# define BEGIN_DECLS    extern "C" {
-# define END_DECLS      }
-#else
-# define BEGIN_DECLS    /* empty */
-# define END_DECLS      /* empty */
-#endif
-
-/* __attribute__ is available in gcc 2.5 and later, but only with gcc 2.7
-   could you use the __format__ form of the attributes, which is what we use
-   (to avoid confusion with other macros). */
-#ifndef __attribute__
-# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
-#  define __attribute__(spec)   /* empty */
-# endif
-#endif
-
-/* Used for unused parameters to silence gcc warnings. */
-#define UNUSED  __attribute__((__unused__))
-
 /* Make available the bool type. */
 #if INN_HAVE_STDBOOL_H
 # include <stdbool.h>

Modified: include/inn/libinn.h
===================================================================
--- include/inn/libinn.h	2014-09-06 07:20:03 UTC (rev 9679)
+++ include/inn/libinn.h	2014-09-06 08:07:27 UTC (rev 9680)
@@ -8,6 +8,7 @@
 
 #include <inn/defines.h>
 #include "inn/xmalloc.h"
+#include "inn/xwrite.h"
 
 #include <stdarg.h>             /* va_list */
 #include <stdio.h>              /* FILE */
@@ -22,7 +23,6 @@
 
 /* Forward declarations to avoid unnecessary includes. */
 struct stat;
-struct iovec;
 struct sockaddr;
 struct sockaddr_in;
 struct in_addr;
@@ -80,11 +80,8 @@
 extern void     daemonize(const char *path);
 extern int      getfdlimit(void);
 extern int      setfdlimit(unsigned int limit);
-extern ssize_t  xpwrite(int fd, const void *buffer, size_t size, off_t offset);
 extern void     (*xsignal(int signum, void (*sigfunc)(int)))(int);
 extern void     (*xsignal_norestart(int signum, void (*sigfunc)(int)))(int);
-extern ssize_t  xwrite(int fd, const void *buffer, size_t size);
-extern ssize_t  xwritev(int fd, const struct iovec *iov, int iovcnt);
 
 
 /* Headers. */

Added: include/inn/macros.h
===================================================================
--- include/inn/macros.h	                        (rev 0)
+++ include/inn/macros.h	2014-09-06 08:07:27 UTC (rev 9680)
@@ -0,0 +1,36 @@
+/* $Id$
+ *
+ * Some standard helpful macros.
+ *
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
+ * Written by Russ Allbery <eagle at eyrie.org>
+ *
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
+ */
+
+#ifndef INN_MACROS_H
+#define INN_MACROS_H 1
+
+#include "portable/macros.h"
+
+/*
+ * Used for iterating through arrays.  ARRAY_SIZE returns the number of
+ * elements in the array (useful for a < upper bound in a for loop) and
+ * ARRAY_END returns a pointer to the element past the end (ISO C99 makes it
+ * legal to refer to such a pointer as long as it's never dereferenced).
+ */
+#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
+#define ARRAY_END(array)  (&(array)[ARRAY_SIZE(array)])
+
+/* Used for unused parameters to silence gcc warnings. */
+#define UNUSED __attribute__((__unused__))
+
+#endif /* INN_MACROS_H */


Property changes on: trunk/include/inn/macros.h
___________________________________________________________________
Added: svn:keywords
   + Author Date Id Revision
Added: svn:eol-style
   + native

Modified: include/inn/vector.h
===================================================================
--- include/inn/vector.h	2014-09-06 07:20:03 UTC (rev 9679)
+++ include/inn/vector.h	2014-09-06 08:07:27 UTC (rev 9680)
@@ -27,6 +27,7 @@
 #define INN_VECTOR_H 1
 
 #include "config.h"
+#include "portable/macros.h"
 
 #include <stddef.h>
 

Modified: include/inn/xmalloc.h
===================================================================
--- include/inn/xmalloc.h	2014-09-06 07:20:03 UTC (rev 9679)
+++ include/inn/xmalloc.h	2014-09-06 08:07:27 UTC (rev 9680)
@@ -32,6 +32,7 @@
 #define INN_XMALLOC_H 1
 
 #include "config.h"
+#include "portable/macros.h"
 
 #include <stdarg.h>
 #include <stddef.h>

Added: include/inn/xwrite.h
===================================================================
--- include/inn/xwrite.h	                        (rev 0)
+++ include/inn/xwrite.h	2014-09-06 08:07:27 UTC (rev 9680)
@@ -0,0 +1,59 @@
+/* $Id$
+ *
+ * Prototypes for write and writev replacements to handle partial writes.
+ *
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
+ * Copyright 2008, 2010, 2013
+ *     The Board of Trustees of the Leland Stanford Junior University
+ * Copyright (c) 2004, 2005, 2006
+ *     by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+ *     2002, 2003 by The Internet Software Consortium and Rich Salz
+ *
+ * This code is derived from software contributed to the Internet Software
+ * Consortium by Rich Salz.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INN_XWRITE_H
+#define INN_XWRITE_H 1
+
+#include "config.h"
+#include "portable/macros.h"
+
+#include <stddef.h>
+#include <sys/types.h>
+
+/* Forward declaration to avoid an include. */
+struct iovec;
+
+BEGIN_DECLS
+
+/*
+ * Like the non-x versions of the same function, but keep writing until either
+ * the write is not making progress or there's a real error.  Handle partial
+ * writes and EINTR/EAGAIN errors.
+ */
+ssize_t xpwrite(int fd, const void *buffer, size_t size, off_t offset)
+    __attribute__((__nonnull__));
+ssize_t xwrite(int fd, const void *buffer, size_t size)
+    __attribute__((__nonnull__));
+ssize_t xwritev(int fd, const struct iovec *iov, int iovcnt)
+    __attribute__((__nonnull__));
+
+END_DECLS
+
+#endif /* INN_XWRITE_H */


Property changes on: trunk/include/inn/xwrite.h
___________________________________________________________________
Added: svn:eol-style
   + native
Added: svn:keywords
   + Author Date Id Revision

Modified: include/portable/getaddrinfo.h
===================================================================
--- include/portable/getaddrinfo.h	2014-09-06 07:20:03 UTC (rev 9679)
+++ include/portable/getaddrinfo.h	2014-09-06 08:07:27 UTC (rev 9680)
@@ -28,6 +28,7 @@
 #define PORTABLE_GETADDRINFO_H 1
 
 #include "config.h"
+#include "portable/macros.h"
 
 /* Skip this entire file if a system getaddrinfo was detected. */
 #ifndef HAVE_GETADDRINFO

Modified: include/portable/getnameinfo.h
===================================================================
--- include/portable/getnameinfo.h	2014-09-06 07:20:03 UTC (rev 9679)
+++ include/portable/getnameinfo.h	2014-09-06 08:07:27 UTC (rev 9680)
@@ -27,6 +27,7 @@
 #define PORTABLE_GETNAMEINFO_H 1
 
 #include "config.h"
+#include "portable/macros.h"
 
 /* Skip this entire file if a system getaddrinfo was detected. */
 #if !HAVE_GETNAMEINFO

Added: include/portable/macros.h
===================================================================
--- include/portable/macros.h	                        (rev 0)
+++ include/portable/macros.h	2014-09-06 08:07:27 UTC (rev 9680)
@@ -0,0 +1,70 @@
+/* $Id$
+ *
+ * Portability macros used in include files.
+ *
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
+ * Written by Russ Allbery <eagle at eyrie.org>
+ *
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
+ */
+
+#ifndef PORTABLE_MACROS_H
+#define PORTABLE_MACROS_H 1
+
+/*
+ * __attribute__ is available in gcc 2.5 and later, but only with gcc 2.7
+ * could you use the __format__ form of the attributes, which is what we use
+ * (to avoid confusion with other macros).
+ */
+#ifndef __attribute__
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+#  define __attribute__(spec)   /* empty */
+# endif
+#endif
+
+/*
+ * We use __alloc_size__, but it was only available in fairly recent versions
+ * of GCC.  Suppress warnings about the unknown attribute if GCC is too old.
+ * We know that we're GCC at this point, so we can use the GCC variadic macro
+ * extension, which will still work with versions of GCC too old to have C99
+ * variadic macro support.
+ */
+#if !defined(__attribute__) && !defined(__alloc_size__)
+# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3)
+#  define __alloc_size__(spec, args...) /* empty */
+# endif
+#endif
+
+/*
+ * LLVM and Clang pretend to be GCC but don't support all of the __attribute__
+ * settings that GCC does.  For them, suppress warnings about unknown
+ * attributes on declarations.  This unfortunately will affect the entire
+ * compilation context, but there's no push and pop available.
+ */
+#if !defined(__attribute__) && (defined(__llvm__) || defined(__clang__))
+# pragma GCC diagnostic ignored "-Wattributes"
+#endif
+
+/*
+ * BEGIN_DECLS is used at the beginning of declarations so that C++
+ * compilers don't mangle their names.  END_DECLS is used at the end.
+ */
+#undef BEGIN_DECLS
+#undef END_DECLS
+#ifdef __cplusplus
+# define BEGIN_DECLS    extern "C" {
+# define END_DECLS      }
+#else
+# define BEGIN_DECLS    /* empty */
+# define END_DECLS      /* empty */
+#endif
+
+#endif /* !PORTABLE_MACROS_H */


Property changes on: trunk/include/portable/macros.h
___________________________________________________________________
Added: svn:keywords
   + Author Date Id Revision
Added: svn:eol-style
   + native

Modified: include/portable/socket.h
===================================================================
--- include/portable/socket.h	2014-09-06 07:20:03 UTC (rev 9679)
+++ include/portable/socket.h	2014-09-06 08:07:27 UTC (rev 9680)
@@ -45,6 +45,7 @@
 #define PORTABLE_SOCKET_H 1
 
 #include "config.h"
+#include "portable/macros.h"
 
 #include <errno.h>
 #include <sys/types.h>
@@ -64,8 +65,8 @@
  * Pick up definitions of getaddrinfo and getnameinfo if not otherwise
  * available.
  */
-#include <portable/getaddrinfo.h>
-#include <portable/getnameinfo.h>
+#include "portable/getaddrinfo.h"
+#include "portable/getnameinfo.h"
 
 /* Define socklen_t if it's not available in sys/socket.h. */
 #ifndef HAVE_SOCKLEN_T

Added: include/portable/uio.h
===================================================================
--- include/portable/uio.h	                        (rev 0)
+++ include/portable/uio.h	2014-09-06 08:07:27 UTC (rev 9680)
@@ -0,0 +1,38 @@
+/* $Id$
+ *
+ * Portability wrapper around <sys/uio.h>.
+ *
+ * Provides a definition of the iovec struct for platforms that don't have it
+ * (primarily Windows).  Currently, the corresponding readv and writev
+ * functions are not provided or prototyped here.
+ *
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
+ * Written by Russ Allbery <eagle at eyrie.org>
+ *
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
+ */
+
+#ifndef PORTABLE_UIO_H
+#define PORTABLE_UIO_H 1
+
+#include <sys/types.h>
+
+/* remctl.h provides its own definition of this struct on Windows. */
+#if defined(HAVE_SYS_UIO_H)
+# include <sys/uio.h>
+#elif !defined(REMCTL_H)
+struct iovec {
+    void *iov_base;
+    size_t iov_len;
+};
+#endif
+
+#endif /* !PORTABLE_UIO_H */


Property changes on: trunk/include/portable/uio.h
___________________________________________________________________
Added: svn:keywords
   + Author Date Id Revision
Added: svn:eol-style
   + native

Modified: lib/fdflag.c
===================================================================
--- lib/fdflag.c	2014-09-06 07:20:03 UTC (rev 9679)
+++ lib/fdflag.c	2014-09-06 08:07:27 UTC (rev 9680)
@@ -47,7 +47,7 @@
 #endif
 
 #include "inn/fdflag.h"
-#include "inn/libinn.h"
+#include "inn/macros.h"
 
 
 /*

Modified: lib/xwrite.c
===================================================================
--- lib/xwrite.c	2014-09-06 07:20:03 UTC (rev 9679)
+++ lib/xwrite.c	2014-09-06 08:07:27 UTC (rev 9680)
@@ -1,39 +1,67 @@
-/*  $Id$
-**
-**  write and writev replacements to handle partial writes.
-**
-**  Usage:
-**
-**      ssize_t xwrite(int fildes, const void *buf, size_t nbyte);
-**      ssize_t xpwrite(int fildes, const void *buf, size_t nbyte,
-**                      off_t offset);
-**      ssize_t xwritev(int fildes, const struct iovec *iov, int iovcnt);
-**
-**  xwrite, xpwrite, and xwritev behave exactly like their C library
-**  counterparts except that, if write or writev succeeds but returns a number
-**  of bytes written less than the total bytes, the write is repeated picking
-**  up where it left off until the full amount of the data is written.  The
-**  write is also repeated if it failed with EINTR.  The write will be aborted
-**  after 10 successive writes with no forward progress.
-**
-**  Both functions return the number of bytes written on success or -1 on an
-**  error, and will leave errno set to whatever the underlying system call
-**  set it to.  Note that it is possible for a write to fail after some data
-**  was written, on the subsequent additional write; in that case, these
-**  functions will return -1 and the number of bytes actually written will
-**  be lost.
-*/
+/* $Id$
+ *
+ * write and writev replacements to handle partial writes.
+ *
+ * Usage:
+ *
+ *     ssize_t xwrite(int fildes, const void *buf, size_t nbyte);
+ *     ssize_t xpwrite(int fildes, const void *buf, size_t nbyte,
+ *                     off_t offset);
+ *     ssize_t xwritev(int fildes, const struct iovec *iov, int iovcnt);
+ *
+ * xwrite, xpwrite, and xwritev behave exactly like their C library
+ * counterparts except that, if write or writev succeeds but returns a number
+ * of bytes written less than the total bytes, the write is repeated picking
+ * up where it left off until the full amount of the data is written.  The
+ * write is also repeated if it failed with EINTR.  The write will be aborted
+ * after 10 successive writes with no forward progress.
+ *
+ * Both functions return the number of bytes written on success or -1 on an
+ * error, and will leave errno set to whatever the underlying system call set
+ * it to.  Note that it is possible for a write to fail after some data was
+ * written, on the subsequent additional write; in that case, these functions
+ * will return -1 and the number of bytes actually written will be lost.
+ *
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
+ * Copyright 2008, 2013, 2014
+ *     The Board of Trustees of the Leland Stanford Junior University
+ * Copyright (c) 2004, 2005, 2006
+ *     by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+ *     2002, 2003 by The Internet Software Consortium and Rich Salz
+ *
+ * This code is derived from software contributed to the Internet Software
+ * Consortium by Rich Salz.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
 
 #include "config.h"
 #include "clibrary.h"
+#include "portable/uio.h"
+
+#include <assert.h>
 #include <errno.h>
-#include <sys/uio.h>
 
-#include "inn/libinn.h"
+#include "inn/xwrite.h"
 
-/* If we're running the test suite, call testing versions of the write
-   functions.  #undef pwrite first because large file support may define a
-   macro pwrite (pointing to pwrite64) on some platforms (e.g. Solaris). */
+/*
+ * If we're running the test suite, call testing versions of the write
+ * functions.  #undef pwrite first because large file support may define a
+ * macro pwrite (pointing to pwrite64) on some platforms (e.g. Solaris).
+ */
 #if TESTING
 # undef pwrite
 # define pwrite fake_pwrite
@@ -44,6 +72,7 @@
 ssize_t fake_writev(int, const struct iovec *, int);
 #endif
 
+
 ssize_t
 xwrite(int fd, const void *buffer, size_t size)
 {
@@ -70,6 +99,8 @@
     return (total < size) ? -1 : (ssize_t) total;
 }
 
+
+#ifndef _WIN32
 ssize_t
 xpwrite(int fd, const void *buffer, size_t size, off_t offset)
 {
@@ -96,7 +127,9 @@
     }
     return (total < size) ? -1 : (ssize_t) total;
 }
+#endif
 
+
 ssize_t
 xwritev(int fd, const struct iovec iov[], int iovcnt)
 {
@@ -105,19 +138,29 @@
     int iovleft, i, count;
     struct iovec *tmpiov;
 
+    /*
+     * Bounds-check the iovcnt argument.  This is just for our safety.  The
+     * system will probably impose a lower limit on iovcnt, causing the later
+     * writev to fail with an error we'll return.
+     */
     if (iovcnt == 0)
 	return 0;
+    if (iovcnt < 0 || (size_t) iovcnt > SIZE_MAX / sizeof(struct iovec)) {
+        errno = EINVAL;
+        return -1;
+    }
 
     /* Get a count of the total number of bytes in the iov array. */
     for (total = 0, i = 0; i < iovcnt; i++)
         total += iov[i].iov_len;
-
     if (total == 0)
 	return 0;
 
-    /* First, try just writing it all out.  Most of the time this will
-       succeed and save us lots of work.  Abort the write if we try ten times 
-       with no forward progress. */
+    /*
+     * First, try just writing it all out.  Most of the time this will succeed
+     * and save us lots of work.  Abort the write if we try ten times with no
+     * forward progress.
+     */
     count = 0;
     do {
         if (++count > 10)
@@ -131,22 +174,29 @@
     if (status == total)
         return total;
 
-    /* If we fell through to here, the first write partially succeeded.
-       Figure out how far through the iov array we got, and then duplicate
-       the rest of it so that we can modify it to reflect how much we manage
-       to write on successive tries. */
+    /*
+     * If we fell through to here, the first write partially succeeded.
+     * Figure out how far through the iov array we got, and then duplicate the
+     * rest of it so that we can modify it to reflect how much we manage to
+     * write on successive tries.
+     */
     offset = status;
     left = total - offset;
     for (i = 0; offset >= (size_t) iov[i].iov_len; i++)
         offset -= iov[i].iov_len;
     iovleft = iovcnt - i;
-    tmpiov = xmalloc(iovleft * sizeof(struct iovec));
+    assert(iovleft > 0);
+    tmpiov = calloc(iovleft, sizeof(struct iovec));
+    if (tmpiov == NULL)
+        return -1;
     memcpy(tmpiov, iov + i, iovleft * sizeof(struct iovec));
 
-    /* status now contains the offset into the first iovec struct in tmpiov.
-       Go into the write loop, trying to write out everything remaining at
-       each point.  At the top of the loop, status will contain a count of
-       bytes written out at the beginning of the set of iovec structs. */
+    /*
+     * status now contains the offset into the first iovec struct in tmpiov.
+     * Go into the write loop, trying to write out everything remaining at
+     * each point.  At the top of the loop, status will contain a count of
+     * bytes written out at the beginning of the set of iovec structs.
+     */
     i = 0;
     do {
         if (++count > 10)

Modified: tests/lib/buffer-t.c
===================================================================
--- tests/lib/buffer-t.c	2014-09-06 07:20:03 UTC (rev 9679)
+++ tests/lib/buffer-t.c	2014-09-06 08:07:27 UTC (rev 9680)
@@ -1,12 +1,11 @@
-/*
+/* $Id$
+ *
  * buffer test suite.
  *
- * $Id$
- *
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Written by Russ Allbery <rra at stanford.edu>
+ * Written by Russ Allbery <eagle at eyrie.org>
  *
  * The authors hereby relinquish any claim to any copyright that they may have
  * in this work, whether granted under contract or by operation of law or
@@ -21,17 +20,18 @@
 
 #include "config.h"
 #include "clibrary.h"
+
 #include <fcntl.h>
 
+#include "tap/basic.h"
 #include "inn/buffer.h"
-#include "inn/messages.h"
-#include "inn/libinn.h"
-#include "tap/basic.h"
+#include "inn/xwrite.h"
 
 static const char test_string1[] = "This is a test";
 static const char test_string2[] = " of the buffer system";
 static const char test_string3[] = "This is a test\0 of the buffer system";
 
+
 /*
  * Test buffer_vsprintf.  Wrapper needed to generate the va_list.
  */
@@ -116,6 +116,8 @@
     /* buffer_resize */
     three = buffer_new();
     ok(three != NULL, "buffer_new works");
+    if (three == NULL)
+        bail("buffer_new returned NULL");
     is_int(0, three->size, "initial size is 0");
     buffer_set(three, test_string1, sizeof(test_string1));
     is_int(1024, three->size, "size becomes 1024 when adding data");
@@ -129,7 +131,7 @@
     fd = open("buffer-test", O_RDWR | O_CREAT | O_TRUNC, 0666);
     if (fd < 0)
         sysbail("cannot create buffer-test");
-    data = xmalloc(2048);
+    data = bmalloc(2048);
     memset(data, 'a', 1023);
     data[1023] = '\r';
     data[1024] = '\n';
@@ -140,6 +142,8 @@
         sysbail("cannot rewind buffer-test");
     three = buffer_new();
     ok(three != NULL, "buffer_new works");
+    if (three == NULL)
+        bail("buffer_new returned NULL");
     is_int(0, three->size, "and initial size is 0");
     buffer_resize(three, 1024);
     is_int(1024, three->size, "resize to 1024 works");
@@ -193,7 +197,7 @@
     buffer_sprintf(three, "%d testing", 8);
     is_int(9, three->left, "replacing the buffer works");
     is_string("8 testing", three->data, "and the results are correct");
-    data = xmalloc(1050);
+    data = bmalloc(1050);
     memset(data, 'a', 1049);
     data[1049] = '\0';
     is_int(1024, three->size, "size before large sprintf is 1024");
@@ -209,7 +213,7 @@
     fd = open("buffer-test", O_RDWR | O_CREAT | O_TRUNC, 0666);
     if (fd < 0)
         sysbail("cannot create buffer-test");
-    data = xmalloc(2049);
+    data = bmalloc(2049);
     memset(data, 'a', 2049);
     if (xwrite(fd, data, 2049) < 2049)
         sysbail("cannot write to buffer-test");
@@ -269,7 +273,7 @@
     test_vsprintf(three, "%d testing", 8);
     is_int(9, three->left, "replacing the buffer results in the correct size");
     is_string("8 testing", three->data, "and the correct data");
-    data = xmalloc(1050);
+    data = bmalloc(1050);
     memset(data, 'a', 1049);
     data[1049] = '\0';
     is_int(1024, three->size, "size is 1024 before large vsprintf");
@@ -281,5 +285,8 @@
     free(data);
     buffer_free(three);
 
+    /* Test buffer_free with NULL and ensure it doesn't explode. */
+    buffer_free(NULL);
+
     return 0;
 }

Modified: tests/lib/fakewrite.c
===================================================================
--- tests/lib/fakewrite.c	2014-09-06 07:20:03 UTC (rev 9679)
+++ tests/lib/fakewrite.c	2014-09-06 08:07:27 UTC (rev 9680)
@@ -1,12 +1,11 @@
-/*
+/* $Id$
+ *
  * Fake write and writev functions for testing xwrite and xwritev.
  *
- * $Id$
- *
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Copyright 2000, 2001, 2002, 2004 Russ Allbery <rra at stanford.edu>
+ * Copyright 2000, 2001, 2002, 2004 Russ Allbery <eagle at eyrie.org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,10 +30,11 @@
 
 #include "config.h"
 #include "clibrary.h"
+#include "portable/uio.h"
+
 #include <errno.h>
-#include <sys/uio.h>
 
-#include "inn/libinn.h"
+#include "inn/macros.h"
 
 ssize_t fake_write(int, const void *, size_t);
 ssize_t fake_pwrite(int, const void *, size_t, off_t);

Modified: tests/lib/xwrite-t.c
===================================================================
--- tests/lib/xwrite-t.c	2014-09-06 07:20:03 UTC (rev 9679)
+++ tests/lib/xwrite-t.c	2014-09-06 08:07:27 UTC (rev 9680)
@@ -1,13 +1,12 @@
-/*
+/* $Id$
+ *
  * Test suite for xwrite, xwritev, and xpwrite.
  *
- * $Id$
- *
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Copyright 2000, 2001, 2002, 2004 Russ Allbery <rra at stanford.edu>
- * Copyright 2009
+ * Copyright 2000, 2001, 2002, 2004 Russ Allbery <eagle at eyrie.org>
+ * Copyright 2009, 2014
  *     The Board of Trustees of the Leland Stanford Junior University
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -33,10 +32,12 @@
 
 #include "config.h"
 #include "clibrary.h"
-#include <sys/uio.h>
+#include "portable/uio.h"
 
-#include "inn/libinn.h"
+#include <errno.h>
+
 #include "tap/basic.h"
+#include "inn/xwrite.h"
 
 /* The data array we'll use to do testing. */
 char data[256];
@@ -62,7 +63,7 @@
     int i;
     struct iovec iov[4];
 
-    plan(38);
+    plan(44);
 
     /* Test xwrite. */
     for (i = 0; i < 256; i++)
@@ -121,6 +122,16 @@
     write_offset = 0;
     write_interrupt = 0;
 
+    /* Test bounds errors in xwritev. */
+    is_int(-1, xwritev(0, iov, -1), "xwrite with negative count");
+    is_int(EINVAL, errno, "...with correct errno");
+    if (INT_MAX <= SIZE_MAX / sizeof(struct iovec))
+        skip_block(2, "xwritev count overflow not possible");
+    else {
+        is_int(-1, xwritev(0, iov, INT_MAX), "xwrite with INT_MAX count");
+        is_int(EINVAL, errno, "...with correct errno");
+    }
+
     /* Test xpwrite. */
     for (i = 0; i < 256; i++)
         data[i] = i;
@@ -150,6 +161,8 @@
     iov[0].iov_base = data + 1;
     iov[0].iov_len = 2;
     test_write(xwritev(0, iov, 0), 0, "xwritev zero length");
+    iov[0].iov_len = 0;
+    test_write(xwritev(0, iov, 1), 0, "xwritev zero length with buffers");
 
     return 0;
 }



More information about the inn-committers mailing list