diff --git a/ChangeLog b/ChangeLog index 7857208fa3..75dfe443c4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-03-17 Sven Neumann + + * configure.in: check for fsync(). + + * libgimpconfig/gimpconfigwriter.c (gimp_config_writer_close_file): + fsync temporary file if destination file exists. + 2009-03-17 Tor Lillqvist * libgimpconfig/gimpconfigwriter.c diff --git a/configure.in b/configure.in index 32a6f7d8ae..8ed0b8c575 100644 --- a/configure.in +++ b/configure.in @@ -401,8 +401,10 @@ AC_FUNC_VPRINTF AC_FUNC_ALLOCA # check some more funcs +AC_CHECK_FUNCS(fsync) AC_CHECK_FUNCS(difftime mmap) + AM_BINRELOC diff --git a/libgimpconfig/gimpconfigwriter.c b/libgimpconfig/gimpconfigwriter.c index eb642e65a8..9d49c1fd24 100644 --- a/libgimpconfig/gimpconfigwriter.c +++ b/libgimpconfig/gimpconfigwriter.c @@ -664,6 +664,31 @@ gimp_config_writer_close_file (GimpConfigWriter *writer, return FALSE; } +#ifdef HAVE_FSYNC + /* If the final destination exists, we want to sync the newly written + * file to ensure the data is on disk when we rename over the destination. + * otherwise if we get a system crash we can lose both the new and the + * old file on some filesystems. (I.E. those that don't guarantee the + * data is written to the disk before the metadata.) + */ + if (writer->tmpname && g_file_test (writer->filename, G_FILE_TEST_EXISTS)) + { + if (fsync (writer->fd) != 0) + { + g_set_error (error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE, + _("Error writing to temporary file for '%s': %s\n" + "The original file has not been touched."), + gimp_filename_to_utf8 (writer->filename), + g_strerror (errno)); + + close (writer->fd); + g_unlink (writer->tmpname); + + return FALSE; + } + } +#endif + if (close (writer->fd) != 0) { if (writer->tmpname)