[glib: 4/6] glocalfile: Check that parent device is the same when trashing



commit 15cdcd2e0b4d18487dc71e3adc85e3bc8090058a
Author: Ondrej Holy <oholy redhat com>
Date:   Fri Jun 8 10:45:56 2018 +0200

    glocalfile: Check that parent device is the same when trashing
    
    To be honest, I am not sure why, but in some special environments (e.g.
    our CI integration) can happen, that file device number is different from
    parent device number. Return "Unable to find or create trash directory for
    %s" error from g_local_file_trash() in that case and also set
    G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH appropriately.

 gio/glocalfile.c     | 26 +++++++++++++++++++++-----
 gio/glocalfileinfo.c |  8 ++++++--
 2 files changed, 27 insertions(+), 7 deletions(-)
---
diff --git a/gio/glocalfile.c b/gio/glocalfile.c
index aff15a982..793118023 100644
--- a/gio/glocalfile.c
+++ b/gio/glocalfile.c
@@ -1677,16 +1677,20 @@ find_mountpoint_for (const char *file,
     }
 }
 
-char *
-_g_local_file_find_topdir_for (const char *file)
+static char *
+_g_local_file_find_topdir_for_internal (const char *file, dev_t file_dev)
 {
   char *dir;
   char *mountpoint = NULL;
   dev_t dir_dev;
 
   dir = get_parent (file, &dir_dev);
-  if (dir == NULL)
-    return NULL;
+  if (dir == NULL || dir_dev != file_dev)
+    {
+      g_free (dir);
+
+      return NULL;
+    }
 
   mountpoint = find_mountpoint_for (dir, dir_dev);
   g_free (dir);
@@ -1694,6 +1698,17 @@ _g_local_file_find_topdir_for (const char *file)
   return mountpoint;
 }
 
+char *
+_g_local_file_find_topdir_for (const char *file)
+{
+  GStatBuf file_stat;
+
+  if (g_lstat (file, &file_stat) != 0)
+    return NULL;
+
+  return _g_local_file_find_topdir_for_internal (file, file_stat.st_dev);
+}
+
 static char *
 get_unique_filename (const char *basename, 
                      int         id)
@@ -1946,7 +1961,8 @@ g_local_file_trash (GFile         *file,
       uid = geteuid ();
       g_snprintf (uid_str, sizeof (uid_str), "%lu", (unsigned long)uid);
 
-      topdir = _g_local_file_find_topdir_for (local->filename);
+      topdir = _g_local_file_find_topdir_for_internal (local->filename,
+                                                       file_stat.st_dev);
       if (topdir == NULL)
        {
           g_set_io_error (error,
diff --git a/gio/glocalfileinfo.c b/gio/glocalfileinfo.c
index df0352a8a..0ebfa15a0 100644
--- a/gio/glocalfileinfo.c
+++ b/gio/glocalfileinfo.c
@@ -924,9 +924,13 @@ get_access_rights (GFileAttributeMatcher *attribute_matcher,
        _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_DELETE,
                                                 writable);
 
+      /* Trashing is supported only if the parent device is the same */
       if (_g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_TRASH))
-        _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_TRASH,
-                                                 writable && parent_info->has_trash_dir);
+        _g_file_info_set_attribute_boolean_by_id (info,
+                                                  G_FILE_ATTRIBUTE_ID_ACCESS_CAN_TRASH,
+                                                  writable &&
+                                                  parent_info->has_trash_dir &&
+                                                  parent_info->device == statbuf->st_dev);
     }
 }
 


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