changeset 13314:d44fde85189e

New module pwrite.
author Peter O'Gorman <pogma@thewrittenword.com>
date Wed, 05 May 2010 21:09:38 +0200
parents 857a5fb91be7
children 39dc842a035e
files ChangeLog doc/posix-functions/pwrite.texi lib/pwrite.c lib/unistd.in.h m4/pwrite.m4 m4/unistd_h.m4 modules/pwrite modules/unistd tests/test-unistd-c++.cc
diffstat 9 files changed, 176 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2010-05-05  Peter O'Gorman  <pogma@thewrittenword.com>
+
+	New module pwrite.
+	* lib/unistd.in.h (pwrite): New declaration.
+	* lib/pwrite.c: New file, from glibc with modifications.
+	* m4/pwrite.m4: New file.
+	* m4/unistd_h.m4 (gl_UNISTD_H): Test whether pwrite is declared.
+	(gl_UNISTD_H_DEFAULTS): Initialize GNULIB_PWRITE, HAVE_PWRITE,
+	REPLACE_PWRITE.
+	* modules/pwrite: New file.
+	* modules/unistd (Makefile.am): Substitute GNULIB_PWRITE, HAVE_PWRITE,
+	REPLACE_PWRITE.
+	* tests/test-unistd-c++.cc: Check GNULIB_NAMESPACE::pwrite.
+	* doc/posix-functions/pwrite.texi: Mention the new module.
+
 2010-05-05  Peter O'Gorman  <pogma@thewrittenword.com>
 
 	pread: Update documentation.
--- a/doc/posix-functions/pwrite.texi
+++ b/doc/posix-functions/pwrite.texi
@@ -4,15 +4,15 @@
 
 POSIX specification: @url{http://www.opengroup.org/onlinepubs/9699919799/functions/pwrite.html}
 
-Gnulib module: ---
+Gnulib module: pwrite
 
 Portability problems fixed by Gnulib:
 @itemize
+@item
+This function is missing on some platforms:
+HP-UX 10, mingw, BeOS.
 @end itemize
 
 Portability problems not fixed by Gnulib:
 @itemize
-@item
-This function is missing on some platforms:
-mingw, BeOS.
 @end itemize
new file mode 100644
--- /dev/null
+++ b/lib/pwrite.c
@@ -0,0 +1,64 @@
+/* Write block to given position in file without changing file pointer.
+   POSIX version.
+   Copyright (C) 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#include <errno.h>
+
+#define __libc_lseek(f,o,w) lseek (f, o, w)
+#define __set_errno(Val) errno = (Val)
+#define __libc_write(f,b,n) write (f, b, n)
+
+/* Note: This implementation of pwrite is not multithread-safe.  */
+
+ssize_t
+pwrite (int fd, const void *buf, size_t nbyte, off_t offset)
+{
+  /* Since we must not change the file pointer preserve the value so that
+     we can restore it later.  */
+  int save_errno;
+  ssize_t result;
+  off_t old_offset = __libc_lseek (fd, 0, SEEK_CUR);
+  if (old_offset == (off_t) -1)
+    return -1;
+
+  /* Set to wanted position.  */
+  if (__libc_lseek (fd, offset, SEEK_SET) == (off_t) -1)
+    return -1;
+
+  /* Write out the data.  */
+  result = __libc_write (fd, buf, nbyte);
+
+  /* Now we have to restore the position.  If this fails we have to
+     return this as an error.  But if the writing also failed we
+     return this error.  */
+  save_errno = errno;
+  if (__libc_lseek (fd, old_offset, SEEK_SET) == (off_t) -1)
+    {
+      if (result == -1)
+	__set_errno (save_errno);
+      return -1;
+    }
+  __set_errno (save_errno);
+
+  return result;
+}
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -86,7 +86,7 @@
 #endif
 
 #if (@GNULIB_WRITE@ || @GNULIB_READLINK@ || @GNULIB_READLINKAT@ \
-     || @GNULIB_PREAD@ || defined GNULIB_POSIXCHECK)
+     || @GNULIB_PREAD@ || @GNULIB_PWRITE@ || defined GNULIB_POSIXCHECK)
 /* Get ssize_t.  */
 # include <sys/types.h>
 #endif
@@ -1016,6 +1016,40 @@
 #endif
 
 
