>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