[glib/glib-2-46] g_local_file_trash: write info file first



commit 0aae1bf0d2e6e03d91e3f180a060f545175737ac
Author: Ryan Lortie <desrt desrt ca>
Date:   Tue Sep 29 10:16:52 2015 -0400

    g_local_file_trash: write info file first
    
    Recent changes to file monitors removed the delay before events were
    reported.  Among other things, this caused the trash backend of gvfs to
    notice trashed files sooner than before.
    
    On noticing trashed files, the backend tries to read the info file to
    discover (among other things) the original location of the file.
    
    Unfortunately, g_local_file_trash() does a strange dance when trashing a
    file.  It does a loop of open(O_EXCL) in order to file an empty filename
    in the trash to write an info file to, trashes the file, and only then
    writes the contents of the info file.  This means that at the time the
    file is moved to the trash, the info file is an empty stub.
    
    Change the order so that we write out the actual content of the info
    file first.  If the actual trash files then we will unlink the info file
    anyway.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=749314

 gio/glocalfile.c |   51 ++++++++++++++++++++++++++++-----------------------
 1 files changed, 28 insertions(+), 23 deletions(-)
---
diff --git a/gio/glocalfile.c b/gio/glocalfile.c
index 60b9560..2ed6dff 100644
--- a/gio/glocalfile.c
+++ b/gio/glocalfile.c
@@ -2099,6 +2099,34 @@ g_local_file_trash (GFile         *file,
 
   (void) g_close (fd, NULL);
 
+  /* Write the full content of the info file before trashing to make
+   * sure someone doesn't read an empty file.  See #749314
+   */
+
+  /* Use absolute names for homedir */
+  if (is_homedir_trash)
+    original_name = g_strdup (local->filename);
+  else
+    original_name = try_make_relative (local->filename, topdir);
+  original_name_escaped = g_uri_escape_string (original_name, "/", FALSE);
+  
+  g_free (original_name);
+  g_free (topdir);
+  
+  {
+    time_t t;
+    struct tm now;
+    t = time (NULL);
+    localtime_r (&t, &now);
+    delete_time[0] = 0;
+    strftime(delete_time, sizeof (delete_time), "%Y-%m-%dT%H:%M:%S", &now);
+  }
+
+  data = g_strdup_printf ("[Trash Info]\nPath=%s\nDeletionDate=%s\n",
+                         original_name_escaped, delete_time);
+
+  g_file_set_contents (infofile, data, -1, NULL);
+
   /* TODO: Maybe we should verify that you can delete the file from the trash
      before moving it? OTOH, that is hard, as it needs a recursive scan */
 
@@ -2142,29 +2170,6 @@ g_local_file_trash (GFile         *file,
 
   /* TODO: Do we need to update mtime/atime here after the move? */
 
-  /* Use absolute names for homedir */
-  if (is_homedir_trash)
-    original_name = g_strdup (local->filename);
-  else
-    original_name = try_make_relative (local->filename, topdir);
-  original_name_escaped = g_uri_escape_string (original_name, "/", FALSE);
-  
-  g_free (original_name);
-  g_free (topdir);
-  
-  {
-    time_t t;
-    struct tm now;
-    t = time (NULL);
-    localtime_r (&t, &now);
-    delete_time[0] = 0;
-    strftime(delete_time, sizeof (delete_time), "%Y-%m-%dT%H:%M:%S", &now);
-  }
-
-  data = g_strdup_printf ("[Trash Info]\nPath=%s\nDeletionDate=%s\n",
-                         original_name_escaped, delete_time);
-
-  g_file_set_contents (infofile, data, -1, NULL);
   g_free (infofile);
   g_free (data);
   


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