>From a1552e630163ceadd92728ec10339c7411191e33 Mon Sep 17 00:00:00 2001
From: Richard W.M. Jones
Date: Wed, 1 Oct 2008 13:54:44 +0100
Subject: [PATCH] fsync implementation.
---
MODULES.html.sh | 1 +
NEWS | 2 +
doc/posix-functions/fsync.texi | 8 ++--
lib/fsync.c | 82 ++++++++++++++++++++++++++++++++++++++++
lib/unistd.in.h | 17 ++++++++
m4/fsync.m4 | 19 +++++++++
m4/unistd_h.m4 | 2 +
modules/fsync | 24 ++++++++++++
modules/fsync-tests | 10 +++++
modules/unistd | 2 +
tests/test-fsync.c | 48 +++++++++++++++++++++++
11 files changed, 211 insertions(+), 4 deletions(-)
create mode 100644 lib/fsync.c
create mode 100644 m4/fsync.m4
create mode 100644 modules/fsync
create mode 100644 modules/fsync-tests
create mode 100644 tests/test-fsync.c
diff --git a/MODULES.html.sh b/MODULES.html.sh
index afaf8ba..058125d 100755
--- a/MODULES.html.sh
+++ b/MODULES.html.sh
@@ -2110,6 +2110,7 @@ func_all_modules ()
func_module freopen
func_module fseek
func_module fseeko
+ func_module fsync
func_module ftell
func_module ftello
func_module ftruncate
diff --git a/NEWS b/NEWS
index ef04cf4..4c6edfe 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,8 @@ User visible incompatible changes
Date Modules Changes
+2008-10-01 fsync This function has been implemented for Windows.
+
2008-09-28 sockets When using this module, you now need to link with
$(LIBSOCKET).
diff --git a/doc/posix-functions/fsync.texi b/doc/posix-functions/fsync.texi
index 405be40..fb88214 100644
--- a/doc/posix-functions/fsync.texi
+++ b/doc/posix-functions/fsync.texi
@@ -4,15 +4,15 @@
POSIX specification: @url{http://www.opengroup.org/susv3xsh/fsync.html}
-Gnulib module: ---
+Gnulib module: fsync
Portability problems fixed by Gnulib:
@itemize
address@hidden
+This function is missing on some platforms:
+mingw.
@end itemize
Portability problems not fixed by Gnulib:
@itemize
address@hidden
-This function is missing on some platforms:
-mingw.
@end itemize
diff --git a/lib/fsync.c b/lib/fsync.c
new file mode 100644
index 0000000..3848a69
--- /dev/null
+++ b/lib/fsync.c
@@ -0,0 +1,82 @@
+/* Emulate fsync on platforms which lack it, primarily Windows and
+ cross-compilers like MinGW.
+
+ This is derived from sqlite3 sources.
+ http://www.sqlite.org/cvstrac/rlog?f=sqlite/src/os_win.c
+ http://www.sqlite.org/copyright.html
+
+ Written by Richard W.M. Jones
+
+ Copyright (C) 2008
+ 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 Lesser General Public
+ License along with the library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA.
+*/
+
+#include
+#include
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
+/* _get_osfhandle */
+#include
+
+/* FlushFileBuffers */
+#define WIN32_LEAN_AND_MEAN
+#include
+
+#include
+
+int
+fsync (int fd)
+{
+ HANDLE h = (HANDLE) _get_osfhandle (fd);
+ DWORD err;
+
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ if (!FlushFileBuffers (h))
+ {
+ /* Translate some Windows errors into rough approximations of Unix
+ * errors. MSDN is useless as usual - in this case it doesn't
+ * document the full range of errors.
+ */
+ err = GetLastError ();
+ switch (err)
+ {
+ /* eg. Trying to fsync a tty. */
+ case ERROR_INVALID_HANDLE:
+ errno = EINVAL;
+ break;
+
+ default:
+ errno = EIO;
+ }
+ return -1;
+ }
+
+ return 0;
+}
+
+#else /* Windows */
+
+#error "This platform lacks fsync function, and Gnulib doesn't provide a replacement. This is a bug in Gnulib."
+
+#endif /* !Windows */
diff --git a/lib/unistd.in.h b/lib/unistd.in.h
index e75b4cd..71eaa4d 100644
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -140,6 +140,23 @@ extern int dup2 (int, int);
#endif
+#if @GNULIB_FSYNC@
+/* Synchronize changes to a file.
+ Return 0 if successful, otherwise -1 and errno set.
+ See POSIX:2001 specification
+ . */
+# if address@hidden@
+extern int fsync (int fd);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef fsync
+# define fsync(fd) \
+ (GL_LINK_WARNING ("fsync is unportable - " \
+ "use gnulib module fsync for portability"), \
+ fsync (fd))
+#endif
+
+
#if @GNULIB_FTRUNCATE@
# if address@hidden@
/* Change the size of the file to which FD is opened to become equal to LENGTH.
diff --git a/m4/fsync.m4 b/m4/fsync.m4
new file mode 100644
index 0000000..eac7409
--- /dev/null
+++ b/m4/fsync.m4
@@ -0,0 +1,19 @@
+# fsync.m4 serial 1
+dnl Copyright (C) 2008 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_FSYNC],
+[
+ AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+ AC_CHECK_FUNCS_ONCE([fsync])
+ if test $ac_cv_func_fsync = no; then
+ HAVE_FSYNC=0
+ AC_LIBOBJ([fsync])
+ gl_PREREQ_FSYNC
+ fi
+])
+
+# Prerequisites of lib/fsync.c.
+AC_DEFUN([gl_PREREQ_FSYNC], [:])
diff --git a/m4/unistd_h.m4 b/m4/unistd_h.m4
index 0e76a52..9e9a56b 100644
--- a/m4/unistd_h.m4
+++ b/m4/unistd_h.m4
@@ -36,6 +36,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
GNULIB_DUP2=0; AC_SUBST([GNULIB_DUP2])
GNULIB_ENVIRON=0; AC_SUBST([GNULIB_ENVIRON])
GNULIB_FCHDIR=0; AC_SUBST([GNULIB_FCHDIR])
+ GNULIB_FSYNC=0; AC_SUBST([GNULIB_FSYNC])
GNULIB_FTRUNCATE=0; AC_SUBST([GNULIB_FTRUNCATE])
GNULIB_GETCWD=0; AC_SUBST([GNULIB_GETCWD])
GNULIB_GETLOGIN_R=0; AC_SUBST([GNULIB_GETLOGIN_R])
@@ -48,6 +49,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
GNULIB_WRITE=0; AC_SUBST([GNULIB_WRITE])
dnl Assume proper GNU behavior unless another module says otherwise.
HAVE_DUP2=1; AC_SUBST([HAVE_DUP2])
+ HAVE_FSYNC=1; AC_SUBST([HAVE_FSYNC])
HAVE_FTRUNCATE=1; AC_SUBST([HAVE_FTRUNCATE])
HAVE_GETPAGESIZE=1; AC_SUBST([HAVE_GETPAGESIZE])
HAVE_READLINK=1; AC_SUBST([HAVE_READLINK])
diff --git a/modules/fsync b/modules/fsync
new file mode 100644
index 0000000..fa01e9b
--- /dev/null
+++ b/modules/fsync
@@ -0,0 +1,24 @@
+Description:
+fsync(2) function: synchronize writes to a file.
+
+Files:
+lib/fsync.c
+m4/fsync.m4
+
+Depends-on:
+unistd
+
+configure.ac:
+gl_FUNC_FSYNC
+gl_UNISTD_MODULE_INDICATOR([fsync])
+
+Makefile.am:
+
+Include:
+
+
+License:
+LGPLv2+
+
+Maintainer:
+Richard W.M. Jones, Jim Meyering
diff --git a/modules/fsync-tests b/modules/fsync-tests
new file mode 100644
index 0000000..c407dc2
--- /dev/null
+++ b/modules/fsync-tests
@@ -0,0 +1,10 @@
+Files:
+tests/test-fsync.c
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-fsync
+check_PROGRAMS += test-fsync
diff --git a/modules/unistd b/modules/unistd
index 9410778..efd97b5 100644
--- a/modules/unistd
+++ b/modules/unistd
@@ -28,6 +28,7 @@ unistd.h: unistd.in.h
-e 's|@''GNULIB_DUP2''@|$(GNULIB_DUP2)|g' \
-e 's|@''GNULIB_ENVIRON''@|$(GNULIB_ENVIRON)|g' \
-e 's|@''GNULIB_FCHDIR''@|$(GNULIB_FCHDIR)|g' \
+ -e 's|@''GNULIB_FSYNC''@|$(GNULIB_FSYNC)|g' \
-e 's|@''GNULIB_FTRUNCATE''@|$(GNULIB_FTRUNCATE)|g' \
-e 's|@''GNULIB_GETCWD''@|$(GNULIB_GETCWD)|g' \
-e 's|@''GNULIB_GETLOGIN_R''@|$(GNULIB_GETLOGIN_R)|g' \
@@ -39,6 +40,7 @@ unistd.h: unistd.in.h
-e 's|@''GNULIB_UNISTD_H_SIGPIPE''@|$(GNULIB_UNISTD_H_SIGPIPE)|g' \
-e 's|@''GNULIB_WRITE''@|$(GNULIB_WRITE)|g' \
-e 's|@''HAVE_DUP2''@|$(HAVE_DUP2)|g' \
+ -e 's|@''HAVE_FSYNC''@|$(HAVE_FSYNC)|g' \
-e 's|@''HAVE_FTRUNCATE''@|$(HAVE_FTRUNCATE)|g' \
-e 's|@''HAVE_GETPAGESIZE''@|$(HAVE_GETPAGESIZE)|g' \
-e 's|@''HAVE_READLINK''@|$(HAVE_READLINK)|g' \
diff --git a/tests/test-fsync.c b/tests/test-fsync.c
new file mode 100644
index 0000000..fcecf3c
--- /dev/null
+++ b/tests/test-fsync.c
@@ -0,0 +1,48 @@
+/* Test of fsync() function.
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ 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 2 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 . */
+
+#include
+#include
+#include
+
+#define ASSERT(expr) \
+ do \
+ { \
+ if (!(expr)) \
+ { \
+ fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
+ fflush (stderr); \
+ abort (); \
+ } \
+ } \
+ while (0)
+
+int
+main ()
+{
+ int fd;
+ const char *file = "test-fsync.txt";
+
+ ASSERT (fsync (0) != 0);
+ fd = open (file, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+ ASSERT (0 <= fd);
+ ASSERT (write (fd, "hello", 5) == 5);
+ ASSERT (fsync (fd) == 0);
+ ASSERT (close (fd) == 0);
+ ASSERT (unlink (file) == 0);
+
+ return 0;
+}
--
1.6.0.1