summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xMODULES.html.sh1
-rw-r--r--doc/posix-functions/fsync.texi8
-rw-r--r--lib/fsync.c78
-rw-r--r--lib/unistd.in.h17
-rw-r--r--m4/fsync.m419
-rw-r--r--m4/unistd_h.m42
-rw-r--r--modules/fsync24
-rw-r--r--modules/fsync-tests10
-rw-r--r--modules/unistd2
-rw-r--r--tests/test-fsync.c49
10 files changed, 206 insertions, 4 deletions
diff --git a/MODULES.html.sh b/MODULES.html.sh
index afaf8ba824..058125d83e 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/doc/posix-functions/fsync.texi b/doc/posix-functions/fsync.texi
index 405be40103..fb8821476b 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
+@item
+This function is missing on some platforms:
+mingw.
@end itemize
Portability problems not fixed by Gnulib:
@itemize
-@item
-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 0000000000..4a0fe0f94c
--- /dev/null
+++ b/lib/fsync.c
@@ -0,0 +1,78 @@
+/* Emulate fsync on platforms that 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 <rjones.at.redhat.com>
+
+ 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 General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+#include <unistd.h>
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
+/* _get_osfhandle */
+#include <io.h>
+
+/* FlushFileBuffers */
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include <errno.h>
+
+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 e75b4cdae1..71eaa4d7f9 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
+ <http://www.opengroup.org/susv3xsh/fsync.html>. */
+# if !@HAVE_FSYNC@
+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 !@HAVE_FTRUNCATE@
/* 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 0000000000..eac74097bb
--- /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 0e76a52abe..9e9a56b338 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 0000000000..fa01e9b122
--- /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:
+<unistd.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+Richard W.M. Jones, Jim Meyering
diff --git a/modules/fsync-tests b/modules/fsync-tests
new file mode 100644
index 0000000000..c407dc2cfe
--- /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 94107789dd..efd97b5947 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 0000000000..26219dab44
--- /dev/null
+++ b/tests/test-fsync.c
@@ -0,0 +1,49 @@
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#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;
+}