[gtk+/gtk-2-24] iconcache: Ensure we don't lose data on power loss



commit 058ff14ac83821bbc4f9baa84061a7759f5da486
Author: Colin Walters <walters verbum org>
Date:   Fri Nov 19 15:46:51 2010 -0500

    iconcache: Ensure we don't lose data on power loss
    
    fsync() should ensure our data hits disk; since corrupt icon
    caches break all apps, we need to ensure it's valid.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=635307

 gtk/updateiconcache.c |   42 +++++++++++++++++++++++++++++++++++-------
 1 files changed, 35 insertions(+), 7 deletions(-)
---
diff --git a/gtk/updateiconcache.c b/gtk/updateiconcache.c
index 3b92701..09db4cc 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);
+  if (!write_file (cache, files, directories))
+    {
+      g_unlink (tmp_cache_path);
+      exit (1);
+    }
 
-  g_list_foreach (directories, (GFunc)g_free, NULL);
-  g_list_free (directories);
-  
-  if (!retval)
+  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"));



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]