[gvfs] google: Support deleting shared Google Drive files
- From: Ondrej Holy <oholy src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gvfs] google: Support deleting shared Google Drive files
- Date: Thu, 9 May 2019 07:16:18 +0000 (UTC)
commit bc8ac1055355a82bc32819569d048d1495793584
Author: Mayank Sharma <mayank8019 gmail com>
Date: Mon Apr 29 09:40:54 2019 +0530
google: Support deleting shared Google Drive files
`g_file_delete ()` currently fails for shared files with
"Permission denied" error (if they have a different owner and only
one parent folder). This is because `gdata_service_delete_entry ()`
can't be used for files, which have a different owner.
`gdata_documents_service_remove_entry_from_folder ()` has to be used
instead in this case (as well as for cases when the files have
multiple parents).
This fix depends on https://gitlab.gnome.org/GNOME/libgdata/merge_requests/5,
which fixes `gdata_documents_service_remove_entry_from_folder ()`
implementation to make it work for files with only one parent.
Fixes: https://gitlab.gnome.org/GNOME/gvfs/issues/265
daemon/gvfsbackendgoogle.c | 80 +++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 75 insertions(+), 5 deletions(-)
---
diff --git a/daemon/gvfsbackendgoogle.c b/daemon/gvfsbackendgoogle.c
index dfb35503..e60ad510 100644
--- a/daemon/gvfsbackendgoogle.c
+++ b/daemon/gvfsbackendgoogle.c
@@ -356,6 +356,55 @@ get_parent_ids (GVfsBackendGoogle *self,
/* ---------------------------------------------------------------------------------------------------- */
+static gboolean
+is_owner (GVfsBackendGoogle *self,
+ GDataEntry *entry,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GDataFeed *acl_feed;
+ GDataAccessRule *rule;
+ GList *l;
+ GError *local_error = NULL;
+ gboolean ret_val = FALSE;
+
+ acl_feed = gdata_access_handler_get_rules (GDATA_ACCESS_HANDLER (GDATA_DOCUMENTS_ENTRY (entry)),
+ GDATA_SERVICE (self->service),
+ cancellable,
+ NULL,
+ NULL,
+ &local_error);
+
+ if (local_error != NULL)
+ {
+ sanitize_error (&local_error);
+ g_propagate_error (error, local_error);
+
+ goto out;
+ }
+
+ for (l = gdata_feed_get_entries (acl_feed); l != NULL; l = l->next)
+ {
+ const gchar *scope_value, *scope_type, *role;
+ rule = GDATA_ACCESS_RULE (l->data);
+ role = gdata_access_rule_get_role (rule);
+ gdata_access_rule_get_scope (rule, &scope_type, &scope_value);
+
+ if (g_strcmp0 (scope_value, self->account_identity) == 0 &&
+ g_strcmp0 (role, GDATA_DOCUMENTS_ACCESS_ROLE_OWNER) == 0)
+ {
+ ret_val = TRUE;
+ goto out;
+ }
+ }
+
+ out:
+ g_clear_object (&acl_feed);
+ return ret_val;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
static gboolean
insert_entry_full (GVfsBackendGoogle *self,
GDataEntry *entry,
@@ -1304,6 +1353,8 @@ g_vfs_backend_google_delete (GVfsBackend *_self,
GError *error;
gchar *entry_path = NULL;
GList *parent_ids;
+ gboolean owner = FALSE;
+ guint parent_ids_len;
g_rec_mutex_lock (&self->mutex);
g_debug ("+ delete: %s\n", filename);
@@ -1339,11 +1390,26 @@ g_vfs_backend_google_delete (GVfsBackend *_self,
error = NULL;
- /* gdata_documents_service_remove_entry_from_folder seems doesn't work for one parent. */
- parent_ids = get_parent_ids (self, entry);
- if (g_list_length (parent_ids) > 1)
+ owner = is_owner (self, GDATA_ENTRY (entry), cancellable, &error);
+ if (error != NULL)
{
- new_entry = gdata_documents_service_remove_entry_from_folder (self->service, GDATA_DOCUMENTS_ENTRY
(entry), GDATA_DOCUMENTS_FOLDER (parent), cancellable, &error);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ goto out;
+ }
+
+ parent_ids = get_parent_ids (self, entry);
+ parent_ids_len = g_list_length (parent_ids);
+ if (parent_ids_len > 1 || !owner)
+ {
+ /* gdata_documents_service_remove_entry_from_folder () returns the
+ * updated entry variable provided as argument with an increased ref.
+ * The ref count after the next line shall be 2. */
+ new_entry = gdata_documents_service_remove_entry_from_folder (self->service,
+ GDATA_DOCUMENTS_ENTRY (entry),
+ GDATA_DOCUMENTS_FOLDER (parent),
+ cancellable,
+ &error);
}
else
{
@@ -1361,7 +1427,11 @@ g_vfs_backend_google_delete (GVfsBackend *_self,
goto out;
}
- if (new_entry)
+ /* In case of files owned by somebody else, the new entry is returned
+ * even if it had just one parent before the operation. The backend
+ * doesn't care about entries without parents (i.e. entries with
+ * parent_ids_len = 1), so let's ignore it. */
+ if (new_entry && parent_ids_len > 1)
insert_entry (self, GDATA_ENTRY (new_entry));
g_hash_table_foreach (self->monitors, emit_delete_event, entry_path);
g_vfs_job_succeeded (G_VFS_JOB (job));
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]