mirror of https://gitee.com/openkylin/gvfs.git
1030 lines
30 KiB
C
1030 lines
30 KiB
C
/* 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., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*
|
|
* Author: Alexander Larsson <alexl@redhat.com>
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include <gmountsource.h>
|
|
#include <gio/gio.h>
|
|
#include <gvfsdbus.h>
|
|
#include "gvfsdaemonprotocol.h"
|
|
|
|
#include <string.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;
|
|
}
|
|
|
|
GVariant *
|
|
g_mount_source_to_dbus (GMountSource *source)
|
|
{
|
|
g_assert (source->dbus_id != NULL);
|
|
g_assert (source->obj_path != NULL);
|
|
|
|
return g_variant_new ("(so)",
|
|
source->dbus_id,
|
|
source->obj_path);
|
|
}
|
|
|
|
GMountSource *
|
|
g_mount_source_from_dbus (GVariant *value)
|
|
{
|
|
const gchar *obj_path, *dbus_id;
|
|
|
|
g_variant_get (value, "(&s&o)",
|
|
&dbus_id,
|
|
&obj_path);
|
|
|
|
return g_mount_source_new (dbus_id, obj_path);
|
|
}
|
|
|
|
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 */
|
|
GMainContext *context;
|
|
GMainLoop *loop;
|
|
|
|
/* 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);
|
|
}
|
|
|
|
static GVfsDBusMountOperation *
|
|
create_mount_operation_proxy_sync (GMountSource *source,
|
|
GError **error)
|
|
{
|
|
GVfsDBusMountOperation *proxy;
|
|
GError *local_error;
|
|
|
|
/* If no dbus id specified, reply that we weren't handled */
|
|
if (source->dbus_id[0] == 0)
|
|
{
|
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Internal Error");
|
|
return NULL;
|
|
}
|
|
|
|
local_error = NULL;
|
|
/* Synchronously creating a proxy using unique/private d-bus name and not loading properties or connecting signals should not block */
|
|
proxy = gvfs_dbus_mount_operation_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
|
|
G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
|
|
source->dbus_id,
|
|
source->obj_path,
|
|
NULL,
|
|
&local_error);
|
|
if (proxy == NULL)
|
|
{
|
|
g_dbus_error_strip_remote_error (local_error);
|
|
g_propagate_error (error, local_error);
|
|
}
|
|
|
|
return proxy;
|
|
}
|
|
|
|
/* the callback from dbus -> main thread */
|
|
static void
|
|
ask_password_reply (GVfsDBusMountOperation *proxy,
|
|
GAsyncResult *res,
|
|
gpointer user_data)
|
|
{
|
|
GTask *task;
|
|
AskPasswordData *data;
|
|
gboolean handled, aborted, anonymous;
|
|
guint32 password_save;
|
|
gchar *password, *username, *domain;
|
|
GError *error;
|
|
|
|
task = G_TASK (user_data);
|
|
handled = TRUE;
|
|
|
|
error = NULL;
|
|
if (!gvfs_dbus_mount_operation_call_ask_password_finish (proxy,
|
|
&handled,
|
|
&aborted,
|
|
&password,
|
|
&username,
|
|
&domain,
|
|
&anonymous,
|
|
&password_save,
|
|
res,
|
|
&error))
|
|
{
|
|
g_dbus_error_strip_remote_error (error);
|
|
g_task_return_error (task, error);
|
|
}
|
|
else if (handled == FALSE)
|
|
{
|
|
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "Internal Error");
|
|
}
|
|
else
|
|
{
|
|
data = g_new0 (AskPasswordData, 1);
|
|
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;
|
|
|
|
g_task_return_pointer (task, data, ask_password_data_free);
|
|
|
|
/* TODO: handle more args */
|
|
g_free (password);
|
|
g_free (username);
|
|
g_free (domain);
|
|
}
|
|
|
|
g_object_unref (task);
|
|
}
|
|
|
|
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)
|
|
{
|
|
GTask *task;
|
|
GVfsDBusMountOperation *proxy;
|
|
GError *error = NULL;
|
|
|
|
task = g_task_new (source, NULL, callback, user_data);
|
|
g_task_set_source_tag (task, g_mount_source_ask_password_async);
|
|
|
|
proxy = create_mount_operation_proxy_sync (source, &error);
|
|
if (proxy == NULL)
|
|
{
|
|
g_task_return_error (task, error);
|
|
g_object_unref (task);
|
|
return;
|
|
}
|
|
|
|
/* 30 minute timeout */
|
|
g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (proxy), G_VFS_DBUS_MOUNT_TIMEOUT_MSECS);
|
|
|
|
gvfs_dbus_mount_operation_call_ask_password (proxy,
|
|
message_string ? message_string : "",
|
|
default_user ? default_user : "",
|
|
default_domain ? default_domain : "",
|
|
flags,
|
|
NULL,
|
|
(GAsyncReadyCallback) ask_password_reply,
|
|
task);
|
|
g_object_unref (proxy);
|
|
}
|
|
|
|
/**
|
|
* 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, };
|
|
|
|
g_return_val_if_fail (g_task_is_valid (result, source), FALSE);
|
|
g_return_val_if_fail (g_async_result_is_tagged (result, g_mount_source_ask_password_async), FALSE);
|
|
|
|
data = g_task_propagate_pointer (G_TASK (result), NULL);
|
|
if (data == NULL)
|
|
data = &def;
|
|
|
|
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);
|
|
|
|
g_main_loop_quit (data->loop);
|
|
}
|
|
|
|
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;
|
|
|
|
data.context = g_main_context_new ();
|
|
data.loop = g_main_loop_new (data.context, FALSE);
|
|
|
|
g_main_context_push_thread_default (data.context);
|
|
|
|
g_mount_source_ask_password_async (source,
|
|
message_string,
|
|
default_user,
|
|
default_domain,
|
|
flags,
|
|
ask_reply_sync,
|
|
&data);
|
|
|
|
g_main_loop_run (data.loop);
|
|
|
|
handled = g_mount_source_ask_password_finish (source,
|
|
data.result,
|
|
aborted_out,
|
|
password_out,
|
|
user_out,
|
|
domain_out,
|
|
anonymous_out,
|
|
password_save_out);
|
|
|
|
g_main_context_pop_thread_default (data.context);
|
|
g_main_context_unref (data.context);
|
|
g_main_loop_unref (data.loop);
|
|
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,
|
|
&password,
|
|
&username,
|
|
&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));
|
|
g_signal_stop_emission_by_name (op, "ask_password");
|
|
return TRUE;
|
|
}
|
|
|
|
typedef struct AskQuestionData AskQuestionData;
|
|
|
|
struct AskQuestionData {
|
|
|
|
/* results: */
|
|
gboolean aborted;
|
|
guint32 choice;
|
|
};
|
|
|
|
/* the callback from dbus -> main thread */
|
|
static void
|
|
ask_question_reply (GVfsDBusMountOperation *proxy,
|
|
GAsyncResult *res,
|
|
gpointer user_data)
|
|
{
|
|
GTask *task;
|
|
AskQuestionData *data;
|
|
gboolean handled, aborted;
|
|
guint32 choice;
|
|
GError *error;
|
|
|
|
task = G_TASK (user_data);
|
|
handled = TRUE;
|
|
|
|
error = NULL;
|
|
if (!gvfs_dbus_mount_operation_call_ask_question_finish (proxy,
|
|
&handled,
|
|
&aborted,
|
|
&choice,
|
|
res,
|
|
&error))
|
|
{
|
|
g_dbus_error_strip_remote_error (error);
|
|
g_task_return_error (task, error);
|
|
}
|
|
else if (handled == FALSE)
|
|
{
|
|
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "Internal Error");
|
|
}
|
|
else
|
|
{
|
|
data = g_new0 (AskQuestionData, 1);
|
|
data->aborted = aborted;
|
|
data->choice = choice;
|
|
|
|
g_task_return_pointer (task, data, g_free);
|
|
}
|
|
|
|
g_object_unref (task);
|
|
}
|
|
|
|
gboolean
|
|
g_mount_source_ask_question (GMountSource *source,
|
|
const char *message,
|
|
const char **choices,
|
|
gboolean *aborted_out,
|
|
gint *choice_out)
|
|
{
|
|
gint choice;
|
|
gboolean handled, aborted;
|
|
AskSyncData data;
|
|
|
|
data.context = g_main_context_new ();
|
|
data.loop = g_main_loop_new (data.context, FALSE);
|
|
|
|
g_main_context_push_thread_default (data.context);
|
|
|
|
g_mount_source_ask_question_async (source,
|
|
message,
|
|
choices,
|
|
ask_reply_sync,
|
|
&data);
|
|
|
|
g_main_loop_run (data.loop);
|
|
|
|
handled = g_mount_source_ask_question_finish (source,
|
|
data.result,
|
|
&aborted,
|
|
&choice);
|
|
|
|
g_main_context_pop_thread_default (data.context);
|
|
g_main_context_unref (data.context);
|
|
g_main_loop_unref (data.loop);
|
|
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,
|
|
GAsyncReadyCallback callback,
|
|
gpointer user_data)
|
|
{
|
|
GTask *task;
|
|
GVfsDBusMountOperation *proxy;
|
|
GError *error = NULL;
|
|
|
|
task = g_task_new (source, NULL, callback, user_data);
|
|
g_task_set_source_tag (task, g_mount_source_ask_question_async);
|
|
|
|
proxy = create_mount_operation_proxy_sync (source, &error);
|
|
if (proxy == NULL)
|
|
{
|
|
g_task_return_error (task, error);
|
|
g_object_unref (task);
|
|
return;
|
|
}
|
|
|
|
/* 30 minute timeout */
|
|
g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (proxy), G_VFS_DBUS_MOUNT_TIMEOUT_MSECS);
|
|
|
|
gvfs_dbus_mount_operation_call_ask_question (proxy,
|
|
message_string ? message_string : "",
|
|
choices,
|
|
NULL,
|
|
(GAsyncReadyCallback) ask_question_reply,
|
|
task);
|
|
g_object_unref (proxy);
|
|
}
|
|
|
|
gboolean
|
|
g_mount_source_ask_question_finish (GMountSource *source,
|
|
GAsyncResult *result,
|
|
gboolean *aborted,
|
|
gint *choice_out)
|
|
{
|
|
AskQuestionData *data, def = { TRUE, };
|
|
|
|
g_return_val_if_fail (g_task_is_valid (result, source), FALSE);
|
|
g_return_val_if_fail (g_async_result_is_tagged (result, g_mount_source_ask_question_async), FALSE);
|
|
|
|
data = g_task_propagate_pointer (G_TASK (result), NULL);
|
|
if (data == NULL)
|
|
data = &def;
|
|
|
|
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,
|
|
GMountSource *mount_source)
|
|
{
|
|
g_mount_source_ask_question_async (mount_source,
|
|
message,
|
|
choices,
|
|
op_ask_question_reply,
|
|
g_object_ref (op));
|
|
g_signal_stop_emission_by_name (op, "ask_question");
|
|
return TRUE;
|
|
}
|
|
|
|
typedef struct ShowProcessesData ShowProcessesData;
|
|
|
|
struct ShowProcessesData {
|
|
|
|
/* results: */
|
|
gboolean aborted;
|
|
guint32 choice;
|
|
};
|
|
|
|
/* the callback from dbus -> main thread */
|
|
static void
|
|
show_processes_reply (GVfsDBusMountOperation *proxy,
|
|
GAsyncResult *res,
|
|
gpointer user_data)
|
|
{
|
|
GTask *task;
|
|
ShowProcessesData *data;
|
|
gboolean handled, aborted;
|
|
guint32 choice;
|
|
GError *error;
|
|
|
|
task = G_TASK (user_data);
|
|
handled = TRUE;
|
|
|
|
error = NULL;
|
|
if (!gvfs_dbus_mount_operation_call_show_processes_finish (proxy,
|
|
&handled,
|
|
&aborted,
|
|
&choice,
|
|
res,
|
|
&error))
|
|
{
|
|
g_dbus_error_strip_remote_error (error);
|
|
g_task_return_error (task, error);
|
|
}
|
|
else if (handled == FALSE)
|
|
{
|
|
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "Internal Error");
|
|
}
|
|
else
|
|
{
|
|
data = g_new0 (ShowProcessesData, 1);
|
|
data->aborted = aborted;
|
|
data->choice = choice;
|
|
|
|
g_task_return_pointer (task, data, g_free);
|
|
}
|
|
|
|
g_object_unref (task);
|
|
}
|
|
|
|
void
|
|
g_mount_source_show_processes_async (GMountSource *source,
|
|
const char *message_string,
|
|
GArray *processes,
|
|
const char **choices,
|
|
GAsyncReadyCallback callback,
|
|
gpointer user_data)
|
|
{
|
|
GTask *task;
|
|
GVfsDBusMountOperation *proxy;
|
|
GVariantBuilder builder;
|
|
guint i;
|
|
GError *error = NULL;
|
|
|
|
task = g_task_new (source, NULL, callback, user_data);
|
|
g_task_set_source_tag (task, g_mount_source_show_processes_async);
|
|
|
|
proxy = create_mount_operation_proxy_sync (source, &error);
|
|
if (proxy == NULL)
|
|
{
|
|
g_task_return_error (task, error);
|
|
g_object_unref (task);
|
|
return;
|
|
}
|
|
|
|
/* 30 minute timeout */
|
|
g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (proxy), G_VFS_DBUS_MOUNT_TIMEOUT_MSECS);
|
|
|
|
g_variant_builder_init (&builder, G_VARIANT_TYPE ("ai"));
|
|
for (i = 0; i < processes->len; i++)
|
|
g_variant_builder_add (&builder, "i",
|
|
g_array_index (processes, gint32, i));
|
|
|
|
gvfs_dbus_mount_operation_call_show_processes (proxy,
|
|
message_string ? message_string : "",
|
|
choices,
|
|
g_variant_builder_end (&builder),
|
|
NULL,
|
|
(GAsyncReadyCallback) show_processes_reply,
|
|
task);
|
|
g_object_unref (proxy);
|
|
}
|
|
|
|
gboolean
|
|
g_mount_source_show_processes_finish (GMountSource *source,
|
|
GAsyncResult *result,
|
|
gboolean *aborted,
|
|
gint *choice_out)
|
|
{
|
|
ShowProcessesData *data, def = { TRUE, };
|
|
|
|
g_return_val_if_fail (g_task_is_valid (result, source), FALSE);
|
|
g_return_val_if_fail (g_async_result_is_tagged (result, g_mount_source_show_processes_async), FALSE);
|
|
|
|
data = g_task_propagate_pointer (G_TASK (result), NULL);
|
|
if (data == NULL)
|
|
data = &def;
|
|
|
|
if (aborted)
|
|
*aborted = data->aborted;
|
|
|
|
if (choice_out)
|
|
*choice_out = data->choice;
|
|
|
|
return data != &def;
|
|
}
|
|
|
|
gboolean
|
|
g_mount_source_show_processes (GMountSource *source,
|
|
const char *message,
|
|
GArray *processes,
|
|
const char **choices,
|
|
gboolean *aborted_out,
|
|
gint *choice_out)
|
|
{
|
|
gint choice;
|
|
gboolean handled, aborted;
|
|
AskSyncData data;
|
|
|
|
data.context = g_main_context_new ();
|
|
data.loop = g_main_loop_new (data.context, FALSE);
|
|
|
|
g_main_context_push_thread_default (data.context);
|
|
|
|
g_mount_source_show_processes_async (source,
|
|
message,
|
|
processes,
|
|
choices,
|
|
ask_reply_sync,
|
|
&data);
|
|
|
|
g_main_loop_run (data.loop);
|
|
|
|
handled = g_mount_source_show_processes_finish (source,
|
|
data.result,
|
|
&aborted,
|
|
&choice);
|
|
|
|
g_main_context_pop_thread_default (data.context);
|
|
g_main_context_unref (data.context);
|
|
g_main_loop_unref (data.loop);
|
|
g_object_unref (data.result);
|
|
|
|
if (aborted_out)
|
|
*aborted_out = aborted;
|
|
|
|
if (choice_out)
|
|
*choice_out = choice;
|
|
|
|
return handled;
|
|
}
|
|
|
|
static void
|
|
op_show_processes_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_show_processes_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_show_processes (GMountOperation *op,
|
|
const char *message,
|
|
GArray *processes,
|
|
const char **choices,
|
|
GMountSource *mount_source)
|
|
{
|
|
g_mount_source_show_processes_async (mount_source,
|
|
message,
|
|
processes,
|
|
choices,
|
|
op_show_processes_reply,
|
|
g_object_ref (op));
|
|
g_signal_stop_emission_by_name (op, "show_processes");
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
show_unmount_progress_reply (GVfsDBusMountOperation *proxy,
|
|
GAsyncResult *res,
|
|
gpointer user_data)
|
|
{
|
|
GError *error;
|
|
|
|
error = NULL;
|
|
if (!gvfs_dbus_mount_operation_call_show_unmount_progress_finish (proxy, res, &error))
|
|
{
|
|
g_warning ("ShowUnmountProgress request failed: %s", error->message);
|
|
g_error_free (error);
|
|
}
|
|
}
|
|
|
|
void
|
|
g_mount_source_show_unmount_progress (GMountSource *source,
|
|
const char *message_string,
|
|
gint64 time_left,
|
|
gint64 bytes_left)
|
|
{
|
|
GVfsDBusMountOperation *proxy;
|
|
|
|
/* If no dbus id specified, warn and return */
|
|
if (source->dbus_id[0] == 0)
|
|
{
|
|
g_warning ("No dbus id specified in the mount source, "
|
|
"ignoring show-unmount-progress request");
|
|
return;
|
|
}
|
|
|
|
proxy = create_mount_operation_proxy_sync (source, NULL);
|
|
if (proxy == NULL)
|
|
return;
|
|
|
|
/* 30 minute timeout */
|
|
g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (proxy), G_VFS_DBUS_MOUNT_TIMEOUT_MSECS);
|
|
|
|
gvfs_dbus_mount_operation_call_show_unmount_progress (proxy,
|
|
message_string ? message_string : "",
|
|
time_left,
|
|
bytes_left,
|
|
NULL,
|
|
(GAsyncReadyCallback) show_unmount_progress_reply,
|
|
NULL);
|
|
g_object_unref (proxy);
|
|
}
|
|
|
|
static void
|
|
op_show_unmount_progress (GMountOperation *op,
|
|
const char *message,
|
|
gint64 time_left,
|
|
gint64 bytes_left,
|
|
GMountSource *mount_source)
|
|
{
|
|
g_mount_source_show_unmount_progress (mount_source,
|
|
message,
|
|
time_left,
|
|
bytes_left);
|
|
g_signal_stop_emission_by_name (op, "show_unmount_progress");
|
|
}
|
|
|
|
static void
|
|
abort_reply (GVfsDBusMountOperation *proxy,
|
|
GAsyncResult *res,
|
|
gpointer user_data)
|
|
{
|
|
gvfs_dbus_mount_operation_call_aborted_finish (proxy, res, NULL);
|
|
}
|
|
|
|
gboolean
|
|
g_mount_source_abort (GMountSource *source)
|
|
{
|
|
GVfsDBusMountOperation *proxy;
|
|
|
|
proxy = create_mount_operation_proxy_sync (source, NULL);
|
|
if (proxy == NULL)
|
|
return FALSE;
|
|
|
|
gvfs_dbus_mount_operation_call_aborted (proxy, NULL,
|
|
(GAsyncReadyCallback) abort_reply, NULL);
|
|
|
|
g_object_unref (proxy);
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
op_aborted (GMountOperation *op,
|
|
GMountSource *source)
|
|
{
|
|
g_mount_source_abort (source);
|
|
}
|
|
|
|
gboolean
|
|
g_mount_source_is_dummy (GMountSource *source)
|
|
{
|
|
g_return_val_if_fail (G_IS_MOUNT_SOURCE (source), TRUE);
|
|
return source->dbus_id[0] == 0;
|
|
}
|
|
|
|
|
|
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);
|
|
g_signal_connect (op, "show_processes", (GCallback)op_show_processes, mount_source);
|
|
g_signal_connect (op, "show_unmount_progress", (GCallback)op_show_unmount_progress, mount_source);
|
|
g_signal_connect (op, "aborted", (GCallback)op_aborted, mount_source);
|
|
|
|
return op;
|
|
}
|