[gvfs/wip/rishi/goa: 4/4] Drive continued ...
- From: Debarshi Ray <debarshir src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gvfs/wip/rishi/goa: 4/4] Drive continued ...
- Date: Fri, 26 Jun 2015 18:15:01 +0000 (UTC)
commit 4ce3516d3395060f2a3c4dc3ebb961ae6e89bdba
Author: Debarshi Ray <debarshir gnome org>
Date: Thu Jun 25 14:09:40 2015 +0200
Drive continued ...
refactor find_root
implement escaping/unescaping of ids
daemon/gvfsbackendgoogle.c | 612 +++++++++++++++++++++++++++++++++++---------
1 files changed, 497 insertions(+), 115 deletions(-)
---
diff --git a/daemon/gvfsbackendgoogle.c b/daemon/gvfsbackendgoogle.c
index 26072a1..c9363d4 100644
--- a/daemon/gvfsbackendgoogle.c
+++ b/daemon/gvfsbackendgoogle.c
@@ -82,6 +82,186 @@ G_DEFINE_TYPE(GVfsBackendGoogle, g_vfs_backend_google, G_VFS_TYPE_BACKEND)
/* ---------------------------------------------------------------------------------------------------- */
+static gchar *
+escape_id (const gchar *id)
+{
+ return g_strconcat ("_", id, NULL);
+}
+
+static gchar *
+escape_filename (const gchar *filename)
+{
+ GString *escaped_filename;
+ gboolean separator_added = FALSE;
+ gchar *basename = NULL;
+ gchar *dirname = NULL;
+ gsize len;
+
+ len = strlen (filename);
+ escaped_filename = g_string_sized_new (len);
+ basename = g_path_get_basename (filename);
+ dirname = g_path_get_dirname (filename);
+
+ while (g_strcmp0 (basename, dirname) != 0)
+ {
+ gchar *escaped_basename;
+ gchar *tmp = NULL;
+
+ escaped_basename = escape_id (basename);
+ g_string_prepend (escaped_filename, escaped_basename);
+ g_string_prepend_c (escaped_filename, G_DIR_SEPARATOR);
+ separator_added = TRUE;
+ g_free (escaped_basename);
+
+ g_free (basename);
+ basename = g_path_get_basename (dirname);
+
+ tmp = dirname;
+ dirname = g_path_get_dirname (dirname);
+ g_free (tmp);
+ }
+
+ if (!separator_added)
+ g_string_prepend_c (escaped_filename, G_DIR_SEPARATOR);
+
+ g_free (basename);
+ g_free (dirname);
+ return g_string_free (escaped_filename, FALSE);
+}
+
+/* Takes a filename as supplied by the application and returns a value
+ * that is either:
+ * (a) guaranteed to be made up of persistent, server-defined IDs, or
+ * (b) can be used to look-up such a persistent filename through the
+ * lookaside cache
+ */
+static gchar *
+unescape_filename (GVfsBackendGoogle *self,
+ const gchar *filename,
+ gboolean *out_is_volatile)
+{
+ GString *unescaped_filename;
+ gboolean is_volatile;
+ gboolean separator_added = FALSE;
+ gchar *basename = NULL;
+ gchar *dirname = NULL;
+ gsize len;
+
+ /* If a path is in the lookaside cache then it is volatile, even if
+ * it looks like /_id10/_id2, and we don't perform the usual
+ * unescaping operation. See the copy job for an explanation.
+ */
+ if (g_hash_table_lookup (self->lookaside, filename) != NULL)
+ {
+ is_volatile = TRUE;
+ unescaped_filename = g_string_new (filename);
+ goto out;
+ }
+ else
+ {
+ is_volatile = FALSE;
+ }
+
+ len = strlen (filename);
+ unescaped_filename = g_string_sized_new (len);
+ basename = g_path_get_basename (filename);
+ dirname = g_path_get_dirname (filename);
+
+ while (g_strcmp0 (basename, dirname) != 0)
+ {
+ const gchar *unescaped_basename;
+ gchar *tmp = NULL;
+
+ if (g_str_has_prefix (basename, "_") && !g_str_has_prefix (basename, "__"))
+ {
+ unescaped_basename = basename + 1;
+ }
+ else
+ {
+ unescaped_basename = basename;
+ is_volatile = TRUE;
+ }
+
+ g_string_prepend (unescaped_filename, unescaped_basename);
+ g_string_prepend_c (unescaped_filename, G_DIR_SEPARATOR);
+ separator_added = TRUE;
+
+ g_free (basename);
+ basename = g_path_get_basename (dirname);
+
+ tmp = dirname;
+ dirname = g_path_get_dirname (dirname);
+ g_free (tmp);
+ }
+
+ if (!separator_added)
+ g_string_prepend_c (unescaped_filename, G_DIR_SEPARATOR);
+
+ out:
+ if (out_is_volatile != NULL)
+ *out_is_volatile = is_volatile;
+ g_free (basename);
+ g_free (dirname);
+ return g_string_free (unescaped_filename, FALSE);
+}
+
+/* Specifically meant for differentiating between /_id1/_id2 and
+ * /_id1/foo when creating a file or directory, and unescaping the
+ * dirname.
+ */
+static gchar *
+unescape_basename_and_map_dirname (GVfsBackendGoogle *self,
+ const gchar *filename,
+ gboolean *out_is_volatile)
+{
+ gboolean is_volatile;
+ gboolean is_dirname_volatile;
+ const gchar *unescaped_basename;
+ gchar *basename = NULL;
+ gchar *dirname = NULL;
+ gchar *ret_val = NULL;
+ gchar *unescaped_dirname = NULL;
+
+ basename = g_path_get_basename (filename);
+ if (g_str_has_prefix (basename, "_") && !g_str_has_prefix (basename, "__"))
+ {
+ unescaped_basename = basename + 1;
+ is_volatile = FALSE;
+ }
+ else
+ {
+ unescaped_basename = basename;
+ is_volatile = TRUE;
+ }
+
+ dirname = g_path_get_dirname (filename);
+ unescaped_dirname = unescape_filename (self, dirname, &is_dirname_volatile);
+ if (is_dirname_volatile)
+ {
+ const gchar *real_dirname;
+
+ real_dirname = g_hash_table_lookup (self->lookaside, unescaped_dirname);
+ if (real_dirname == NULL)
+ goto out;
+
+ g_free (unescaped_dirname);
+ unescaped_dirname = g_strdup (real_dirname);
+ }
+
+ ret_val = g_build_filename (unescaped_dirname, unescaped_basename);
+
+ if (out_is_volatile != NULL)
+ *out_is_volatile = is_volatile;
+
+ out:
+ g_free (unescaped_dirname);
+ g_free (dirname);
+ g_free (basename);
+ return ret_val;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
static void
emit_event_internal (GVfsMonitor *monitor,
const gchar *filename,
@@ -91,7 +271,13 @@ emit_event_internal (GVfsMonitor *monitor,
monitored_path = g_object_get_data (G_OBJECT (monitor), "g-vfs-backend-google-path");
if (g_str_has_prefix (filename, monitored_path))
- g_vfs_monitor_emit_event (monitor, event, filename, NULL);
+ {
+ gchar *escaped_filename = NULL;
+
+ escaped_filename = escape_filename (filename);
+ g_vfs_monitor_emit_event (monitor, event, escaped_filename, NULL);
+ g_free (escaped_filename);
+ }
}
static void
@@ -185,6 +371,7 @@ build_file_info (GVfsBackendGoogle *self,
const gchar *id;
const gchar *name;
const gchar *title;
+ gchar *escaped_name = NULL;
gchar *content_type = NULL;
gchar *copy_name = NULL;
gint64 atime;
@@ -223,15 +410,18 @@ build_file_info (GVfsBackendGoogle *self,
{
const gchar *mount_identity;
const gchar *type;
+ gchar *escaped_filename = NULL;
gchar *target_uri = NULL;
file_type = G_FILE_TYPE_SYMBOLIC_LINK;
type = g_mount_spec_get (spec, "type");
mount_identity = g_mount_spec_get (spec, "goa-identity");
- target_uri = g_strdup_printf ("%s://%s%s", type, mount_identity, filename);
+ escaped_filename = escape_filename (filename);
+ target_uri = g_strdup_printf ("%s://%s%s", type, mount_identity, escaped_filename);
g_file_info_set_symlink_target (info, target_uri);
g_free (target_uri);
+ g_free (escaped_filename);
}
if (content_type != NULL)
@@ -258,10 +448,18 @@ build_file_info (GVfsBackendGoogle *self,
if (is_root)
goto out;
+ id = gdata_entry_get_id (entry);
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILE, id);
+
if (is_symlink)
- name = symlink_name;
+ {
+ name = symlink_name;
+ }
else
- name = gdata_entry_get_id (entry);
+ {
+ escaped_name = escape_id (id);
+ name = escaped_name;
+ }
g_file_info_set_name (info, name);
@@ -289,22 +487,19 @@ build_file_info (GVfsBackendGoogle *self,
if (authors != NULL)
{
GDataAuthor *author = GDATA_AUTHOR (authors->data);
+ const gchar *author_name;
const gchar *email_address;
- const gchar *name;
+
+ author_name = gdata_author_get_name (author);
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER_REAL, author_name);
email_address = gdata_author_get_email_address (author);
g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER, email_address);
-
- name = gdata_author_get_name (author);
- g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER_REAL, name);
}
etag = gdata_entry_get_etag (entry);
g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_ETAG_VALUE, etag);
- id = gdata_entry_get_id (entry);
- g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILE, id);
-
if (!is_folder)
{
const gchar *thumbnail_uri;
@@ -322,11 +517,32 @@ build_file_info (GVfsBackendGoogle *self,
out:
g_free (copy_name);
+ g_free (escaped_name);
g_free (content_type);
}
/* ---------------------------------------------------------------------------------------------------- */
+static void
+find_root (GVfsBackendGoogle *self, GCancellable *cancellable, GError **error)
+{
+ GDataAuthorizationDomain *auth_domain;
+
+ if (self->root != NULL)
+ return;
+
+ auth_domain = gdata_documents_service_get_primary_authorization_domain ();
+ self->root = gdata_service_query_single_entry (GDATA_SERVICE (self->service),
+ auth_domain,
+ "root",
+ NULL,
+ GDATA_TYPE_DOCUMENTS_FOLDER,
+ cancellable,
+ error);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
static gchar *
get_parent_id (GDataEntry *entry)
{
@@ -370,7 +586,7 @@ get_entry_path (GVfsBackendGoogle *self, GDataEntry *entry)
base_id = gdata_entry_get_id (entry);
path = g_string_new (base_id);
- path = g_string_prepend_c (path, '/');
+ g_string_prepend_c (path, '/');
id = get_parent_id (entry);
root_id = gdata_entry_get_id (self->root);
@@ -391,8 +607,8 @@ get_entry_path (GVfsBackendGoogle *self, GDataEntry *entry)
if (parent_entry == NULL)
goto out;
- path = g_string_prepend (path, id);
- path = g_string_prepend_c (path, '/');
+ g_string_prepend (path, id);
+ g_string_prepend_c (path, '/');
g_free (id);
id = get_parent_id (parent_entry);
@@ -455,25 +671,12 @@ rebuild_entries (GVfsBackendGoogle *self,
GError *local_error;
gboolean succeeded_once = FALSE;
- if (self->root == NULL)
+ local_error = NULL;
+ find_root (self, cancellable, &local_error);
+ if (local_error != NULL)
{
- GDataAuthorizationDomain *auth_domain;
-
- auth_domain = gdata_documents_service_get_primary_authorization_domain ();
-
- local_error = NULL;
- self->root = gdata_service_query_single_entry (GDATA_SERVICE (self->service),
- auth_domain,
- "root",
- NULL,
- GDATA_TYPE_DOCUMENTS_FOLDER,
- cancellable,
- &local_error);
- if (local_error != NULL)
- {
- g_propagate_error (error, local_error);
- goto out;
- }
+ g_propagate_error (error, local_error);
+ goto out;
}
query = gdata_documents_query_new_with_limits (NULL, 1, MAX_RESULTS);
@@ -601,6 +804,7 @@ g_vfs_backend_google_copy (GVfsBackend *_self,
GError *error;
gboolean is_folder;
gboolean is_root;
+ gboolean is_volatile_source;
const gchar *id;
const gchar *real_destination_parent_path;
const gchar *real_parent_path;
@@ -609,27 +813,54 @@ g_vfs_backend_google_copy (GVfsBackend *_self,
gchar *destination_parent_path = NULL;
gchar *path = NULL;
gchar *source_id = NULL;
+ gchar *unescaped_destination = NULL;
+ gchar *unescaped_source = NULL;
+
+ /* The destination is always volatile. Even in the best case, it
+ * will look like /_id1/_id2 -> /_id10/_id2, whereas in reality it
+ * will be /_id1/_id2 -> /_id10/_id20. This will confuse our
+ * escaping logic when /_id10/_id2 is passed to a any subsequent
+ * job, and make it think that it is a non-volatile path. Hence, we
+ * add /_id10/_id2 to the lookaside cache at the end of the
+ * copy so that subsequent jobs can recognize it as a volatile path.
+ */
g_rec_mutex_lock (&self->mutex);
- g_debug ("+ copy: %s -> %s\n", source, destination);
+ unescaped_destination = unescape_filename (self, destination, NULL);
+ unescaped_source = unescape_filename (self, source, &is_volatile_source);
+ g_debug ("+ copy: %s (%s, %d) -> %s (%s, 1)\n",
+ source,
+ unescaped_source,
+ is_volatile_source,
+ destination,
+ unescaped_destination);
+ source = unescaped_source;
- real_source = g_hash_table_lookup (self->lookaside, source);
- if (real_source != NULL)
- source = real_source;
-
- source_id = g_path_get_basename (source);
- source_entry = g_hash_table_lookup (self->entries, source_id);
- is_folder_or_root (source, source_entry, &is_folder, NULL);
- if (is_folder)
+ error = NULL;
+ find_root (self, cancellable, &error);
+ if (error != NULL)
{
- g_vfs_job_failed (G_VFS_JOB (job),
- G_IO_ERROR,
- G_IO_ERROR_WOULD_RECURSE,
- _("Can't recursively copy directory"));
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
goto out;
}
- destination_parent_path = g_path_get_dirname (destination);
+ if (is_volatile_source)
+ {
+ real_source = g_hash_table_lookup (self->lookaside, source);
+ if (real_source == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file or
directory"));
+ goto out;
+ }
+
+ source = real_source;
+ }
+
+ source_id = g_path_get_basename (source);
+ source_entry = g_hash_table_lookup (self->entries, source_id);
+
+ destination_parent_path = g_path_get_dirname (unescaped_destination);
real_destination_parent_path = g_hash_table_lookup (self->lookaside, destination_parent_path);
if (real_destination_parent_path != NULL)
{
@@ -646,27 +877,38 @@ g_vfs_backend_google_copy (GVfsBackend *_self,
{
destination_parent_id = g_path_get_basename (destination_parent_path);
destination_parent = g_hash_table_lookup (self->entries, destination_parent_id);
+ }
- if (destination_parent == NULL)
+ if (source_entry == NULL || destination_parent == NULL)
+ {
+ error = NULL;
+ rebuild_entries (self, cancellable, &error);
+ if (error != NULL)
{
- error = NULL;
- rebuild_entries (self, cancellable, &error);
- if (error != NULL)
- {
- g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
- g_error_free (error);
- goto out;
- }
-
- destination_parent = g_hash_table_lookup (self->entries, destination_parent_id);
- if (destination_parent == NULL)
- {
- g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file or
directory"));
- goto out;
- }
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ goto out;
}
}
+ source_entry = g_hash_table_lookup (self->entries, source_id);
+ is_folder_or_root (source, source_entry, &is_folder, NULL);
+ if (is_folder)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR,
+ G_IO_ERROR_WOULD_RECURSE,
+ _("Can't recursively copy directory"));
+ goto out;
+ }
+
+ destination_parent = g_hash_table_lookup (self->entries, destination_parent_id);
+ if (source_entry == NULL || destination_parent == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file or directory"));
+ goto out;
+ }
+
error = NULL;
new_entry = gdata_documents_service_add_entry_to_folder (self->service,
GDATA_DOCUMENTS_ENTRY (source_entry),
@@ -686,6 +928,7 @@ g_vfs_backend_google_copy (GVfsBackend *_self,
path = get_entry_path (self, GDATA_ENTRY (new_entry));
if (path != NULL)
{
+ g_debug (" insert lookaside: %s -> %s\n", destination, path);
g_hash_table_insert (self->lookaside, g_strdup (destination), g_strdup (path));
g_hash_table_foreach (self->monitors, emit_create_event, (gpointer) path);
}
@@ -700,6 +943,8 @@ g_vfs_backend_google_copy (GVfsBackend *_self,
g_free (destination_parent_id);
g_free (destination_parent_path);
g_free (source_id);
+ g_free (unescaped_source);
+ g_free (unescaped_destination);
g_debug ("- copy\n");
g_rec_mutex_unlock (&self->mutex);
}
@@ -719,9 +964,28 @@ g_vfs_backend_google_create_dir_monitor (GVfsBackend *_self,
GVfsMonitor *monitor = NULL;
gboolean is_folder;
gboolean is_root;
+ gboolean is_volatile;
gchar *id = NULL;
+ gchar *unescaped_filename = NULL;
g_rec_mutex_lock (&self->mutex);
+ unescaped_filename = unescape_filename (self, filename, &is_volatile);
+ g_debug ("+ create_dir_monitor: %s (%s, %d)\n", filename, unescaped_filename, is_volatile);
+ filename = unescaped_filename;
+
+ if (is_volatile)
+ {
+ const gchar *real_filename;
+
+ real_filename = g_hash_table_lookup (self->lookaside, filename);
+ if (real_filename == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file or
directory"));
+ goto out;
+ }
+
+ filename = real_filename;
+ }
id = g_path_get_basename (filename);
entry = g_hash_table_lookup (self->entries, id);
@@ -763,6 +1027,8 @@ g_vfs_backend_google_create_dir_monitor (GVfsBackend *_self,
out:
g_clear_object (&monitor);
g_free (id);
+ g_free (unescaped_filename);
+ g_debug ("- create_dir_monitor\n");
g_rec_mutex_unlock (&self->mutex);
return TRUE;
}
@@ -780,16 +1046,29 @@ g_vfs_backend_google_delete (GVfsBackend *_self,
GDataEntry *entry;
GError *error;
gboolean is_root;
- const gchar *real_filename;
+ gboolean is_volatile;
gchar *path = NULL;
gchar *id = NULL;
+ gchar *unescaped_filename = NULL;
g_rec_mutex_lock (&self->mutex);
- g_debug ("+ delete: %s\n", filename);
+ unescaped_filename = unescape_filename (self, filename, &is_volatile);
+ g_debug ("+ delete: %s (%s, %d)\n", filename, unescaped_filename, is_volatile);
+ filename = unescaped_filename;
- real_filename = g_hash_table_lookup (self->lookaside, filename);
- if (real_filename != NULL)
- filename = real_filename;
+ if (is_volatile)
+ {
+ const gchar *real_filename;
+
+ real_filename = g_hash_table_lookup (self->lookaside, filename);
+ if (real_filename == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file or
directory"));
+ goto out;
+ }
+
+ filename = real_filename;
+ }
is_folder_or_root (filename, NULL, NULL, &is_root);
if (is_root)
@@ -845,6 +1124,7 @@ g_vfs_backend_google_delete (GVfsBackend *_self,
out:
g_free (path);
g_free (id);
+ g_free (unescaped_filename);
g_debug ("- delete\n");
g_rec_mutex_unlock (&self->mutex);
}
@@ -874,9 +1154,27 @@ g_vfs_backend_google_enumerate (GVfsBackend *_self,
GDataEntry *entry;
GError *error;
GHashTableIter iter;
+ gboolean is_volatile;
+ gchar *unescaped_filename = NULL;
g_rec_mutex_lock (&self->mutex);
- g_debug ("+ enumerate: %s\n", filename);
+ unescaped_filename = unescape_filename (self, filename, &is_volatile);
+ g_debug ("+ enumerate: %s (%s, %d)\n", filename, unescaped_filename, is_volatile);
+ filename = unescaped_filename;
+
+ if (is_volatile)
+ {
+ const gchar *real_filename;
+
+ real_filename = g_hash_table_lookup (self->lookaside, filename);
+ if (real_filename == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file or
directory"));
+ goto out;
+ }
+
+ filename = real_filename;
+ }
if (self->entries_stale_timeout == 0)
{
@@ -933,6 +1231,7 @@ g_vfs_backend_google_enumerate (GVfsBackend *_self,
g_vfs_job_enumerate_done (job);
out:
+ g_free (unescaped_filename);
g_debug ("- enumerate\n");
g_rec_mutex_unlock (&self->mutex);
}
@@ -949,19 +1248,31 @@ g_vfs_backend_google_make_directory (GVfsBackend *_self,
GDataDocumentsEntry *new_entry = NULL;
GDataDocumentsFolder *folder = NULL;
GDataDocumentsFolder *parent;
+ GDataEntry *source_entry = NULL;
GError *error;
+ gboolean is_display_name;
gboolean is_root;
+ gboolean needs_rebuild = FALSE;
const gchar *id;
const gchar *real_parent_path;
gchar *parent_id = NULL;
gchar *parent_path = NULL;
gchar *path = NULL;
+ gchar *source_id = NULL;
gchar *title = NULL;
+ gchar *unescaped_filename = NULL;
g_rec_mutex_lock (&self->mutex);
- g_debug ("+ make_directory: %s\n", filename);
+ unescaped_filename = unescape_basename_and_map_dirname (self, filename, &is_display_name);
+ g_debug ("+ make_directory: %s (%s, %d)\n", filename, unescaped_filename, is_display_name);
- is_folder_or_root (filename, NULL, NULL, &is_root);
+ if (unescaped_filename == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file or directory"));
+ goto out;
+ }
+
+ is_folder_or_root (unescaped_filename, NULL, NULL, &is_root);
if (is_root)
{
g_vfs_job_failed (G_VFS_JOB (job),
@@ -971,14 +1282,23 @@ g_vfs_backend_google_make_directory (GVfsBackend *_self,
goto out;
}
- parent_path = g_path_get_dirname (filename);
- real_parent_path = g_hash_table_lookup (self->lookaside, parent_path);
- if (real_parent_path != NULL)
+ error = NULL;
+ find_root (self, cancellable, &error);
+ if (error != NULL)
{
- g_free (parent_path);
- parent_path = g_strdup (real_parent_path);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ goto out;
}
+ parent_path = g_path_get_dirname (unescaped_filename);
+ /* real_parent_path = g_hash_table_lookup (self->lookaside, parent_path); */
+ /* if (real_parent_path != NULL) */
+ /* { */
+ /* g_free (parent_path); */
+ /* parent_path = g_strdup (real_parent_path); */
+ /* } */
+
is_folder_or_root (parent_path, NULL, NULL, &is_root);
if (is_root)
{
@@ -988,29 +1308,54 @@ g_vfs_backend_google_make_directory (GVfsBackend *_self,
{
parent_id = g_path_get_basename (parent_path);
parent = g_hash_table_lookup (self->entries, parent_id);
-
if (parent == NULL)
+ needs_rebuild = TRUE;
+ }
+
+ if (is_display_name)
+ {
+ title = g_path_get_basename (unescaped_filename);
+ }
+ else
+ {
+ source_id = g_path_get_basename (unescaped_filename);
+ source_entry = g_hash_table_lookup (self->entries, source_id);
+ if (source_entry == NULL)
+ needs_rebuild = TRUE;
+ }
+
+ if (needs_rebuild)
+ {
+ error = NULL;
+ rebuild_entries (self, cancellable, &error);
+ if (error != NULL)
{
- error = NULL;
- rebuild_entries (self, cancellable, &error);
- if (error != NULL)
- {
- g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
- g_error_free (error);
- goto out;
- }
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ goto out;
+ }
+ }
- parent = g_hash_table_lookup (self->entries, parent_id);
- if (parent == NULL)
- {
- g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file or
directory"));
- goto out;
- }
+ parent = g_hash_table_lookup (self->entries, parent_id);
+ if (parent == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file or directory"));
+ goto out;
+ }
+
+ if (!is_display_name)
+ {
+ source_entry = g_hash_table_lookup (self->entries, source_id);
+ if (source_entry == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file or
directory"));
+ goto out;
}
+
+ title = g_strdup (gdata_entry_get_title (source_entry));
}
folder = gdata_documents_folder_new (NULL);
- title = g_path_get_basename (filename);
gdata_entry_set_title (GDATA_ENTRY (folder), title);
error = NULL;
@@ -1030,6 +1375,7 @@ g_vfs_backend_google_make_directory (GVfsBackend *_self,
g_hash_table_insert (self->entries, g_strdup (id), g_object_ref (new_entry));
path = get_entry_path (self, GDATA_ENTRY (new_entry));
+ g_debug (" insert lookaside: %s -> %s\n", filename, path);
g_hash_table_insert (self->lookaside, g_strdup (filename), g_strdup (path));
self->entries_stale = TRUE;
@@ -1040,10 +1386,12 @@ g_vfs_backend_google_make_directory (GVfsBackend *_self,
out:
g_clear_object (&new_entry);
g_clear_object (&folder);
+ g_free (source_id);
g_free (parent_id);
g_free (parent_path);
g_free (path);
g_free (title);
+ g_free (unescaped_filename);
g_debug ("- make_directory\n");
g_rec_mutex_unlock (&self->mutex);
}
@@ -1147,16 +1495,29 @@ g_vfs_backend_google_open_for_read (GVfsBackend *_self,
GError *error;
gboolean is_folder;
gboolean is_root;
- const gchar *real_filename;
+ gboolean is_volatile;
gchar *content_type = NULL;
gchar *id = NULL;
+ gchar *unescaped_filename = NULL;
g_rec_mutex_lock (&self->mutex);
- g_debug ("+ open_for_read: %s\n", filename);
+ unescaped_filename = unescape_filename (self, filename, &is_volatile);
+ g_debug ("+ open_for_read: %s (%s, %d)\n", filename, unescaped_filename, is_volatile);
+ filename = unescaped_filename;
+
+ if (is_volatile)
+ {
+ const gchar *real_filename;
+
+ real_filename = g_hash_table_lookup (self->lookaside, filename);
+ if (real_filename == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file or
directory"));
+ goto out;
+ }
- real_filename = g_hash_table_lookup (self->lookaside, filename);
- if (real_filename != NULL)
- filename = real_filename;
+ filename = real_filename;
+ }
id = g_path_get_basename (filename);
entry = g_hash_table_lookup (self->entries, id);
@@ -1244,6 +1605,7 @@ g_vfs_backend_google_open_for_read (GVfsBackend *_self,
out:
g_free (content_type);
g_free (id);
+ g_free (unescaped_filename);
g_debug ("- open_for_read\n");
g_rec_mutex_unlock (&self->mutex);
}
@@ -1428,6 +1790,7 @@ g_vfs_backend_google_push (GVfsBackend *_self,
g_hash_table_insert (self->entries, g_strdup (id), g_object_ref (new_document));
path = get_entry_path (self, GDATA_ENTRY (new_document));
+ g_debug (" insert lookaside: %s -> %s\n", destination, path);
g_hash_table_insert (self->lookaside, g_strdup (destination), g_strdup (path));
self->entries_stale = TRUE;
@@ -1492,16 +1855,27 @@ g_vfs_backend_google_query_info (GVfsBackend *_self,
GError *error;
gboolean is_root;
gboolean is_symlink = FALSE;
- const gchar *real_filename;
+ gboolean is_volatile;
gchar *id = NULL;
gchar *symlink_name = NULL;
+ gchar *unescaped_filename = NULL;
g_rec_mutex_lock (&self->mutex);
- g_debug ("+ query_info: %s, %d\n", filename, flags);
+ unescaped_filename = unescape_filename (self, filename, &is_volatile);
+ g_debug ("+ query_info: %s (%s, %d), %d\n", filename, unescaped_filename, is_volatile, flags);
+ filename = unescaped_filename;
- real_filename = g_hash_table_lookup (self->lookaside, filename);
- if (real_filename != NULL)
+ if (is_volatile)
{
+ const gchar *real_filename;
+
+ real_filename = g_hash_table_lookup (self->lookaside, filename);
+ if (real_filename == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file or
directory"));
+ goto out;
+ }
+
filename = real_filename;
if ((flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS) != 0)
{
@@ -1542,6 +1916,7 @@ g_vfs_backend_google_query_info (GVfsBackend *_self,
out:
g_free (id);
g_free (symlink_name);
+ g_free (unescaped_filename);
g_debug ("- query_info\n");
g_rec_mutex_unlock (&self->mutex);
}
@@ -1636,19 +2011,31 @@ g_vfs_backend_google_set_display_name (GVfsBackend *_self,
GDataEntry *new_entry = NULL;
GError *error;
gboolean is_root;
+ gboolean is_volatile;
const gchar *new_id;
- const gchar *real_filename;
gchar *id = NULL;
- gchar *path = NULL;
+ gchar *unescaped_filename = NULL;
g_rec_mutex_lock (&self->mutex);
- g_debug ("+ set_display_name: %s, %s\n", filename, display_name);
+ unescaped_filename = unescape_filename (self, filename, &is_volatile);
+ g_debug ("+ set_display_name: %s (%s, %d), %s\n", filename, unescaped_filename, is_volatile, display_name);
- real_filename = g_hash_table_lookup (self->lookaside, filename);
- if (real_filename != NULL)
- filename = real_filename;
+ if (is_volatile)
+ {
+ const gchar *real_filename;
- is_folder_or_root (filename, NULL, NULL, &is_root);
+ real_filename = g_hash_table_lookup (self->lookaside, unescaped_filename);
+ if (real_filename == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file or
directory"));
+ goto out;
+ }
+
+ g_free (unescaped_filename);
+ unescaped_filename = g_strdup (real_filename);
+ }
+
+ is_folder_or_root (unescaped_filename, NULL, NULL, &is_root);
if (is_root)
{
g_vfs_job_failed (G_VFS_JOB (job),
@@ -1658,7 +2045,7 @@ g_vfs_backend_google_set_display_name (GVfsBackend *_self,
goto out;
}
- id = g_path_get_basename (filename);
+ id = g_path_get_basename (unescaped_filename);
entry = g_hash_table_lookup (self->entries, id);
if (entry == NULL)
@@ -1681,7 +2068,6 @@ g_vfs_backend_google_set_display_name (GVfsBackend *_self,
}
gdata_entry_set_title (entry, display_name);
-
auth_domain = gdata_documents_service_get_primary_authorization_domain ();
error = NULL;
@@ -1698,17 +2084,13 @@ g_vfs_backend_google_set_display_name (GVfsBackend *_self,
new_id = gdata_entry_get_id (new_entry);
g_hash_table_insert (self->entries, g_strdup (new_id), g_object_ref (new_entry));
- path = get_entry_path (self, new_entry);
- g_vfs_job_set_display_name_set_new_path (job, path);
-
- g_warn_if_fail (g_strcmp0 (filename, path) == 0);
-
+ g_vfs_job_set_display_name_set_new_path (job, filename);
g_vfs_job_succeeded (G_VFS_JOB (job));
out:
g_clear_object (&new_entry);
g_free (id);
- g_free (path);
+ g_free (unescaped_filename);
g_debug ("- set_display_name\n");
g_rec_mutex_unlock (&self->mutex);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]