Subject: fdatasync module proposal

From: Paul Eggert <[email-masked]>
Date: Fri, 22 Jul 2011 14:13:29 -0700

Surely coreutils is not the only program that will have problems
with fdatasync on Mac OS.  How about the following gnulib patches?
One is for fdatasync, the other for its tests.

>From d5c4b4b9266db16c8477a94640290e0b662cee93 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Fri, 22 Jul 2011 14:00:22 -0700
Subject: [PATCH 1/2] fdatasync: New module

* MODULES.html.sh: Add it.
* doc/posix-functions/fdatasync.texi (fdatasync): Document it.
* lib/unistd.in.h (fdatasync): Arrange for replacement.
* m4/unistd_h.m4 (gl_UNISTD_H): Prepare for warn-on-use.
(gl_UNISTD_H_DEFAULTS): Define defaults for it.
* modules/unistd (unistd.h): Substitute for its vars.
* lib/fdatasync.c, m4/fdatasync.m4, modules/fdatasync: New files.
---
 ChangeLog                          |    9 +++++++++
 MODULES.html.sh                    |    1 +
 doc/posix-functions/fdatasync.texi |   11 +++++++----
 lib/fdatasync.c                    |   30 ++++++++++++++++++++++++++++++
 lib/unistd.in.h                    |   28 ++++++++++++++++++++++++++++
 m4/fdatasync.m4                    |   34 ++++++++++++++++++++++++++++++++++
 m4/unistd_h.m4                     |    6 +++++-
 modules/fdatasync                  |   32 ++++++++++++++++++++++++++++++++
 modules/unistd                     |    4 ++++
 9 files changed, 150 insertions(+), 5 deletions(-)
 create mode 100644 lib/fdatasync.c
 create mode 100644 m4/fdatasync.m4
 create mode 100644 modules/fdatasync

diff --git a/ChangeLog b/ChangeLog
index b652f25..15b0fe5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
 2011-07-22  Paul Eggert  <[email-masked]>
 
+	fdatasync: New module
+	* MODULES.html.sh: Add it.
+	* doc/posix-functions/fdatasync.texi (fdatasync): Document it.
+	* lib/unistd.in.h (fdatasync): Arrange for replacement.
+	* m4/unistd_h.m4 (gl_UNISTD_H): Prepare for warn-on-use.
+	(gl_UNISTD_H_DEFAULTS): Define defaults for it.
+	* modules/unistd (unistd.h): Substitute for its vars.
+	* lib/fdatasync.c, m4/fdatasync.m4, modules/fdatasync: New files.
+
 	fsusage: port to MacOS X 10.7 with 4 TiB file systems
 	* m4/fsusage.m4 (gl_FILE_SYSTEM_USAGE): Reject statvfs
 	implementations that use only 32 bits to count blocks.
diff --git a/MODULES.html.sh b/MODULES.html.sh
index 80befa9..a185c42 100755
--- a/MODULES.html.sh
+++ b/MODULES.html.sh
@@ -2360,6 +2360,7 @@ func_all_modules ()
   func_module fclose
   func_module fcntl-h
   func_module fcntl
+  func_module fdatasync
   func_module flock
   func_module fopen
   func_module fprintf-posix
diff --git a/doc/posix-functions/fdatasync.texi b/doc/posix-functions/fdatasync.texi
index 8631207..2c581d8 100644
--- a/doc/posix-functions/fdatasync.texi
+++ b/doc/posix-functions/fdatasync.texi
@@ -4,15 +4,18 @@
 
 POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html}
 
-Gnulib module: ---
+Gnulib module: fdatasync
 
 Portability problems fixed by Gnulib:
 @itemize
+@item
+This function is present but undeclared and ineffective on some platforms:
+MacOS X 10.7
+@item
+This function is missing on some platforms:
+MacOS X 10.5, FreeBSD 6.0, OpenBSD 3.8, IRIX 5.3, Solaris 2.4, mingw, Interix 3.5, BeOS.
 @end itemize
 
 Portability problems not fixed by Gnulib:
 @itemize
