diff options
Diffstat (limited to 'gnome-2-24/common')
-rw-r--r-- | gnome-2-24/common/Makefile.am | 23 | ||||
-rw-r--r-- | gnome-2-24/common/gdbusutils.c | 1391 | ||||
-rw-r--r-- | gnome-2-24/common/gdbusutils.h | 100 | ||||
-rw-r--r-- | gnome-2-24/common/gmountoperationdbus.c | 324 | ||||
-rw-r--r-- | gnome-2-24/common/gmountoperationdbus.h | 40 | ||||
-rw-r--r-- | gnome-2-24/common/gmountsource.c | 716 | ||||
-rw-r--r-- | gnome-2-24/common/gmountsource.h | 115 | ||||
-rw-r--r-- | gnome-2-24/common/gmountspec.c | 534 | ||||
-rw-r--r-- | gnome-2-24/common/gmountspec.h | 103 | ||||
-rw-r--r-- | gnome-2-24/common/gmounttracker.c | 621 | ||||
-rw-r--r-- | gnome-2-24/common/gmounttracker.h | 86 | ||||
-rw-r--r-- | gnome-2-24/common/gsysutils.c | 181 | ||||
-rw-r--r-- | gnome-2-24/common/gsysutils.h | 39 | ||||
-rw-r--r-- | gnome-2-24/common/gvfsdaemonprotocol.c | 614 | ||||
-rw-r--r-- | gnome-2-24/common/gvfsdaemonprotocol.h | 186 |
15 files changed, 5073 insertions, 0 deletions
diff --git a/gnome-2-24/common/Makefile.am b/gnome-2-24/common/Makefile.am new file mode 100644 index 00000000..2fbb908b --- /dev/null +++ b/gnome-2-24/common/Makefile.am @@ -0,0 +1,23 @@ +NULL = + +lib_LTLIBRARIES=libgvfscommon.la + +INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/gvfs \ + -I$(top_srcdir)/daemon \ + $(GLIB_CFLAGS) $(DBUS_CFLAGS) \ + -DG_LOG_DOMAIN=\"GVFS\" -DG_DISABLE_DEPRECATED \ + -DDBUS_API_SUBJECT_TO_CHANGE + +libgvfscommon_la_SOURCES = \ + gsysutils.c gsysutils.h \ + gdbusutils.c gdbusutils.h \ + gmountspec.c gmountspec.h \ + gmountoperationdbus.c gmountoperationdbus.h \ + gmountsource.c gmountsource.h \ + gmounttracker.c gmounttracker.h \ + gvfsdaemonprotocol.c gvfsdaemonprotocol.h \ + $(NULL) + +libgvfscommon_la_LIBADD = \ + $(DBUS_LIBS) \ + $(GLIB_LIBS) diff --git a/gnome-2-24/common/gdbusutils.c b/gnome-2-24/common/gdbusutils.c new file mode 100644 index 00000000..c4282452 --- /dev/null +++ b/gnome-2-24/common/gdbusutils.c @@ -0,0 +1,1391 @@ +/* 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/gi18n-lib.h> +#include <gdbusutils.h> +#include <gio/gio.h> + +void +_g_dbus_oom (void) +{ + g_error ("DBus failed with out of memory error"); +} + +/* We use _ for escaping, so its not valid */ +#define VALID_INITIAL_NAME_CHARACTER(c) \ + ( ((c) >= 'A' && (c) <= 'Z') || \ + ((c) >= 'a' && (c) <= 'z') ) +#define VALID_NAME_CHARACTER(c) \ + ( ((c) >= '0' && (c) <= '9') || \ + ((c) >= 'A' && (c) <= 'Z') || \ + ((c) >= 'a' && (c) <= 'z')) + + +static void +append_escaped_name (GString *s, + const char *unescaped) +{ + char c; + gboolean first; + static const gchar hex[16] = "0123456789ABCDEF"; + + while ((c = *unescaped++) != 0) + { + if (first) + { + if (VALID_INITIAL_NAME_CHARACTER (c)) + { + g_string_append_c (s, c); + continue; + } + } + else + { + if (VALID_NAME_CHARACTER (c)) + { + g_string_append_c (s, c); + continue; + } + } + + first = FALSE; + g_string_append_c (s, '_'); + g_string_append_c (s, hex[((guchar)c) >> 4]); + g_string_append_c (s, hex[((guchar)c) & 0xf]); + } +} + +DBusMessage * +_dbus_message_new_gerror (DBusMessage *message, + GQuark domain, + gint code, + const gchar *format, + ...) +{ + DBusMessage *reply; + va_list args; + GError error; + + error.domain = domain; + error.code = code; + va_start (args, format); + error.message = g_strdup_vprintf (format, args); + va_end (args); + + reply = _dbus_message_new_from_gerror (message, &error); + + g_free (error.message); + + return reply; +} + +DBusMessage * +_dbus_message_new_from_gerror (DBusMessage *message, + GError *error) +{ + DBusMessage *reply; + GString *str; + + str = g_string_new ("org.glib.GError."); + append_escaped_name (str, g_quark_to_string (error->domain)); + g_string_append_printf (str, ".c%d", error->code); + reply = dbus_message_new_error (message, str->str, error->message); + g_string_free (str, TRUE); + return reply; +} + +gboolean +_g_error_from_message (DBusMessage *message, + GError **error) +{ + DBusError derror; + + dbus_error_init (&derror); + if (dbus_set_error_from_message (&derror, message)) + { + _g_error_from_dbus (&derror, error); + dbus_error_free (&derror); + return TRUE; + } + return FALSE; +} + + + +static void +append_unescaped_dbus_name (GString *s, + const char *escaped, + const char *end) +{ + guchar c; + + while (escaped < end) + { + c = *escaped++; + if (c == '_' && + escaped < end) + { + c = g_ascii_xdigit_value (*escaped++) << 4; + + if (escaped < end) + c |= g_ascii_xdigit_value (*escaped++); + } + g_string_append_c (s, c); + } +} + +char * +_g_dbus_unescape_bus_name (const char *escaped, const char *end) +{ + GString *s = g_string_new (""); + + if (end == NULL) + end = escaped + strlen (escaped); + + append_unescaped_dbus_name (s, escaped, end); + return g_string_free (s, FALSE); +} + +/* We use _ for escaping */ +#define VALID_INITIAL_BUS_NAME_CHARACTER(c) \ + ( ((c) >= 'A' && (c) <= 'Z') || \ + ((c) >= 'a' && (c) <= 'z') || \ + /*((c) == '_') || */((c) == '-')) +#define VALID_BUS_NAME_CHARACTER(c) \ + ( ((c) >= '0' && (c) <= '9') || \ + ((c) >= 'A' && (c) <= 'Z') || \ + ((c) >= 'a' && (c) <= 'z') || \ + /*((c) == '_')||*/ ((c) == '-')) + +void +_g_dbus_append_escaped_bus_name (GString *s, + gboolean at_start, + const char *unescaped) +{ + char c; + gboolean first; + static const gchar hex[16] = "0123456789ABCDEF"; + + while ((c = *unescaped++) != 0) + { + if (first && at_start) + { + if (VALID_INITIAL_BUS_NAME_CHARACTER (c)) + { + g_string_append_c (s, c); + continue; + } + } + else + { + if (VALID_BUS_NAME_CHARACTER (c)) + { + g_string_append_c (s, c); + continue; + } + } + + first = FALSE; + g_string_append_c (s, '_'); + g_string_append_c (s, hex[((guchar)c) >> 4]); + g_string_append_c (s, hex[((guchar)c) & 0xf]); + } +} + +void +_g_dbus_message_iter_append_cstring (DBusMessageIter *iter, const char *str) +{ + DBusMessageIter array; + + if (str == NULL) + str = ""; + + if (!dbus_message_iter_open_container (iter, + DBUS_TYPE_ARRAY, + DBUS_TYPE_BYTE_AS_STRING, + &array)) + _g_dbus_oom (); + + if (!dbus_message_iter_append_fixed_array (&array, + DBUS_TYPE_BYTE, + &str, strlen (str))) + _g_dbus_oom (); + + if (!dbus_message_iter_close_container (iter, &array)) + _g_dbus_oom (); +} + +void +_g_dbus_message_iter_append_args_valist (DBusMessageIter *iter, + int first_arg_type, + va_list var_args) +{ + int type; + + g_return_if_fail (iter != NULL); + + type = first_arg_type; + + while (type != DBUS_TYPE_INVALID) + { + if (type == G_DBUS_TYPE_CSTRING) + { + const char **value_p; + const char *value; + + value_p = va_arg (var_args, const char**); + value = *value_p; + + _g_dbus_message_iter_append_cstring (iter, value); + } + else if (dbus_type_is_basic (type)) + { + const void *value; + value = va_arg (var_args, const void*); + + if (!dbus_message_iter_append_basic (iter, + type, + value)) + _g_dbus_oom (); + } + else if (type == DBUS_TYPE_ARRAY) + { + int element_type; + DBusMessageIter array; + char buf[2]; + + element_type = va_arg (var_args, int); + + buf[0] = element_type; + buf[1] = '\0'; + if (!dbus_message_iter_open_container (iter, + DBUS_TYPE_ARRAY, + buf, + &array)) + _g_dbus_oom (); + + if (dbus_type_is_fixed (element_type)) + { + const void **value; + int n_elements; + + value = va_arg (var_args, const void**); + n_elements = va_arg (var_args, int); + + if (!dbus_message_iter_append_fixed_array (&array, + element_type, + value, + n_elements)) + _g_dbus_oom (); + } + else if (element_type == DBUS_TYPE_STRING || + element_type == DBUS_TYPE_SIGNATURE || + element_type == DBUS_TYPE_OBJECT_PATH) + { + const char ***value_p; + const char **value; + int n_elements; + int i; + + value_p = va_arg (var_args, const char***); + n_elements = va_arg (var_args, int); + + value = *value_p; + + i = 0; + while (i < n_elements) + { + if (!dbus_message_iter_append_basic (&array, + element_type, + &value[i])) + _g_dbus_oom (); + ++i; + } + } + else + { + g_error ("arrays of %d can't be appended with _g_dbus_message_append_args_valist for now\n", + element_type); + } + + if (!dbus_message_iter_close_container (iter, &array)) + _g_dbus_oom (); + } + + type = va_arg (var_args, int); + } +} + + +void +_g_dbus_message_append_args_valist (DBusMessage *message, + int first_arg_type, + va_list var_args) +{ + int type; + DBusMessageIter iter; + + g_return_if_fail (message != NULL); + + type = first_arg_type; + + dbus_message_iter_init_append (message, &iter); + + _g_dbus_message_iter_append_args_valist (&iter, + first_arg_type, + var_args); +} + +dbus_bool_t +_g_dbus_message_iter_get_args_valist (DBusMessageIter *iter, + DBusError *error, + int first_arg_type, + va_list var_args) +{ + int spec_type, msg_type, i, dbus_spec_type; + dbus_bool_t retval; + + + retval = FALSE; + + spec_type = first_arg_type; + i = 0; + + while (spec_type != DBUS_TYPE_INVALID) + { + msg_type = dbus_message_iter_get_arg_type (iter); + + if (spec_type == G_DBUS_TYPE_CSTRING) + dbus_spec_type = DBUS_TYPE_ARRAY; + else + dbus_spec_type = spec_type; + + if (msg_type != dbus_spec_type) + { + dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, + "Argument %d is specified to be of type \"%c\", but " + "is actually of type \"%c\"\n", i, + spec_type, + msg_type); + + goto out; + } + + if (spec_type == G_DBUS_TYPE_CSTRING) + { + int element_type; + char **ptr; + const char *str; + int n_elements; + DBusMessageIter array; + + element_type = dbus_message_iter_get_element_type (iter); + if (DBUS_TYPE_BYTE != element_type) + { + dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, + "Argument %d is specified to be an array of \"char\", but " + "is actually an array of \"%d\"\n", + i, + element_type); + goto out; + } + + ptr = va_arg (var_args, char**); + g_assert (ptr != NULL); + + dbus_message_iter_recurse (iter, &array); + dbus_message_iter_get_fixed_array (&array, + &str, &n_elements); + *ptr = g_strndup (str, n_elements); + } + else if (dbus_type_is_basic (spec_type)) + { + void *ptr; + + ptr = va_arg (var_args, void*); + + g_assert (ptr != NULL); + + dbus_message_iter_get_basic (iter, ptr); + } + else if (spec_type == DBUS_TYPE_ARRAY) + { + int element_type; + int spec_element_type; + const void **ptr; + int *n_elements_p; + DBusMessageIter array; + + spec_element_type = va_arg (var_args, int); + element_type = dbus_message_iter_get_element_type (iter); + + if (spec_element_type != element_type) + { + dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, + "Argument %d is specified to be an array of \"%d\", but " + "is actually an array of \"%d\"\n", + i, + spec_element_type, + element_type); + + goto out; + } + + if (dbus_type_is_fixed (spec_element_type)) + { + ptr = va_arg (var_args, const void**); + n_elements_p = va_arg (var_args, int*); + + g_assert (ptr != NULL); + g_assert (n_elements_p != NULL); + + dbus_message_iter_recurse (iter, &array); + + dbus_message_iter_get_fixed_array (&array, + ptr, n_elements_p); + } + else if (spec_element_type == DBUS_TYPE_STRING || + spec_element_type == DBUS_TYPE_SIGNATURE || + spec_element_type == DBUS_TYPE_OBJECT_PATH) + { + char ***str_array_p; + int n_elements; + char **str_array; + + str_array_p = va_arg (var_args, char***); + n_elements_p = va_arg (var_args, int*); + + g_assert (str_array_p != NULL); + g_assert (n_elements_p != NULL); + + /* Count elements in the array */ + dbus_message_iter_recurse (iter, &array); + + n_elements = 0; + while (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_INVALID) + { + ++n_elements; + dbus_message_iter_next (&array); + } + + str_array = g_new0 (char*, n_elements + 1); + if (str_array == NULL) + { + _g_dbus_oom (); + goto out; + } + + /* Now go through and dup each string */ + dbus_message_iter_recurse (iter, &array); + + i = 0; + while (i < n_elements) + { + const char *s; + dbus_message_iter_get_basic (&array, &s); + + str_array[i] = g_strdup (s); + if (str_array[i] == NULL) + { + g_strfreev (str_array); + _g_dbus_oom (); + goto out; + } + + ++i; + + if (!dbus_message_iter_next (&array)) + g_assert (i == n_elements); + } + + g_assert (dbus_message_iter_get_arg_type (&array) == DBUS_TYPE_INVALID); + g_assert (i == n_elements); + g_assert (str_array[i] == NULL); + + *str_array_p = str_array; + *n_elements_p = n_elements; + } + } + + spec_type = va_arg (var_args, int); + if (!dbus_message_iter_next (iter) && spec_type != DBUS_TYPE_INVALID) + { + dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, + "Message has only %d arguments, but more were expected", i); + goto out; + } + + i++; + } + + retval = TRUE; + + out: + return retval; +} + +dbus_bool_t +_g_dbus_message_iter_get_args (DBusMessageIter *iter, + DBusError *error, + int first_arg_type, + ...) +{ + va_list var_args; + dbus_bool_t res; + + va_start (var_args, first_arg_type); + res = _g_dbus_message_iter_get_args_valist (iter, error, + first_arg_type, + var_args); + va_end (var_args); + return res; +} + +/* Same as the dbus one, except doesn't give OOM and handles + G_DBUS_TYPE_CSTRING +*/ +void +_g_dbus_message_append_args (DBusMessage *message, + int first_arg_type, + ...) +{ + va_list var_args; + + g_return_if_fail (message != NULL); + + va_start (var_args, first_arg_type); + _g_dbus_message_append_args_valist (message, + first_arg_type, + var_args); + va_end (var_args); +} + +void +_g_dbus_message_iter_append_args (DBusMessageIter *iter, + int first_arg_type, + ...) +{ + va_list var_args; + + g_return_if_fail (iter != NULL); + + va_start (var_args, first_arg_type); + _g_dbus_message_iter_append_args_valist (iter, + first_arg_type, + var_args); + va_end (var_args); +} + +void +_g_error_from_dbus (DBusError *derror, + GError **error) +{ + const char *name, *end; + GString *str; + GQuark domain; + int code; + + if (g_str_has_prefix (derror->name, "org.glib.GError.")) + { + domain = 0; + code = 0; + + name = derror->name + strlen ("org.glib.GError."); + end = strchr (name, '.'); + if (end) + { + str = g_string_new (NULL); + append_unescaped_dbus_name (str, name, end); + domain = g_quark_from_string (str->str); + g_string_free (str, TRUE); + + end++; /* skip . */ + if (*end++ == 'c') + code = atoi (end); + } + + g_set_error_literal (error, domain, code, derror->message); + } + /* TODO: Special case other types, like DBUS_ERROR_NO_MEMORY etc? */ + else + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "DBus error %s: %s", derror->name, derror->message); +} + +GList * +_g_dbus_bus_list_names_with_prefix (DBusConnection *connection, + const char *prefix, + DBusError *error) +{ + DBusMessage *message, *reply; + DBusMessageIter iter, array; + GList *names; + + g_return_val_if_fail (connection != NULL, NULL); + + message = dbus_message_new_method_call (DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "ListNames"); + if (message == NULL) + return NULL; + + reply = dbus_connection_send_with_reply_and_block (connection, message, -1, error); + dbus_message_unref (message); + + if (reply == NULL) + return NULL; + + names = NULL; + + if (!dbus_message_iter_init (reply, &iter) || + (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) || + (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_STRING)) + goto out; + + for (dbus_message_iter_recurse (&iter, &array); + dbus_message_iter_get_arg_type (&array) == DBUS_TYPE_STRING; + dbus_message_iter_next (&array)) + { + char *name; + dbus_message_iter_get_basic (&array, &name); + if (g_str_has_prefix (name, prefix)) + names = g_list_prepend (names, g_strdup (name)); + } + + names = g_list_reverse (names); + + out: + dbus_message_unref (reply); + return names; +} + +/************************************************************************* + * Helper fd source * + ************************************************************************/ + +typedef struct +{ + GSource source; + GPollFD pollfd; + GCancellable *cancellable; + gulong cancelled_tag; +} FDSource; + +static gboolean +fd_source_prepare (GSource *source, + gint *timeout) +{ + FDSource *fd_source = (FDSource *)source; + *timeout = -1; + + return g_cancellable_is_cancelled (fd_source->cancellable); +} + +static gboolean +fd_source_check (GSource *source) +{ + FDSource *fd_source = (FDSource *)source; + + return + g_cancellable_is_cancelled (fd_source->cancellable) || + fd_source->pollfd.revents != 0; +} + +static gboolean +fd_source_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) + +{ + GFDSourceFunc func = (GFDSourceFunc)callback; + FDSource *fd_source = (FDSource *)source; + + g_assert (func != NULL); + + return (*func) (user_data, fd_source->pollfd.revents, fd_source->pollfd.fd); +} + +static void +fd_source_finalize (GSource *source) +{ + FDSource *fd_source = (FDSource *)source; + + if (fd_source->cancelled_tag) + g_signal_handler_disconnect (fd_source->cancellable, + fd_source->cancelled_tag); + + if (fd_source->cancellable) + g_object_unref (fd_source->cancellable); +} + +static GSourceFuncs fd_source_funcs = { + fd_source_prepare, + fd_source_check, + fd_source_dispatch, + fd_source_finalize +}; + +/* Might be called on another thread */ +static void +fd_source_cancelled_cb (GCancellable *cancellable, + gpointer data) +{ + /* Wake up the mainloop in case we're waiting on async calls with FDSource */ + g_main_context_wakeup (NULL); +} + +/* Two __ to avoid conflict with gio version */ +GSource * +__g_fd_source_new (int fd, + gushort events, + GCancellable *cancellable) +{ + GSource *source; + FDSource *fd_source; + + source = g_source_new (&fd_source_funcs, sizeof (FDSource)); + fd_source = (FDSource *)source; + + if (cancellable) + fd_source->cancellable = g_object_ref (cancellable); + + fd_source->pollfd.fd = fd; + fd_source->pollfd.events = events; + g_source_add_poll (source, &fd_source->pollfd); + + if (cancellable) + fd_source->cancelled_tag = + g_signal_connect_data (cancellable, "cancelled", + (GCallback)fd_source_cancelled_cb, + NULL, NULL, + 0); + + return source; +} + + +/************************************************************************* + * * + * dbus mainloop integration for async ops * + * * + *************************************************************************/ + +static gint32 main_integration_data_slot = -1; +static GOnce once_init_main_integration = G_ONCE_INIT; + +/** + * A GSource subclass for dispatching DBusConnection messages. + * We need this on top of the IO handlers, because sometimes + * there are messages to dispatch queued up but no IO pending. + * + * The source is owned by the connection (and the main context + * while that is alive) + */ +typedef struct +{ + GSource source; + + DBusConnection *connection; + GSList *ios; + GSList *timeouts; +} DBusSource; + +typedef struct +{ + DBusSource *dbus_source; + GSource *source; + DBusWatch *watch; +} IOHandler; + +typedef struct +{ + DBusSource *dbus_source; + GSource *source; + DBusTimeout *timeout; +} TimeoutHandler; + +static gpointer +main_integration_init (gpointer arg) +{ + if (!dbus_connection_allocate_data_slot (&main_integration_data_slot)) + g_error ("Unable to allocate data slot"); + + return NULL; +} + +static gboolean +dbus_source_prepare (GSource *source, + gint *timeout) +{ + DBusConnection *connection = ((DBusSource *)source)->connection; + + *timeout = -1; + + return (dbus_connection_get_dispatch_status (connection) == DBUS_DISPATCH_DATA_REMAINS); +} + +static gboolean +dbus_source_check (GSource *source) +{ + return FALSE; +} + +static gboolean +dbus_source_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + DBusConnection *connection = ((DBusSource *)source)->connection; + + dbus_connection_ref (connection); + + /* Only dispatch once - we don't want to starve other GSource */ + dbus_connection_dispatch (connection); + + dbus_connection_unref (connection); + + return TRUE; +} + +static gboolean +io_handler_dispatch (gpointer data, + GIOCondition condition, + int fd) +{ + IOHandler *handler = data; + guint dbus_condition = 0; + DBusConnection *connection; + + connection = handler->dbus_source->connection; + + if (connection) + dbus_connection_ref (connection); + + if (condition & G_IO_IN) + dbus_condition |= DBUS_WATCH_READABLE; + if (condition & G_IO_OUT) + dbus_condition |= DBUS_WATCH_WRITABLE; + if (condition & G_IO_ERR) + dbus_condition |= DBUS_WATCH_ERROR; + if (condition & G_IO_HUP) + dbus_condition |= DBUS_WATCH_HANGUP; + + /* Note that we don't touch the handler after this, because + * dbus may have disabled the watch and thus killed the + * handler. + */ + dbus_watch_handle (handler->watch, dbus_condition); + handler = NULL; + + if (connection) + dbus_connection_unref (connection); + + return TRUE; +} + +static void +io_handler_free (IOHandler *handler) +{ + DBusSource *dbus_source; + + dbus_source = handler->dbus_source; + dbus_source->ios = g_slist_remove (dbus_source->ios, handler); + + g_source_destroy (handler->source); + g_source_unref (handler->source); + g_free (handler); +} + +static void +dbus_source_add_watch (DBusSource *dbus_source, + DBusWatch *watch) +{ + guint flags; + GIOCondition condition; + IOHandler *handler; + int fd; + + if (!dbus_watch_get_enabled (watch)) + return; + + g_assert (dbus_watch_get_data (watch) == NULL); + + flags = dbus_watch_get_flags (watch); + + condition = G_IO_ERR | G_IO_HUP; + if (flags & DBUS_WATCH_READABLE) + condition |= G_IO_IN; + if (flags & DBUS_WATCH_WRITABLE) + condition |= G_IO_OUT; + + handler = g_new0 (IOHandler, 1); + handler->dbus_source = dbus_source; + handler->watch = watch; + +#if (DBUS_MAJOR_VERSION == 1 && DBUS_MINOR_VERSION == 1 && DBUS_MICRO_VERSION >= 1) || (DBUS_MAJOR_VERSION == 1 && DBUS_MINOR_VERSION > 1) || (DBUS_MAJOR_VERSION > 1) + fd = dbus_watch_get_unix_fd (watch); +#else + fd = dbus_watch_get_fd (watch); +#endif + + handler->source = __g_fd_source_new (fd, condition, NULL); + g_source_set_callback (handler->source, + (GSourceFunc) io_handler_dispatch, handler, + NULL); + g_source_attach (handler->source, NULL); + + dbus_source->ios = g_slist_prepend (dbus_source->ios, handler); + dbus_watch_set_data (watch, handler, + (DBusFreeFunction)io_handler_free); +} + +static void +dbus_source_remove_watch (DBusSource *dbus_source, + DBusWatch *watch) +{ + dbus_watch_set_data (watch, NULL, NULL); +} + +static void +timeout_handler_free (TimeoutHandler *handler) +{ + DBusSource *dbus_source; + + dbus_source = handler->dbus_source; + dbus_source->timeouts = g_slist_remove (dbus_source->timeouts, handler); + + g_source_destroy (handler->source); + g_source_unref (handler->source); + g_free (handler); +} + +static gboolean +timeout_handler_dispatch (gpointer data) +{ + TimeoutHandler *handler = data; + + dbus_timeout_handle (handler->timeout); + + return TRUE; +} + +static void +dbus_source_add_timeout (DBusSource *dbus_source, + DBusTimeout *timeout) +{ + TimeoutHandler *handler; + + if (!dbus_timeout_get_enabled (timeout)) + return; + + g_assert (dbus_timeout_get_data (timeout) == NULL); + + handler = g_new0 (TimeoutHandler, 1); + handler->dbus_source = dbus_source; + handler->timeout = timeout; + + handler->source = g_timeout_source_new (dbus_timeout_get_interval (timeout)); + g_source_set_callback (handler->source, + timeout_handler_dispatch, handler, + NULL); + g_source_attach (handler->source, NULL); + + /* handler->source is owned by the context here */ + dbus_source->timeouts = g_slist_prepend (dbus_source->timeouts, handler); + + dbus_timeout_set_data (timeout, handler, + (DBusFreeFunction)timeout_handler_free); +} + +static void +dbus_source_remove_timeout (DBusSource *source, + DBusTimeout *timeout) +{ + dbus_timeout_set_data (timeout, NULL, NULL); +} + +static dbus_bool_t +add_watch (DBusWatch *watch, + gpointer data) +{ + DBusSource *dbus_source = data; + + dbus_source_add_watch (dbus_source, watch); + + return TRUE; +} + +static void +remove_watch (DBusWatch *watch, + gpointer data) +{ + DBusSource *dbus_source = data; + + dbus_source_remove_watch (dbus_source, watch); +} + +static void +watch_toggled (DBusWatch *watch, + void *data) +{ + /* Because we just exit on OOM, enable/disable is + * no different from add/remove */ + if (dbus_watch_get_enabled (watch)) + add_watch (watch, data); + else + remove_watch (watch, data); +} + +static dbus_bool_t +add_timeout (DBusTimeout *timeout, + void *data) +{ + DBusSource *source = data; + + if (!dbus_timeout_get_enabled (timeout)) + return TRUE; + + dbus_source_add_timeout (source, timeout); + + return TRUE; +} + +static void +remove_timeout (DBusTimeout *timeout, + void *data) +{ + DBusSource *source = data; + + dbus_source_remove_timeout (source, timeout); +} + +static void +timeout_toggled (DBusTimeout *timeout, + void *data) +{ + /* Because we just exit on OOM, enable/disable is + * no different from add/remove + */ + if (dbus_timeout_get_enabled (timeout)) + add_timeout (timeout, data); + else + remove_timeout (timeout, data); +} + +static void +wakeup_main (void *data) +{ + g_main_context_wakeup (NULL); +} + +static const GSourceFuncs dbus_source_funcs = { + dbus_source_prepare, + dbus_source_check, + dbus_source_dispatch +}; + +/* Called when the connection dies or when we're unintegrating from mainloop */ +static void +dbus_source_free (DBusSource *dbus_source) +{ + while (dbus_source->ios) + { + IOHandler *handler = dbus_source->ios->data; + + dbus_watch_set_data (handler->watch, NULL, NULL); + } + + while (dbus_source->timeouts) + { + TimeoutHandler *handler = dbus_source->timeouts->data; + + dbus_timeout_set_data (handler->timeout, NULL, NULL); + } + + /* Remove from mainloop */ + g_source_destroy ((GSource *)dbus_source); + + g_source_unref ((GSource *)dbus_source); +} + +void +_g_dbus_connection_integrate_with_main (DBusConnection *connection) +{ + DBusSource *dbus_source; + + g_once (&once_init_main_integration, main_integration_init, NULL); + + g_assert (connection != NULL); + + _g_dbus_connection_remove_from_main (connection); + + dbus_source = (DBusSource *) + g_source_new ((GSourceFuncs*)&dbus_source_funcs, + sizeof (DBusSource)); + + dbus_source->connection = connection; + + if (!dbus_connection_set_watch_functions (connection, + add_watch, + remove_watch, + watch_toggled, + dbus_source, NULL)) + _g_dbus_oom (); + + if (!dbus_connection_set_timeout_functions (connection, + add_timeout, + remove_timeout, + timeout_toggled, + dbus_source, NULL)) + _g_dbus_oom (); + + dbus_connection_set_wakeup_main_function (connection, + wakeup_main, + dbus_source, NULL); + + /* Owned by both connection and mainloop (until destroy) */ + g_source_attach ((GSource *)dbus_source, NULL); + + if (!dbus_connection_set_data (connection, + main_integration_data_slot, + dbus_source, (DBusFreeFunction)dbus_source_free)) + _g_dbus_oom (); +} + +void +_g_dbus_connection_remove_from_main (DBusConnection *connection) +{ + g_once (&once_init_main_integration, main_integration_init, NULL); + + if (!dbus_connection_set_data (connection, + main_integration_data_slot, + NULL, NULL)) + _g_dbus_oom (); +} + +void +_g_dbus_message_iter_copy (DBusMessageIter *dest, + DBusMessageIter *source) +{ + int type, element_type; + + while (dbus_message_iter_get_arg_type (source) != DBUS_TYPE_INVALID) + { + type = dbus_message_iter_get_arg_type (source); + + if (dbus_type_is_basic (type)) + { + dbus_uint64_t value; + dbus_message_iter_get_basic (source, &value); + dbus_message_iter_append_basic (dest, type, &value); + } + else if (type == DBUS_TYPE_ARRAY) + { + DBusMessageIter source_array, dest_array; + void *value; + int n_elements; + char buf[2]; + + element_type = dbus_message_iter_get_element_type (source); + if (dbus_type_is_fixed (element_type)) + { + buf[0] = element_type; + buf[1] = '\0'; + + dbus_message_iter_recurse (source, &source_array); + dbus_message_iter_get_fixed_array (&source_array, &value, &n_elements); + + if (!dbus_message_iter_open_container (dest, DBUS_TYPE_ARRAY, + buf, &dest_array)) + _g_dbus_oom (); + + if (!dbus_message_iter_append_fixed_array (&dest_array, + element_type, + &value, n_elements)) + _g_dbus_oom (); + + if (!dbus_message_iter_close_container (dest, &dest_array)) + _g_dbus_oom (); + } + else + g_error ("Unsupported array type %c in _g_dbus_message_iter_copy", element_type); + } + else + g_error ("Unsupported type %c in _g_dbus_message_iter_copy", type); + + dbus_message_iter_next (source); + } + +} + +typedef struct { + GAsyncDBusCallback callback; + gpointer user_data; + GError *io_error; + + + /* protected by async_call lock: */ + gboolean ran; /* the pending_call reply handler ran */ + gboolean idle; /* we queued an idle */ + + /* only used for idle */ + DBusPendingCall *pending; +} AsyncDBusCallData; + +/* Lock to protect the data for working around racecondition + between send_with_reply and pending_set_notify */ +G_LOCK_DEFINE_STATIC(async_call); + +static void +handle_async_reply (DBusPendingCall *pending, + AsyncDBusCallData *data) +{ + DBusMessage *reply; + GError *error; + + reply = dbus_pending_call_steal_reply (pending); + + error = NULL; + if (_g_error_from_message (reply, &error)) + { + if (data->callback) + data->callback (NULL, error, data->user_data); + g_error_free (error); + } + else + { + if (data->callback) + data->callback (reply, NULL, data->user_data); + } + + dbus_message_unref (reply); +} + +static void +async_call_reply (DBusPendingCall *pending, + void *_data) +{ + AsyncDBusCallData *data = _data; + + G_LOCK (async_call); + if (data->idle) + return; + data->ran = TRUE; + G_UNLOCK (async_call); + + handle_async_reply (pending, data); +} + +static gboolean +idle_async_callback (void *_data) +{ + AsyncDBusCallData *data = _data; + handle_async_reply (data->pending, data); + dbus_pending_call_unref (data->pending); + return FALSE; +} + +static gboolean +async_call_error_at_idle (gpointer _data) +{ + AsyncDBusCallData *data = _data; + + if (data->callback) + data->callback (NULL, data->io_error, data->user_data); + + g_error_free (data->io_error); + g_free (data); + + return FALSE; +} + +void +_g_dbus_connection_call_async (DBusConnection *connection, + DBusMessage *message, + int timeout_msecs, + GAsyncDBusCallback callback, + gpointer user_data) +{ + AsyncDBusCallData *data; + DBusPendingCall *pending_call; + DBusError derror; + + data = g_new0 (AsyncDBusCallData, 1); + data->callback = callback; + data->user_data = user_data; + + if (connection == NULL) + { + dbus_error_init (&derror); + connection = dbus_bus_get (DBUS_BUS_SESSION, &derror); + if (connection == NULL) + { + g_set_error_literal (&data->io_error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Can't open dbus connection"); + g_idle_add (async_call_error_at_idle, data); + dbus_error_free (&derror); + return; + } + } + + if (!dbus_connection_send_with_reply (connection, message, &pending_call, timeout_msecs)) + _g_dbus_oom (); + + if (pending_call == NULL) + { + g_set_error (&data->io_error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Error while getting peer-to-peer dbus connection: %s", + "Connection is closed"); + g_idle_add (async_call_error_at_idle, data); + return; + } + + if (!dbus_pending_call_set_notify (pending_call, + async_call_reply, + data, g_free)) + _g_dbus_oom (); + + + /* All this is required to work around a race condition between + * send_with_reply and pending_call_set_notify :/ + */ + G_LOCK (async_call); + + if (dbus_pending_call_get_completed (pending_call) && + !data->ran) + { + data->idle = TRUE; + data->pending = dbus_pending_call_ref (pending_call); + g_idle_add (idle_async_callback, data); + } + + G_UNLOCK (async_call); + + + dbus_pending_call_unref (pending_call); +} diff --git a/gnome-2-24/common/gdbusutils.h b/gnome-2-24/common/gdbusutils.h new file mode 100644 index 00000000..00ef566d --- /dev/null +++ b/gnome-2-24/common/gdbusutils.h @@ -0,0 +1,100 @@ +/* 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_DBUS_UTILS_H__ +#define __G_DBUS_UTILS_H__ + +#include <glib.h> +#include <dbus/dbus.h> +#include <gio/gio.h> + +G_BEGIN_DECLS + +typedef gboolean (*GFDSourceFunc) (gpointer data, + GIOCondition condition, + int fd); +typedef void (*GAsyncDBusCallback) (DBusMessage *reply, + GError *error, + gpointer user_data); + +/* Only used internally, never on wire */ +#define G_DBUS_TYPE_CSTRING 1024 + +GList * _g_dbus_bus_list_names_with_prefix (DBusConnection *connection, + const char *prefix, + DBusError *error); +void _g_dbus_message_iter_append_cstring (DBusMessageIter *iter, + const char *str); +void _g_dbus_message_iter_append_args_valist (DBusMessageIter *iter, + int first_arg_type, + va_list var_args); +void _g_dbus_message_iter_append_args (DBusMessageIter *iter, + int first_arg_type, + ...); +void _g_dbus_message_append_args_valist (DBusMessage *message, + int first_arg_type, + va_list var_args); +void _g_dbus_message_append_args (DBusMessage *message, + int first_arg_type, + ...); +dbus_bool_t _g_dbus_message_iter_get_args_valist (DBusMessageIter *iter, + DBusError *error, + int first_arg_type, + va_list var_args); +dbus_bool_t _g_dbus_message_iter_get_args (DBusMessageIter *iter, + DBusError *error, + int first_arg_type, + ...); +void _g_error_from_dbus (DBusError *derror, + GError **error); +gboolean _g_error_from_message (DBusMessage *message, + GError **error); +DBusMessage *_dbus_message_new_from_gerror (DBusMessage *message, + GError *error); +DBusMessage *_dbus_message_new_gerror (DBusMessage *message, + GQuark domain, + gint code, + const gchar *format, + ...); +char * _g_dbus_unescape_bus_name (const char *escaped, + const char *end); +void _g_dbus_append_escaped_bus_name (GString *string, + gboolean at_start, + const char *unescaped); +void _g_dbus_connection_integrate_with_main (DBusConnection *connection); +void _g_dbus_connection_remove_from_main (DBusConnection *connection); +GSource * __g_fd_source_new (int fd, + gushort events, + GCancellable *cancellable); +void _g_dbus_message_iter_copy (DBusMessageIter *dest, + DBusMessageIter *source); +void _g_dbus_oom (void) G_GNUC_NORETURN; +void _g_dbus_connection_call_async (DBusConnection *connection, + DBusMessage *message, + int timeout_msecs, + GAsyncDBusCallback callback, + gpointer user_data); + +G_END_DECLS + + +#endif /* __G_DBUS_UTILS_H__ */ diff --git a/gnome-2-24/common/gmountoperationdbus.c b/gnome-2-24/common/gmountoperationdbus.c new file mode 100644 index 00000000..1027b3a9 --- /dev/null +++ b/gnome-2-24/common/gmountoperationdbus.c @@ -0,0 +1,324 @@ +/* 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 <dbus/dbus.h> + +#define I_(string) g_intern_static_string (string) + +#include <gio/gio.h> +#include "gmountoperationdbus.h" +#include "gvfsdaemonprotocol.h" +#include "gdbusutils.h" +#include <glib/gi18n-lib.h> + +typedef struct +{ + GMountOperation *op; + char *obj_path; + char *dbus_id; + DBusConnection *connection; +} GMountOperationDBus; + +static DBusHandlerResult mount_op_message_function (DBusConnection *connection, + DBusMessage *message, + void *user_data); +static void mount_op_unregister_function (DBusConnection *connection, + void *user_data); +static void mount_op_ask_password (GMountOperationDBus *op_dbus, + DBusMessage *message); +static void mount_op_ask_question (GMountOperationDBus *op_dbus, + DBusMessage *message); + +static void +g_mount_operation_dbus_free (GMountOperationDBus *op_dbus) +{ + if (op_dbus->connection) + { + dbus_connection_unregister_object_path (op_dbus->connection, + op_dbus->obj_path); + dbus_connection_unref (op_dbus->connection); + } + g_free (op_dbus->dbus_id); + g_free (op_dbus->obj_path); + g_free (op_dbus); +} + +GMountSource * +g_mount_operation_dbus_wrap (GMountOperation *op, + DBusConnection *connection) +{ + GMountOperationDBus *op_dbus; + static int mount_id = 0; + DBusObjectPathVTable mount_vtable = { + mount_op_unregister_function, + mount_op_message_function + }; + + if (op == NULL) + return g_mount_source_new_dummy (); + + op_dbus = g_new0 (GMountOperationDBus, 1); + + op_dbus->op = op; + op_dbus->connection = dbus_connection_ref (connection); + op_dbus->obj_path = g_strdup_printf ("/org/gtk/gvfs/mountop/%d", mount_id++); + if (op_dbus->connection) + { + op_dbus->dbus_id = g_strdup (dbus_bus_get_unique_name (op_dbus->connection)); + if (!dbus_connection_register_object_path (op_dbus->connection, + op_dbus->obj_path, + &mount_vtable, + op_dbus)) + _g_dbus_oom (); + } + + g_object_set_data_full (G_OBJECT (op), "dbus-op", + op_dbus, (GDestroyNotify)g_mount_operation_dbus_free); + + return g_mount_source_new (op_dbus->dbus_id, op_dbus->obj_path); +} + +/** + * Called when a #DBusObjectPathVTable is unregistered (or its connection is freed). + * Found in #DBusObjectPathVTable. + */ +static void +mount_op_unregister_function (DBusConnection *connection, + void *user_data) +{ +} + +/** + * Called when a message is sent to a registered object path. Found in + * #DBusObjectPathVTable which is registered with dbus_connection_register_object_path() + * or dbus_connection_register_fallback(). + */ +static DBusHandlerResult +mount_op_message_function (DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + GMountOperationDBus *op_dbus = user_data; + + if (dbus_message_is_method_call (message, + G_VFS_DBUS_MOUNT_OPERATION_INTERFACE, + G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_PASSWORD)) + mount_op_ask_password (op_dbus, message); + else if (dbus_message_is_method_call (message, + G_VFS_DBUS_MOUNT_OPERATION_INTERFACE, + G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_QUESTION)) + mount_op_ask_question (op_dbus, message); + else + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + return DBUS_HANDLER_RESULT_HANDLED; +} + +static void +mount_op_send_reply (GMountOperationDBus *op_dbus, + DBusMessage *reply) +{ + if (!dbus_connection_send (op_dbus->connection, reply, NULL)) + _g_dbus_oom (); + + g_signal_handlers_disconnect_matched (op_dbus->op, + G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DATA, + g_signal_lookup ("reply", G_TYPE_MOUNT_OPERATION), + 0, + NULL, + NULL, + reply); + dbus_message_unref (reply); +} + +static void +ask_password_reply (GMountOperation *op, + GMountOperationResult result, + gpointer data) +{ + DBusMessage *reply = data; + const char *username, *password, *domain; + dbus_bool_t anonymous; + guint32 password_save; + dbus_bool_t handled, abort_dbus; + GMountOperationDBus *op_dbus; + + op_dbus = g_object_get_data (G_OBJECT (op), "dbus-op"); + + handled = (result != G_MOUNT_OPERATION_UNHANDLED); + abort_dbus = (result == G_MOUNT_OPERATION_ABORTED); + + password = g_mount_operation_get_password (op); + if (password == NULL) + password = ""; + username = g_mount_operation_get_username (op); + if (username == NULL) + username = ""; + domain = g_mount_operation_get_domain (op); + if (domain == NULL) + domain = ""; + anonymous = g_mount_operation_get_anonymous (op); + password_save = g_mount_operation_get_password_save (op); + + _g_dbus_message_append_args (reply, + DBUS_TYPE_BOOLEAN, &handled, + DBUS_TYPE_BOOLEAN, &abort_dbus, + DBUS_TYPE_STRING, &password, + DBUS_TYPE_STRING, &username, + DBUS_TYPE_STRING, &domain, + DBUS_TYPE_BOOLEAN, &anonymous, + DBUS_TYPE_UINT32, &password_save, + 0); + + mount_op_send_reply (op_dbus, reply); +} + +static void +mount_op_ask_password (GMountOperationDBus *op_dbus, + DBusMessage *message) +{ + const char *message_string, *default_user, *default_domain; + guint32 flags; + DBusMessageIter iter; + DBusMessage *reply; + DBusError error; + + reply = NULL; + + dbus_message_iter_init (message, &iter); + + dbus_error_init (&error); + if (!_g_dbus_message_iter_get_args (&iter, + &error, + DBUS_TYPE_STRING, &message_string, + DBUS_TYPE_STRING, &default_user, + DBUS_TYPE_STRING, &default_domain, + DBUS_TYPE_UINT32, &flags, + 0)) + { + reply = dbus_message_new_error (message, error.name, error.message); + if (reply == NULL) + _g_dbus_oom (); + if (!dbus_connection_send (op_dbus->connection, reply, NULL)) + _g_dbus_oom (); + dbus_message_unref (reply); + dbus_error_free (&error); + return; + } + + reply = dbus_message_new_method_return (message); + if (reply == NULL) + _g_dbus_oom (); + + g_signal_connect (op_dbus->op, "reply", (GCallback)ask_password_reply, reply); + + g_signal_emit_by_name (op_dbus->op, "ask_password", + message_string, + default_user, + default_domain, + flags); +} + +static void +ask_question_reply (GMountOperation *op, + GMountOperationResult result, + gpointer data) +{ + DBusMessage *reply = data; + guint32 choice; + dbus_bool_t handled, abort_dbus; + GMountOperationDBus *op_dbus; + + op_dbus = g_object_get_data (G_OBJECT (op), "dbus-op"); + + handled = (result != G_MOUNT_OPERATION_UNHANDLED); + abort_dbus = (result == G_MOUNT_OPERATION_ABORTED); + + choice = g_mount_operation_get_choice (op); + + _g_dbus_message_append_args (reply, + DBUS_TYPE_BOOLEAN, &handled, + DBUS_TYPE_BOOLEAN, &abort_dbus, + DBUS_TYPE_UINT32, &choice, + 0); + + mount_op_send_reply (op_dbus, reply); +} + +static void +mount_op_ask_question (GMountOperationDBus *op_dbus, + DBusMessage *message) +{ + const char *message_string; + char **choices; + int num_choices; + dbus_bool_t handled = FALSE; + DBusMessage *reply; + DBusError error; + gboolean res; + DBusMessageIter iter; + + reply = NULL; + + dbus_message_iter_init (message, &iter); + dbus_error_init (&error); + if (!_g_dbus_message_iter_get_args (&iter, + &error, + DBUS_TYPE_STRING, &message_string, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, + &choices, &num_choices, + 0)) + { + reply = dbus_message_new_error (message, error.name, error.message); + if (reply == NULL) + _g_dbus_oom (); + if (!dbus_connection_send (op_dbus->connection, reply, NULL)) + _g_dbus_oom (); + dbus_message_unref (reply); + dbus_error_free (&error); + return; + } + + reply = dbus_message_new_method_return (message); + if (reply == NULL) + _g_dbus_oom (); + + g_signal_connect (op_dbus->op, "reply", (GCallback)ask_question_reply, reply); + + g_signal_emit_by_name (op_dbus->op, "ask_question", + message_string, + choices, + &res); + if (!res) + { + _g_dbus_message_append_args (reply, + DBUS_TYPE_BOOLEAN, &handled, + 0); + mount_op_send_reply (op_dbus, reply); + } + + dbus_free_string_array (choices); +} diff --git a/gnome-2-24/common/gmountoperationdbus.h b/gnome-2-24/common/gmountoperationdbus.h new file mode 100644 index 00000000..26ee4013 --- /dev/null +++ b/gnome-2-24/common/gmountoperationdbus.h @@ -0,0 +1,40 @@ +/* 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_MOUNT_OPERATION_DBUS_H__ +#define __G_MOUNT_OPERATION_DBUS_H__ + +#include <sys/stat.h> + +#include <glib-object.h> +#include <gio/gio.h> +#include <gmountspec.h> +#include <gmountsource.h> + +G_BEGIN_DECLS + +GMountSource *g_mount_operation_dbus_wrap (GMountOperation *op, + DBusConnection *connection); + +G_END_DECLS + +#endif /* __G_MOUNT_OPERATION_DBUS_H__ */ diff --git a/gnome-2-24/common/gmountsource.c b/gnome-2-24/common/gmountsource.c new file mode 100644 index 00000000..e801d647 --- /dev/null +++ b/gnome-2-24/common/gmountsource.c @@ -0,0 +1,716 @@ +/* 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 <gmountsource.h> +#include <gdbusutils.h> +#include <gio/gio.h> +#include <gvfsdaemonprotocol.h> + +struct _GMountSource +{ + GObject parent_instance; + + char *dbus_id; + char *obj_path; +}; + +G_DEFINE_TYPE (GMountSource, g_mount_source, G_TYPE_OBJECT) + +static void +g_mount_source_finalize (GObject *object) +{ + GMountSource *source; + + source = G_MOUNT_SOURCE (object); + + g_free (source->dbus_id); + g_free (source->obj_path); + + if (G_OBJECT_CLASS (g_mount_source_parent_class)->finalize) + (*G_OBJECT_CLASS (g_mount_source_parent_class)->finalize) (object); +} + +static void +g_mount_source_class_init (GMountSourceClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = g_mount_source_finalize; +} + +static void +g_mount_source_init (GMountSource *mount_source) +{ +} + +GMountSource * +g_mount_source_new (const char *dbus_id, + const char *obj_path) +{ + GMountSource *source; + + source = g_object_new (G_TYPE_MOUNT_SOURCE, NULL); + + source->dbus_id = g_strdup (dbus_id); + source->obj_path = g_strdup (obj_path); + + return source; +} + +GMountSource * +g_mount_source_new_dummy (void) +{ + GMountSource *source; + + source = g_object_new (G_TYPE_MOUNT_SOURCE, NULL); + + source->dbus_id = g_strdup (""); + source->obj_path = g_strdup ("/"); + + return source; +} + + +void +g_mount_source_to_dbus (GMountSource *source, + DBusMessage *message) +{ + g_assert (source->dbus_id != NULL); + g_assert (source->obj_path != NULL); + + if (!dbus_message_append_args (message, + DBUS_TYPE_STRING, &source->dbus_id, + DBUS_TYPE_OBJECT_PATH, &source->obj_path, + 0)) + _g_dbus_oom (); + +} + +const char * +g_mount_source_get_dbus_id (GMountSource *mount_source) +{ + return mount_source->dbus_id; +} + +const char * +g_mount_source_get_obj_path (GMountSource *mount_source) +{ + return mount_source->obj_path; +} + +typedef struct AskPasswordData AskPasswordData; + +struct AskPasswordData { + + /* results: */ + gboolean aborted; + char *password; + char *username; + char *domain; + GPasswordSave password_save; + gboolean anonymous; +}; + +typedef struct AskSyncData AskSyncData; + +struct AskSyncData { + + /* For sync calls */ + GMutex *mutex; + GCond *cond; + + /* results: */ + GAsyncResult *result; +}; + +static void +ask_password_data_free (gpointer _data) +{ + AskPasswordData *data = (AskPasswordData *) _data; + g_free (data->password); + g_free (data->username); + g_free (data->domain); + g_free (data); +} + +/* the callback from dbus -> main thread */ +static void +ask_password_reply (DBusMessage *reply, + GError *error, + gpointer _data) +{ + GSimpleAsyncResult *result; + AskPasswordData *data; + dbus_bool_t handled, aborted, anonymous; + guint32 password_save; + const char *password, *username, *domain; + DBusMessageIter iter; + + result = G_SIMPLE_ASYNC_RESULT (_data); + handled = TRUE; + + data = g_new0 (AskPasswordData, 1); + g_simple_async_result_set_op_res_gpointer (result, data, ask_password_data_free); + + if (reply == NULL) + { + data->aborted = TRUE; + } + else + { + dbus_message_iter_init (reply, &iter); + if (!_g_dbus_message_iter_get_args (&iter, NULL, + DBUS_TYPE_BOOLEAN, &handled, + DBUS_TYPE_BOOLEAN, &aborted, + DBUS_TYPE_STRING, &password, + DBUS_TYPE_STRING, &username, + DBUS_TYPE_STRING, &domain, + DBUS_TYPE_BOOLEAN, &anonymous, + DBUS_TYPE_UINT32, &password_save, + 0)) + data->aborted = TRUE; + else + { + data->aborted = aborted; + + if (!anonymous) + { + data->password = g_strdup (password); + data->username = *username == 0 ? NULL : g_strdup (username); + data->domain = *domain == 0 ? NULL : g_strdup (domain); + } + data->password_save = (GPasswordSave)password_save; + data->anonymous = anonymous; + + /* TODO: handle more args */ + } + } + + if (handled == FALSE) + { + g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, "Internal Error"); + } + + g_simple_async_result_complete (result); +} + +void +g_mount_source_ask_password_async (GMountSource *source, + const char *message_string, + const char *default_user, + const char *default_domain, + GAskPasswordFlags flags, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + DBusMessage *message; + guint32 flags_as_int; + + + /* If no dbus id specified, reply that we weren't handled */ + if (source->dbus_id[0] == 0) + { + g_simple_async_report_error_in_idle (G_OBJECT (source), + callback, + user_data, + G_IO_ERROR, G_IO_ERROR_FAILED, + "Internal Error"); + return; + } + + if (message_string == NULL) + message_string = ""; + if (default_user == NULL) + default_user = ""; + if (default_domain == NULL) + default_domain = ""; + + flags_as_int = flags; + + message = dbus_message_new_method_call (source->dbus_id, + source->obj_path, + G_VFS_DBUS_MOUNT_OPERATION_INTERFACE, + G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_PASSWORD); + + _g_dbus_message_append_args (message, + DBUS_TYPE_STRING, &message_string, + DBUS_TYPE_STRING, &default_user, + DBUS_TYPE_STRING, &default_domain, + DBUS_TYPE_UINT32, &flags_as_int, + 0); + + result = g_simple_async_result_new (G_OBJECT (source), callback, user_data, + g_mount_source_ask_password_async); + /* 30 minute timeout */ + _g_dbus_connection_call_async (NULL, message, 1000 * 60 * 30, + ask_password_reply, result); + dbus_message_unref (message); + +} + +/** + * g_mount_source_ask_password_finish: + * @source: the source to query + * @result: the async result + * @aborted: set to %TRUE if the password dialog was aborted by the user + * @password_out: the to the password set by the user or to %NULL if none + * @user_out: set to the username set by the user or to %NULL if none + * @domain_out: set to the domain set by the user or to %NULL if none + * @anonymous_out: set to %TRUE if the user selected anonymous login. This + * should only happen if G_ASK_PASSWORD_ANONYMOUS_SUPPORTED + * was supplied whe querying the password. + * @password_save_out: set to the save flags to use when saving the password + * in the keyring. + * + * Requests the reply parameters from a g_mount_source_ask_password_async() + * request. All out parameters can be set to %NULL to ignore them. + * <note><para>Please be aware that out parameters other than the password + * are set to %NULL if the user don't specify them so make sure to + * check them.</para></note> + * + * Returns: %FALSE if the async reply contained an error. + **/ +gboolean +g_mount_source_ask_password_finish (GMountSource *source, + GAsyncResult *result, + gboolean *aborted, + char **password_out, + char **user_out, + char **domain_out, + gboolean *anonymous_out, + GPasswordSave *password_save_out) +{ + AskPasswordData *data, def = { TRUE, }; + GSimpleAsyncResult *simple; + + simple = G_SIMPLE_ASYNC_RESULT (result); + + if (g_simple_async_result_propagate_error (simple, NULL)) + data = &def; + else + data = (AskPasswordData *) g_simple_async_result_get_op_res_gpointer (simple); + + if (aborted) + *aborted = data->aborted; + + if (password_out) + { + *password_out = data->password; + data->password = NULL; + } + + if (user_out) + { + *user_out = data->username; + data->username = NULL; + } + + if (domain_out) + { + *domain_out = data->domain; + data->domain = NULL; + } + + if (anonymous_out) + *anonymous_out = data->anonymous; + + if (password_save_out) + *password_save_out = data->password_save; + + return data != &def; +} + + +static void +ask_reply_sync (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + AskSyncData *data; + + data = (AskSyncData *) user_data; + + data->result = g_object_ref (res); + + /* Wake up sync call thread */ + g_mutex_lock (data->mutex); + g_cond_signal (data->cond); + g_mutex_unlock (data->mutex); +} + +gboolean +g_mount_source_ask_password (GMountSource *source, + const char *message_string, + const char *default_user, + const char *default_domain, + GAskPasswordFlags flags, + gboolean *aborted_out, + char **password_out, + char **user_out, + char **domain_out, + gboolean *anonymous_out, + GPasswordSave *password_save_out) +{ + gboolean handled; + AskSyncData data = {NULL}; + + data.mutex = g_mutex_new (); + data.cond = g_cond_new (); + + g_mutex_lock (data.mutex); + + + g_mount_source_ask_password_async (source, + message_string, + default_user, + default_domain, + flags, + ask_reply_sync, + &data); + + g_cond_wait(data.cond, data.mutex); + g_mutex_unlock (data.mutex); + + g_cond_free (data.cond); + g_mutex_free (data.mutex); + + + handled = g_mount_source_ask_password_finish (source, + data.result, + aborted_out, + password_out, + user_out, + domain_out, + anonymous_out, + password_save_out); + g_object_unref (data.result); + + return handled; +} + +static void +op_ask_password_reply (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GMountOperationResult result; + GMountOperation *op; + GMountSource *source; + gboolean handled, aborted; + char *username; + char *password; + char *domain; + GPasswordSave password_save; + + source = G_MOUNT_SOURCE (source_object); + op = G_MOUNT_OPERATION (user_data); + username = NULL; + password = NULL; + domain = NULL; + + handled = g_mount_source_ask_password_finish (source, + res, + &aborted, + &username, + &password, + &domain, + NULL, + &password_save); + + if (!handled) + result = G_MOUNT_OPERATION_UNHANDLED; + else if (aborted) + result = G_MOUNT_OPERATION_ABORTED; + else + { + result = G_MOUNT_OPERATION_HANDLED; + + if (password) + g_mount_operation_set_password (op, password); + if (username) + g_mount_operation_set_username (op, username); + if (domain) + g_mount_operation_set_domain (op, domain); + g_mount_operation_set_password_save (op, password_save); + } + + g_mount_operation_reply (op, result); + g_object_unref (op); +} + +static gboolean +op_ask_password (GMountOperation *op, + const char *message, + const char *default_user, + const char *default_domain, + GAskPasswordFlags flags, + GMountSource *mount_source) +{ + g_mount_source_ask_password_async (mount_source, + message, + default_user, + default_domain, + flags, + op_ask_password_reply, + g_object_ref (op)); + return TRUE; +} + +typedef struct AskQuestionData AskQuestionData; + +struct AskQuestionData { + + /* results: */ + gboolean aborted; + guint32 choice; +}; + +/* the callback from dbus -> main thread */ +static void +ask_question_reply (DBusMessage *reply, + GError *error, + gpointer _data) +{ + GSimpleAsyncResult *result; + AskQuestionData *data; + dbus_bool_t handled, aborted; + guint32 choice; + DBusMessageIter iter; + + result = G_SIMPLE_ASYNC_RESULT (_data); + handled = TRUE; + + data = g_new0 (AskQuestionData, 1); + g_simple_async_result_set_op_res_gpointer (result, data, g_free); + + if (reply == NULL) + { + data->aborted = TRUE; + } + else + { + dbus_message_iter_init (reply, &iter); + if (!_g_dbus_message_iter_get_args (&iter, NULL, + DBUS_TYPE_BOOLEAN, &handled, + DBUS_TYPE_BOOLEAN, &aborted, + DBUS_TYPE_UINT32, &choice, + 0)) + data->aborted = TRUE; + else + { + data->aborted = aborted; + data->choice = choice; + } + } + + if (handled == FALSE) + { + g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, "Internal Error"); + } + + g_simple_async_result_complete (result); +} + +gboolean +g_mount_source_ask_question (GMountSource *source, + const char *message, + const char **choices, + gint n_choices, + gboolean *aborted_out, + gint *choice_out) +{ + gint choice; + gboolean handled, aborted; + AskSyncData data = {NULL}; + + data.mutex = g_mutex_new (); + data.cond = g_cond_new (); + + g_mutex_lock (data.mutex); + + g_mount_source_ask_question_async (source, + message, + choices, + n_choices, + ask_reply_sync, + &data); + + g_cond_wait(data.cond, data.mutex); + g_mutex_unlock (data.mutex); + + g_cond_free (data.cond); + g_mutex_free (data.mutex); + + handled = g_mount_source_ask_question_finish (source, + data.result, + &aborted, + &choice); + + g_object_unref (data.result); + + if (aborted_out) + *aborted_out = aborted; + + if (choice_out) + *choice_out = choice; + + return handled; +} + +void +g_mount_source_ask_question_async (GMountSource *source, + const char *message_string, + const char **choices, + gint n_choices, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + DBusMessage *message; + + /* If no dbus id specified, reply that we weren't handled */ + if (source->dbus_id[0] == 0) + { + g_simple_async_report_error_in_idle (G_OBJECT (source), + callback, + user_data, + G_IO_ERROR, G_IO_ERROR_FAILED, + "Internal Error"); + return; + } + + if (message_string == NULL) + message_string = ""; + + message = dbus_message_new_method_call (source->dbus_id, + source->obj_path, + G_VFS_DBUS_MOUNT_OPERATION_INTERFACE, + G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_QUESTION); + + _g_dbus_message_append_args (message, + DBUS_TYPE_STRING, &message_string, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, + choices, n_choices, + 0); + + result = g_simple_async_result_new (G_OBJECT (source), callback, user_data, + g_mount_source_ask_question_async); + /* 30 minute timeout */ + _g_dbus_connection_call_async (NULL, message, 1000 * 60 * 30, + ask_question_reply, result); + dbus_message_unref (message); + +} + +gboolean +g_mount_source_ask_question_finish (GMountSource *source, + GAsyncResult *result, + gboolean *aborted, + gint *choice_out) +{ + AskQuestionData *data, def= { FALSE, }; + GSimpleAsyncResult *simple; + + simple = G_SIMPLE_ASYNC_RESULT (result); + + if (g_simple_async_result_propagate_error (simple, NULL)) + data = &def; + else + data = (AskQuestionData *) g_simple_async_result_get_op_res_gpointer (simple); + + if (aborted) + *aborted = data->aborted; + + if (choice_out) + *choice_out = data->choice; + + return data != &def; +} + +static void +op_ask_question_reply (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GMountOperationResult result; + GMountOperation *op; + GMountSource *source; + gboolean handled, aborted; + gint choice; + + source = G_MOUNT_SOURCE (source_object); + op = G_MOUNT_OPERATION (user_data); + + handled = g_mount_source_ask_question_finish (source, + res, + &aborted, + &choice); + + if (!handled) + result = G_MOUNT_OPERATION_UNHANDLED; + else if (aborted) + result = G_MOUNT_OPERATION_ABORTED; + else + { + result = G_MOUNT_OPERATION_HANDLED; + g_mount_operation_set_choice (op, choice); + } + + g_mount_operation_reply (op, result); + g_object_unref (op); +} + +static gboolean +op_ask_question (GMountOperation *op, + const char *message, + const char **choices, + gint n_choices, + GMountSource *mount_source) +{ + g_mount_source_ask_question_async (mount_source, + message, + choices, + n_choices, + op_ask_question_reply, + g_object_ref (op)); + return TRUE; +} + +GMountOperation * +g_mount_source_get_operation (GMountSource *mount_source) +{ + GMountOperation *op; + + op = g_mount_operation_new (); + g_object_set_data_full (G_OBJECT (op), "source", + g_object_ref (mount_source), + g_object_unref); + + + g_signal_connect (op, "ask_password", (GCallback)op_ask_password, mount_source); + g_signal_connect (op, "ask_question", (GCallback)op_ask_question, mount_source); + + return op; +} diff --git a/gnome-2-24/common/gmountsource.h b/gnome-2-24/common/gmountsource.h new file mode 100644 index 00000000..e4298357 --- /dev/null +++ b/gnome-2-24/common/gmountsource.h @@ -0,0 +1,115 @@ +/* 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_MOUNT_SOURCE_H__ +#define __G_MOUNT_SOURCE_H__ + +#include <glib-object.h> +#include <gmountspec.h> +#include <gio/gio.h> + +G_BEGIN_DECLS + +#define G_TYPE_MOUNT_SOURCE (g_mount_source_get_type ()) +#define G_MOUNT_SOURCE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_MOUNT_SOURCE, GMountSource)) +#define G_MOUNT_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_MOUNT_SOURCE, GMountSourceClass)) +#define G_IS_MOUNT_SOURCE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_MOUNT_SOURCE)) +#define G_IS_MOUNT_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_MOUNT_SOURCE)) +#define G_MOUNT_SOURCE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_MOUNT_SOURCE, GMountSourceClass)) + +typedef struct _GMountSource GMountSource; +typedef struct _GMountSourceClass GMountSourceClass; + +struct _GMountSourceClass +{ + GObjectClass parent_class; +}; + +typedef void (*RequestMountSpecCallback) (GMountSource *source, + GMountSpec *mount_spec, + GError *error, + gpointer data); + +GType g_mount_source_get_type (void) G_GNUC_CONST; + +GMountSource *g_mount_source_new (const char *dbus_id, + const char *obj_path); +GMountSource *g_mount_source_new_dummy (void); +void g_mount_source_to_dbus (GMountSource *source, + DBusMessage *message); +gboolean g_mount_source_ask_password (GMountSource *mount_source, + const char *message, + const char *initial_user, + const char *initial_domain, + GAskPasswordFlags flags, + gboolean *aborted, + char **password_out, + char **user_out, + char **domain_out, + gboolean *anonymous_out, + GPasswordSave *password_save_out); + +void g_mount_source_ask_password_async (GMountSource *mount_source, + const char *message, + const char *initial_user, + const char *initial_domain, + GAskPasswordFlags flags, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean g_mount_source_ask_password_finish (GMountSource *source, + GAsyncResult *result, + gboolean *aborted, + char **password_out, + char **user_out, + char **domain_out, + gboolean *anonymous_out, + GPasswordSave *password_save_out); + +gboolean g_mount_source_ask_question (GMountSource *mount_source, + const char *message, + const char **choices, + gint n_choices, + gboolean *aborted, + gint *choice_out); + +void g_mount_source_ask_question_async (GMountSource *mount_source, + const char *message, + const char **choices, + gint n_choices, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean g_mount_source_ask_question_finish (GMountSource *source, + GAsyncResult *result, + gboolean *aborted, + gint *choice_out); + + +const char * g_mount_source_get_dbus_id (GMountSource *mount_source); +const char * g_mount_source_get_obj_path (GMountSource *mount_source); + +GMountOperation *g_mount_source_get_operation (GMountSource *mount_source); + +G_END_DECLS + +#endif /* __G_MOUNT_SOURCE_H__ */ diff --git a/gnome-2-24/common/gmountspec.c b/gnome-2-24/common/gmountspec.c new file mode 100644 index 00000000..7d8fa57e --- /dev/null +++ b/gnome-2-24/common/gmountspec.c @@ -0,0 +1,534 @@ +/* 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 <stdlib.h> + +#include <glib/gi18n-lib.h> + +#include "gdbusutils.h" +#include "gmountspec.h" + +static GHashTable *unique_hash = NULL; +G_LOCK_DEFINE_STATIC(unique_hash); + +static int +item_compare (const void *_a, const void *_b) +{ + const GMountSpecItem *a = _a; + const GMountSpecItem *b = _b; + + return strcmp (a->key, b->key); +} + +GMountSpec * +g_mount_spec_new (const char *type) +{ + GMountSpec *spec; + + spec = g_new0 (GMountSpec, 1); + spec->ref_count = 1; + spec->items = g_array_new (FALSE, TRUE, sizeof (GMountSpecItem)); + spec->mount_prefix = g_strdup ("/"); + + if (type != NULL) + g_mount_spec_set (spec, "type", type); + + return spec; +} + +/* Takes ownership of passed in data */ +GMountSpec * +g_mount_spec_new_from_data (GArray *items, + char *mount_prefix) +{ + GMountSpec *spec; + + spec = g_new0 (GMountSpec, 1); + spec->ref_count = 1; + spec->items = items; + if (mount_prefix == NULL) + spec->mount_prefix = g_strdup ("/"); + else + spec->mount_prefix = mount_prefix; + + g_array_sort (spec->items, item_compare); + + return spec; +} + +GMountSpec * +g_mount_spec_get_unique_for (GMountSpec *spec) +{ + GMountSpec *unique_spec; + + if (spec->is_unique) + return g_mount_spec_ref (spec); + + G_LOCK (unique_hash); + + if (unique_hash == NULL) + unique_hash = g_hash_table_new (g_mount_spec_hash, (GEqualFunc)g_mount_spec_equal); + + unique_spec = g_hash_table_lookup (unique_hash, spec); + + if (unique_spec == NULL) + { + spec->is_unique = TRUE; + g_hash_table_insert (unique_hash, spec, spec); + unique_spec = spec; + } + + g_mount_spec_ref (unique_spec); + + G_UNLOCK (unique_hash); + + return unique_spec; +} + +void +g_mount_spec_set_mount_prefix (GMountSpec *spec, + const char *mount_prefix) +{ + g_free (spec->mount_prefix); + spec->mount_prefix = g_strdup (mount_prefix); +} + + +static void +add_item (GMountSpec *spec, + const char *key, + char *value) +{ + GMountSpecItem item; + + g_return_if_fail (key != NULL); + g_return_if_fail (value != NULL); + + item.key = g_strdup (key); + item.value = value; + + g_array_append_val (spec->items, item); +} + + +void +g_mount_spec_set_with_len (GMountSpec *spec, + const char *key, + const char *value, + int value_len) +{ + int i; + char *value_copy; + + g_return_if_fail (key != NULL); + g_return_if_fail (value != NULL); + + if (value_len == -1) + value_copy = g_strdup (value); + else + value_copy = g_strndup (value, value_len); + + for (i = 0; i < spec->items->len; i++) + { + GMountSpecItem *item = &g_array_index (spec->items, GMountSpecItem, i); + if (strcmp (item->key, key) == 0) + { + g_free (item->value); + item->value = value_copy; + return; + } + } + + add_item (spec, key, value_copy); + g_array_sort (spec->items, item_compare); +} + +void +g_mount_spec_set (GMountSpec *spec, + const char *key, + const char *value) +{ + g_mount_spec_set_with_len (spec, key, value, -1); +} + + +GMountSpec * +g_mount_spec_copy (GMountSpec *spec) +{ + GMountSpec *copy; + int i; + + copy = g_mount_spec_new (NULL); + g_mount_spec_set_mount_prefix (copy, spec->mount_prefix); + + for (i = 0; i < spec->items->len; i++) + { + GMountSpecItem *item = &g_array_index (spec->items, GMountSpecItem, i); + g_mount_spec_set (copy, item->key, item->value); + } + + return copy; +} + +GMountSpec * +g_mount_spec_ref (GMountSpec *spec) +{ + g_atomic_int_inc (&spec->ref_count); + return spec; +} + + +void +g_mount_spec_unref (GMountSpec *spec) +{ + int i; + + if (g_atomic_int_dec_and_test (&spec->ref_count)) + { + G_LOCK (unique_hash); + if (unique_hash != NULL && + spec->is_unique) + g_hash_table_remove (unique_hash, spec); + G_UNLOCK (unique_hash); + + g_free (spec->mount_prefix); + for (i = 0; i < spec->items->len; i++) + { + GMountSpecItem *item = &g_array_index (spec->items, GMountSpecItem, i); + g_free (item->key); + g_free (item->value); + } + g_array_free (spec->items, TRUE); + + g_free (spec); + } +} + +GMountSpec * +g_mount_spec_from_dbus (DBusMessageIter *iter) +{ + GMountSpec *spec; + DBusMessageIter array_iter, struct_iter, spec_iter; + const char *key; + char *value; + char *mount_prefix; + + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRUCT) + return NULL; + + dbus_message_iter_recurse (iter, &spec_iter); + + mount_prefix = NULL; + if (!_g_dbus_message_iter_get_args (&spec_iter, NULL, + G_DBUS_TYPE_CSTRING, &mount_prefix, + 0)) + return NULL; + + spec = g_mount_spec_new (NULL); + g_free (spec->mount_prefix); + spec->mount_prefix = mount_prefix; + + if (dbus_message_iter_get_arg_type (&spec_iter) != DBUS_TYPE_ARRAY || + dbus_message_iter_get_element_type (&spec_iter) != DBUS_TYPE_STRUCT) + { + g_mount_spec_unref (spec); + return NULL; + } + + dbus_message_iter_recurse (&spec_iter, &array_iter); + while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT) + { + dbus_message_iter_recurse (&array_iter, &struct_iter); + if (_g_dbus_message_iter_get_args (&struct_iter, NULL, + DBUS_TYPE_STRING, &key, + G_DBUS_TYPE_CSTRING, &value, + 0)) + add_item (spec, key, value); + dbus_message_iter_next (&array_iter); + } + + dbus_message_iter_next (iter); + + /* Sort on key */ + g_array_sort (spec->items, item_compare); + + return spec; +} + +void +g_mount_spec_to_dbus_with_path (DBusMessageIter *iter, + GMountSpec *spec, + const char *path) +{ + DBusMessageIter spec_iter, array_iter, item_iter; + int i; + + if (!dbus_message_iter_open_container (iter, + DBUS_TYPE_STRUCT, + NULL, + &spec_iter)) + _g_dbus_oom (); + + _g_dbus_message_iter_append_cstring (&spec_iter, path ? path : ""); + + if (!dbus_message_iter_open_container (&spec_iter, + DBUS_TYPE_ARRAY, + G_MOUNT_SPEC_ITEM_TYPE_AS_STRING, + &array_iter)) + _g_dbus_oom (); + + for (i = 0; i < spec->items->len; i++) + { + GMountSpecItem *item = &g_array_index (spec->items, GMountSpecItem, i); + + if (!dbus_message_iter_open_container (&array_iter, + DBUS_TYPE_STRUCT, + NULL, + &item_iter)) + _g_dbus_oom (); + + if (!dbus_message_iter_append_basic (&item_iter, DBUS_TYPE_STRING, + &item->key)) + _g_dbus_oom (); + _g_dbus_message_iter_append_cstring (&item_iter, item->value); + + if (!dbus_message_iter_close_container (&array_iter, &item_iter)) + _g_dbus_oom (); + + } + + if (!dbus_message_iter_close_container (&spec_iter, &array_iter)) + _g_dbus_oom (); + + + + if (!dbus_message_iter_close_container (iter, &spec_iter)) + _g_dbus_oom (); + +} + +void +g_mount_spec_to_dbus (DBusMessageIter *iter, + GMountSpec *spec) +{ + g_mount_spec_to_dbus_with_path (iter, spec, spec->mount_prefix); +} + +static gboolean +items_equal (GArray *a, + GArray *b) +{ + int i; + + if (a->len != b->len) + return FALSE; + + for (i = 0; i < a->len; i++) + { + GMountSpecItem *item_a = &g_array_index (a, GMountSpecItem, i); + GMountSpecItem *item_b = &g_array_index (b, GMountSpecItem, i); + + if (strcmp (item_a->key, item_b->key) != 0) + return FALSE; + if (strcmp (item_a->value, item_b->value) != 0) + return FALSE; + } + + return TRUE; +} + +static gboolean +path_has_prefix (const char *path, + const char *prefix) +{ + int prefix_len; + + if (prefix == NULL) + return TRUE; + + prefix_len = strlen (prefix); + + if (strncmp (path, prefix, prefix_len) == 0 && + (prefix_len == 0 || /* empty prefix always matches */ + prefix[prefix_len - 1] == '/' || /* last char in prefix was a /, so it must be in path too */ + path[prefix_len] == 0 || + path[prefix_len] == '/')) + return TRUE; + + return FALSE; +} + +guint +g_mount_spec_hash (gconstpointer _mount) +{ + GMountSpec *mount = (GMountSpec *) _mount; + guint hash; + int i; + + hash = 0; + if (mount->mount_prefix) + hash ^= g_str_hash (mount->mount_prefix); + + for (i = 0; i < mount->items->len; i++) + { + GMountSpecItem *item = &g_array_index (mount->items, GMountSpecItem, i); + hash ^= g_str_hash (item->value); + } + + return hash; +} + +gboolean +g_mount_spec_equal (GMountSpec *mount1, + GMountSpec *mount2) +{ + return items_equal (mount1->items, mount2->items) && + ((mount1->mount_prefix == mount2->mount_prefix) || + (mount1->mount_prefix != NULL && mount2->mount_prefix != NULL && + strcmp (mount1->mount_prefix, mount2->mount_prefix) == 0)); +} + +gboolean +g_mount_spec_match_with_path (GMountSpec *mount, + GMountSpec *spec, + const char *path) +{ + if (items_equal (mount->items, spec->items) && + path_has_prefix (path, mount->mount_prefix)) + return TRUE; + return FALSE; +} + +gboolean +g_mount_spec_match (GMountSpec *mount, + GMountSpec *path) +{ + return g_mount_spec_match_with_path (mount, path, path->mount_prefix); +} + +const char * +g_mount_spec_get (GMountSpec *spec, + const char *key) +{ + int i; + + for (i = 0; i < spec->items->len; i++) + { + GMountSpecItem *item = &g_array_index (spec->items, GMountSpecItem, i); + + if (strcmp (item->key, key) == 0) + return item->value; + } + + return NULL; +} + +const char * +g_mount_spec_get_type (GMountSpec *spec) +{ + return g_mount_spec_get (spec, "type"); +} + +char * +g_mount_spec_to_string (GMountSpec *spec) +{ + GString *str; + int i; + + if (spec == NULL) + return g_strdup ("(null)"); + + str = g_string_new (""); + + for (i = 0; i < spec->items->len; i++) + { + GMountSpecItem *item = &g_array_index (spec->items, GMountSpecItem, i); + + g_string_append_printf (str, "%s='%s',", item->key, item->value); + } + g_string_append_printf (str, "mount_prefix='%s'", spec->mount_prefix); + + return g_string_free (str, FALSE); +} + +char * +g_mount_spec_canonicalize_path (const char *path) +{ + char *canon, *start, *p, *q; + + if (*path != '/') + canon = g_strconcat ("/", path, NULL); + else + canon = g_strdup (path); + + /* Skip initial slash */ + start = canon + 1; + + p = start; + while (*p != 0) + { + if (p[0] == '.' && (p[1] == 0 || p[1] == '/')) + { + memmove (p, p+1, strlen (p+1)+1); + } + else if (p[0] == '.' && p[1] == '.' && (p[2] == 0 || p[2] == '/')) + { + q = p + 2; + /* Skip previous separator */ + p = p - 2; + if (p < start) + p = start; + while (p > start && *p != '/') + p--; + if (*p == '/') + p++; + memmove (p, q, strlen (q)+1); + } + else + { + /* Skip until next separator */ + while (*p != 0 && *p != '/') + p++; + + /* Keep one separator */ + if (*p != 0) + p++; + } + + /* Remove additional separators */ + q = p; + while (*q && *q == '/') + q++; + + if (p != q) + memmove (p, q, strlen (q)+1); + } + + /* Remove trailing slashes */ + if (p > start && *(p-1) == '/') + *(p-1) = 0; + + return canon; +} diff --git a/gnome-2-24/common/gmountspec.h b/gnome-2-24/common/gmountspec.h new file mode 100644 index 00000000..55ac5c63 --- /dev/null +++ b/gnome-2-24/common/gmountspec.h @@ -0,0 +1,103 @@ +/* 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_MOUNT_SPEC_H__ +#define __G_MOUNT_SPEC_H__ + +#include <glib.h> +#include <dbus/dbus.h> + +G_BEGIN_DECLS + +#define G_MOUNT_SPEC_ITEM_INNER_TYPE_AS_STRING \ + DBUS_TYPE_STRING_AS_STRING \ + DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING + +#define G_MOUNT_SPEC_ITEM_TYPE_AS_STRING \ + DBUS_STRUCT_BEGIN_CHAR_AS_STRING \ + G_MOUNT_SPEC_ITEM_INNER_TYPE_AS_STRING \ + DBUS_STRUCT_END_CHAR_AS_STRING + +#define G_MOUNT_SPEC_INNER_TYPE_AS_STRING \ + DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING \ + DBUS_TYPE_ARRAY_AS_STRING G_MOUNT_SPEC_ITEM_TYPE_AS_STRING + +#define G_MOUNT_SPEC_TYPE_AS_STRING \ + DBUS_STRUCT_BEGIN_CHAR_AS_STRING \ + G_MOUNT_SPEC_INNER_TYPE_AS_STRING \ + DBUS_STRUCT_END_CHAR_AS_STRING + +typedef struct { + char *key; + char *value; +} GMountSpecItem; + +typedef struct { + volatile int ref_count; + GArray *items; + char *mount_prefix; + gboolean is_unique; +} GMountSpec; + +GMountSpec *g_mount_spec_new (const char *type); +GMountSpec *g_mount_spec_new_from_data (GArray *items, + char *mount_prefix); +GMountSpec *g_mount_spec_ref (GMountSpec *spec); +void g_mount_spec_unref (GMountSpec *spec); +GMountSpec *g_mount_spec_get_unique_for (GMountSpec *spec); +GMountSpec *g_mount_spec_copy (GMountSpec *spec); +GMountSpec *g_mount_spec_from_dbus (DBusMessageIter *iter); +void g_mount_spec_to_dbus (DBusMessageIter *iter, + GMountSpec *spec); +void g_mount_spec_to_dbus_with_path (DBusMessageIter *iter, + GMountSpec *spec, + const char *path); +void g_mount_spec_set_mount_prefix (GMountSpec *spec, + const char *mount_prefix); +void g_mount_spec_set (GMountSpec *spec, + const char *key, + const char *value); +void g_mount_spec_set_with_len (GMountSpec *spec, + const char *key, + const char *value, + int value_len); +guint g_mount_spec_hash (gconstpointer mount); +gboolean g_mount_spec_equal (GMountSpec *mount1, + GMountSpec *mount2); +gboolean g_mount_spec_match (GMountSpec *mount, + GMountSpec *path); +gboolean g_mount_spec_match_with_path (GMountSpec *mount, + GMountSpec *spec, + const char *path); +const char *g_mount_spec_get (GMountSpec *spec, + const char *key); +const char *g_mount_spec_get_type (GMountSpec *spec); + +/* For debugging */ +char * g_mount_spec_to_string (GMountSpec *spec); + +char * g_mount_spec_canonicalize_path (const char *path); + +G_END_DECLS + + +#endif /* __G_MOUNT_SPEC_H__ */ diff --git a/gnome-2-24/common/gmounttracker.c b/gnome-2-24/common/gmounttracker.c new file mode 100644 index 00000000..eba29ef5 --- /dev/null +++ b/gnome-2-24/common/gmounttracker.c @@ -0,0 +1,621 @@ +/* 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 <gmounttracker.h> +#include <gdbusutils.h> +#include <gvfsdaemonprotocol.h> + +enum { + MOUNTED, + UNMOUNTED, + LAST_SIGNAL +}; + +enum { + PROP_0, + PROP_CONNECTION +}; + +/* TODO: Real P_() */ +#define P_(_x) (_x) +#define I_(string) g_intern_static_string (string) + +static guint signals[LAST_SIGNAL] = { 0 }; + +struct _GMountTracker +{ + GObject parent_instance; + + GMutex *lock; + GList *mounts; + DBusConnection *connection; +}; + +G_DEFINE_TYPE (GMountTracker, g_mount_tracker, G_TYPE_OBJECT) + +static DBusHandlerResult g_mount_tracker_filter_func (DBusConnection *conn, + DBusMessage *message, + gpointer data); +static GObject* g_mount_tracker_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_params); +static void g_mount_tracker_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void g_mount_tracker_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +gboolean +g_mount_info_equal (GMountInfo *info1, + GMountInfo *info2) +{ + return + strcmp (info1->dbus_id, info2->dbus_id) == 0 && + strcmp (info1->object_path, info2->object_path) == 0; +} + +GMountInfo * +g_mount_info_dup (GMountInfo *info) +{ + GMountInfo *copy; + + copy = g_new (GMountInfo, 1); + copy->ref_count = 1; + copy->display_name = g_strdup (info->display_name); + copy->stable_name = g_strdup (info->stable_name); + copy->x_content_types = g_strdup (info->x_content_types); + copy->icon = g_strdup (info->icon); + copy->dbus_id = g_strdup (info->dbus_id); + copy->object_path = g_strdup (info->object_path); + copy->mount_spec = g_mount_spec_copy (info->mount_spec); + copy->user_visible = info->user_visible; + copy->prefered_filename_encoding = g_strdup (info->prefered_filename_encoding); + copy->fuse_mountpoint = g_strdup (info->fuse_mountpoint); + + return copy; +} + +GMountInfo * +g_mount_info_ref (GMountInfo *info) +{ + g_atomic_int_inc (&info->ref_count); + return info; +} + +void +g_mount_info_unref (GMountInfo *info) +{ + if (g_atomic_int_dec_and_test (&info->ref_count)) + { + g_free (info->display_name); + g_free (info->stable_name); + g_free (info->x_content_types); + g_free (info->icon); + g_free (info->dbus_id); + g_free (info->object_path); + g_mount_spec_unref (info->mount_spec); + g_free (info->prefered_filename_encoding); + g_free (info->fuse_mountpoint); + g_free (info); + } +} + +const char * +g_mount_info_resolve_path (GMountInfo *info, + const char *path) +{ + const char *new_path; + int len; + + if (info->mount_spec->mount_prefix != NULL && + info->mount_spec->mount_prefix[0] != 0) + { + len = strlen (info->mount_spec->mount_prefix); + if (info->mount_spec->mount_prefix[len-1] == '/') + len--; + new_path = path + len; + } + else + new_path = path; + + if (new_path == NULL || + new_path[0] == 0) + new_path = "/"; + + return new_path; +} + +GMountInfo * +g_mount_info_from_dbus (DBusMessageIter *iter) +{ + DBusMessageIter struct_iter; + GMountInfo *info; + GMountSpec *mount_spec; + dbus_bool_t user_visible; + char *display_name; + char *stable_name; + char *x_content_types; + char *icon; + char *prefered_filename_encoding; + char *dbus_id; + char *obj_path; + char *fuse_mountpoint; + + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRUCT) + return NULL; + + dbus_message_iter_recurse (iter, &struct_iter); + + if (!_g_dbus_message_iter_get_args (&struct_iter, NULL, + DBUS_TYPE_STRING, &dbus_id, + DBUS_TYPE_OBJECT_PATH, &obj_path, + DBUS_TYPE_STRING, &display_name, + DBUS_TYPE_STRING, &stable_name, + DBUS_TYPE_STRING, &x_content_types, + DBUS_TYPE_STRING, &icon, + DBUS_TYPE_STRING, &prefered_filename_encoding, + DBUS_TYPE_BOOLEAN, &user_visible, + G_DBUS_TYPE_CSTRING, &fuse_mountpoint, + 0)) + return NULL; + + mount_spec = g_mount_spec_from_dbus (&struct_iter); + if (mount_spec == NULL) { + g_free (fuse_mountpoint); + return NULL; + } + + info = g_new0 (GMountInfo, 1); + info->ref_count = 1; + info->display_name = g_strdup (display_name); + info->stable_name = g_strdup (stable_name); + info->x_content_types = g_strdup (x_content_types); + info->icon = g_strdup (icon); + info->dbus_id = g_strdup (dbus_id); + info->object_path = g_strdup (obj_path); + info->mount_spec = mount_spec; + info->user_visible = user_visible; + info->prefered_filename_encoding = g_strdup (prefered_filename_encoding); + info->fuse_mountpoint = fuse_mountpoint; + + return info; +} + + +static void +g_mount_tracker_finalize (GObject *object) +{ + GMountTracker *tracker; + + tracker = G_MOUNT_TRACKER (object); + + if (tracker->lock) + g_mutex_free (tracker->lock); + + g_list_foreach (tracker->mounts, + (GFunc)g_mount_info_unref, NULL); + g_list_free (tracker->mounts); + + dbus_connection_remove_filter (tracker->connection, g_mount_tracker_filter_func, tracker); + + + dbus_bus_remove_match (tracker->connection, + "sender='"G_VFS_DBUS_DAEMON_NAME"'," + "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"'," + "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED"'", + NULL); + dbus_bus_remove_match (tracker->connection, + "sender='"G_VFS_DBUS_DAEMON_NAME"'," + "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"'," + "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_UNMOUNTED"'", + NULL); + + dbus_connection_unref (tracker->connection); + + if (G_OBJECT_CLASS (g_mount_tracker_parent_class)->finalize) + (*G_OBJECT_CLASS (g_mount_tracker_parent_class)->finalize) (object); +} + +static void +g_mount_tracker_class_init (GMountTrackerClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = g_mount_tracker_finalize; + gobject_class->constructor = g_mount_tracker_constructor; + gobject_class->set_property = g_mount_tracker_set_property; + gobject_class->get_property = g_mount_tracker_get_property; + + signals[MOUNTED] = g_signal_new (I_("mounted"), + G_TYPE_MOUNT_TRACKER, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GMountTrackerClass, mounted), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + + signals[UNMOUNTED] = g_signal_new (I_("unmounted"), + G_TYPE_MOUNT_TRACKER, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GMountTrackerClass, unmounted), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + + g_object_class_install_property (gobject_class, + PROP_CONNECTION, + g_param_spec_pointer ("connection", + P_("DBus connection"), + P_("The dbus connection to use for ipc."), + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); + +} + +static void +g_mount_tracker_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GMountTracker *tracker = G_MOUNT_TRACKER (object); + + switch (prop_id) + { + case PROP_CONNECTION: + if (tracker->connection) + dbus_connection_unref (tracker->connection); + tracker->connection = NULL; + if (g_value_get_pointer (value)) + tracker->connection = dbus_connection_ref (g_value_get_pointer (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +g_mount_tracker_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GMountTracker *tracker = G_MOUNT_TRACKER (object); + + switch (prop_id) + { + case PROP_CONNECTION: + g_value_set_pointer (value, tracker->connection); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GList * +g_mount_tracker_find (GMountTracker *tracker, + GMountInfo *info) +{ + GList *l; + + for (l = tracker->mounts; l != NULL; l = l->next) + { + if (g_mount_info_equal (info, (GMountInfo *)l->data)) + return l; + } + + return NULL; +} + +static void +g_mount_tracker_add_mount (GMountTracker *tracker, + GMountInfo *info) +{ + if (tracker->lock) + g_mutex_lock (tracker->lock); + + /* Don't add multiple times */ + if (g_mount_tracker_find (tracker, info)) + { + if (tracker->lock) + g_mutex_unlock (tracker->lock); + return; + } + + tracker->mounts = g_list_prepend (tracker->mounts, g_mount_info_ref (info)); + + if (tracker->lock) + g_mutex_unlock (tracker->lock); + + g_signal_emit (tracker, signals[MOUNTED], 0, info); +} + +static void +g_mount_tracker_remove_mount (GMountTracker *tracker, + GMountInfo *info) +{ + GList *l; + GMountInfo *old_info; + + if (tracker->lock) + g_mutex_lock (tracker->lock); + + l = g_mount_tracker_find (tracker, info); + + /* Don't remove multiple times */ + if (l == NULL) + { + if (tracker->lock) + g_mutex_unlock (tracker->lock); + return; + } + + old_info = l->data; + + tracker->mounts = g_list_delete_link (tracker->mounts, l); + + if (tracker->lock) + g_mutex_unlock (tracker->lock); + + g_signal_emit (tracker, signals[UNMOUNTED], 0, old_info); + g_mount_info_unref (old_info); +} + +static void +list_mounts_reply (GMountTracker *tracker, + DBusMessage *reply) +{ + DBusMessageIter iter, array_iter; + GMountInfo *info; + gboolean b; + + b = dbus_message_iter_init (reply, &iter); + if (b && dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY) + { + dbus_message_iter_recurse (&iter, &array_iter); + + do + { + info = g_mount_info_from_dbus (&array_iter); + if (info) + { + g_mount_tracker_add_mount (tracker, info); + g_mount_info_unref (info); + } + } + while (dbus_message_iter_next (&array_iter)); + } + else + { + /* list_mounts_reply problem - gvfsd not running? */ + } +} + +static DBusHandlerResult +g_mount_tracker_filter_func (DBusConnection *conn, + DBusMessage *message, + gpointer data) +{ + GMountTracker *tracker = data; + GMountInfo *info; + DBusMessageIter iter; + + if (dbus_message_is_signal (message, + G_VFS_DBUS_MOUNTTRACKER_INTERFACE, + G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED)) + { + dbus_message_iter_init (message, &iter); + info = g_mount_info_from_dbus (&iter); + + if (info) + { + g_mount_tracker_add_mount (tracker, info); + g_mount_info_unref (info); + } + } + else if (dbus_message_is_signal (message, + G_VFS_DBUS_MOUNTTRACKER_INTERFACE, + G_VFS_DBUS_MOUNTTRACKER_SIGNAL_UNMOUNTED)) + { + dbus_message_iter_init (message, &iter); + info = g_mount_info_from_dbus (&iter); + + if (info) + { + g_mount_tracker_remove_mount (tracker, info); + g_mount_info_unref (info); + } + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +/* Called after construction when the construct properties (like connection) are set */ +static void +init_connection (GMountTracker *tracker) +{ + DBusMessage *message, *reply; + + if (tracker->connection == NULL) + tracker->connection = dbus_bus_get (DBUS_BUS_SESSION, 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_LIST_MOUNTS); + if (message == NULL) + _g_dbus_oom (); + + dbus_message_set_auto_start (message, TRUE); + + reply = dbus_connection_send_with_reply_and_block (tracker->connection, message, + G_VFS_DBUS_TIMEOUT_MSECS, + NULL); + dbus_message_unref (message); + + if (reply != NULL) + { + list_mounts_reply (tracker, reply); + dbus_message_unref (reply); + } + + dbus_connection_add_filter (tracker->connection, g_mount_tracker_filter_func, tracker, NULL); + + dbus_bus_add_match (tracker->connection, + "sender='"G_VFS_DBUS_DAEMON_NAME"'," + "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"'," + "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED"'", + NULL); + dbus_bus_add_match (tracker->connection, + "sender='"G_VFS_DBUS_DAEMON_NAME"'," + "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"'," + "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_UNMOUNTED"'", + NULL); +} + +static void +g_mount_tracker_init (GMountTracker *tracker) +{ + if (g_thread_supported ()) + tracker->lock = g_mutex_new (); +} + + +static GObject* +g_mount_tracker_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_params) +{ + GObject *object; + GMountTracker *tracker; + + object = (* G_OBJECT_CLASS (g_mount_tracker_parent_class)->constructor) (type, + n_construct_properties, + construct_params); + + tracker = G_MOUNT_TRACKER (object); + + init_connection (tracker); + + return object; +} + +GMountTracker * +g_mount_tracker_new (DBusConnection *connection) +{ + GMountTracker *tracker; + + tracker = g_object_new (G_TYPE_MOUNT_TRACKER, "connection", connection, NULL); + + return tracker; +} + +GList * +g_mount_tracker_list_mounts (GMountTracker *tracker) +{ + GList *res, *l; + GMountInfo *copy; + + if (tracker->lock) + g_mutex_lock (tracker->lock); + + res = NULL; + for (l = tracker->mounts; l != NULL; l = l->next) + { + copy = g_mount_info_ref (l->data); + res = g_list_prepend (res, copy); + } + + if (tracker->lock) + g_mutex_unlock (tracker->lock); + + return g_list_reverse (res); +} + +GMountInfo * +g_mount_tracker_find_by_mount_spec (GMountTracker *tracker, + GMountSpec *mount_spec) +{ + GList *l; + GMountInfo *info, *found; + + if (tracker->lock) + g_mutex_lock (tracker->lock); + + found = NULL; + for (l = tracker->mounts; l != NULL; l = l->next) + { + info = l->data; + + if (g_mount_spec_equal (info->mount_spec, mount_spec)) + { + found = g_mount_info_ref (info); + break; + } + } + + if (tracker->lock) + g_mutex_unlock (tracker->lock); + + return found; +} + + +gboolean +g_mount_tracker_has_mount_spec (GMountTracker *tracker, + GMountSpec *mount_spec) +{ + GList *l; + GMountInfo *info; + gboolean found; + + if (tracker->lock) + g_mutex_lock (tracker->lock); + + found = FALSE; + for (l = tracker->mounts; l != NULL; l = l->next) + { + info = l->data; + + if (g_mount_spec_equal (info->mount_spec, mount_spec)) + { + found = TRUE; + break; + } + } + + if (tracker->lock) + g_mutex_unlock (tracker->lock); + + return found; +} + diff --git a/gnome-2-24/common/gmounttracker.h b/gnome-2-24/common/gmounttracker.h new file mode 100644 index 00000000..67c91ff1 --- /dev/null +++ b/gnome-2-24/common/gmounttracker.h @@ -0,0 +1,86 @@ +/* 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_MOUNT_TRACKER_H__ +#define __G_MOUNT_TRACKER_H__ + +#include <glib-object.h> +#include <gmountspec.h> + +G_BEGIN_DECLS + +#define G_TYPE_MOUNT_TRACKER (g_mount_tracker_get_type ()) +#define G_MOUNT_TRACKER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_MOUNT_TRACKER, GMountTracker)) +#define G_MOUNT_TRACKER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_MOUNT_TRACKER, GMountTrackerClass)) +#define G_IS_MOUNT_TRACKER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_MOUNT_TRACKER)) +#define G_IS_MOUNT_TRACKER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_MOUNT_TRACKER)) +#define G_MOUNT_TRACKER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_MOUNT_TRACKER, GMountTrackerClass)) + +typedef struct _GMountTracker GMountTracker; +typedef struct _GMountTrackerClass GMountTrackerClass; + +typedef struct { + volatile int ref_count; + char *display_name; + char *stable_name; + char *x_content_types; + char *icon; + char *dbus_id; + char *object_path; + gboolean user_visible; + char *prefered_filename_encoding; /* NULL -> UTF8 */ + char *fuse_mountpoint; + GMountSpec *mount_spec; +} GMountInfo; + +struct _GMountTrackerClass +{ + GObjectClass parent_class; + + void (*mounted) (GMountTracker *tracker, + GMountInfo *info); + void (*unmounted) (GMountTracker *tracker, + GMountInfo *info); +}; + +GType g_mount_tracker_get_type (void) G_GNUC_CONST; + +gboolean g_mount_info_equal (GMountInfo *info1, + GMountInfo *info2); +GMountInfo *g_mount_info_ref (GMountInfo *info); +GMountInfo *g_mount_info_dup (GMountInfo *info); +void g_mount_info_unref (GMountInfo *info); +const char *g_mount_info_resolve_path (GMountInfo *info, + const char *path); + +GMountInfo * g_mount_info_from_dbus (DBusMessageIter *iter); + +GMountTracker *g_mount_tracker_new (DBusConnection *connection); +GList * g_mount_tracker_list_mounts (GMountTracker *tracker); +GMountInfo * g_mount_tracker_find_by_mount_spec (GMountTracker *tracker, + GMountSpec *mount_spec); +gboolean g_mount_tracker_has_mount_spec (GMountTracker *tracker, + GMountSpec *mount_spec); + +G_END_DECLS + +#endif /* __G_MOUNT_TRACKER_H__ */ diff --git a/gnome-2-24/common/gsysutils.c b/gnome-2-24/common/gsysutils.c new file mode 100644 index 00000000..9dd8afa4 --- /dev/null +++ b/gnome-2-24/common/gsysutils.c @@ -0,0 +1,181 @@ +/* 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> + +#if defined(HAVE_SYS_PARAM_H) +#include <sys/param.h> +#endif +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#include <sys/socket.h> +#include <sys/un.h> +#include <stdio.h> +#include <string.h> +#include <strings.h> +#include <errno.h> +#include <unistd.h> +#ifdef HAVE_SYS_UIO_H +#include <sys/uio.h> +#endif +#include <gio/gio.h> + +#include <glib/gi18n-lib.h> + +#include "gsysutils.h" + +int +_g_socket_send_fd (int connection_fd, + int fd) +{ + struct msghdr msg; + struct iovec vec[1]; + char buf[1] = {'x'}; + char ccmsg[CMSG_SPACE (sizeof (fd))]; + struct cmsghdr *cmsg; + int ret; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + + vec[0].iov_base = buf; + vec[0].iov_len = 1; + msg.msg_iov = vec; + msg.msg_iovlen = 1; + msg.msg_control = ccmsg; + msg.msg_controllen = sizeof (ccmsg); + cmsg = CMSG_FIRSTHDR (&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN (sizeof(fd)); + *(int*)CMSG_DATA (cmsg) = fd; + msg.msg_controllen = cmsg->cmsg_len; + msg.msg_flags = 0; + + ret = sendmsg (connection_fd, &msg, 0); + return ret; +} + +/* receive a file descriptor over file descriptor fd */ +int +_g_socket_receive_fd (int socket_fd) +{ + struct msghdr msg; + struct iovec iov[1]; + char buf[1]; + int rv; + char ccmsg[CMSG_SPACE (sizeof(int))]; + struct cmsghdr *cmsg; + + iov[0].iov_base = buf; + iov[0].iov_len = 1; + msg.msg_name = 0; + msg.msg_namelen = 0; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_control = ccmsg; + msg.msg_controllen = sizeof (ccmsg); + + rv = recvmsg (socket_fd, &msg, 0); + if (rv == -1) + { + perror ("recvmsg"); + return -1; + } + + cmsg = CMSG_FIRSTHDR (&msg); + if (cmsg == NULL) + return -1; + + if (!cmsg->cmsg_type == SCM_RIGHTS) { + g_warning("got control message of unknown type %d", + cmsg->cmsg_type); + return -1; + } + + return *(int*)CMSG_DATA(cmsg); +} + +int +_g_socket_connect (const char *address, + GError **error) +{ + int fd; + const char *path; + size_t path_len; + struct sockaddr_un addr; + gboolean abstract; + + fd = socket (PF_UNIX, SOCK_STREAM, 0); + if (fd == -1) + { + int errsv = errno; + + g_set_error (error, G_IO_ERROR, + g_io_error_from_errno (errsv), + _("Error creating socket: %s"), + g_strerror (errsv)); + return -1; + } + + if (g_str_has_prefix (address, "unix:abstract=")) + { + path = address + strlen ("unix:abstract="); + abstract = TRUE; + } + else + { + path = address + strlen ("unix:path="); + abstract = FALSE; + } + + memset (&addr, 0, sizeof (addr)); + addr.sun_family = AF_UNIX; + path_len = strlen (path); + + if (abstract) + { + addr.sun_path[0] = '\0'; /* this is what says "use abstract" */ + path_len++; /* Account for the extra nul byte added to the start of sun_path */ + + strncpy (&addr.sun_path[1], path, path_len); + } + else + { + strncpy (addr.sun_path, path, path_len); + } + + if (connect (fd, (struct sockaddr*) &addr, G_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0) + { + int errsv = errno; + + g_set_error (error, G_IO_ERROR, + g_io_error_from_errno (errsv), + _("Error connecting to socket: %s"), + g_strerror (errsv)); + close (fd); + return -1; + } + + return fd; +} diff --git a/gnome-2-24/common/gsysutils.h b/gnome-2-24/common/gsysutils.h new file mode 100644 index 00000000..f68a2642 --- /dev/null +++ b/gnome-2-24/common/gsysutils.h @@ -0,0 +1,39 @@ +/* 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_SYS_UTILS_H__ +#define __G_SYS_UTILS_H__ + +#include <glib.h> + +G_BEGIN_DECLS + +int _g_socket_send_fd (int socket_fd, + int fd); +int _g_socket_receive_fd (int socket_fd); +int _g_socket_connect (const char *address, + GError **error); + +G_END_DECLS + + +#endif /* __G_SYS_UTILS_H__ */ diff --git a/gnome-2-24/common/gvfsdaemonprotocol.c b/gnome-2-24/common/gvfsdaemonprotocol.c new file mode 100644 index 00000000..36331ed8 --- /dev/null +++ b/gnome-2-24/common/gvfsdaemonprotocol.c @@ -0,0 +1,614 @@ +/* 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 <glib-object.h> +#include <dbus/dbus.h> +#include <glib/gi18n-lib.h> +#include <gvfsdaemonprotocol.h> +#include <gdbusutils.h> +#include <gio/gio.h> + +static const char * +get_object_signature (GObject *obj) +{ + if (G_IS_THEMED_ICON (obj)) + { + return + DBUS_STRUCT_BEGIN_CHAR_AS_STRING + DBUS_TYPE_UINT32_AS_STRING + DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING + DBUS_STRUCT_END_CHAR_AS_STRING; + } + else if (G_IS_FILE_ICON (obj)) + { + GFile *file; + char *path; + + file = g_file_icon_get_file (G_FILE_ICON (obj)); + + path = g_file_get_path (file); + if (path) + { + g_free (path); + return + DBUS_STRUCT_BEGIN_CHAR_AS_STRING + DBUS_TYPE_UINT32_AS_STRING + DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING + DBUS_STRUCT_END_CHAR_AS_STRING; + } + } + return + DBUS_STRUCT_BEGIN_CHAR_AS_STRING + DBUS_TYPE_UINT32_AS_STRING + DBUS_STRUCT_END_CHAR_AS_STRING; +} + +static void +append_string_array (DBusMessageIter *iter, char **strs) +{ + DBusMessageIter array; + int i; + + if (!dbus_message_iter_open_container (iter, + DBUS_TYPE_ARRAY, + DBUS_TYPE_STRING_AS_STRING, + &array)) + _g_dbus_oom (); + + + for (i = 0; strs[i] != NULL; i++) + { + if (!dbus_message_iter_append_basic (&array, DBUS_TYPE_STRING, &strs[i])) + _g_dbus_oom (); + } + + if (!dbus_message_iter_close_container (iter, &array)) + _g_dbus_oom (); +} + +static void +append_object (DBusMessageIter *iter, GObject *obj) +{ + DBusMessageIter obj_struct_iter; + guint32 v_uint32; + + if (!dbus_message_iter_open_container (iter, + DBUS_TYPE_STRUCT, + NULL, + &obj_struct_iter)) + _g_dbus_oom (); + + if (G_IS_THEMED_ICON (obj)) + { + const char * const *icons; + + icons = g_themed_icon_get_names (G_THEMED_ICON (obj)); + + v_uint32 = 1; + if (!dbus_message_iter_append_basic (&obj_struct_iter, + DBUS_TYPE_UINT32, &v_uint32)) + _g_dbus_oom (); + + append_string_array (&obj_struct_iter, (char **)icons); + } + else if (G_IS_FILE_ICON (obj)) + { + GFile *file; + char *path; + + file = g_file_icon_get_file (G_FILE_ICON (obj)); + + path = g_file_get_path (file); + if (path) + { + v_uint32 = 2; + if (!dbus_message_iter_append_basic (&obj_struct_iter, + DBUS_TYPE_UINT32, &v_uint32)) + _g_dbus_oom (); + + path = g_file_get_path (file); + _g_dbus_message_iter_append_cstring (&obj_struct_iter, path); + g_free (path); + } + else + { + /* Seems unlikely that daemon backend will generate GFileIcons with + files on the vfs, so its probably not a problem not to support this. + (Its tricky to support, since we don't link the daemon to the client/ + library directly.) */ + g_warning ("Unknown file type for icon in attribute, ignoring"); + + v_uint32 = 0; + if (!dbus_message_iter_append_basic (&obj_struct_iter, + DBUS_TYPE_UINT32, &v_uint32)) + _g_dbus_oom (); + } + } + else + { + /* NULL or unknown type: */ + if (obj != NULL) + g_warning ("Unknown attribute object type, ignoring"); + + v_uint32 = 0; + if (!dbus_message_iter_append_basic (&obj_struct_iter, + DBUS_TYPE_UINT32, &v_uint32)) + _g_dbus_oom (); + } + + if (!dbus_message_iter_close_container (iter, &obj_struct_iter)) + _g_dbus_oom (); +} + +void +_g_dbus_attribute_value_destroy (GFileAttributeType type, + GDbusAttributeValue *value) +{ + switch (type) { + case G_FILE_ATTRIBUTE_TYPE_STRING: + case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING: + g_free (value->ptr); + break; + case G_FILE_ATTRIBUTE_TYPE_OBJECT: + if (value->ptr) + g_object_unref (value->ptr); + break; + default: + break; + } +} + +gpointer +_g_dbus_attribute_as_pointer (GFileAttributeType type, + GDbusAttributeValue *value) +{ + switch (type) { + case G_FILE_ATTRIBUTE_TYPE_STRING: + case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING: + case G_FILE_ATTRIBUTE_TYPE_OBJECT: + return value->ptr; + default: + return (gpointer) value; + } +} + +const char * +_g_dbus_type_from_file_attribute_type (GFileAttributeType type) +{ + char *dbus_type; + + switch (type) + { + case G_FILE_ATTRIBUTE_TYPE_STRING: + dbus_type = DBUS_TYPE_STRING_AS_STRING; + break; + case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING: + dbus_type = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING; + break; + case G_FILE_ATTRIBUTE_TYPE_BOOLEAN: + dbus_type = DBUS_TYPE_BOOLEAN_AS_STRING; + break; + case G_FILE_ATTRIBUTE_TYPE_UINT32: + dbus_type = DBUS_TYPE_UINT32_AS_STRING; + break; + case G_FILE_ATTRIBUTE_TYPE_INT32: + dbus_type = DBUS_TYPE_INT32_AS_STRING; + break; + case G_FILE_ATTRIBUTE_TYPE_UINT64: + dbus_type = DBUS_TYPE_UINT64_AS_STRING; + break; + case G_FILE_ATTRIBUTE_TYPE_INT64: + dbus_type = DBUS_TYPE_INT64_AS_STRING; + break; + case G_FILE_ATTRIBUTE_TYPE_OBJECT: + dbus_type = DBUS_TYPE_STRUCT_AS_STRING; + break; + default: + dbus_type = NULL; + g_warning ("Invalid attribute type %u, ignoring\n", type); + break; + } + + return dbus_type; +} + +void +_g_dbus_append_file_attribute (DBusMessageIter *iter, + const char *attribute, + GFileAttributeType type, + gpointer value_p) +{ + DBusMessageIter variant_iter, inner_struct_iter; + const char *dbus_type; + GObject *obj = NULL; + + dbus_type = _g_dbus_type_from_file_attribute_type (type); + + if (!dbus_message_iter_open_container (iter, + DBUS_TYPE_STRUCT, + NULL, + &inner_struct_iter)) + _g_dbus_oom (); + + if (!dbus_message_iter_append_basic (&inner_struct_iter, + DBUS_TYPE_STRING, + &attribute)) + _g_dbus_oom (); + + if (dbus_type[0] == DBUS_TYPE_STRUCT) + dbus_type = get_object_signature ((GObject *)value_p); + + if (!dbus_message_iter_open_container (&inner_struct_iter, + DBUS_TYPE_VARIANT, + dbus_type, + &variant_iter)) + _g_dbus_oom (); + + if (dbus_type[0] == DBUS_TYPE_STRING) + { + if (!dbus_message_iter_append_basic (&variant_iter, + DBUS_TYPE_STRING, &value_p)) + _g_dbus_oom (); + } + else if (dbus_type[0] == DBUS_TYPE_ARRAY) + _g_dbus_message_iter_append_cstring (&variant_iter, (char *)value_p); + else if (dbus_type[0] == DBUS_STRUCT_BEGIN_CHAR) + append_object (&variant_iter, (GObject *)value_p); + else if (dbus_type[0] == DBUS_TYPE_BOOLEAN) + { + /* dbus bool is uint32, gboolean is just "int", convert */ + dbus_bool_t bool = *(gboolean *)value_p; + if (!dbus_message_iter_append_basic (&variant_iter, + dbus_type[0], &bool)) + _g_dbus_oom (); + } + else + { + /* All other types have the same size as dbus types */ + if (!dbus_message_iter_append_basic (&variant_iter, + dbus_type[0], value_p)) + _g_dbus_oom (); + } + + if (obj) + g_object_unref (obj); + + if (!dbus_message_iter_close_container (&inner_struct_iter, &variant_iter)) + _g_dbus_oom (); + + if (!dbus_message_iter_close_container (iter, &inner_struct_iter)) + _g_dbus_oom (); +} + +void +_g_dbus_append_file_info (DBusMessageIter *iter, + GFileInfo *info) +{ + DBusMessageIter struct_iter, array_iter; + char **attributes; + int i; + + attributes = g_file_info_list_attributes (info, NULL); + + if (!dbus_message_iter_open_container (iter, + DBUS_TYPE_STRUCT, + NULL, + &struct_iter)) + _g_dbus_oom (); + + + if (!dbus_message_iter_open_container (&struct_iter, + DBUS_TYPE_ARRAY, + DBUS_STRUCT_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_STRUCT_END_CHAR_AS_STRING, + &array_iter)) + _g_dbus_oom (); + + for (i = 0; attributes[i] != NULL; i++) + { + GFileAttributeType type; + gpointer value_p; + + if (g_file_info_get_attribute_data (info, attributes[i], &type, &value_p, NULL)) + _g_dbus_append_file_attribute (&array_iter, attributes [i], type, value_p); + } + + g_strfreev (attributes); + + if (!dbus_message_iter_close_container (&struct_iter, &array_iter)) + _g_dbus_oom (); + + if (!dbus_message_iter_close_container (iter, &struct_iter)) + _g_dbus_oom (); +} + +gboolean +_g_dbus_get_file_attribute (DBusMessageIter *iter, + gchar **attribute, + GFileAttributeType *type, + GDbusAttributeValue *value) +{ + char *str; + char **strs; + int n_elements; + DBusMessageIter inner_struct_iter, variant_iter, cstring_iter, obj_iter; + const gchar *attribute_temp; + dbus_uint32_t obj_type; + dbus_bool_t dbus_bool; + GObject *obj; + + dbus_message_iter_recurse (iter, &inner_struct_iter); + + if (dbus_message_iter_get_arg_type (&inner_struct_iter) != DBUS_TYPE_STRING) + goto error; + + dbus_message_iter_get_basic (&inner_struct_iter, &attribute_temp); + *attribute = g_strdup (attribute_temp); + + dbus_message_iter_next (&inner_struct_iter); + + if (dbus_message_iter_get_arg_type (&inner_struct_iter) != DBUS_TYPE_VARIANT) + goto error; + + dbus_message_iter_recurse (&inner_struct_iter, &variant_iter); + + switch (dbus_message_iter_get_arg_type (&variant_iter)) + { + case DBUS_TYPE_STRING: + *type = G_FILE_ATTRIBUTE_TYPE_STRING; + dbus_message_iter_get_basic (&variant_iter, &str); + value->ptr = g_strdup (str); + break; + case DBUS_TYPE_ARRAY: + if (dbus_message_iter_get_element_type (&variant_iter) != DBUS_TYPE_BYTE) + goto error; + + *type = G_FILE_ATTRIBUTE_TYPE_BYTE_STRING; + + dbus_message_iter_recurse (&variant_iter, &cstring_iter); + dbus_message_iter_get_fixed_array (&cstring_iter, + &str, &n_elements); + value->ptr = g_strndup (str, n_elements); + break; + case DBUS_TYPE_BOOLEAN: + dbus_message_iter_get_basic (&variant_iter, &dbus_bool); + value->boolean = dbus_bool; + *type = G_FILE_ATTRIBUTE_TYPE_BOOLEAN; + break; + case DBUS_TYPE_UINT32: + dbus_message_iter_get_basic (&variant_iter, value); + *type = G_FILE_ATTRIBUTE_TYPE_UINT32; + break; + case DBUS_TYPE_INT32: + dbus_message_iter_get_basic (&variant_iter, value); + *type = G_FILE_ATTRIBUTE_TYPE_INT32; + break; + case DBUS_TYPE_UINT64: + dbus_message_iter_get_basic (&variant_iter, value); + *type = G_FILE_ATTRIBUTE_TYPE_UINT64; + break; + case DBUS_TYPE_INT64: + dbus_message_iter_get_basic (&variant_iter, value); + *type = G_FILE_ATTRIBUTE_TYPE_INT64; + break; + case DBUS_TYPE_STRUCT: + dbus_message_iter_recurse (&variant_iter, &obj_iter); + if (dbus_message_iter_get_arg_type (&obj_iter) != DBUS_TYPE_UINT32) + goto error; + + *type = G_FILE_ATTRIBUTE_TYPE_OBJECT; + + dbus_message_iter_get_basic (&obj_iter, &obj_type); + obj = NULL; + + dbus_message_iter_next (&obj_iter); + /* 0 == NULL */ + + if (obj_type == 1) + { + /* G_THEMED_ICON */ + if (_g_dbus_message_iter_get_args (&obj_iter, + NULL, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, + &strs, &n_elements, 0)) + { + obj = G_OBJECT (g_themed_icon_new_from_names (strs, n_elements)); + dbus_free_string_array (strs); + } + } + else if (obj_type == 2) + { + /* G_FILE_ICON, w/ local file */ + if (_g_dbus_message_iter_get_args (&obj_iter, + NULL, + G_DBUS_TYPE_CSTRING, &str, + 0)) + { + GFile *file = g_file_new_for_path (str); + obj = G_OBJECT (g_file_icon_new (file)); + g_free (str); + } + } + else + { + /* NULL (or unsupported) */ + if (obj_type != 0) + g_warning ("Unsupported object type in file attribute"); + } + + value->ptr = obj; + break; + default: + goto error; + } + + return TRUE; + + error: + return FALSE; +} + +GFileInfo * +_g_dbus_get_file_info (DBusMessageIter *iter, + GError **error) +{ + GFileInfo *info; + DBusMessageIter struct_iter, array_iter; + gchar *attribute; + GFileAttributeType type; + GDbusAttributeValue value; + + info = g_file_info_new (); + + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRUCT) + goto error; + + dbus_message_iter_recurse (iter, &struct_iter); + + if (dbus_message_iter_get_arg_type (&struct_iter) != DBUS_TYPE_ARRAY) + goto error; + + dbus_message_iter_recurse (&struct_iter, &array_iter); + + while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT) + { + if (!_g_dbus_get_file_attribute (&array_iter, &attribute, &type, &value)) + goto error; + + g_file_info_set_attribute (info, attribute, type, _g_dbus_attribute_as_pointer (type, &value)); + + g_free (attribute); + _g_dbus_attribute_value_destroy (type, &value); + + dbus_message_iter_next (&array_iter); + } + + dbus_message_iter_next (iter); + return info; + + error: + g_object_unref (info); + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, + _("Invalid file info format")); + return NULL; +} + +GFileAttributeInfoList * +_g_dbus_get_attribute_info_list (DBusMessageIter *iter, + GError **error) +{ + GFileAttributeInfoList *list; + DBusMessageIter array_iter, struct_iter; + const char *name; + dbus_uint32_t type, flags; + + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_ARRAY || + dbus_message_iter_get_element_type (iter) != DBUS_TYPE_STRUCT) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, + _("Invalid attribute info list content")); + return NULL; + } + + list = g_file_attribute_info_list_new (); + + dbus_message_iter_recurse (iter, &array_iter); + while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT) + { + dbus_message_iter_recurse (&array_iter, &struct_iter); + + if (dbus_message_iter_get_arg_type (&struct_iter) == DBUS_TYPE_STRING) + { + dbus_message_iter_get_basic (&struct_iter, &name); + dbus_message_iter_next (&struct_iter); + + if (dbus_message_iter_get_arg_type (&struct_iter) == DBUS_TYPE_UINT32) + { + dbus_message_iter_get_basic (&struct_iter, &type); + dbus_message_iter_next (&struct_iter); + + if (dbus_message_iter_get_arg_type (&struct_iter) == DBUS_TYPE_UINT32) + { + dbus_message_iter_get_basic (&struct_iter, &flags); + + g_file_attribute_info_list_add (list, name, type, flags); + } + } + } + + dbus_message_iter_next (&array_iter); + } + + return list; +} + +void +_g_dbus_append_attribute_info_list (DBusMessageIter *iter, + GFileAttributeInfoList *list) +{ + DBusMessageIter array_iter, struct_iter; + int i; + dbus_uint32_t dbus_type, dbus_flags; + + if (!dbus_message_iter_open_container (iter, + DBUS_TYPE_ARRAY, + DBUS_STRUCT_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_UINT32_AS_STRING + DBUS_TYPE_UINT32_AS_STRING + DBUS_STRUCT_END_CHAR_AS_STRING, + &array_iter)) + _g_dbus_oom (); + + for (i = 0; i < list->n_infos; i++) + { + if (!dbus_message_iter_open_container (&array_iter, + DBUS_TYPE_STRUCT, + NULL, + &struct_iter)) + _g_dbus_oom (); + + if (!dbus_message_iter_append_basic (&struct_iter, + DBUS_TYPE_STRING, &list->infos[i].name)) + _g_dbus_oom (); + + dbus_type = list->infos[i].type; + if (!dbus_message_iter_append_basic (&struct_iter, + DBUS_TYPE_UINT32, &dbus_type)) + _g_dbus_oom (); + + dbus_flags = list->infos[i].flags; + if (!dbus_message_iter_append_basic (&struct_iter, + DBUS_TYPE_UINT32, &dbus_flags)) + _g_dbus_oom (); + + if (!dbus_message_iter_close_container (&array_iter, &struct_iter)) + _g_dbus_oom (); + } + + if (!dbus_message_iter_close_container (iter, &array_iter)) + _g_dbus_oom (); +} diff --git a/gnome-2-24/common/gvfsdaemonprotocol.h b/gnome-2-24/common/gvfsdaemonprotocol.h new file mode 100644 index 00000000..0e73c52e --- /dev/null +++ b/gnome-2-24/common/gvfsdaemonprotocol.h @@ -0,0 +1,186 @@ +#ifndef __G_VFS_DAEMON_PROTOCOL_H__ +#define __G_VFS_DAEMON_PROTOCOL_H__ + +#include <gio/gio.h> + +G_BEGIN_DECLS + +/* The well known name of the main daemon */ +#define G_VFS_DBUS_DAEMON_NAME "org.gtk.vfs.Daemon" + +/* The mount tracking interface in the main daemon */ +#define G_VFS_DBUS_MOUNTTRACKER_INTERFACE "org.gtk.vfs.MountTracker" +#define G_VFS_DBUS_MOUNTTRACKER_PATH "/org/gtk/vfs/mounttracker" +#define G_VFS_DBUS_MOUNTTRACKER_OP_LOOKUP_MOUNT "lookupMount" +#define G_VFS_DBUS_MOUNTTRACKER_OP_MOUNT_LOCATION "mountLocation" +#define G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNTS "listMounts" +#define G_VFS_DBUS_MOUNTTRACKER_OP_REGISTER_MOUNT "registerMount" +#define G_VFS_DBUS_MOUNTTRACKER_OP_UNREGISTER_MOUNT "unregisterMount" +#define G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNT_TYPES "listMountTypes" +#define G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNTABLE_INFO "listMountableInfo" +#define G_VFS_DBUS_MOUNTTRACKER_OP_REGISTER_FUSE "registerFuse" +#define G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED "mounted" +#define G_VFS_DBUS_MOUNTTRACKER_SIGNAL_UNMOUNTED "unmounted" + +/* Each mount (there might be several in a daemon) implements one of these interfaces + for standard i/o operations */ +#define G_VFS_DBUS_MOUNT_INTERFACE "org.gtk.vfs.Mount" +#define G_VFS_DBUS_MOUNT_OP_UNMOUNT "Unmount" +#define G_VFS_DBUS_MOUNT_OP_OPEN_FOR_READ "OpenForRead" +#define G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE "OpenForWrite" +#define G_VFS_DBUS_MOUNT_OP_QUERY_INFO "QueryInfo" +#define G_VFS_DBUS_MOUNT_OP_QUERY_FILESYSTEM_INFO "QueryFilesystemInfo" +#define G_VFS_DBUS_MOUNT_OP_ENUMERATE "Enumerate" +#define G_VFS_DBUS_MOUNT_OP_CREATE_DIR_MONITOR "CreateDirectoryMonitor" +#define G_VFS_DBUS_MOUNT_OP_CREATE_FILE_MONITOR "CreateFileMonitor" +#define G_VFS_DBUS_MOUNT_OP_MOUNT_MOUNTABLE "MountMountable" +#define G_VFS_DBUS_MOUNT_OP_UNMOUNT_MOUNTABLE "UnountMountable" +#define G_VFS_DBUS_MOUNT_OP_EJECT_MOUNTABLE "EjectMountable" +#define G_VFS_DBUS_MOUNT_OP_SET_DISPLAY_NAME "SetDisplayName" +#define G_VFS_DBUS_MOUNT_OP_DELETE "Delete" +#define G_VFS_DBUS_MOUNT_OP_TRASH "Trash" +#define G_VFS_DBUS_MOUNT_OP_MAKE_DIRECTORY "MakeDirectory" +#define G_VFS_DBUS_MOUNT_OP_MAKE_SYMBOLIC_LINK "MakeSymbolicLink" +#define G_VFS_DBUS_MOUNT_OP_COPY "Copy" +#define G_VFS_DBUS_MOUNT_OP_MOVE "Move" +#define G_VFS_DBUS_MOUNT_OP_PUSH "Push" +#define G_VFS_DBUS_MOUNT_OP_PULL "Pull" +#define G_VFS_DBUS_MOUNT_OP_SET_ATTRIBUTE "SetAttribute" +#define G_VFS_DBUS_MOUNT_OP_QUERY_SETTABLE_ATTRIBUTES "QuerySettableAttributes" +#define G_VFS_DBUS_MOUNT_OP_QUERY_WRITABLE_NAMESPACES "QueryWritableNamespaces" + +/* Progress callback interface for copy and move */ +#define G_VFS_DBUS_PROGRESS_INTERFACE "org.gtk.vfs.Progress" +#define G_VFS_DBUS_PROGRESS_OP_PROGRESS "Progress" + +/* mount daemons that support mounting more mounts implement this, + and set the dbus name in the mountable description file */ +#define G_VFS_DBUS_MOUNTABLE_INTERFACE "org.gtk.vfs.Mountable" +#define G_VFS_DBUS_MOUNTABLE_PATH "/org/gtk/vfs/mountable" +#define G_VFS_DBUS_MOUNTABLE_OP_MOUNT "mount" + +#define G_VFS_DBUS_ERROR_SOCKET_FAILED "org.gtk.vfs.Error.SocketFailed" + +/* Each daemon (main and for mounts) implement this. */ +#define G_VFS_DBUS_DAEMON_INTERFACE "org.gtk.vfs.Daemon" +#define G_VFS_DBUS_DAEMON_PATH "/org/gtk/vfs/Daemon" +#define G_VFS_DBUS_OP_GET_CONNECTION "GetConnection" +#define G_VFS_DBUS_OP_CANCEL "Cancel" + +/* Used by the dbus-proxying implementation of GMoutOperation */ +#define G_VFS_DBUS_MOUNT_OPERATION_INTERFACE "org.gtk.vfs.MountOperation" +#define G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_PASSWORD "askPassword" +#define G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_QUESTION "askQuestion" + +/* Implemented by the spawner of a process, the spawned process sends the + spawned message (with noreply) when it has spawned and gotten a dbus id */ +#define G_VFS_DBUS_SPAWNER_INTERFACE "org.gtk.vfs.Spawner" +#define G_VFS_DBUS_OP_SPAWNED "spawned" + +/* Implemented by client side for a file enumerator */ +#define G_VFS_DBUS_ENUMERATOR_INTERFACE "org.gtk.vfs.Enumerator" +#define G_VFS_DBUS_ENUMERATOR_OP_DONE "Done" +#define G_VFS_DBUS_ENUMERATOR_OP_GOT_INFO "GotInfo" + +#define G_VFS_DBUS_MONITOR_INTERFACE "org.gtk.vfs.Monitor" +#define G_VFS_DBUS_MONITOR_OP_SUBSCRIBE "Subscribe" +#define G_VFS_DBUS_MONITOR_OP_UNSUBSCRIBE "Unsubscribe" + +#define G_VFS_DBUS_MONITOR_CLIENT_INTERFACE "org.gtk.vfs.MonitorClient" +#define G_VFS_DBUS_MONITOR_CLIENT_OP_CHANGED "Changed" + + +/* Mounts time out in 10 minutes, since they can be slow, with auth, etc */ +#define G_VFS_DBUS_MOUNT_TIMEOUT_MSECS (1000*60*10) +/* Normal ops are faster, one minute timeout */ +#define G_VFS_DBUS_TIMEOUT_MSECS (1000*60) + +typedef struct { + guint32 command; + guint32 seq_nr; + guint32 arg1; + guint32 arg2; + guint32 data_len; +} GVfsDaemonSocketProtocolRequest; + +#define G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SIZE sizeof(GVfsDaemonSocketProtocolRequest) + +#define G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_READ 0 +#define G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_WRITE 1 +#define G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CLOSE 2 +#define G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CANCEL 3 +#define G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SEEK_SET 4 +#define G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SEEK_END 5 + +/* +read, readahead reply: +type, seek_generation, size, data + +seek reply: +type, pos (64), + +error: +type, code, size, data (size bytes, 2 strings: domain, message) +*/ + +typedef struct { + guint32 type; + guint32 seq_nr; + guint32 arg1; + guint32 arg2; +} GVfsDaemonSocketProtocolReply; + +#define G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE 16 + +#define G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_DATA 0 +#define G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_ERROR 1 +#define G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SEEK_POS 2 +#define G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_WRITTEN 3 +#define G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_CLOSED 4 + +#define G_FILE_INFO_INNER_TYPE_AS_STRING \ + DBUS_TYPE_ARRAY_AS_STRING \ + DBUS_STRUCT_BEGIN_CHAR_AS_STRING \ + DBUS_TYPE_STRING_AS_STRING \ + DBUS_TYPE_VARIANT_AS_STRING \ + DBUS_STRUCT_END_CHAR_AS_STRING + +#define G_FILE_INFO_TYPE_AS_STRING \ + DBUS_STRUCT_BEGIN_CHAR_AS_STRING \ + G_FILE_INFO_INNER_TYPE_AS_STRING \ + DBUS_STRUCT_END_CHAR_AS_STRING + + +typedef union { + gboolean boolean; + guint32 uint32; + guint64 uint64; + gpointer ptr; +} GDbusAttributeValue; + +void _g_dbus_attribute_value_destroy (GFileAttributeType type, + GDbusAttributeValue *value); +gpointer _g_dbus_attribute_as_pointer (GFileAttributeType type, + GDbusAttributeValue *value); +const char*_g_dbus_type_from_file_attribute_type (GFileAttributeType type); +void _g_dbus_append_file_attribute (DBusMessageIter *iter, + const char *attribute, + GFileAttributeType type, + gpointer value_p); +void _g_dbus_append_file_info (DBusMessageIter *iter, + GFileInfo *file_info); +gboolean _g_dbus_get_file_attribute (DBusMessageIter *iter, + gchar **attribute, + GFileAttributeType *type, + GDbusAttributeValue *value); +GFileInfo *_g_dbus_get_file_info (DBusMessageIter *iter, + GError **error); + +GFileAttributeInfoList *_g_dbus_get_attribute_info_list (DBusMessageIter *iter, + GError **error); +void _g_dbus_append_attribute_info_list (DBusMessageIter *iter, + GFileAttributeInfoList *list); + +G_END_DECLS + +#endif /* __G_VFS_DAEMON_PROTOCOL_H__ */ |