+#if @GNULIB_PWRITE@
+/* Write at most BUFSIZE bytes from BUF into FD, starting at OFFSET.
+   Return the number of bytes written if successful, otherwise
+   set errno and return -1.  0 indicates nothing written.  See the
+   POSIX:2001 specification
+   <http://www.opengroup.org/susv3xsh/pwrite.html>.  */
+# if @REPLACE_PWRITE@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   define pwrite rpl_pwrite
+#  endif
+_GL_FUNCDECL_RPL (pwrite, ssize_t,
+                  (int fd, const void *buf, size_t bufsize, off_t offset)
+                  _GL_ARG_NONNULL ((2)));
+_GL_CXXALIAS_RPL (pwrite, ssize_t,
+                  (int fd, const void *buf, size_t bufsize, off_t offset));
+# else
+#  if !@HAVE_PWRITE@
+_GL_FUNCDECL_SYS (pwrite, ssize_t,
+                  (int fd, const void *buf, size_t bufsize, off_t offset)
+                  _GL_ARG_NONNULL ((2)));
+#  endif
+_GL_CXXALIAS_SYS (pwrite, ssize_t,
+                  (int fd, const void *buf, size_t bufsize, off_t offset));
+# endif
+_GL_CXXALIASWARN (pwrite);
+#elif defined GNULIB_POSIXCHECK
+# undef pwrite
+# if HAVE_RAW_DECL_PWRITE
+_GL_WARN_ON_USE (pwrite, "pwrite is unportable - "
+                 "use gnulib module pwrite for portability");
+# endif
+#endif
+
+
 #if @GNULIB_READLINK@
 /* Read the contents of the symbolic link FILE and place the first BUFSIZE
    bytes of it into BUF.  Return the number of bytes placed into BUF if
new file mode 100644
--- /dev/null
+++ b/m4/pwrite.m4
@@ -0,0 +1,19 @@
+# pwrite.m4 serial 1
+dnl Copyright (C) 2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_PWRITE],
+[
+  AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+
+  dnl Persuade glibc <unistd.h> to declare pwrite().
+  AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
+
+  AC_CHECK_FUNCS_ONCE([pwrite])
+  if test $ac_cv_func_pwrite = no; then
+    HAVE_PWRITE=0
+    AC_LIBOBJ([pwrite])
+  fi
+])
--- a/m4/unistd_h.m4
+++ b/m4/unistd_h.m4
@@ -38,8 +38,9 @@
     ]], [chown dup2 dup3 environ euidaccess faccessat fchdir fchownat
     fsync ftruncate getcwd getdomainname getdtablesize getgroups
     gethostname getlogin getlogin_r getpagesize getusershell setusershell
-    endusershell lchown link linkat lseek pipe2 pread readlink readlinkat
-    rmdir sleep symlink symlinkat ttyname_r unlink unlinkat usleep])
+    endusershell lchown link linkat lseek pipe2 pread pwrite readlink
+    readlinkat rmdir sleep symlink symlinkat ttyname_r unlink unlinkat
+    usleep])
 ])
 
 AC_DEFUN([gl_UNISTD_MODULE_INDICATOR],
@@ -79,6 +80,7 @@
   GNULIB_LSEEK=0;            AC_SUBST([GNULIB_LSEEK])
   GNULIB_PIPE2=0;            AC_SUBST([GNULIB_PIPE2])
   GNULIB_PREAD=0;            AC_SUBST([GNULIB_PREAD])
+  GNULIB_PWRITE=0;           AC_SUBST([GNULIB_PWRITE])
   GNULIB_READLINK=0;         AC_SUBST([GNULIB_READLINK])
   GNULIB_READLINKAT=0;       AC_SUBST([GNULIB_READLINKAT])
   GNULIB_RMDIR=0;            AC_SUBST([GNULIB_RMDIR])
@@ -113,6 +115,7 @@
   HAVE_LINKAT=1;          AC_SUBST([HAVE_LINKAT])
   HAVE_PIPE2=1;           AC_SUBST([HAVE_PIPE2])
   HAVE_PREAD=1;           AC_SUBST([HAVE_PREAD])
+  HAVE_PWRITE=1;          AC_SUBST([HAVE_PWRITE])
   HAVE_READLINK=1;        AC_SUBST([HAVE_READLINK])
   HAVE_READLINKAT=1;      AC_SUBST([HAVE_READLINKAT])
   HAVE_SLEEP=1;           AC_SUBST([HAVE_SLEEP])
@@ -140,6 +143,7 @@
   REPLACE_LINKAT=0;       AC_SUBST([REPLACE_LINKAT])
   REPLACE_LSEEK=0;        AC_SUBST([REPLACE_LSEEK])
   REPLACE_PREAD=0;        AC_SUBST([REPLACE_PREAD])
+  REPLACE_PWRITE=0;       AC_SUBST([REPLACE_PWRITE])
   REPLACE_READLINK=0;     AC_SUBST([REPLACE_READLINK])
   REPLACE_RMDIR=0;        AC_SUBST([REPLACE_RMDIR])
   REPLACE_SLEEP=0;        AC_SUBST([REPLACE_SLEEP])
new file mode 100644
--- /dev/null
+++ b/modules/pwrite
@@ -0,0 +1,25 @@
+Description:
+pwrite() function: write without changing file offset
+
+Files:
+lib/pwrite.c
+m4/pwrite.m4
+
+Depends-on:
+lseek
+unistd
+
+configure.ac:
+gl_FUNC_PWRITE
+gl_UNISTD_MODULE_INDICATOR([pwrite])
+
+Makefile.am:
+
+Include:
+<unistd.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+Peter O'Gorman
--- a/modules/unistd
+++ b/modules/unistd
@@ -53,6 +53,7 @@
 	      -e 's|@''GNULIB_LSEEK''@|$(GNULIB_LSEEK)|g' \
 	      -e 's|@''GNULIB_PIPE2''@|$(GNULIB_PIPE2)|g' \
 	      -e 's|@''GNULIB_PREAD''@|$(GNULIB_PREAD)|g' \
+	      -e 's|@''GNULIB_PWRITE''@|$(GNULIB_PWRITE)|g' \
 	      -e 's|@''GNULIB_READLINK''@|$(GNULIB_READLINK)|g' \
 	      -e 's|@''GNULIB_READLINKAT''@|$(GNULIB_READLINKAT)|g' \
 	      -e 's|@''GNULIB_RMDIR''@|$(GNULIB_RMDIR)|g' \
@@ -87,6 +88,7 @@
 	      -e 's|@''HAVE_LINKAT''@|$(HAVE_LINKAT)|g' \
 	      -e 's|@''HAVE_PIPE2''@|$(HAVE_PIPE2)|g' \
 	      -e 's|@''HAVE_PREAD''@|$(HAVE_PREAD)|g' \
+	      -e 's|@''HAVE_PWRITE''@|$(HAVE_PWRITE)|g' \
 	      -e 's|@''HAVE_READLINK''@|$(HAVE_READLINK)|g' \
 	      -e 's|@''HAVE_READLINKAT''@|$(HAVE_READLINKAT)|g' \
 	      -e 's|@''HAVE_SLEEP''@|$(HAVE_SLEEP)|g' \
@@ -114,6 +116,7 @@
 	      -e 's|@''REPLACE_LINKAT''@|$(REPLACE_LINKAT)|g' \
 	      -e 's|@''REPLACE_LSEEK''@|$(REPLACE_LSEEK)|g' \
 	      -e 's|@''REPLACE_PREAD''@|$(REPLACE_PREAD)|g' \
+	      -e 's|@''REPLACE_PWRITE''@|$(REPLACE_PWRITE)|g' \
 	      -e 's|@''REPLACE_READLINK''@|$(REPLACE_READLINK)|g' \
 	      -e 's|@''REPLACE_RMDIR''@|$(REPLACE_RMDIR)|g' \
 	      -e 's|@''REPLACE_SLEEP''@|$(REPLACE_SLEEP)|g' \
--- a/tests/test-unistd-c++.cc
+++ b/tests/test-unistd-c++.cc
@@ -138,6 +138,11 @@
                  (int, void *, size_t, off_t));
 #endif
 
+#if GNULIB_TEST_PWRITE
+SIGNATURE_CHECK (GNULIB_NAMESPACE::pwrite, ssize_t,
+                 (int, const void *, size_t, off_t));
+#endif
+
 #if GNULIB_TEST_READLINK
 SIGNATURE_CHECK (GNULIB_NAMESPACE::readlink, ssize_t,
                  (const char *, char *, size_t));