aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert <[email protected]>2013-03-13 11:42:22 -0700
committerPaul Eggert <[email protected]>2013-03-13 11:42:22 -0700
commit47d7532e093db8a5068a40c587915121ffaaad18 (patch)
treea99ea6eca34ea0e9c8d6e8a8d6291833ce27dca5
parentc7ffccaf17d63cefd34bef0a9becc4e68df3b115 (diff)
File synchronization fixes.
* admin/CPP-DEFINES (BSD_SYSTEM, HAVE_FSYNC): Remove. * admin/merge-gnulib (GNULIB_MODULES): Add fsync, fdatasync. * configure.ac (BSD_SYSTEM, BSD_SYSTEM_AHB): Remove; no longer needed. (fsync): Remove check; now done by gnulib. * lib/fdatasync.c, lib/fsync.c, m4/fdatasync.m4, m4/fsync.m4: New files, from gnulib. * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate. * lib-src/Makefile.in (LIB_FDATASYNC): New macro. (emacsclient${EXEEXT}): Use it. * lib-src/emacsclient.c (main): Use fdatasync, not fsync, since we don't care about metadata. Keep trying if interrupted. * lib-src/movemail.c (main, popmail): Don't worry about BSD_SYSTEM, since fsync is available everywhere (or there is a substitute). Don't report an error if fsync returns EINVAL. * nt/inc/ms-w32.h (fdatasync): New macro, suggested by Eli Zaretskii. * src/Makefile.in (LIB_FDATASYNC): New macro. (LIBES): Use it. * src/conf_post.h (BSD_SYSTEM, BSD_SYSTEM_AHB): Remove; no longer needed. * src/fileio.c (Fwrite_region, write_region_inhibit_fsync): Don't worry about HAVE_FSYNC, since a substitute fsync is available if the system lacks one. (Fwrite_regin): Retry fsync if interrupted. Fixes: debbugs:13944
-rw-r--r--ChangeLog7
-rw-r--r--admin/CPP-DEFINES2
-rw-r--r--admin/ChangeLog6
-rwxr-xr-xadmin/merge-gnulib3
-rw-r--r--configure.ac36
-rw-r--r--lib-src/ChangeLog9
-rw-r--r--lib-src/Makefile.in4
-rw-r--r--lib-src/emacsclient.c6
-rw-r--r--lib-src/movemail.c17
-rw-r--r--lib/fdatasync.c27
-rw-r--r--lib/fsync.c83
-rw-r--r--lib/gnulib.mk20
-rw-r--r--m4/fdatasync.m432
-rw-r--r--m4/fsync.m417
-rw-r--r--m4/gnulib-comp.m417
-rw-r--r--nt/ChangeLog5
-rw-r--r--nt/inc/ms-w32.h1
-rw-r--r--src/ChangeLog11
-rw-r--r--src/Makefile.in3
-rw-r--r--src/conf_post.h13
-rw-r--r--src/fileio.c17
-rw-r--r--src/filelock.c8
-rw-r--r--src/sysdep.c5
23 files changed, 273 insertions, 76 deletions
diff --git a/ChangeLog b/ChangeLog
index 2ac8ec1de5..2fcd7c7711 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
2013-03-13 Paul Eggert <[email protected]>
+ File synchronization fixes (Bug#13944).
+ * configure.ac (BSD_SYSTEM, BSD_SYSTEM_AHB): Remove; no longer needed.
+ (fsync): Remove check; now done by gnulib.
+ * lib/fdatasync.c, lib/fsync.c, m4/fdatasync.m4, m4/fsync.m4:
+ New files, from gnulib.
+ * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate.
+
Merge from gnulib, incorporating:
2013-03-13 putenv: port to Solaris 10
2013-03-12 mktime: fix configure typo
diff --git a/admin/CPP-DEFINES b/admin/CPP-DEFINES
index da8dec5a0f..c11c3c3b48 100644
--- a/admin/CPP-DEFINES
+++ b/admin/CPP-DEFINES
@@ -9,7 +9,6 @@ documented in config.in, and this file would not be necessary.
AIX
_AIX
-BSD_SYSTEM
CYGWIN Compiling the Cygwin port.
__CYGWIN__ Ditto
GNU_LINUX
@@ -149,7 +148,6 @@ HAVE_FORK
HAVE_FREEIFADDRS
HAVE_FREETYPE
HAVE_FSEEKO
-HAVE_FSYNC
HAVE_FUTIMENS
HAVE_FUTIMES
HAVE_FUTIMESAT
diff --git a/admin/ChangeLog b/admin/ChangeLog
index a0fd90e0d1..fcc339c17c 100644
--- a/admin/ChangeLog
+++ b/admin/ChangeLog
@@ -1,3 +1,9 @@
+2013-03-13 Paul Eggert <[email protected]>
+
+ File synchronization fixes (Bug#13944).
+ * CPP-DEFINES (BSD_SYSTEM, HAVE_FSYNC): Remove.
+ * merge-gnulib (GNULIB_MODULES): Add fsync, fdatasync.
+
2013-03-11 Paul Eggert <[email protected]>
* notes/unicode: Improve notes about Emacs source file encoding.
diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index b43f2bd9bb..100749191f 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -29,7 +29,8 @@ GNULIB_MODULES='
alloca-opt c-ctype c-strcase
careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512
dtoastr dtotimespec dup2 environ execinfo faccessat
- fcntl-h fdopendir filemode fstatat getloadavg getopt-gnu gettime gettimeofday
+ fcntl-h fdatasync fdopendir filemode fstatat fsync
+ getloadavg getopt-gnu gettime gettimeofday
ignore-value intprops largefile lstat
manywarnings memrchr mktime
pselect pthread_sigmask putenv readlink readlinkat
diff --git a/configure.ac b/configure.ac
index aed625e44a..0d1f31032a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2872,7 +2872,7 @@ select getpagesize setlocale \
utimes getrlimit setrlimit shutdown getaddrinfo \
strsignal setitimer \
sendto recvfrom getsockname getpeername getifaddrs freeifaddrs \
-gai_strerror mkstemp getline getdelim fsync sync \
+gai_strerror mkstemp getline getdelim sync \
difftime posix_memalign \
getpwent endpwent getgrent endgrent \
touchlock \
@@ -3774,7 +3774,6 @@ esac
dnl Define symbols to identify the version of Unix this is.
dnl Define all the symbols that apply correctly.
-AH_TEMPLATE(BSD_SYSTEM, [Define if the system is compatible with BSD 4.2.])
AH_TEMPLATE(DOS_NT, [Define if the system is MS DOS or MS Windows.])
AH_TEMPLATE(MSDOS, [Define if the system is MS DOS.])
AH_TEMPLATE(USG, [Define if the system is compatible with System III.])
@@ -3798,30 +3797,12 @@ case $opsys in
;;
darwin)
- dnl BSD4_3 and BSD4_4 are already defined in sys/param.h.
- AC_DEFINE(BSD_SYSTEM, [])
- dnl More specific than the above two. We cannot use __APPLE__ as this
- dnl may not be defined on non-OSX Darwin, and we cannot define DARWIN
- dnl here because Panther and lower CoreFoundation.h uses DARWIN to
+ dnl Not __APPLE__, as this may not be defined on non-OSX Darwin.
+ dnl Not DARWIN, because Panther and lower CoreFoundation.h use DARWIN to
dnl distinguish OS X from pure Darwin.
AC_DEFINE(DARWIN_OS, [], [Define if the system is Darwin.])
;;
- freebsd)
- dnl Hack to avoid calling AC_PREPROC_IFELSE multiple times.
- dnl Would not be needed with autoconf >= 2.67, where the
- dnl preprocessed output is accessible in "conftest.i".
- AC_DEFINE(BSD_SYSTEM_AHB, 1, [Define if AH_BOTTOM should change BSD_SYSTEM.])
- ;;
-
- gnu | netbsd | openbsd )
- AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[
-#ifndef BSD_SYSTEM
-# error "BSD_SYSTEM not defined"
-#endif
- ]], [[]])], [], AC_DEFINE(BSD_SYSTEM, 43) )
- ;;
-
gnu-linux | gnu-kfreebsd )
AC_DEFINE(USG, [])
AC_DEFINE(GNU_LINUX, [], [Define if ths system is compatible with GNU/Linux.])
@@ -4185,15 +4166,8 @@ case "$opsys" in
LD_SWITCH_SYSTEM_TEMACS="-fno-pie -prebind $libs_nsgui -Xlinker -headerpad -Xlinker $headerpad_extra"
## This is here because src/Makefile.in did some extra fiddling around
- ## with LD_SWITCH_SYSTEM. The cpp logic was:
- ## #ifndef LD_SWITCH_SYSTEM
- ## #if !defined (__GNUC__) && ((defined (BSD_SYSTEM) && !defined (COFF)))
- ## Since all the *bsds define LD_SWITCH_SYSTEM, this simplifies to:
- ## not using gcc, darwin.
- ## Because this was done in src/Makefile.in, the resulting part of
- ## LD_SWITCH_SYSTEM was not used in configure (ie, in ac_link).
- ## It therefore seems cleaner to put this in LD_SWITCH_SYSTEM_TEMACS,
- ## rather than LD_SWITCH_SYSTEM.
+ ## with LD_SWITCH_SYSTEM. It seems cleaner to put this in
+ ## LD_SWITCH_SYSTEM_TEMACS instead,
test "x$LD_SWITCH_SYSTEM" = "x" && test "x$GCC" != "xyes" && \
LD_SWITCH_SYSTEM_TEMACS="-X $LD_SWITCH_SYSTEM_TEMACS"
;;
diff --git a/lib-src/ChangeLog b/lib-src/ChangeLog
index 6ecfb283ff..d8ec057942 100644
--- a/lib-src/ChangeLog
+++ b/lib-src/ChangeLog
@@ -1,5 +1,14 @@
2013-03-13 Paul Eggert <[email protected]>
+ File synchronization fixes (Bug#13944).
+ * Makefile.in (LIB_FDATASYNC): New macro.
+ (emacsclient${EXEEXT}): Use it.
+ * emacsclient.c (main): Use fdatasync, not fsync, since we don't
+ care about metadata. Keep trying if interrupted.
+ * movemail.c (main, popmail): Don't worry about BSD_SYSTEM, since
+ fsync is available everywhere (or there is a substitute). Don't
+ report an error if fsync returns EINVAL.
+
Static checking by Sun C 5.12.
* etags.c (analyse_regex): Omit unreachable code.
diff --git a/lib-src/Makefile.in b/lib-src/Makefile.in
index 8a6960ee2f..7069af9767 100644
--- a/lib-src/Makefile.in
+++ b/lib-src/Makefile.in
@@ -161,6 +161,8 @@ LIBRESOLV=@LIBRESOLV@
LIBS_MAIL=@LIBS_MAIL@
## empty or -lrt or -lposix4 if HAVE_CLOCK_GETTIME
LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@
+## empty or -lrt or -lposix4 if HAVE_FDATASYNC
+LIB_FDATASYNC = @LIB_FDATASYNC@
## Extra libraries to use when linking movemail.
LIBS_MOVE = $(LIBS_MAIL) $(KRB4LIB) $(DESLIB) $(KRB5LIB) $(CRYPTOLIB) \
@@ -334,7 +336,7 @@ pop.o: ${srcdir}/pop.c ${srcdir}/../lib/min-max.h $(config_h)
emacsclient${EXEEXT}: ${srcdir}/emacsclient.c $(config_h)
$(CC) ${ALL_CFLAGS} ${srcdir}/emacsclient.c \
-DVERSION="\"${version}\"" \
- $(LOADLIBES) -o emacsclient
+ $(LOADLIBES) $(LIB_FDATASYNC) -o emacsclient
hexl${EXEEXT}: ${srcdir}/hexl.c $(config_h)
$(CC) ${ALL_CFLAGS} ${srcdir}/hexl.c $(LOADLIBES) -o hexl
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c
index 6feaf18ba6..898e8d69b0 100644
--- a/lib-src/emacsclient.c
+++ b/lib-src/emacsclient.c
@@ -1724,7 +1724,8 @@ main (int argc, char **argv)
needlf = 2;
}
fflush (stdout);
- fsync (1);
+ while (fdatasync (1) != 0 && errno == EINTR)
+ continue;
/* Now, wait for an answer and print any messages. */
while (exit_status == EXIT_SUCCESS)
@@ -1825,7 +1826,8 @@ main (int argc, char **argv)
if (needlf)
printf ("\n");
fflush (stdout);
- fsync (1);
+ while (fdatasync (1) != 0 && errno == EINTR)
+ continue;
if (rl < 0)
exit_status = EXIT_FAILURE;
diff --git a/lib-src/movemail.c b/lib-src/movemail.c
index 190937d762..81ac8aa187 100644
--- a/lib-src/movemail.c
+++ b/lib-src/movemail.c
@@ -466,10 +466,8 @@ main (int argc, char **argv)
}
}
-#ifdef BSD_SYSTEM
- if (fsync (outdesc) < 0)
+ if (fsync (outdesc) != 0 && errno != EINVAL)
pfatal_and_delete (outname);
-#endif
/* Prevent symlink attacks truncating other users' mailboxes */
if (setregid (-1, real_gid) < 0)
@@ -750,21 +748,14 @@ popmail (char *mailbox, char *outfile, int preserve, char *password, int reverse
}
}
- /* On AFS, a call to write only modifies the file in the local
- * workstation's AFS cache. The changes are not written to the server
- * until a call to fsync or close is made. Users with AFS home
- * directories have lost mail when over quota because these checks were
- * not made in previous versions of movemail. */
-
-#ifdef BSD_SYSTEM
- if (fsync (mbfi) < 0)
+ if (fsync (mbfi) != 0 && errno != EINVAL)
{
error ("Error in fsync: %s", strerror (errno), 0);
+ close (mbfi);
return EXIT_FAILURE;
}
-#endif
- if (close (mbfi) == -1)
+ if (close (mbfi) != 0)
{
error ("Error in close: %s", strerror (errno), 0);
return EXIT_FAILURE;
diff --git a/lib/fdatasync.c b/lib/fdatasync.c
new file mode 100644
index 0000000000..8f9bf15a52
--- /dev/null
+++ b/lib/fdatasync.c
@@ -0,0 +1,27 @@
+/* Emulate fdatasync on platforms that lack it.
+
+ Copyright (C) 2011-2013 Free Software Foundation, Inc.
+
+ This library 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 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
+ 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>
+
+int
+fdatasync (int fd)
+{
+ /* This does more work than strictly necessary, but is the best we
+ can do portably. */
+ return fsync (fd);
+}
diff --git a/lib/fsync.c b/lib/fsync.c
new file mode 100644
index 0000000000..8a1a975049
--- /dev/null
+++ b/lib/fsync.c
@@ -0,0 +1,83 @@
+/* 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-2013 Free Software Foundation, Inc.
+
+ This library 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 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
+ 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__
+
+/* FlushFileBuffers */
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+
+# include <errno.h>
+
+/* Get _get_osfhandle. */
+# include "msvc-nothrow.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)
+ {
+ case ERROR_ACCESS_DENIED:
+ /* For a read-only handle, fsync should succeed, even though we have
+ no way to sync the access-time changes. */
+ return 0;
+
+ /* 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/gnulib.mk b/lib/gnulib.mk
index c130cbc65b..4b754ec21d 100644
--- a/lib/gnulib.mk
+++ b/lib/gnulib.mk
@@ -21,7 +21,7 @@
# the same distribution terms as the rest of that program.
#
# Generated by gnulib-tool.
-# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=dup --avoid=errno --avoid=fchdir --avoid=fcntl --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=sys_types --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt c-ctype c-strcase careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl-h fdopendir filemode fstatat getloadavg getopt-gnu gettime gettimeofday ignore-value intprops largefile lstat manywarnings memrchr mktime pselect pthread_sigmask putenv readlink readlinkat sig2str socklen stat-time stdalign stdarg stdbool stdio strftime strtoimax strtoumax symlink sys_stat sys_time time timer-time timespec-add timespec-sub unsetenv utimens warnings
+# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=dup --avoid=errno --avoid=fchdir --avoid=fcntl --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=sys_types --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt c-ctype c-strcase careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday ignore-value intprops largefile lstat manywarnings memrchr mktime pselect pthread_sigmask putenv readlink readlinkat sig2str socklen stat-time stdalign stdarg stdbool stdio strftime strtoimax strtoumax symlink sys_stat sys_time time timer-time timespec-add timespec-sub unsetenv utimens warnings
MOSTLYCLEANFILES += core *.stackdump
@@ -297,6 +297,15 @@ EXTRA_DIST += fcntl.in.h
## end gnulib module fcntl-h
+## begin gnulib module fdatasync
+
+
+EXTRA_DIST += fdatasync.c
+
+EXTRA_libgnu_a_SOURCES += fdatasync.c
+
+## end gnulib module fdatasync
+
## begin gnulib module fdopendir
@@ -332,6 +341,15 @@ EXTRA_libgnu_a_SOURCES += at-func.c fstatat.c
## end gnulib module fstatat
+## begin gnulib module fsync
+
+
+EXTRA_DIST += fsync.c
+
+EXTRA_libgnu_a_SOURCES += fsync.c
+
+## end gnulib module fsync
+
## begin gnulib module getgroups
if gl_GNULIB_ENABLED_getgroups
diff --git a/m4/fdatasync.m4 b/m4/fdatasync.m4
new file mode 100644
index 0000000000..551c0d9ff4
--- /dev/null
+++ b/m4/fdatasync.m4
@@ -0,0 +1,32 @@
+# fdatasync.m4 serial 4
+dnl Copyright (C) 2008-2013 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_FDATASYNC],
+[
+ AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+
+ dnl Using AC_CHECK_FUNCS_ONCE would break our subsequent AC_SEARCH_LIBS
+ AC_CHECK_DECLS_ONCE([fdatasync])
+ LIB_FDATASYNC=
+ AC_SUBST([LIB_FDATASYNC])
+
+ if test $ac_cv_have_decl_fdatasync = no; then
+ HAVE_DECL_FDATASYNC=0
+ dnl Mac OS X 10.7 has fdatasync but does not declare it.
+ AC_CHECK_FUNCS([fdatasync])
+ if test $ac_cv_func_fdatasync = no; then
+ HAVE_FDATASYNC=0
+ fi
+ else
+ dnl Solaris <= 2.6 has fdatasync() in libposix4.
+ dnl Solaris 7..10 has it in librt.
+ gl_saved_libs=$LIBS
+ AC_SEARCH_LIBS([fdatasync], [rt posix4],
+ [test "$ac_cv_search_fdatasync" = "none required" ||
+ LIB_FDATASYNC=$ac_cv_search_fdatasync])
+ LIBS=$gl_saved_libs
+ fi
+])
diff --git a/m4/fsync.m4 b/m4/fsync.m4
new file mode 100644
index 0000000000..43f51528d6
--- /dev/null
+++ b/m4/fsync.m4
@@ -0,0 +1,17 @@
+# fsync.m4 serial 2
+dnl Copyright (C) 2008-2013 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
+ fi
+])
+
+# Prerequisites of lib/fsync.c.
+AC_DEFUN([gl_PREREQ_FSYNC], [:])
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index 6c3012d827..d304f10b76 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -63,10 +63,12 @@ AC_DEFUN([gl_EARLY],
# Code from module extern-inline:
# Code from module faccessat:
# Code from module fcntl-h:
+ # Code from module fdatasync:
# Code from module fdopendir:
# Code from module filemode:
# Code from module fpending:
# Code from module fstatat:
+ # Code from module fsync:
# Code from module getgroups:
# Code from module getloadavg:
# Code from module getopt-gnu:
@@ -187,6 +189,11 @@ AC_DEFUN([gl_INIT],
gl_MODULE_INDICATOR([faccessat])
gl_UNISTD_MODULE_INDICATOR([faccessat])
gl_FCNTL_H
+ gl_FUNC_FDATASYNC
+ if test $HAVE_FDATASYNC = 0; then
+ AC_LIBOBJ([fdatasync])
+ fi
+ gl_UNISTD_MODULE_INDICATOR([fdatasync])
gl_FUNC_FDOPENDIR
if test $HAVE_FDOPENDIR = 0 || test $REPLACE_FDOPENDIR = 1; then
AC_LIBOBJ([fdopendir])
@@ -204,6 +211,12 @@ AC_DEFUN([gl_INIT],
AC_LIBOBJ([fstatat])
fi
gl_SYS_STAT_MODULE_INDICATOR([fstatat])
+ gl_FUNC_FSYNC
+ if test $HAVE_FSYNC = 0; then
+ AC_LIBOBJ([fsync])
+ gl_PREREQ_FSYNC
+ fi
+ gl_UNISTD_MODULE_INDICATOR([fsync])
gl_GETLOADAVG
if test $HAVE_GETLOADAVG = 0; then
AC_LIBOBJ([getloadavg])
@@ -743,12 +756,14 @@ AC_DEFUN([gl_FILE_LIST], [
lib/execinfo.in.h
lib/faccessat.c
lib/fcntl.in.h
+ lib/fdatasync.c
lib/fdopendir.c
lib/filemode.c
lib/filemode.h
lib/fpending.c
lib/fpending.h
lib/fstatat.c
+ lib/fsync.c
lib/ftoastr.c
lib/ftoastr.h
lib/getgroups.c
@@ -842,10 +857,12 @@ AC_DEFUN([gl_FILE_LIST], [
m4/faccessat.m4
m4/fcntl-o.m4
m4/fcntl_h.m4
+ m4/fdatasync.m4
m4/fdopendir.m4
m4/filemode.m4
m4/fpending.m4
m4/fstatat.m4
+ m4/fsync.m4
m4/getgroups.m4
m4/getloadavg.m4
m4/getopt.m4
diff --git a/nt/ChangeLog b/nt/ChangeLog
index dcda682cfc..48c1cb8bc8 100644
--- a/nt/ChangeLog
+++ b/nt/ChangeLog
@@ -1,3 +1,8 @@
+2013-03-13 Paul Eggert <[email protected]>
+
+ File synchronization fixes (Bug#13944).
+ * inc/ms-w32.h (fdatasync): New macro, suggested by Eli Zaretskii.
+
2013-03-05 Paul Eggert <[email protected]>
FILE's lock is now always .#FILE and may be a regular file (Bug#13807).
diff --git a/nt/inc/ms-w32.h b/nt/inc/ms-w32.h
index 9473fbe3ca..1240239089 100644
--- a/nt/inc/ms-w32.h
+++ b/nt/inc/ms-w32.h
@@ -220,6 +220,7 @@ extern int sys_unlink (const char *);
/* Map to MSVC names. */
#define execlp _execlp
#define execvp _execvp
+#define fdatasync _commit
#define fdopen _fdopen
#ifndef fileno
#define fileno _fileno
diff --git a/src/ChangeLog b/src/ChangeLog
index ae6fe86f66..d328d0a74c 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,14 @@
+2013-03-13 Paul Eggert <[email protected]>
+
+ File synchronization fixes (Bug#13944).
+ * Makefile.in (LIB_FDATASYNC): New macro.
+ (LIBES): Use it.
+ * conf_post.h (BSD_SYSTEM, BSD_SYSTEM_AHB): Remove; no longer needed.
+ * fileio.c (Fwrite_region, write_region_inhibit_fsync):
+ Don't worry about HAVE_FSYNC, since a substitute fsync is
+ available if the system lacks one.
+ (Fwrite_regin): Retry fsync if interrupted.
+
2013-03-13 Eli Zaretskii <[email protected]>
* w32term.c (w32_read_socket): If we Emacs frame is being
diff --git a/src/Makefile.in b/src/Makefile.in
index b2034a3379..31de9714c6 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -139,6 +139,7 @@ M17N_FLT_LIBS = @M17N_FLT_LIBS@
LIB_CLOCK_GETTIME=@LIB_CLOCK_GETTIME@
LIB_EACCESS=@LIB_EACCESS@
+LIB_FDATASYNC=@LIB_FDATASYNC@
LIB_TIMER_TIME=@LIB_TIMER_TIME@
DBUS_CFLAGS = @DBUS_CFLAGS@
@@ -391,7 +392,7 @@ ALLOBJS = $(VMLIMIT_OBJ) $(obj) $(otherobj)
LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \
$(LIBX_OTHER) $(LIBSOUND) \
$(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_CLOCK_GETTIME) \
- $(LIB_EACCESS) $(LIB_TIMER_TIME) $(DBUS_LIBS) \
+ $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \
$(LIB_EXECINFO) \
$(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \
$(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
diff --git a/src/conf_post.h b/src/conf_post.h
index 6c9747a436..5cb385d902 100644
--- a/src/conf_post.h
+++ b/src/conf_post.h
@@ -44,19 +44,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
# define __has_attribute(a) 0 /* non-clang */
#endif
-/* This silences a few compilation warnings on FreeBSD. */
-#ifdef BSD_SYSTEM_AHB
-#undef BSD_SYSTEM_AHB
-#undef BSD_SYSTEM
-#if __FreeBSD__ == 1
-#define BSD_SYSTEM 199103
-#elif __FreeBSD__ == 2
-#define BSD_SYSTEM 199306
-#elif __FreeBSD__ >= 3
-#define BSD_SYSTEM 199506
-#endif
-#endif
-
#ifdef DARWIN_OS
#ifdef emacs
#define malloc unexec_malloc
diff --git a/src/fileio.c b/src/fileio.c
index 8937f7ca47..724250c8aa 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -4959,20 +4959,23 @@ This calls `write-region-annotate-functions' at the start, and
immediate_quit = 0;
-#ifdef HAVE_FSYNC
/* fsync appears to change the modtime on BSD4.2.
Disk full in NFS may be reported here. */
/* mib says that closing the file will try to write as fast as NFS can do
it, and that means the fsync here is not crucial for autosave files. */
- if (!auto_saving && !write_region_inhibit_fsync && fsync (desc) < 0)
+ if (!auto_saving && !write_region_inhibit_fsync)
{
- /* If fsync fails with EINTR, don't treat that as serious. Also
+ /* Transfer data and metadata to disk, retrying if interrupted. Also,
ignore EINVAL which happens when fsync is not supported on this
file. */
- if (errno != EINTR && errno != EINVAL)
- ok = 0, save_errno = errno;
+ while (fsync (desc) != 0)
+ if (errno != EINTR)
+ {
+ if (errno != EINVAL)
+ ok = 0, save_errno = errno;
+ break;
+ }
}
-#endif
modtime = invalid_emacs_time ();
if (visiting)
@@ -6046,13 +6049,11 @@ in the buffer; this is the default behavior, because the auto-save
file is usually more useful if it contains the deleted text. */);
Vauto_save_include_big_deletions = Qnil;
-#ifdef HAVE_FSYNC
DEFVAR_BOOL ("write-region-inhibit-fsync", write_region_inhibit_fsync,
doc: /* Non-nil means don't call fsync in `write-region'.
This variable affects calls to `write-region' as well as save commands.
A non-nil value may result in data loss! */);
write_region_inhibit_fsync = 0;
-#endif
DEFVAR_BOOL ("delete-by-moving-to-trash", delete_by_moving_to_trash,
doc: /* Specifies whether to use the system's trash can.
diff --git a/src/filelock.c b/src/filelock.c
index 32992896c2..f17d3182ea 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -437,6 +437,14 @@ create_lock_file (char *lfname, char *lock_info_str, bool force)
if (emacs_write (fd, lock_info_str, lock_info_len) != lock_info_len
|| (need_fchmod && fchmod (fd, world_readable) != 0))
err = errno;
+ else
+ while (fsync (fd) != 0)
+ if (errno != EINTR)
+ {
+ if (errno != EINVAL)
+ err = errno;
+ break;
+ }
if (emacs_close (fd) != 0)
err = errno;
if (!err && rename_lock_file (nonce, lfname, force) != 0)
diff --git a/src/sysdep.c b/src/sysdep.c
index b99f179210..bff11fc9f7 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -1289,10 +1289,9 @@ reset_sys_modes (struct tty_display_info *tty_out)
if (tty_out->terminal->reset_terminal_modes_hook)
tty_out->terminal->reset_terminal_modes_hook (tty_out->terminal);
-#ifdef BSD_SYSTEM
/* Avoid possible loss of output when changing terminal modes. */
- fsync (fileno (tty_out->output));
-#endif
+ while (fdatasync (fileno (tty_out->output)) != 0 && errno == EINTR)
+ continue;
#ifndef DOS_NT
#ifdef F_SETOWN