[glib/wip/oholy/x-gvfs-notrash: 2/2] gfile: Add support for x-gvfs-notrash option to ignore mounts



commit e0771a64f5e441083843db3671e56824dbf974fc
Author: Ondrej Holy <oholy redhat com>
Date:   Tue Jun 23 08:36:26 2020 +0200

    gfile: Add support for x-gvfs-notrash option to ignore mounts
    
    Add support for x-gvfs-notrash mount option, which allows to disable
    trash functionality for certain mounts. This might be especially useful
    e.g. to prevent trash folder creation on enterprise shares, which are
    also accessed from Windows...
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1096200

 gio/gfile.c      |  3 ++-
 gio/glocalfile.c | 62 ++++++++++++++++++++++++++++++++++++++++++++------------
 2 files changed, 51 insertions(+), 14 deletions(-)
---
diff --git a/gio/gfile.c b/gio/gfile.c
index a2ded14ea..1d39c8fe3 100644
--- a/gio/gfile.c
+++ b/gio/gfile.c
@@ -4134,7 +4134,8 @@ g_file_delete_finish (GFile         *file,
  * Sends @file to the "Trashcan", if possible. This is similar to
  * deleting it, but the user can recover it before emptying the trashcan.
  * Not all file systems support trashing, so this call can return the
- * %G_IO_ERROR_NOT_SUPPORTED error.
+ * %G_IO_ERROR_NOT_SUPPORTED error. Since GLib 2.66, the x-gvfs-notrash unix
+ * mount option can be used to disable trash for certain mounts.
  *
  * If @cancellable is not %NULL, then the operation can be cancelled by
  * triggering the cancellable object from another thread. If the operation
diff --git a/gio/glocalfile.c b/gio/glocalfile.c
index a92c7b28b..9f6a0895f 100644
--- a/gio/glocalfile.c
+++ b/gio/glocalfile.c
@@ -1815,6 +1815,53 @@ try_make_relative (const char *path,
   return g_strdup (path);
 }
 
+static gboolean
+ignore_trash_mount (GUnixMountEntry *mount)
+{
+  GUnixMountPoint *mount_point = NULL;
+  const gchar *mount_options;
+  gboolean retval = TRUE;
+
+  if (g_unix_mount_is_system_internal (mount))
+    goto out;
+
+  mount_options = g_unix_mount_get_options (mount);
+  if (mount_options == NULL)
+    {
+      mount_point = g_unix_mount_point_at (g_unix_mount_get_mount_path (mount),
+                                           NULL);
+      if (mount_point != NULL)
+        mount_options = g_unix_mount_point_get_options (mount_point);
+    }
+
+  if (mount_options == NULL ||
+      strstr (mount_options, "x-gvfs-notrash") == NULL)
+    retval = FALSE;
+
+ out:
+  g_clear_pointer (&mount_point, g_unix_mount_point_free);
+
+  return retval;
+}
+
+static gboolean
+ignore_trash_path (const gchar *topdir)
+{
+  GUnixMountEntry *mount;
+  gboolean retval = TRUE;
+
+  mount = g_unix_mount_at (topdir, NULL);
+  if (mount == NULL)
+    goto out;
+
+  retval = ignore_trash_mount (mount);
+
+ out:
+  g_clear_pointer (&mount, g_unix_mount_free);
+
+  return retval;
+}
+
 gboolean
 _g_local_file_has_trash_dir (const char *dirname, dev_t dir_dev)
 {
@@ -1825,7 +1872,6 @@ _g_local_file_has_trash_dir (const char *dirname, dev_t dir_dev)
   char uid_str[32];
   GStatBuf global_stat, trash_stat;
   gboolean res;
-  GUnixMountEntry *mount;
 
   if (g_once_init_enter (&home_dev_set))
     {
@@ -1844,17 +1890,13 @@ _g_local_file_has_trash_dir (const char *dirname, dev_t dir_dev)
   if (topdir == NULL)
     return FALSE;
 
-  mount = g_unix_mount_at (topdir, NULL);
-  if (mount == NULL || g_unix_mount_is_system_internal (mount))
+  if (ignore_trash_path (topdir))
     {
-      g_clear_pointer (&mount, g_unix_mount_free);
       g_free (topdir);
 
       return FALSE;
     }
 
-  g_clear_pointer (&mount, g_unix_mount_free);
-
   globaldir = g_build_filename (topdir, ".Trash", NULL);
   if (g_lstat (globaldir, &global_stat) == 0 &&
       S_ISDIR (global_stat.st_mode) &&
@@ -2020,7 +2062,6 @@ g_local_file_trash (GFile         *file,
     {
       uid_t uid;
       char uid_str[32];
-      GUnixMountEntry *mount;
 
       uid = geteuid ();
       g_snprintf (uid_str, sizeof (uid_str), "%lu", (unsigned long)uid);
@@ -2034,20 +2075,15 @@ g_local_file_trash (GFile         *file,
          return FALSE;
        }
 
-      mount = g_unix_mount_at (topdir, NULL);
-      if (mount == NULL || g_unix_mount_is_system_internal (mount))
+      if (ignore_trash_path (topdir))
         {
           g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
                        _("Trashing on system internal mounts is not supported"));
-
-          g_clear_pointer (&mount, g_unix_mount_free);
           g_free (topdir);
 
           return FALSE;
         }
 
-      g_clear_pointer (&mount, g_unix_mount_free);
-
       /* Try looking for global trash dir $topdir/.Trash/$uid */
       globaldir = g_build_filename (topdir, ".Trash", NULL);
       if (g_lstat (globaldir, &global_stat) == 0 &&


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