# HG changeset patch # User Ethan Blanton # Date 1194551352 0 # Node ID 33da7f2a30e4ec8596f0be1b5abb33a21bf62295 # Parent 4886667b0686e565376566e046d3a63df0c9071a Manually fflush() files written with purple_util_write_data_to_file, because apparently some filesystems (XFS) can and will leave bogus file contents if we don't. For systems which don't have fileno(), this involves closing and reopening the file. diff -r 4886667b0686 -r 33da7f2a30e4 configure.ac --- a/configure.ac Tue Nov 06 16:46:04 2007 +0000 +++ b/configure.ac Thu Nov 08 19:49:12 2007 +0000 @@ -233,6 +233,30 @@ dnl FreeBSD doesn't have libdl, dlopen is provided by libc AC_CHECK_FUNC(dlopen, LIBDL="", [AC_CHECK_LIB(dl, dlopen, LIBDL="-ldl")]) +AC_MSG_CHECKING(for fileno()) +AC_TRY_RUN([ +#include + +int main(int argc, char *argv[]) +{ + int fd; + + fd = fileno(stdout); + + return !(fd > 0); +} +], [ + AC_MSG_RESULT(yes) + AC_DEFINE([HAVE_FILENO], [1], + [Define to 1 if your stdio has int fileno(FILE *).]) +], [ + AC_MSG_RESULT(no) +], [ + # Fallback for Cross Compiling... + # This will enable the compatibility code. + AC_MSG_RESULT(no) +]) + AC_MSG_CHECKING(for the %z format string in strftime()) AC_TRY_RUN([ #ifdef HAVE_SYS_TIME_H diff -r 4886667b0686 -r 33da7f2a30e4 libpurple/util.c --- a/libpurple/util.c Tue Nov 06 16:46:04 2007 +0000 +++ b/libpurple/util.c Thu Nov 08 19:49:12 2007 +0000 @@ -2561,6 +2561,9 @@ FILE *file; size_t real_size, byteswritten; struct stat st; +#ifndef HAVE_FILENO + int fd; +#endif purple_debug_info("util", "Writing file %s\n", filename_full); @@ -2595,6 +2598,19 @@ real_size = (size == -1) ? strlen(data) : (size_t) size; byteswritten = fwrite(data, 1, real_size, file); +#ifdef HAVE_FILENO + /* Apparently XFS (and possibly other filesystems) do not + * guarantee that file data is flushed before file metadata, + * so this procedure is insufficient without some flushage. */ + if (fsync(fileno(file)) < 0) { + purple_debug_error("util", "Error syncing file contents for %s: %s\n", + filename_temp, g_strerror(errno)); + g_free(filename_temp); + fclose(file); + return FALSE; + } +#endif + /* Close file */ if (fclose(file) != 0) { @@ -2604,6 +2620,30 @@ return FALSE; } +#ifndef HAVE_FILENO + /* This is the same effect (we hope) as the HAVE_FILENO block + * above, but for systems without fileno(). */ + if ((fd = open(filename_temp, O_RDWR)) < 0) { + purple_debug_error("util", "Error opening file %s for flush: %s\n", + filename_temp, g_strerror(errno)); + g_free(filename_temp); + return FALSE; + } + if (fsync(fd) < 0) { + purple_debug_error("util", "Error syncing %s: %s\n", + filename_temp, g_strerror(errno)); + g_free(filename_temp); + close(fd); + return FALSE; + } + if (close(fd) < 0) { + purple_debug_error("util", "Error closing %s after sync: %s\n", + filename_temp, g_strerror(errno)); + g_free(filename_temp); + return FALSE; + } +#endif + /* Ensure the file is the correct size */ if (byteswritten != real_size) {