summaryrefslogtreecommitdiff
path: root/daemon
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@src.gnome.org>2007-09-13 11:53:50 +0000
committerAlexander Larsson <alexl@src.gnome.org>2007-09-13 11:53:50 +0000
commit0d563301b7ad117c2938279cb5d4bb4a352821db (patch)
treed886e8eb032e0eb9b1b3ec4160d67c5c83831d9a /daemon
parentcff8ac68e7cbbc9aa2e645555c2eeeffec143ba4 (diff)
downloadgvfs-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.am1
-rw-r--r--daemon/gvfsbackendsmb.c120
-rw-r--r--daemon/gvfsdaemon.c3
-rw-r--r--daemon/mount.c139
-rw-r--r--daemon/mount.h13
-rw-r--r--daemon/mounttracker.c101
-rw-r--r--daemon/smb.mount.in2
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