fsync output file before closing
authorPaul Eggert <eggert@cs.ucla.edu>
Tue, 23 Feb 2016 07:21:49 +0000 (23:21 -0800)
committerPaul Eggert <eggert@cs.ucla.edu>
Tue, 23 Feb 2016 07:22:58 +0000 (23:22 -0800)
Problem reported by Yanyan Jiang 蒋炎岩 in: http://bugs.gnu.org/22768
* NEWS: Document this.
* bootstrap.conf (gnulib_modules): Add fsync.
* gzip.c (treat_file): Call fsync just before closing the output.
* lib/.gitignore, m4/.gitignore: Add fsync-related gnulib files.

NEWS
bootstrap.conf
gzip.c
lib/.gitignore
m4/.gitignore

diff --git a/NEWS b/NEWS
index a1c668f77dad62d2f89560d0c918911a21f83ce7..31472cc65da920c5e741d3d4630ac76bd94f41a7 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,10 @@ GNU gzip NEWS                                    -*- outline -*-
 
 ** Changes in behavior
 
+  When acting in-place, gzip now fsyncs the output before closing it.
+  This is slower, but on many file systems it is safer if the system
+  is about to crash.
+
   The GZIP environment variable is now obsolescent; gzip now warns if
   it is used, and rejects attempts to use dangerous options or operands.
   You can use an alias or script instead.
index 13a485dc3cdc5c5d32e4afb6c174c1145755ccae..b15caa335ab4a032747da27df3d3ced6ae548d4c 100644 (file)
@@ -31,6 +31,7 @@ fcntl-safer
 fdl
 fdopendir
 fprintf-posix
+fsync
 getopt-gnu
 git-version-gen
 gitlog-to-changelog
diff --git a/gzip.c b/gzip.c
index a013540c4960609e3dae62f9741afaba4ac00da3..b872383def341073ac31948f5bee6d28faeee772 100644 (file)
--- a/gzip.c
+++ b/gzip.c
@@ -926,8 +926,17 @@ local void treat_file(iname)
 
     if (!to_stdout)
       {
-
         copy_stat (&istat);
+
+        /* Transfer output data to the output file's storage device.
+           Otherwise, if the system crashed now the user might lose
+           both input and output data.  See: Pillai TS et al.  All
+           file systems are not created equal: on the complexity of
+           crafting crash-consistent applications. OSDI'14. 2014:433-48.
+           https://www.usenix.org/conference/osdi14/technical-sessions/presentation/pillai  */
+        if (!keep && fsync (ofd) != 0 && errno != EINVAL)
+          write_error ();
+
         if (close (ofd) != 0)
           write_error ();
 
index 81d94ff91b747e8467999adddabaf7c9c4cefae8..a368a26efa2988ed55fdba3ab05dbda63155c981 100644 (file)
 /xsize.h
 /yesno.c
 /yesno.h
+/fsync.c
index 660b926a3e928d1d3e9e59b1a2e57e66d8342acb..32f5566bda9c98f7da28aa38e6435d8018fd8883 100644 (file)
 /xalloc.m4
 /xsize.m4
 /yesno.m4
+/fsync.m4