diff --git a/gtk/updateiconcache.c b/gtk/updateiconcache.c index 3b927011cc..7697a2c3f4 100644 --- a/gtk/updateiconcache.c +++ b/gtk/updateiconcache.c @@ -1424,6 +1424,30 @@ validate_file (const gchar *file) return TRUE; } +/** + * safe_fclose: + * @f: A FILE* stream, must have underlying fd + * + * Unix defaults for data preservation after system crash + * are unspecified, and many systems will eat your data + * in this situation unless you explicitly fsync(). + * + * Returns: %TRUE on success, %FALSE on failure, and will set errno() + */ +static gboolean +safe_fclose (FILE *f) +{ + int fd = fileno (f); + g_assert (fd >= 0); + if (fflush (f) == EOF) + return FALSE; + if (fsync (fd) < 0) + return FALSE; + if (fclose (f) == EOF) + return FALSE; + return TRUE; +} + static void build_cache (const gchar *path) { @@ -1432,7 +1456,6 @@ build_cache (const gchar *path) gchar *bak_cache_path = NULL; #endif GHashTable *files; - gboolean retval; FILE *cache; struct stat path_stat, cache_stat; struct utimbuf utime_buf; @@ -1490,18 +1513,23 @@ opentmp: } /* FIXME: Handle failure */ - retval = write_file (cache, files, directories); - fclose (cache); - - g_list_foreach (directories, (GFunc)g_free, NULL); - g_list_free (directories); - - if (!retval) + if (!write_file (cache, files, directories)) { g_unlink (tmp_cache_path); exit (1); } + if (!safe_fclose (cache)) + { + g_printerr (_("Failed to write cache file: %s\n"), g_strerror (errno)); + g_unlink (tmp_cache_path); + exit (1); + } + cache = NULL; + + g_list_foreach (directories, (GFunc)g_free, NULL); + g_list_free (directories); + if (!validate_file (tmp_cache_path)) { g_printerr (_("The generated cache was invalid.\n"));