From 15cdcd2e0b4d18487dc71e3adc85e3bc8090058a Mon Sep 17 00:00:00 2001 From: Ondrej Holy Date: Fri, 8 Jun 2018 10:45:56 +0200 Subject: [PATCH] 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); } }