diff options
author | Christian Kellner <gicmo@src.gnome.org> | 2008-09-24 12:46:09 +0000 |
---|---|---|
committer | Christian Kellner <gicmo@src.gnome.org> | 2008-09-24 12:46:09 +0000 |
commit | d01d71d8f36809983b174f0b7d62d20bedf33a74 (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /gnome-2-24/client | |
parent | 953132a87aed73507042a6279b343523741a1800 (diff) | |
download | gvfs-GVFS_1_0_1_svn2027.tar.gz |
Wrong branchGVFS_1_0_1_svn2027
svn path=/tags/GVFS_1_0_1; revision=2026
Diffstat (limited to 'gnome-2-24/client')
28 files changed, 0 insertions, 13442 deletions
diff --git a/gnome-2-24/client/.gitignore b/gnome-2-24/client/.gitignore deleted file mode 100644 index b185be91..00000000 --- a/gnome-2-24/client/.gitignore +++ /dev/null @@ -1 +0,0 @@ -gvfs-fuse-daemon diff --git a/gnome-2-24/client/Makefile.am b/gnome-2-24/client/Makefile.am deleted file mode 100644 index 274d9fd3..00000000 --- a/gnome-2-24/client/Makefile.am +++ /dev/null @@ -1,81 +0,0 @@ -NULL = - -INCLUDES = -I$(top_srcdir) \ - -I$(top_srcdir)/client \ - -I$(top_srcdir)/common \ - $(GLIB_CFLAGS) $(DBUS_CFLAGS) \ - -DG_LOG_DOMAIN=\"GVFS\" -DG_DISABLE_DEPRECATED \ - -DGVFS_MODULE_DIR=\"$(libdir)/gvfs/modules\" \ - -DGVFS_LOCALEDIR=\""$(localedir)"\" \ - -DDBUS_API_SUBJECT_TO_CHANGE - -module_flags = -export_dynamic -avoid-version -module -no-undefined -export-symbols-regex '^g_vfs_.*|g_io_module_load|g_io_module_unload' - -## Common to dynamic and static client libs - -gvfsclientincludedir=$(includedir)/gvfs-client/gvfs/ -gvfsclientinclude_HEADERS = \ - gvfsuriutils.h gvfsurimapper.h \ - $(NULL) - -URI_PARSER_SOURCES = \ - smburi.c \ - httpuri.c \ - $(NULL) - -vfssources = \ - gdaemonvfs.c gdaemonvfs.h \ - gdaemonmount.c gdaemonmount.h \ - gdaemonvolumemonitor.c gdaemonvolumemonitor.h \ - gdaemonfile.c gdaemonfile.h \ - gdaemonfileinputstream.c gdaemonfileinputstream.h \ - gdaemonfileoutputstream.c gdaemonfileoutputstream.h \ - gdaemonfileenumerator.c gdaemonfileenumerator.h \ - gdaemonfilemonitor.c gdaemonfilemonitor.h \ - gvfsdaemondbus.c gvfsdaemondbus.h \ - gvfsuriutils.c gvfsuriutils.h \ - gvfsurimapper.c gvfsurimapper.h \ - $(URI_PARSER_SOURCES) \ - $(NULL) - -vfslibs = \ - $(top_builddir)/common/libgvfscommon.la \ - $(DBUS_LIBS) \ - $(GLIB_LIBS) \ - $(NULL) - -## Dynamic client lib - -giomodules_LTLIBRARIES = libgvfsdbus.la - -libgvfsdbus_la_LDFLAGS = $(module_flags) -libgvfsdbus_la_SOURCES = $(vfssources) -libgvfsdbus_la_LIBADD = $(vfslibs) - -noinst_PROGRAMS = test-uri-utils - -test_uri_utils_SOURCES = test-uri-utils.c gvfsuriutils.c gvfsuriutils.h -test_uri_utils_LDADD = $(vfslibs) -test_uri_utils_CFLAGS = $(INCLUDES) - -if USE_FUSE - -## FUSE daemon - -libexec_PROGRAMS = gvfs-fuse-daemon - -gvfs_fuse_daemon_SOURCES = \ - gvfsfusedaemon.c - -gvfs_fuse_daemon_CFLAGS = \ - -I$(top_srcdir) \ - -I$(top_srcdir)/common \ - $(GLIB_CFLAGS) $(DBUS_CFLAGS) $(FUSE_CFLAGS) \ - -DG_LOG_DOMAIN=\"GVFS-FUSE\" -DG_DISABLE_DEPRECATED \ - -DDBUS_API_SUBJECT_TO_CHANGE - -gvfs_fuse_daemon_LDADD = \ - $(top_builddir)/common/libgvfscommon.la \ - $(GLIB_LIBS) $(DBUS_LIBS) $(FUSE_LIBS) - -endif diff --git a/gnome-2-24/client/gdaemonfile.c b/gnome-2-24/client/gdaemonfile.c deleted file mode 100644 index 9e8eb637..00000000 --- a/gnome-2-24/client/gdaemonfile.c +++ /dev/null @@ -1,2805 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -#include <config.h> - -#include <unistd.h> -#include <string.h> -#include <stdio.h> -#include <sys/types.h> -#include <sys/socket.h> - -#include "gdaemonfile.h" -#include "gvfsdaemondbus.h" -#include "gdaemonmount.h" -#include <gvfsdaemonprotocol.h> -#include <gdaemonfileinputstream.h> -#include <gdaemonfileoutputstream.h> -#include <gdaemonfilemonitor.h> -#include <gdaemonfileenumerator.h> -#include <glib/gi18n-lib.h> -#include "gdbusutils.h" -#include "gmountoperationdbus.h" -#include <gio/gio.h> - -static void g_daemon_file_file_iface_init (GFileIface *iface); - -struct _GDaemonFile -{ - GObject parent_instance; - - GMountSpec *mount_spec; - char *path; -}; - -static void g_daemon_file_read_async (GFile *file, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer callback_data); - -G_DEFINE_TYPE_WITH_CODE (GDaemonFile, g_daemon_file, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (G_TYPE_FILE, - g_daemon_file_file_iface_init)) - -static void -g_daemon_file_finalize (GObject *object) -{ - GDaemonFile *daemon_file; - - daemon_file = G_DAEMON_FILE (object); - - g_mount_spec_unref (daemon_file->mount_spec); - g_free (daemon_file->path); - - if (G_OBJECT_CLASS (g_daemon_file_parent_class)->finalize) - (*G_OBJECT_CLASS (g_daemon_file_parent_class)->finalize) (object); -} - -static void -g_daemon_file_class_init (GDaemonFileClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->finalize = g_daemon_file_finalize; -} - -static void -g_daemon_file_init (GDaemonFile *daemon_file) -{ -} - -GFile * -g_daemon_file_new (GMountSpec *mount_spec, - const char *path) -{ - GDaemonFile *daemon_file; - - daemon_file = g_object_new (G_TYPE_DAEMON_FILE, NULL); - daemon_file->mount_spec = g_mount_spec_get_unique_for (mount_spec); - daemon_file->path = g_mount_spec_canonicalize_path (path); - - return G_FILE (daemon_file); -} - -static gboolean -g_daemon_file_is_native (GFile *file) -{ - return FALSE; -} - -static gboolean -g_daemon_file_has_uri_scheme (GFile *file, - const char *uri_scheme) -{ - GDaemonFile *daemon_file = G_DAEMON_FILE (file); - const char *scheme; - - scheme = _g_daemon_vfs_mountspec_get_uri_scheme (daemon_file->mount_spec); - return g_ascii_strcasecmp (scheme, uri_scheme) == 0; -} - -static char * -g_daemon_file_get_uri_scheme (GFile *file) -{ - GDaemonFile *daemon_file = G_DAEMON_FILE (file); - const char *scheme; - - scheme = _g_daemon_vfs_mountspec_get_uri_scheme (daemon_file->mount_spec); - - return g_strdup (scheme); -} - -static char * -g_daemon_file_get_basename (GFile *file) -{ - GDaemonFile *daemon_file = G_DAEMON_FILE (file); - char *last_slash; - - /* This code relies on the path being canonicalized */ - - last_slash = strrchr (daemon_file->path, '/'); - /* If no slash, or only "/" fallback to full path */ - if (last_slash == NULL || - last_slash[1] == '\0') - return g_strdup (daemon_file->path); - - return g_strdup (last_slash + 1); -} - -static char * -g_daemon_file_get_path (GFile *file) -{ - GDaemonFile *daemon_file = G_DAEMON_FILE (file); - GMountInfo *mount_info; - const char *rel_path; - char *path; - - /* This is a sync i/o call, which is a bit unfortunate, as - * this is supposed to be a fast call. However, in almost all - * cases this will be cached. - */ - - mount_info = _g_daemon_vfs_get_mount_info_sync (daemon_file->mount_spec, - daemon_file->path, - NULL); - - if (mount_info == NULL) - return NULL; - - path = NULL; - - if (mount_info->fuse_mountpoint) - { - rel_path = daemon_file->path + - strlen (mount_info->mount_spec->mount_prefix); - - path = g_build_filename (mount_info->fuse_mountpoint, rel_path, NULL); - } - - g_mount_info_unref (mount_info); - - return path; -} - -static char * -g_daemon_file_get_uri (GFile *file) -{ - GDaemonFile *daemon_file = G_DAEMON_FILE (file); - - return _g_daemon_vfs_get_uri_for_mountspec (daemon_file->mount_spec, - daemon_file->path, - FALSE); -} - -static char * -g_daemon_file_get_parse_name (GFile *file) -{ - GDaemonFile *daemon_file = G_DAEMON_FILE (file); - - return _g_daemon_vfs_get_uri_for_mountspec (daemon_file->mount_spec, - daemon_file->path, - TRUE); -} - -static GFile * -new_file_for_new_path (GDaemonFile *daemon_file, - const char *new_path) -{ - GFile *new_file; - GMountSpec *new_spec; - - new_spec = _g_daemon_vfs_get_mount_spec_for_path (daemon_file->mount_spec, - daemon_file->path, - new_path); - - new_file = g_daemon_file_new (new_spec, new_path); - g_mount_spec_unref (new_spec); - - return new_file; -} - -static GFile * -g_daemon_file_get_parent (GFile *file) -{ - GDaemonFile *daemon_file = G_DAEMON_FILE (file); - const char *path; - GFile *parent; - const char *base; - char *parent_path; - gsize len; - - path = daemon_file->path; - base = strrchr (path, '/'); - if (base == NULL || - *(base+1) == 0) - return NULL; - - while (base > path && *base == '/') - base--; - - len = (guint) 1 + base - path; - - parent_path = g_new (gchar, len + 1); - g_memmove (parent_path, path, len); - parent_path[len] = 0; - - parent = new_file_for_new_path (daemon_file, parent_path); - g_free (parent_path); - - return parent; -} - -static GFile * -g_daemon_file_dup (GFile *file) -{ - GDaemonFile *daemon_file = G_DAEMON_FILE (file); - - return g_daemon_file_new (daemon_file->mount_spec, - daemon_file->path); -} - -static guint -g_daemon_file_hash (GFile *file) -{ - GDaemonFile *daemon_file = G_DAEMON_FILE (file); - - return - g_str_hash (daemon_file->path) ^ - GPOINTER_TO_UINT (daemon_file->mount_spec); /* We have unique mount_spec objects so hash directly on it */ -} - -static gboolean -g_daemon_file_equal (GFile *file1, - GFile *file2) -{ - GDaemonFile *daemon_file1 = G_DAEMON_FILE (file1); - GDaemonFile *daemon_file2 = G_DAEMON_FILE (file2); - - return daemon_file1->mount_spec == daemon_file2->mount_spec && - g_str_equal (daemon_file1->path, daemon_file2->path); -} - - -static const char * -match_prefix (const char *path, const char *prefix) -{ - int prefix_len; - - prefix_len = strlen (prefix); - if (strncmp (path, prefix, prefix_len) != 0) - return NULL; - - /* Handle the case where prefix is the root, so that - * the IS_DIR_SEPRARATOR check below works */ - if (prefix_len > 0 && - prefix[prefix_len-1] == '/') - prefix_len--; - - - return path + prefix_len; -} - -static gboolean -g_daemon_file_prefix_matches (GFile *parent, - GFile *descendant) -{ - GDaemonFile *parent_daemon = G_DAEMON_FILE (parent); - GDaemonFile *descendant_daemon = G_DAEMON_FILE (descendant); - const char *remainder; - - if (descendant_daemon->mount_spec != parent_daemon->mount_spec) - return FALSE; - - remainder = match_prefix (descendant_daemon->path, parent_daemon->path); - if (remainder != NULL && *remainder == '/') - return TRUE; - return FALSE; -} - -static char * -g_daemon_file_get_relative_path (GFile *parent, - GFile *descendant) -{ - GDaemonFile *parent_daemon = G_DAEMON_FILE (parent); - GDaemonFile *descendant_daemon = G_DAEMON_FILE (descendant); - const char *remainder; - - if (descendant_daemon->mount_spec != parent_daemon->mount_spec) - return NULL; - - remainder = match_prefix (descendant_daemon->path, parent_daemon->path); - - if (remainder != NULL && *remainder == '/') - return g_strdup (remainder + 1); - return NULL; -} - -static GFile * -g_daemon_file_resolve_relative_path (GFile *file, - const char *relative_path) -{ - GDaemonFile *daemon_file = G_DAEMON_FILE (file); - char *path; - GFile *child; - - if (*relative_path == '/') - return new_file_for_new_path (daemon_file, relative_path); - - path = g_build_path ("/", daemon_file->path, relative_path, NULL); - child = new_file_for_new_path (daemon_file, path); - g_free (path); - - return child; -} - -static DBusMessage * -create_empty_message (GFile *file, - const char *op, - GMountInfo **mount_info_out, - GError **error) -{ - GDaemonFile *daemon_file = G_DAEMON_FILE (file); - DBusMessage *message; - GMountInfo *mount_info; - const char *path; - - mount_info = _g_daemon_vfs_get_mount_info_sync (daemon_file->mount_spec, - daemon_file->path, - error); - if (mount_info == NULL) - return NULL; - - if (mount_info_out) - *mount_info_out = g_mount_info_ref (mount_info); - - message = - dbus_message_new_method_call (mount_info->dbus_id, - mount_info->object_path, - G_VFS_DBUS_MOUNT_INTERFACE, - op); - - path = g_mount_info_resolve_path (mount_info, - daemon_file->path); - _g_dbus_message_append_args (message, G_DBUS_TYPE_CSTRING, &path, 0); - - g_mount_info_unref (mount_info); - return message; -} - -static DBusMessage * -do_sync_path_call (GFile *file, - const char *op, - GMountInfo **mount_info_out, - DBusConnection **connection_out, - GCancellable *cancellable, - GError **error, - int first_arg_type, - ...) -{ - DBusMessage *message, *reply; - va_list var_args; - GError *my_error; - - retry: - - message = create_empty_message (file, op, mount_info_out, error); - if (!message) - return NULL; - - va_start (var_args, first_arg_type); - _g_dbus_message_append_args_valist (message, - first_arg_type, - var_args); - va_end (var_args); - - - my_error = NULL; - reply = _g_vfs_daemon_call_sync (message, - connection_out, - NULL, NULL, NULL, - cancellable, &my_error); - dbus_message_unref (message); - - if (reply == NULL) - { - if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY)) - { - g_error_free (my_error); - goto retry; - } - g_propagate_error (error, my_error); - } - - return reply; -} - -static DBusMessage * -do_sync_2_path_call (GFile *file1, - GFile *file2, - const char *op, - const char *callback_obj_path, - DBusObjectPathMessageFunction callback, - gpointer callback_user_data, - DBusConnection **connection_out, - GCancellable *cancellable, - GError **error, - int first_arg_type, - ...) -{ - GDaemonFile *daemon_file1 = G_DAEMON_FILE (file1); - GDaemonFile *daemon_file2 = G_DAEMON_FILE (file2); - DBusMessage *message, *reply; - GMountInfo *mount_info1, *mount_info2; - const char *path1, *path2; - va_list var_args; - GError *my_error; - - retry: - - mount_info1 = _g_daemon_vfs_get_mount_info_sync (daemon_file1->mount_spec, - daemon_file1->path, - error); - if (mount_info1 == NULL) - return NULL; - - mount_info2 = NULL; - if (daemon_file2) - { - mount_info2 = _g_daemon_vfs_get_mount_info_sync (daemon_file2->mount_spec, - daemon_file2->path, - error); - if (mount_info2 == NULL) - { - g_mount_info_unref (mount_info1); - return NULL; - } - - if (mount_info1 != mount_info2) - { - g_mount_info_unref (mount_info1); - /* For copy this will cause the fallback code to be involved */ - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - _("Operation not supported, files on different mounts")); - return NULL; - } - } - - message = - dbus_message_new_method_call (mount_info1->dbus_id, - mount_info1->object_path, - G_VFS_DBUS_MOUNT_INTERFACE, - op); - - path1 = g_mount_info_resolve_path (mount_info1, - daemon_file1->path); - _g_dbus_message_append_args (message, G_DBUS_TYPE_CSTRING, &path1, 0); - - if (daemon_file2) - { - path2 = g_mount_info_resolve_path (mount_info2, - daemon_file2->path); - _g_dbus_message_append_args (message, G_DBUS_TYPE_CSTRING, &path2, 0); - } - - va_start (var_args, first_arg_type); - _g_dbus_message_append_args_valist (message, - first_arg_type, - var_args); - va_end (var_args); - - my_error = NULL; - reply = _g_vfs_daemon_call_sync (message, - connection_out, - callback_obj_path, - callback, - callback_user_data, - cancellable, &my_error); - dbus_message_unref (message); - - g_mount_info_unref (mount_info1); - if (mount_info2) - g_mount_info_unref (mount_info2); - - if (reply == NULL) - { - if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY)) - { - g_error_free (my_error); - goto retry; - } - g_propagate_error (error, my_error); - } - - return reply; -} - -typedef void (*AsyncPathCallCallback) (DBusMessage *reply, - DBusConnection *connection, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data); - - -typedef struct { - GSimpleAsyncResult *result; - GFile *file; - char *op; - GCancellable *cancellable; - DBusMessage *args; - AsyncPathCallCallback callback; - gpointer callback_data; - GDestroyNotify notify; -} AsyncPathCall; - -static void -async_path_call_free (AsyncPathCall *data) -{ - if (data->notify) - data->notify (data->callback_data); - - if (data->result) - g_object_unref (data->result); - g_object_unref (data->file); - g_free (data->op); - if (data->cancellable) - g_object_unref (data->cancellable); - if (data->args) - dbus_message_unref (data->args); - g_free (data); -} - -static void -async_path_call_done (DBusMessage *reply, - DBusConnection *connection, - GError *io_error, - gpointer _data) -{ - AsyncPathCall *data = _data; - GSimpleAsyncResult *result; - - if (io_error != NULL) - { - g_simple_async_result_set_from_error (data->result, io_error); - g_simple_async_result_complete (data->result); - async_path_call_free (data); - } - else - { - result = data->result; - g_object_weak_ref (G_OBJECT (result), (GWeakNotify)async_path_call_free, data); - data->result = NULL; - - data->callback (reply, connection, - result, - data->cancellable, - data->callback_data); - - /* Free data here, or later if callback ref:ed the result */ - g_object_unref (result); - } -} - -static void -do_async_path_call_callback (GMountInfo *mount_info, - gpointer _data, - GError *error) -{ - AsyncPathCall *data = _data; - GDaemonFile *daemon_file = G_DAEMON_FILE (data->file); - const char *path; - DBusMessage *message; - DBusMessageIter arg_source, arg_dest; - - if (error != NULL) - { - g_simple_async_result_set_from_error (data->result, error); - g_simple_async_result_complete (data->result); - async_path_call_free (data); - return; - } - - message = - dbus_message_new_method_call (mount_info->dbus_id, - mount_info->object_path, - G_VFS_DBUS_MOUNT_INTERFACE, - data->op); - - path = g_mount_info_resolve_path (mount_info, daemon_file->path); - _g_dbus_message_append_args (message, G_DBUS_TYPE_CSTRING, &path, 0); - - /* Append more args from data->args */ - - if (data->args) - { - dbus_message_iter_init (data->args, &arg_source); - dbus_message_iter_init_append (message, &arg_dest); - - _g_dbus_message_iter_copy (&arg_dest, &arg_source); - } - - _g_vfs_daemon_call_async (message, - async_path_call_done, data, - data->cancellable); - - dbus_message_unref (message); -} - -static void -do_async_path_call (GFile *file, - const char *op, - GCancellable *cancellable, - GAsyncReadyCallback op_callback, - gpointer op_callback_data, - AsyncPathCallCallback callback, - gpointer callback_data, - GDestroyNotify notify, - int first_arg_type, - ...) -{ - GDaemonFile *daemon_file = G_DAEMON_FILE (file); - va_list var_args; - AsyncPathCall *data; - - data = g_new0 (AsyncPathCall, 1); - - data->result = g_simple_async_result_new (G_OBJECT (file), - op_callback, op_callback_data, - NULL); - - data->file = g_object_ref (file); - data->op = g_strdup (op); - if (cancellable) - data->cancellable = g_object_ref (cancellable); - data->callback = callback; - data->callback_data = callback_data; - data->notify = notify; - - if (first_arg_type != 0) - { - data->args = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL); - if (data->args == NULL) - _g_dbus_oom (); - - va_start (var_args, first_arg_type); - _g_dbus_message_append_args_valist (data->args, - first_arg_type, - var_args); - va_end (var_args); - } - - - _g_daemon_vfs_get_mount_info_async (daemon_file->mount_spec, - daemon_file->path, - do_async_path_call_callback, - data); -} - - -static GFileEnumerator * -g_daemon_file_enumerate_children (GFile *file, - const char *attributes, - GFileQueryInfoFlags flags, - GCancellable *cancellable, - GError **error) -{ - DBusMessage *reply; - dbus_uint32_t flags_dbus; - char *obj_path; - GDaemonFileEnumerator *enumerator; - DBusConnection *connection; - char *uri; - - enumerator = g_daemon_file_enumerator_new (file); - obj_path = g_daemon_file_enumerator_get_object_path (enumerator); - - - uri = g_file_get_uri (file); - - if (attributes == NULL) - attributes = ""; - flags_dbus = flags; - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_ENUMERATE, - NULL, &connection, - cancellable, error, - DBUS_TYPE_STRING, &obj_path, - DBUS_TYPE_STRING, &attributes, - DBUS_TYPE_UINT32, &flags_dbus, - DBUS_TYPE_STRING, &uri, - 0); - g_free (uri); - g_free (obj_path); - - if (reply == NULL) - goto error; - - dbus_message_unref (reply); - - g_daemon_file_enumerator_set_sync_connection (enumerator, connection); - - return G_FILE_ENUMERATOR (enumerator); - - error: - if (reply) - dbus_message_unref (reply); - g_object_unref (enumerator); - return NULL; -} - -static GFileInfo * -g_daemon_file_query_info (GFile *file, - const char *attributes, - GFileQueryInfoFlags flags, - GCancellable *cancellable, - GError **error) -{ - DBusMessage *reply; - dbus_uint32_t flags_dbus; - DBusMessageIter iter; - GFileInfo *info; - char *uri; - - uri = g_file_get_uri (file); - - if (attributes == NULL) - attributes = ""; - flags_dbus = flags; - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_QUERY_INFO, - NULL, NULL, - cancellable, error, - DBUS_TYPE_STRING, &attributes, - DBUS_TYPE_UINT32, &flags_dbus, - DBUS_TYPE_STRING, &uri, - 0); - - g_free (uri); - - if (reply == NULL) - return NULL; - - info = NULL; - - if (!dbus_message_iter_init (reply, &iter) || - (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRUCT)) - { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from get_info")); - goto out; - } - - info = _g_dbus_get_file_info (&iter, error); - - out: - dbus_message_unref (reply); - return info; -} - -static void -query_info_async_cb (DBusMessage *reply, - DBusConnection *connection, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) -{ - DBusMessageIter iter; - GFileInfo *info; - GError *error; - - info = NULL; - - if (!dbus_message_iter_init (reply, &iter) || - (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRUCT)) - { - g_simple_async_result_set_error (result, - G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from query_info")); - g_simple_async_result_complete (result); - return; - } - - error = NULL; - info = _g_dbus_get_file_info (&iter, &error); - if (info == NULL) - { - g_simple_async_result_set_from_error (result, error); - g_error_free (error); - g_simple_async_result_complete (result); - return; - } - - g_simple_async_result_set_op_res_gpointer (result, info, g_object_unref); - g_simple_async_result_complete (result); -} - -static void -g_daemon_file_query_info_async (GFile *file, - const char *attributes, - GFileQueryInfoFlags flags, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - guint32 dbus_flags; - char *uri; - - uri = g_file_get_uri (file); - - dbus_flags = flags; - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_QUERY_INFO, - cancellable, - callback, user_data, - query_info_async_cb, NULL, NULL, - DBUS_TYPE_STRING, &attributes, - DBUS_TYPE_UINT32, &dbus_flags, - DBUS_TYPE_STRING, &uri, - 0); - - g_free (uri); -} - -static GFileInfo * -g_daemon_file_query_info_finish (GFile *file, - GAsyncResult *res, - GError **error) -{ - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); - GFileInfo *info; - - info = g_simple_async_result_get_op_res_gpointer (simple); - if (info) - return g_object_ref (info); - - return NULL; -} - -typedef struct { - GSimpleAsyncResult *result; - gboolean can_seek; -} GetFDData; - -static void -read_async_get_fd_cb (int fd, - gpointer callback_data) -{ - GetFDData *data = callback_data; - GFileInputStream *stream; - - if (fd == -1) - { - g_simple_async_result_set_error (data->result, - G_IO_ERROR, G_IO_ERROR_FAILED, - _("Couldn't get stream file descriptor")); - } - else - { - stream = g_daemon_file_input_stream_new (fd, data->can_seek); - g_simple_async_result_set_op_res_gpointer (data->result, stream, g_object_unref); - } - - g_simple_async_result_complete (data->result); - - g_object_unref (data->result); - g_free (data); -} - -static void -read_async_cb (DBusMessage *reply, - DBusConnection *connection, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) -{ - guint32 fd_id; - dbus_bool_t can_seek; - GetFDData *get_fd_data; - - if (!dbus_message_get_args (reply, NULL, - DBUS_TYPE_UINT32, &fd_id, - DBUS_TYPE_BOOLEAN, &can_seek, - DBUS_TYPE_INVALID)) - { - g_simple_async_result_set_error (result, - G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from open")); - g_simple_async_result_complete (result); - return; - } - - get_fd_data = g_new0 (GetFDData, 1); - get_fd_data->result = g_object_ref (result); - get_fd_data->can_seek = can_seek; - - _g_dbus_connection_get_fd_async (connection, fd_id, - read_async_get_fd_cb, get_fd_data); -} - -static void -g_daemon_file_read_async (GFile *file, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer callback_data) -{ - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_OPEN_FOR_READ, - cancellable, - callback, callback_data, - read_async_cb, NULL, NULL, - 0); -} - -static GFileInputStream * -g_daemon_file_read_finish (GFile *file, - GAsyncResult *res, - GError **error) -{ - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); - gpointer op; - - op = g_simple_async_result_get_op_res_gpointer (simple); - if (op) - return g_object_ref (op); - - return NULL; -} - - -static GFileInputStream * -g_daemon_file_read (GFile *file, - GCancellable *cancellable, - GError **error) -{ - DBusConnection *connection; - int fd; - DBusMessage *reply; - guint32 fd_id; - dbus_bool_t can_seek; - - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_OPEN_FOR_READ, - NULL, &connection, - cancellable, error, - 0); - if (reply == NULL) - return NULL; - - if (!dbus_message_get_args (reply, NULL, - DBUS_TYPE_UINT32, &fd_id, - DBUS_TYPE_BOOLEAN, &can_seek, - DBUS_TYPE_INVALID)) - { - dbus_message_unref (reply); - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from open")); - return NULL; - } - - dbus_message_unref (reply); - - fd = _g_dbus_connection_get_fd_sync (connection, fd_id); - if (fd == -1) - { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Didn't get stream file descriptor")); - return NULL; - } - - return g_daemon_file_input_stream_new (fd, can_seek); -} - -static GFileOutputStream * -g_daemon_file_append_to (GFile *file, - GFileCreateFlags flags, - GCancellable *cancellable, - GError **error) -{ - DBusConnection *connection; - int fd; - DBusMessage *reply; - guint32 fd_id; - dbus_bool_t can_seek; - guint16 mode; - guint64 initial_offset; - dbus_bool_t make_backup; - guint32 dbus_flags; - char *etag; - - mode = 1; - etag = ""; - make_backup = FALSE; - dbus_flags = flags; - - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE, - NULL, &connection, - cancellable, error, - DBUS_TYPE_UINT16, &mode, - DBUS_TYPE_STRING, &etag, - DBUS_TYPE_BOOLEAN, &make_backup, - DBUS_TYPE_UINT32, &dbus_flags, - 0); - if (reply == NULL) - return NULL; - - if (!dbus_message_get_args (reply, NULL, - DBUS_TYPE_UINT32, &fd_id, - DBUS_TYPE_BOOLEAN, &can_seek, - DBUS_TYPE_UINT64, &initial_offset, - DBUS_TYPE_INVALID)) - { - dbus_message_unref (reply); - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from open")); - return NULL; - } - - dbus_message_unref (reply); - - fd = _g_dbus_connection_get_fd_sync (connection, fd_id); - if (fd == -1) - { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Didn't get stream file descriptor")); - return NULL; - } - - return g_daemon_file_output_stream_new (fd, can_seek, initial_offset); -} - -static GFileOutputStream * -g_daemon_file_create (GFile *file, - GFileCreateFlags flags, - GCancellable *cancellable, - GError **error) -{ - DBusConnection *connection; - int fd; - DBusMessage *reply; - guint32 fd_id; - dbus_bool_t can_seek; - guint16 mode; - guint64 initial_offset; - dbus_bool_t make_backup; - char *etag; - guint32 dbus_flags; - - mode = 0; - etag = ""; - make_backup = FALSE; - dbus_flags = flags; - - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE, - NULL, &connection, - cancellable, error, - DBUS_TYPE_UINT16, &mode, - DBUS_TYPE_STRING, &etag, - DBUS_TYPE_BOOLEAN, &make_backup, - DBUS_TYPE_UINT32, &dbus_flags, - 0); - if (reply == NULL) - return NULL; - - if (!dbus_message_get_args (reply, NULL, - DBUS_TYPE_UINT32, &fd_id, - DBUS_TYPE_BOOLEAN, &can_seek, - DBUS_TYPE_UINT64, &initial_offset, - DBUS_TYPE_INVALID)) - { - dbus_message_unref (reply); - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from open")); - return NULL; - } - - dbus_message_unref (reply); - - fd = _g_dbus_connection_get_fd_sync (connection, fd_id); - if (fd == -1) - { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Didn't get stream file descriptor")); - return NULL; - } - - return g_daemon_file_output_stream_new (fd, can_seek, initial_offset); -} - -static GFileOutputStream * -g_daemon_file_replace (GFile *file, - const char *etag, - gboolean make_backup, - GFileCreateFlags flags, - GCancellable *cancellable, - GError **error) -{ - DBusConnection *connection; - int fd; - DBusMessage *reply; - guint32 fd_id; - dbus_bool_t can_seek; - guint16 mode; - guint64 initial_offset; - dbus_bool_t dbus_make_backup; - guint32 dbus_flags; - - mode = 2; - dbus_make_backup = make_backup; - dbus_flags = flags; - - if (etag == NULL) - etag = ""; - - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE, - NULL, &connection, - cancellable, error, - DBUS_TYPE_UINT16, &mode, - DBUS_TYPE_STRING, &etag, - DBUS_TYPE_BOOLEAN, &dbus_make_backup, - DBUS_TYPE_UINT32, &dbus_flags, - 0); - if (reply == NULL) - return NULL; - - if (!dbus_message_get_args (reply, NULL, - DBUS_TYPE_UINT32, &fd_id, - DBUS_TYPE_BOOLEAN, &can_seek, - DBUS_TYPE_UINT64, &initial_offset, - DBUS_TYPE_INVALID)) - { - dbus_message_unref (reply); - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from open")); - return NULL; - } - - dbus_message_unref (reply); - - fd = _g_dbus_connection_get_fd_sync (connection, fd_id); - if (fd == -1) - { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Didn't get stream file descriptor")); - return NULL; - } - - return g_daemon_file_output_stream_new (fd, can_seek, initial_offset); -} - -static void -mount_mountable_location_mounted_cb (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - GSimpleAsyncResult *result = user_data; - GError *error = NULL; - - if (!g_file_mount_enclosing_volume_finish (G_FILE (source_object), res, &error)) - { - g_simple_async_result_set_from_error (result, error); - g_error_free (error); - } - - g_simple_async_result_complete (result); - g_object_unref (result); - -} - -static void -mount_mountable_async_cb (DBusMessage *reply, - DBusConnection *connection, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) -{ - GMountOperation *mount_operation = callback_data; - GMountSpec *mount_spec; - char *path; - DBusMessageIter iter; - GFile *file; - dbus_bool_t must_mount_location, is_uri; - - path = NULL; - - dbus_message_iter_init (reply, &iter); - - if (!_g_dbus_message_iter_get_args (&iter, NULL, - DBUS_TYPE_BOOLEAN, &is_uri, - G_DBUS_TYPE_CSTRING, &path, - DBUS_TYPE_BOOLEAN, &must_mount_location, - 0)) - { - g_simple_async_result_set_error (result, - G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from call")); - g_simple_async_result_complete (result); - - return; - } - - if (is_uri) - { - file = g_file_new_for_uri (path); - } - else - { - mount_spec = g_mount_spec_from_dbus (&iter); - if (mount_spec == NULL) - { - g_simple_async_result_set_error (result, - G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from call")); - g_simple_async_result_complete (result); - return; - } - - file = g_daemon_file_new (mount_spec, path); - g_mount_spec_unref (mount_spec); - } - - g_free (path); - g_simple_async_result_set_op_res_gpointer (result, file, g_object_unref); - - if (must_mount_location) - { - g_file_mount_enclosing_volume (file, - 0, - mount_operation, - cancellable, - mount_mountable_location_mounted_cb, - g_object_ref (result)); - - } - else - g_simple_async_result_complete (result); -} - -static void -g_daemon_file_mount_mountable (GFile *file, - GMountMountFlags flags, - GMountOperation *mount_operation, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GMountSource *mount_source; - const char *dbus_id, *obj_path; - - mount_source = g_mount_operation_dbus_wrap (mount_operation, _g_daemon_vfs_get_async_bus ()); - - dbus_id = g_mount_source_get_dbus_id (mount_source); - obj_path = g_mount_source_get_obj_path (mount_source); - - if (mount_operation) - g_object_ref (mount_operation); - - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_MOUNT_MOUNTABLE, - cancellable, - callback, user_data, - mount_mountable_async_cb, - mount_operation, mount_operation ? g_object_unref : NULL, - DBUS_TYPE_STRING, &dbus_id, - DBUS_TYPE_OBJECT_PATH, &obj_path, - 0); - - g_object_unref (mount_source); -} - -static GFile * -g_daemon_file_mount_mountable_finish (GFile *file, - GAsyncResult *result, - GError **error) -{ - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); - GFile *result_file; - - result_file = g_simple_async_result_get_op_res_gpointer (simple); - if (result_file) - return g_object_ref (result_file); - - return NULL; -} - -static void -eject_mountable_async_cb (DBusMessage *reply, - DBusConnection *connection, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) -{ - g_simple_async_result_complete (result); -} - -static void -g_daemon_file_eject_mountable (GFile *file, - GMountUnmountFlags flags, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - guint32 dbus_flags; - - dbus_flags = flags; - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_EJECT_MOUNTABLE, - cancellable, - callback, user_data, - eject_mountable_async_cb, - NULL, NULL, - DBUS_TYPE_UINT32, &dbus_flags, - 0); -} - -static gboolean -g_daemon_file_eject_mountable_finish (GFile *file, - GAsyncResult *result, - GError **error) -{ - return TRUE; -} - -static void -unmount_mountable_async_cb (DBusMessage *reply, - DBusConnection *connection, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) -{ - g_simple_async_result_complete (result); -} - -static void -g_daemon_file_unmount_mountable (GFile *file, - GMountUnmountFlags flags, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - guint32 dbus_flags; - - dbus_flags = flags; - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_UNMOUNT_MOUNTABLE, - cancellable, - callback, user_data, - unmount_mountable_async_cb, - NULL, NULL, - DBUS_TYPE_UINT32, &dbus_flags, - 0); -} - -static gboolean -g_daemon_file_unmount_mountable_finish (GFile *file, - GAsyncResult *result, - GError **error) -{ - return TRUE; -} - - -typedef struct { - GFile *file; - GMountOperation *mount_operation; - GAsyncReadyCallback callback; - gpointer user_data; -} MountData; - -static void g_daemon_file_mount_enclosing_volume (GFile *location, - GMountMountFlags flags, - GMountOperation *mount_operation, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -static void -mount_reply (DBusMessage *reply, - GError *error, - gpointer user_data) -{ - MountData *data = user_data; - GSimpleAsyncResult *res; - - if (reply == NULL) - { - res = g_simple_async_result_new_from_error (G_OBJECT (data->file), - data->callback, - data->user_data, - error); - } - else - { - res = g_simple_async_result_new (G_OBJECT (data->file), - data->callback, - data->user_data, - g_daemon_file_mount_enclosing_volume); - } - - g_simple_async_result_complete (res); - - g_object_unref (data->file); - if (data->mount_operation) - g_object_unref (data->mount_operation); - g_free (data); -} - -static void -g_daemon_file_mount_enclosing_volume (GFile *location, - GMountMountFlags flags, - GMountOperation *mount_operation, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GDaemonFile *daemon_file; - DBusMessage *message; - GMountSpec *spec; - GMountSource *mount_source; - DBusMessageIter iter; - MountData *data; - - daemon_file = G_DAEMON_FILE (location); - - message = dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME, - G_VFS_DBUS_MOUNTTRACKER_PATH, - G_VFS_DBUS_MOUNTTRACKER_INTERFACE, - G_VFS_DBUS_MOUNTTRACKER_OP_MOUNT_LOCATION); - - spec = g_mount_spec_copy (daemon_file->mount_spec); - g_mount_spec_set_mount_prefix (spec, daemon_file->path); - dbus_message_iter_init_append (message, &iter); - g_mount_spec_to_dbus (&iter, spec); - g_mount_spec_unref (spec); - - mount_source = g_mount_operation_dbus_wrap (mount_operation, _g_daemon_vfs_get_async_bus ()); - g_mount_source_to_dbus (mount_source, message); - g_object_unref (mount_source); - - data = g_new0 (MountData, 1); - data->callback = callback; - data->user_data = user_data; - data->file = g_object_ref (location); - if (mount_operation) - data->mount_operation = g_object_ref (mount_operation); - - /* TODO: Ignoring cancellable here */ - _g_dbus_connection_call_async (_g_daemon_vfs_get_async_bus (), - message, - G_VFS_DBUS_MOUNT_TIMEOUT_MSECS, - mount_reply, data); - - dbus_message_unref (message); -} - -static gboolean -g_daemon_file_mount_enclosing_volume_finish (GFile *location, - GAsyncResult *result, - GError **error) -{ - /* Errors handled in generic code */ - return TRUE; -} - -static GFileInfo * -g_daemon_file_query_filesystem_info (GFile *file, - const char *attributes, - GCancellable *cancellable, - GError **error) -{ - DBusMessage *reply; - DBusMessageIter iter; - GFileInfo *info; - - if (attributes == NULL) - attributes = ""; - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_QUERY_FILESYSTEM_INFO, - NULL, NULL, - cancellable, error, - DBUS_TYPE_STRING, &attributes, - 0); - if (reply == NULL) - return NULL; - - info = NULL; - - if (!dbus_message_iter_init (reply, &iter) || - (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRUCT)) - { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from get_filesystem_info")); - goto out; - } - - info = _g_dbus_get_file_info (&iter, error); - - out: - dbus_message_unref (reply); - return info; -} - -static void -query_fs_info_async_cb (DBusMessage *reply, - DBusConnection *connection, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) -{ - DBusMessageIter iter; - GFileInfo *info; - GError *error; - - info = NULL; - - if (!dbus_message_iter_init (reply, &iter) || - (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRUCT)) - { - g_simple_async_result_set_error (result, - G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from query_info")); - g_simple_async_result_complete (result); - return; - } - - error = NULL; - info = _g_dbus_get_file_info (&iter, &error); - if (info == NULL) - { - g_simple_async_result_set_from_error (result, error); - g_error_free (error); - g_simple_async_result_complete (result); - return; - } - - g_simple_async_result_set_op_res_gpointer (result, info, g_object_unref); - g_simple_async_result_complete (result); -} - -static void -g_daemon_file_query_filesystem_info_async (GFile *file, - const char *attributes, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_QUERY_FILESYSTEM_INFO, - cancellable, - callback, user_data, - query_fs_info_async_cb, NULL, NULL, - DBUS_TYPE_STRING, &attributes, - 0); -} - -static GFileInfo * -g_daemon_file_query_filesystem_info_finish (GFile *file, - GAsyncResult *res, - GError **error) -{ - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); - GFileInfo *info; - - info = g_simple_async_result_get_op_res_gpointer (simple); - if (info) - return g_object_ref (info); - - return NULL; -} - -static GMount * -g_daemon_file_find_enclosing_mount (GFile *file, - GCancellable *cancellable, - GError **error) -{ - GDaemonFile *daemon_file = G_DAEMON_FILE (file); - GMountInfo *mount_info; - GDaemonMount *mount; - - mount_info = _g_daemon_vfs_get_mount_info_sync (daemon_file->mount_spec, - daemon_file->path, - error); - if (mount_info == NULL) - return NULL; - - if (mount_info->user_visible) - { - /* if we have a daemon volume monitor then return one of it's mounts */ - mount = g_daemon_volume_monitor_find_mount_by_mount_info (mount_info); - if (mount == NULL) - { - mount = g_daemon_mount_new (mount_info, NULL); - } - g_mount_info_unref (mount_info); - - if (mount) - return G_MOUNT (mount); - } - - g_set_error_literal (error, G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - /* translators: this is an error message when there is no user visible "mount" object - corresponding to a particular path/uri */ - _("Could not find enclosing mount")); - return NULL; -} - -static GFile * -g_daemon_file_get_child_for_display_name (GFile *file, - const char *display_name, - GError **error) -{ - GDaemonFile *daemon_file = G_DAEMON_FILE (file); - GMountInfo *mount_info; - char *basename; - GFile *child; - - mount_info = _g_daemon_vfs_get_mount_info_sync (daemon_file->mount_spec, - daemon_file->path, - NULL); - - - if (mount_info && mount_info->prefered_filename_encoding) - { - basename = g_convert (display_name, -1, - mount_info->prefered_filename_encoding, - "UTF-8", - NULL, NULL, - NULL); - if (basename == NULL) - { - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_INVALID_FILENAME, - _("Invalid filename %s"), display_name); - return NULL; - } - - child = g_file_get_child (file, basename); - g_free (basename); - } - else - child = g_file_get_child (file, display_name); - - return child; -} - -static GFile * -g_daemon_file_set_display_name (GFile *file, - const char *display_name, - GCancellable *cancellable, - GError **error) -{ - GDaemonFile *daemon_file; - DBusMessage *reply; - DBusMessageIter iter; - char *new_path; - - daemon_file = G_DAEMON_FILE (file); - - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_SET_DISPLAY_NAME, - NULL, NULL, - cancellable, error, - DBUS_TYPE_STRING, &display_name, - 0); - if (reply == NULL) - return NULL; - - - if (!dbus_message_iter_init (reply, &iter) || - !_g_dbus_message_iter_get_args (&iter, NULL, - G_DBUS_TYPE_CSTRING, &new_path, - 0)) - { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from query_filesystem_info")); - goto out; - } - - file = new_file_for_new_path (daemon_file, new_path); - g_free (new_path); - - out: - dbus_message_unref (reply); - return file; -} - -static gboolean -g_daemon_file_delete (GFile *file, - GCancellable *cancellable, - GError **error) -{ - DBusMessage *reply; - - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_DELETE, - NULL, NULL, - cancellable, error, - 0); - if (reply == NULL) - return FALSE; - - dbus_message_unref (reply); - return TRUE; -} - -static gboolean -g_daemon_file_trash (GFile *file, - GCancellable *cancellable, - GError **error) -{ - DBusMessage *reply; - - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_TRASH, - NULL, NULL, - cancellable, error, - 0); - if (reply == NULL) - return FALSE; - - dbus_message_unref (reply); - return TRUE; -} - -static gboolean -g_daemon_file_make_directory (GFile *file, - GCancellable *cancellable, - GError **error) -{ - DBusMessage *reply; - - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_MAKE_DIRECTORY, - NULL, NULL, - cancellable, error, - 0); - if (reply == NULL) - return FALSE; - - dbus_message_unref (reply); - return TRUE; -} - -static gboolean -g_daemon_file_make_symbolic_link (GFile *file, - const char *symlink_value, - GCancellable *cancellable, - GError **error) -{ - DBusMessage *reply; - - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_MAKE_SYMBOLIC_LINK, - NULL, NULL, - cancellable, error, - G_DBUS_TYPE_CSTRING, &symlink_value, - 0); - if (reply == NULL) - return FALSE; - - dbus_message_unref (reply); - return TRUE; -} - -static GFileAttributeInfoList * -g_daemon_file_query_settable_attributes (GFile *file, - GCancellable *cancellable, - GError **error) -{ - DBusMessage *reply; - GFileAttributeInfoList *list; - DBusMessageIter iter; - - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_QUERY_SETTABLE_ATTRIBUTES, - NULL, NULL, - cancellable, error, - 0); - if (reply == NULL) - return NULL; - - dbus_message_iter_init (reply, &iter); - list = _g_dbus_get_attribute_info_list (&iter, error); - - dbus_message_unref (reply); - - return list; -} - -static GFileAttributeInfoList * -g_daemon_file_query_writable_namespaces (GFile *file, - GCancellable *cancellable, - GError **error) -{ - DBusMessage *reply; - GFileAttributeInfoList *list; - DBusMessageIter iter; - - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_QUERY_WRITABLE_NAMESPACES, - NULL, NULL, - cancellable, error, - 0); - if (reply == NULL) - return NULL; - - dbus_message_iter_init (reply, &iter); - list = _g_dbus_get_attribute_info_list (&iter, error); - - dbus_message_unref (reply); - - return list; - -} - -static gboolean -g_daemon_file_set_attribute (GFile *file, - const char *attribute, - GFileAttributeType type, - gpointer value_p, - GFileQueryInfoFlags flags, - GCancellable *cancellable, - GError **error) -{ - DBusMessage *message, *reply; - DBusMessageIter iter; - dbus_uint32_t flags_dbus; - GError *my_error; - - retry: - - message = create_empty_message (file, G_VFS_DBUS_MOUNT_OP_SET_ATTRIBUTE, NULL, error); - if (!message) - return FALSE; - - dbus_message_iter_init_append (message, &iter); - - flags_dbus = flags; - dbus_message_iter_append_basic (&iter, - DBUS_TYPE_UINT32, - &flags_dbus); - - _g_dbus_append_file_attribute (&iter, attribute, type, value_p); - - my_error = NULL; - reply = _g_vfs_daemon_call_sync (message, - NULL, - NULL, NULL, NULL, - cancellable, &my_error); - - dbus_message_unref (message); - - if (reply == NULL) - { - if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY)) - { - g_error_free (my_error); - goto retry; - } - g_propagate_error (error, my_error); - return FALSE; - } - - dbus_message_unref (reply); - return TRUE; -} - -struct ProgressCallbackData { - GFileProgressCallback progress_callback; - gpointer progress_callback_data; -}; - -static DBusHandlerResult -progress_callback_message (DBusConnection *connection, - DBusMessage *message, - void *user_data) -{ - struct ProgressCallbackData *data = user_data; - dbus_uint64_t current_dbus, total_dbus; - - if (dbus_message_is_method_call (message, - G_VFS_DBUS_PROGRESS_INTERFACE, - G_VFS_DBUS_PROGRESS_OP_PROGRESS)) - { - if (dbus_message_get_args (message, NULL, - DBUS_TYPE_UINT64, ¤t_dbus, - DBUS_TYPE_UINT64, &total_dbus, - 0)) - data->progress_callback (current_dbus, total_dbus, data->progress_callback_data); - } - else - g_warning ("Unknown progress callback message type\n"); - - /* TODO: demarshal args and call reall callback */ - return DBUS_HANDLER_RESULT_HANDLED; -} - -static gboolean -file_transfer (GFile *source, - GFile *destination, - GFileCopyFlags flags, - gboolean remove_source, - GCancellable *cancellable, - GFileProgressCallback progress_callback, - gpointer progress_callback_data, - GError **error) -{ - DBusMessage *reply; - char *obj_path, *dbus_obj_path; - dbus_uint32_t flags_dbus; - dbus_bool_t dbus_remove_source; - struct ProgressCallbackData data; - char *local_path = NULL; - gboolean source_is_daemon; - gboolean dest_is_daemon; - gboolean native_transfer; - - native_transfer = FALSE; - source_is_daemon = G_IS_DAEMON_FILE (source); - dest_is_daemon = G_IS_DAEMON_FILE (destination); - - if (source_is_daemon && dest_is_daemon) - native_transfer = TRUE; - else if (dest_is_daemon && !source_is_daemon) - local_path = g_file_get_path (source); - else if (source_is_daemon && !dest_is_daemon) - local_path = g_file_get_path (destination); - else - { - /* Fall back to default copy/move */ - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "Operation not supported"); - return FALSE; - } - - if (!native_transfer && local_path == NULL) - { - /* This will cause the fallback code to be involved */ - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - _("Operation not supported, files on different mounts")); - return FALSE; - - } - - if (progress_callback) - { - obj_path = g_strdup_printf ("/org/gtk/vfs/callback/%p", &obj_path); - dbus_obj_path = obj_path; - } - else - { - obj_path = NULL; - /* Can't pass NULL obj path as arg */ - dbus_obj_path = "/org/gtk/vfs/void"; - } - - data.progress_callback = progress_callback; - data.progress_callback_data = progress_callback_data; - - flags_dbus = flags; - dbus_remove_source = remove_source; - - if (native_transfer == TRUE) - { - const char *method_string; - - if (remove_source == FALSE) - method_string = G_VFS_DBUS_MOUNT_OP_COPY; - else - method_string = G_VFS_DBUS_MOUNT_OP_MOVE; - - reply = do_sync_2_path_call (source, destination, - method_string, - obj_path, progress_callback_message, &data, - NULL, cancellable, error, - DBUS_TYPE_UINT32, &flags_dbus, - DBUS_TYPE_OBJECT_PATH, &dbus_obj_path, - 0); - } - else if (dest_is_daemon == TRUE) - { - reply = do_sync_2_path_call (destination, NULL, - G_VFS_DBUS_MOUNT_OP_PUSH, - obj_path, progress_callback_message, &data, - NULL, cancellable, error, - G_DBUS_TYPE_CSTRING, &local_path, - DBUS_TYPE_UINT32, &flags_dbus, - DBUS_TYPE_OBJECT_PATH, &dbus_obj_path, - DBUS_TYPE_BOOLEAN, &dbus_remove_source, - 0); - } - else - { - reply = do_sync_2_path_call (source, NULL, - G_VFS_DBUS_MOUNT_OP_PULL, - obj_path, progress_callback_message, &data, - NULL, cancellable, error, - G_DBUS_TYPE_CSTRING, &local_path, - DBUS_TYPE_UINT32, &flags_dbus, - DBUS_TYPE_OBJECT_PATH, &dbus_obj_path, - DBUS_TYPE_BOOLEAN, &dbus_remove_source, - 0); - - } - - g_free (local_path); - g_free (obj_path); - - if (reply == NULL) - return FALSE; - - dbus_message_unref (reply); - return TRUE; -} - -static gboolean -g_daemon_file_copy (GFile *source, - GFile *destination, - GFileCopyFlags flags, - GCancellable *cancellable, - GFileProgressCallback progress_callback, - gpointer progress_callback_data, - GError **error) -{ - gboolean result; - - result = file_transfer (source, - destination, - flags, - FALSE, - cancellable, - progress_callback, - progress_callback_data, - error); - - return result; -} - -static gboolean -g_daemon_file_move (GFile *source, - GFile *destination, - GFileCopyFlags flags, - GCancellable *cancellable, - GFileProgressCallback progress_callback, - gpointer progress_callback_data, - GError **error) -{ - gboolean result; - - result = file_transfer (source, - destination, - flags, - TRUE, - cancellable, - progress_callback, - progress_callback_data, - error); - - return result; -} - -static GFileMonitor* -g_daemon_file_monitor_dir (GFile* file, - GFileMonitorFlags flags, - GCancellable *cancellable, - GError **error) -{ - GFileMonitor *monitor; - char *obj_path; - dbus_uint32_t flags_dbus; - GMountInfo *mount_info; - DBusMessage *reply; - - flags_dbus = flags; - - mount_info = NULL; - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_CREATE_DIR_MONITOR, - &mount_info, NULL, - cancellable, error, - DBUS_TYPE_UINT32, &flags_dbus, - 0); - - if (reply == NULL) - { - if (mount_info) - g_mount_info_unref (mount_info); - return NULL; - } - - if (!dbus_message_get_args (reply, NULL, - DBUS_TYPE_OBJECT_PATH, &obj_path, - DBUS_TYPE_INVALID)) - { - g_mount_info_unref (mount_info); - dbus_message_unref (reply); - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from monitor_dir")); - return NULL; - } - - monitor = g_daemon_file_monitor_new (mount_info->dbus_id, - obj_path); - - g_mount_info_unref (mount_info); - dbus_message_unref (reply); - - return monitor; -} - -static GFileMonitor* -g_daemon_file_monitor_file (GFile* file, - GFileMonitorFlags flags, - GCancellable *cancellable, - GError **error) -{ - GFileMonitor *monitor; - char *obj_path; - dbus_uint32_t flags_dbus; - GMountInfo *mount_info; - DBusMessage *reply; - - flags_dbus = flags; - - mount_info = NULL; - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_CREATE_FILE_MONITOR, - &mount_info, NULL, - cancellable, error, - DBUS_TYPE_UINT32, &flags_dbus, - 0); - - if (reply == NULL) - { - if (mount_info) - g_mount_info_unref (mount_info); - return NULL; - } - - if (!dbus_message_get_args (reply, NULL, - DBUS_TYPE_OBJECT_PATH, &obj_path, - DBUS_TYPE_INVALID)) - { - g_mount_info_unref (mount_info); - dbus_message_unref (reply); - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from monitor_file")); - return NULL; - } - - monitor = g_daemon_file_monitor_new (mount_info->dbus_id, - obj_path); - - g_mount_info_unref (mount_info); - dbus_message_unref (reply); - - return monitor; -} - -typedef struct -{ - GSimpleAsyncResult *result; - dbus_bool_t can_seek; - guint64 initial_offset; -} -StreamOpenParams; - -static void -stream_open_cb (gint fd, StreamOpenParams *params) -{ - GFileOutputStream *output_stream; - - if (fd == -1) - { - g_simple_async_result_set_error (params->result, G_IO_ERROR, G_IO_ERROR_FAILED, - "%s", _("Didn't get stream file descriptor")); - goto out; - } - - output_stream = g_daemon_file_output_stream_new (fd, params->can_seek, params->initial_offset); - g_simple_async_result_set_op_res_gpointer (params->result, output_stream, g_object_unref); - -out: - g_simple_async_result_complete (params->result); - g_object_unref (params->result); - g_slice_free (StreamOpenParams, params); -} - -static void -append_to_async_cb (DBusMessage *reply, - DBusConnection *connection, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) -{ - guint32 fd_id; - StreamOpenParams *open_params; - - open_params = g_slice_new0 (StreamOpenParams); - - if (!dbus_message_get_args (reply, NULL, - DBUS_TYPE_UINT32, &fd_id, - DBUS_TYPE_BOOLEAN, &open_params->can_seek, - DBUS_TYPE_UINT64, &open_params->initial_offset, - DBUS_TYPE_INVALID)) - { - g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, - "%s", _("Invalid return value from open")); - goto failure; - } - - open_params->result = g_object_ref (result); - _g_dbus_connection_get_fd_async (connection, fd_id, - (GetFdAsyncCallback) stream_open_cb, open_params); - return; - -failure: - g_slice_free (StreamOpenParams, open_params); - g_simple_async_result_complete (result); -} - -static void -g_daemon_file_append_to_async (GFile *file, - GFileCreateFlags flags, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - guint16 mode; - dbus_bool_t make_backup; - guint32 dbus_flags; - char *etag; - - mode = 1; - etag = ""; - make_backup = FALSE; - dbus_flags = flags; - - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE, - cancellable, - callback, user_data, - append_to_async_cb, NULL, NULL, - DBUS_TYPE_UINT16, &mode, - DBUS_TYPE_STRING, &etag, - DBUS_TYPE_BOOLEAN, &make_backup, - DBUS_TYPE_UINT32, &dbus_flags, - 0); -} - -static GFileOutputStream * -g_daemon_file_append_to_finish (GFile *file, - GAsyncResult *res, - GError **error) -{ - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); - GFileOutputStream *output_stream; - - output_stream = g_simple_async_result_get_op_res_gpointer (simple); - if (output_stream) - return g_object_ref (output_stream); - - return NULL; -} - -static void -create_async_cb (DBusMessage *reply, - DBusConnection *connection, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) -{ - guint32 fd_id; - StreamOpenParams *open_params; - - open_params = g_slice_new0 (StreamOpenParams); - - if (!dbus_message_get_args (reply, NULL, - DBUS_TYPE_UINT32, &fd_id, - DBUS_TYPE_BOOLEAN, &open_params->can_seek, - DBUS_TYPE_UINT64, &open_params->initial_offset, - DBUS_TYPE_INVALID)) - { - g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, - "%s", _("Invalid return value from open")); - goto failure; - } - - open_params->result = g_object_ref (result); - _g_dbus_connection_get_fd_async (connection, fd_id, - (GetFdAsyncCallback) stream_open_cb, open_params); - return; - -failure: - g_slice_free (StreamOpenParams, open_params); - g_simple_async_result_complete (result); -} - -static void -g_daemon_file_create_async (GFile *file, - GFileCreateFlags flags, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - guint16 mode; - dbus_bool_t make_backup; - char *etag; - guint32 dbus_flags; - - mode = 0; - etag = ""; - make_backup = FALSE; - dbus_flags = flags; - - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE, - cancellable, - callback, user_data, - create_async_cb, NULL, NULL, - DBUS_TYPE_UINT16, &mode, - DBUS_TYPE_STRING, &etag, - DBUS_TYPE_BOOLEAN, &make_backup, - DBUS_TYPE_UINT32, &dbus_flags, - 0); -} - -static GFileOutputStream * -g_daemon_file_create_finish (GFile *file, - GAsyncResult *res, - GError **error) -{ - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); - GFileOutputStream *output_stream; - - output_stream = g_simple_async_result_get_op_res_gpointer (simple); - if (output_stream) - return g_object_ref (output_stream); - - return NULL; -} - -static void -enumerate_children_async_cb (DBusMessage *reply, - DBusConnection *connection, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) -{ - GDaemonFileEnumerator *enumerator = callback_data; - - if (reply == NULL || connection == NULL) - { - g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, - "Invalid return value from enumerate_children"); - goto out; - } - - g_object_ref (enumerator); - - g_simple_async_result_set_op_res_gpointer (result, enumerator, g_object_unref); - -out: - g_simple_async_result_complete (result); -} - -static void -g_daemon_file_enumerate_children_async (GFile *file, - const char *attributes, - GFileQueryInfoFlags flags, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - dbus_uint32_t flags_dbus; - char *obj_path; - GDaemonFileEnumerator *enumerator; - char *uri; - - enumerator = g_daemon_file_enumerator_new (file); - obj_path = g_daemon_file_enumerator_get_object_path (enumerator); - - uri = g_file_get_uri (file); - - if (attributes == NULL) - attributes = ""; - flags_dbus = flags; - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_ENUMERATE, - cancellable, - callback, user_data, - enumerate_children_async_cb, enumerator, g_object_unref, - DBUS_TYPE_STRING, &obj_path, - DBUS_TYPE_STRING, &attributes, - DBUS_TYPE_UINT32, &flags_dbus, - DBUS_TYPE_STRING, &uri, - 0); - g_free (uri); - g_free (obj_path); -} - -static GFileEnumerator * -g_daemon_file_enumerate_children_finish (GFile *file, - GAsyncResult *res, - GError **error) -{ - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); - GDaemonFileEnumerator *enumerator; - - enumerator = g_simple_async_result_get_op_res_gpointer (simple); - if (enumerator) - return g_object_ref (enumerator); - - return NULL; -} - -typedef struct -{ - GFile *file; - GSimpleAsyncResult *result; - GCancellable *cancellable; -} -FindEnclosingMountData; - -static void -find_enclosing_mount_cb (GMountInfo *mount_info, - gpointer user_data, - GError *error) -{ - FindEnclosingMountData *data = user_data; - GError *my_error = NULL; - - if (data->cancellable && g_cancellable_set_error_if_cancelled (data->cancellable, &my_error)) - { - g_simple_async_result_set_from_error (data->result, my_error); - goto out; - } - - if (error) - { - g_simple_async_result_set_from_error (data->result, error); - goto out; - } - - if (!mount_info) - { - g_simple_async_result_set_error (data->result, G_IO_ERROR, G_IO_ERROR_FAILED, - "Internal error: \"%s\"", - "No error but no mount info from g_daemon_vfs_get_mount_info_async"); - goto out; - } - - if (mount_info->user_visible) - { - GDaemonMount *mount; - - /* if we have a daemon volume monitor then return one of it's mounts */ - mount = g_daemon_volume_monitor_find_mount_by_mount_info (mount_info); - if (mount == NULL) - mount = g_daemon_mount_new (mount_info, NULL); - - if (mount) - g_simple_async_result_set_op_res_gpointer (data->result, mount, g_object_unref); - else - g_simple_async_result_set_error (data->result, G_IO_ERROR, G_IO_ERROR_FAILED, - "Internal error: \"%s\"", - "Mount info did not yield a mount"); - } - -out: - g_simple_async_result_complete (data->result); - - if (my_error) - g_error_free (my_error); - if (data->cancellable) - g_object_unref (data->cancellable); - g_object_unref (data->file); - g_object_unref (data->result); - g_free (data); -} - -static void -g_daemon_file_find_enclosing_mount_async (GFile *file, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GDaemonFile *daemon_file = G_DAEMON_FILE (file); - FindEnclosingMountData *data; - - data = g_new0 (FindEnclosingMountData, 1); - - data->result = g_simple_async_result_new (G_OBJECT (file), - callback, user_data, - NULL); - data->file = g_object_ref (file); - - if (cancellable) - data->cancellable = g_object_ref (cancellable); - - _g_daemon_vfs_get_mount_info_async (daemon_file->mount_spec, - daemon_file->path, - find_enclosing_mount_cb, - data); -} - -static GMount * -g_daemon_file_find_enclosing_mount_finish (GFile *file, - GAsyncResult *res, - GError **error) -{ - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); - GMount *mount; - - mount = g_simple_async_result_get_op_res_gpointer (simple); - if (mount) - return g_object_ref (mount); - - return NULL; -} - -static void -replace_async_cb (DBusMessage *reply, - DBusConnection *connection, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) -{ - guint32 fd_id; - StreamOpenParams *open_params; - - open_params = g_slice_new0 (StreamOpenParams); - - if (!dbus_message_get_args (reply, NULL, - DBUS_TYPE_UINT32, &fd_id, - DBUS_TYPE_BOOLEAN, &open_params->can_seek, - DBUS_TYPE_UINT64, &open_params->initial_offset, - DBUS_TYPE_INVALID)) - { - g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, - "%s", _("Invalid return value from open")); - goto failure; - } - - open_params->result = g_object_ref (result); - _g_dbus_connection_get_fd_async (connection, fd_id, - (GetFdAsyncCallback) stream_open_cb, open_params); - return; - -failure: - g_slice_free (StreamOpenParams, open_params); - g_simple_async_result_complete (result); -} - -static void -g_daemon_file_replace_async (GFile *file, - const char *etag, - gboolean make_backup, - GFileCreateFlags flags, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - dbus_bool_t dbus_make_backup = make_backup; - guint32 dbus_flags = flags; - guint16 mode = 2; - - if (etag == NULL) - etag = ""; - - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE, - cancellable, - callback, user_data, - replace_async_cb, NULL, NULL, - DBUS_TYPE_UINT16, &mode, - DBUS_TYPE_STRING, &etag, - DBUS_TYPE_BOOLEAN, &dbus_make_backup, - DBUS_TYPE_UINT32, &dbus_flags, - 0); -} - -static GFileOutputStream * -g_daemon_file_replace_finish (GFile *file, - GAsyncResult *res, - GError **error) -{ - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); - GFileOutputStream *output_stream; - - output_stream = g_simple_async_result_get_op_res_gpointer (simple); - if (output_stream) - return g_object_ref (output_stream); - - return NULL; -} - -static void -set_display_name_async_cb (DBusMessage *reply, - DBusConnection *connection, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) -{ - GDaemonFile *daemon_file = callback_data; - GFile *file; - DBusMessageIter iter; - gchar *new_path; - - if (!dbus_message_iter_init (reply, &iter) || - !_g_dbus_message_iter_get_args (&iter, NULL, - G_DBUS_TYPE_CSTRING, &new_path, - 0)) - { - g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, - "%s", "Invalid return value from set_display_name"); - goto out; - } - - file = new_file_for_new_path (daemon_file, new_path); - g_free (new_path); - - g_simple_async_result_set_op_res_gpointer (result, file, g_object_unref); - -out: - g_simple_async_result_complete (result); -} - -static void -g_daemon_file_set_display_name_async (GFile *file, - const char *display_name, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_object_ref (file); - - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_SET_DISPLAY_NAME, - cancellable, - callback, user_data, - set_display_name_async_cb, file, g_object_unref, - DBUS_TYPE_STRING, &display_name, - 0); -} - -static GFile * -g_daemon_file_set_display_name_finish (GFile *file, - GAsyncResult *res, - GError **error) -{ - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); - GFile *new_file; - - new_file = g_simple_async_result_get_op_res_gpointer (simple); - return new_file; -} - -#if 0 - -static void -g_daemon_file_set_attributes_async (GFile *file, - GFileInfo *info, - GFileQueryInfoFlags flags, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* TODO */ -} - -static gboolean -g_daemon_file_set_attributes_finish (GFile *file, - GAsyncResult *result, - GFileInfo **info, - GError **error) -{ - /* TODO */ -} - -#endif - -static void -g_daemon_file_file_iface_init (GFileIface *iface) -{ - iface->dup = g_daemon_file_dup; - iface->hash = g_daemon_file_hash; - iface->equal = g_daemon_file_equal; - iface->is_native = g_daemon_file_is_native; - iface->has_uri_scheme = g_daemon_file_has_uri_scheme; - iface->get_uri_scheme = g_daemon_file_get_uri_scheme; - iface->get_basename = g_daemon_file_get_basename; - iface->get_path = g_daemon_file_get_path; - iface->get_uri = g_daemon_file_get_uri; - iface->get_parse_name = g_daemon_file_get_parse_name; - iface->get_parent = g_daemon_file_get_parent; - iface->prefix_matches = g_daemon_file_prefix_matches; - iface->get_relative_path = g_daemon_file_get_relative_path; - iface->resolve_relative_path = g_daemon_file_resolve_relative_path; - iface->get_child_for_display_name = g_daemon_file_get_child_for_display_name; - iface->enumerate_children = g_daemon_file_enumerate_children; - iface->query_info = g_daemon_file_query_info; - iface->query_info_async = g_daemon_file_query_info_async; - iface->query_info_finish = g_daemon_file_query_info_finish; - iface->find_enclosing_mount = g_daemon_file_find_enclosing_mount; - iface->read_fn = g_daemon_file_read; - iface->append_to = g_daemon_file_append_to; - iface->create = g_daemon_file_create; - iface->replace = g_daemon_file_replace; - iface->read_async = g_daemon_file_read_async; - iface->read_finish = g_daemon_file_read_finish; - iface->mount_enclosing_volume = g_daemon_file_mount_enclosing_volume; - iface->mount_enclosing_volume_finish = g_daemon_file_mount_enclosing_volume_finish; - iface->mount_mountable = g_daemon_file_mount_mountable; - iface->mount_mountable_finish = g_daemon_file_mount_mountable_finish; - iface->unmount_mountable = g_daemon_file_unmount_mountable; - iface->unmount_mountable_finish = g_daemon_file_unmount_mountable_finish; - iface->eject_mountable = g_daemon_file_eject_mountable; - iface->eject_mountable_finish = g_daemon_file_eject_mountable_finish; - iface->query_filesystem_info = g_daemon_file_query_filesystem_info; - iface->query_filesystem_info_async = g_daemon_file_query_filesystem_info_async; - iface->query_filesystem_info_finish = g_daemon_file_query_filesystem_info_finish; - iface->set_display_name = g_daemon_file_set_display_name; - iface->delete_file = g_daemon_file_delete; - iface->trash = g_daemon_file_trash; - iface->make_directory = g_daemon_file_make_directory; - iface->copy = g_daemon_file_copy; - iface->move = g_daemon_file_move; - iface->query_settable_attributes = g_daemon_file_query_settable_attributes; - iface->query_writable_namespaces = g_daemon_file_query_writable_namespaces; - iface->set_attribute = g_daemon_file_set_attribute; - iface->make_symbolic_link = g_daemon_file_make_symbolic_link; - iface->monitor_dir = g_daemon_file_monitor_dir; - iface->monitor_file = g_daemon_file_monitor_file; - - /* Async operations */ - - iface->append_to_async = g_daemon_file_append_to_async; - iface->append_to_finish = g_daemon_file_append_to_finish; - iface->create_async = g_daemon_file_create_async; - iface->create_finish = g_daemon_file_create_finish; - iface->enumerate_children_async = g_daemon_file_enumerate_children_async; - iface->enumerate_children_finish = g_daemon_file_enumerate_children_finish; - iface->find_enclosing_mount_async = g_daemon_file_find_enclosing_mount_async; - iface->find_enclosing_mount_finish = g_daemon_file_find_enclosing_mount_finish; - iface->replace_async = g_daemon_file_replace_async; - iface->replace_finish = g_daemon_file_replace_finish; - iface->set_display_name_async = g_daemon_file_set_display_name_async; - iface->set_display_name_finish = g_daemon_file_set_display_name_finish; -#if 0 - iface->set_attributes_async = g_daemon_file_set_attributes_async; - iface->set_attributes_finish = g_daemon_file_set_attributes_finish; -#endif -} diff --git a/gnome-2-24/client/gdaemonfile.h b/gnome-2-24/client/gdaemonfile.h deleted file mode 100644 index 297066a9..00000000 --- a/gnome-2-24/client/gdaemonfile.h +++ /dev/null @@ -1,54 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -#ifndef __G_DAEMON_FILE_H__ -#define __G_DAEMON_FILE_H__ - -#include <gio/gio.h> -#include "gdaemonvfs.h" -#include "gmountspec.h" - -G_BEGIN_DECLS - -#define G_TYPE_DAEMON_FILE (g_daemon_file_get_type ()) -#define G_DAEMON_FILE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DAEMON_FILE, GDaemonFile)) -#define G_DAEMON_FILE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DAEMON_FILE, GDaemonFileClass)) -#define G_IS_DAEMON_FILE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DAEMON_FILE)) -#define G_IS_DAEMON_FILE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DAEMON_FILE)) -#define G_DAEMON_FILE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_DAEMON_FILE, GDaemonFileClass)) - -typedef struct _GDaemonFile GDaemonFile; -typedef struct _GDaemonFileClass GDaemonFileClass; - -struct _GDaemonFileClass -{ - GObjectClass parent_class; -}; - -GType g_daemon_file_get_type (void) G_GNUC_CONST; - -GFile * g_daemon_file_new (GMountSpec *mount_spec, - const char *path); - -G_END_DECLS - -#endif /* __G_DAEMON_FILE_H__ */ diff --git a/gnome-2-24/client/gdaemonfileenumerator.c b/gnome-2-24/client/gdaemonfileenumerator.c deleted file mode 100644 index 56b1488d..00000000 --- a/gnome-2-24/client/gdaemonfileenumerator.c +++ /dev/null @@ -1,461 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -#include <config.h> - -#include <stdlib.h> -#include <string.h> -#include <glib.h> -#include <glib/gi18n-lib.h> -#include <gdaemonfileenumerator.h> -#include <gio/gio.h> -#include <gvfsdaemondbus.h> -#include <gvfsdaemonprotocol.h> - -#define OBJ_PATH_PREFIX "/org/gtk/vfs/client/enumerator/" - -/* atomic */ -static volatile gint path_counter = 1; - -G_LOCK_DEFINE_STATIC(infos); - -struct _GDaemonFileEnumerator -{ - GFileEnumerator parent; - - gint id; - DBusConnection *sync_connection; /* NULL if async, i.e. we're listening on main dbus connection */ - - /* protected by infos lock */ - GList *infos; - gboolean done; - - /* For async ops, also protected by infos lock */ - int async_requested_files; - GCancellable *async_cancel; - gulong cancelled_tag; - guint timeout_tag; - GSimpleAsyncResult *async_res; -}; - -G_DEFINE_TYPE (GDaemonFileEnumerator, g_daemon_file_enumerator, G_TYPE_FILE_ENUMERATOR) - -static GFileInfo * g_daemon_file_enumerator_next_file (GFileEnumerator *enumerator, - GCancellable *cancellable, - GError **error); -static void g_daemon_file_enumerator_next_files_async (GFileEnumerator *enumerator, - int num_files, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -static GList * g_daemon_file_enumerator_next_files_finish (GFileEnumerator *enumerator, - GAsyncResult *result, - GError **error); -static gboolean g_daemon_file_enumerator_close (GFileEnumerator *enumerator, - GCancellable *cancellable, - GError **error); -static void g_daemon_file_enumerator_close_async (GFileEnumerator *enumerator, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -static gboolean g_daemon_file_enumerator_close_finish (GFileEnumerator *enumerator, - GAsyncResult *result, - GError **error); -static DBusHandlerResult g_daemon_file_enumerator_dbus_filter (DBusConnection *connection, - DBusMessage *message, - void *user_data); - -static void -free_info_list (GList *infos) -{ - g_list_foreach (infos, (GFunc)g_object_unref, NULL); - g_list_free (infos); -} - -static void -g_daemon_file_enumerator_finalize (GObject *object) -{ - GDaemonFileEnumerator *daemon; - char *path; - - daemon = G_DAEMON_FILE_ENUMERATOR (object); - - path = g_daemon_file_enumerator_get_object_path (daemon); - _g_dbus_unregister_vfs_filter (path); - g_free (path); - - free_info_list (daemon->infos); - - if (daemon->sync_connection) - dbus_connection_unref (daemon->sync_connection); - - if (G_OBJECT_CLASS (g_daemon_file_enumerator_parent_class)->finalize) - (*G_OBJECT_CLASS (g_daemon_file_enumerator_parent_class)->finalize) (object); -} - - -static void -g_daemon_file_enumerator_class_init (GDaemonFileEnumeratorClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GFileEnumeratorClass *enumerator_class = G_FILE_ENUMERATOR_CLASS (klass); - - gobject_class->finalize = g_daemon_file_enumerator_finalize; - - enumerator_class->next_file = g_daemon_file_enumerator_next_file; - enumerator_class->next_files_async = g_daemon_file_enumerator_next_files_async; - enumerator_class->next_files_finish = g_daemon_file_enumerator_next_files_finish; - enumerator_class->close_fn = g_daemon_file_enumerator_close; - enumerator_class->close_async = g_daemon_file_enumerator_close_async; - enumerator_class->close_finish = g_daemon_file_enumerator_close_finish; -} - -static void -g_daemon_file_enumerator_init (GDaemonFileEnumerator *daemon) -{ - char *path; - - daemon->id = g_atomic_int_exchange_and_add (&path_counter, 1); - - path = g_daemon_file_enumerator_get_object_path (daemon); - _g_dbus_register_vfs_filter (path, g_daemon_file_enumerator_dbus_filter, - G_OBJECT (daemon)); - g_free (path); -} - -GDaemonFileEnumerator * -g_daemon_file_enumerator_new (GFile *file) -{ - GDaemonFileEnumerator *daemon; - - daemon = g_object_new (G_TYPE_DAEMON_FILE_ENUMERATOR, - "container", file, - NULL); - - return daemon; -} - -/* Called with infos lock held */ -static void -trigger_async_done (GDaemonFileEnumerator *daemon, gboolean ok) -{ - GList *rest, *l; - - if (ok) - { - l = daemon->infos; - rest = g_list_nth (l, daemon->async_requested_files); - if (rest) - { - /* Split list */ - rest->prev->next = NULL; - rest->prev = NULL; - } - daemon->infos = rest; - - g_simple_async_result_set_op_res_gpointer (daemon->async_res, - l, - (GDestroyNotify)free_info_list); - } - - g_simple_async_result_complete_in_idle (daemon->async_res); - - if (daemon->cancelled_tag != 0) - g_signal_handler_disconnect (daemon->async_cancel, - daemon->cancelled_tag); - daemon->async_cancel = 0; - daemon->cancelled_tag = 0; - - if (daemon->timeout_tag != 0) - g_source_remove (daemon->timeout_tag); - daemon->timeout_tag = 0; - - daemon->async_requested_files = 0; - - g_object_unref (daemon->async_res); - daemon->async_res = NULL; -} - -static DBusHandlerResult -g_daemon_file_enumerator_dbus_filter (DBusConnection *connection, - DBusMessage *message, - void *user_data) -{ - GDaemonFileEnumerator *enumerator = user_data; - const char *member; - DBusMessageIter iter, array_iter; - GList *infos; - GFileInfo *info; - - member = dbus_message_get_member (message); - - if (strcmp (member, G_VFS_DBUS_ENUMERATOR_OP_DONE) == 0) - { - G_LOCK (infos); - enumerator->done = TRUE; - if (enumerator->async_requested_files > 0) - trigger_async_done (enumerator, TRUE); - G_UNLOCK (infos); - return DBUS_HANDLER_RESULT_HANDLED; - } - else if (strcmp (member, G_VFS_DBUS_ENUMERATOR_OP_GOT_INFO) == 0) - { - infos = NULL; - - dbus_message_iter_init (message, &iter); - if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_ARRAY && - dbus_message_iter_get_element_type (&iter) == DBUS_TYPE_STRUCT) - { - dbus_message_iter_recurse (&iter, &array_iter); - - while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT) - { - info = _g_dbus_get_file_info (&array_iter, NULL); - if (info) - g_assert (G_IS_FILE_INFO (info)); - - if (info) - infos = g_list_prepend (infos, info); - - dbus_message_iter_next (&iter); - } - } - - infos = g_list_reverse (infos); - - G_LOCK (infos); - enumerator->infos = g_list_concat (enumerator->infos, infos); - if (enumerator->async_requested_files > 0 && - g_list_length (enumerator->infos) >= enumerator->async_requested_files) - trigger_async_done (enumerator, TRUE); - G_UNLOCK (infos); - return DBUS_HANDLER_RESULT_HANDLED; - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -char * -g_daemon_file_enumerator_get_object_path (GDaemonFileEnumerator *enumerator) -{ - return g_strdup_printf (OBJ_PATH_PREFIX"%d", enumerator->id); -} - -void -g_daemon_file_enumerator_set_sync_connection (GDaemonFileEnumerator *enumerator, - DBusConnection *connection) -{ - enumerator->sync_connection = dbus_connection_ref (connection); -} - -static GFileInfo * -g_daemon_file_enumerator_next_file (GFileEnumerator *enumerator, - GCancellable *cancellable, - GError **error) -{ - GDaemonFileEnumerator *daemon = G_DAEMON_FILE_ENUMERATOR (enumerator); - GFileInfo *info; - gboolean done; - int count; - - info = NULL; - done = FALSE; - count = 0; - while (count++ < G_VFS_DBUS_TIMEOUT_MSECS / 100) - { - G_LOCK (infos); - if (daemon->infos) - { - done = TRUE; - info = daemon->infos->data; - if (info) - g_assert (G_IS_FILE_INFO (info)); - daemon->infos = g_list_delete_link (daemon->infos, daemon->infos); - } - else if (daemon->done) - done = TRUE; - G_UNLOCK (infos); - - if (info) - g_assert (G_IS_FILE_INFO (info)); - - if (done) - break; - - /* We sleep only 100 msecs here, not the full time because we might have - * raced with the filter func being called after unlocking - * and setting done or ->infos. So, we want to check it again reasonaby soon. - */ - if (daemon->sync_connection != NULL) - { - /* The initializing call for the enumerator was a sync one, and we - have a reference to its private connection. In order to ensure we - get the responses sent to that originating connection we pump it - here. - This should be safe as we're either on the thread that did the call - so its our connection, or its the private connection for another - thread. If that thread is idle the pumping won't affect anything, and - if it is doing something thats ok to, because we don't use filters - on the private sync connections so we won't cause any reentrancy - (except the file enumerator filter, but that is safe to run in - some other thread). - */ - if (!dbus_connection_read_write_dispatch (daemon->sync_connection, 100)) - break; - } - else - { - /* The enumerator was initialized by an async call, so responses will - come to the async dbus connection. We can't pump that as that would - cause all sort of filters and stuff to run, possibly on the wrong - thread. If you want to do async next_files you must create the - enumerator asynchrounously. - */ - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Can't do synchronous next_files() on a file enumerator created asynchronously"); - return NULL; - } - } - - return info; -} - -static void -async_cancelled (GCancellable *cancellable, - GDaemonFileEnumerator *daemon) -{ - g_simple_async_result_set_error (daemon->async_res, - G_IO_ERROR, - G_IO_ERROR_CANCELLED, - _("Operation was cancelled")); - trigger_async_done (daemon, FALSE); -} - -static gboolean -async_timeout (gpointer data) -{ - GDaemonFileEnumerator *daemon = G_DAEMON_FILE_ENUMERATOR (data); - trigger_async_done (daemon, TRUE); - return FALSE; -} - -static void -g_daemon_file_enumerator_next_files_async (GFileEnumerator *enumerator, - int num_files, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GDaemonFileEnumerator *daemon = G_DAEMON_FILE_ENUMERATOR (enumerator); - - if (daemon->sync_connection != NULL) - { - /* If the enumerator was created synchronously then the connection used - * for return messages will be the private connection for that thread. - * We can't rely on it being pumped, so we don't support this. - * We could possibly pump it ourselves in this case, but i'm not sure - * how much sense this makes, so we don't for now. - */ - g_simple_async_report_error_in_idle (G_OBJECT (enumerator), - callback, - user_data, - G_IO_ERROR, G_IO_ERROR_FAILED, - "Can't do asynchronous next_files() on a file enumerator created synchronously"); - return; - } - - G_LOCK (infos); - daemon->async_cancel = cancellable; - daemon->cancelled_tag = 0; - daemon->timeout_tag = 0; - daemon->async_requested_files = num_files; - daemon->async_res = g_simple_async_result_new (G_OBJECT (enumerator), callback, user_data, - g_daemon_file_enumerator_next_files_async); - - /* Maybe we already have enough info to fulfill the requeust already */ - if (daemon->done || - g_list_length (daemon->infos) >= daemon->async_requested_files) - trigger_async_done (daemon, TRUE); - else - { - if (cancellable) - daemon->cancelled_tag = g_signal_connect (cancellable, "cancelled", (GCallback)async_cancelled, daemon); - daemon->timeout_tag = g_timeout_add (G_VFS_DBUS_TIMEOUT_MSECS, - async_timeout, daemon); - } - - G_UNLOCK (infos); -} - -static GList * -g_daemon_file_enumerator_next_files_finish (GFileEnumerator *enumerator, - GAsyncResult *result, - GError **error) -{ - GList *l; - - l = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result)); - /* We want the caller to own this, and not the result, so clear the result data */ - g_simple_async_result_set_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result), - NULL, NULL); - - return l; -} - -static gboolean -g_daemon_file_enumerator_close (GFileEnumerator *enumerator, - GCancellable *cancellable, - GError **error) -{ - /*GDaemonFileEnumerator *daemon = G_DAEMON_FILE_ENUMERATOR (enumerator); */ - - return TRUE; -} - - -/* We want an explicitly async version of close (doing nothing) to avoid - the default thread-using version. */ -static void -g_daemon_file_enumerator_close_async (GFileEnumerator *enumerator, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GSimpleAsyncResult *res; - - res = g_simple_async_result_new (G_OBJECT (enumerator), callback, user_data, - g_daemon_file_enumerator_close_async); - g_simple_async_result_complete_in_idle (res); - g_object_unref (res); -} - -static gboolean -g_daemon_file_enumerator_close_finish (GFileEnumerator *enumerator, - GAsyncResult *result, - GError **error) -{ - return TRUE; -} diff --git a/gnome-2-24/client/gdaemonfileenumerator.h b/gnome-2-24/client/gdaemonfileenumerator.h deleted file mode 100644 index 25f5195a..00000000 --- a/gnome-2-24/client/gdaemonfileenumerator.h +++ /dev/null @@ -1,57 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -#ifndef __G_DAEMON_FILE_ENUMERATOR_H__ -#define __G_DAEMON_FILE_ENUMERATOR_H__ - -#include <gio/gio.h> -#include <dbus/dbus.h> - -G_BEGIN_DECLS - -#define G_TYPE_DAEMON_FILE_ENUMERATOR (g_daemon_file_enumerator_get_type ()) -#define G_DAEMON_FILE_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DAEMON_FILE_ENUMERATOR, GDaemonFileEnumerator)) -#define G_DAEMON_FILE_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DAEMON_FILE_ENUMERATOR, GDaemonFileEnumeratorClass)) -#define G_IS_DAEMON_FILE_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DAEMON_FILE_ENUMERATOR)) -#define G_IS_DAEMON_FILE_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DAEMON_FILE_ENUMERATOR)) -#define G_DAEMON_FILE_ENUMERATOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_DAEMON_FILE_ENUMERATOR, GDaemonFileEnumeratorClass)) - -typedef struct _GDaemonFileEnumerator GDaemonFileEnumerator; -typedef struct _GDaemonFileEnumeratorClass GDaemonFileEnumeratorClass; -typedef struct _GDaemonFileEnumeratorPrivate GDaemonFileEnumeratorPrivate; - -struct _GDaemonFileEnumeratorClass -{ - GFileEnumeratorClass parent_class; -}; - -GType g_daemon_file_enumerator_get_type (void) G_GNUC_CONST; - -GDaemonFileEnumerator *g_daemon_file_enumerator_new (GFile *file); -char * g_daemon_file_enumerator_get_object_path (GDaemonFileEnumerator *enumerator); -void g_daemon_file_enumerator_set_sync_connection (GDaemonFileEnumerator *enumerator, - DBusConnection *connection); - - -G_END_DECLS - -#endif /* __G_FILE_DAEMON_FILE_ENUMERATOR_H__ */ diff --git a/gnome-2-24/client/gdaemonfileinputstream.c b/gnome-2-24/client/gdaemonfileinputstream.c deleted file mode 100644 index 8cdc3622..00000000 --- a/gnome-2-24/client/gdaemonfileinputstream.c +++ /dev/null @@ -1,1643 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -#include <config.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <sys/socket.h> -#include <sys/un.h> - -#include <glib.h> -#include <glib/gstdio.h> -#include <glib/gi18n-lib.h> -#include <gio/gio.h> -#include <gio/gunixinputstream.h> -#include <gio/gunixoutputstream.h> -#include "gdaemonfileinputstream.h" -#include "gvfsdaemondbus.h" -#include <gvfsdaemonprotocol.h> - -#define MAX_READ_SIZE (4*1024*1024) - -typedef enum { - INPUT_STATE_IN_REPLY_HEADER, - INPUT_STATE_IN_BLOCK -} InputState; - -typedef enum { - STATE_OP_DONE, - STATE_OP_READ, - STATE_OP_WRITE, - STATE_OP_SKIP -} StateOp; - -typedef enum { - READ_STATE_INIT = 0, - READ_STATE_WROTE_COMMAND, - READ_STATE_HANDLE_INPUT, - READ_STATE_HANDLE_INPUT_BLOCK, - READ_STATE_SKIP_BLOCK, - READ_STATE_HANDLE_HEADER, - READ_STATE_READ_BLOCK -} ReadState; - -typedef struct { - ReadState state; - - /* Input */ - char *buffer; - gsize buffer_size; - /* Output */ - gssize ret_val; - GError *ret_error; - - gboolean sent_cancel; - - guint32 seq_nr; -} ReadOperation; - -typedef enum { - SEEK_STATE_INIT = 0, - SEEK_STATE_WROTE_REQUEST, - SEEK_STATE_HANDLE_INPUT, - SEEK_STATE_HANDLE_INPUT_BLOCK, - SEEK_STATE_SKIP_BLOCK, - SEEK_STATE_HANDLE_HEADER -} SeekState; - -typedef struct { - SeekState state; - - /* Input */ - goffset offset; - GSeekType seek_type; - /* Output */ - gboolean ret_val; - GError *ret_error; - goffset ret_offset; - - gboolean sent_cancel; - gboolean sent_seek; - - guint32 seq_nr; -} SeekOperation; - -typedef enum { - CLOSE_STATE_INIT = 0, - CLOSE_STATE_WROTE_REQUEST, - CLOSE_STATE_HANDLE_INPUT, - CLOSE_STATE_HANDLE_INPUT_BLOCK, - CLOSE_STATE_SKIP_BLOCK, - CLOSE_STATE_HANDLE_HEADER -} CloseState; - -typedef struct { - CloseState state; - - /* Input */ - - /* Output */ - gboolean ret_val; - GError *ret_error; - - gboolean sent_cancel; - - guint32 seq_nr; -} CloseOperation; - - -typedef struct { - gboolean cancelled; - - char *io_buffer; - gsize io_size; - gsize io_res; - /* The operation always succeeds, or gets cancelled. - If we get an error doing the i/o that is considered fatal */ - gboolean io_allow_cancel; - gboolean io_cancelled; -} IOOperationData; - -typedef StateOp (*state_machine_iterator) (GDaemonFileInputStream *file, IOOperationData *io_op, gpointer data); - -struct _GDaemonFileInputStream { - GFileInputStream parent; - - GOutputStream *command_stream; - GInputStream *data_stream; - guint can_seek : 1; - - int seek_generation; - guint32 seq_nr; - goffset current_offset; - - InputState input_state; - gsize input_block_size; - int input_block_seek_generation; - GString *input_buffer; - - GString *output_buffer; -}; - -static gssize g_daemon_file_input_stream_read (GInputStream *stream, - void *buffer, - gsize count, - GCancellable *cancellable, - GError **error); -static gssize g_daemon_file_input_stream_skip (GInputStream *stream, - gsize count, - GCancellable *cancellable, - GError **error); -static gboolean g_daemon_file_input_stream_close (GInputStream *stream, - GCancellable *cancellable, - GError **error); -static GFileInfo *g_daemon_file_input_stream_query_info (GFileInputStream *stream, - char *attributes, - GCancellable *cancellable, - GError **error); -static goffset g_daemon_file_input_stream_tell (GFileInputStream *stream); -static gboolean g_daemon_file_input_stream_can_seek (GFileInputStream *stream); -static gboolean g_daemon_file_input_stream_seek (GFileInputStream *stream, - goffset offset, - GSeekType type, - GCancellable *cancellable, - GError **error); -static void g_daemon_file_input_stream_read_async (GInputStream *stream, - void *buffer, - gsize count, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer data); -static gssize g_daemon_file_input_stream_read_finish (GInputStream *stream, - GAsyncResult *result, - GError **error); -static void g_daemon_file_input_stream_skip_async (GInputStream *stream, - gsize count, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer data); -static gssize g_daemon_file_input_stream_skip_finish (GInputStream *stream, - GAsyncResult *result, - GError **error); -static void g_daemon_file_input_stream_close_async (GInputStream *stream, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer data); -static gboolean g_daemon_file_input_stream_close_finish (GInputStream *stream, - GAsyncResult *result, - GError **error); - - -G_DEFINE_TYPE (GDaemonFileInputStream, g_daemon_file_input_stream, - G_TYPE_FILE_INPUT_STREAM) - -static void -g_daemon_file_input_stream_finalize (GObject *object) -{ - GDaemonFileInputStream *file; - - file = G_DAEMON_FILE_INPUT_STREAM (object); - - if (file->command_stream) - g_object_unref (file->command_stream); - if (file->data_stream) - g_object_unref (file->data_stream); - - g_string_free (file->input_buffer, TRUE); - g_string_free (file->output_buffer, TRUE); - - if (G_OBJECT_CLASS (g_daemon_file_input_stream_parent_class)->finalize) - (*G_OBJECT_CLASS (g_daemon_file_input_stream_parent_class)->finalize) (object); -} - -static void -g_daemon_file_input_stream_class_init (GDaemonFileInputStreamClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass); - GFileInputStreamClass *file_stream_class = G_FILE_INPUT_STREAM_CLASS (klass); - - gobject_class->finalize = g_daemon_file_input_stream_finalize; - - stream_class->read_fn = g_daemon_file_input_stream_read; - if (0) stream_class->skip = g_daemon_file_input_stream_skip; - stream_class->close_fn = g_daemon_file_input_stream_close; - - stream_class->read_async = g_daemon_file_input_stream_read_async; - stream_class->read_finish = g_daemon_file_input_stream_read_finish; - if (0) - { - stream_class->skip_async = g_daemon_file_input_stream_skip_async; - stream_class->skip_finish = g_daemon_file_input_stream_skip_finish; - } - stream_class->close_async = g_daemon_file_input_stream_close_async; - stream_class->close_finish = g_daemon_file_input_stream_close_finish; - - file_stream_class->tell = g_daemon_file_input_stream_tell; - file_stream_class->can_seek = g_daemon_file_input_stream_can_seek; - file_stream_class->seek = g_daemon_file_input_stream_seek; - file_stream_class->query_info = g_daemon_file_input_stream_query_info; - -} - -static void -g_daemon_file_input_stream_init (GDaemonFileInputStream *info) -{ - info->output_buffer = g_string_new (""); - info->input_buffer = g_string_new (""); - info->seq_nr = 1; -} - -GFileInputStream * -g_daemon_file_input_stream_new (int fd, - gboolean can_seek) -{ - GDaemonFileInputStream *stream; - - stream = g_object_new (G_TYPE_DAEMON_FILE_INPUT_STREAM, NULL); - - stream->command_stream = g_unix_output_stream_new (fd, FALSE); - stream->data_stream = g_unix_input_stream_new (fd, TRUE); - stream->can_seek = can_seek; - - return G_FILE_INPUT_STREAM (stream); -} - -static gboolean -error_is_cancel (GError *error) -{ - return error != NULL && - error->domain == G_IO_ERROR && - error->code == G_IO_ERROR_CANCELLED; -} - -static void -append_request (GDaemonFileInputStream *stream, guint32 command, - guint32 arg1, guint32 arg2, guint32 *seq_nr) -{ - GVfsDaemonSocketProtocolRequest cmd; - - g_assert (sizeof (cmd) == G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SIZE); - - if (seq_nr) - *seq_nr = stream->seq_nr; - - cmd.command = g_htonl (command); - cmd.seq_nr = g_htonl (stream->seq_nr++); - cmd.arg1 = g_htonl (arg1); - cmd.arg2 = g_htonl (arg2); - cmd.data_len = 0; - - g_string_append_len (stream->output_buffer, - (char *)&cmd, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SIZE); -} - -static gsize -get_reply_header_missing_bytes (GString *buffer) -{ - GVfsDaemonSocketProtocolReply *reply; - guint32 type; - guint32 arg2; - - if (buffer->len < G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE) - return G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE - buffer->len; - - reply = (GVfsDaemonSocketProtocolReply *)buffer->str; - - type = g_ntohl (reply->type); - arg2 = g_ntohl (reply->arg2); - - if (type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_ERROR) - return G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE + arg2 - buffer->len; - return 0; -} - -static char * -decode_reply (GString *buffer, GVfsDaemonSocketProtocolReply *reply_out) -{ - GVfsDaemonSocketProtocolReply *reply; - reply = (GVfsDaemonSocketProtocolReply *)buffer->str; - reply_out->type = g_ntohl (reply->type); - reply_out->seq_nr = g_ntohl (reply->seq_nr); - reply_out->arg1 = g_ntohl (reply->arg1); - reply_out->arg2 = g_ntohl (reply->arg2); - - return buffer->str + G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE; -} - -static void -decode_error (GVfsDaemonSocketProtocolReply *reply, char *data, GError **error) -{ - g_set_error_literal (error, - g_quark_from_string (data), - reply->arg1, - data + strlen (data) + 1); -} - - -static gboolean -run_sync_state_machine (GDaemonFileInputStream *file, - state_machine_iterator iterator, - gpointer data, - GCancellable *cancellable, - GError **error) -{ - gssize res; - StateOp io_op; - IOOperationData io_data; - GError *io_error; - - memset (&io_data, 0, sizeof (io_data)); - - while (TRUE) - { - if (cancellable) - io_data.cancelled = g_cancellable_is_cancelled (cancellable); - - io_op = iterator (file, &io_data, data); - - if (io_op == STATE_OP_DONE) - return TRUE; - - io_error = NULL; - if (io_op == STATE_OP_READ) - { - res = g_input_stream_read (file->data_stream, - io_data.io_buffer, io_data.io_size, - io_data.io_allow_cancel ? cancellable : NULL, - &io_error); - } - else if (io_op == STATE_OP_SKIP) - { - res = g_input_stream_skip (file->data_stream, - io_data.io_size, - io_data.io_allow_cancel ? cancellable : NULL, - &io_error); - } - else if (io_op == STATE_OP_WRITE) - { - res = g_output_stream_write (file->command_stream, - io_data.io_buffer, io_data.io_size, - io_data.io_allow_cancel ? cancellable : NULL, - &io_error); - } - else - { - res = 0; - g_assert_not_reached (); - } - - if (res == -1) - { - if (error_is_cancel (io_error)) - { - io_data.io_res = 0; - io_data.io_cancelled = TRUE; - g_error_free (io_error); - } - else - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Error in stream protocol: %s"), io_error->message); - g_error_free (io_error); - return FALSE; - } - } - else if (res == 0 && io_data.io_size != 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Error in stream protocol: %s"), _("End of stream")); - return FALSE; - } - else - { - io_data.io_res = res; - io_data.io_cancelled = FALSE; - } - } -} - -/* read cycle: - - if we know of a (partially read) matching outstanding block, read from it - create packet, append to outgoing - flush outgoing - start processing input, looking for a data block with same seek gen, - or an error with same seq nr - on cancel, send cancel command and go back to loop - */ - -static StateOp -iterate_read_state_machine (GDaemonFileInputStream *file, IOOperationData *io_op, ReadOperation *op) -{ - gsize len; - - while (TRUE) - { - switch (op->state) - { - /* Initial state for read op */ - case READ_STATE_INIT: - /* If we're already reading some data, but we didn't read all, just use that - and don't even send a request */ - if (file->input_state == INPUT_STATE_IN_BLOCK && - file->seek_generation == file->input_block_seek_generation) - { - op->state = READ_STATE_READ_BLOCK; - io_op->io_buffer = op->buffer; - io_op->io_size = MIN (op->buffer_size, file->input_block_size); - io_op->io_allow_cancel = TRUE; /* Allow cancel before we sent request */ - return STATE_OP_READ; - } - - append_request (file, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_READ, - op->buffer_size, 0, &op->seq_nr); - op->state = READ_STATE_WROTE_COMMAND; - io_op->io_buffer = file->output_buffer->str; - io_op->io_size = file->output_buffer->len; - io_op->io_allow_cancel = TRUE; /* Allow cancel before first byte of request sent */ - return STATE_OP_WRITE; - - /* wrote parts of output_buffer */ - case READ_STATE_WROTE_COMMAND: - if (io_op->io_cancelled) - { - op->ret_val = -1; - g_set_error_literal (&op->ret_error, - G_IO_ERROR, - G_IO_ERROR_CANCELLED, - _("Operation was cancelled")); - return STATE_OP_DONE; - } - - if (io_op->io_res < file->output_buffer->len) - { - memcpy (file->output_buffer->str, - file->output_buffer->str + io_op->io_res, - file->output_buffer->len - io_op->io_res); - g_string_truncate (file->output_buffer, - file->output_buffer->len - io_op->io_res); - io_op->io_buffer = file->output_buffer->str; - io_op->io_size = file->output_buffer->len; - io_op->io_allow_cancel = FALSE; - return STATE_OP_WRITE; - } - g_string_truncate (file->output_buffer, 0); - - op->state = READ_STATE_HANDLE_INPUT; - break; - - /* No op */ - case READ_STATE_HANDLE_INPUT: - if (io_op->cancelled && !op->sent_cancel) - { - op->sent_cancel = TRUE; - append_request (file, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CANCEL, - op->seq_nr, 0, NULL); - op->state = READ_STATE_WROTE_COMMAND; - io_op->io_buffer = file->output_buffer->str; - io_op->io_size = file->output_buffer->len; - io_op->io_allow_cancel = FALSE; - return STATE_OP_WRITE; - } - - if (file->input_state == INPUT_STATE_IN_BLOCK) - { - op->state = READ_STATE_HANDLE_INPUT_BLOCK; - break; - } - else if (file->input_state == INPUT_STATE_IN_REPLY_HEADER) - { - op->state = READ_STATE_HANDLE_HEADER; - break; - } - g_assert_not_reached (); - break; - - /* No op */ - case READ_STATE_HANDLE_INPUT_BLOCK: - g_assert (file->input_state == INPUT_STATE_IN_BLOCK); - - if (file->seek_generation == - file->input_block_seek_generation) - { - op->state = READ_STATE_READ_BLOCK; - io_op->io_buffer = op->buffer; - io_op->io_size = MIN (op->buffer_size, file->input_block_size); - io_op->io_allow_cancel = FALSE; - return STATE_OP_READ; - } - else - { - op->state = READ_STATE_SKIP_BLOCK; - io_op->io_buffer = NULL; - io_op->io_size = file->input_block_size; - io_op->io_allow_cancel = !op->sent_cancel; - return STATE_OP_SKIP; - } - break; - - /* Read block data */ - case READ_STATE_SKIP_BLOCK: - if (io_op->io_cancelled) - { - op->state = READ_STATE_HANDLE_INPUT; - break; - } - - g_assert (io_op->io_res <= file->input_block_size); - file->input_block_size -= io_op->io_res; - - if (file->input_block_size == 0) - file->input_state = INPUT_STATE_IN_REPLY_HEADER; - - op->state = READ_STATE_HANDLE_INPUT; - break; - - /* read header data, (or manual io_len/res = 0) */ - case READ_STATE_HANDLE_HEADER: - if (io_op->io_cancelled) - { - op->state = READ_STATE_HANDLE_INPUT; - break; - } - - if (io_op->io_res > 0) - { - gsize unread_size = io_op->io_size - io_op->io_res; - g_string_set_size (file->input_buffer, - file->input_buffer->len - unread_size); - } - - len = get_reply_header_missing_bytes (file->input_buffer); - if (len > 0) - { - gsize current_len = file->input_buffer->len; - g_string_set_size (file->input_buffer, - current_len + len); - io_op->io_buffer = file->input_buffer->str + current_len; - io_op->io_size = len; - io_op->io_allow_cancel = !op->sent_cancel; - return STATE_OP_READ; - } - - /* Got full header */ - - { - GVfsDaemonSocketProtocolReply reply; - char *data; - data = decode_reply (file->input_buffer, &reply); - - if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_ERROR && - reply.seq_nr == op->seq_nr) - { - op->ret_val = -1; - decode_error (&reply, data, &op->ret_error); - g_string_truncate (file->input_buffer, 0); - return STATE_OP_DONE; - } - else if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_DATA) - { - g_string_truncate (file->input_buffer, 0); - file->input_state = INPUT_STATE_IN_BLOCK; - file->input_block_size = reply.arg1; - file->input_block_seek_generation = reply.arg2; - op->state = READ_STATE_HANDLE_INPUT_BLOCK; - break; - } - /* Ignore other reply types */ - } - - g_string_truncate (file->input_buffer, 0); - - /* This wasn't interesting, read next reply */ - op->state = READ_STATE_HANDLE_HEADER; - break; - - /* Read block data */ - case READ_STATE_READ_BLOCK: - if (io_op->io_cancelled) - { - op->ret_val = -1; - g_set_error_literal (&op->ret_error, - G_IO_ERROR, - G_IO_ERROR_CANCELLED, - _("Operation was cancelled")); - return STATE_OP_DONE; - } - - if (io_op->io_res > 0) - { - g_assert (io_op->io_res <= file->input_block_size); - file->input_block_size -= io_op->io_res; - if (file->input_block_size == 0) - file->input_state = INPUT_STATE_IN_REPLY_HEADER; - } - - op->ret_val = io_op->io_res; - op->ret_error = NULL; - return STATE_OP_DONE; - - default: - g_assert_not_reached (); - } - - /* Clear io_op between non-op state switches */ - io_op->io_size = 0; - io_op->io_res = 0; - io_op->io_cancelled = FALSE; - - } -} - -static gssize -g_daemon_file_input_stream_read (GInputStream *stream, - void *buffer, - gsize count, - GCancellable *cancellable, - GError **error) -{ - GDaemonFileInputStream *file; - ReadOperation op; - - file = G_DAEMON_FILE_INPUT_STREAM (stream); - - if (g_cancellable_set_error_if_cancelled (cancellable, error)) - return -1; - - /* Limit for sanity and to avoid 32bit overflow */ - if (count > MAX_READ_SIZE) - count = MAX_READ_SIZE; - - memset (&op, 0, sizeof (op)); - op.state = READ_STATE_INIT; - op.buffer = buffer; - op.buffer_size = count; - - if (!run_sync_state_machine (file, (state_machine_iterator)iterate_read_state_machine, - &op, cancellable, error)) - return -1; /* IO Error */ - - if (op.ret_val == -1) - g_propagate_error (error, op.ret_error); - else - file->current_offset += op.ret_val; - - return op.ret_val; -} - -static gssize -g_daemon_file_input_stream_skip (GInputStream *stream, - gsize count, - GCancellable *cancellable, - GError **error) -{ -#if 0 - GDaemonFileInputStream *file; - - file = G_DAEMON_FILE_INPUT_STREAM (stream); -#endif - /* TODO: implement skip */ - g_assert_not_reached (); - - return 0; -} - -static StateOp -iterate_close_state_machine (GDaemonFileInputStream *file, IOOperationData *io_op, CloseOperation *op) -{ - gsize len; - - while (TRUE) - { - switch (op->state) - { - /* Initial state for read op */ - case CLOSE_STATE_INIT: - append_request (file, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CLOSE, - 0, 0, &op->seq_nr); - op->state = CLOSE_STATE_WROTE_REQUEST; - io_op->io_buffer = file->output_buffer->str; - io_op->io_size = file->output_buffer->len; - io_op->io_allow_cancel = TRUE; /* Allow cancel before first byte of request sent */ - return STATE_OP_WRITE; - - /* wrote parts of output_buffer */ - case CLOSE_STATE_WROTE_REQUEST: - if (io_op->io_cancelled) - { - op->ret_val = FALSE; - g_set_error_literal (&op->ret_error, - G_IO_ERROR, - G_IO_ERROR_CANCELLED, - _("Operation was cancelled")); - return STATE_OP_DONE; - } - - if (io_op->io_res < file->output_buffer->len) - { - memcpy (file->output_buffer->str, - file->output_buffer->str + io_op->io_res, - file->output_buffer->len - io_op->io_res); - g_string_truncate (file->output_buffer, - file->output_buffer->len - io_op->io_res); - io_op->io_buffer = file->output_buffer->str; - io_op->io_size = file->output_buffer->len; - io_op->io_allow_cancel = FALSE; - return STATE_OP_WRITE; - } - g_string_truncate (file->output_buffer, 0); - - op->state = CLOSE_STATE_HANDLE_INPUT; - break; - - /* No op */ - case CLOSE_STATE_HANDLE_INPUT: - if (io_op->cancelled && !op->sent_cancel) - { - op->sent_cancel = TRUE; - append_request (file, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CANCEL, - op->seq_nr, 0, NULL); - op->state = CLOSE_STATE_WROTE_REQUEST; - io_op->io_buffer = file->output_buffer->str; - io_op->io_size = file->output_buffer->len; - io_op->io_allow_cancel = FALSE; - return STATE_OP_WRITE; - } - - if (file->input_state == INPUT_STATE_IN_BLOCK) - { - op->state = CLOSE_STATE_HANDLE_INPUT_BLOCK; - break; - } - else if (file->input_state == INPUT_STATE_IN_REPLY_HEADER) - { - op->state = CLOSE_STATE_HANDLE_HEADER; - break; - } - g_assert_not_reached (); - break; - - /* No op */ - case CLOSE_STATE_HANDLE_INPUT_BLOCK: - g_assert (file->input_state == INPUT_STATE_IN_BLOCK); - - op->state = CLOSE_STATE_SKIP_BLOCK; - io_op->io_buffer = NULL; - io_op->io_size = file->input_block_size; - io_op->io_allow_cancel = !op->sent_cancel; - return STATE_OP_SKIP; - - /* Read block data */ - case CLOSE_STATE_SKIP_BLOCK: - if (io_op->io_cancelled) - { - op->state = CLOSE_STATE_HANDLE_INPUT; - break; - } - - g_assert (io_op->io_res <= file->input_block_size); - file->input_block_size -= io_op->io_res; - - if (file->input_block_size == 0) - file->input_state = INPUT_STATE_IN_REPLY_HEADER; - - op->state = CLOSE_STATE_HANDLE_INPUT; - break; - - /* read header data, (or manual io_len/res = 0) */ - case CLOSE_STATE_HANDLE_HEADER: - if (io_op->io_cancelled) - { - op->state = CLOSE_STATE_HANDLE_INPUT; - break; - } - - if (io_op->io_res > 0) - { - gsize unread_size = io_op->io_size - io_op->io_res; - g_string_set_size (file->input_buffer, - file->input_buffer->len - unread_size); - } - - len = get_reply_header_missing_bytes (file->input_buffer); - if (len > 0) - { - gsize current_len = file->input_buffer->len; - g_string_set_size (file->input_buffer, - current_len + len); - io_op->io_buffer = file->input_buffer->str + current_len; - io_op->io_size = len; - io_op->io_allow_cancel = !op->sent_cancel; - return STATE_OP_READ; - } - - /* Got full header */ - - { - GVfsDaemonSocketProtocolReply reply; - char *data; - data = decode_reply (file->input_buffer, &reply); - - if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_ERROR && - reply.seq_nr == op->seq_nr) - { - op->ret_val = FALSE; - decode_error (&reply, data, &op->ret_error); - g_string_truncate (file->input_buffer, 0); - return STATE_OP_DONE; - } - else if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_DATA) - { - g_string_truncate (file->input_buffer, 0); - file->input_state = INPUT_STATE_IN_BLOCK; - file->input_block_size = reply.arg1; - file->input_block_seek_generation = reply.arg2; - op->state = CLOSE_STATE_HANDLE_INPUT_BLOCK; - break; - } - else if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_CLOSED) - { - op->ret_val = TRUE; - g_string_truncate (file->input_buffer, 0); - return STATE_OP_DONE; - } - /* Ignore other reply types */ - } - - g_string_truncate (file->input_buffer, 0); - - /* This wasn't interesting, read next reply */ - op->state = CLOSE_STATE_HANDLE_HEADER; - break; - - default: - g_assert_not_reached (); - } - - /* Clear io_op between non-op state switches */ - io_op->io_size = 0; - io_op->io_res = 0; - io_op->io_cancelled = FALSE; - } -} - - -static gboolean -g_daemon_file_input_stream_close (GInputStream *stream, - GCancellable *cancellable, - GError **error) -{ - GDaemonFileInputStream *file; - CloseOperation op; - gboolean res; - - file = G_DAEMON_FILE_INPUT_STREAM (stream); - - /* We need to do a full roundtrip to guarantee that the writes have - reached the disk. */ - - memset (&op, 0, sizeof (op)); - op.state = CLOSE_STATE_INIT; - - if (!run_sync_state_machine (file, (state_machine_iterator)iterate_close_state_machine, - &op, cancellable, error)) - res = FALSE; - else - { - if (!op.ret_val) - g_propagate_error (error, op.ret_error); - res = op.ret_val; - } - - /* Return the first error, but close all streams */ - if (res) - res = g_output_stream_close (file->command_stream, cancellable, error); - else - g_output_stream_close (file->command_stream, cancellable, NULL); - - if (res) - res = g_input_stream_close (file->data_stream, cancellable, error); - else - g_input_stream_close (file->data_stream, cancellable, NULL); - - return res; -} - -static goffset -g_daemon_file_input_stream_tell (GFileInputStream *stream) -{ - GDaemonFileInputStream *file; - - file = G_DAEMON_FILE_INPUT_STREAM (stream); - - return file->current_offset; -} - -static gboolean -g_daemon_file_input_stream_can_seek (GFileInputStream *stream) -{ - GDaemonFileInputStream *file; - - file = G_DAEMON_FILE_INPUT_STREAM (stream); - - return file->can_seek; -} - -static StateOp -iterate_seek_state_machine (GDaemonFileInputStream *file, IOOperationData *io_op, SeekOperation *op) -{ - gsize len; - guint32 request; - - while (TRUE) - { - switch (op->state) - { - /* Initial state for read op */ - case SEEK_STATE_INIT: - request = G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SEEK_SET; - if (op->seek_type == G_SEEK_CUR) - op->offset = file->current_offset + op->offset; - else if (op->seek_type == G_SEEK_END) - request = G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SEEK_END; - append_request (file, request, - op->offset & 0xffffffff, - op->offset >> 32, - &op->seq_nr); - op->state = SEEK_STATE_WROTE_REQUEST; - op->sent_seek = FALSE; - io_op->io_buffer = file->output_buffer->str; - io_op->io_size = file->output_buffer->len; - io_op->io_allow_cancel = TRUE; /* Allow cancel before first byte of request sent */ - return STATE_OP_WRITE; - - /* wrote parts of output_buffer */ - case SEEK_STATE_WROTE_REQUEST: - if (io_op->io_cancelled) - { - op->ret_val = -1; - g_set_error_literal (&op->ret_error, - G_IO_ERROR, - G_IO_ERROR_CANCELLED, - _("Operation was cancelled")); - return STATE_OP_DONE; - } - - /* We weren't cancelled before first byte sent, so now we will send - * the seek request. Increase the seek generation now. */ - if (!op->sent_seek) - file->seek_generation++; - op->sent_seek = TRUE; - - if (io_op->io_res < file->output_buffer->len) - { - memcpy (file->output_buffer->str, - file->output_buffer->str + io_op->io_res, - file->output_buffer->len - io_op->io_res); - g_string_truncate (file->output_buffer, - file->output_buffer->len - io_op->io_res); - io_op->io_buffer = file->output_buffer->str; - io_op->io_size = file->output_buffer->len; - io_op->io_allow_cancel = FALSE; - return STATE_OP_WRITE; - } - g_string_truncate (file->output_buffer, 0); - - op->state = SEEK_STATE_HANDLE_INPUT; - break; - - /* No op */ - case SEEK_STATE_HANDLE_INPUT: - if (io_op->cancelled && !op->sent_cancel) - { - op->sent_cancel = TRUE; - append_request (file, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CANCEL, - op->seq_nr, 0, NULL); - op->state = SEEK_STATE_WROTE_REQUEST; - io_op->io_buffer = file->output_buffer->str; - io_op->io_size = file->output_buffer->len; - io_op->io_allow_cancel = FALSE; - return STATE_OP_WRITE; - } - - if (file->input_state == INPUT_STATE_IN_BLOCK) - { - op->state = SEEK_STATE_HANDLE_INPUT_BLOCK; - break; - } - else if (file->input_state == INPUT_STATE_IN_REPLY_HEADER) - { - op->state = SEEK_STATE_HANDLE_HEADER; - break; - } - g_assert_not_reached (); - break; - - /* No op */ - case SEEK_STATE_HANDLE_INPUT_BLOCK: - g_assert (file->input_state == INPUT_STATE_IN_BLOCK); - - op->state = SEEK_STATE_SKIP_BLOCK; - /* Reuse client buffer for skipping */ - io_op->io_buffer = NULL; - io_op->io_size = file->input_block_size; - io_op->io_allow_cancel = !op->sent_cancel; - return STATE_OP_SKIP; - - /* Read block data */ - case SEEK_STATE_SKIP_BLOCK: - if (io_op->io_cancelled) - { - op->state = SEEK_STATE_HANDLE_INPUT; - break; - } - - g_assert (io_op->io_res <= file->input_block_size); - file->input_block_size -= io_op->io_res; - - if (file->input_block_size == 0) - file->input_state = INPUT_STATE_IN_REPLY_HEADER; - - op->state = SEEK_STATE_HANDLE_INPUT; - break; - - /* read header data, (or manual io_len/res = 0) */ - case SEEK_STATE_HANDLE_HEADER: - if (io_op->io_cancelled) - { - op->state = SEEK_STATE_HANDLE_INPUT; - break; - } - - if (io_op->io_res > 0) - { - gsize unread_size = io_op->io_size - io_op->io_res; - g_string_set_size (file->input_buffer, - file->input_buffer->len - unread_size); - } - - len = get_reply_header_missing_bytes (file->input_buffer); - if (len > 0) - { - gsize current_len = file->input_buffer->len; - g_string_set_size (file->input_buffer, - current_len + len); - io_op->io_buffer = file->input_buffer->str + current_len; - io_op->io_size = len; - io_op->io_allow_cancel = !op->sent_cancel; - return STATE_OP_READ; - } - - /* Got full header */ - - { - GVfsDaemonSocketProtocolReply reply; - char *data; - data = decode_reply (file->input_buffer, &reply); - - if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_ERROR && - reply.seq_nr == op->seq_nr) - { - op->ret_val = FALSE; - decode_error (&reply, data, &op->ret_error); - g_string_truncate (file->input_buffer, 0); - return STATE_OP_DONE; - } - else if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_DATA) - { - g_string_truncate (file->input_buffer, 0); - file->input_state = INPUT_STATE_IN_BLOCK; - file->input_block_size = reply.arg1; - file->input_block_seek_generation = reply.arg2; - op->state = SEEK_STATE_HANDLE_INPUT_BLOCK; - break; - } - else if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SEEK_POS) - { - op->ret_val = TRUE; - op->ret_offset = ((goffset)reply.arg2) << 32 | (goffset)reply.arg1; - g_string_truncate (file->input_buffer, 0); - return STATE_OP_DONE; - } - /* Ignore other reply types */ - } - - g_string_truncate (file->input_buffer, 0); - - /* This wasn't interesting, read next reply */ - op->state = SEEK_STATE_HANDLE_HEADER; - break; - - default: - g_assert_not_reached (); - } - - /* Clear io_op between non-op state switches */ - io_op->io_size = 0; - io_op->io_res = 0; - io_op->io_cancelled = FALSE; - } -} - -static gboolean -g_daemon_file_input_stream_seek (GFileInputStream *stream, - goffset offset, - GSeekType type, - GCancellable *cancellable, - GError **error) -{ - GDaemonFileInputStream *file; - SeekOperation op; - - file = G_DAEMON_FILE_INPUT_STREAM (stream); - - if (!file->can_seek) - { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - _("Seek not supported on stream")); - return FALSE; - } - - if (g_cancellable_set_error_if_cancelled (cancellable, error)) - return FALSE; - - memset (&op, 0, sizeof (op)); - op.state = SEEK_STATE_INIT; - op.offset = offset; - op.seek_type = type; - - if (!run_sync_state_machine (file, (state_machine_iterator)iterate_seek_state_machine, - &op, cancellable, error)) - return FALSE; /* IO Error */ - - if (!op.ret_val) - g_propagate_error (error, op.ret_error); - else - file->current_offset = op.ret_offset; - - return op.ret_val; -} - -static GFileInfo * -g_daemon_file_input_stream_query_info (GFileInputStream *stream, - char *attributes, - GCancellable *cancellable, - GError **error) -{ - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("The query info operation is not supported")); - - return NULL; -} - -/************************************************************************ - * Async I/O Code * - ************************************************************************/ - -typedef struct AsyncIterator AsyncIterator; - -typedef void (*AsyncIteratorDone) (GInputStream *stream, - gpointer op_data, - GAsyncReadyCallback callback, - gpointer callback_data, - GError *io_error); - -struct AsyncIterator { - AsyncIteratorDone done_cb; - GDaemonFileInputStream *file; - GCancellable *cancellable; - IOOperationData io_data; - state_machine_iterator iterator; - gpointer iterator_data; - int io_priority; - GAsyncReadyCallback callback; - gpointer callback_data; -}; - -static void async_iterate (AsyncIterator *iterator); - -static void -async_iterator_done (AsyncIterator *iterator, GError *io_error) -{ - iterator->done_cb (G_INPUT_STREAM (iterator->file), - iterator->iterator_data, - iterator->callback, - iterator->callback_data, - io_error); - - g_free (iterator); - -} - -static void -async_op_handle (AsyncIterator *iterator, - gssize res, - GError *io_error) -{ - IOOperationData *io_data = &iterator->io_data; - GError *error; - - if (io_error != NULL) - { - if (error_is_cancel (io_error)) - { - io_data->io_res = 0; - io_data->io_cancelled = TRUE; - } - else - { - error = NULL; - g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Error in stream protocol: %s"), io_error->message); - async_iterator_done (iterator, error); - g_error_free (error); - return; - } - } - else if (res == 0 && io_data->io_size != 0) - { - error = NULL; - g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Error in stream protocol: %s"), _("End of stream")); - async_iterator_done (iterator, error); - g_error_free (error); - return; - } - else - { - io_data->io_res = res; - io_data->io_cancelled = FALSE; - } - - async_iterate (iterator); -} - -static void -async_read_op_callback (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - GInputStream *stream = G_INPUT_STREAM (source_object); - gssize count_read; - GError *error = NULL; - - count_read = g_input_stream_read_finish (stream, res, &error); - - async_op_handle ((AsyncIterator *)user_data, count_read, error); - if (error) - g_error_free (error); -} - -static void -async_skip_op_callback (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - GInputStream *stream = G_INPUT_STREAM (source_object); - gssize count_skipped; - GError *error = NULL; - - count_skipped = g_input_stream_skip_finish (stream, res, &error); - - async_op_handle ((AsyncIterator *)user_data, count_skipped, error); - if (error) - g_error_free (error); -} - -static void -async_write_op_callback (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - GOutputStream *stream = G_OUTPUT_STREAM (source_object); - gssize bytes_written; - GError *error = NULL; - - bytes_written = g_output_stream_write_finish (stream, res, &error); - - async_op_handle ((AsyncIterator *)user_data, bytes_written, error); - if (error) - g_error_free (error); -} - -static void -async_iterate (AsyncIterator *iterator) -{ - IOOperationData *io_data = &iterator->io_data; - GDaemonFileInputStream *file = iterator->file; - StateOp io_op; - - io_data->cancelled = - g_cancellable_is_cancelled (iterator->cancellable); - - io_op = iterator->iterator (file, io_data, iterator->iterator_data); - - if (io_op == STATE_OP_DONE) - { - async_iterator_done (iterator, NULL); - return; - } - - /* TODO: Handle allow_cancel... */ - - if (io_op == STATE_OP_READ) - { - g_input_stream_read_async (file->data_stream, - io_data->io_buffer, io_data->io_size, - iterator->io_priority, - io_data->io_allow_cancel ? iterator->cancellable : NULL, - async_read_op_callback, iterator); - } - else if (io_op == STATE_OP_SKIP) - { - g_input_stream_skip_async (file->data_stream, - io_data->io_size, - iterator->io_priority, - io_data->io_allow_cancel ? iterator->cancellable : NULL, - async_skip_op_callback, iterator); - } - else if (io_op == STATE_OP_WRITE) - { - g_output_stream_write_async (file->command_stream, - io_data->io_buffer, io_data->io_size, - iterator->io_priority, - io_data->io_allow_cancel ? iterator->cancellable : NULL, - async_write_op_callback, iterator); - } - else - g_assert_not_reached (); -} - -static void -run_async_state_machine (GDaemonFileInputStream *file, - state_machine_iterator iterator_cb, - gpointer iterator_data, - int io_priority, - GAsyncReadyCallback callback, - gpointer data, - GCancellable *cancellable, - AsyncIteratorDone done_cb) -{ - AsyncIterator *iterator; - - iterator = g_new0 (AsyncIterator, 1); - iterator->file = file; - iterator->iterator = iterator_cb; - iterator->iterator_data = iterator_data; - iterator->io_priority = io_priority; - iterator->cancellable = cancellable; - iterator->callback = callback; - iterator->callback_data = data; - iterator->done_cb = done_cb; - - async_iterate (iterator); -} - -static void -async_read_done (GInputStream *stream, - gpointer op_data, - GAsyncReadyCallback callback, - gpointer user_data, - GError *io_error) -{ - ReadOperation *op; - gssize count_read; - GError *error; - GSimpleAsyncResult *simple; - - op = op_data; - - if (io_error) - { - count_read = -1; - error = io_error; - } - else - { - count_read = op->ret_val; - error = op->ret_error; - } - - simple = g_simple_async_result_new (G_OBJECT (stream), - callback, user_data, - g_daemon_file_input_stream_read_async); - - g_simple_async_result_set_op_res_gssize (simple, count_read); - - if (count_read == -1) - g_simple_async_result_set_from_error (simple, error); - - /* Complete immediately, not in idle, since we're already in a mainloop callout */ - g_simple_async_result_complete (simple); - g_object_unref (simple); - - if (op->ret_error) - g_error_free (op->ret_error); - g_free (op); -} - -static void -g_daemon_file_input_stream_read_async (GInputStream *stream, - void *buffer, - gsize count, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GDaemonFileInputStream *file; - ReadOperation *op; - - file = G_DAEMON_FILE_INPUT_STREAM (stream); - - /* Limit for sanity and to avoid 32bit overflow */ - if (count > MAX_READ_SIZE) - count = MAX_READ_SIZE; - - op = g_new0 (ReadOperation, 1); - op->state = READ_STATE_INIT; - op->buffer = buffer; - op->buffer_size = count; - - run_async_state_machine (file, - (state_machine_iterator)iterate_read_state_machine, - op, - io_priority, - callback, user_data, - cancellable, - async_read_done); -} - -static gssize -g_daemon_file_input_stream_read_finish (GInputStream *stream, - GAsyncResult *result, - GError **error) -{ - GSimpleAsyncResult *simple; - gssize nread; - - simple = G_SIMPLE_ASYNC_RESULT (result); - g_assert (g_simple_async_result_get_source_tag (simple) == g_daemon_file_input_stream_read_async); - - nread = g_simple_async_result_get_op_res_gssize (simple); - return nread; -} - - -static void -g_daemon_file_input_stream_skip_async (GInputStream *stream, - gsize count, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer data) -{ - g_assert_not_reached (); - /* TODO: Not implemented */ -} - -static gssize -g_daemon_file_input_stream_skip_finish (GInputStream *stream, - GAsyncResult *result, - GError **error) -{ - g_assert_not_reached (); - /* TODO: Not implemented */ -} - -static void -async_close_done (GInputStream *stream, - gpointer op_data, - GAsyncReadyCallback callback, - gpointer user_data, - GError *io_error) -{ - GDaemonFileInputStream *file; - GSimpleAsyncResult *simple; - CloseOperation *op; - gboolean result; - GError *error; - GCancellable *cancellable = NULL; /* TODO: get cancellable */ - - file = G_DAEMON_FILE_INPUT_STREAM (stream); - - op = op_data; - - if (io_error) - { - result = FALSE; - error = io_error; - } - else - { - result = op->ret_val; - error = op->ret_error; - } - - if (result) - result = g_output_stream_close (file->command_stream, cancellable, &error); - else - g_output_stream_close (file->command_stream, cancellable, NULL); - - if (result) - result = g_input_stream_close (file->data_stream, cancellable, &error); - else - g_input_stream_close (file->data_stream, cancellable, NULL); - - - simple = g_simple_async_result_new (G_OBJECT (stream), - callback, user_data, - g_daemon_file_input_stream_read_async); - - if (!result) - g_simple_async_result_set_from_error (simple, error); - - /* Complete immediately, not in idle, since we're already in a mainloop callout */ - g_simple_async_result_complete (simple); - g_object_unref (simple); - - if (op->ret_error) - g_error_free (op->ret_error); - g_free (op); -} - -static void -g_daemon_file_input_stream_close_async (GInputStream *stream, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer data) -{ - GDaemonFileInputStream *file; - CloseOperation *op; - - file = G_DAEMON_FILE_INPUT_STREAM (stream); - - op = g_new0 (CloseOperation, 1); - op->state = CLOSE_STATE_INIT; - - run_async_state_machine (file, - (state_machine_iterator)iterate_close_state_machine, - op, io_priority, - callback, data, - cancellable, - async_close_done); -} - -static gboolean -g_daemon_file_input_stream_close_finish (GInputStream *stream, - GAsyncResult *result, - GError **error) -{ - /* Failures handled in generic close_finish code */ - return TRUE; -} diff --git a/gnome-2-24/client/gdaemonfileinputstream.h b/gnome-2-24/client/gdaemonfileinputstream.h deleted file mode 100644 index 2d4cc4ce..00000000 --- a/gnome-2-24/client/gdaemonfileinputstream.h +++ /dev/null @@ -1,52 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -#ifndef __G_DAEMON_FILE_INPUT_STREAM_H__ -#define __G_DAEMON_FILE_INPUT_STREAM_H__ - -#include <gio/gio.h> - -G_BEGIN_DECLS - -#define G_TYPE_DAEMON_FILE_INPUT_STREAM (g_daemon_file_input_stream_get_type ()) -#define G_DAEMON_FILE_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DAEMON_FILE_INPUT_STREAM, GDaemonFileInputStream)) -#define G_DAEMON_FILE_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DAEMON_FILE_INPUT_STREAM, GDaemonFileInputStreamClass)) -#define G_IS_DAEMON_FILE_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DAEMON_FILE_INPUT_STREAM)) -#define G_IS_DAEMON_FILE_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DAEMON_FILE_INPUT_STREAM)) -#define G_DAEMON_FILE_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_DAEMON_FILE_INPUT_STREAM, GDaemonFileInputStreamClass)) - -typedef struct _GDaemonFileInputStream GDaemonFileInputStream; -typedef struct _GDaemonFileInputStreamClass GDaemonFileInputStreamClass; - -struct _GDaemonFileInputStreamClass -{ - GFileInputStreamClass parent_class; -}; - -GType g_daemon_file_input_stream_get_type (void) G_GNUC_CONST; - -GFileInputStream *g_daemon_file_input_stream_new (int fd, - gboolean can_seek); - -G_END_DECLS - -#endif /* __G_DAEMON_FILE_INPUT_STREAM_H__ */ diff --git a/gnome-2-24/client/gdaemonfilemonitor.c b/gnome-2-24/client/gdaemonfilemonitor.c deleted file mode 100644 index 61b35e54..00000000 --- a/gnome-2-24/client/gdaemonfilemonitor.c +++ /dev/null @@ -1,213 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -#include <config.h> -#include <string.h> - -#include "gdaemonfilemonitor.h" -#include <gio/gio.h> -#include <gvfsdaemondbus.h> -#include <gvfsdaemonprotocol.h> -#include "gdbusutils.h" -#include "gmountspec.h" -#include "gdaemonfile.h" - -#define OBJ_PATH_PREFIX "/org/gtk/vfs/client/filemonitor/" - -/* atomic */ -static volatile gint path_counter = 1; - -static gboolean g_daemon_file_monitor_cancel (GFileMonitor* monitor); -static DBusHandlerResult g_daemon_file_monitor_dbus_filter (DBusConnection *connection, - DBusMessage *message, - void *user_data); - - -struct _GDaemonFileMonitor -{ - GFileMonitor parent_instance; - - char *object_path; - char *remote_obj_path; - char *remote_id; -}; - -G_DEFINE_TYPE (GDaemonFileMonitor, g_daemon_file_monitor, G_TYPE_FILE_MONITOR) - -static void -g_daemon_file_monitor_finalize (GObject* object) -{ - GDaemonFileMonitor *daemon_monitor; - - daemon_monitor = G_DAEMON_FILE_MONITOR (object); - - _g_dbus_unregister_vfs_filter (daemon_monitor->object_path); - - g_free (daemon_monitor->object_path); - g_free (daemon_monitor->remote_id); - g_free (daemon_monitor->remote_obj_path); - - if (G_OBJECT_CLASS (g_daemon_file_monitor_parent_class)->finalize) - (*G_OBJECT_CLASS (g_daemon_file_monitor_parent_class)->finalize) (object); -} - -static void -g_daemon_file_monitor_class_init (GDaemonFileMonitorClass* klass) -{ - GObjectClass* gobject_class = G_OBJECT_CLASS (klass); - GFileMonitorClass *file_monitor_class = G_FILE_MONITOR_CLASS (klass); - - gobject_class->finalize = g_daemon_file_monitor_finalize; - - file_monitor_class->cancel = g_daemon_file_monitor_cancel; -} - -static void -g_daemon_file_monitor_init (GDaemonFileMonitor* daemon_monitor) -{ - gint id; - - id = g_atomic_int_exchange_and_add (&path_counter, 1); - - daemon_monitor->object_path = g_strdup_printf (OBJ_PATH_PREFIX"%d", id); - - _g_dbus_register_vfs_filter (daemon_monitor->object_path, - g_daemon_file_monitor_dbus_filter, - G_OBJECT (daemon_monitor)); -} - -GFileMonitor* -g_daemon_file_monitor_new (const char *remote_id, - const char *remote_obj_path) -{ - GDaemonFileMonitor* daemon_monitor; - DBusMessage *message; - - daemon_monitor = g_object_new (G_TYPE_DAEMON_FILE_MONITOR, NULL); - - daemon_monitor->remote_id = g_strdup (remote_id); - daemon_monitor->remote_obj_path = g_strdup (remote_obj_path); - - message = - dbus_message_new_method_call (daemon_monitor->remote_id, - daemon_monitor->remote_obj_path, - G_VFS_DBUS_MONITOR_INTERFACE, - G_VFS_DBUS_MONITOR_OP_SUBSCRIBE); - - _g_dbus_message_append_args (message, DBUS_TYPE_OBJECT_PATH, - &daemon_monitor->object_path, 0); - - _g_vfs_daemon_call_async (message, - NULL, NULL, - NULL); - - dbus_message_unref (message); - - return G_FILE_MONITOR (daemon_monitor); -} - -static DBusHandlerResult -g_daemon_file_monitor_dbus_filter (DBusConnection *connection, - DBusMessage *message, - void *user_data) -{ - GDaemonFileMonitor *monitor = G_DAEMON_FILE_MONITOR (user_data); - const char *member; - guint32 event_type; - DBusMessageIter iter; - GMountSpec *spec1, *spec2; - char *path1, *path2; - GFile *file1, *file2; - - member = dbus_message_get_member (message); - - if (strcmp (member, G_VFS_DBUS_MONITOR_CLIENT_OP_CHANGED) == 0) - { - dbus_message_iter_init (message, &iter); - - if (!_g_dbus_message_iter_get_args (&iter, NULL, - DBUS_TYPE_UINT32, &event_type, - 0)) - return DBUS_HANDLER_RESULT_HANDLED; - - spec1 = g_mount_spec_from_dbus (&iter); - if (!_g_dbus_message_iter_get_args (&iter, NULL, - G_DBUS_TYPE_CSTRING, &path1, - 0)) - { - g_mount_spec_unref (spec1); - return DBUS_HANDLER_RESULT_HANDLED; - } - - file1 = g_daemon_file_new (spec1, path1); - - g_mount_spec_unref (spec1); - g_free (path1); - - file2 = NULL; - - spec2 = g_mount_spec_from_dbus (&iter); - if (spec2) { - if (_g_dbus_message_iter_get_args (&iter, NULL, - G_DBUS_TYPE_CSTRING, &path2, - 0)) - { - file2 = g_daemon_file_new (spec2, path2); - - g_free (path2); - } - - g_mount_spec_unref (spec2); - } - - g_file_monitor_emit_event (G_FILE_MONITOR (monitor), - file1, file2, - event_type); - - return DBUS_HANDLER_RESULT_HANDLED; - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - - -static gboolean -g_daemon_file_monitor_cancel (GFileMonitor* monitor) -{ - GDaemonFileMonitor *daemon_monitor = G_DAEMON_FILE_MONITOR (monitor); - DBusMessage *message; - - message = - dbus_message_new_method_call (daemon_monitor->remote_id, - daemon_monitor->remote_obj_path, - G_VFS_DBUS_MONITOR_INTERFACE, - G_VFS_DBUS_MONITOR_OP_UNSUBSCRIBE); - - _g_vfs_daemon_call_async (message, - NULL, NULL, - NULL); - - dbus_message_unref (message); - - return TRUE; -} - diff --git a/gnome-2-24/client/gdaemonfilemonitor.h b/gnome-2-24/client/gdaemonfilemonitor.h deleted file mode 100644 index 9cd02175..00000000 --- a/gnome-2-24/client/gdaemonfilemonitor.h +++ /dev/null @@ -1,52 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -#ifndef __G_DAEMON_FILE_MONITOR_H__ -#define __G_DAEMON_FILE_MONITOR_H__ - -#include <glib-object.h> -#include <gio/gio.h> - -G_BEGIN_DECLS - -#define G_TYPE_DAEMON_FILE_MONITOR (g_daemon_file_monitor_get_type ()) -#define G_DAEMON_FILE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DAEMON_FILE_MONITOR, GDaemonFileMonitor)) -#define G_DAEMON_FILE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), G_TYPE_DAEMON_FILE_MONITOR, GDaemonFileMonitorClass)) -#define G_IS_DAEMON_FILE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DAEMON_FILE_MONITOR)) -#define G_IS_DAEMON_FILE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DAEMON_FILE_MONITOR)) - -typedef struct _GDaemonFileMonitor GDaemonFileMonitor; -typedef struct _GDaemonFileMonitorClass GDaemonFileMonitorClass; - -struct _GDaemonFileMonitorClass { - GFileMonitorClass parent_class; -}; - -GType g_daemon_file_monitor_get_type (void) G_GNUC_CONST; - -GFileMonitor* g_daemon_file_monitor_new (const char *remote_id, - const char *remote_obj_path); - - -G_END_DECLS - -#endif /* __G_DAEMON_FILE_MONITOR_H__ */ diff --git a/gnome-2-24/client/gdaemonfileoutputstream.c b/gnome-2-24/client/gdaemonfileoutputstream.c deleted file mode 100644 index 525475c8..00000000 --- a/gnome-2-24/client/gdaemonfileoutputstream.c +++ /dev/null @@ -1,1374 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -#include <config.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <sys/socket.h> -#include <sys/un.h> - -#include <glib.h> -#include <glib/gstdio.h> -#include <glib/gi18n-lib.h> -#include <gio/gio.h> -#include <gio/gunixinputstream.h> -#include <gio/gunixoutputstream.h> -#include "gdaemonfileoutputstream.h" -#include "gvfsdaemondbus.h" -#include <gvfsdaemonprotocol.h> - -#define MAX_WRITE_SIZE (4*1024*1024) - -typedef enum { - STATE_OP_DONE, - STATE_OP_READ, - STATE_OP_WRITE, - STATE_OP_SKIP -} StateOp; - -typedef enum { - WRITE_STATE_INIT = 0, - WRITE_STATE_WROTE_COMMAND, - WRITE_STATE_SEND_DATA, - WRITE_STATE_HANDLE_INPUT -} WriteState; - -typedef struct { - WriteState state; - - /* Output */ - const char *buffer; - gsize buffer_size; - gsize buffer_pos; - - /* Input */ - gssize ret_val; - GError *ret_error; - - gboolean sent_cancel; - - guint32 seq_nr; -} WriteOperation; - -typedef enum { - SEEK_STATE_INIT = 0, - SEEK_STATE_WROTE_REQUEST, - SEEK_STATE_HANDLE_INPUT -} SeekState; - -typedef struct { - SeekState state; - - /* Output */ - goffset offset; - GSeekType seek_type; - /* Output */ - gboolean ret_val; - GError *ret_error; - goffset ret_offset; - - gboolean sent_cancel; - - guint32 seq_nr; -} SeekOperation; - -typedef enum { - CLOSE_STATE_INIT = 0, - CLOSE_STATE_WROTE_REQUEST, - CLOSE_STATE_HANDLE_INPUT -} CloseState; - -typedef struct { - CloseState state; - - /* Output */ - - /* Output */ - gboolean ret_val; - GError *ret_error; - - gboolean sent_cancel; - - guint32 seq_nr; -} CloseOperation; - - -typedef struct { - gboolean cancelled; - - char *io_buffer; - gsize io_size; - gsize io_res; - /* The operation always succeeds, or gets cancelled. - If we get an error doing the i/o that is considered fatal */ - gboolean io_allow_cancel; - gboolean io_cancelled; -} IOOperationData; - -typedef StateOp (*state_machine_iterator) (GDaemonFileOutputStream *file, IOOperationData *io_op, gpointer data); - -struct _GDaemonFileOutputStream { - GFileOutputStream parent; - - GOutputStream *command_stream; - GInputStream *data_stream; - guint can_seek : 1; - - guint32 seq_nr; - goffset current_offset; - - gsize input_block_size; - GString *input_buffer; - - GString *output_buffer; - - char *etag; - -}; - -static gssize g_daemon_file_output_stream_write (GOutputStream *stream, - const void *buffer, - gsize count, - GCancellable *cancellable, - GError **error); -static gboolean g_daemon_file_output_stream_close (GOutputStream *stream, - GCancellable *cancellable, - GError **error); -static GFileInfo *g_daemon_file_output_stream_query_info (GFileOutputStream *stream, - char *attributes, - GCancellable *cancellable, - GError **error); -static char *g_daemon_file_output_stream_get_etag (GFileOutputStream *stream); -static goffset g_daemon_file_output_stream_tell (GFileOutputStream *stream); -static gboolean g_daemon_file_output_stream_can_seek (GFileOutputStream *stream); -static gboolean g_daemon_file_output_stream_seek (GFileOutputStream *stream, - goffset offset, - GSeekType type, - GCancellable *cancellable, - GError **error); -static void g_daemon_file_output_stream_write_async (GOutputStream *stream, - const void *buffer, - gsize count, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer data); -static gssize g_daemon_file_output_stream_write_finish (GOutputStream *stream, - GAsyncResult *result, - GError **error); -static void g_daemon_file_output_stream_close_async (GOutputStream *stream, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer data); -static gboolean g_daemon_file_output_stream_close_finish (GOutputStream *stream, - GAsyncResult *result, - GError **error); - -G_DEFINE_TYPE (GDaemonFileOutputStream, g_daemon_file_output_stream, - G_TYPE_FILE_OUTPUT_STREAM) - -static void -g_daemon_file_output_stream_finalize (GObject *object) -{ - GDaemonFileOutputStream *file; - - file = G_DAEMON_FILE_OUTPUT_STREAM (object); - - if (file->command_stream) - g_object_unref (file->command_stream); - if (file->data_stream) - g_object_unref (file->data_stream); - - g_string_free (file->input_buffer, TRUE); - g_string_free (file->output_buffer, TRUE); - - g_free (file->etag); - - if (G_OBJECT_CLASS (g_daemon_file_output_stream_parent_class)->finalize) - (*G_OBJECT_CLASS (g_daemon_file_output_stream_parent_class)->finalize) (object); -} - -static void -g_daemon_file_output_stream_class_init (GDaemonFileOutputStreamClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GOutputStreamClass *stream_class = G_OUTPUT_STREAM_CLASS (klass); - GFileOutputStreamClass *file_stream_class = G_FILE_OUTPUT_STREAM_CLASS (klass); - - gobject_class->finalize = g_daemon_file_output_stream_finalize; - - stream_class->write_fn = g_daemon_file_output_stream_write; - stream_class->close_fn = g_daemon_file_output_stream_close; - - stream_class->write_async = g_daemon_file_output_stream_write_async; - stream_class->write_finish = g_daemon_file_output_stream_write_finish; - stream_class->close_async = g_daemon_file_output_stream_close_async; - stream_class->close_finish = g_daemon_file_output_stream_close_finish; - - file_stream_class->tell = g_daemon_file_output_stream_tell; - file_stream_class->can_seek = g_daemon_file_output_stream_can_seek; - file_stream_class->seek = g_daemon_file_output_stream_seek; - file_stream_class->query_info = g_daemon_file_output_stream_query_info; - file_stream_class->get_etag = g_daemon_file_output_stream_get_etag; -} - -static void -g_daemon_file_output_stream_init (GDaemonFileOutputStream *info) -{ - info->output_buffer = g_string_new (""); - info->input_buffer = g_string_new (""); - info->seq_nr = 1; -} - -GFileOutputStream * -g_daemon_file_output_stream_new (int fd, - gboolean can_seek, - goffset initial_offset) -{ - GDaemonFileOutputStream *stream; - - stream = g_object_new (G_TYPE_DAEMON_FILE_OUTPUT_STREAM, NULL); - - stream->command_stream = g_unix_output_stream_new (fd, FALSE); - stream->data_stream = g_unix_input_stream_new (fd, TRUE); - stream->can_seek = can_seek; - stream->current_offset = initial_offset; - - return G_FILE_OUTPUT_STREAM (stream); -} - -static gboolean -error_is_cancel (GError *error) -{ - return error != NULL && - error->domain == G_IO_ERROR && - error->code == G_IO_ERROR_CANCELLED; -} - -static void -append_request (GDaemonFileOutputStream *stream, guint32 command, - guint32 arg1, guint32 arg2, guint32 data_len, guint32 *seq_nr) -{ - GVfsDaemonSocketProtocolRequest cmd; - - g_assert (sizeof (cmd) == G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SIZE); - - if (seq_nr) - *seq_nr = stream->seq_nr; - - cmd.command = g_htonl (command); - cmd.seq_nr = g_htonl (stream->seq_nr++); - cmd.arg1 = g_htonl (arg1); - cmd.arg2 = g_htonl (arg2); - cmd.data_len = g_htonl (data_len); - - g_string_append_len (stream->output_buffer, - (char *)&cmd, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SIZE); -} - -static gsize -get_reply_header_missing_bytes (GString *buffer) -{ - GVfsDaemonSocketProtocolReply *reply; - guint32 type; - guint32 arg2; - - if (buffer->len < G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE) - return G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE - buffer->len; - - reply = (GVfsDaemonSocketProtocolReply *)buffer->str; - - type = g_ntohl (reply->type); - arg2 = g_ntohl (reply->arg2); - - /* ERROR and CLOSED has extra data w/ len in arg2 */ - if (type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_ERROR || - type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_CLOSED) - return G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE + arg2 - buffer->len; - return 0; -} - -static char * -decode_reply (GString *buffer, GVfsDaemonSocketProtocolReply *reply_out) -{ - GVfsDaemonSocketProtocolReply *reply; - reply = (GVfsDaemonSocketProtocolReply *)buffer->str; - reply_out->type = g_ntohl (reply->type); - reply_out->seq_nr = g_ntohl (reply->seq_nr); - reply_out->arg1 = g_ntohl (reply->arg1); - reply_out->arg2 = g_ntohl (reply->arg2); - - return buffer->str + G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE; -} - -static void -decode_error (GVfsDaemonSocketProtocolReply *reply, char *data, GError **error) -{ - g_set_error_literal (error, - g_quark_from_string (data), - reply->arg1, - data + strlen (data) + 1); -} - - -static gboolean -run_sync_state_machine (GDaemonFileOutputStream *file, - state_machine_iterator iterator, - gpointer data, - GCancellable *cancellable, - GError **error) -{ - gssize res; - StateOp io_op; - IOOperationData io_data; - GError *io_error; - - memset (&io_data, 0, sizeof (io_data)); - - while (TRUE) - { - if (cancellable) - io_data.cancelled = g_cancellable_is_cancelled (cancellable); - - io_op = iterator (file, &io_data, data); - - if (io_op == STATE_OP_DONE) - return TRUE; - - io_error = NULL; - if (io_op == STATE_OP_READ) - { - res = g_input_stream_read (file->data_stream, - io_data.io_buffer, io_data.io_size, - io_data.io_allow_cancel ? cancellable : NULL, - &io_error); - } - else if (io_op == STATE_OP_SKIP) - { - res = g_input_stream_skip (file->data_stream, - io_data.io_size, - io_data.io_allow_cancel ? cancellable : NULL, - &io_error); - } - else if (io_op == STATE_OP_WRITE) - { - res = g_output_stream_write (file->command_stream, - io_data.io_buffer, io_data.io_size, - io_data.io_allow_cancel ? cancellable : NULL, - &io_error); - } - else - { - res = 0; - g_assert_not_reached (); - } - - if (res == -1) - { - if (error_is_cancel (io_error)) - { - io_data.io_res = 0; - io_data.io_cancelled = TRUE; - g_error_free (io_error); - } - else - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Error in stream protocol: %s"), io_error->message); - g_error_free (io_error); - return FALSE; - } - } - else if (res == 0 && io_data.io_size != 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Error in stream protocol: %s"), _("End of stream")); - return FALSE; - } - else - { - io_data.io_res = res; - io_data.io_cancelled = FALSE; - } - } -} - -/* read cycle: - - if we know of a (partially read) matching outstanding block, read from it - create packet, append to outgoing - flush outgoing - start processing output, looking for a data block with same seek gen, - or an error with same seq nr - on cancel, send cancel command and go back to loop - */ - -static StateOp -iterate_write_state_machine (GDaemonFileOutputStream *file, IOOperationData *io_op, WriteOperation *op) -{ - gsize len; - - while (TRUE) - { - switch (op->state) - { - /* Initial state for read op */ - case WRITE_STATE_INIT: - append_request (file, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_WRITE, - op->buffer_size, 0, op->buffer_size, &op->seq_nr); - op->state = WRITE_STATE_WROTE_COMMAND; - io_op->io_buffer = file->output_buffer->str; - io_op->io_size = file->output_buffer->len; - io_op->io_allow_cancel = TRUE; /* Allow cancel before first byte of request sent */ - return STATE_OP_WRITE; - - /* wrote parts of output_buffer */ - case WRITE_STATE_WROTE_COMMAND: - if (io_op->io_cancelled) - { - op->ret_val = -1; - g_set_error_literal (&op->ret_error, - G_IO_ERROR, - G_IO_ERROR_CANCELLED, - _("Operation was cancelled")); - return STATE_OP_DONE; - } - - if (io_op->io_res < file->output_buffer->len) - { - memcpy (file->output_buffer->str, - file->output_buffer->str + io_op->io_res, - file->output_buffer->len - io_op->io_res); - g_string_truncate (file->output_buffer, - file->output_buffer->len - io_op->io_res); - io_op->io_buffer = file->output_buffer->str; - io_op->io_size = file->output_buffer->len; - io_op->io_allow_cancel = FALSE; - return STATE_OP_WRITE; - } - g_string_truncate (file->output_buffer, 0); - - op->buffer_pos = 0; - if (op->sent_cancel) - op->state = WRITE_STATE_HANDLE_INPUT; - else - op->state = WRITE_STATE_SEND_DATA; - break; - - /* No op */ - case WRITE_STATE_SEND_DATA: - op->buffer_pos += io_op->io_res; - - if (op->buffer_pos < op->buffer_size) - { - io_op->io_buffer = (char *)(op->buffer + op->buffer_pos); - io_op->io_size = op->buffer_size - op->buffer_pos; - io_op->io_allow_cancel = FALSE; - return STATE_OP_WRITE; - } - - op->state = WRITE_STATE_HANDLE_INPUT; - break; - - /* No op */ - case WRITE_STATE_HANDLE_INPUT: - if (io_op->cancelled && !op->sent_cancel) - { - op->sent_cancel = TRUE; - append_request (file, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CANCEL, - op->seq_nr, 0, 0, NULL); - op->state = WRITE_STATE_WROTE_COMMAND; - io_op->io_buffer = file->output_buffer->str; - io_op->io_size = file->output_buffer->len; - io_op->io_allow_cancel = FALSE; - return STATE_OP_WRITE; - } - - if (io_op->io_res > 0) - { - gsize unread_size = io_op->io_size - io_op->io_res; - g_string_set_size (file->input_buffer, - file->input_buffer->len - unread_size); - } - - len = get_reply_header_missing_bytes (file->input_buffer); - if (len > 0) - { - gsize current_len = file->input_buffer->len; - g_string_set_size (file->input_buffer, - current_len + len); - io_op->io_buffer = file->input_buffer->str + current_len; - io_op->io_size = len; - io_op->io_allow_cancel = !op->sent_cancel; - return STATE_OP_READ; - } - - /* Got full header */ - - { - GVfsDaemonSocketProtocolReply reply; - char *data; - data = decode_reply (file->input_buffer, &reply); - - if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_ERROR && - reply.seq_nr == op->seq_nr) - { - op->ret_val = -1; - decode_error (&reply, data, &op->ret_error); - g_string_truncate (file->input_buffer, 0); - return STATE_OP_DONE; - } - else if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_WRITTEN) - { - op->ret_val = reply.arg1; - g_string_truncate (file->input_buffer, 0); - return STATE_OP_DONE; - } - /* Ignore other reply types */ - } - - g_string_truncate (file->input_buffer, 0); - - /* This wasn't interesting, read next reply */ - op->state = WRITE_STATE_HANDLE_INPUT; - break; - - default: - g_assert_not_reached (); - } - - /* Clear io_op between non-op state switches */ - io_op->io_size = 0; - io_op->io_res = 0; - io_op->io_cancelled = FALSE; - - } -} - -static gssize -g_daemon_file_output_stream_write (GOutputStream *stream, - const void *buffer, - gsize count, - GCancellable *cancellable, - GError **error) -{ - GDaemonFileOutputStream *file; - WriteOperation op; - - file = G_DAEMON_FILE_OUTPUT_STREAM (stream); - - if (g_cancellable_set_error_if_cancelled (cancellable, error)) - return -1; - - /* Limit for sanity and to avoid 32bit overflow */ - if (count > MAX_WRITE_SIZE) - count = MAX_WRITE_SIZE; - - memset (&op, 0, sizeof (op)); - op.state = WRITE_STATE_INIT; - op.buffer = buffer; - op.buffer_size = count; - - if (!run_sync_state_machine (file, (state_machine_iterator)iterate_write_state_machine, - &op, cancellable, error)) - return -1; /* IO Error */ - - if (op.ret_val == -1) - g_propagate_error (error, op.ret_error); - else - file->current_offset += op.ret_val; - - return op.ret_val; -} - -static StateOp -iterate_close_state_machine (GDaemonFileOutputStream *file, IOOperationData *io_op, CloseOperation *op) -{ - gsize len; - - while (TRUE) - { - switch (op->state) - { - /* Initial state for read op */ - case CLOSE_STATE_INIT: - append_request (file, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CLOSE, - 0, 0, 0, &op->seq_nr); - op->state = CLOSE_STATE_WROTE_REQUEST; - io_op->io_buffer = file->output_buffer->str; - io_op->io_size = file->output_buffer->len; - io_op->io_allow_cancel = TRUE; /* Allow cancel before first byte of request sent */ - return STATE_OP_WRITE; - - /* wrote parts of output_buffer */ - case CLOSE_STATE_WROTE_REQUEST: - if (io_op->io_cancelled) - { - op->ret_val = FALSE; - g_set_error_literal (&op->ret_error, - G_IO_ERROR, - G_IO_ERROR_CANCELLED, - _("Operation was cancelled")); - return STATE_OP_DONE; - } - - if (io_op->io_res < file->output_buffer->len) - { - memcpy (file->output_buffer->str, - file->output_buffer->str + io_op->io_res, - file->output_buffer->len - io_op->io_res); - g_string_truncate (file->output_buffer, - file->output_buffer->len - io_op->io_res); - io_op->io_buffer = file->output_buffer->str; - io_op->io_size = file->output_buffer->len; - io_op->io_allow_cancel = FALSE; - return STATE_OP_WRITE; - } - g_string_truncate (file->output_buffer, 0); - - op->state = CLOSE_STATE_HANDLE_INPUT; - break; - - /* No op */ - case CLOSE_STATE_HANDLE_INPUT: - if (io_op->cancelled && !op->sent_cancel) - { - op->sent_cancel = TRUE; - append_request (file, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CANCEL, - op->seq_nr, 0, 0, NULL); - op->state = CLOSE_STATE_WROTE_REQUEST; - io_op->io_buffer = file->output_buffer->str; - io_op->io_size = file->output_buffer->len; - io_op->io_allow_cancel = FALSE; - return STATE_OP_WRITE; - } - - if (io_op->io_res > 0) - { - gsize unread_size = io_op->io_size - io_op->io_res; - g_string_set_size (file->input_buffer, - file->input_buffer->len - unread_size); - } - - len = get_reply_header_missing_bytes (file->input_buffer); - if (len > 0) - { - gsize current_len = file->input_buffer->len; - g_string_set_size (file->input_buffer, - current_len + len); - io_op->io_buffer = file->input_buffer->str + current_len; - io_op->io_size = len; - io_op->io_allow_cancel = !op->sent_cancel; - return STATE_OP_READ; - } - - /* Got full header */ - - { - GVfsDaemonSocketProtocolReply reply; - char *data; - data = decode_reply (file->input_buffer, &reply); - - if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_ERROR && - reply.seq_nr == op->seq_nr) - { - op->ret_val = FALSE; - decode_error (&reply, data, &op->ret_error); - g_string_truncate (file->input_buffer, 0); - return STATE_OP_DONE; - } - else if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_CLOSED) - { - op->ret_val = TRUE; - if (reply.arg2 > 0) - file->etag = g_strndup (data, reply.arg2); - g_string_truncate (file->input_buffer, 0); - return STATE_OP_DONE; - } - /* Ignore other reply types */ - } - - g_string_truncate (file->input_buffer, 0); - - /* This wasn't interesting, read next reply */ - op->state = CLOSE_STATE_HANDLE_INPUT; - break; - - default: - g_assert_not_reached (); - } - - /* Clear io_op between non-op state switches */ - io_op->io_size = 0; - io_op->io_res = 0; - io_op->io_cancelled = FALSE; - } -} - - -static gboolean -g_daemon_file_output_stream_close (GOutputStream *stream, - GCancellable *cancellable, - GError **error) -{ - GDaemonFileOutputStream *file; - CloseOperation op; - gboolean res; - - file = G_DAEMON_FILE_OUTPUT_STREAM (stream); - - /* We need to do a full roundtrip to guarantee that the writes have - reached the disk. */ - - memset (&op, 0, sizeof (op)); - op.state = CLOSE_STATE_INIT; - - if (!run_sync_state_machine (file, (state_machine_iterator)iterate_close_state_machine, - &op, cancellable, error)) - res = FALSE; - else - { - if (!op.ret_val) - g_propagate_error (error, op.ret_error); - res = op.ret_val; - } - - /* Return the first error, but close all streams */ - if (res) - res = g_output_stream_close (file->command_stream, cancellable, error); - else - g_output_stream_close (file->command_stream, cancellable, NULL); - - if (res) - res = g_input_stream_close (file->data_stream, cancellable, error); - else - g_input_stream_close (file->data_stream, cancellable, NULL); - - return res; -} - -static goffset -g_daemon_file_output_stream_tell (GFileOutputStream *stream) -{ - GDaemonFileOutputStream *file; - - file = G_DAEMON_FILE_OUTPUT_STREAM (stream); - - return file->current_offset; -} - -static gboolean -g_daemon_file_output_stream_can_seek (GFileOutputStream *stream) -{ - GDaemonFileOutputStream *file; - - file = G_DAEMON_FILE_OUTPUT_STREAM (stream); - - return file->can_seek; -} - -static StateOp -iterate_seek_state_machine (GDaemonFileOutputStream *file, IOOperationData *io_op, SeekOperation *op) -{ - gsize len; - guint32 request; - - while (TRUE) - { - switch (op->state) - { - /* Initial state for read op */ - case SEEK_STATE_INIT: - request = G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SEEK_SET; - if (op->seek_type == G_SEEK_CUR) - op->offset = file->current_offset + op->offset; - else if (op->seek_type == G_SEEK_END) - request = G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SEEK_END; - append_request (file, request, - op->offset & 0xffffffff, - op->offset >> 32, - 0, - &op->seq_nr); - op->state = SEEK_STATE_WROTE_REQUEST; - io_op->io_buffer = file->output_buffer->str; - io_op->io_size = file->output_buffer->len; - io_op->io_allow_cancel = TRUE; /* Allow cancel before first byte of request sent */ - return STATE_OP_WRITE; - - /* wrote parts of output_buffer */ - case SEEK_STATE_WROTE_REQUEST: - if (io_op->io_cancelled) - { - op->ret_val = -1; - g_set_error_literal (&op->ret_error, - G_IO_ERROR, - G_IO_ERROR_CANCELLED, - _("Operation was cancelled")); - return STATE_OP_DONE; - } - - if (io_op->io_res < file->output_buffer->len) - { - memcpy (file->output_buffer->str, - file->output_buffer->str + io_op->io_res, - file->output_buffer->len - io_op->io_res); - g_string_truncate (file->output_buffer, - file->output_buffer->len - io_op->io_res); - io_op->io_buffer = file->output_buffer->str; - io_op->io_size = file->output_buffer->len; - io_op->io_allow_cancel = FALSE; - return STATE_OP_WRITE; - } - g_string_truncate (file->output_buffer, 0); - - op->state = SEEK_STATE_HANDLE_INPUT; - break; - - /* No op */ - case SEEK_STATE_HANDLE_INPUT: - if (io_op->cancelled && !op->sent_cancel) - { - op->sent_cancel = TRUE; - append_request (file, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CANCEL, - op->seq_nr, 0, 0, NULL); - op->state = SEEK_STATE_WROTE_REQUEST; - io_op->io_buffer = file->output_buffer->str; - io_op->io_size = file->output_buffer->len; - io_op->io_allow_cancel = FALSE; - return STATE_OP_WRITE; - } - - if (io_op->io_res > 0) - { - gsize unread_size = io_op->io_size - io_op->io_res; - g_string_set_size (file->input_buffer, - file->input_buffer->len - unread_size); - } - - len = get_reply_header_missing_bytes (file->input_buffer); - if (len > 0) - { - gsize current_len = file->input_buffer->len; - g_string_set_size (file->input_buffer, - current_len + len); - io_op->io_buffer = file->input_buffer->str + current_len; - io_op->io_size = len; - io_op->io_allow_cancel = !op->sent_cancel; - return STATE_OP_READ; - } - - /* Got full header */ - - { - GVfsDaemonSocketProtocolReply reply; - char *data; - data = decode_reply (file->input_buffer, &reply); - - if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_ERROR && - reply.seq_nr == op->seq_nr) - { - op->ret_val = FALSE; - decode_error (&reply, data, &op->ret_error); - g_string_truncate (file->input_buffer, 0); - return STATE_OP_DONE; - } - else if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SEEK_POS) - { - op->ret_val = TRUE; - op->ret_offset = ((goffset)reply.arg2) << 32 | (goffset)reply.arg1; - g_string_truncate (file->input_buffer, 0); - return STATE_OP_DONE; - } - /* Ignore other reply types */ - } - - g_string_truncate (file->input_buffer, 0); - - /* This wasn't interesting, read next reply */ - op->state = SEEK_STATE_HANDLE_INPUT; - break; - - default: - g_assert_not_reached (); - } - - /* Clear io_op between non-op state switches */ - io_op->io_size = 0; - io_op->io_res = 0; - io_op->io_cancelled = FALSE; - } -} - -static gboolean -g_daemon_file_output_stream_seek (GFileOutputStream *stream, - goffset offset, - GSeekType type, - GCancellable *cancellable, - GError **error) -{ - GDaemonFileOutputStream *file; - SeekOperation op; - - file = G_DAEMON_FILE_OUTPUT_STREAM (stream); - - if (!file->can_seek) - { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - _("Seek not supported on stream")); - return FALSE; - } - - if (g_cancellable_set_error_if_cancelled (cancellable, error)) - return FALSE; - - memset (&op, 0, sizeof (op)); - op.state = SEEK_STATE_INIT; - op.offset = offset; - op.seek_type = type; - - if (!run_sync_state_machine (file, (state_machine_iterator)iterate_seek_state_machine, - &op, cancellable, error)) - return FALSE; /* IO Error */ - - if (!op.ret_val) - g_propagate_error (error, op.ret_error); - else - file->current_offset = op.ret_offset; - - return op.ret_val; -} - -static char * -g_daemon_file_output_stream_get_etag (GFileOutputStream *stream) -{ - GDaemonFileOutputStream *file; - - file = G_DAEMON_FILE_OUTPUT_STREAM (stream); - - return g_strdup (file->etag); -} - -static GFileInfo * -g_daemon_file_output_stream_query_info (GFileOutputStream *stream, - char *attributes, - GCancellable *cancellable, - GError **error) -{ -#if 0 - GDaemonFileOutputStream *file; - - file = G_DAEMON_FILE_OUTPUT_STREAM (stream); -#endif - - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - _("Query info not supported on stream")); - - return NULL; -} - -/************************************************************************ - * Async I/O Code * - ************************************************************************/ - -typedef struct AsyncIterator AsyncIterator; - -typedef void (*AsyncIteratorDone) (GOutputStream *stream, - gpointer op_data, - GAsyncReadyCallback callback, - gpointer callback_data, - GError *io_error); - -struct AsyncIterator { - AsyncIteratorDone done_cb; - GDaemonFileOutputStream *file; - GCancellable *cancellable; - IOOperationData io_data; - state_machine_iterator iterator; - gpointer iterator_data; - int io_priority; - GAsyncReadyCallback callback; - gpointer callback_data; -}; - -static void async_iterate (AsyncIterator *iterator); - -static void -async_iterator_done (AsyncIterator *iterator, GError *io_error) -{ - iterator->done_cb (G_OUTPUT_STREAM (iterator->file), - iterator->iterator_data, - iterator->callback, - iterator->callback_data, - io_error); - - g_free (iterator); - -} - -static void -async_op_handle (AsyncIterator *iterator, - gssize res, - GError *io_error) -{ - IOOperationData *io_data = &iterator->io_data; - GError *error; - - if (io_error != NULL) - { - if (error_is_cancel (io_error)) - { - io_data->io_res = 0; - io_data->io_cancelled = TRUE; - } - else - { - error = NULL; - g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Error in stream protocol: %s"), io_error->message); - async_iterator_done (iterator, error); - g_error_free (error); - return; - } - } - else if (res == 0 && io_data->io_size != 0) - { - error = NULL; - g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Error in stream protocol: %s"), _("End of stream")); - async_iterator_done (iterator, error); - g_error_free (error); - return; - } - else - { - io_data->io_res = res; - io_data->io_cancelled = FALSE; - } - - async_iterate (iterator); -} - -static void -async_read_op_callback (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - GInputStream *stream = G_INPUT_STREAM (source_object); - gssize count_read; - GError *error = NULL; - - count_read = g_input_stream_read_finish (stream, res, &error); - - async_op_handle ((AsyncIterator *)user_data, count_read, error); - if (error) - g_error_free (error); -} - -static void -async_skip_op_callback (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - GInputStream *stream = G_INPUT_STREAM (source_object); - gssize count_skipped; - GError *error = NULL; - - count_skipped = g_input_stream_skip_finish (stream, res, &error); - - async_op_handle ((AsyncIterator *)user_data, count_skipped, error); - if (error) - g_error_free (error); -} - -static void -async_write_op_callback (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - GOutputStream *stream = G_OUTPUT_STREAM (source_object); - gssize bytes_written; - GError *error = NULL; - - bytes_written = g_output_stream_write_finish (stream, res, &error); - - async_op_handle ((AsyncIterator *)user_data, bytes_written, error); - if (error) - g_error_free (error); -} - -static void -async_iterate (AsyncIterator *iterator) -{ - IOOperationData *io_data = &iterator->io_data; - GDaemonFileOutputStream *file = iterator->file; - StateOp io_op; - - io_data->cancelled = - g_cancellable_is_cancelled (iterator->cancellable); - - io_op = iterator->iterator (file, io_data, iterator->iterator_data); - - if (io_op == STATE_OP_DONE) - { - async_iterator_done (iterator, NULL); - return; - } - - /* TODO: Handle allow_cancel... */ - - if (io_op == STATE_OP_READ) - { - g_input_stream_read_async (file->data_stream, - io_data->io_buffer, io_data->io_size, - iterator->io_priority, - io_data->io_allow_cancel ? iterator->cancellable : NULL, - async_read_op_callback, iterator); - } - else if (io_op == STATE_OP_SKIP) - { - g_input_stream_skip_async (file->data_stream, - io_data->io_size, - iterator->io_priority, - io_data->io_allow_cancel ? iterator->cancellable : NULL, - async_skip_op_callback, iterator); - } - else if (io_op == STATE_OP_WRITE) - { - g_output_stream_write_async (file->command_stream, - io_data->io_buffer, io_data->io_size, - iterator->io_priority, - io_data->io_allow_cancel ? iterator->cancellable : NULL, - async_write_op_callback, iterator); - } - else - g_assert_not_reached (); -} - -static void -run_async_state_machine (GDaemonFileOutputStream *file, - state_machine_iterator iterator_cb, - gpointer iterator_data, - int io_priority, - GAsyncReadyCallback callback, - gpointer data, - GCancellable *cancellable, - AsyncIteratorDone done_cb) -{ - AsyncIterator *iterator; - - iterator = g_new0 (AsyncIterator, 1); - iterator->file = file; - iterator->iterator = iterator_cb; - iterator->iterator_data = iterator_data; - iterator->io_priority = io_priority; - iterator->cancellable = cancellable; - iterator->callback = callback; - iterator->callback_data = data; - iterator->done_cb = done_cb; - - async_iterate (iterator); -} - -static void -async_write_done (GOutputStream *stream, - gpointer op_data, - GAsyncReadyCallback callback, - gpointer user_data, - GError *io_error) -{ - GSimpleAsyncResult *simple; - WriteOperation *op; - gssize count_written; - GError *error; - - op = op_data; - - if (io_error) - { - count_written = -1; - error = io_error; - } - else - { - count_written = op->ret_val; - error = op->ret_error; - } - - simple = g_simple_async_result_new (G_OBJECT (stream), - callback, user_data, - g_daemon_file_output_stream_write_async); - - g_simple_async_result_set_op_res_gssize (simple, count_written); - - if (count_written == -1) - g_simple_async_result_set_from_error (simple, error); - - /* Complete immediately, not in idle, since we're already in a mainloop callout */ - g_simple_async_result_complete (simple); - g_object_unref (simple); - - if (op->ret_error) - g_error_free (op->ret_error); - g_free (op); -} - -static void -g_daemon_file_output_stream_write_async (GOutputStream *stream, - const void *buffer, - gsize count, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer data) -{ - GDaemonFileOutputStream *file; - WriteOperation *op; - - file = G_DAEMON_FILE_OUTPUT_STREAM (stream); - - /* Limit for sanity and to avoid 32bit overflow */ - if (count > MAX_WRITE_SIZE) - count = MAX_WRITE_SIZE; - - op = g_new0 (WriteOperation, 1); - op->state = WRITE_STATE_INIT; - op->buffer = buffer; - op->buffer_size = count; - - run_async_state_machine (file, - (state_machine_iterator)iterate_write_state_machine, - op, - io_priority, - callback, data, - cancellable, - async_write_done); -} - -static gssize -g_daemon_file_output_stream_write_finish (GOutputStream *stream, - GAsyncResult *result, - GError **error) -{ - GSimpleAsyncResult *simple; - gssize nwritten; - - simple = G_SIMPLE_ASYNC_RESULT (result); - g_assert (g_simple_async_result_get_source_tag (simple) == g_daemon_file_output_stream_write_async); - - nwritten = g_simple_async_result_get_op_res_gssize (simple); - return nwritten; -} - -static void -async_close_done (GOutputStream *stream, - gpointer op_data, - GAsyncReadyCallback callback, - gpointer user_data, - GError *io_error) -{ - GDaemonFileOutputStream *file; - GSimpleAsyncResult *simple; - CloseOperation *op; - gboolean result; - GError *error; - GCancellable *cancellable = NULL; /* TODO: get cancellable */ - - file = G_DAEMON_FILE_OUTPUT_STREAM (stream); - - op = op_data; - - if (io_error) - { - result = FALSE; - error = io_error; - } - else - { - result = op->ret_val; - error = op->ret_error; - } - - if (result) - result = g_output_stream_close (file->command_stream, cancellable, &error); - else - g_output_stream_close (file->command_stream, cancellable, NULL); - - if (result) - result = g_input_stream_close (file->data_stream, cancellable, &error); - else - g_input_stream_close (file->data_stream, cancellable, NULL); - - simple = g_simple_async_result_new (G_OBJECT (stream), - callback, user_data, - g_daemon_file_output_stream_close_async); - - if (!result) - g_simple_async_result_set_from_error (simple, error); - - /* Complete immediately, not in idle, since we're already in a mainloop callout */ - g_simple_async_result_complete (simple); - g_object_unref (simple); - - if (op->ret_error) - g_error_free (op->ret_error); - g_free (op); -} - -static void -g_daemon_file_output_stream_close_async (GOutputStream *stream, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer data) -{ - GDaemonFileOutputStream *file; - CloseOperation *op; - - file = G_DAEMON_FILE_OUTPUT_STREAM (stream); - - op = g_new0 (CloseOperation, 1); - op->state = CLOSE_STATE_INIT; - - run_async_state_machine (file, - (state_machine_iterator)iterate_close_state_machine, - op, io_priority, - (GAsyncReadyCallback)callback, data, - cancellable, - (AsyncIteratorDone)async_close_done); -} - -static gboolean -g_daemon_file_output_stream_close_finish (GOutputStream *stream, - GAsyncResult *result, - GError **error) -{ - /* Failures handled in generic close_finish code */ - return TRUE; -} diff --git a/gnome-2-24/client/gdaemonfileoutputstream.h b/gnome-2-24/client/gdaemonfileoutputstream.h deleted file mode 100644 index e609a48b..00000000 --- a/gnome-2-24/client/gdaemonfileoutputstream.h +++ /dev/null @@ -1,53 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -#ifndef __G_DAEMON_FILE_OUTPUT_STREAM_H__ -#define __G_DAEMON_FILE_OUTPUT_STREAM_H__ - -#include <gio/gio.h> - -G_BEGIN_DECLS - -#define G_TYPE_DAEMON_FILE_OUTPUT_STREAM (g_daemon_file_output_stream_get_type ()) -#define G_DAEMON_FILE_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DAEMON_FILE_OUTPUT_STREAM, GDaemonFileOutputStream)) -#define G_DAEMON_FILE_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DAEMON_FILE_OUTPUT_STREAM, GDaemonFileOutputStreamClass)) -#define G_IS_DAEMON_FILE_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DAEMON_FILE_OUTPUT_STREAM)) -#define G_IS_DAEMON_FILE_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DAEMON_FILE_OUTPUT_STREAM)) -#define G_DAEMON_FILE_OUTPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_DAEMON_FILE_OUTPUT_STREAM, GDaemonFileOutputStreamClass)) - -typedef struct _GDaemonFileOutputStream GDaemonFileOutputStream; -typedef struct _GDaemonFileOutputStreamClass GDaemonFileOutputStreamClass; - -struct _GDaemonFileOutputStreamClass -{ - GFileOutputStreamClass parent_class; -}; - -GType g_daemon_file_output_stream_get_type (void) G_GNUC_CONST; - -GFileOutputStream *g_daemon_file_output_stream_new (int fd, - gboolean can_seek, - goffset initial_offset); - -G_END_DECLS - -#endif /* __G_DAEMON_FILE_OUTPUT_STREAM_H__ */ diff --git a/gnome-2-24/client/gdaemonmount.c b/gnome-2-24/client/gdaemonmount.c deleted file mode 100644 index 43d8e181..00000000 --- a/gnome-2-24/client/gdaemonmount.c +++ /dev/null @@ -1,421 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -#include <config.h> - -#include <string.h> - -#include <glib.h> -#include <glib/gi18n-lib.h> -#include <gio/gio.h> -#include "gdaemonvolumemonitor.h" -#include "gdaemonmount.h" -#include "gvfsdaemondbus.h" -#include "gdaemonfile.h" -#include "gvfsdaemonprotocol.h" -#include "gdbusutils.h" - -/* Protects all fields of GDaemonMount that can change - which at this point is just foreign_volume */ -G_LOCK_DEFINE_STATIC(daemon_mount); - -struct _GDaemonMount { - GObject parent; - - GMountInfo *mount_info; - - GVolume *foreign_volume; - GVolumeMonitor *volume_monitor; -}; - -static void g_daemon_mount_mount_iface_init (GMountIface *iface); - -G_DEFINE_TYPE_WITH_CODE (GDaemonMount, g_daemon_mount, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (G_TYPE_MOUNT, - g_daemon_mount_mount_iface_init)) - -static void -g_daemon_mount_finalize (GObject *object) -{ - GDaemonMount *mount; - - mount = G_DAEMON_MOUNT (object); - - if (mount->foreign_volume != NULL) - g_object_unref (mount->foreign_volume); - - if (mount->volume_monitor != NULL) - g_object_remove_weak_pointer (G_OBJECT (mount->volume_monitor), (gpointer) &(mount->volume_monitor)); - - g_mount_info_unref (mount->mount_info); - - if (G_OBJECT_CLASS (g_daemon_mount_parent_class)->finalize) - (*G_OBJECT_CLASS (g_daemon_mount_parent_class)->finalize) (object); -} - -static void -g_daemon_mount_class_init (GDaemonMountClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->finalize = g_daemon_mount_finalize; -} - -static void -g_daemon_mount_init (GDaemonMount *daemon_mount) -{ -} - -GDaemonMount * -g_daemon_mount_new (GMountInfo *mount_info, - GVolumeMonitor *volume_monitor) -{ - GDaemonMount *mount; - - mount = g_object_new (G_TYPE_DAEMON_MOUNT, NULL); - mount->mount_info = g_mount_info_ref (mount_info); - mount->volume_monitor = volume_monitor; - g_object_set_data (G_OBJECT (mount), "g-stable-name", (gpointer) mount_info->stable_name); - if (mount->volume_monitor != NULL) - g_object_add_weak_pointer (G_OBJECT (volume_monitor), (gpointer) &(mount->volume_monitor)); - - return mount; -} - -GMountInfo * -g_daemon_mount_get_mount_info (GDaemonMount *mount) -{ - return mount->mount_info; -} - -static GFile * -g_daemon_mount_get_root (GMount *mount) -{ - GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount); - - return g_daemon_file_new (daemon_mount->mount_info->mount_spec, "/"); -} - -static GIcon * -g_daemon_mount_get_icon (GMount *mount) -{ - GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount); - - return g_themed_icon_new_with_default_fallbacks (daemon_mount->mount_info->icon); -} - -static char * -g_daemon_mount_get_name (GMount *mount) -{ - GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount); - - return g_strdup (daemon_mount->mount_info->display_name); -} - -static char * -g_daemon_mount_get_uuid (GMount *mount) -{ - return NULL; -} - -static GVolume * -g_daemon_mount_get_volume (GMount *mount) -{ - GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount); - if (daemon_mount->foreign_volume != NULL) - return g_object_ref (daemon_mount->foreign_volume); - return NULL; -} - -static GDrive * -g_daemon_mount_get_drive (GMount *mount) -{ - GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount); - GDrive *drive; - - G_LOCK (daemon_mount); - drive = NULL; - if (daemon_mount->foreign_volume != NULL) - drive = g_volume_get_drive (daemon_mount->foreign_volume); - G_UNLOCK (daemon_mount); - return drive; -} - -static gboolean -g_daemon_mount_can_unmount (GMount *mount) -{ - return TRUE; -} - -static gboolean -g_daemon_mount_can_eject (GMount *mount) -{ - GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount); - gboolean res; - - G_LOCK (daemon_mount); - res = FALSE; - if (daemon_mount->foreign_volume != NULL) - res = g_volume_can_eject (daemon_mount->foreign_volume); - G_UNLOCK (daemon_mount); - - return res; -} - -static void -foreign_volume_removed (GVolume *volume, gpointer user_data) -{ - GDaemonMount *daemon_mount = G_DAEMON_MOUNT (user_data); - - G_LOCK (daemon_mount); - - g_object_ref (daemon_mount); - - if (daemon_mount->foreign_volume == volume) - { - g_object_unref (daemon_mount->foreign_volume); - daemon_mount->foreign_volume = NULL; - } - - G_UNLOCK (daemon_mount); - - g_signal_emit_by_name (daemon_mount, "changed"); - if (daemon_mount->volume_monitor != NULL) - g_signal_emit_by_name (daemon_mount->volume_monitor, "mount_changed", daemon_mount); - - g_object_unref (daemon_mount); -} - -void -g_daemon_mount_set_foreign_volume (GDaemonMount *mount, - GVolume *foreign_volume) -{ - G_LOCK (daemon_mount); - - if (mount->foreign_volume != NULL) - g_object_unref (mount->foreign_volume); - - if (foreign_volume != NULL) - { - mount->foreign_volume = foreign_volume; - g_signal_connect_object (foreign_volume, "removed", (GCallback) foreign_volume_removed, mount, 0); - } - else - mount->foreign_volume = NULL; - - G_UNLOCK (daemon_mount); -} - -static void -unmount_reply (DBusMessage *reply, - DBusConnection *connection, - GError *io_error, - gpointer _data) -{ - GSimpleAsyncResult *result = _data; - - if (io_error != NULL) - g_simple_async_result_set_from_error (result, io_error); - - g_simple_async_result_complete (result); - g_object_unref (result); -} - -static void -g_daemon_mount_unmount (GMount *mount, - GMountUnmountFlags flags, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount); - DBusMessage *message; - GMountInfo *mount_info; - GSimpleAsyncResult *res; - guint32 dbus_flags; - - mount_info = daemon_mount->mount_info; - - message = - dbus_message_new_method_call (mount_info->dbus_id, - mount_info->object_path, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_UNMOUNT); - - dbus_flags = flags; - _g_dbus_message_append_args (message, DBUS_TYPE_UINT32, &dbus_flags, 0); - - res = g_simple_async_result_new (G_OBJECT (mount), - callback, user_data, - g_daemon_mount_unmount); - - _g_vfs_daemon_call_async (message, - unmount_reply, res, - cancellable); - - dbus_message_unref (message); -} - -static gboolean -g_daemon_mount_unmount_finish (GMount *mount, - GAsyncResult *result, - GError **error) -{ - return TRUE; -} - -typedef struct { - GObject *object; - GAsyncReadyCallback callback; - gpointer user_data; -} EjectWrapperOp; - -static void -eject_wrapper_callback (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - EjectWrapperOp *data = user_data; - data->callback (data->object, res, data->user_data); - g_free (data); -} - -static void -g_daemon_mount_eject (GMount *mount, - GMountUnmountFlags flags, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount); - GDrive *drive; - - G_LOCK (daemon_mount); - - drive = NULL; - if (daemon_mount->foreign_volume != NULL) - drive = g_volume_get_drive (G_VOLUME (daemon_mount->foreign_volume)); - - G_UNLOCK (daemon_mount); - - if (drive != NULL) - { - EjectWrapperOp *data; - data = g_new0 (EjectWrapperOp, 1); - data->object = G_OBJECT (mount); - data->callback = callback; - data->user_data = user_data; - g_drive_eject (drive, flags, cancellable, eject_wrapper_callback, data); - g_object_unref (drive); - } -} - -static gboolean -g_daemon_mount_eject_finish (GMount *mount, - GAsyncResult *result, - GError **error) -{ - GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount); - GDrive *drive; - gboolean res; - - res = TRUE; - - G_LOCK (daemon_mount); - - drive = NULL; - if (daemon_mount->foreign_volume != NULL) - drive = g_volume_get_drive (G_VOLUME (daemon_mount->foreign_volume)); - - G_UNLOCK (daemon_mount); - - if (drive != NULL) - { - res = g_drive_eject_finish (drive, result, error); - g_object_unref (drive); - } - - return res; -} - -static char ** -g_daemon_mount_guess_content_type_sync (GMount *mount, - gboolean force_rescan, - GCancellable *cancellable, - GError **error) -{ - GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount); - char **result; - - result = NULL; - G_LOCK (daemon_mount); - if (daemon_mount->mount_info->x_content_types != NULL && - strlen (daemon_mount->mount_info->x_content_types) > 0) - result = g_strsplit (daemon_mount->mount_info->x_content_types, " ", 0); - G_UNLOCK (daemon_mount); - - return result; -} - -static void -g_daemon_mount_guess_content_type (GMount *mount, - gboolean force_rescan, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GSimpleAsyncResult *simple; - simple = g_simple_async_result_new (G_OBJECT (mount), - callback, - user_data, - NULL); - g_simple_async_result_complete (simple); - g_object_unref (simple); -} - -static char ** -g_daemon_mount_guess_content_type_finish (GMount *mount, - GAsyncResult *result, - GError **error) -{ - return g_daemon_mount_guess_content_type_sync (mount, FALSE, NULL, error); -} - -static void -g_daemon_mount_mount_iface_init (GMountIface *iface) -{ - iface->get_root = g_daemon_mount_get_root; - iface->get_name = g_daemon_mount_get_name; - iface->get_icon = g_daemon_mount_get_icon; - iface->get_uuid = g_daemon_mount_get_uuid; - iface->get_volume = g_daemon_mount_get_volume; - iface->get_drive = g_daemon_mount_get_drive; - iface->can_unmount = g_daemon_mount_can_unmount; - iface->can_eject = g_daemon_mount_can_eject; - iface->unmount = g_daemon_mount_unmount; - iface->unmount_finish = g_daemon_mount_unmount_finish; - iface->eject = g_daemon_mount_eject; - iface->eject_finish = g_daemon_mount_eject_finish; - iface->guess_content_type = g_daemon_mount_guess_content_type; - iface->guess_content_type_finish = g_daemon_mount_guess_content_type_finish; - iface->guess_content_type_sync = g_daemon_mount_guess_content_type_sync; -} diff --git a/gnome-2-24/client/gdaemonmount.h b/gnome-2-24/client/gdaemonmount.h deleted file mode 100644 index bf4ba099..00000000 --- a/gnome-2-24/client/gdaemonmount.h +++ /dev/null @@ -1,57 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -#ifndef __G_DAEMON_MOUNT_H__ -#define __G_DAEMON_MOUNT_H__ - -#include <glib-object.h> -#include <gio/gio.h> -#include "gdaemonvfs.h" -#include "gdaemonvolumemonitor.h" -#include "gmounttracker.h" - -G_BEGIN_DECLS - -#define G_TYPE_DAEMON_MOUNT (g_daemon_mount_get_type ()) -#define G_DAEMON_MOUNT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DAEMON_MOUNT, GDaemonMount)) -#define G_DAEMON_MOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DAEMON_MOUNT, GDaemonMountClass)) -#define G_IS_DAEMON_MOUNT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DAEMON_MOUNT)) -#define G_IS_DAEMON_MOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DAEMON_MOUNT)) - -typedef struct _GDaemonMountClass GDaemonMountClass; - -struct _GDaemonMountClass { - GObjectClass parent_class; -}; - -GType g_daemon_mount_get_type (void) G_GNUC_CONST; - -GDaemonMount *g_daemon_mount_new (GMountInfo *mount_info, - GVolumeMonitor *volume_monitor); - -GMountInfo *g_daemon_mount_get_mount_info (GDaemonMount *mount); - -void g_daemon_mount_set_foreign_volume (GDaemonMount *mount, GVolume *foreign_volume); - -G_END_DECLS - -#endif /* __G_DAEMON_MOUNT_H__ */ diff --git a/gnome-2-24/client/gdaemonvfs.c b/gnome-2-24/client/gdaemonvfs.c deleted file mode 100644 index 7479bd82..00000000 --- a/gnome-2-24/client/gdaemonvfs.c +++ /dev/null @@ -1,1010 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -#include <config.h> -#include <string.h> -#include <signal.h> -#include <stdlib.h> -#include <dbus/dbus.h> -#include "gdaemonvfs.h" -#include "gvfsuriutils.h" -#include "gdaemonfile.h" -#include <gio/gio.h> -#include <gvfsdaemonprotocol.h> -#include <gmodule.h> -#include "gvfsdaemondbus.h" -#include "gdbusutils.h" -#include "gmountspec.h" -#include "gvfsurimapper.h" -#include "gdaemonvolumemonitor.h" -#include <glib/gi18n-lib.h> - -typedef struct { - char *type; - char *scheme; - char **scheme_aliases; - int default_port; - gboolean host_is_inet; -} MountableInfo; - -struct _GDaemonVfs -{ - GVfs parent; - - DBusConnection *async_bus; - - GVfs *wrapped_vfs; - GList *mount_cache; - - GHashTable *from_uri_hash; - GHashTable *to_uri_hash; - - MountableInfo **mountable_info; - char **supported_uri_schemes; -}; - -struct _GDaemonVfsClass -{ - GVfsClass parent_class; -}; - -G_DEFINE_DYNAMIC_TYPE (GDaemonVfs, g_daemon_vfs, G_TYPE_VFS) - -static GDaemonVfs *the_vfs = NULL; - -G_LOCK_DEFINE_STATIC(mount_cache); - - -static void fill_mountable_info (GDaemonVfs *vfs); - -static void -g_daemon_vfs_finalize (GObject *object) -{ - GDaemonVfs *vfs; - - vfs = G_DAEMON_VFS (object); - - if (vfs->from_uri_hash) - g_hash_table_destroy (vfs->from_uri_hash); - - if (vfs->to_uri_hash) - g_hash_table_destroy (vfs->to_uri_hash); - - g_strfreev (vfs->supported_uri_schemes); - - if (vfs->async_bus) - { - dbus_connection_close (vfs->async_bus); - dbus_connection_unref (vfs->async_bus); - } - - if (vfs->wrapped_vfs) - g_object_unref (vfs->wrapped_vfs); - - /* must chain up */ - G_OBJECT_CLASS (g_daemon_vfs_parent_class)->finalize (object); -} - -static MountableInfo * -get_mountable_info_for_scheme (GDaemonVfs *vfs, - const char *scheme) -{ - MountableInfo *info; - int i, j; - - if (vfs->mountable_info == NULL) - return NULL; - - for (i = 0; vfs->mountable_info[i] != NULL; i++) - { - info = vfs->mountable_info[i]; - - if (info->scheme != NULL && strcmp (info->scheme, scheme) == 0) - return info; - - if (info->scheme_aliases != NULL) - { - for (j = 0; info->scheme_aliases[j] != NULL; j++) - { - if (strcmp (info->scheme_aliases[j], scheme) == 0) - return info; - } - } - - } - - return NULL; -} - -static MountableInfo * -get_mountable_info_for_type (GDaemonVfs *vfs, - const char *type) -{ - MountableInfo *info; - int i; - - if (vfs->mountable_info == NULL) - return NULL; - - for (i = 0; vfs->mountable_info[i] != NULL; i++) - { - info = vfs->mountable_info[i]; - - if (strcmp (info->type, type) == 0) - return info; - } - - return NULL; -} - -static void -str_tolower_inplace (char *str) -{ - char *p = str; - - while (*p != 0) - { - *p = g_ascii_tolower (*p); - p++; - } - -} - -static gboolean -get_mountspec_from_uri (GDaemonVfs *vfs, - const char *uri, - GMountSpec **spec_out, - char **path_out) -{ - GMountSpec *spec; - char *path; - GVfsUriMapper *mapper; - char *scheme; - GVfsUriMountInfo *info; - - scheme = g_uri_parse_scheme (uri); - if (scheme == NULL) - return FALSE; - - /* convert the scheme to lower case since g_uri_parse_scheme - * doesn't do that and we compare with g_str_equal */ - str_tolower_inplace (scheme); - - spec = NULL; - path = NULL; - - mapper = g_hash_table_lookup (vfs->from_uri_hash, scheme); - - if (mapper) - { - info = g_vfs_uri_mapper_from_uri (mapper, uri); - if (info != NULL) - { - spec = g_mount_spec_new_from_data (info->keys, NULL); - path = info->path; - /* We took over ownership of info parts, custom free: */ - g_free (info); - } - } - - if (spec == NULL) - { - GDecodedUri *decoded; - MountableInfo *mountable; - char *type; - int l; - - decoded = g_vfs_decode_uri (uri); - if (decoded) - { - mountable = get_mountable_info_for_scheme (vfs, decoded->scheme); - - if (mountable) - type = mountable->type; - else - type = decoded->scheme; - - spec = g_mount_spec_new (type); - - if (decoded->host && *decoded->host) - { - if (mountable && mountable->host_is_inet) - { - /* Convert hostname to lower case */ - str_tolower_inplace (decoded->host); - - /* Remove brackets aroung ipv6 addresses */ - l = strlen (decoded->host); - if (decoded->host[0] == '[' && - decoded->host[l - 1] == ']') - g_mount_spec_set_with_len (spec, "host", decoded->host+1, l - 2); - else - g_mount_spec_set (spec, "host", decoded->host); - } - else - g_mount_spec_set (spec, "host", decoded->host); - } - - if (decoded->userinfo && *decoded->userinfo) - g_mount_spec_set (spec, "user", decoded->userinfo); - - if (decoded->port != -1 && - (mountable == NULL || - mountable->default_port == 0 || - mountable->default_port != decoded->port)) - { - char *port = g_strdup_printf ("%d", decoded->port); - g_mount_spec_set (spec, "port", port); - g_free (port); - } - - if (decoded->query && *decoded->query) - g_mount_spec_set (spec, "query", decoded->query); - if (decoded->fragment && *decoded->fragment) - g_mount_spec_set (spec, "fragment", decoded->fragment); - - path = g_strdup (decoded->path); - - g_vfs_decoded_uri_free (decoded); - } - } - - g_free (scheme); - - if (spec == NULL) - return FALSE; - - *spec_out = spec; - *path_out = path; - - return TRUE; -} - -static void -g_daemon_vfs_init (GDaemonVfs *vfs) -{ - GType *mappers; - guint n_mappers; - const char * const *schemes, * const *mount_types; - GVfsUriMapper *mapper; - GList *modules; - int i; - - bindtextdomain (GETTEXT_PACKAGE, GVFS_LOCALEDIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - - vfs->async_bus = dbus_bus_get_private (DBUS_BUS_SESSION, NULL); - - if (vfs->async_bus == NULL) - return; /* Not supported, return here and return false in vfs_is_active() */ - - g_assert (the_vfs == NULL); - the_vfs = vfs; - - if (g_thread_supported ()) - dbus_threads_init_default (); - - /* We disable SIGPIPE globally. This is sort of bad - for s library to do since its a global resource. - However, without this there is no way to be able - to handle mount daemons dying without client apps - crashing, which is much worse. - - I blame Unix, there really should be a portable - way to do this on all unixes, but there isn't, - even for somewhat modern ones like solaris. - */ - signal (SIGPIPE, SIG_IGN); - - fill_mountable_info (vfs); - - vfs->wrapped_vfs = g_vfs_get_local (); - - dbus_connection_set_exit_on_disconnect (vfs->async_bus, FALSE); - - _g_dbus_connection_integrate_with_main (vfs->async_bus); - - modules = g_io_modules_load_all_in_directory (GVFS_MODULE_DIR); - - vfs->from_uri_hash = g_hash_table_new (g_str_hash, g_str_equal); - vfs->to_uri_hash = g_hash_table_new (g_str_hash, g_str_equal); - - mappers = g_type_children (G_VFS_TYPE_URI_MAPPER, &n_mappers); - - for (i = 0; i < n_mappers; i++) - { - int j; - mapper = g_object_new (mappers[i], NULL); - - schemes = g_vfs_uri_mapper_get_handled_schemes (mapper); - - for (j = 0; schemes != NULL && schemes[j] != NULL; j++) - g_hash_table_insert (vfs->from_uri_hash, (char *)schemes[j], mapper); - - mount_types = g_vfs_uri_mapper_get_handled_mount_types (mapper); - for (j = 0; mount_types != NULL && mount_types[j] != NULL; j++) - g_hash_table_insert (vfs->to_uri_hash, (char *)mount_types[j], mapper); - } - - /* The above should have ref:ed the modules anyway */ - g_list_foreach (modules, (GFunc)g_type_module_unuse, NULL); - g_list_free (modules); - g_free (mappers); -} - -GDaemonVfs * -g_daemon_vfs_new (void) -{ - return g_object_new (G_TYPE_DAEMON_VFS, NULL); -} - -static GFile * -g_daemon_vfs_get_file_for_path (GVfs *vfs, - const char *path) -{ - /* TODO: detect fuse paths and convert to daemon vfs GFiles */ - - return g_vfs_get_file_for_path (G_DAEMON_VFS (vfs)->wrapped_vfs, path); -} - -static GFile * -g_daemon_vfs_get_file_for_uri (GVfs *vfs, - const char *uri) -{ - GDaemonVfs *daemon_vfs; - GFile *file; - GMountSpec *spec; - char *path; - - daemon_vfs = G_DAEMON_VFS (vfs); - - if (g_ascii_strncasecmp (uri, "file:", 5) == 0) - { - path = g_filename_from_uri (uri, NULL, NULL); - - if (path == NULL) - /* Dummy file */ - return g_vfs_get_file_for_uri (G_DAEMON_VFS (vfs)->wrapped_vfs, uri); - - file = g_daemon_vfs_get_file_for_path (vfs, path); - g_free (path); - return file; - } - - if (get_mountspec_from_uri (daemon_vfs, uri, &spec, &path)) - { - file = g_daemon_file_new (spec, path); - g_mount_spec_unref (spec); - g_free (path); - return file; - } - - /* Dummy file */ - return g_vfs_get_file_for_uri (G_DAEMON_VFS (vfs)->wrapped_vfs, uri); -} - -GMountSpec * -_g_daemon_vfs_get_mount_spec_for_path (GMountSpec *spec, - const char *path, - const char *new_path) -{ - const char *type; - GVfsUriMapper *mapper; - GMountSpec *new_spec; - - type = g_mount_spec_get_type (spec); - - if (type == NULL) - return g_mount_spec_ref (spec); - - new_spec = NULL; - mapper = g_hash_table_lookup (the_vfs->to_uri_hash, type); - if (mapper) - { - GVfsUriMountInfo info, *new_info; - info.keys = spec->items; - info.path = (char *)path; - new_info = g_vfs_uri_mapper_get_mount_info_for_path (mapper, &info, new_path); - if (new_info != NULL) - { - new_spec = g_mount_spec_new_from_data (new_info->keys, NULL); - /* We took over ownership of parts of new_info, custom free: */ - g_free (new_info->path); - g_free (new_info); - } - } - - if (new_spec == NULL) - new_spec = g_mount_spec_ref (spec); - - return new_spec; -} - -char * -_g_daemon_vfs_get_uri_for_mountspec (GMountSpec *spec, - char *path, - gboolean allow_utf8) -{ - char *uri; - const char *type; - GVfsUriMapper *mapper; - - type = g_mount_spec_get_type (spec); - if (type == NULL) - { - GString *string = g_string_new ("unknown://"); - if (path) - g_string_append_uri_escaped (string, - path, - "!$&'()*+,;=:@/", - allow_utf8); - - return g_string_free (string, FALSE); - } - - uri = NULL; - mapper = g_hash_table_lookup (the_vfs->to_uri_hash, type); - if (mapper) - { - GVfsUriMountInfo info; - info.keys = spec->items; - info.path = path; - uri = g_vfs_uri_mapper_to_uri (mapper, &info, allow_utf8); - } - - if (uri == NULL) - { - GDecodedUri decoded; - MountableInfo *mountable; - const char *port; - gboolean free_host; - - memset (&decoded, 0, sizeof (decoded)); - decoded.port = -1; - - mountable = get_mountable_info_for_type (the_vfs, type); - - if (mountable) - decoded.scheme = mountable->scheme; - else - decoded.scheme = (char *)type; - decoded.host = (char *)g_mount_spec_get (spec, "host"); - free_host = FALSE; - if (mountable && mountable->host_is_inet && decoded.host != NULL && strchr (decoded.host, ':') != NULL) - { - free_host = TRUE; - decoded.host = g_strconcat ("[", decoded.host, "]", NULL); - } - - decoded.userinfo = (char *)g_mount_spec_get (spec, "user"); - port = g_mount_spec_get (spec, "port"); - if (port != NULL) - decoded.port = atoi (port); - - if (path == NULL) - decoded.path = "/"; - else - decoded.path = path; - - decoded.query = (char *)g_mount_spec_get (spec, "query"); - decoded.fragment = (char *)g_mount_spec_get (spec, "fragment"); - - uri = g_vfs_encode_uri (&decoded, FALSE); - - if (free_host) - g_free (decoded.host); - } - - return uri; -} - -const char * -_g_daemon_vfs_mountspec_get_uri_scheme (GMountSpec *spec) -{ - const char *type, *scheme; - GVfsUriMapper *mapper; - MountableInfo *mountable; - - type = g_mount_spec_get_type (spec); - mapper = g_hash_table_lookup (the_vfs->to_uri_hash, type); - - scheme = NULL; - if (mapper) - { - GVfsUriMountInfo info; - - info.keys = spec->items; - info.path = "/"; - - scheme = g_vfs_uri_mapper_to_uri_scheme (mapper, &info); - } - - if (scheme == NULL) - { - mountable = get_mountable_info_for_type (the_vfs, type); - if (mountable) - scheme = mountable->scheme; - else - scheme = type; - } - - return scheme; -} - -static int -find_string (GPtrArray *array, const char *find_me) -{ - int i; - - g_return_val_if_fail (find_me != NULL, -1); - - for (i = 0; i < array->len; ++i) - { - if (strcmp (g_ptr_array_index (array, i), find_me) == 0) - return i; - } - - return -1; -} - - -static void -fill_mountable_info (GDaemonVfs *vfs) -{ - DBusMessage *message, *reply; - DBusError error; - DBusMessageIter iter, array_iter, struct_iter; - MountableInfo *info; - GPtrArray *infos, *uri_schemes; - gint i, count; - - message = dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME, - G_VFS_DBUS_MOUNTTRACKER_PATH, - G_VFS_DBUS_MOUNTTRACKER_INTERFACE, - G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNTABLE_INFO); - - if (message == NULL) - _g_dbus_oom (); - - dbus_message_set_auto_start (message, TRUE); - - dbus_error_init (&error); - reply = dbus_connection_send_with_reply_and_block (vfs->async_bus, - message, - G_VFS_DBUS_TIMEOUT_MSECS, - &error); - dbus_message_unref (message); - - if (dbus_error_is_set (&error)) - { - dbus_error_free (&error); - return; - } - - if (reply == NULL) - _g_dbus_oom (); - - dbus_message_iter_init (reply, &iter); - - dbus_message_iter_recurse (&iter, &array_iter); - - infos = g_ptr_array_new (); - uri_schemes = g_ptr_array_new (); - count = 0; - do - { - char *type, *scheme, **scheme_aliases; - int scheme_aliases_len; - gint32 default_port; - dbus_bool_t host_is_inet; - - if (dbus_message_iter_get_arg_type (&array_iter) != DBUS_TYPE_STRUCT) - break; - - dbus_message_iter_recurse (&array_iter, &struct_iter); - - if (!_g_dbus_message_iter_get_args (&struct_iter, NULL, - DBUS_TYPE_STRING, &type, - DBUS_TYPE_STRING, &scheme, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &scheme_aliases, &scheme_aliases_len, - DBUS_TYPE_INT32, &default_port, - DBUS_TYPE_BOOLEAN, &host_is_inet, - 0)) - break; - - info = g_new0 (MountableInfo, 1); - info->type = g_strdup (type); - if (*scheme != 0) - { - info->scheme = g_strdup (scheme); - if (find_string (uri_schemes, scheme) == -1) - g_ptr_array_add (uri_schemes, g_strdup (scheme)); - } - - if (scheme_aliases_len > 0) - { - info->scheme_aliases = g_new (char *, scheme_aliases_len + 1); - for (i = 0; i < scheme_aliases_len; i++) - { - info->scheme_aliases[i] = g_strdup (scheme_aliases[i]); - if (find_string (uri_schemes, scheme_aliases[i]) == -1) - g_ptr_array_add (uri_schemes, g_strdup (scheme_aliases[i])); - } - info->scheme_aliases[scheme_aliases_len] = NULL; - } - - info->default_port = default_port; - info->host_is_inet = host_is_inet; - - g_ptr_array_add (infos, info); - - g_strfreev (scheme_aliases); - } - while (dbus_message_iter_next (&array_iter)); - - dbus_message_unref (reply); - - g_ptr_array_add (uri_schemes, NULL); - g_ptr_array_add (infos, NULL); - vfs->mountable_info = (MountableInfo **)g_ptr_array_free (infos, FALSE); - vfs->supported_uri_schemes = (char **)g_ptr_array_free (uri_schemes, FALSE); -} - - -static const gchar * const * -g_daemon_vfs_get_supported_uri_schemes (GVfs *vfs) -{ - return (const gchar * const *) G_DAEMON_VFS (vfs)->supported_uri_schemes; -} - -static GMountInfo * -lookup_mount_info_in_cache_locked (GMountSpec *spec, - const char *path) -{ - GMountInfo *info; - GList *l; - - info = NULL; - for (l = the_vfs->mount_cache; l != NULL; l = l->next) - { - GMountInfo *mount_info = l->data; - - if (g_mount_spec_match_with_path (mount_info->mount_spec, spec, path)) - { - info = g_mount_info_ref (mount_info); - break; - } - } - - return info; -} - -static GMountInfo * -lookup_mount_info_in_cache (GMountSpec *spec, - const char *path) -{ - GMountInfo *info; - - G_LOCK (mount_cache); - info = lookup_mount_info_in_cache_locked (spec, path); - G_UNLOCK (mount_cache); - - return info; -} - -void -_g_daemon_vfs_invalidate_dbus_id (const char *dbus_id) -{ - GList *l, *next; - - G_LOCK (mount_cache); - for (l = the_vfs->mount_cache; l != NULL; l = next) - { - GMountInfo *mount_info = l->data; - next = l->next; - - if (strcmp (mount_info->dbus_id, dbus_id) == 0) - { - the_vfs->mount_cache = g_list_delete_link (the_vfs->mount_cache, l); - g_mount_info_unref (mount_info); - } - } - - G_UNLOCK (mount_cache); -} - - -static GMountInfo * -handler_lookup_mount_reply (DBusMessage *reply, - GError **error) -{ - DBusError derror; - GMountInfo *info; - DBusMessageIter iter; - GList *l; - gboolean in_cache; - - - if (_g_error_from_message (reply, error)) - return NULL; - - dbus_error_init (&derror); - dbus_message_iter_init (reply, &iter); - - info = g_mount_info_from_dbus (&iter); - if (info == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Error while getting mount info: %s"), - "Invalid reply"); - return NULL; - } - - G_LOCK (mount_cache); - - in_cache = FALSE; - /* Already in cache from other thread? */ - for (l = the_vfs->mount_cache; l != NULL; l = l->next) - { - GMountInfo *cached_info = l->data; - - if (g_mount_info_equal (info, cached_info)) - { - in_cache = TRUE; - g_mount_info_unref (info); - info = g_mount_info_ref (cached_info); - break; - } - } - - /* No, lets add it to the cache */ - if (!in_cache) - the_vfs->mount_cache = g_list_prepend (the_vfs->mount_cache, g_mount_info_ref (info)); - - G_UNLOCK (mount_cache); - - return info; -} - -typedef struct { - GMountInfoLookupCallback callback; - gpointer user_data; -} GetMountInfoData; - -static void -async_get_mount_info_response (DBusMessage *reply, - GError *io_error, - void *_data) -{ - GetMountInfoData *data = _data; - GMountInfo *info; - GError *error; - - if (reply == NULL) - data->callback (NULL, data->user_data, io_error); - else - { - error = NULL; - info = handler_lookup_mount_reply (reply, &error); - - data->callback (info, data->user_data, error); - - if (info) - g_mount_info_unref (info); - - if (error) - g_error_free (error); - } - - g_free (data); -} - -void -_g_daemon_vfs_get_mount_info_async (GMountSpec *spec, - const char *path, - GMountInfoLookupCallback callback, - gpointer user_data) -{ - GMountInfo *info; - GetMountInfoData *data; - DBusMessage *message; - DBusMessageIter iter; - - info = lookup_mount_info_in_cache (spec, path); - - if (info != NULL) - { - callback (info, user_data, NULL); - g_mount_info_unref (info); - return; - } - - message = - dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME, - G_VFS_DBUS_MOUNTTRACKER_PATH, - G_VFS_DBUS_MOUNTTRACKER_INTERFACE, - G_VFS_DBUS_MOUNTTRACKER_OP_LOOKUP_MOUNT); - dbus_message_set_auto_start (message, TRUE); - - dbus_message_iter_init_append (message, &iter); - g_mount_spec_to_dbus_with_path (&iter, spec, path); - - data = g_new0 (GetMountInfoData, 1); - data->callback = callback; - data->user_data = user_data; - - _g_dbus_connection_call_async (the_vfs->async_bus, message, G_VFS_DBUS_TIMEOUT_MSECS, - async_get_mount_info_response, - data); - - dbus_message_unref (message); -} - - -GMountInfo * -_g_daemon_vfs_get_mount_info_sync (GMountSpec *spec, - const char *path, - GError **error) -{ - GMountInfo *info; - DBusConnection *conn; - DBusMessage *message, *reply; - DBusMessageIter iter; - DBusError derror; - - info = lookup_mount_info_in_cache (spec, path); - - if (info != NULL) - return info; - - conn = _g_dbus_connection_get_sync (NULL, error); - if (conn == NULL) - return NULL; - - message = - dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME, - G_VFS_DBUS_MOUNTTRACKER_PATH, - G_VFS_DBUS_MOUNTTRACKER_INTERFACE, - G_VFS_DBUS_MOUNTTRACKER_OP_LOOKUP_MOUNT); - dbus_message_set_auto_start (message, TRUE); - - dbus_message_iter_init_append (message, &iter); - g_mount_spec_to_dbus_with_path (&iter, spec, path); - - dbus_error_init (&derror); - reply = dbus_connection_send_with_reply_and_block (conn, message, -1, &derror); - dbus_message_unref (message); - - if (!reply) - { - _g_error_from_dbus (&derror, error); - dbus_error_free (&derror); - return NULL; - } - - info = handler_lookup_mount_reply (reply, error); - - dbus_message_unref (reply); - - return info; -} - -static GFile * -g_daemon_vfs_parse_name (GVfs *vfs, - const char *parse_name) -{ - GFile *file; - - if (g_path_is_absolute (parse_name) || - *parse_name == '~') - { - /* TODO: detect fuse paths and convert to daemon vfs GFiles ? */ - file = g_vfs_parse_name (G_DAEMON_VFS (vfs)->wrapped_vfs, parse_name); - } - else - { - file = g_daemon_vfs_get_file_for_uri (vfs, parse_name); - } - - return file; -} - -DBusConnection * -_g_daemon_vfs_get_async_bus (void) -{ - return the_vfs->async_bus; -} - -static gboolean -g_daemon_vfs_is_active (GVfs *vfs) -{ - GDaemonVfs *daemon_vfs = G_DAEMON_VFS (vfs); - return daemon_vfs->async_bus != NULL; -} - -static void -g_daemon_vfs_class_finalize (GDaemonVfsClass *klass) -{ -} - -static void -g_daemon_vfs_class_init (GDaemonVfsClass *class) -{ - GObjectClass *object_class; - GVfsClass *vfs_class; - - object_class = (GObjectClass *) class; - - g_daemon_vfs_parent_class = g_type_class_peek_parent (class); - - object_class->finalize = g_daemon_vfs_finalize; - - vfs_class = G_VFS_CLASS (class); - - vfs_class->is_active = g_daemon_vfs_is_active; - vfs_class->get_file_for_path = g_daemon_vfs_get_file_for_path; - vfs_class->get_file_for_uri = g_daemon_vfs_get_file_for_uri; - vfs_class->get_supported_uri_schemes = g_daemon_vfs_get_supported_uri_schemes; - vfs_class->parse_name = g_daemon_vfs_parse_name; -} - -/* Module API */ - -void g_vfs_uri_mapper_smb_register (GIOModule *module); -void g_vfs_uri_mapper_http_register (GIOModule *module); -void g_vfs_uri_mapper_sftp_register (GIOModule *module); - -void -g_io_module_load (GIOModule *module) -{ - /* This is so that system daemons can use gio - * without spawning private dbus instances. - * See bug 526454. - */ - if (g_getenv ("DBUS_SESSION_BUS_ADDRESS") == NULL) - return; - - /* Make this module resident so that we ground the common - * library. If that is unloaded we could get into all kinds - * of strange situations. This is safe to do even if we loaded - * some other common-using module first as all modules are loaded - * before any are freed. - */ - g_type_module_use (G_TYPE_MODULE (module)); - - g_daemon_vfs_register_type (G_TYPE_MODULE (module)); - g_daemon_volume_monitor_register_types (G_TYPE_MODULE (module)); - - g_io_extension_point_implement (G_VFS_EXTENSION_POINT_NAME, - G_TYPE_DAEMON_VFS, - "gvfs", - 10); - - g_vfs_uri_mapper_register (module); - g_vfs_uri_mapper_smb_register (module); - g_vfs_uri_mapper_http_register (module); -} - -void -g_io_module_unload (GIOModule *module) -{ -} diff --git a/gnome-2-24/client/gdaemonvfs.h b/gnome-2-24/client/gdaemonvfs.h deleted file mode 100644 index 3b17b880..00000000 --- a/gnome-2-24/client/gdaemonvfs.h +++ /dev/null @@ -1,73 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -#ifndef __G_DAEMON_VFS_H__ -#define __G_DAEMON_VFS_H__ - -#include <gio/gio.h> -#include <dbus/dbus.h> -#include "gmountspec.h" -#include "gmounttracker.h" -#include "gvfsuriutils.h" - -G_BEGIN_DECLS - -#define G_TYPE_DAEMON_VFS (g_daemon_vfs_get_type ()) -#define G_DAEMON_VFS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_DAEMON_VFS, GDaemonVfs)) -#define G_DAEMON_VFS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), G_TYPE_DAEMON_VFS, GDaemonVfsClass)) -#define G_IS_DAEMON_VFS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_DAEMON_VFS)) -#define G_IS_DAEMON_VFS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), G_TYPE_DAEMON_VFS)) -#define G_DAEMON_VFS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_DAEMON_VFS, GDaemonVfsClass)) - -typedef struct _GDaemonVfs GDaemonVfs; -typedef struct _GDaemonVfsClass GDaemonVfsClass; - -typedef void (*GMountInfoLookupCallback) (GMountInfo *mount_info, - gpointer data, - GError *error); - -GType g_daemon_vfs_get_type (void); - -GDaemonVfs *g_daemon_vfs_new (void); - -char * _g_daemon_vfs_get_uri_for_mountspec (GMountSpec *spec, - char *path, - gboolean allow_utf8); -const char * _g_daemon_vfs_mountspec_get_uri_scheme (GMountSpec *spec); -void _g_daemon_vfs_get_mount_info_async (GMountSpec *spec, - const char *path, - GMountInfoLookupCallback callback, - gpointer user_data); -GMountInfo * _g_daemon_vfs_get_mount_info_sync (GMountSpec *spec, - const char *path, - GError **error); -GMountSpec * _g_daemon_vfs_get_mount_spec_for_path (GMountSpec *spec, - const char *path, - const char *new_path); -void _g_daemon_vfs_invalidate_dbus_id (const char *dbus_id); -DBusConnection *_g_daemon_vfs_get_async_bus (void); - - - -G_END_DECLS - -#endif /* __G_DAEMON_VFS_H__ */ diff --git a/gnome-2-24/client/gdaemonvolumemonitor.c b/gnome-2-24/client/gdaemonvolumemonitor.c deleted file mode 100644 index e26bde09..00000000 --- a/gnome-2-24/client/gdaemonvolumemonitor.c +++ /dev/null @@ -1,329 +0,0 @@ - -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -#include <config.h> - -#include <string.h> - -#include <glib.h> -#include <glib/gi18n-lib.h> -#include "gdaemonvolumemonitor.h" -#include "gdaemonmount.h" -#include "gdaemonvfs.h" -#include "gmounttracker.h" - -G_LOCK_DEFINE_STATIC(daemon_vm); - -static GDaemonVolumeMonitor *_the_daemon_volume_monitor; - -struct _GDaemonVolumeMonitor { - GVolumeMonitor parent; - - GMountTracker *mount_tracker; - GList *mounts; -}; - -G_DEFINE_DYNAMIC_TYPE (GDaemonVolumeMonitor, g_daemon_volume_monitor, G_TYPE_VOLUME_MONITOR) - -static GList * -get_mounts (GVolumeMonitor *volume_monitor) -{ - GDaemonVolumeMonitor *monitor; - GList *l; - - G_LOCK (daemon_vm); - - monitor = G_DAEMON_VOLUME_MONITOR (volume_monitor); - - l = g_list_copy (monitor->mounts); - g_list_foreach (l, (GFunc)g_object_ref, NULL); - - G_UNLOCK (daemon_vm); - - return l; -} - -static GList * -get_volumes (GVolumeMonitor *volume_monitor) -{ - /* TODO: Can daemon mounts have volumes? */ - return NULL; -} - -static GList * -get_connected_drives (GVolumeMonitor *volume_monitor) -{ - /* TODO: Can daemon mounts have drives? */ - return NULL; -} - -static GVolume * -get_volume_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid) -{ - return NULL; -} - -static GMount * -get_mount_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid) -{ - return NULL; -} - -static GDaemonMount * -find_mount_by_mount_info (GDaemonVolumeMonitor *daemon_monitor, GMountInfo *mount_info) -{ - GDaemonMount *found_mount = NULL; - GList *l; - - for (l = daemon_monitor->mounts; l; l = g_list_next (l)) - { - GDaemonMount *existing_mount = l->data; - GMountInfo *existing_mount_info; - - existing_mount_info = g_daemon_mount_get_mount_info (existing_mount); - if (g_mount_info_equal (mount_info, existing_mount_info)) - { - found_mount = existing_mount; - break; - } - } - - return found_mount; -} - -GDaemonMount * -g_daemon_volume_monitor_find_mount_by_mount_info (GMountInfo *mount_info) -{ - GDaemonMount *daemon_mount; - - G_LOCK (daemon_vm); - - daemon_mount = NULL; - if (_the_daemon_volume_monitor != NULL) - { - daemon_mount = find_mount_by_mount_info (_the_daemon_volume_monitor, mount_info); - - if (daemon_mount != NULL) - g_object_ref (daemon_mount); - } - - G_UNLOCK (daemon_vm); - - return daemon_mount; -} - -static void -mount_added (GDaemonVolumeMonitor *daemon_monitor, GMountInfo *mount_info) -{ - GDaemonMount *mount; - GVolume *volume; - - G_LOCK (daemon_vm); - - mount = find_mount_by_mount_info (daemon_monitor, mount_info); - if (mount) - { - g_warning (G_STRLOC ": Mount was added twice!"); - - G_UNLOCK (daemon_vm); - return; - } - - if (mount_info->user_visible) - { - mount = g_daemon_mount_new (mount_info, G_VOLUME_MONITOR (daemon_monitor)); - volume = g_volume_monitor_adopt_orphan_mount (G_MOUNT (mount)); - if (volume != NULL) - g_daemon_mount_set_foreign_volume (mount, volume); - daemon_monitor->mounts = g_list_prepend (daemon_monitor->mounts, mount); - - /* Ref for the signal emission, other ref is owned by volume monitor */ - g_object_ref (mount); - } - - G_UNLOCK (daemon_vm); - - if (mount) - { - /* Emit signal outside lock */ - g_signal_emit_by_name (daemon_monitor, "mount_added", mount); - g_object_unref (mount); - } -} - -static void -mount_removed (GDaemonVolumeMonitor *daemon_monitor, GMountInfo *mount_info) -{ - GDaemonMount *mount; - - G_LOCK (daemon_vm); - - mount = find_mount_by_mount_info (daemon_monitor, mount_info); - if (!mount) - { - if (mount_info->user_visible) - g_warning (G_STRLOC ": An unknown mount was removed!"); - - G_UNLOCK (daemon_vm); - return; - } - - daemon_monitor->mounts = g_list_remove (daemon_monitor->mounts, mount); - - G_UNLOCK (daemon_vm); - - g_signal_emit_by_name (daemon_monitor, "mount_removed", mount); - g_signal_emit_by_name (mount, "unmounted"); - - g_object_unref (mount); -} - -static void -g_daemon_volume_monitor_init (GDaemonVolumeMonitor *daemon_monitor) -{ - GList *mounts, *l; - GDaemonMount *mount; - GMountInfo *info; - GVolume *volume; - - _the_daemon_volume_monitor = daemon_monitor; - - daemon_monitor->mount_tracker = g_mount_tracker_new (_g_daemon_vfs_get_async_bus ()); - - g_signal_connect_swapped (daemon_monitor->mount_tracker, "mounted", - (GCallback) mount_added, daemon_monitor); - g_signal_connect_swapped (daemon_monitor->mount_tracker, "unmounted", - (GCallback) mount_removed, daemon_monitor); - - /* Initialize with current list */ - mounts = g_mount_tracker_list_mounts (daemon_monitor->mount_tracker); - - for (l = mounts; l != NULL; l = l->next) { - info = l->data; - if (info->user_visible) - { - mount = g_daemon_mount_new (info, G_VOLUME_MONITOR (daemon_monitor)); - volume = g_volume_monitor_adopt_orphan_mount (G_MOUNT (mount)); - if (volume != NULL) - g_daemon_mount_set_foreign_volume (mount, volume); - daemon_monitor->mounts = g_list_prepend (daemon_monitor->mounts, mount); - } - - g_mount_info_unref (info); - } - - g_list_free (mounts); -} - -static void -g_daemon_volume_monitor_finalize (GObject *object) -{ - GDaemonVolumeMonitor *monitor; - - monitor = G_DAEMON_VOLUME_MONITOR (object); - - g_signal_handlers_disconnect_by_func (monitor->mount_tracker, mount_added, monitor); - g_signal_handlers_disconnect_by_func (monitor->mount_tracker, mount_removed, monitor); - - g_object_unref (monitor->mount_tracker); - - g_list_foreach (monitor->mounts, (GFunc)g_object_unref, NULL); - g_list_free (monitor->mounts); - - if (G_OBJECT_CLASS (g_daemon_volume_monitor_parent_class)->finalize) - (*G_OBJECT_CLASS (g_daemon_volume_monitor_parent_class)->finalize) (object); -} - -static void -g_daemon_volume_monitor_dispose (GObject *object) -{ - GDaemonVolumeMonitor *monitor; - - monitor = G_DAEMON_VOLUME_MONITOR (object); - - G_LOCK (daemon_vm); - _the_daemon_volume_monitor = NULL; - G_UNLOCK (daemon_vm); - - if (G_OBJECT_CLASS (g_daemon_volume_monitor_parent_class)->dispose) - (*G_OBJECT_CLASS (g_daemon_volume_monitor_parent_class)->dispose) (object); -} - -static void -g_daemon_volume_monitor_class_finalize (GDaemonVolumeMonitorClass *klass) -{ -} - -static gboolean -is_supported (void) -{ - GVfs *vfs; - gboolean res; - - res = FALSE; - - /* Don't do anything if the default vfs is not DAEMON_VFS */ - vfs = g_vfs_get_default (); - - if (vfs != NULL && G_IS_DAEMON_VFS (vfs)) - res = TRUE; - - return res; -} - -static void -g_daemon_volume_monitor_class_init (GDaemonVolumeMonitorClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GVolumeMonitorClass *monitor_class = G_VOLUME_MONITOR_CLASS (klass); - - gobject_class->finalize = g_daemon_volume_monitor_finalize; - gobject_class->dispose = g_daemon_volume_monitor_dispose; - - monitor_class->is_supported = is_supported; - monitor_class->get_mounts = get_mounts; - monitor_class->get_volumes = get_volumes; - monitor_class->get_connected_drives = get_connected_drives; - monitor_class->get_volume_for_uuid = get_volume_for_uuid; - monitor_class->get_mount_for_uuid = get_mount_for_uuid; -} - -GVolumeMonitor * -g_daemon_volume_monitor_new (void) -{ - GDaemonVolumeMonitor *monitor; - - monitor = g_object_new (G_TYPE_DAEMON_VOLUME_MONITOR, NULL); - - return G_VOLUME_MONITOR (monitor); -} - -void -g_daemon_volume_monitor_register_types (GTypeModule *module) -{ - g_daemon_volume_monitor_register_type (G_TYPE_MODULE (module)); - g_io_extension_point_implement (G_VOLUME_MONITOR_EXTENSION_POINT_NAME, - G_TYPE_DAEMON_VOLUME_MONITOR, - "gvfs", - 0); -} diff --git a/gnome-2-24/client/gdaemonvolumemonitor.h b/gnome-2-24/client/gdaemonvolumemonitor.h deleted file mode 100644 index 4019ca35..00000000 --- a/gnome-2-24/client/gdaemonvolumemonitor.h +++ /dev/null @@ -1,60 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -#ifndef __G_DAEMON_VOLUME_MONITOR_H__ -#define __G_DAEMON_VOLUME_MONITOR_H__ - -#include <glib-object.h> -#include <gio/gio.h> -#include "gmounttracker.h" - -G_BEGIN_DECLS - -#define G_TYPE_DAEMON_VOLUME_MONITOR (g_daemon_volume_monitor_get_type ()) -#define G_DAEMON_VOLUME_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DAEMON_VOLUME_MONITOR, GDaemonVolumeMonitor)) -#define G_DAEMON_VOLUME_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DAEMON_VOLUME_MONITOR, GDaemonVolumeMonitorClass)) -#define G_IS_DAEMON_VOLUME_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DAEMON_VOLUME_MONITOR)) -#define G_IS_DAEMON_VOLUME_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DAEMON_VOLUME_MONITOR)) - -typedef struct _GDaemonVolumeMonitor GDaemonVolumeMonitor; -typedef struct _GDaemonVolumeMonitorClass GDaemonVolumeMonitorClass; - -/* Forward definitions */ -typedef struct _GDaemonMount GDaemonMount; -typedef struct _GDaemonVolume GDaemonVolume; -typedef struct _GDaemonDrive GDaemonDrive; - -struct _GDaemonVolumeMonitorClass { - GVolumeMonitorClass parent_class; - -}; - -GType g_daemon_volume_monitor_get_type (void) G_GNUC_CONST; -void g_daemon_volume_monitor_register_types (GTypeModule *type_module); - -GVolumeMonitor *g_daemon_volume_monitor_new (void); - -GDaemonMount *g_daemon_volume_monitor_find_mount_by_mount_info (GMountInfo *mount_info); - -G_END_DECLS - -#endif /* __G_DAEMON_VOLUME_MONITOR_H__ */ diff --git a/gnome-2-24/client/gvfsdaemondbus.c b/gnome-2-24/client/gvfsdaemondbus.c deleted file mode 100644 index aabb8dea..00000000 --- a/gnome-2-24/client/gvfsdaemondbus.c +++ /dev/null @@ -1,1024 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -#include <config.h> - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <stdlib.h> -#include <unistd.h> -#include <stdio.h> -#include <errno.h> -#include <poll.h> - -#include <glib/gi18n-lib.h> - -#include <gio/gio.h> -#include "gvfsdaemondbus.h" -#include <gvfsdaemonprotocol.h> -#include <gdaemonvfs.h> -#include "gdbusutils.h" -#include "gsysutils.h" - -/* Extra vfs-specific data for DBusConnections */ -typedef struct { - int extra_fd; - int extra_fd_count; - char *async_dbus_id; - - /* Only used for async connections */ - GHashTable *outstanding_fds; - GSource *extra_fd_source; -} VfsConnectionData; - -static gint32 vfs_data_slot = -1; -static GOnce once_init_dbus = G_ONCE_INIT; - -static GStaticPrivate local_connections = G_STATIC_PRIVATE_INIT; - -/* dbus id -> async connection */ -static GHashTable *async_map = NULL; -G_LOCK_DEFINE_STATIC(async_map); - -/* dbus object path -> dbus message filter */ -static GHashTable *obj_path_map = NULL; -G_LOCK_DEFINE_STATIC(obj_path_map); - -static void setup_async_fd_receive (VfsConnectionData *connection_data); -static void invalidate_local_connection (const char *dbus_id, - GError **error); - - -GQuark -_g_vfs_error_quark (void) -{ - return g_quark_from_static_string ("g-vfs-error-quark"); -} - -static gpointer -vfs_dbus_init (gpointer arg) -{ - if (!dbus_connection_allocate_data_slot (&vfs_data_slot)) - g_error ("Unable to allocate data slot"); - - return NULL; -} - -/************************************************************************** - * message filters for vfs dbus connections * - *************************************************************************/ - -typedef struct { - DBusHandleMessageFunction callback; - GObject *data; -} PathMapEntry; - -void -_g_dbus_register_vfs_filter (const char *obj_path, - DBusHandleMessageFunction callback, - GObject *data) -{ - PathMapEntry * entry; - - G_LOCK (obj_path_map); - - if (obj_path_map == NULL) - obj_path_map = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, g_free); - - entry = g_new (PathMapEntry,1 ); - entry->callback = callback; - entry->data = data; - - g_hash_table_insert (obj_path_map, g_strdup (obj_path), entry); - - G_UNLOCK (obj_path_map); -} - -void -_g_dbus_unregister_vfs_filter (const char *obj_path) -{ - G_LOCK (obj_path_map); - - if (obj_path_map) - g_hash_table_remove (obj_path_map, obj_path); - - G_UNLOCK (obj_path_map); -} - -static DBusHandlerResult -vfs_connection_filter (DBusConnection *connection, - DBusMessage *message, - void *user_data) -{ - PathMapEntry *entry; - DBusHandlerResult res; - DBusHandleMessageFunction callback; - GObject *data; - VfsConnectionData *connection_data; - const char *path; - - callback = NULL; - data = NULL; - - if (dbus_message_is_signal (message, - DBUS_INTERFACE_LOCAL, - "Disconnected")) - { - connection_data = dbus_connection_get_data (connection, vfs_data_slot); - if (connection_data->async_dbus_id) - { - _g_daemon_vfs_invalidate_dbus_id (connection_data->async_dbus_id); - G_LOCK (async_map); - g_hash_table_remove (async_map, connection_data->async_dbus_id); - G_UNLOCK (async_map); - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - - path = dbus_message_get_path (message); - G_LOCK (obj_path_map); - if (obj_path_map && path) - { - entry = g_hash_table_lookup (obj_path_map, - path); - - if (entry) - { - callback = entry->callback; - data = g_object_ref (entry->data); - } - } - G_UNLOCK (obj_path_map); - - res = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - if (callback) - { - res = callback (connection, message, data); - g_object_unref (data); - } - - return res; -} - -static void -connection_data_free (gpointer p) -{ - VfsConnectionData *data = p; - - if (data->extra_fd != -1) - close (data->extra_fd); - - if (data->extra_fd_source) - { - g_source_destroy (data->extra_fd_source); - g_source_unref (data->extra_fd_source); - } - - if (data->outstanding_fds) - g_hash_table_destroy (data->outstanding_fds); - - g_free (data->async_dbus_id); - - g_free (data); -} - -static void -vfs_connection_setup (DBusConnection *connection, - int extra_fd, - gboolean async) -{ - VfsConnectionData *connection_data; - - connection_data = g_new0 (VfsConnectionData, 1); - connection_data->extra_fd = extra_fd; - connection_data->extra_fd_count = 0; - - if (async) - setup_async_fd_receive (connection_data); - - if (!dbus_connection_set_data (connection, vfs_data_slot, connection_data, connection_data_free)) - _g_dbus_oom (); - - if (!dbus_connection_add_filter (connection, vfs_connection_filter, NULL, NULL)) - _g_dbus_oom (); -} - -/************************************************************************** - * Functions to get fds from vfs dbus connections * - *************************************************************************/ - -typedef struct { - int fd; - GetFdAsyncCallback callback; - gpointer callback_data; -} OutstandingFD; - -static void -outstanding_fd_free (OutstandingFD *outstanding) -{ - if (outstanding->fd != -1) - close (outstanding->fd); - - g_free (outstanding); -} - -static void -async_connection_accept_new_fd (VfsConnectionData *data, - GIOCondition condition, - int fd) -{ - int new_fd; - int fd_id; - OutstandingFD *outstanding_fd; - - if (condition & G_IO_HUP) - { - close (data->extra_fd); - data->extra_fd = -1; - g_source_destroy (data->extra_fd_source); - g_source_unref (data->extra_fd_source); - data->extra_fd_source = NULL; - return; - } - - fd_id = data->extra_fd_count; - new_fd = _g_socket_receive_fd (data->extra_fd); - if (new_fd != -1) - { - data->extra_fd_count++; - - outstanding_fd = g_hash_table_lookup (data->outstanding_fds, GINT_TO_POINTER (fd_id)); - - if (outstanding_fd) - { - outstanding_fd->callback (new_fd, outstanding_fd->callback_data); - g_hash_table_remove (data->outstanding_fds, GINT_TO_POINTER (fd_id)); - } - else - { - outstanding_fd = g_new0 (OutstandingFD, 1); - outstanding_fd->fd = new_fd; - outstanding_fd->callback = NULL; - outstanding_fd->callback_data = NULL; - g_hash_table_insert (data->outstanding_fds, - GINT_TO_POINTER (fd_id), - outstanding_fd); - } - } -} - -static void -setup_async_fd_receive (VfsConnectionData *connection_data) -{ - connection_data->outstanding_fds = - g_hash_table_new_full (g_direct_hash, - g_direct_equal, - NULL, - (GDestroyNotify)outstanding_fd_free); - - - connection_data->extra_fd_source = - __g_fd_source_new (connection_data->extra_fd, POLLIN|POLLERR, NULL); - g_source_set_callback (connection_data->extra_fd_source, - (GSourceFunc)async_connection_accept_new_fd, - connection_data, NULL); - g_source_attach (connection_data->extra_fd_source, NULL); -} - -int -_g_dbus_connection_get_fd_sync (DBusConnection *connection, - int fd_id) -{ - VfsConnectionData *data; - int fd; - - data = dbus_connection_get_data (connection, vfs_data_slot); - g_assert (data != NULL); - - /* I don't think we can get reorders here, can we? - * Its a sync per-thread connection after all - */ - g_assert (fd_id == data->extra_fd_count); - - fd = _g_socket_receive_fd (data->extra_fd); - if (fd != -1) - data->extra_fd_count++; - - return fd; -} - -void -_g_dbus_connection_get_fd_async (DBusConnection *connection, - int fd_id, - GetFdAsyncCallback callback, - gpointer callback_data) -{ - VfsConnectionData *data; - OutstandingFD *outstanding_fd; - int fd; - - data = dbus_connection_get_data (connection, vfs_data_slot); - g_assert (data != NULL); - - outstanding_fd = g_hash_table_lookup (data->outstanding_fds, GINT_TO_POINTER (fd_id)); - - if (outstanding_fd) - { - fd = outstanding_fd->fd; - outstanding_fd->fd = -1; - g_hash_table_remove (data->outstanding_fds, GINT_TO_POINTER (fd_id)); - callback (fd, callback_data); - } - else - { - outstanding_fd = g_new0 (OutstandingFD, 1); - outstanding_fd->fd = -1; - outstanding_fd->callback = callback; - outstanding_fd->callback_data = callback_data; - g_hash_table_insert (data->outstanding_fds, - GINT_TO_POINTER (fd_id), - outstanding_fd); - } -} - -/******************************************************************* - * Caching of async connections * - *******************************************************************/ - - -static DBusConnection * -get_connection_for_async (const char *dbus_id) -{ - DBusConnection *connection; - - connection = NULL; - G_LOCK (async_map); - if (async_map != NULL) - connection = g_hash_table_lookup (async_map, dbus_id); - if (connection) - dbus_connection_ref (connection); - G_UNLOCK (async_map); - - return connection; -} - -static void -close_and_unref_connection (void *data) -{ - DBusConnection *connection = data; - - dbus_connection_close (connection); - dbus_connection_unref (connection); -} - -static void -set_connection_for_async (DBusConnection *connection, const char *dbus_id) -{ - VfsConnectionData *data; - - G_LOCK (async_map); - data = dbus_connection_get_data (connection, vfs_data_slot); - data->async_dbus_id = g_strdup (dbus_id); - - if (async_map == NULL) - async_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, close_and_unref_connection); - - g_hash_table_insert (async_map, g_strdup (dbus_id), connection); - dbus_connection_ref (connection); - G_UNLOCK (async_map); -} - -/************************************************************************** - * Asynchronous daemon calls * - *************************************************************************/ - -typedef struct { - const char *dbus_id; - - DBusMessage *message; - DBusConnection *connection; - GCancellable *cancellable; - - GVfsAsyncDBusCallback callback; - gpointer callback_data; - - GError *io_error; - gulong cancelled_tag; -} AsyncDBusCall; - -static void -async_call_finish (AsyncDBusCall *async_call, - DBusMessage *reply) -{ - if (async_call->callback) - async_call->callback (reply, async_call->connection, - async_call->io_error, - async_call->callback_data); - - if (async_call->connection) - dbus_connection_unref (async_call->connection); - dbus_message_unref (async_call->message); - if (async_call->cancellable) - g_object_unref (async_call->cancellable); - if (async_call->io_error) - g_error_free (async_call->io_error); - g_free (async_call); -} - -static void -async_dbus_response (DBusMessage *reply, - GError *error, - gpointer data) -{ - AsyncDBusCall *async_call = data; - - if (async_call->cancelled_tag) - g_signal_handler_disconnect (async_call->cancellable, - async_call->cancelled_tag); - - if (reply == NULL) - async_call->io_error = g_error_copy (error); - - async_call_finish (async_call, reply); -} - -typedef struct { - DBusConnection *connection; - dbus_uint32_t serial; -} AsyncCallCancelData; - -static void -async_call_cancel_data_free (gpointer _data) -{ - AsyncCallCancelData *data = _data; - - dbus_connection_unref (data->connection); - g_free (data); -} - -/* Might be called on another thread */ -static void -async_call_cancelled_cb (GCancellable *cancellable, - gpointer _data) -{ - AsyncCallCancelData *data = _data; - DBusMessage *cancel_message; - - /* Send cancellation message, this just queues it, sending - * will happen in mainloop */ - cancel_message = dbus_message_new_method_call (NULL, - G_VFS_DBUS_DAEMON_PATH, - G_VFS_DBUS_DAEMON_INTERFACE, - G_VFS_DBUS_OP_CANCEL); - if (cancel_message != NULL) - { - if (dbus_message_append_args (cancel_message, - DBUS_TYPE_UINT32, &data->serial, - DBUS_TYPE_INVALID)) - dbus_connection_send (data->connection, - cancel_message, NULL); - dbus_message_unref (cancel_message); - } -} - -static void -async_call_send (AsyncDBusCall *async_call) -{ - AsyncCallCancelData *cancel_data; - - if (async_call->cancellable) - { - cancel_data = g_new0 (AsyncCallCancelData, 1); - cancel_data->connection = dbus_connection_ref (async_call->connection); - cancel_data->serial = dbus_message_get_serial (async_call->message); - async_call->cancelled_tag = - g_signal_connect_data (async_call->cancellable, "cancelled", - (GCallback)async_call_cancelled_cb, - cancel_data, - (GClosureNotify)async_call_cancel_data_free, - 0); - } - - _g_dbus_connection_call_async (async_call->connection, - async_call->message, - G_VFS_DBUS_TIMEOUT_MSECS, - async_dbus_response, - async_call); -} - -static void -async_get_connection_response (DBusMessage *reply, - GError *error, - void *data) -{ - AsyncDBusCall *async_call = data; - DBusError derror; - char *address1, *address2; - int extra_fd; - DBusConnection *connection, *existing_connection; - - if (reply == NULL) - { - async_call->io_error = g_error_copy (error); - async_call_finish (async_call, NULL); - return; - } - - dbus_error_init (&derror); - if (!dbus_message_get_args (reply, &derror, - DBUS_TYPE_STRING, &address1, - DBUS_TYPE_STRING, &address2, - DBUS_TYPE_INVALID)) - { - _g_error_from_dbus (&derror, &async_call->io_error); - dbus_error_free (&derror); - async_call_finish (async_call, NULL); - return; - } - - /* I don't know of any way to do an async connect */ - error = NULL; - extra_fd = _g_socket_connect (address2, &error); - if (extra_fd == -1) - { - g_set_error (&async_call->io_error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Error connecting to daemon: %s"), error->message); - g_error_free (error); - async_call_finish (async_call, NULL); - return; - } - - /* Unfortunately dbus doesn't have an async open */ - dbus_error_init (&derror); - connection = dbus_connection_open_private (address1, &derror); - if (!connection) - { - close (extra_fd); - dbus_message_unref (reply); - - g_set_error (&async_call->io_error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Error while getting peer-to-peer dbus connection: %s", - derror.message); - dbus_error_free (&derror); - async_call_finish (async_call, NULL); - return; - } - - vfs_connection_setup (connection, extra_fd, TRUE); - - /* Maybe we already had a connection? This happens if we requested - * the same owner several times in parallel. - * If so, just drop this connection and use that. - */ - - existing_connection = get_connection_for_async (async_call->dbus_id); - if (existing_connection != NULL) - { - async_call->connection = existing_connection; - dbus_connection_close (connection); - dbus_connection_unref (connection); - } - else - { - _g_dbus_connection_integrate_with_main (connection); - set_connection_for_async (connection, async_call->dbus_id); - async_call->connection = connection; - } - - /* Maybe we were canceled while setting up connection, then - * avoid doing the operation */ - if (g_cancellable_set_error_if_cancelled (async_call->cancellable, &async_call->io_error)) - { - async_call_finish (async_call, NULL); - return; - } - - async_call_send (async_call); -} - -static void -open_connection_async (AsyncDBusCall *async_call) -{ - DBusMessage *get_connection_message; - - get_connection_message = dbus_message_new_method_call (async_call->dbus_id, - G_VFS_DBUS_DAEMON_PATH, - G_VFS_DBUS_DAEMON_INTERFACE, - G_VFS_DBUS_OP_GET_CONNECTION); - - if (get_connection_message == NULL) - _g_dbus_oom (); - - - _g_dbus_connection_call_async (_g_daemon_vfs_get_async_bus (), - get_connection_message, - G_VFS_DBUS_TIMEOUT_MSECS, - async_get_connection_response, - async_call); - - dbus_message_unref (get_connection_message); -} - -void -_g_vfs_daemon_call_async (DBusMessage *message, - GVfsAsyncDBusCallback callback, - gpointer callback_data, - GCancellable *cancellable) -{ - AsyncDBusCall *async_call; - - g_once (&once_init_dbus, vfs_dbus_init, NULL); - - async_call = g_new0 (AsyncDBusCall, 1); - async_call->dbus_id = dbus_message_get_destination (message); - async_call->message = dbus_message_ref (message); - if (cancellable) - async_call->cancellable = g_object_ref (cancellable); - async_call->callback = callback; - async_call->callback_data = callback_data; - - async_call->connection = get_connection_for_async (async_call->dbus_id); - if (async_call->connection == NULL) - open_connection_async (async_call); - else - async_call_send (async_call); -} - -/************************************************************************** - * Synchronous daemon calls * - *************************************************************************/ - -DBusMessage * -_g_vfs_daemon_call_sync (DBusMessage *message, - DBusConnection **connection_out, - const char *callback_obj_path, - DBusObjectPathMessageFunction callback, - gpointer callback_user_data, - GCancellable *cancellable, - GError **error) -{ - DBusConnection *connection; - DBusError derror; - DBusMessage *reply; - DBusPendingCall *pending; - int dbus_fd; - int cancel_fd; - gboolean sent_cancel; - DBusMessage *cancel_message; - dbus_uint32_t serial; - gboolean handle_callbacks; - const char *dbus_id = dbus_message_get_destination (message); - - if (g_cancellable_set_error_if_cancelled (cancellable, error)) - return NULL; - - connection = _g_dbus_connection_get_sync (dbus_id, error); - if (connection == NULL) - return NULL; - - if (g_cancellable_set_error_if_cancelled (cancellable, error)) - return NULL; - - handle_callbacks = FALSE; - if (callback_obj_path != NULL && callback != NULL) - { - struct DBusObjectPathVTable vtable = { NULL, callback }; - handle_callbacks = dbus_connection_register_object_path (connection, - callback_obj_path, - &vtable, - callback_user_data); - } - - reply = NULL; - cancel_fd = g_cancellable_get_fd (cancellable); - if (cancel_fd != -1 || handle_callbacks) - { - if (!dbus_connection_send_with_reply (connection, message, - &pending, - G_VFS_DBUS_TIMEOUT_MSECS)) - _g_dbus_oom (); - - if (pending == NULL || - !dbus_connection_get_is_connected (connection)) - { - if (pending) - dbus_pending_call_unref (pending); - invalidate_local_connection (dbus_id, error); - goto out; - } - - /* Make sure the message is sent */ - dbus_connection_flush (connection); - - if (!dbus_connection_get_unix_fd (connection, &dbus_fd)) - { - dbus_pending_call_unref (pending); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Error while getting peer-to-peer dbus connection: %s", - "No fd"); - goto out; - } - - sent_cancel = (cancel_fd == -1); - while (!dbus_pending_call_get_completed (pending)) - { - struct pollfd poll_fds[2]; - int poll_ret; - - do - { - poll_fds[0].events = POLLIN; - poll_fds[0].fd = dbus_fd; - poll_fds[1].events = POLLIN; - poll_fds[1].fd = cancel_fd; - poll_ret = poll (poll_fds, sent_cancel?1:2, -1); - } - while (poll_ret == -1 && errno == EINTR); - - if (poll_ret == -1) - { - dbus_pending_call_unref (pending); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Error while getting peer-to-peer dbus connection: %s", - "poll error"); - goto out; - } - - if (!sent_cancel && g_cancellable_is_cancelled (cancellable)) - { - sent_cancel = TRUE; - serial = dbus_message_get_serial (message); - cancel_message = - dbus_message_new_method_call (NULL, - G_VFS_DBUS_DAEMON_PATH, - G_VFS_DBUS_DAEMON_INTERFACE, - G_VFS_DBUS_OP_CANCEL); - if (cancel_message != NULL) - { - if (dbus_message_append_args (cancel_message, - DBUS_TYPE_UINT32, &serial, - DBUS_TYPE_INVALID)) - { - dbus_connection_send (connection, cancel_message, NULL); - dbus_connection_flush (connection); - } - - dbus_message_unref (cancel_message); - } - } - - if (poll_fds[0].revents != 0) - { - dbus_connection_read_write (connection, - G_VFS_DBUS_TIMEOUT_MSECS); - - while (dbus_connection_dispatch (connection) == DBUS_DISPATCH_DATA_REMAINS) - ; - } - } - - reply = dbus_pending_call_steal_reply (pending); - dbus_pending_call_unref (pending); - } - else - { - dbus_error_init (&derror); - reply = dbus_connection_send_with_reply_and_block (connection, message, - G_VFS_DBUS_TIMEOUT_MSECS, - &derror); - if (!reply) - { - if (dbus_error_has_name (&derror, DBUS_ERROR_NO_REPLY) && - !dbus_connection_get_is_connected (connection)) - { - /* The mount for this connection died, we invalidate - * the caches, and then caller needs to retry. - */ - - invalidate_local_connection (dbus_id, error); - } - else - _g_error_from_dbus (&derror, error); - dbus_error_free (&derror); - goto out; - } - } - - if (connection_out) - *connection_out = connection; - - out: - - if (handle_callbacks) - dbus_connection_unregister_object_path (connection, callback_obj_path); - - if (reply != NULL && _g_error_from_message (reply, error)) - { - dbus_message_unref (reply); - return NULL; - } - - return reply; -} - -/************************************************************************* - * get per-thread synchronous dbus connections * - *************************************************************************/ - -typedef struct { - GHashTable *connections; - DBusConnection *session_bus; -} ThreadLocalConnections; - -static void -free_mount_connection (DBusConnection *conn) -{ - dbus_connection_close (conn); - dbus_connection_unref (conn); -} - -static void -free_local_connections (ThreadLocalConnections *local) -{ - g_hash_table_destroy (local->connections); - if (local->session_bus) - free_mount_connection (local->session_bus); - g_free (local); -} - -static void -invalidate_local_connection (const char *dbus_id, - GError **error) -{ - ThreadLocalConnections *local; - - _g_daemon_vfs_invalidate_dbus_id (dbus_id); - - local = g_static_private_get (&local_connections); - if (local) - g_hash_table_remove (local->connections, dbus_id); - - g_set_error_literal (error, - G_VFS_ERROR, - G_VFS_ERROR_RETRY, - "Cache invalid, retry (internally handled)"); -} - -DBusConnection * -_g_dbus_connection_get_sync (const char *dbus_id, - GError **error) -{ - DBusConnection *bus; - ThreadLocalConnections *local; - GError *local_error; - DBusConnection *connection; - DBusMessage *message, *reply; - DBusError derror; - char *address1, *address2; - int extra_fd; - - g_once (&once_init_dbus, vfs_dbus_init, NULL); - - local = g_static_private_get (&local_connections); - if (local == NULL) - { - local = g_new0 (ThreadLocalConnections, 1); - local->connections = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, (GDestroyNotify)free_mount_connection); - g_static_private_set (&local_connections, local, (GDestroyNotify)free_local_connections); - } - - if (dbus_id == NULL) - { - /* Session bus */ - - if (local->session_bus) - { - if (dbus_connection_get_is_connected (local->session_bus)) - return local->session_bus; - - /* Session bus was disconnected, re-connect */ - local->session_bus = NULL; - dbus_connection_unref (local->session_bus); - } - } - else - { - /* Mount daemon connection */ - - connection = g_hash_table_lookup (local->connections, dbus_id); - if (connection != NULL) - { - if (!dbus_connection_get_is_connected (connection)) - { - /* The mount for this connection died, we invalidate - * the caches, and then caller needs to retry. - */ - - invalidate_local_connection (dbus_id, error); - return NULL; - } - - return connection; - } - } - - dbus_error_init (&derror); - - if (local->session_bus == NULL) - { - bus = dbus_bus_get_private (DBUS_BUS_SESSION, &derror); - if (bus == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Couldn't get main dbus connection: %s", - derror.message); - dbus_error_free (&derror); - return NULL; - } - - local->session_bus = bus; - - if (dbus_id == NULL) - return bus; /* We actually wanted the session bus, so done */ - } - - message = dbus_message_new_method_call (dbus_id, - G_VFS_DBUS_DAEMON_PATH, - G_VFS_DBUS_DAEMON_INTERFACE, - G_VFS_DBUS_OP_GET_CONNECTION); - reply = dbus_connection_send_with_reply_and_block (local->session_bus, message, -1, - &derror); - dbus_message_unref (message); - - if (!reply) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Error while getting peer-to-peer dbus connection: %s", - derror.message); - dbus_error_free (&derror); - return NULL; - } - - if (_g_error_from_message (reply, error)) - return NULL; - - dbus_message_get_args (reply, NULL, - DBUS_TYPE_STRING, &address1, - DBUS_TYPE_STRING, &address2, - DBUS_TYPE_INVALID); - - local_error = NULL; - extra_fd = _g_socket_connect (address2, &local_error); - if (extra_fd == -1) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Error connecting to daemon: %s"), local_error->message); - g_error_free (local_error); - dbus_message_unref (reply); - return NULL; - } - - dbus_error_init (&derror); - connection = dbus_connection_open_private (address1, &derror); - if (!connection) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Error while getting peer-to-peer dbus connection: %s", - derror.message); - close (extra_fd); - dbus_message_unref (reply); - dbus_error_free (&derror); - return NULL; - } - dbus_message_unref (reply); - - vfs_connection_setup (connection, extra_fd, FALSE); - - g_hash_table_insert (local->connections, g_strdup (dbus_id), connection); - - return connection; -} diff --git a/gnome-2-24/client/gvfsdaemondbus.h b/gnome-2-24/client/gvfsdaemondbus.h deleted file mode 100644 index 7a132cdc..00000000 --- a/gnome-2-24/client/gvfsdaemondbus.h +++ /dev/null @@ -1,80 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -#ifndef __G_VFS_DAEMON_DBUS_H__ -#define __G_VFS_DAEMON_DBUS_H__ - -#include <glib.h> -#include <dbus/dbus.h> -#include <gio/gio.h> - -G_BEGIN_DECLS - -/* Used for internal errors */ -GQuark _g_vfs_error_quark (void); -#define G_VFS_ERROR _g_vfs_error_quark() - -typedef enum -{ - G_VFS_ERROR_RETRY -} GVfsError; - - -typedef void (*GVfsAsyncDBusCallback) (DBusMessage *reply, - DBusConnection *connection, - GError *io_error, - gpointer callback_data); -typedef void (*GetFdAsyncCallback) (int fd, - gpointer callback_data); - -void _g_dbus_register_vfs_filter (const char *obj_path, - DBusHandleMessageFunction callback, - GObject *data); -void _g_dbus_unregister_vfs_filter (const char *obj_path); -GList * _g_dbus_bus_list_names_with_prefix_sync (DBusConnection *connection, - const char *prefix, - DBusError *error); -DBusConnection *_g_dbus_connection_get_sync (const char *dbus_id, - GError **error); -int _g_dbus_connection_get_fd_sync (DBusConnection *conn, - int fd_id); -void _g_dbus_connection_get_fd_async (DBusConnection *connection, - int fd_id, - GetFdAsyncCallback callback, - gpointer callback_data); -void _g_vfs_daemon_call_async (DBusMessage *message, - GVfsAsyncDBusCallback callback, - gpointer callback_data, - GCancellable *cancellable); -DBusMessage * _g_vfs_daemon_call_sync (DBusMessage *message, - DBusConnection **connection_out, - const char *callback_obj_path, - DBusObjectPathMessageFunction callback, - gpointer callback_user_data, - GCancellable *cancellable, - GError **error); -GFileInfo * _g_dbus_get_file_info (DBusMessageIter *iter, - GError **error); - -G_END_DECLS - -#endif /* __G_VFS_DAEMON_DBUS_H__ */ diff --git a/gnome-2-24/client/gvfsfusedaemon.c b/gnome-2-24/client/gvfsfusedaemon.c deleted file mode 100644 index ef3314c3..00000000 --- a/gnome-2-24/client/gvfsfusedaemon.c +++ /dev/null @@ -1,2207 +0,0 @@ -/* gvfsfusedaemon.c - FUSE file system mapping daemon for GVFS - * - * Copyright (C) 2007-2008 Hans Petter Jansson - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Hans Petter Jansson <hpj@novell.com> - */ - -#include <config.h> - -#include <stdio.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <sys/vfs.h> -#include <sys/time.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <signal.h> - -#include <dbus/dbus.h> - -#include <glib.h> -#include <glib/gi18n.h> -#include <glib/gprintf.h> -#include <gio/gio.h> - -#include <glib/gurifuncs.h> - -/* stuff from common/ */ -#include <gdaemonmount.h> -#include <gvfsdaemonprotocol.h> -#include <gdbusutils.h> - -#define FUSE_USE_VERSION 26 -#include <fuse.h> - -#define DEBUG_ENABLED 0 - -#define GET_FILE_HANDLE(fi) ((gpointer) (fi)->fh) -#define SET_FILE_HANDLE(fi, fh) ((fi)->fh = (guint64) (fh)) - -typedef struct { - time_t creation_time; - char *name; - GFile *root; -} MountRecord; - -typedef enum { - FILE_OP_NONE, - FILE_OP_READ, - FILE_OP_WRITE -} FileOp; - -typedef struct { - gint refcount; - - GMutex *mutex; - gchar *path; - FileOp op; - gpointer stream; - gint length; - size_t pos; -} FileHandle; - -static GThread *subthread = NULL; -static GMainLoop *subthread_main_loop = NULL; -static GVfs *gvfs = NULL; - -static GVolumeMonitor *volume_monitor = NULL; - -/* Contains pointers to MountRecord */ -static GList *mount_list = NULL; -static GMutex *mount_list_mutex; - -static time_t daemon_creation_time; -static uid_t daemon_uid; -static gid_t daemon_gid; - -static GStaticMutex global_mutex = G_STATIC_MUTEX_INIT; -static GHashTable *global_fh_table = NULL; - -/* ------- * - * Helpers * - * ------- */ - -static void -debug_print (const gchar *message, ...) -{ -#if DEBUG_ENABLED - - static FILE *debug_fhd = NULL; - va_list var_args; - char *file; - - if (!debug_fhd) - { - file = g_build_filename (g_get_home_dir (), "vfs.debug", NULL); - debug_fhd = fopen (file, "at"); - g_free (file); - } - - if (!debug_fhd) - return; - - va_start (var_args, message); - g_vfprintf (debug_fhd, message, var_args); - va_end (var_args); - - fflush (debug_fhd); - -#endif -} - -typedef struct { - gint gioerror; - gint errno_value; -} ErrorMap; - -static gint -errno_from_error (GError *error) -{ - gint i; - static const ErrorMap error_map [] = - { - { G_IO_ERROR_FAILED, EIO }, - { G_IO_ERROR_NOT_FOUND, ENOENT }, - { G_IO_ERROR_EXISTS, EEXIST }, - { G_IO_ERROR_IS_DIRECTORY, EISDIR }, - { G_IO_ERROR_NOT_DIRECTORY, ENOTDIR }, - { G_IO_ERROR_NOT_EMPTY, ENOTEMPTY }, - { G_IO_ERROR_NOT_REGULAR_FILE, EIO }, - { G_IO_ERROR_NOT_SYMBOLIC_LINK, EIO }, - { G_IO_ERROR_NOT_MOUNTABLE_FILE, EIO }, - { G_IO_ERROR_FILENAME_TOO_LONG, ENAMETOOLONG }, - { G_IO_ERROR_INVALID_FILENAME, EIO }, - { G_IO_ERROR_TOO_MANY_LINKS, ELOOP }, - { G_IO_ERROR_NO_SPACE, ENOSPC }, - { G_IO_ERROR_INVALID_ARGUMENT, EINVAL }, - { G_IO_ERROR_PERMISSION_DENIED, EACCES }, - { G_IO_ERROR_NOT_SUPPORTED, ENOTSUP }, - { G_IO_ERROR_NOT_MOUNTED, EIO }, - { G_IO_ERROR_ALREADY_MOUNTED, EIO }, - { G_IO_ERROR_CLOSED, EIO }, - { G_IO_ERROR_CANCELLED, EIO }, - { G_IO_ERROR_PENDING, EIO }, - { G_IO_ERROR_READ_ONLY, EACCES }, - { G_IO_ERROR_CANT_CREATE_BACKUP, EIO }, - { G_IO_ERROR_WRONG_ETAG, EIO }, - { G_IO_ERROR_TIMED_OUT, EIO }, - { G_IO_ERROR_BUSY, EBUSY }, - { -1, -1 } - }; - - if (error->domain != G_IO_ERROR) - return EIO; - - for (i = 0; error_map [i].gioerror >= 0; i++) - { - if (error_map [i].gioerror == error->code) - break; - } - - if (error_map [i].gioerror >= 0) - return error_map [i].errno_value; - - return EIO; -} - -static FileHandle * -file_handle_new (const gchar *path) -{ - FileHandle *file_handle; - - file_handle = g_new0 (FileHandle, 1); - file_handle->refcount = 1; - file_handle->mutex = g_mutex_new (); - file_handle->op = FILE_OP_NONE; - file_handle->path = g_strdup (path); - - return file_handle; -} - -static FileHandle * -file_handle_ref (FileHandle *file_handle) -{ - g_atomic_int_inc (&file_handle->refcount); - return file_handle; -} - -static void -file_handle_unref (FileHandle *file_handle) -{ - if (g_atomic_int_dec_and_test (&file_handle->refcount)) - { - g_static_mutex_lock (&global_mutex); - - /* Test again, since e.g. get_file_handle_for_path() might have - * snatched the global mutex and revived the file handle between - * g_atomic_int_dec_and_test() and us obtaining the lock. */ - - if (g_atomic_int_get (&file_handle->refcount) == 0) - g_hash_table_remove (global_fh_table, file_handle->path); - - g_static_mutex_unlock (&global_mutex); - } -} - -static void -file_handle_close_stream (FileHandle *file_handle) -{ - debug_print ("file_handle_close_stream\n"); - if (file_handle->stream) - { - switch (file_handle->op) - { - case FILE_OP_READ: - g_input_stream_close (file_handle->stream, NULL, NULL); - break; - - case FILE_OP_WRITE: - g_output_stream_close (file_handle->stream, NULL, NULL); - break; - - default: - g_assert_not_reached (); - } - - g_object_unref (file_handle->stream); - file_handle->stream = NULL; - file_handle->op = FILE_OP_NONE; - } -} - -/* Called on hash table removal */ -static void -file_handle_free (FileHandle *file_handle) -{ - file_handle_close_stream (file_handle); - g_mutex_free (file_handle->mutex); - g_free (file_handle->path); - g_free (file_handle); -} - -static FileHandle * -get_file_handle_for_path (const gchar *path) -{ - FileHandle *fh; - - g_static_mutex_lock (&global_mutex); - - fh = g_hash_table_lookup (global_fh_table, path); - if (fh) - file_handle_ref (fh); - - g_static_mutex_unlock (&global_mutex); - - return fh; -} - -static FileHandle * -get_or_create_file_handle_for_path (const gchar *path) -{ - FileHandle *fh; - - g_static_mutex_lock (&global_mutex); - - fh = g_hash_table_lookup (global_fh_table, path); - - if (fh) - { - file_handle_ref (fh); - } - else - { - fh = file_handle_new (path); - g_hash_table_insert (global_fh_table, fh->path, fh); - } - - g_static_mutex_unlock (&global_mutex); - - return fh; -} - -static void -reindex_file_handle_for_path (const gchar *old_path, const gchar *new_path) -{ - gchar *old_path_internal; - FileHandle *fh; - - g_static_mutex_lock (&global_mutex); - - if (!g_hash_table_lookup_extended (global_fh_table, old_path, - (gpointer *) &old_path_internal, - (gpointer *) &fh)) - goto out; - - g_hash_table_steal (global_fh_table, old_path); - - g_free (fh->path); - fh->path = g_strdup (new_path); - - g_hash_table_insert (global_fh_table, fh->path, fh); - - out: - g_static_mutex_unlock (&global_mutex); -} - -static MountRecord * -mount_record_new (GMount *mount) -{ - MountRecord *mount_record; - char *name; - - mount_record = g_new (MountRecord, 1); - - mount_record->root = g_mount_get_root (mount); - name = g_object_get_data (G_OBJECT (mount), "g-stable-name"); - if (name != NULL && *name != 0) - name = g_strdup (name); - else - name = g_mount_get_name (mount); - - /* Keep in sync with gvfs daemon mount tracker */ - mount_record->name = g_uri_escape_string (name, "+@#$., ", TRUE); - g_free (name); - mount_record->creation_time = time (NULL); - - return mount_record; -} - -static void -mount_record_free (MountRecord *mount_record) -{ - g_object_unref (mount_record->root); - g_free (mount_record->name); - g_free (mount_record); -} - -static void -mount_list_lock (void) -{ - g_mutex_lock (mount_list_mutex); -} - -static void -mount_list_unlock (void) -{ - g_mutex_unlock (mount_list_mutex); -} - -static void -mount_list_free (void) -{ - g_list_foreach (mount_list, (GFunc) mount_record_free, NULL); - g_list_free (mount_list); - mount_list = NULL; -} - -static gboolean -mount_record_for_mount_exists (GMount *mount) -{ - GList *l; - GFile *root; - gboolean res; - - g_assert (mount != NULL); - - root = g_mount_get_root (mount); - - res = FALSE; - - mount_list_lock (); - - for (l = mount_list; l != NULL; l = l->next) - { - MountRecord *this_mount_record = l->data; - - if (g_file_equal (root, this_mount_record->root)) - { - res = TRUE; - break; - } - } - - mount_list_unlock (); - - g_object_unref (root); - - return res; -} - -static GFile * -mount_record_find_root_by_mount_name (const gchar *mount_name) -{ - GList *l; - GFile *root; - - g_assert (mount_name != NULL); - - root = NULL; - - mount_list_lock (); - - for (l = mount_list; l != NULL; l = l->next) - { - MountRecord *mount_record = l->data; - - if (strcmp (mount_name, mount_record->name) == 0) - { - root = g_object_ref (mount_record->root); - break; - } - } - - mount_list_unlock (); - - return root; -} - -static void -mount_list_update (void) -{ - GList *mounts; - GList *l; - - mounts = g_volume_monitor_get_mounts (volume_monitor); - - for (l = mounts; l != NULL; l = l->next) - { - GMount *mount = l->data; - - if (!mount_record_for_mount_exists (mount)) - { - mount_list_lock (); - mount_list = g_list_prepend (mount_list, mount_record_new (mount)); - mount_list_unlock (); - } - - g_object_unref (mount); - } - - g_list_free (mounts); -} - -#if 0 - -static gint -file_info_get_attribute_as_int (GFileInfo *file_info, const gchar *attribute) -{ - GFileAttributeType attribute_type; - gint int_result; - - attribute_type = g_file_info_get_attribute_type (file_info, attribute); - - switch (attribute_type) - { - case G_FILE_ATTRIBUTE_TYPE_UINT32: - int_result = g_file_info_get_attribute_uint32 (file_info, attribute); - break; - - case G_FILE_ATTRIBUTE_TYPE_INT32: - int_result = g_file_info_get_attribute_int32 (file_info, attribute); - break; - - case G_FILE_ATTRIBUTE_TYPE_UINT64: - int_result = g_file_info_get_attribute_uint64 (file_info, attribute); - break; - - case G_FILE_ATTRIBUTE_TYPE_INT64: - int_result = g_file_info_get_attribute_int64 (file_info, attribute); - break; - - default: - int_result = 0; - g_assert_not_reached (); - break; - } - - return int_result; -} - -#endif - -static guint -file_info_get_attribute_as_uint (GFileInfo *file_info, const gchar *attribute) -{ - GFileAttributeType attribute_type; - guint uint_result; - - attribute_type = g_file_info_get_attribute_type (file_info, attribute); - - switch (attribute_type) - { - case G_FILE_ATTRIBUTE_TYPE_UINT32: - uint_result = g_file_info_get_attribute_uint32 (file_info, attribute); - break; - - case G_FILE_ATTRIBUTE_TYPE_INT32: - uint_result = g_file_info_get_attribute_int32 (file_info, attribute); - break; - - case G_FILE_ATTRIBUTE_TYPE_UINT64: - uint_result = g_file_info_get_attribute_uint64 (file_info, attribute); - break; - - case G_FILE_ATTRIBUTE_TYPE_INT64: - uint_result = g_file_info_get_attribute_int64 (file_info, attribute); - break; - - default: - uint_result = 0; - g_assert_not_reached (); - break; - } - - return uint_result; -} - -static gboolean -path_is_mount_list (const gchar *path) -{ - while (*path == '/') - path++; - - return *path == 0; -} - - -static GFile * -file_from_full_path (const gchar *path) -{ - gchar *mount_name; - GFile *file = NULL; - const gchar *s1, *s2; - GFile *root; - - file = NULL; - - s1 = path; - while (*s1 == '/') - s1++; - - if (*s1) - { - s2 = strchr (s1, '/'); - if (s2 == NULL) - s2 = s1 + strlen (s1); - - mount_name = g_strndup (s1, s2 - s1); - root = mount_record_find_root_by_mount_name (mount_name); - g_free (mount_name); - - if (root) - { - while (*s2 == '/') - s2++; - file = g_file_resolve_relative_path (root, s2); - g_object_unref (root); - } - } - - return file; -} - -/* ------------- * - * VFS functions * - * ------------- */ - -#if 0 - -/* A stat -f <path> on a FUSE mount always results in this function being called with a path - * of '/'. This means we can't return valid info for the various mounts. Hopefully we can - * fix this in the future. */ - -static gint -vfs_statfs (const gchar *path, struct statvfs *stbuf) -{ - GFile *file; - GError *error = NULL; - gint result = 0; - - debug_print ("vfs_statfs: %s\n", path); - - if ((file = file_from_full_path (path))) - { - GFileInfo *file_info; - - file_info = g_file_get_filesystem_info (file, "*", NULL, &error); - - if (file_info) - { - memset (stbuf, 0, sizeof (*stbuf)); - - stbuf->f_bsize = 4096; - stbuf->f_frsize = 4096; /* Ignored by FUSE */ - stbuf->f_blocks = 0; - stbuf->f_bfree = 0; - stbuf->f_bavail = 0; - stbuf->f_files = 0; - stbuf->f_ffree = 0; - stbuf->f_favail = 0; /* Ignored by FUSE */ - stbuf->f_fsid = 1; /* Ignored by FUSE */ - stbuf->f_flag = 0; /* Ignored by FUSE */ - stbuf->f_namemax = 1024; - - if (g_file_info_has_attribute (file_info, G_FILE_ATTRIBUTE_FILESYSTEM_SIZE)) - stbuf->f_blocks = g_file_info_get_attribute_uint64 (file_info, G_FILE_ATTRIBUTE_FILESYSTEM_SIZE) / 4096; - if (g_file_info_has_attribute (file_info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE)) - stbuf->f_bfree = stbuf->f_bavail = g_file_info_get_attribute_uint64 (file_info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE) / 4096; - } - else if (error) - { - result = -errno_from_error (error); - g_error_free (error); - } - else - { - result = -EIO; - } - - g_object_unref (file); - } - - debug_print ("vfs_statfs: -> %s\n", strerror (-result)); - - return result; -} - -#endif - -static gint -vfs_statfs (const gchar *path, struct statvfs *stbuf) -{ - gint result = 0; - - debug_print ("vfs_statfs: %s\n", path); - - memset (stbuf, 0, sizeof (*stbuf)); - - stbuf->f_bsize = 4096; - stbuf->f_frsize = 4096; /* Ignored by FUSE */ - stbuf->f_blocks = 0; - stbuf->f_bfree = 0; - stbuf->f_bavail = 0; - stbuf->f_files = 0; - stbuf->f_ffree = 0; - stbuf->f_favail = 0; /* Ignored by FUSE */ - stbuf->f_fsid = 1; /* Ignored by FUSE */ - stbuf->f_flag = 0; /* Ignored by FUSE */ - stbuf->f_namemax = 1024; - - debug_print ("vfs_statfs: -> %s\n", strerror (-result)); - - return result; -} - -static mode_t -file_info_get_stat_mode (GFileInfo *file_info) -{ - GFileType file_type; - mode_t unix_mode; - - file_type = g_file_info_get_file_type (file_info); - - switch (file_type) - { - case G_FILE_TYPE_REGULAR: - unix_mode = S_IFREG; - break; - - case G_FILE_TYPE_DIRECTORY: - case G_FILE_TYPE_MOUNTABLE: - unix_mode = S_IFDIR; - break; - - case G_FILE_TYPE_SYMBOLIC_LINK: - case G_FILE_TYPE_SHORTCUT: - unix_mode = S_IFLNK; - break; - - case G_FILE_TYPE_SPECIAL: - default: - unix_mode = 0; - break; - } - - if (file_type == G_FILE_TYPE_DIRECTORY || - !g_file_info_has_attribute (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ) || - g_file_info_get_attribute_boolean (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ)) - unix_mode |= S_IRUSR; - if (!g_file_info_has_attribute (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE) || - g_file_info_get_attribute_boolean (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE)) - unix_mode |= S_IWUSR; - if (file_type == G_FILE_TYPE_DIRECTORY || - !g_file_info_has_attribute (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE) || - g_file_info_get_attribute_boolean (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE)) - unix_mode |= S_IXUSR; - - return unix_mode; -} - -static gint -getattr_for_file (GFile *file, struct stat *sbuf) -{ - GFileInfo *file_info; - GError *error = NULL; - gint result = 0; - - file_info = g_file_query_info (file, "*", 0, NULL, &error); - - if (file_info) - { - GTimeVal mod_time; - - sbuf->st_mode = file_info_get_stat_mode (file_info); - sbuf->st_size = g_file_info_get_size (file_info); - sbuf->st_uid = daemon_uid; - sbuf->st_gid = daemon_gid; - - g_file_info_get_modification_time (file_info, &mod_time); - sbuf->st_mtime = mod_time.tv_sec; - sbuf->st_ctime = mod_time.tv_sec; - sbuf->st_atime = mod_time.tv_sec; - - if (g_file_info_has_attribute (file_info, G_FILE_ATTRIBUTE_TIME_CHANGED)) - sbuf->st_ctime = file_info_get_attribute_as_uint (file_info, G_FILE_ATTRIBUTE_TIME_CHANGED); - if (g_file_info_has_attribute (file_info, G_FILE_ATTRIBUTE_TIME_ACCESS)) - sbuf->st_atime = file_info_get_attribute_as_uint (file_info, G_FILE_ATTRIBUTE_TIME_ACCESS); - - /* Setting st_nlink to 1 for directories makes 'find' work */ - sbuf->st_nlink = 1; - - g_object_unref (file_info); - } - else - { - if (error) - { - debug_print ("Error from GVFS: %s\n", error->message); - result = -errno_from_error (error); - g_error_free (error); - } - else - { - debug_print ("No file info, but no error from GVFS.\n"); - result = -EIO; - } - } - - return result; -} - -static gint -vfs_getattr (const gchar *path, struct stat *sbuf) -{ - GFile *file; - gint result = 0; - FileHandle *fh; - - debug_print ("vfs_getattr: %s\n", path); - - fh = get_file_handle_for_path (path); - if (fh) - g_mutex_lock (fh->mutex); - - memset (sbuf, 0, sizeof (*sbuf)); - - sbuf->st_dev = 0; /* dev_t ID of device containing file */ - sbuf->st_ino = 0; /* ino_t inode number */ - sbuf->st_uid = 0; /* uid_t user ID of owner */ - sbuf->st_gid = 0; /* gid_t group ID of owner */ - sbuf->st_rdev = 0; /* dev_t device ID (if special file) */ - sbuf->st_size = 0; /* off_t total size, in bytes */ - sbuf->st_blocks = 0; /* blkcnt_t number of blocks allocated */ - sbuf->st_atime = 0; /* time_t time of last access */ - sbuf->st_mtime = 0; /* time_t time of last modification */ - sbuf->st_ctime = 0; /* time_t time of last status change */ - sbuf->st_blksize = 4096; /* blksize_t blocksize for filesystem I/O */ - - if (path_is_mount_list (path)) - { - /* Mount list */ - - sbuf->st_mode = S_IFDIR | 0500; /* mode_t protection */ - sbuf->st_nlink = 2 + g_list_length (mount_list); /* nlink_t number of hard links */ - sbuf->st_atime = daemon_creation_time; - sbuf->st_mtime = daemon_creation_time; - sbuf->st_ctime = daemon_creation_time; - sbuf->st_uid = daemon_uid; - sbuf->st_gid = daemon_gid; - } - else if ((file = file_from_full_path (path))) - { - /* Submount */ - - result = getattr_for_file (file, sbuf); - g_object_unref (file); - } - else - { - result = -ENOENT; - } - - if (fh) - { - g_mutex_unlock (fh->mutex); - file_handle_unref (fh); - } - - debug_print ("vfs_getattr: -> %s\n", strerror (-result)); - - return result; -} - -static gint -vfs_readlink (const gchar *path, gchar *target, size_t size) -{ - debug_print ("vfs_readlink: %s\n", path); - - return 0; -} - -static gint -setup_input_stream (GFile *file, FileHandle *fh) -{ - GError *error = NULL; - gint result = 0; - - if (fh->stream) - { - debug_print ("setup_input_stream: have stream\n"); - - if (fh->op == FILE_OP_READ) - { - debug_print ("setup_input_stream: doing read\n"); - } - else - { - debug_print ("setup_input_stream: doing write\n"); - - g_output_stream_close (fh->stream, NULL, NULL); - g_object_unref (fh->stream); - fh->stream = NULL; - } - } - - if (!fh->stream) - { - debug_print ("setup_input_stream: no stream\n"); - fh->stream = g_file_read (file, NULL, &error); - fh->pos = 0; - } - - if (fh->stream) - fh->op = FILE_OP_READ; - else - fh->op = FILE_OP_NONE; - - if (error) - { - debug_print ("setup_input_stream: error\n"); - result = -errno_from_error (error); - g_error_free (error); - } - - return result; -} - -static gint -setup_output_stream (GFile *file, FileHandle *fh) -{ - GError *error = NULL; - gint result = 0; - - if (fh->stream) - { - if (fh->op == FILE_OP_WRITE) - { - } - else - { - g_input_stream_close (fh->stream, NULL, NULL); - g_object_unref (fh->stream); - fh->stream = NULL; - } - } - - if (!fh->stream) - { - fh->stream = g_file_append_to (file, 0, NULL, &error); - if (fh->stream) - fh->pos = g_seekable_tell (G_SEEKABLE (fh->stream)); - } - - if (fh->stream) - fh->op = FILE_OP_WRITE; - else - fh->op = FILE_OP_NONE; - - if (error) - { - result = -errno_from_error (error); - g_error_free (error); - } - - return result; -} - -static gint -vfs_open (const gchar *path, struct fuse_file_info *fi) -{ - GFile *file; - gint result = 0; - - debug_print ("vfs_open: %s\n", path); - - if (path_is_mount_list (path)) - result = -EISDIR; - else if ((file = file_from_full_path (path))) - { - GFileInfo *file_info; - GError *error = NULL; - - file_info = g_file_query_info (file, "*", 0, NULL, &error); - - if (file_info) - { - GFileType file_type = g_file_info_get_file_type (file_info); - - if (file_type == G_FILE_TYPE_REGULAR) - { - FileHandle *fh = get_or_create_file_handle_for_path (path); - - /* File exists */ - - SET_FILE_HANDLE (fi, fh); - - debug_print ("vfs_open: flags=%o\n", fi->flags); - - /* Set up a stream here, so we can check for errors */ - - g_mutex_lock (fh->mutex); - - if (fi->flags & O_WRONLY || fi->flags & O_RDWR) - result = setup_output_stream (file, fh); - else - result = setup_input_stream (file, fh); - - g_mutex_unlock (fh->mutex); - - /* The added reference to the file handle is released in vfs_release() */ - } - else if (file_type == G_FILE_TYPE_DIRECTORY) - { - /* EISDIR is supposedly only for attempts to write to directory handles, - * but outside readdir(), we don't support reading them either. */ - result = -EISDIR; - } - else - { - result = -EACCES; - } - - g_object_unref (file_info); - } - else - { - if (error) - { - debug_print ("Error from GVFS: %s\n", error->message); - result = -errno_from_error (error); - g_error_free (error); - } - else - { - debug_print ("No file info, but no error from GVFS.\n"); - result = -EIO; - } - } - - g_object_unref (file); - } - else - { - result = -ENOENT; - } - - debug_print ("vfs_open: -> %s\n", strerror (-result)); - - return result; -} - -static gint -vfs_create (const gchar *path, mode_t mode, struct fuse_file_info *fi) -{ - GFile *file; - gint result = 0; - - debug_print ("vfs_create: %s\n", path); - - if (path_is_mount_list (path)) - result = -EEXIST; - if ((file = file_from_full_path (path))) - { - GFileInfo *file_info; - GError *error = NULL; - - file_info = g_file_query_info (file, "*", 0, NULL, &error); - - if (file_info) - { - result = -EEXIST; - g_object_unref (file_info); - } - else - { - GFileOutputStream *file_output_stream; - - if (error) - { - g_error_free (error); - error = NULL; - } - - file_output_stream = g_file_create (file, 0, NULL, &error); - if (file_output_stream) - { - FileHandle *fh = get_or_create_file_handle_for_path (path); - - /* Success */ - - SET_FILE_HANDLE (fi, fh); - - g_mutex_lock (fh->mutex); - - file_handle_close_stream (fh); - fh->stream = file_output_stream; - fh->op = FILE_OP_WRITE; - - g_mutex_unlock (fh->mutex); - - /* The added reference to the file handle is released in vfs_release() */ - } - else - { - result = -errno_from_error (error); - g_error_free (error); - } - } - - g_object_unref (file); - } - else - { - result = -ENOENT; - } - - debug_print ("vfs_create: -> %s\n", strerror (-result)); - - return result; -} - -static gint -vfs_release (const gchar *path, struct fuse_file_info *fi) -{ - FileHandle *fh = GET_FILE_HANDLE (fi); - - debug_print ("vfs_release: %s\n", path); - - if (fh) - file_handle_unref (fh); - - return 0; -} - -static gint -read_stream (FileHandle *fh, gchar *output_buf, size_t output_buf_size, off_t offset) -{ - GInputStream *input_stream; - gint n_bytes_skipped = 0; - gint n_bytes_read = 0; - gint result = 0; - GError *error = NULL; - - input_stream = fh->stream; - - if (offset != fh->pos) - { - if (g_seekable_can_seek (G_SEEKABLE (input_stream))) - { - /* Can seek */ - - debug_print ("read_stream: seeking to offset %d.\n", offset); - - if (g_seekable_seek (G_SEEKABLE (input_stream), offset, G_SEEK_SET, NULL, &error)) - { - fh->pos = offset; - } - else - { - result = -errno_from_error (error); - g_error_free (error); - } - } - else if (offset > fh->pos) - { - /* Can skip ahead */ - - debug_print ("read_stream: skipping to offset %d.\n", offset); - - n_bytes_skipped = g_input_stream_skip (input_stream, offset - fh->pos, NULL, &error); - - if (n_bytes_skipped > 0) - fh->pos += n_bytes_skipped; - - if (n_bytes_skipped != offset - fh->pos) - { - if (error) - { - result = -errno_from_error (error); - g_error_free (error); - } - else - { - result = -EIO; - } - } - } - else - { - /* Can't seek, can't skip backwards */ - - debug_print ("read_stream: can't seek nor skip to offset %d!\n", offset); - - result = -ENOTSUP; - } - } - - if (result == 0) - { - while (n_bytes_read < output_buf_size) - { - gboolean part_result; - gsize part_bytes_read = 0; - - part_result = g_input_stream_read_all (input_stream, - output_buf + n_bytes_read, - output_buf_size - n_bytes_read, - &part_bytes_read, - NULL, - &error); - - n_bytes_read += part_bytes_read; - fh->pos += part_bytes_read; - - if (!part_result || part_bytes_read == 0) - break; - } - - result = n_bytes_read; - - if (n_bytes_read < output_buf_size) - { - debug_print ("read_stream: wanted %d bytes, but got %d.\n", output_buf_size, n_bytes_read); - - if (error) - { - result = -errno_from_error (error); - g_error_free (error); - } - } - } - - return result; -} - -static gint -vfs_read (const gchar *path, gchar *buf, size_t size, - off_t offset, struct fuse_file_info *fi) -{ - GFile *file; - gint result = 0; - - debug_print ("vfs_read: %s\n", path); - - if ((file = file_from_full_path (path))) - { - FileHandle *fh = GET_FILE_HANDLE (fi); - - g_mutex_lock (fh->mutex); - - result = setup_input_stream (file, fh); - - if (result == 0) - { - result = read_stream (fh, buf, size, offset); - } - else - { - debug_print ("vfs_read: failed to setup input_stream!\n"); - } - - g_object_unref (file); - g_mutex_unlock (fh->mutex); - } - else - { - result = -EIO; - } - - if (result < 0) - debug_print ("vfs_read: -> %s\n", strerror (-result)); - else - debug_print ("vfs_read: -> %d bytes read.\n", result); - - return result; -} - -static gint -write_stream (FileHandle *fh, const gchar *input_buf, size_t input_buf_size, off_t offset) -{ - GOutputStream *output_stream; - gint n_bytes_written = 0; - gint result = 0; - GError *error = NULL; - - debug_print ("write_stream: %d bytes at offset %d.\n", input_buf_size, offset); - - output_stream = fh->stream; - - if (offset != fh->pos) - { - if (g_seekable_can_seek (G_SEEKABLE (output_stream))) - { - /* Can seek */ - - if (g_seekable_seek (G_SEEKABLE (output_stream), offset, G_SEEK_SET, NULL, &error)) - { - fh->pos = offset; - } - else - { - result = -errno_from_error (error); - g_error_free (error); - } - } - else - { - /* Can't seek, and output streams can't skip */ - - result = -ENOTSUP; - } - } - - if (result == 0) - { - while (n_bytes_written < input_buf_size) - { - gboolean part_result; - gsize part_bytes_written = 0; - - part_result = g_output_stream_write_all (output_stream, - (void *) (input_buf + n_bytes_written), - input_buf_size - n_bytes_written, - &part_bytes_written, - NULL, - &error); - - n_bytes_written += part_bytes_written; - fh->pos += part_bytes_written; - - if (!part_result) - break; - } - - result = n_bytes_written; - - if (n_bytes_written < input_buf_size) - { - if (error) - { - result = -errno_from_error (error); - g_error_free (error); - } - } - else if (!g_output_stream_flush (output_stream, NULL, &error)) - { - result = -errno_from_error (error); - g_error_free (error); - } - } - - return result; -} - -static gint -vfs_write (const gchar *path, const gchar *buf, size_t len, off_t offset, - struct fuse_file_info *fi) -{ - GFile *file; - gint result = 0; - - debug_print ("vfs_write: %s\n", path); - - if ((file = file_from_full_path (path))) - { - FileHandle *fh = GET_FILE_HANDLE (fi); - - g_mutex_lock (fh->mutex); - - result = setup_output_stream (file, fh); - if (result == 0) - { - result = write_stream (fh, buf, len, offset); - } - - g_object_unref (file); - g_mutex_unlock (fh->mutex); - } - else - { - result = -EIO; - } - - if (result < 0) - debug_print ("vfs_write: -> %s\n", strerror (-result)); - else - debug_print ("vfs_write: -> %d bytes written.\n", result); - - return result; -} - -static gint -vfs_flush (const gchar *path, struct fuse_file_info *fi) -{ - debug_print ("vfs_flush: %s\n", path); - - return 0; -} - -static gint -vfs_opendir (const gchar *path, struct fuse_file_info *fi) -{ - GFile *file; - gint result = 0; - - debug_print ("vfs_opendir: %s\n", path); - - if (path_is_mount_list (path)) - { - /* Mount list */ - } - else if ((file = file_from_full_path (path)) != NULL) - { - /* Submount */ - - /* TODO: Check that path exists */ - - g_object_unref (file); - } - else - { - /* Not found */ - - result = -ENOENT; - } - - return result; -} - -static gint -readdir_for_file (GFile *base_file, gpointer buf, fuse_fill_dir_t filler) -{ - GFileEnumerator *enumerator; - GFileInfo *file_info; - GError *error = NULL; - - g_assert (base_file != NULL); - - enumerator = g_file_enumerate_children (base_file, G_FILE_ATTRIBUTE_STANDARD_NAME, 0, NULL, &error); - if (!enumerator) - { - gint result; - - if (error) - { - debug_print ("Error from GVFS: %s\n", error->message); - result = -errno_from_error (error); - g_error_free (error); - } - else - { - debug_print ("No file info, but no error from GVFS.\n"); - result = -EIO; - } - - return result; - } - - filler (buf, ".", NULL, 0); - filler (buf, "..", NULL, 0); - - while ((file_info = g_file_enumerator_next_file (enumerator, NULL, &error)) != NULL) - { - filler (buf, g_file_info_get_name (file_info), NULL, 0); - g_object_unref (file_info); - } - - g_object_unref (enumerator); - - return 0; -} - -static gint -vfs_readdir (const gchar *path, gpointer buf, fuse_fill_dir_t filler, off_t offset, - struct fuse_file_info *fi) -{ - GFile *base_file; - gint result = 0; - - debug_print ("vfs_readdir: %s\n", path); - - if (path_is_mount_list (path)) - { - GList *l; - - /* Mount list */ - - filler (buf, ".", NULL, 0); - filler (buf, "..", NULL, 0); - - mount_list_lock (); - - for (l = mount_list; l; l = g_list_next (l)) - { - MountRecord *mount_record = l->data; - - filler (buf, mount_record->name, NULL, 0); - } - - mount_list_unlock (); - } - else if ((base_file = file_from_full_path (path))) - { - /* Submount */ - - result = readdir_for_file (base_file, buf, filler); - - g_object_unref (base_file); - } - else - { - /* Not found */ - - result = -ENOENT; - } - - return result; -} - -static gint -vfs_rename (const gchar *old_path, const gchar *new_path) -{ - GFile *old_file; - GFile *new_file; - GError *error = NULL; - gint result = 0; - - debug_print ("vfs_rename: %s -> %s\n", old_path, new_path); - - old_file = file_from_full_path (old_path); - new_file = file_from_full_path (new_path); - - if (old_file && new_file) - { - FileHandle *fh; - - fh = get_file_handle_for_path (old_path); - - if (fh) - { - g_mutex_lock (fh->mutex); - file_handle_close_stream (fh); - } - - g_file_move (old_file, new_file, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &error); - - if (error) - { - debug_print ("vfs_rename failed: %s\n", error->message); - - result = -errno_from_error (error); - g_error_free (error); - } - else - { - reindex_file_handle_for_path (old_path, new_path); - } - - if (fh) - { - g_mutex_unlock (fh->mutex); - file_handle_unref (fh); - } - - if (result == -EISDIR) - { - /* This makes e.g. 'mv' fall back to a recursive copy + delete operation */ - result = -EXDEV; - } - } - else - { - result = -ENOENT; - } - - if (old_file) - g_object_unref (old_file); - if (new_file) - g_object_unref (new_file); - - debug_print ("vfs_rename: -> %s\n", strerror (-result)); - - return result; -} - -static gint -vfs_unlink (const gchar *path) -{ - GFile *file; - GError *error = NULL; - gint result = 0; - - debug_print ("vfs_unlink: %s\n", path); - - file = file_from_full_path (path); - - if (file) - { - FileHandle *fh; - - fh = get_file_handle_for_path (path); - - if (fh) - { - g_mutex_lock (fh->mutex); - file_handle_close_stream (fh); - } - - g_file_delete (file, NULL, &error); - - if (fh) - { - g_mutex_unlock (fh->mutex); - file_handle_unref (fh); - } - - if (error) - { - debug_print ("vfs_unlink failed: %s (%s)\n", path, error->message); - - result = -errno_from_error (error); - g_error_free (error); - } - - g_object_unref (file); - } - else - { - result = -ENOENT; - } - - debug_print ("vfs_unlink: -> %s\n", strerror (-result)); - - return result; -} - -static gint -vfs_mkdir (const gchar *path, mode_t mode) -{ - GFile *file; - GError *error = NULL; - gint result = 0; - - debug_print ("vfs_mkdir: %s\n", path); - - file = file_from_full_path (path); - - if (file) - { - if (g_file_make_directory (file, NULL, &error)) - { - /* Ignore errors setting the mode. We already created the directory, and that's - * good enough. */ - g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_MODE, mode, 0, NULL, NULL); - } - - if (error) - { - result = -errno_from_error (error); - g_error_free (error); - } - - g_object_unref (file); - } - else - { - result = -ENOENT; - } - - debug_print ("vfs_mkdir: -> %s\n", strerror (-result)); - - return result; -} - -static gint -vfs_rmdir (const gchar *path) -{ - GFile *file; - GError *error = NULL; - gint result = 0; - - debug_print ("vfs_rmdir: %s\n", path); - - file = file_from_full_path (path); - - if (file) - { - GFileInfo *file_info; - - file_info = g_file_query_info (file, "*", 0, NULL, &error); - if (file_info) - { - if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY) - { - g_file_delete (file, NULL, &error); - - if (error) - { - result = -errno_from_error (error); - g_error_free (error); - } - } - else - { - result = -ENOTDIR; - } - } - else - { - if (error) - { - result = -errno_from_error (error); - g_error_free (error); - } - else - { - result = -ENOENT; - } - } - } - else - { - result = -ENOENT; - } - - debug_print ("vfs_rmdir: -> %s\n", strerror (-result)); - - return result; -} - -static gint -vfs_ftruncate (const gchar *path, off_t size, struct fuse_file_info *fi) -{ - GFile *file; - GError *error = NULL; - gint result = 0; - - debug_print ("vfs_ftruncate: %s\n", path); - - file = file_from_full_path (path); - - if (file) - { - FileHandle *fh = GET_FILE_HANDLE (fi); - - g_mutex_lock (fh->mutex); - - result = setup_output_stream (file, fh); - - if (result == 0) - { - if (g_seekable_can_truncate (G_SEEKABLE (fh->stream))) - { - g_seekable_truncate (fh->stream, size, NULL, &error); - } - else if (size == 0) - { - g_output_stream_close (fh->stream, NULL, NULL); - g_object_unref (fh->stream); - fh->stream = NULL; - - fh->stream = g_file_replace (file, 0, FALSE, 0, NULL, &error); - } - else - { - result = -ENOTSUP; - } - - if (error) - { - result = -errno_from_error (error); - g_error_free (error); - } - } - - g_object_unref (file); - g_mutex_unlock (fh->mutex); - } - else - { - result = -ENOENT; - } - - debug_print ("vfs_ftruncate: -> %s\n", strerror (-result)); - - return result; -} - -static gint -vfs_truncate (const gchar *path, off_t size) -{ - GFile *file; - GError *error = NULL; - gint result = 0; - - debug_print ("vfs_truncate: %s\n", path); - - file = file_from_full_path (path); - - if (file) - { - GFileOutputStream *file_output_stream = NULL; - FileHandle *fh; - - fh = get_file_handle_for_path (path); - if (fh) - g_mutex_lock (fh->mutex); - - if (size == 0) - { - file_output_stream = g_file_replace (file, 0, FALSE, 0, NULL, &error); - } - else - { - file_output_stream = g_file_append_to (file, 0, NULL, &error); - if (file_output_stream) - g_seekable_truncate (G_SEEKABLE (file_output_stream), size, NULL, &error); - } - - if (error) - { - result = -errno_from_error (error); - g_error_free (error); - } - - if (file_output_stream) - { - g_output_stream_close (G_OUTPUT_STREAM (file_output_stream), NULL, NULL); - g_object_unref (file_output_stream); - } - - if (fh) - { - g_mutex_unlock (fh->mutex); - file_handle_unref (fh); - } - - g_object_unref (file); - } - else - { - result = -ENOENT; - } - - debug_print ("vfs_truncate: -> %s\n", strerror (-result)); - - return result; -} - -static gint -vfs_symlink (const gchar *path_old, const gchar *path_new) -{ - GFile *file; - GError *error = NULL; - gint result = 0; - - debug_print ("vfs_symlink: %s -> %s\n", path_new, path_old); - - file = file_from_full_path (path_new); - - if (file) - { - g_file_make_symbolic_link (file, path_old, NULL, &error); - - if (error) - { - result = -errno_from_error (error); - g_error_free (error); - } - } - else - { - result = -ENOENT; - } - - debug_print ("vfs_symlink: -> %s\n", strerror (-result)); - - return result; -} - -static gint -vfs_access (const gchar *path, gint mode) -{ - GFile *file; - GError *error = NULL; - gint result = 0; - - debug_print ("vfs_access: %s\n", path); - - file = file_from_full_path (path); - - if (file) - { - GFileInfo *file_info; - - file_info = g_file_query_info (file, "*", 0, NULL, &error); - if (file_info) - { - if ((mode & R_OK && (g_file_info_has_attribute (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ) && - !g_file_info_get_attribute_boolean (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ))) || - (mode & W_OK && (g_file_info_has_attribute (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE) && - !g_file_info_get_attribute_boolean (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE))) || - (mode & X_OK && (g_file_info_has_attribute (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE) && - !g_file_info_get_attribute_boolean (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE)))) - result = -EACCES; - - g_object_unref (file_info); - } - else if (error) - { - result = -errno_from_error (error); - g_error_free (error); - } - else - { - result = -EIO; - } - - g_object_unref (file); - } - else if (path_is_mount_list (path)) - { - result = 0; - } - else - { - result = -ENOENT; - } - - debug_print ("vfs_access: -> %s\n", strerror (-result)); - return result; -} - -static gint -vfs_utimens (const gchar *path, const struct timespec tv [2]) -{ - GFile *file; - GError *error = NULL; - gint result = 0; - - debug_print ("vfs_utimens: %s\n", path); - - file = file_from_full_path (path); - - if (file) - { - guint64 atime; - guint64 mtime; - - if (tv) - { - atime = (guint64) tv [0].tv_sec * 1000000 + (guint64) tv [0].tv_nsec / (guint64) 1000; - mtime = (guint64) tv [1].tv_sec * 1000000 + (guint64) tv [1].tv_nsec / (guint64) 1000; - } - else - { - struct timeval tiv; - - gettimeofday (&tiv, NULL); - atime = (guint64) tiv.tv_sec * (guint64) 1000000 + (guint64) tiv.tv_usec; - mtime = atime; - } - - g_file_set_attribute (file, G_FILE_ATTRIBUTE_TIME_ACCESS_USEC, - G_FILE_ATTRIBUTE_TYPE_UINT64, &atime, - 0, NULL, &error); - - if (!error) - { - g_file_set_attribute (file, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC, - G_FILE_ATTRIBUTE_TYPE_UINT64, &mtime, - 0, NULL, &error); - } - - if (error) - { - result = -errno_from_error (error); - g_error_free (error); - } - - g_object_unref (file); - } - else if (path_is_mount_list (path)) - { - /* */ - } - else - { - result = -ENOENT; - } - - debug_print ("vfs_utimens: -> %s\n", strerror (-result)); - return result; -} - -static gint -vfs_chmod (const gchar *path, mode_t mode) -{ - GFile *file; - GError *error = NULL; - gint result = 0; - - file = file_from_full_path (path); - - if (file) - { - g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_MODE, mode, 0, NULL, &error); - - if (error) - { - result = -errno_from_error (error); - g_error_free (error); - } - - g_object_unref (file); - } - - return result; -} - -static void -mount_tracker_mounted_cb (GVolumeMonitor *volume_monitor, - GMount *mount) -{ - MountRecord *mount_record; - - if (mount_record_for_mount_exists (mount)) - return; - - mount_record = mount_record_new (mount); - - mount_list_lock (); - mount_list = g_list_prepend (mount_list, mount_record); - mount_list_unlock (); -} - -static void -mount_tracker_unmounted_cb (GVolumeMonitor *volume_monitor, - GMount *mount) -{ - GFile *root; - GList *l; - - root = g_mount_get_root (mount); - - mount_list_lock (); - - root = g_mount_get_root (mount); - - for (l = mount_list; l != NULL; l = l->next) - { - MountRecord *mount_record = l->data; - - if (g_file_equal (root, mount_record->root)) - { - mount_list = g_list_delete_link (mount_list, l); - mount_record_free (mount_record); - break; - } - } - - mount_list_unlock (); - - g_object_unref (root); -} - -static gpointer -subthread_main (gpointer data) -{ - - mount_list_update (); - - g_signal_connect (volume_monitor, "mount_added", (GCallback) mount_tracker_mounted_cb, NULL); - g_signal_connect (volume_monitor, "mount_removed", (GCallback) mount_tracker_unmounted_cb, NULL); - - g_main_loop_run (subthread_main_loop); - - g_signal_handlers_disconnect_by_func (volume_monitor, mount_tracker_mounted_cb, NULL); - g_signal_handlers_disconnect_by_func (volume_monitor, mount_tracker_unmounted_cb, NULL); - - g_main_loop_unref (subthread_main_loop); - subthread_main_loop = NULL; - - g_object_unref (volume_monitor); - volume_monitor = NULL; - - /* Tell the main thread to unmount. Using kill() is necessary according to FUSE maintainers. */ - kill (getpid (), SIGHUP); - - return NULL; -} - -static DBusHandlerResult -dbus_filter_func (DBusConnection *connection, - DBusMessage *message, - void *data) -{ - if (dbus_message_is_signal (message, - DBUS_INTERFACE_DBUS, - "NameOwnerChanged")) - { - const char *service, *old_owner, *new_owner; - - dbus_message_get_args (message, - NULL, - DBUS_TYPE_STRING, &service, - DBUS_TYPE_STRING, &old_owner, - DBUS_TYPE_STRING, &new_owner, - DBUS_TYPE_INVALID); - - /* Handle monitor owner going away */ - if (service != NULL && - strcmp (G_VFS_DBUS_DAEMON_NAME, service) == 0 && - *new_owner == 0) - { - /* The daemon died, unmount */ - g_main_loop_quit (subthread_main_loop); - } - } - else if (dbus_message_is_signal (message, - DBUS_INTERFACE_LOCAL, - "Disconnected")) - { - /* Session bus died, unmount */ - g_main_loop_quit (subthread_main_loop); - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static gpointer -vfs_init (struct fuse_conn_info *conn) -{ - DBusConnection *dbus_conn; - DBusMessage *message; - DBusError error; - - daemon_creation_time = time (NULL); - daemon_uid = getuid (); - daemon_gid = getgid (); - - mount_list_mutex = g_mutex_new (); - global_fh_table = g_hash_table_new_full (g_str_hash, g_str_equal, - NULL, (GDestroyNotify) file_handle_free); - - dbus_error_init (&error); - - dbus_conn = dbus_bus_get (DBUS_BUS_SESSION, &error); - if (dbus_conn == NULL) - { - g_printerr ("Failed to connect to the D-BUS daemon: %s\n", - error.message); - dbus_error_free (&error); - return NULL; - } - - dbus_connection_set_exit_on_disconnect (dbus_conn, FALSE); - - _g_dbus_connection_integrate_with_main (dbus_conn); - - dbus_bus_add_match (dbus_conn, - "type='signal',sender='" DBUS_SERVICE_DBUS "'," - "interface='" DBUS_INTERFACE_DBUS "'," - "member='NameOwnerChanged'," - "arg0='"G_VFS_DBUS_DAEMON_NAME"'", - NULL); - dbus_connection_add_filter (dbus_conn, - dbus_filter_func, - NULL, - NULL); - - message = dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME, - G_VFS_DBUS_MOUNTTRACKER_PATH, - G_VFS_DBUS_MOUNTTRACKER_INTERFACE, - G_VFS_DBUS_MOUNTTRACKER_OP_REGISTER_FUSE); - dbus_message_set_auto_start (message, TRUE); - dbus_connection_send (dbus_conn, message, NULL); - dbus_connection_flush (dbus_conn); - - gvfs = g_vfs_get_default (); - - volume_monitor = g_object_new (g_type_from_name ("GDaemonVolumeMonitor"), NULL); - - subthread_main_loop = g_main_loop_new (NULL, FALSE); - subthread = g_thread_create ((GThreadFunc) subthread_main, NULL, FALSE, NULL); - - return NULL; -} - -static void -vfs_destroy (gpointer param) -{ - mount_list_free (); - if (subthread_main_loop != NULL) - g_main_loop_quit (subthread_main_loop); - g_mutex_free (mount_list_mutex); - g_object_unref (gvfs); -} - -static struct fuse_operations vfs_oper = -{ - .init = vfs_init, - .destroy = vfs_destroy, - - .getattr = vfs_getattr, - .readdir = vfs_readdir, - - .statfs = vfs_statfs, - - .opendir = vfs_opendir, - .readdir = vfs_readdir, - .readlink = vfs_readlink, - - .open = vfs_open, - .create = vfs_create, - .release = vfs_release, - .flush = vfs_flush, - - .read = vfs_read, - .write = vfs_write, - - .rename = vfs_rename, - .unlink = vfs_unlink, - .mkdir = vfs_mkdir, - .rmdir = vfs_rmdir, - .ftruncate = vfs_ftruncate, - .truncate = vfs_truncate, - .symlink = vfs_symlink, - .access = vfs_access, - .utimens = vfs_utimens, - .chmod = vfs_chmod, - -#if 0 - .chown = vfs_chown, - .setxattr = vfs_setxattr, - .getxattr = vfs_getxattr, - .listxattr = vfs_listxattr, - .removexattr = vfs_removexattr, -#endif -}; - -gint -main (gint argc, gchar *argv []) -{ - g_type_init (); - g_thread_init (NULL); - - return fuse_main (argc, argv, &vfs_oper, NULL /* user data */); -} diff --git a/gnome-2-24/client/gvfsurimapper.c b/gnome-2-24/client/gvfsurimapper.c deleted file mode 100644 index 9c98347a..00000000 --- a/gnome-2-24/client/gvfsurimapper.c +++ /dev/null @@ -1,220 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -#include <config.h> -#include <string.h> -#include <gmodule.h> -#include "gvfsurimapper.h" - -G_DEFINE_DYNAMIC_TYPE (GVfsUriMapper, g_vfs_uri_mapper, G_TYPE_OBJECT) - -void -g_vfs_uri_mapper_register (GIOModule *module) -{ - g_vfs_uri_mapper_register_type (G_TYPE_MODULE (module)); -} - -GVfsUriMountInfo * -g_vfs_uri_mount_info_new (const char *type) -{ - GVfsUriMountInfo *info; - - info = g_new0 (GVfsUriMountInfo, 1); - info->keys = g_array_new (TRUE, TRUE, sizeof (GVfsUriMountInfoKey)); - - if (type != NULL) - g_vfs_uri_mount_info_set (info, "type", type); - - return info; -} - -void -g_vfs_uri_mount_info_free (GVfsUriMountInfo *info) -{ - int i; - GVfsUriMountInfoKey *key; - - for (i = 0; i < info->keys->len; i++) { - key = &g_array_index (info->keys, GVfsUriMountInfoKey, i); - - g_free (key->key); - g_free (key->value); - } - g_array_free (info->keys, TRUE); - g_free (info->path); - g_free (info); -} - -static GVfsUriMountInfoKey * -lookup_key (GVfsUriMountInfo *info, - const char *key) -{ - int i; - GVfsUriMountInfoKey *keyp; - - for (i = 0; i < info->keys->len; i++) { - keyp = &g_array_index (info->keys, GVfsUriMountInfoKey, i); - - if (strcmp (keyp->key, key) == 0) - return keyp; - } - - return NULL; -} - -const char * -g_vfs_uri_mount_info_get (GVfsUriMountInfo *info, - const char *key) -{ - GVfsUriMountInfoKey *keyp; - - keyp = lookup_key (info, key); - - if (keyp) - return keyp->value; - - return NULL; -} - -void -g_vfs_uri_mount_info_set_with_len (GVfsUriMountInfo *info, - const char *key, - const char *value, - int value_len) -{ - GVfsUriMountInfoKey *keyp; - GVfsUriMountInfoKey keyv; - char *value_copy; - - if (value_len == -1) - value_copy = g_strdup (value); - else - value_copy = g_strndup (value, value_len); - - keyp = lookup_key (info, key); - if (keyp) - { - g_free (keyp->value); - keyp->value = value_copy; - } - else - { - keyv.key = g_strdup (key); - keyv.value = value_copy; - g_array_append_val (info->keys, keyv); - } -} - -void -g_vfs_uri_mount_info_set (GVfsUriMountInfo *info, - const char *key, - const char *value) -{ - g_vfs_uri_mount_info_set_with_len (info, key, value, -1); -} - - -static void -g_vfs_uri_mapper_class_finalize (GVfsUriMapperClass *klass) -{ -} - -static void -g_vfs_uri_mapper_class_init (GVfsUriMapperClass *klass) -{ -} - -static void -g_vfs_uri_mapper_init (GVfsUriMapper *vfs) -{ -} - -const char * const * -g_vfs_uri_mapper_get_handled_schemes (GVfsUriMapper *mapper) -{ - GVfsUriMapperClass *class; - - class = G_VFS_URI_MAPPER_GET_CLASS (mapper); - - return (* class->get_handled_schemes) (mapper); -} - - -GVfsUriMountInfo * -g_vfs_uri_mapper_from_uri (GVfsUriMapper *mapper, - const char *uri) -{ - GVfsUriMapperClass *class; - - class = G_VFS_URI_MAPPER_GET_CLASS (mapper); - - return (* class->from_uri) (mapper, uri); -} - -GVfsUriMountInfo * -g_vfs_uri_mapper_get_mount_info_for_path (GVfsUriMapper *mapper, - GVfsUriMountInfo *info, - const char *new_path) -{ - GVfsUriMapperClass *class; - - class = G_VFS_URI_MAPPER_GET_CLASS (mapper); - - if (class->get_mount_info_for_path != NULL) - return (* class->get_mount_info_for_path) (mapper, info, new_path); - else - return NULL; -} - -const char * const * -g_vfs_uri_mapper_get_handled_mount_types (GVfsUriMapper *mapper) -{ - GVfsUriMapperClass *class; - - class = G_VFS_URI_MAPPER_GET_CLASS (mapper); - - return (* class->get_handled_mount_types) (mapper); -} - -char * -g_vfs_uri_mapper_to_uri (GVfsUriMapper *mapper, - GVfsUriMountInfo *mount_info, - gboolean allow_utf8) -{ - GVfsUriMapperClass *class; - - class = G_VFS_URI_MAPPER_GET_CLASS (mapper); - - return (* class->to_uri) (mapper, mount_info, allow_utf8); -} - -const char * -g_vfs_uri_mapper_to_uri_scheme (GVfsUriMapper *mapper, - GVfsUriMountInfo *mount_info) -{ - GVfsUriMapperClass *class; - - class = G_VFS_URI_MAPPER_GET_CLASS (mapper); - - return (* class->to_uri_scheme) (mapper, mount_info); -} - diff --git a/gnome-2-24/client/gvfsurimapper.h b/gnome-2-24/client/gvfsurimapper.h deleted file mode 100644 index 6a3b5ea5..00000000 --- a/gnome-2-24/client/gvfsurimapper.h +++ /dev/null @@ -1,109 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -#ifndef __G_VFS_URI_MAPPER_H__ -#define __G_VFS_URI_MAPPER_H__ - -#include <glib-object.h> -#include <gio/gio.h> - -G_BEGIN_DECLS - -#define G_VFS_TYPE_URI_MAPPER (g_vfs_uri_mapper_get_type ()) -#define G_VFS_URI_MAPPER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_URI_MAPPER, GVfsUriMapper)) -#define G_VFS_URI_MAPPER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_URI_MAPPER, GVfsUriMapperClass)) -#define G_VFS_URI_MAPPER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_URI_MAPPER, GVfsUriMapperClass)) -#define G_IS_VFS_URI_MAPPER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_URI_MAPPER)) -#define G_IS_VFS_URI_MAPPER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_URI_MAPPER)) - -typedef struct _GVfsUriMapper GVfsUriMapper; /* Dummy typedef */ -typedef struct _GVfsUriMapperClass GVfsUriMapperClass; - -struct _GVfsUriMapper { - GObject parent; -}; - -/* Keep in sync with GMountSpecItem */ -typedef struct { - char *key; - char *value; -} GVfsUriMountInfoKey; - -typedef struct { - GArray *keys; - char *path; -} GVfsUriMountInfo; - -struct _GVfsUriMapperClass -{ - GObjectClass parent_class; - - /* Virtual Table */ - - const char * const * (*get_handled_schemes) (GVfsUriMapper *mapper); - GVfsUriMountInfo * (*from_uri) (GVfsUriMapper *mapper, - const char *uri); - GVfsUriMountInfo * (*get_mount_info_for_path) (GVfsUriMapper *mapper, - GVfsUriMountInfo *mount_info, - const char *new_path); - - const char * const * (*get_handled_mount_types) (GVfsUriMapper *mapper); - char * (*to_uri) (GVfsUriMapper *mapper, - GVfsUriMountInfo *mount_info, - gboolean allow_utf8); - const char * (*to_uri_scheme) (GVfsUriMapper *mapper, - GVfsUriMountInfo *mount_info); -}; - -GType g_vfs_uri_mapper_get_type (void); -void g_vfs_uri_mapper_register (GIOModule *module); - -GVfsUriMountInfo *g_vfs_uri_mount_info_new (const char *type); -void g_vfs_uri_mount_info_free (GVfsUriMountInfo *info); -const char * g_vfs_uri_mount_info_get (GVfsUriMountInfo *info, - const char *key); -void g_vfs_uri_mount_info_set (GVfsUriMountInfo *info, - const char *key, - const char *value); -void g_vfs_uri_mount_info_set_with_len (GVfsUriMountInfo *info, - const char *key, - const char *value, - int value_len); - -const char * const *g_vfs_uri_mapper_get_handled_schemes (GVfsUriMapper *mapper); -GVfsUriMountInfo * g_vfs_uri_mapper_from_uri (GVfsUriMapper *mapper, - const char *uri); -GVfsUriMountInfo * g_vfs_uri_mapper_get_mount_info_for_path (GVfsUriMapper *mapper, - GVfsUriMountInfo *mount_info, - const char *new_path); - -const char * const *g_vfs_uri_mapper_get_handled_mount_types (GVfsUriMapper *mapper); -char * g_vfs_uri_mapper_to_uri (GVfsUriMapper *mapper, - GVfsUriMountInfo *mount_info, - gboolean allow_utf8); -const char * g_vfs_uri_mapper_to_uri_scheme (GVfsUriMapper *mapper, - GVfsUriMountInfo *mount_infoxo); - - -G_END_DECLS - -#endif /* __G_VFS_URI_MAPPER_H__ */ diff --git a/gnome-2-24/client/gvfsuriutils.c b/gnome-2-24/client/gvfsuriutils.c deleted file mode 100644 index c9bae69b..00000000 --- a/gnome-2-24/client/gvfsuriutils.c +++ /dev/null @@ -1,288 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -#include <config.h> -#include "gvfsuriutils.h" -#include <string.h> -#include <stdlib.h> - -void -g_vfs_decoded_uri_free (GDecodedUri *decoded) -{ - if (decoded == NULL) - return; - - g_free (decoded->scheme); - g_free (decoded->query); - g_free (decoded->fragment); - g_free (decoded->userinfo); - g_free (decoded->host); - g_free (decoded->path); - g_free (decoded); -} - -GDecodedUri * -g_vfs_decoded_uri_new (void) -{ - GDecodedUri *uri; - - uri = g_new0 (GDecodedUri, 1); - uri->port = -1; - - return uri; -} - -GDecodedUri * -g_vfs_decode_uri (const char *uri) -{ - GDecodedUri *decoded; - const char *p, *in, *hier_part_start, *hier_part_end, *query_start, *fragment_start; - char *out; - char c; - - /* From RFC 3986 Decodes: - * URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] - */ - - p = uri; - - /* Decode scheme: - scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) - */ - - if (!g_ascii_isalpha (*p)) - return NULL; - - while (1) - { - c = *p++; - - if (c == ':') - break; - - if (!(g_ascii_isalnum(c) || - c == '+' || - c == '-' || - c == '.')) - return NULL; - } - - decoded = g_vfs_decoded_uri_new (); - - decoded->scheme = g_malloc (p - uri); - out = decoded->scheme; - for (in = uri; in < p - 1; in++) - *out++ = g_ascii_tolower (*in); - *out = 0; - - hier_part_start = p; - - query_start = strchr (p, '?'); - if (query_start) - { - hier_part_end = query_start++; - fragment_start = strchr (query_start, '#'); - if (fragment_start) - { - decoded->query = g_strndup (query_start, fragment_start - query_start); - decoded->fragment = g_strdup (fragment_start+1); - } - else - { - decoded->query = g_strdup (query_start); - decoded->fragment = NULL; - } - } - else - { - /* No query */ - decoded->query = NULL; - fragment_start = strchr (p, '#'); - if (fragment_start) - { - hier_part_end = fragment_start++; - decoded->fragment = g_strdup (fragment_start); - } - else - { - hier_part_end = p + strlen (p); - decoded->fragment = NULL; - } - } - - /* 3: - hier-part = "//" authority path-abempty - / path-absolute - / path-rootless - / path-empty - - */ - - if (hier_part_start[0] == '/' && - hier_part_start[1] == '/') - { - const char *authority_start, *authority_end; - const char *userinfo_start, *userinfo_end; - const char *host_start, *host_end; - const char *port_start; - - authority_start = hier_part_start + 2; - /* authority is always followed by / or nothing */ - authority_end = memchr (authority_start, '/', hier_part_end - authority_start); - if (authority_end == NULL) - authority_end = hier_part_end; - - /* 3.2: - authority = [ userinfo "@" ] host [ ":" port ] - */ - - userinfo_end = memchr (authority_start, '@', authority_end - authority_start); - if (userinfo_end) - { - userinfo_start = authority_start; - decoded->userinfo = g_uri_unescape_segment (userinfo_start, userinfo_end, NULL); - if (decoded->userinfo == NULL) - { - g_vfs_decoded_uri_free (decoded); - return NULL; - } - host_start = userinfo_end + 1; - } - else - host_start = authority_start; - - /* We should handle hostnames in brackets, as those are used by IPv6 URIs - * See http://tools.ietf.org/html/rfc2732 */ - if (*host_start == '[') - { - char *s; - - port_start = NULL; - host_end = memchr (host_start, ']', authority_end - host_start); - if (host_end == NULL) - { - g_vfs_decoded_uri_free (decoded); - return NULL; - } - - /* Look for the start of the port, - * And we sure we don't have it start somewhere - * in the path section */ - s = (char *) host_end; - while (1) - { - if (*s == '/') - { - port_start = NULL; - break; - } - else if (*s == ':') - { - port_start = s; - break; - } - else if (*s == '\0') - { - break; - } - - s++; - } - } - else - { - port_start = memchr (host_start, ':', authority_end - host_start); - } - - if (port_start) - { - host_end = port_start++; - - decoded->port = atoi(port_start); - } - else - { - host_end = authority_end; - decoded->port = -1; - } - - decoded->host = g_strndup (host_start, host_end - host_start); - - hier_part_start = authority_end; - } - - decoded->path = g_uri_unescape_segment (hier_part_start, hier_part_end, "/"); - - if (decoded->path == NULL) - { - g_vfs_decoded_uri_free (decoded); - return NULL; - } - - return decoded; -} - -char * -g_vfs_encode_uri (GDecodedUri *decoded, gboolean allow_utf8) -{ - GString *uri; - - uri = g_string_new (NULL); - - g_string_append (uri, decoded->scheme); - g_string_append (uri, "://"); - - if (decoded->host != NULL) - { - if (decoded->userinfo) - { - /* userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) */ - g_string_append_uri_escaped (uri, decoded->userinfo, - G_URI_RESERVED_CHARS_ALLOWED_IN_USERINFO, allow_utf8); - g_string_append_c (uri, '@'); - } - - g_string_append (uri, decoded->host); - - if (decoded->port != -1) - { - g_string_append_c (uri, ':'); - g_string_append_printf (uri, "%d", decoded->port); - } - } - - g_string_append_uri_escaped (uri, decoded->path, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, allow_utf8); - - if (decoded->query) - { - g_string_append_c (uri, '?'); - g_string_append (uri, decoded->query); - } - - if (decoded->fragment) - { - g_string_append_c (uri, '#'); - g_string_append (uri, decoded->fragment); - } - - return g_string_free (uri, FALSE); -} diff --git a/gnome-2-24/client/gvfsuriutils.h b/gnome-2-24/client/gvfsuriutils.h deleted file mode 100644 index 20de00d3..00000000 --- a/gnome-2-24/client/gvfsuriutils.h +++ /dev/null @@ -1,50 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -#ifndef __G_VFS_URI_UTILS_H__ -#define __G_VFS_URI_UTILS_H__ - -#include <glib.h> -#include <glib/gurifuncs.h> - -G_BEGIN_DECLS - -typedef struct { - char *scheme; - char *userinfo; - char *host; - int port; /* -1 => not in uri */ - char *path; - char *query; - char *fragment; -} GDecodedUri; - -char * g_vfs_encode_uri (GDecodedUri *decoded, - gboolean allow_utf8); -void g_vfs_decoded_uri_free (GDecodedUri *decoded); -GDecodedUri *g_vfs_decode_uri (const char *uri); -GDecodedUri *g_vfs_decoded_uri_new (void); - - -G_END_DECLS - -#endif /* __G_VFS_URI_UTILS_H__ */ diff --git a/gnome-2-24/client/httpuri.c b/gnome-2-24/client/httpuri.c deleted file mode 100644 index 7eef0cbb..00000000 --- a/gnome-2-24/client/httpuri.c +++ /dev/null @@ -1,313 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2008 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Christian Kellner <gicmo@gnome.org> - */ - -#include <config.h> -#include <string.h> - -#include <stdlib.h> /* atoi */ - -#include <gio/gio.h> -#include <gvfsurimapper.h> -#include <gvfsuriutils.h> - -typedef struct _GVfsUriMapperHttp GVfsUriMapperHttp; -typedef struct _GVfsUriMapperHttpClass GVfsUriMapperHttpClass; - -struct _GVfsUriMapperHttp -{ - GVfsUriMapper parent; -}; - -struct _GVfsUriMapperHttpClass -{ - GVfsUriMapperClass parent_class; -}; - -GType g_vfs_uri_mapper_http_get_type (void); -void g_vfs_uri_mapper_http_register (GIOModule *module); - -G_DEFINE_DYNAMIC_TYPE (GVfsUriMapperHttp, g_vfs_uri_mapper_http, G_VFS_TYPE_URI_MAPPER) - -static void -g_vfs_uri_mapper_http_init (GVfsUriMapperHttp *vfs) -{ -} - -static const char * const * -http_get_handled_schemes (GVfsUriMapper *mapper) -{ - static const char *schemes[] = { - "http", - "https", - "dav", - "davs", - NULL - }; - return schemes; -} - -static inline gboolean -port_is_defaul_port (int port, gboolean ssl) -{ - if (ssl) - return port == 443; - else - return port == 80; -} - -static GVfsUriMountInfo * -http_from_uri (GVfsUriMapper *mapper, - const char *uri_str) -{ - GVfsUriMountInfo *info; - char *path; - gboolean ssl; - - path = NULL; - if (!g_ascii_strncasecmp (uri_str, "http", 4)) - { - GDecodedUri *uri; - - uri = g_vfs_decode_uri (uri_str); - - info = g_vfs_uri_mount_info_new ("http"); - g_vfs_uri_mount_info_set (info, "uri", uri_str); - - if (uri) - { - path = uri->path; - uri->path = NULL; - g_vfs_decoded_uri_free (uri); - } - } - else - { - GDecodedUri *uri; - - uri = g_vfs_decode_uri (uri_str); - - if (uri == NULL) - return NULL; - - info = g_vfs_uri_mount_info_new ("dav"); - ssl = !g_ascii_strcasecmp (uri->scheme, "davs"); - g_vfs_uri_mount_info_set (info, "ssl", ssl ? "true" : "false"); - - if (uri->host && *uri->host) - g_vfs_uri_mount_info_set (info, "host", uri->host); - - if (uri->userinfo && *uri->userinfo) - g_vfs_uri_mount_info_set (info, "user", uri->userinfo); - - /* only set the port if it isn't the default port */ - if (uri->port != -1 && ! port_is_defaul_port (uri->port, ssl)) - { - char *port = g_strdup_printf ("%d", uri->port); - g_vfs_uri_mount_info_set (info, "port", port); - g_free (port); - } - - path = uri->path; - uri->path = NULL; - - g_vfs_decoded_uri_free (uri); - } - - - info->path = path; - return info; -} - -static GVfsUriMountInfo * -http_get_mount_info_for_path (GVfsUriMapper *mapper, - GVfsUriMountInfo *info, - const char *new_path) -{ - const char *type; - - type = g_vfs_uri_mount_info_get (info, "type"); - - if (strcmp (type, "http") == 0) - { - const char *uri_str; - char *new_uri; - GDecodedUri *uri; - GVfsUriMountInfo *new_info; - - uri_str = g_vfs_uri_mount_info_get (info, "uri"); - - uri = g_vfs_decode_uri (uri_str); - - if (uri == NULL) - return NULL; - - if (strcmp (uri->path, new_path) == 0) - { - g_vfs_decoded_uri_free (uri); - return NULL; - } - - g_free (uri->path); - uri->path = g_strdup (new_path); - - g_free (uri->query); - uri->query = NULL; - - g_free (uri->fragment); - uri->fragment = NULL; - - new_info = g_vfs_uri_mount_info_new ("http"); - - new_uri = g_vfs_encode_uri (uri, TRUE); - g_vfs_uri_mount_info_set (new_info, "uri", new_uri); - g_free (new_uri); - - uri->path = NULL; - - g_vfs_decoded_uri_free (uri); - - return new_info; - } - else - return NULL; -} - -static const char * const * -http_get_handled_mount_types (GVfsUriMapper *mapper) -{ - static const char *types[] = { - "http", - "dav", - NULL - }; - return types; -} - -static char * -http_to_uri (GVfsUriMapper *mapper, - GVfsUriMountInfo *info, - gboolean allow_utf8) -{ - char *res; - const char *type; - const char *host; - const char *user; - const char *port; - const char *ssl; - - type = g_vfs_uri_mount_info_get (info, "type"); - - if (strcmp (type, "http") == 0) - { - res = g_strdup (g_vfs_uri_mount_info_get (info, "uri")); - } - else - { - GDecodedUri *decoded_uri; - int port_num; - - decoded_uri = g_new0 (GDecodedUri, 1); - - ssl = g_vfs_uri_mount_info_get (info, "ssl"); - host = g_vfs_uri_mount_info_get (info, "host"); - user = g_vfs_uri_mount_info_get (info, "user"); - port = g_vfs_uri_mount_info_get (info, "port"); - - if (ssl && strcmp (ssl, "true") == 0) - decoded_uri->scheme = g_strdup ("davs"); - else - decoded_uri->scheme = g_strdup ("dav"); - - decoded_uri->host = g_strdup (host); - decoded_uri->userinfo = g_strdup (user); - - if (port && (port_num = atoi (port))) - decoded_uri->port = port_num; - else - decoded_uri->port = -1; - - decoded_uri->path = g_strdup (info->path); - - res = g_vfs_encode_uri (decoded_uri, allow_utf8); - g_vfs_decoded_uri_free (decoded_uri); - } - - return res; -} - -static const char * -http_to_uri_scheme (GVfsUriMapper *mapper, - GVfsUriMountInfo *info) -{ - const gchar *ssl; - const gchar *type; - gboolean is_dav; - gboolean is_ssl; - - ssl = g_vfs_uri_mount_info_get (info, "ssl"); - type = g_vfs_uri_mount_info_get (info, "type"); - - if (strcmp (type, "dav") == 0) - is_dav = TRUE; - else if (strcmp (type, "http") == 0) - is_dav = FALSE; - else - return NULL; - - is_ssl = - ssl != NULL && - strcmp (ssl, "true") == 0; - - if (is_dav && is_ssl) - return "davs"; - else if (is_dav && !is_ssl) - return "dav"; - else if (!is_dav && is_ssl) - return "https"; - else - return "http"; -} - -static void -g_vfs_uri_mapper_http_class_finalize (GVfsUriMapperHttpClass *klass) -{ -} - -static void -g_vfs_uri_mapper_http_class_init (GVfsUriMapperHttpClass *class) -{ - GVfsUriMapperClass *mapper_class; - - mapper_class = G_VFS_URI_MAPPER_CLASS (class); - mapper_class->get_handled_schemes = http_get_handled_schemes; - mapper_class->from_uri = http_from_uri; - mapper_class->get_mount_info_for_path = http_get_mount_info_for_path; - mapper_class->get_handled_mount_types = http_get_handled_mount_types; - mapper_class->to_uri = http_to_uri; - mapper_class->to_uri_scheme = http_to_uri_scheme; -} - -void -g_vfs_uri_mapper_http_register (GIOModule *module) -{ - g_vfs_uri_mapper_http_register_type (G_TYPE_MODULE (module)); -} diff --git a/gnome-2-24/client/smburi.c b/gnome-2-24/client/smburi.c deleted file mode 100644 index d3804cf4..00000000 --- a/gnome-2-24/client/smburi.c +++ /dev/null @@ -1,297 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Alexander Larsson <alexl@redhat.com> - */ - -#include <config.h> -#include <string.h> - -#include <gio/gio.h> -#include <gvfsurimapper.h> -#include <gvfsuriutils.h> - -typedef struct _GVfsUriMapperSmb GVfsUriMapperSmb; -typedef struct _GVfsUriMapperSmbClass GVfsUriMapperSmbClass; - -struct _GVfsUriMapperSmb -{ - GVfsUriMapper parent; -}; - -struct _GVfsUriMapperSmbClass -{ - GVfsUriMapperClass parent_class; -}; - -GType g_vfs_uri_mapper_smb_get_type (void); -void g_vfs_uri_mapper_smb_register (GIOModule *module); - -G_DEFINE_DYNAMIC_TYPE (GVfsUriMapperSmb, g_vfs_uri_mapper_smb, G_VFS_TYPE_URI_MAPPER) - -static void -g_vfs_uri_mapper_smb_init (GVfsUriMapperSmb *vfs) -{ -} - -static char * -normalize_smb_name (const char *name, gssize len) -{ - gboolean valid_utf8; - - valid_utf8 = g_utf8_validate (name, len, NULL); - - if (valid_utf8) - return g_utf8_casefold (name, len); - else - return g_ascii_strdown (name, len); -} - -static const char * const * -smb_get_handled_schemes (GVfsUriMapper *mapper) -{ - static const char *schemes[] = { - "smb", - NULL - }; - return schemes; -} - -static GVfsUriMountInfo * -smb_from_uri (GVfsUriMapper *mapper, - const char *uri_str) -{ - char *tmp; - const char *p; - const char *share, *share_end; - GDecodedUri *uri; - GVfsUriMountInfo *info; - - uri = g_vfs_decode_uri (uri_str); - if (uri == NULL) - return NULL; - - if (uri->host == NULL || strlen (uri->host) == 0) - { - /* uri form: smb:/// or smb:///$path */ - info = g_vfs_uri_mount_info_new ("smb-network"); - if (uri->path == NULL || *uri->path == 0) - info->path = g_strdup ("/"); - else - info->path = g_strdup (uri->path); - } - else - { - /* host set */ - p = uri->path; - while (p && *p == '/') - p++; - - if (p == NULL || *p == 0) - { - /* uri form: smb://$host/ */ - info = g_vfs_uri_mount_info_new ("smb-server"); - tmp = normalize_smb_name (uri->host, -1); - g_vfs_uri_mount_info_set (info, "server", tmp); - g_free (tmp); - info->path = g_strdup ("/"); - } - else - { - share = p; - share_end = strchr (share, '/'); - if (share_end == NULL) - share_end = share + strlen (share); - - p = share_end; - - while (*p == '/') - p++; - - if (*p == 0) - { - /* uri form: smb://$host/$share/ - * Here we special case smb-server files by adding "._" to the names in the uri */ - if (share[0] == '.' && share[1] == '_') - { - info = g_vfs_uri_mount_info_new ("smb-server"); - tmp = normalize_smb_name (uri->host, -1); - g_vfs_uri_mount_info_set (info, "server", tmp); - g_free (tmp); - tmp = normalize_smb_name (share + 2, share_end - (share + 2)); - info->path = g_strconcat ("/", tmp, NULL); - g_free (tmp); - } - else - { - info = g_vfs_uri_mount_info_new ("smb-share"); - tmp = normalize_smb_name (uri->host, -1); - g_vfs_uri_mount_info_set (info, "server", tmp); - g_free (tmp); - tmp = normalize_smb_name (share, share_end - share); - g_vfs_uri_mount_info_set (info, "share", tmp); - g_free (tmp); - info->path = g_strdup ("/"); - } - } - else - { - info = g_vfs_uri_mount_info_new ("smb-share"); - - tmp = normalize_smb_name (uri->host, -1); - g_vfs_uri_mount_info_set (info, "server", tmp); - g_free (tmp); - - tmp = normalize_smb_name (share, share_end - share); - g_vfs_uri_mount_info_set (info, "share", tmp); - g_free (tmp); - - info->path = g_strconcat ("/", p, NULL); - } - } - } - - if (uri->userinfo) - { - const char *user = uri->userinfo; - p = strchr (uri->userinfo, ';'); - if (p) - { - if (p != user) - g_vfs_uri_mount_info_set_with_len (info, "domain", user, p - user); - user = p + 1; - } - if (*user != 0) - g_vfs_uri_mount_info_set (info, "user", user); - } - - g_vfs_decoded_uri_free (uri); - - return info; -} - -static const char * const * -smb_get_handled_mount_types (GVfsUriMapper *mapper) -{ - static const char *types[] = { - "smb-network", - "smb-server", - "smb-share", - NULL - }; - return types; -} - -static char * -smb_to_uri (GVfsUriMapper *mapper, - GVfsUriMountInfo *info, - gboolean allow_utf8) -{ - const char *type; - const char *server; - const char *share; - const char *user; - const char *domain; - char *s; - GDecodedUri *uri; - - uri = g_new0 (GDecodedUri, 1); - - type = g_vfs_uri_mount_info_get (info, "type"); - - uri->scheme = g_strdup ("smb"); - uri->port = -1; - - if (strcmp (type, "smb-network") == 0) - { - uri->path = g_strdup (info->path); - } - else if (strcmp (type, "smb-server") == 0) - { - server = g_vfs_uri_mount_info_get (info, "server"); - uri->host = g_strdup (server); - - /* Map the mountables in server to ._share because the actual share mount maps to smb://server/share */ - if (info->path && info->path[0] == '/' && info->path[1] != 0) - uri->path = g_strconcat ("/._", info->path + 1, NULL); - else - uri->path = g_strdup ("/"); - } - else if (strcmp (type, "smb-share") == 0) - { - server = g_vfs_uri_mount_info_get (info, "server"); - uri->host = g_strdup (server); - share = g_vfs_uri_mount_info_get (info, "share"); - if (info->path[0] == '/') - uri->path = g_strconcat ("/", share, info->path, NULL); - else - uri->path = g_strconcat ("/", share, "/", info->path, NULL); - - user = g_vfs_uri_mount_info_get (info, "user"); - domain = g_vfs_uri_mount_info_get (info, "domain"); - if (user) { - if (domain) - uri->userinfo = g_strconcat (domain, ";", user, NULL); - else - uri->userinfo = g_strdup (user); - } - } - - s = g_vfs_encode_uri (uri, allow_utf8); - g_vfs_decoded_uri_free (uri); - return s; -} - -static const char * -smb_to_uri_scheme (GVfsUriMapper *mapper, - GVfsUriMountInfo *info) -{ - const gchar *type = g_vfs_uri_mount_info_get (info, "type"); - - if (strcmp ("smb-network", type) == 0 || - strcmp ("smb-server", type) == 0 || - strcmp ("smb-share", type) == 0) - return "smb"; - else - return NULL; -} - -static void -g_vfs_uri_mapper_smb_class_finalize (GVfsUriMapperSmbClass *klass) -{ -} - -static void -g_vfs_uri_mapper_smb_class_init (GVfsUriMapperSmbClass *class) -{ - GVfsUriMapperClass *mapper_class; - - mapper_class = G_VFS_URI_MAPPER_CLASS (class); - mapper_class->get_handled_schemes = smb_get_handled_schemes; - mapper_class->from_uri = smb_from_uri; - mapper_class->get_handled_mount_types = smb_get_handled_mount_types; - mapper_class->to_uri = smb_to_uri; - mapper_class->to_uri_scheme = smb_to_uri_scheme; -} - -void -g_vfs_uri_mapper_smb_register (GIOModule *module) -{ - g_vfs_uri_mapper_smb_register_type (G_TYPE_MODULE (module)); -} diff --git a/gnome-2-24/client/test-uri-utils.c b/gnome-2-24/client/test-uri-utils.c deleted file mode 100644 index 41cfb057..00000000 --- a/gnome-2-24/client/test-uri-utils.c +++ /dev/null @@ -1,58 +0,0 @@ - -#include <string.h> - -#include "gvfsuriutils.h" - - -typedef struct { - const char *uri; - const char *expected_host; - guint expected_port; -} TestURIs; - -static TestURIs uris[] = { - { "https://[2001:0db8:85a3:08d3:1319:8a2e:0370:7344]:443/", "[2001:0db8:85a3:08d3:1319:8a2e:0370:7344]", 443 }, - { "http://test:443/", "test", 443 }, - { "http://test/", "test", -1 }, - { "obex://[00:FF:FF:FF:FF:FF]/MMC/foo.jpg", "[00:FF:FF:FF:FF:FF]", -1 }, - { "obex://[00:FF:FF:FF:FF:FF]/C:", "[00:FF:FF:FF:FF:FF]", -1 }, - { "http://windows-host:8080/C:/", "windows-host", 8080 }, -}; - -int main (int argc, char **argv) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (uris); i++) { - GDecodedUri *decoded; - char *encoded; - - decoded = g_vfs_decode_uri (uris[i].uri); - if (decoded == NULL) { - g_warning ("Failed to parse \"%s\"", uris[i].uri); - return 1; - } - if (decoded->host == NULL || strcmp (decoded->host, uris[i].expected_host) != 0) { - g_warning ("Wrong host for \"%s\" (got '%s', expected '%s')", uris[i].uri, decoded->host, uris[i].expected_host); - g_vfs_decoded_uri_free (decoded); - return 1; - } - if (decoded->port != uris[i].expected_port) { - g_warning ("Wrong port for \"%s\"", uris[i].uri); - g_vfs_decoded_uri_free (decoded); - return 1; - } - encoded = g_vfs_encode_uri (decoded, TRUE); - if (encoded == NULL || strcmp (encoded, uris[i].uri) != 0) { - g_warning ("Failed to re-encode \"%s\" from '%s'", uris[i].uri, encoded); - g_vfs_decoded_uri_free (decoded); - g_free (encoded); - return 1; - } - g_free (encoded); - g_vfs_decoded_uri_free (decoded); - } - - return 0; -} - |