From 0d6b17584a7d637ad9482a5ab90915e2698378c6 Mon Sep 17 00:00:00 2001 From: Ondrej Holy Date: Tue, 23 Jun 2020 08:23:16 +0200 Subject: [PATCH 1/2] gunixmounts: Add g_unix_mount_point_at There is already g_unix_mount_at function which allows to find certain unix mount for given mount path. It would be useful to have similar function for mount points, which will allow to replace custom codes in gvfs. Let's add g_unix_mount_point_at. --- docs/reference/gio/gio-sections-common.txt | 1 + gio/gunixmounts.c | 46 ++++++++++++++++++++++ gio/gunixmounts.h | 3 ++ 3 files changed, 50 insertions(+) diff --git a/docs/reference/gio/gio-sections-common.txt b/docs/reference/gio/gio-sections-common.txt index 442b2247b..39999c452 100644 --- a/docs/reference/gio/gio-sections-common.txt +++ b/docs/reference/gio/gio-sections-common.txt @@ -1572,6 +1572,7 @@ g_unix_mount_point_guess_symbolic_icon g_unix_mount_point_guess_name g_unix_mount_point_guess_can_eject g_unix_mount_points_get +g_unix_mount_point_at g_unix_mounts_get g_unix_mount_at g_unix_mount_for diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c index 0d3fa68b0..b0fdfa8c0 100644 --- a/gio/gunixmounts.c +++ b/gio/gunixmounts.c @@ -1660,6 +1660,52 @@ g_unix_mount_points_get (guint64 *time_read) return _g_get_unix_mount_points (); } +/** + * g_unix_mount_point_at: + * @mount_path: (type filename): path for a possible unix mount point. + * @time_read: (out) (optional): guint64 to contain a timestamp. + * + * Gets a #GUnixMountPoint for a given mount path. If @time_read is set, it + * will be filled with a unix timestamp for checking if the mount points have + * changed since with g_unix_mount_points_changed_since(). + * + * If more mount points have the same mount path, the last matching mount point + * is returned. + * + * Returns: (transfer full) (nullable): a #GUnixMountPoint, or %NULL if no match + * is found. + * + * Since: 2.66 + **/ +GUnixMountPoint * +g_unix_mount_point_at (const char *mount_path, + guint64 *time_read) +{ + GList *mount_points, *l; + GUnixMountPoint *mount_point, *found; + + mount_points = g_unix_mount_points_get (time_read); + + found = NULL; + for (l = mount_points; l != NULL; l = l->next) + { + mount_point = l->data; + + if (strcmp (mount_path, mount_point->mount_path) == 0) + { + if (found != NULL) + g_unix_mount_point_free (found); + + found = mount_point; + } + else + g_unix_mount_point_free (mount_point); + } + g_list_free (mount_points); + + return found; +} + /** * g_unix_mounts_changed_since: * @time: guint64 to contain a timestamp. diff --git a/gio/gunixmounts.h b/gio/gunixmounts.h index fe8e24160..2553e1ca1 100644 --- a/gio/gunixmounts.h +++ b/gio/gunixmounts.h @@ -132,6 +132,9 @@ GIcon * g_unix_mount_point_guess_symbolic_icon (GUnixMountPoint *mount GLIB_AVAILABLE_IN_ALL GList * g_unix_mount_points_get (guint64 *time_read); +GLIB_AVAILABLE_IN_2_66 +GUnixMountPoint *g_unix_mount_point_at (const char *mount_path, + guint64 *time_read); GLIB_AVAILABLE_IN_ALL GList * g_unix_mounts_get (guint64 *time_read); GLIB_AVAILABLE_IN_ALL From 4602a5ee17055677a03659f77cabcabffe7ef0fb Mon Sep 17 00:00:00 2001 From: Ondrej Holy Date: Tue, 23 Jun 2020 08:36:26 +0200 Subject: [PATCH 2/2] 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 | 4 +++- gio/glocalfile.c | 61 +++++++++++++++++++++++++++++++++++++----------- 2 files changed, 51 insertions(+), 14 deletions(-) diff --git a/gio/gfile.c b/gio/gfile.c index a2ded14ea..a8d12aa2c 100644 --- a/gio/gfile.c +++ b/gio/gfile.c @@ -4134,7 +4134,9 @@ 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 g_file_trash() support for certain + * mounts, the %G_IO_ERROR_NOT_SUPPORTED error will be returned in that case. * * 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 dc97867e1..4d61663ba 100644 --- a/gio/glocalfile.c +++ b/gio/glocalfile.c @@ -1777,6 +1777,52 @@ 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)) + return TRUE; + + 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; + + 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) { @@ -1787,7 +1833,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)) { @@ -1806,17 +1851,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) && @@ -1982,7 +2023,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); @@ -1996,20 +2036,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 &&