diff options
author | Alexander Larsson <alexl@src.gnome.org> | 2007-09-13 11:53:50 +0000 |
---|---|---|
committer | Alexander Larsson <alexl@src.gnome.org> | 2007-09-13 11:53:50 +0000 |
commit | 0d563301b7ad117c2938279cb5d4bb4a352821db (patch) | |
tree | d886e8eb032e0eb9b1b3ec4160d67c5c83831d9a /daemon | |
parent | cff8ac68e7cbbc9aa2e645555c2eeeffec143ba4 (diff) | |
download | gvfs-0d563301b7ad117c2938279cb5d4bb4a352821db.tar.gz |
Initial work on allowing manual mounts
Original git commit by Alexander Larsson <alex@greebo.(none)> at 1171469241 +0100
svn path=/trunk/; revision=347
Diffstat (limited to 'daemon')
-rw-r--r-- | daemon/Makefile.am | 1 | ||||
-rw-r--r-- | daemon/gvfsbackendsmb.c | 120 | ||||
-rw-r--r-- | daemon/gvfsdaemon.c | 3 | ||||
-rw-r--r-- | daemon/mount.c | 139 | ||||
-rw-r--r-- | daemon/mount.h | 13 | ||||
-rw-r--r-- | daemon/mounttracker.c | 101 | ||||
-rw-r--r-- | daemon/smb.mount.in | 2 |
7 files changed, 278 insertions, 101 deletions
diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 1a1ad56a..59981f9c 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -59,7 +59,6 @@ libdaemon_la_SOURCES = \ gvfsjobcloseread.c gvfsjobcloseread.h \ gvfsjobgetinfo.c gvfsjobgetinfo.h \ gvfsjobenumerate.c gvfsjobenumerate.h \ - gmountsource.c gmountsource.h \ gvfsdaemonprotocol.c \ dbus-gmain.h dbus-gmain.c \ $(NULL) diff --git a/daemon/gvfsbackendsmb.c b/daemon/gvfsbackendsmb.c index 5e066aca..4c8c8c84 100644 --- a/daemon/gvfsbackendsmb.c +++ b/daemon/gvfsbackendsmb.c @@ -34,6 +34,14 @@ struct _GVfsBackendSmb SMBCCTX *smb_context; + char *last_user; + char *last_domain; + char *last_password; + + GMountSource *mount_source; /* Only used/set during mount */ + int mount_try; + gboolean mount_try_again; + /* Cache */ char *cached_server_name; char *cached_share_name; @@ -96,15 +104,91 @@ auth_callback (SMBCCTX *context, char *password_out, int pwmaxlen) { GVfsBackendSmb *backend; + char *ask_password, *ask_user, *ask_domain; + gboolean handled, abort; backend = smbc_option_get (context, "user_data"); + strncpy (password_out, "", pwmaxlen); + if (backend->domain) strncpy (domain_out, backend->domain, domainmaxlen); if (backend->user) strncpy (username_out, backend->user, unmaxlen); + + if (backend->mount_source == NULL) + { + /* Not during mount, use last password */ + if (backend->last_user) + strncpy (username_out, backend->last_user, unmaxlen); + if (backend->last_domain) + strncpy (domain_out, backend->last_domain, domainmaxlen); + if (backend->last_password) + strncpy (password_out, backend->last_password, pwmaxlen); + + return; + } - g_print ("auth_callback: %s %s\n", server_name, share_name); + if (backend->mount_try == 0 && + backend->user == NULL && + backend->domain == NULL) + { + /* Try anon login */ + strncpy (username_out, "", unmaxlen); + strncpy (password_out, "", pwmaxlen); + /* Try again if anon login fails */ + backend->mount_try_again = TRUE; + } + else + { + GPasswordFlags flags = G_PASSWORD_FLAGS_NEED_PASSWORD; + char *message; + + if (backend->domain == NULL) + flags |= G_PASSWORD_FLAGS_NEED_DOMAIN; + if (backend->user == NULL) + flags |= G_PASSWORD_FLAGS_NEED_USERNAME; + + message = g_strdup_printf (_("Password required for share %s on %s"), + server_name, share_name); + handled = g_mount_source_ask_password (backend->mount_source, + message, + username_out, + domain_out, + flags, + &abort, + &ask_password, + &ask_user, + &ask_domain); + g_free (message); + if (!handled) + goto out; + + if (abort) + { + strncpy (username_out, "ABORT", unmaxlen); + strncpy (password_out, "", pwmaxlen); + goto out; + } + + /* Try again if this fails */ + backend->mount_try_again = TRUE; + + strncpy (password_out, ask_password, pwmaxlen); + if (ask_user && *ask_user) + strncpy (username_out, ask_user, unmaxlen); + if (ask_domain && *ask_domain) + strncpy (domain_out, ask_domain, domainmaxlen); + + out: + g_free (ask_password); + g_free (ask_user); + g_free (ask_domain); + } + + backend->last_user = g_strdup (username_out); + backend->last_domain = g_strdup (domain_out); + backend->last_password = g_strdup (password_out); } /* Add a server to the cache system @@ -189,8 +273,6 @@ get_cached_server (SMBCCTX * context, backend = smbc_option_get (context, "user_data"); - g_print ("get_cached_server %s, %s\n", server_name, share_name); - if (backend->cached_server != NULL && strcmp (backend->cached_server_name, server_name) == 0 && strcmp (backend->cached_share_name, share_name) == 0 && @@ -198,7 +280,6 @@ get_cached_server (SMBCCTX * context, strcmp (backend->cached_username, username) == 0) return backend->cached_server; - g_print ("get_cached_server -> miss\n"); return NULL; } @@ -307,8 +388,6 @@ do_mount (GVfsBackend *backend, char *display_name; GMountSpec *smb_mount_spec; - g_print ("do_mount\n"); - smb_context = smbc_new_context (); if (smb_context == NULL) { @@ -337,7 +416,7 @@ do_mount (GVfsBackend *backend, smb_context->flags |= SMB_CTX_FLAG_USE_KERBEROS | SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS; #endif #if defined(SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON) - //smb_context->flags |= SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON; + smb_context->flags |= SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON; #endif #endif @@ -372,10 +451,32 @@ do_mount (GVfsBackend *backend, g_mount_spec_unref (smb_mount_spec); uri = create_smb_uri (op_backend->server, op_backend->share, NULL); - res = smb_context->stat (smb_context, uri, &st); + + op_backend->mount_source = mount_source; + op_backend->mount_try = 0; + + do + { + op_backend->mount_try_again = FALSE; + + res = smb_context->stat (smb_context, uri, &st); + + if (res == 0 || + (errno != EACCES && errno != EPERM)) + break; + + op_backend->mount_try ++; + } + while (op_backend->mount_try_again); + g_free (uri); + + op_backend->mount_source = NULL; + if (res != 0) { + /* TODO: Error from errno? */ + op_backend->mount_source = NULL; g_vfs_job_failed (G_VFS_JOB (job), G_FILE_ERROR, G_FILE_ERROR_IO, "Failed to mount smb share"); @@ -383,7 +484,6 @@ do_mount (GVfsBackend *backend, } g_vfs_job_succeeded (G_VFS_JOB (job)); - g_print ("finished mount\n"); } static gboolean @@ -395,8 +495,6 @@ try_mount (GVfsBackend *backend, GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend); const char *server, *share, *user, *domain; - g_print ("try_mount\n"); - server = g_mount_spec_get (mount_spec, "server"); share = g_mount_spec_get (mount_spec, "share"); diff --git a/daemon/gvfsdaemon.c b/daemon/gvfsdaemon.c index 935372ca..249296ff 100644 --- a/daemon/gvfsdaemon.c +++ b/daemon/gvfsdaemon.c @@ -779,13 +779,12 @@ daemon_start_mount (GVfsDaemon *daemon, GMountSource *mount_source; dbus_bool_t automount; - dbus_id = dbus_message_get_sender (message); - dbus_message_iter_init (message, &iter); mount_spec = NULL; dbus_error_init (&derror); if (!_g_dbus_message_iter_get_args (&iter, &derror, + DBUS_TYPE_STRING, &dbus_id, DBUS_TYPE_OBJECT_PATH, &obj_path, DBUS_TYPE_BOOLEAN, &automount, 0)) diff --git a/daemon/mount.c b/daemon/mount.c index cc60cc7c..a135ea68 100644 --- a/daemon/mount.c +++ b/daemon/mount.c @@ -102,64 +102,55 @@ lookup_mountable (GMountSpec *spec) } static void -exec_mount (GMountOperationDBus *op, - Mountable *mountable) +exec_mount (Mountable *mountable, + GMountSource *source) { - DBusConnection *conn; - const char *id; char *exec; GError *error; + error = NULL; if (mountable->exec == NULL) { - error = NULL; g_set_error (&error, G_FILE_ERROR, G_FILE_ERROR_IO, "No exec key defined for mountpoint"); - g_mount_operation_dbus_fail_at_idle (op, error); + g_mount_source_failed (source, error); g_error_free (error); - return; } - - conn = dbus_bus_get (DBUS_BUS_SESSION, NULL); - id = dbus_bus_get_unique_name (conn); - - exec = g_strconcat (mountable->exec, " ", id, " ", op->obj_path, NULL); - - dbus_connection_unref (conn); - - if (!g_spawn_command_line_async (exec, &error)) + else { - g_mount_operation_dbus_fail_at_idle (op, error); - g_error_free (error); + exec = g_strconcat (mountable->exec, " ", g_mount_source_get_dbus_id (source), " ", g_mount_source_get_obj_path (source), NULL); + if (!g_spawn_command_line_async (exec, &error)) + { + g_mount_source_failed (source, error); + g_error_free (error); + } + g_free (exec); } - - g_free (exec); } static void dbus_mount_reply (DBusPendingCall *pending, void *user_data) { + GMountSource *source = user_data; Mountable *mountable; DBusMessage *reply; GError *error; - GMountOperationDBus *op = user_data; + mountable = g_object_get_data (G_OBJECT (source), "mountable"); + reply = dbus_pending_call_steal_reply (pending); dbus_pending_call_unref (pending); if (dbus_message_is_error (reply, DBUS_ERROR_NAME_HAS_NO_OWNER) || dbus_message_is_error (reply, DBUS_ERROR_SERVICE_UNKNOWN)) - { - mountable = g_object_get_data (G_OBJECT (op), "mountable"); - exec_mount (op, mountable); - } + exec_mount (mountable, source); else { error = NULL; if (_g_error_from_message (reply, &error)) { - g_mount_operation_dbus_fail_at_idle (op, error); + g_mount_source_failed (source, error); g_error_free (error); } } @@ -167,64 +158,60 @@ dbus_mount_reply (DBusPendingCall *pending, dbus_message_unref (reply); } -GMountOperation * +void mountable_mount (Mountable *mountable, - GMountSpec *spec, - gboolean is_automount) + GMountSource *source) { DBusConnection *conn; - GMountOperationDBus *op; DBusMessage *message; - DBusMessageIter iter; DBusPendingCall *pending; - dbus_bool_t automount; + GError *error = NULL; - op = g_mount_operation_dbus_new (spec); - g_object_set_data (G_OBJECT (op), "mountable", mountable); + if (mountable->dbus_name == NULL) + { + exec_mount (mountable, source); + return; + } + + conn = dbus_bus_get (DBUS_BUS_SESSION, NULL); + if (conn == NULL) + { + g_set_error (&error, G_FILE_ERROR, G_FILE_ERROR_IO, + "Error while getting peer-to-peer dbus connection"); + g_mount_source_failed (source, error); + g_error_free (error); + return; + } + + message = dbus_message_new_method_call (mountable->dbus_name, + G_VFS_DBUS_MOUNTABLE_PATH, + G_VFS_DBUS_MOUNTABLE_INTERFACE, + "mount"); + + g_mount_source_to_dbus (source, message); + if (!dbus_connection_send_with_reply (conn, message, + &pending, + 2000)) + _g_dbus_oom (); - if (mountable->dbus_name) + dbus_message_unref (message); + dbus_connection_unref (conn); + + if (pending == NULL) { - message = dbus_message_new_method_call (mountable->dbus_name, - G_VFS_DBUS_MOUNTABLE_PATH, - G_VFS_DBUS_MOUNTABLE_INTERFACE, - "mount"); - automount = is_automount; - if (!dbus_message_append_args (message, - DBUS_TYPE_OBJECT_PATH, &op->obj_path, - DBUS_TYPE_BOOLEAN, &automount, - 0)) - _g_dbus_oom (); - - dbus_message_iter_init_append (message, &iter); - g_mount_spec_to_dbus (&iter, spec); - - conn = dbus_bus_get (DBUS_BUS_SESSION, NULL); - - if (!dbus_connection_send_with_reply (conn, message, - &pending, - 2000)) - _g_dbus_oom (); - - dbus_connection_unref (conn); - dbus_message_unref (message); - - if (pending == NULL) - { - GError *error = NULL; - g_set_error (&error, G_FILE_ERROR, G_FILE_ERROR_IO, - "Error while getting peer-to-peer dbus connection: %s", - "Connection is closed"); - g_mount_operation_dbus_fail_at_idle (op, error); - g_error_free (error); - } - else if (!dbus_pending_call_set_notify (pending, - dbus_mount_reply, - g_object_ref (op), - g_object_unref)) - _g_dbus_oom (); + g_set_error (&error, G_FILE_ERROR, G_FILE_ERROR_IO, + "Error while getting peer-to-peer dbus connection: %s", + "Connection is closed"); + g_mount_source_failed (source, error); + g_error_free (error); + return; } - else - exec_mount (op, mountable); + + g_object_set_data (G_OBJECT (source), "mountable", mountable); - return G_MOUNT_OPERATION (op); + if (!dbus_pending_call_set_notify (pending, + dbus_mount_reply, + g_object_ref (source), + g_object_unref)) + _g_dbus_oom (); } diff --git a/daemon/mount.h b/daemon/mount.h index 5fe12048..aa4ce5fe 100644 --- a/daemon/mount.h +++ b/daemon/mount.h @@ -3,18 +3,17 @@ #include <glib-object.h> #include <gio/gmountoperation.h> -#include <gmountspec.h> +#include <gmountsource.h> G_BEGIN_DECLS typedef struct _Mountable Mountable; -void mount_init (void); -Mountable * lookup_mountable (GMountSpec *spec); -gboolean mountable_is_automount (Mountable *mountable); -GMountOperation *mountable_mount (Mountable *mountable, - GMountSpec *spec, - gboolean is_automount); +void mount_init (void); +Mountable *lookup_mountable (GMountSpec *spec); +gboolean mountable_is_automount (Mountable *mountable); +void mountable_mount (Mountable *mountable, + GMountSource *source); G_END_DECLS diff --git a/daemon/mounttracker.c b/daemon/mounttracker.c index b3a65539..e0a4c050 100644 --- a/daemon/mounttracker.c +++ b/daemon/mounttracker.c @@ -14,6 +14,7 @@ #include "gmountspec.h" #include "gvfsdaemonprotocol.h" #include <gio/gvfserror.h> +#include <gmountoperationdbus.h> #include <mount.h> typedef struct { @@ -265,7 +266,6 @@ automount_done (GMountOperation *op, g_object_unref (op); - dbus_connection_unref (data->connection); dbus_message_unref (data->message); g_free (data); @@ -290,16 +290,23 @@ maybe_automount (GMountTracker *tracker, { GMountOperation *op; AutoMountData *data; + GMountSource *mount_source; g_print ("automounting...\n"); - op = mountable_mount (mountable, spec, TRUE); - + op = g_mount_operation_new (); + mount_source = g_mount_operation_dbus_wrap (op, spec); + g_mount_source_set_is_automount (mount_source, TRUE); + data = g_new0 (AutoMountData, 1); data->tracker = tracker; data->message = dbus_message_ref (message); data->connection = dbus_connection_ref (connection); g_signal_connect (op, "done", (GCallback)automount_done, data); + + mountable_mount (mountable, mount_source); + g_object_unref (mount_source); + } else { @@ -415,6 +422,90 @@ list_mounts (GMountTracker *tracker, dbus_connection_send (connection, reply, NULL); } +static void +mount (GMountTracker *tracker, + DBusConnection *connection, + DBusMessage *message) +{ + DBusMessageIter iter; + DBusMessage *reply; + DBusError derror; + GMountSpec *spec; + const char *obj_path, *dbus_id; + GError *error; + Mountable *mountable; + dbus_bool_t automount; + + + dbus_message_iter_init (message, &iter); + + mountable = NULL; + spec = NULL; + dbus_error_init (&derror); + if (_g_dbus_message_iter_get_args (&iter, + &derror, + DBUS_TYPE_STRING, &dbus_id, + DBUS_TYPE_OBJECT_PATH, &obj_path, + DBUS_TYPE_BOOLEAN, &automount, + 0)) + { + spec = g_mount_spec_from_dbus (&iter); + if (spec != NULL) + { + VFSMount *mount; + mount = match_vfs_mount (tracker, spec); + if (mount != NULL) + { + error = NULL; + g_set_error (&error, G_VFS_ERROR, G_VFS_ERROR_ALREADY_MOUNTED, + _("Location is already mounted")); + reply = _dbus_message_new_error_from_gerror (message, error); + g_error_free (error); + } + else + { + mountable = lookup_mountable (spec); + + if (mountable != NULL) + reply = dbus_message_new_method_return (message); + else + { + error = NULL; + g_set_error (&error, G_VFS_ERROR, G_VFS_ERROR_NOT_MOUNTED, + _("Location is not mountable")); + reply = _dbus_message_new_error_from_gerror (message, error); + g_error_free (error); + } + } + } + else + reply = dbus_message_new_error (message, DBUS_ERROR_INVALID_ARGS, + "Invalid arguments"); + } + else + { + reply = dbus_message_new_error (message, derror.name, derror.message); + dbus_error_free (&derror); + } + + if (reply == NULL) + _g_dbus_oom (); + + dbus_connection_send (connection, reply, NULL); + + if (mountable) + { + GMountSource *source; + source = g_mount_source_new_dbus (dbus_id, obj_path, spec); + mountable_mount (mountable, source); + g_object_unref (source); + } + + if (spec) + g_mount_spec_unref (spec); + +} + static DBusHandlerResult dbus_message_function (DBusConnection *connection, DBusMessage *message, @@ -437,6 +528,10 @@ dbus_message_function (DBusConnection *connection, G_VFS_DBUS_MOUNTTRACKER_INTERFACE, "listMounts")) list_mounts (tracker, connection, message); + else if (dbus_message_is_method_call (message, + G_VFS_DBUS_MOUNTTRACKER_INTERFACE, + G_VFS_DBUS_MOUNTTRACKER_OP_MOUNT)) + mount (tracker, connection, message); else res = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; diff --git a/daemon/smb.mount.in b/daemon/smb.mount.in index e6d8374e..f78c61ef 100644 --- a/daemon/smb.mount.in +++ b/daemon/smb.mount.in @@ -1,4 +1,4 @@ [Mount] Type=smb-share Exec=@libexecdir@/gvfs-daemon-smb --dbus -AutoMount=true +AutoMount=false |