-@item
-This function is missing on some platforms:
-MacOS X 10.5, FreeBSD 6.0, OpenBSD 3.8, IRIX 5.3, Solaris 2.4, mingw, Interix 3.5, BeOS.
 @end itemize
diff --git a/lib/fdatasync.c b/lib/fdatasync.c
new file mode 100644
index 0000000..fbb7b5a
--- /dev/null
+++ b/lib/fdatasync.c
@@ -0,0 +1,30 @@
+/* Emulate fdatasync on platforms that lack it.
+
+   Copyright (C) 2011 Free Software Foundation, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library 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
+   Lesser 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/>.  */
+
+/* written by Paul Eggert */
+
+#include <config.h>
+
+#include <unistd.h>
+
+int
+fdatasync (int fd)
+#undef fdatasync
+{
+  /* This isn't right, but it's the best we can do portably.  */
+  return fsync (fd);
+}
diff --git a/lib/unistd.in.h b/lib/unistd.in.h
index e612fb3..aac5bb2 100644
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -483,6 +483,34 @@ _GL_WARN_ON_USE (fchownat, "fchownat is not portable - "
 #endif

+#if @GNULIB_FDATASYNC@
+/* Synchronize data changes to a file.
+   Return 0 if successful, otherwise -1 and errno set.
+   See POSIX:2001 specification
+   <http://www.opengroup.org/susv3xsh/fdatasync.html>.  */
+# if @REPLACE_FDATASYNC@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef fdatasync
+#   define fdatasync rpl_fdatasync
+#  endif
+_GL_FUNCDECL_RPL (fdatasync, int, (int /* fd */));
+_GL_CXXALIAS_RPL (fdatasync, int, (int /* fd */));
+# else
+#  if !@HAVE_DECL_FDATASYNC@
+_GL_FUNCDECL_SYS (fdatasync, int, (int /* fd */));
+#  endif
+_GL_CXXALIAS_SYS (fdatasync, int, (int /* fd */));
+# endif
+_GL_CXXALIASWARN (fdatasync);
+#elif defined GNULIB_POSIXCHECK
+# undef fdatasync
+# if HAVE_RAW_DECL_FDATASYNC
+_GL_WARN_ON_USE (fdatasync, "fdatasync is unportable - "
+                 "use gnulib module fdatasync for portability");
+# endif
+#endif
+
+
 #if @GNULIB_FSYNC@
 /* Synchronize changes to a file.
    Return 0 if successful, otherwise -1 and errno set.
diff --git a/m4/fdatasync.m4 b/m4/fdatasync.m4
new file mode 100644
index 0000000..af17970
--- /dev/null
+++ b/m4/fdatasync.m4
@@ -0,0 +1,34 @@
+# fdatasync.m4
+dnl Copyright 2011 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.
+
+dnl written by Paul Eggert
+
+AC_DEFUN([gl_FUNC_FDATASYNC],
+[
+  AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+
+  LIB_FDATASYNC=
+  AC_SUBST([LIB_FDATASYNC])
+
+  AC_CHECK_DECLS_ONCE([fdatasync])
+  if test $ac_cv_have_decl_fdatasync = no; then
+    HAVE_DECL_FDATASYNC=0
+
+    # If it isn't declared, replace it.  This is better for MacOS X 10.7,
+    # where it is not declared, exists, and is ineffective.
+    REPLACE_FDATASYNC=1
+  else
+    gl_saved_libs=$LIBS
+      AC_SEARCH_LIBS([fdatasync], [rt posix4],
+                     [test "$ac_cv_search_fdatasync" = "none required" ||
+                      LIB_FDATASYNC=$ac_cv_search_fdatasync])
+      AC_CHECK_FUNCS([fdatasync])
+    LIBS=$gl_saved_libs
+    if test $ac_cv_func_fdatasync = no; then
+      HAVE_FDATASYNC=0
+    fi
+  fi
+])
diff --git a/m4/unistd_h.m4 b/m4/unistd_h.m4
index fb6fe07..dc6b63e 100644
--- a/m4/unistd_h.m4
+++ b/m4/unistd_h.m4
@@ -34,7 +34,7 @@ AC_DEFUN([gl_UNISTD_H],
 # endif
 #endif
     ]], [chown dup2 dup3 environ euidaccess faccessat fchdir fchownat
-    fsync ftruncate getcwd getdomainname getdtablesize getgroups
+    fdatasync fsync ftruncate getcwd getdomainname getdtablesize getgroups
     gethostname getlogin getlogin_r getpagesize getusershell setusershell
     endusershell group_member lchown link linkat lseek pipe pipe2 pread pwrite
     readlink readlinkat rmdir sleep symlink symlinkat ttyname_r unlink unlinkat
@@ -61,6 +61,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
   GNULIB_FACCESSAT=0;            AC_SUBST([GNULIB_FACCESSAT])
   GNULIB_FCHDIR=0;               AC_SUBST([GNULIB_FCHDIR])
   GNULIB_FCHOWNAT=0;             AC_SUBST([GNULIB_FCHOWNAT])
+  GNULIB_FDATASYNC=0;            AC_SUBST([GNULIB_FDATASYNC])
   GNULIB_FSYNC=0;                AC_SUBST([GNULIB_FSYNC])
   GNULIB_FTRUNCATE=0;            AC_SUBST([GNULIB_FTRUNCATE])
   GNULIB_GETCWD=0;               AC_SUBST([GNULIB_GETCWD])
@@ -104,6 +105,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
   HAVE_FACCESSAT=1;       AC_SUBST([HAVE_FACCESSAT])
   HAVE_FCHDIR=1;          AC_SUBST([HAVE_FCHDIR])
   HAVE_FCHOWNAT=1;        AC_SUBST([HAVE_FCHOWNAT])
+  HAVE_FDATASYNC=1;       AC_SUBST([HAVE_FDATASYNC])
   HAVE_FSYNC=1;           AC_SUBST([HAVE_FSYNC])
   HAVE_FTRUNCATE=1;       AC_SUBST([HAVE_FTRUNCATE])
   HAVE_GETDTABLESIZE=1;   AC_SUBST([HAVE_GETDTABLESIZE])
@@ -128,6 +130,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
   HAVE_USLEEP=1;          AC_SUBST([HAVE_USLEEP])
   HAVE_DECL_ENVIRON=1;    AC_SUBST([HAVE_DECL_ENVIRON])
   HAVE_DECL_FCHDIR=1;     AC_SUBST([HAVE_DECL_FCHDIR])
+  HAVE_DECL_FDATASYNC=1;  AC_SUBST([HAVE_DECL_FDATASYNC])
   HAVE_DECL_GETDOMAINNAME=1; AC_SUBST([HAVE_DECL_GETDOMAINNAME])
   HAVE_DECL_GETLOGIN_R=1; AC_SUBST([HAVE_DECL_GETLOGIN_R])
   HAVE_DECL_GETPAGESIZE=1; AC_SUBST([HAVE_DECL_GETPAGESIZE])
@@ -140,6 +143,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
   REPLACE_DUP=0;          AC_SUBST([REPLACE_DUP])
   REPLACE_DUP2=0;         AC_SUBST([REPLACE_DUP2])
   REPLACE_FCHOWNAT=0;     AC_SUBST([REPLACE_FCHOWNAT])
+  REPLACE_FDATASYNC=0;    AC_SUBST([REPLACE_FDATASYNC])
   REPLACE_GETCWD=0;       AC_SUBST([REPLACE_GETCWD])
   REPLACE_GETDOMAINNAME=0; AC_SUBST([REPLACE_GETDOMAINNAME])
   REPLACE_GETLOGIN_R=0;   AC_SUBST([REPLACE_GETLOGIN_R])
diff --git a/modules/fdatasync b/modules/fdatasync
new file mode 100644
index 0000000..94980ec
--- /dev/null
+++ b/modules/fdatasync
@@ -0,0 +1,32 @@
+Description:
+Synchronize data writes to a file.
+
+Files:
+lib/fdatasync.c
+m4/fdatasync.m4
+
+Depends-on:
+extensions
+fsync           [test $HAVE_FDATASYNC = 0]
+unistd
+
+configure.ac:
+gl_FUNC_FDATASYNC
+if test $HAVE_FDATASYNC = 0; then
+  AC_LIBOBJ([fdatasync])
+fi
+gl_UNISTD_MODULE_INDICATOR([fdatasync])
+
+Makefile.am:
+
+Include:
+<unistd.h>
+
+Link:
+$(LIB_FDATASYNC)
+
+License:
+LGPLv2+
+
+Maintainer:
+Paul Eggert, Jim Meyering
diff --git a/modules/unistd b/modules/unistd
index 6c8ea1e..8361608 100644
--- a/modules/unistd
+++ b/modules/unistd
@@ -38,6 +38,7 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
 	      -e 's/@''GNULIB_FACCESSAT''@/$(GNULIB_FACCESSAT)/g' \
 	      -e 's/@''GNULIB_FCHDIR''@/$(GNULIB_FCHDIR)/g' \
 	      -e 's/@''GNULIB_FCHOWNAT''@/$(GNULIB_FCHOWNAT)/g' \
+	      -e 's/@''GNULIB_FDATASYNC''@/$(GNULIB_FDATASYNC)/g' \
 	      -e 's/@''GNULIB_FSYNC''@/$(GNULIB_FSYNC)/g' \
 	      -e 's/@''GNULIB_FTRUNCATE''@/$(GNULIB_FTRUNCATE)/g' \
 	      -e 's/@''GNULIB_GETCWD''@/$(GNULIB_GETCWD)/g' \
@@ -81,6 +82,7 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
 	      -e 's|@''HAVE_FACCESSAT''@|$(HAVE_FACCESSAT)|g' \
 	      -e 's|@''HAVE_FCHDIR''@|$(HAVE_FCHDIR)|g' \
 	      -e 's|@''HAVE_FCHOWNAT''@|$(HAVE_FCHOWNAT)|g' \
+	      -e 's|@''HAVE_FDATASYNC''@|$(HAVE_FDATASYNC)|g' \
 	      -e 's|@''HAVE_FSYNC''@|$(HAVE_FSYNC)|g' \
 	      -e 's|@''HAVE_FTRUNCATE''@|$(HAVE_FTRUNCATE)|g' \
 	      -e 's|@''HAVE_GETDTABLESIZE''@|$(HAVE_GETDTABLESIZE)|g' \
@@ -105,6 +107,7 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
 	      -e 's|@''HAVE_USLEEP''@|$(HAVE_USLEEP)|g' \
 	      -e 's|@''HAVE_DECL_ENVIRON''@|$(HAVE_DECL_ENVIRON)|g' \
 	      -e 's|@''HAVE_DECL_FCHDIR''@|$(HAVE_DECL_FCHDIR)|g' \
+	      -e 's|@''HAVE_DECL_FDATASYNC''@|$(HAVE_DECL_FDATASYNC)|g' \
 	      -e 's|@''HAVE_DECL_GETDOMAINNAME''@|$(HAVE_DECL_GETDOMAINNAME)|g' \
 	      -e 's|@''HAVE_DECL_GETLOGIN_R''@|$(HAVE_DECL_GETLOGIN_R)|g' \
 	      -e 's|@''HAVE_DECL_GETPAGESIZE''@|$(HAVE_DECL_GETPAGESIZE)|g' \
@@ -118,6 +121,7 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
 	      -e 's|@''REPLACE_DUP''@|$(REPLACE_DUP)|g' \
 	      -e 's|@''REPLACE_DUP2''@|$(REPLACE_DUP2)|g' \
 	      -e 's|@''REPLACE_FCHOWNAT''@|$(REPLACE_FCHOWNAT)|g' \
+	      -e 's|@''REPLACE_FDATASYNC''@|$(REPLACE_FDATASYNC)|g' \
 	      -e 's|@''REPLACE_GETCWD''@|$(REPLACE_GETCWD)|g' \
 	      -e 's|@''REPLACE_GETDOMAINNAME''@|$(REPLACE_GETDOMAINNAME)|g' \
 	      -e 's|@''REPLACE_GETLOGIN_R''@|$(REPLACE_GETLOGIN_R)|g' \
-- 
1.7.4.4

>From 68da59ddad1456ff7ddc67a66ef605c3a8888da0 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Fri, 22 Jul 2011 14:02:55 -0700
Subject: [PATCH 2/2] fdatasync-tests: New module

* modules/fdatasync-tests, tests/test-fdatasync.c: New files.
* tests/test-fsync.c (FSYNC): New macro, to let us test fdatasync.
* tests/test-unistd-c++.cc: Add fdatasync test.
---
 ChangeLog                |    5 +++++
 modules/fdatasync-tests  |   13 +++++++++++++
 tests/test-fdatasync.c   |    2 ++
 tests/test-fsync.c       |   10 +++++++---
 tests/test-unistd-c++.cc |    4 ++++
 5 files changed, 31 insertions(+), 3 deletions(-)
 create mode 100644 modules/fdatasync-tests
 create mode 100644 tests/test-fdatasync.c

diff --git a/ChangeLog b/ChangeLog
index 15b0fe5..f089c68 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2011-07-22  Paul Eggert  <[email-masked]>
 
+	fdatasync-tests: New module
+	* modules/fdatasync-tests, tests/test-fdatasync.c: New files.
+	* tests/test-fsync.c (FSYNC): New macro, to let us test fdatasync.
+	* tests/test-unistd-c++.cc: Add fdatasync test.
+
 	fdatasync: New module
 	* MODULES.html.sh: Add it.
 	* doc/posix-functions/fdatasync.texi (fdatasync): Document it.
diff --git a/modules/fdatasync-tests b/modules/fdatasync-tests
new file mode 100644
index 0000000..3862eda
--- /dev/null
+++ b/modules/fdatasync-tests
@@ -0,0 +1,13 @@
+Files:
+tests/test-fdatasync.c
+tests/test-fsync.c
+tests/signature.h
+tests/macros.h
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-fdatasync
+check_PROGRAMS += test-fdatasync
diff --git a/tests/test-fdatasync.c b/tests/test-fdatasync.c
new file mode 100644
index 0000000..90964cc
--- /dev/null
+++ b/tests/test-fdatasync.c
@@ -0,0 +1,2 @@
+#define FSYNC fdatasync
+#include "test-fsync.c"
diff --git a/tests/test-fsync.c b/tests/test-fsync.c
index 2627d0c..6bac01c 100644
--- a/tests/test-fsync.c
+++ b/tests/test-fsync.c
@@ -18,8 +18,12 @@
 
 #include <unistd.h>
 
+#ifndef FSYNC
+# define FSYNC fsync
+#endif
+
 #include "signature.h"
-SIGNATURE_CHECK (fsync, int, (int));
+SIGNATURE_CHECK (FSYNC, int, (int));
 
 #include <errno.h>
 #include <fcntl.h>
@@ -32,7 +36,7 @@ main (void)
   int fd;
   const char *file = "test-fsync.txt";
 
-  if (fsync (0) != 0)
+  if (FSYNC (0) != 0)
     {
       ASSERT (errno == EINVAL /* POSIX */
               || errno == ENOTSUP /* seen on MacOS X 10.5 */
@@ -42,7 +46,7 @@ main (void)
   fd = open (file, O_WRONLY|O_CREAT|O_TRUNC, 0644);
   ASSERT (0 <= fd);
   ASSERT (write (fd, "hello", 5) == 5);
-  ASSERT (fsync (fd) == 0);
+  ASSERT (FSYNC (fd) == 0);
   ASSERT (close (fd) == 0);
   ASSERT (unlink (file) == 0);
 
diff --git a/tests/test-unistd-c++.cc b/tests/test-unistd-c++.cc
index 12e415b..fb7425b 100644
--- a/tests/test-unistd-c++.cc
+++ b/tests/test-unistd-c++.cc
@@ -60,6 +60,10 @@ SIGNATURE_CHECK (GNULIB_NAMESPACE::fchownat, int,
                  (int, char const *, uid_t, gid_t, int));
 #endif
 
+#if GNULIB_TEST_FDATASYNC
+SIGNATURE_CHECK (GNULIB_NAMESPACE::fdatasync, int, (int));
+#endif
+
 #if GNULIB_TEST_FSYNC
 SIGNATURE_CHECK (GNULIB_NAMESPACE::fsync, int, (int));
 #endif
-- 
1.7.4.4