Commit 2e6f0c31 authored by Alexander Larsson's avatar Alexander Larsson

More work on mounting. Automount of smb now works (test).

Original git commit by Alexander Larsson <alex@greebo.(none)> at 1170415025 +0100

svn path=/trunk/; revision=296
parent 59503037
......@@ -76,7 +76,7 @@ get_mountspec_from_uri (GDecodedUri *uri,
{
spec = g_mount_spec_new ("smb-share");
g_mount_spec_add_item (spec, "server", uri->host);
g_mount_spec_set (spec, "server", uri->host);
share = uri->path + 1;
share_end = strchr (share, '/');
......@@ -86,7 +86,7 @@ get_mountspec_from_uri (GDecodedUri *uri,
else
tmp = g_strdup (share);
g_mount_spec_add_item (spec, "share", tmp);
g_mount_spec_set (spec, "share", tmp);
g_free (tmp);
if (share_end)
......
......@@ -21,6 +21,8 @@ static void mount_op_ask_question (GMountOperationDBus *op,
DBusMessage *message);
static void mount_op_done (GMountOperationDBus *op,
DBusMessage *message);
static void mount_op_get_mount_spec (GMountOperationDBus *op,
DBusMessage *message);
static void
g_mount_operation_dbus_finalize (GObject *object)
......@@ -67,9 +69,14 @@ g_mount_operation_dbus_init (GMountOperationDBus *operation)
}
GMountOperationDBus *
g_mount_operation_dbus_new (void)
g_mount_operation_dbus_new (GMountSpec *spec)
{
return g_object_new (G_TYPE_MOUNT_OPERATION_DBUS, NULL);
GMountOperationDBus *op;
op = g_object_new (G_TYPE_MOUNT_OPERATION_DBUS, NULL);
op->mount_spec = g_mount_spec_ref (spec);
return op;
}
......@@ -107,12 +114,31 @@ mount_op_message_function (DBusConnection *connection,
G_VFS_DBUS_MOUNT_OPERATION_INTERFACE,
"done"))
mount_op_done (op, message);
else if (dbus_message_is_method_call (message,
G_VFS_DBUS_MOUNT_OPERATION_INTERFACE,
"getMountSpec"))
mount_op_get_mount_spec (op, message);
else
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
return DBUS_HANDLER_RESULT_HANDLED;
}
static void
mount_op_get_mount_spec (GMountOperationDBus *op,
DBusMessage *message)
{
DBusMessage *reply;
DBusMessageIter iter;
reply = dbus_message_new_method_return (message);
dbus_message_iter_init_append (reply, &iter);
g_mount_spec_to_dbus (&iter, op->mount_spec);
if (!dbus_connection_send (op->connection, reply, NULL))
_g_dbus_oom ();
}
static void
mount_op_send_reply (GMountOperationDBus *op,
......
......@@ -5,6 +5,7 @@
#include <glib-object.h>
#include <gio/gmountoperation.h>
#include <gmountspec.h>
#include <dbus/dbus.h>
G_BEGIN_DECLS
......@@ -25,6 +26,7 @@ struct _GMountOperationDBus
char *obj_path;
DBusConnection *connection;
GMountSpec *mount_spec;
};
struct _GMountOperationDBusClass
......@@ -34,7 +36,7 @@ struct _GMountOperationDBusClass
GType g_mount_operation_dbus_get_type (void) G_GNUC_CONST;
GMountOperationDBus * g_mount_operation_dbus_new (void);
GMountOperationDBus * g_mount_operation_dbus_new (GMountSpec *spec);
G_END_DECLS
......
......@@ -27,7 +27,7 @@ g_mount_spec_new (const char *type)
spec->items = g_array_new (FALSE, TRUE, sizeof (GMountSpecItem));
if (type != NULL)
g_mount_spec_add_item (spec, "type", type);
g_mount_spec_set (spec, "type", type);
return spec;
}
......@@ -47,9 +47,9 @@ add_item (GMountSpec *spec,
void
g_mount_spec_add_item (GMountSpec *spec,
const char *key,
const char *value)
g_mount_spec_set (GMountSpec *spec,
const char *key,
const char *value)
{
add_item (spec, key, g_strdup (value));
g_array_sort (spec->items, item_compare);
......@@ -253,7 +253,8 @@ g_mount_spec_match (GMountSpec *mount,
}
const char *
g_mount_spec_get_type (GMountSpec *spec)
g_mount_spec_get (GMountSpec *spec,
const char *key)
{
int i;
......@@ -261,9 +262,16 @@ g_mount_spec_get_type (GMountSpec *spec)
{
GMountSpecItem *item = &g_array_index (spec->items, GMountSpecItem, i);
if (strcmp (item->key, "type") == 0)
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");
}
......@@ -44,7 +44,7 @@ void g_mount_spec_to_dbus (DBusMessageIter *iter,
void g_mount_spec_to_dbus_with_path (DBusMessageIter *iter,
GMountSpec *spec,
const char *path);
void g_mount_spec_add_item (GMountSpec *spec,
void g_mount_spec_set (GMountSpec *spec,
const char *key,
const char *value);
gboolean g_mount_spec_match (GMountSpec *mount,
......@@ -52,6 +52,8 @@ gboolean g_mount_spec_match (GMountSpec *mount,
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);
G_END_DECLS
......
......@@ -10,3 +10,4 @@ gvfs-daemon
gvfs-daemon-smb
gvfs-daemon-test
*.service
*.mount
......@@ -6,7 +6,7 @@ INCLUDES = \
-I$(top_builddir) \
$(GLIB_CFLAGS) $(DBUS_CFLAGS) \
-DDBUS_API_SUBJECT_TO_CHANGE \
-DMOUNTPOINT_DIR=\"$(sysconfdir)/gvfs/mounts/\" \
-DMOUNTABLE_DIR=\"$(sysconfdir)/gvfs/mounts/\" \
-DG_DISABLE_DEPRECATED
noinst_LTLIBRARIES=libdaemon.la
......@@ -25,15 +25,21 @@ servicedir = $(DBUS_SERVICE_DIR)
service_in_files = gvfs-daemon.service.in
service_DATA = gvfs-daemon.service
%.mount: %.mount.in ../config.log
sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
mountdir = $(sysconfdir)/gvfs/mounts
mount_in_files = smb.mount.in
mount_DATA = smb.mount
EXTRA_DIST = gvfs-daemon.service.in
DISTCLEANFILES = gvfs-daemon.service
libexec_PROGRAMS=gvfs-daemon
libexec_PROGRAMS=gvfs-daemon gvfs-daemon-smb
noinst_PROGRAMS = \
gvfs-daemon-test \
gvfs-daemon-smb \
$(NULL)
libdaemon_la_SOURCES = \
......@@ -56,6 +62,7 @@ libdaemon_la_SOURCES = \
gvfs_daemon_SOURCES = \
mounttracker.c mounttracker.h \
mount.c mount.h \
main.c
gvfs_daemon_LDADD = $(libraries)
......
......@@ -247,8 +247,8 @@ create_smb_uri (const char *server,
}
GVfsBackendSmb *
g_vfs_backend_smb_new (const char *server,
const char *share)
g_vfs_backend_smb_new (GMountSpec *spec,
GError **error)
{
GVfsBackendSmb *backend;
GVfsBackend *_backend;
......@@ -256,12 +256,32 @@ g_vfs_backend_smb_new (const char *server,
int res;
char *uri;
struct stat st;
const char *server;
const char *share;
g_assert (smb_backend == NULL);
server = g_mount_spec_get (spec, "server");
share = g_mount_spec_get (spec, "share");
if (server == NULL ||
share == NULL)
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL,
_("Invalid mount spec"));
return NULL;
}
smb_context = smbc_new_context ();
if (smb_context == NULL)
return NULL;
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_IO,
"Failed to allocate smb context");
return NULL;
}
smb_context->debug = 0;
smb_context->callbacks.auth_fn = auth_callback;
......@@ -286,7 +306,8 @@ g_vfs_backend_smb_new (const char *server,
if (!smbc_init_context (smb_context))
{
g_print ("init context failed\n");
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_IO,
"Failed to initialize smb context");
smbc_free_context (smb_context, FALSE);
return NULL;
}
......@@ -300,10 +321,10 @@ g_vfs_backend_smb_new (const char *server,
_backend = G_VFS_BACKEND (backend);
_backend->display_name = g_strdup_printf ("%s on %s", share, server);
_backend->mount_spec = g_mount_spec_new ("smb-share");
g_mount_spec_add_item (_backend->mount_spec,
"share", share);
g_mount_spec_add_item (_backend->mount_spec,
"server", server);
g_mount_spec_set (_backend->mount_spec,
"share", share);
g_mount_spec_set (_backend->mount_spec,
"server", server);
smb_backend = backend;
backend->smb_context = smb_context;
......@@ -313,6 +334,8 @@ g_vfs_backend_smb_new (const char *server,
g_free (uri);
if (res != 0)
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_IO,
"Failed to mount smb share");
g_object_unref (backend);
return NULL;
}
......
......@@ -2,6 +2,7 @@
#define __G_VFS_BACKEND_SMB_H__
#include <gvfsbackend.h>
#include <gmountspec.h>
#include <libsmbclient.h>
......@@ -41,8 +42,8 @@ struct _GVfsBackendSmbClass
GType g_vfs_backend_smb_get_type (void) G_GNUC_CONST;
GVfsBackendSmb *g_vfs_backend_smb_new (const char *server,
const char *share);
GVfsBackendSmb *g_vfs_backend_smb_new (GMountSpec *mount_spec,
GError **error);
G_END_DECLS
......
......@@ -8,6 +8,7 @@
#include "gvfsbackendtest.h"
#include <gvfsdaemonprotocol.h>
#include "mounttracker.h"
#include "mount.h"
int
main (int argc, char *argv[])
......@@ -46,6 +47,8 @@ main (int argc, char *argv[])
if (daemon == NULL)
return 1;
mount_init ();
g_mount_tracker_new ();
loop = g_main_loop_new (NULL, FALSE);
......
#include <config.h>
#include <string.h>
#include <glib.h>
#include <dbus/dbus.h>
#include <glib/gi18n.h>
#include "mount.h"
#include "gmountoperationdbus.h"
struct _Mountable {
char *type;
char *exec;
gboolean automount;
};
static GList *mountables;
void
mount_init (void)
{
GDir *dir;
char *mount_dir, *path;
const char *filename;
GKeyFile *keyfile;
char *type, *exec;
Mountable *mountable;
gboolean automount;
mount_dir = MOUNTABLE_DIR;
dir = g_dir_open (mount_dir, 0, NULL);
if (dir)
{
while ((filename = g_dir_read_name (dir)) != NULL)
{
path = g_build_filename (mount_dir, filename, NULL);
keyfile = g_key_file_new ();
if (g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, NULL))
{
type = g_key_file_get_string (keyfile, "Mount", "Type", NULL);
exec = g_key_file_get_string (keyfile, "Mount", "Exec", NULL);
automount = g_key_file_get_boolean (keyfile, "Mount", "AutoMount", NULL);
if (type != NULL && exec != NULL)
{
mountable = g_new0 (Mountable, 1);
mountable->type = g_strdup (type);
mountable->exec = g_strdup (exec);
mountable->automount = automount;
mountables = g_list_prepend (mountables, mountable);
}
g_free (type);
g_free (exec);
}
g_key_file_free (keyfile);
g_free (path);
}
}
}
gboolean
mountable_is_automount (Mountable *mountable)
{
return mountable->automount;
}
static Mountable *
find_mountable (const char *type)
{
GList *l;
for (l = mountables; l != NULL; l = l->next)
{
Mountable *mountable = l->data;
if (strcmp (mountable->type, type) == 0)
return mountable;
}
return NULL;
}
Mountable *
lookup_mountable (GMountSpec *spec)
{
const char *type;
type = g_mount_spec_get_type (spec);
if (type == NULL)
return NULL;
return find_mountable (type);
}
GMountOperation *
mountable_mount (Mountable *mountable,
GMountSpec *spec,
GError **error)
{
DBusConnection *conn;
const char *id;
char *exec;
gboolean res;
GMountOperationDBus *op;
conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
id = dbus_bus_get_unique_name (conn);
dbus_connection_unref (conn);
op = g_mount_operation_dbus_new (spec);
exec = g_strconcat (mountable->exec, " ", id, " ", op->obj_path, NULL);
res = g_spawn_command_line_async (exec, error);
g_free (exec);
if (!res)
{
g_object_unref (op);
return NULL;
}
return G_MOUNT_OPERATION (op);
}
#ifndef __MOUNT_H__
#define __MOUNT_H__
#include <glib-object.h>
#include <gio/gmountoperation.h>
#include <gmountspec.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,
GError **error);
G_END_DECLS
#endif /* __MOUNT_H__ */
......@@ -14,6 +14,7 @@
#include "gmountspec.h"
#include "gvfsdaemonprotocol.h"
#include <gio/gvfserror.h>
#include <mount.h>
typedef struct {
char *key;
......@@ -39,6 +40,11 @@ struct _GMountTracker
GList *mounts;
};
static void lookup_mount (GMountTracker *tracker,
DBusConnection *connection,
DBusMessage *message,
gboolean do_automount);
G_DEFINE_TYPE (GMountTracker, g_mount_tracker, G_TYPE_OBJECT);
static VFSMount *
......@@ -223,32 +229,129 @@ register_mount (GMountTracker *tracker,
dbus_connection_send (connection, reply, NULL);
}
typedef struct {
DBusMessage *message;
DBusConnection *connection;
GMountTracker *tracker;
} AutoMountData;
static void
automount_done (GMountOperation *op,
gboolean succeeded,
GError *error,
gpointer _data)
{
DBusMessage *reply;
AutoMountData *data = _data;
if (!succeeded)
{
GError *mount_error = NULL;
g_set_error (&mount_error, G_VFS_ERROR, G_VFS_ERROR_NOT_MOUNTED,
_("Automount failed: %s"), error->message);
reply = _dbus_message_new_error_from_gerror (data->message, mount_error);
g_error_free (mount_error);
dbus_connection_send (data->connection, reply, NULL);
}
else
lookup_mount (data->tracker,
data->connection,
data->message,
FALSE);
g_object_unref (op);
dbus_connection_unref (data->connection);
dbus_message_unref (data->message);
g_free (data);
}
static DBusMessage *
maybe_automount (GMountTracker *tracker,
GMountSpec *spec,
DBusMessage *message,
DBusConnection *connection,
gboolean do_automount)
{
Mountable *mountable;
DBusMessage *reply;
GError *error;
mountable = lookup_mountable (spec);
g_print ("mountable: %p, do-automount: %d, is_automount: %d\n",
mountable, do_automount,
mountable_is_automount (mountable));
reply = NULL;
if (mountable != NULL && do_automount &&
mountable_is_automount (mountable))
{
GMountOperation *op;
GError *mount_error;
g_print ("automounting...\n");
mount_error = NULL;
op = mountable_mount (mountable, spec, &error);
g_print ("op = %p\n", op);
if (op == NULL)
{
error = NULL;
g_set_error (&error, G_VFS_ERROR, G_VFS_ERROR_NOT_MOUNTED,
_("Error automounting location: %s"), mount_error->message);
reply = _dbus_message_new_error_from_gerror (message, error);
g_error_free (mount_error);
g_error_free (error);
}
else
{
AutoMountData *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);
}
}
else
{
error = NULL;
g_set_error (&error, G_VFS_ERROR, G_VFS_ERROR_NOT_MOUNTED,
(mountable == NULL) ?
_("Location is not mountable") :
_("Location is not mounted"));
reply = _dbus_message_new_error_from_gerror (message, error);
g_error_free (error);
}
return reply;
}
static void
lookup_mount (GMountTracker *tracker,
DBusConnection *connection,
DBusMessage *message)
DBusMessage *message,
gboolean do_automount)
{
VFSMount *mount;
DBusMessage *reply;
DBusMessageIter iter;
GMountSpec *spec;
GError *error;
dbus_message_iter_init (message, &iter);
spec = g_mount_spec_from_dbus (&iter);
reply = NULL;
if (spec != NULL)
{
mount = match_vfs_mount (tracker, spec);
if (mount == NULL)
{
error = NULL;
g_set_error (&error, G_VFS_ERROR, G_VFS_ERROR_NOT_MOUNTED,
_("Location is not mounted"));
reply = _dbus_message_new_error_from_gerror (message, error);
g_error_free (error);
}
reply = maybe_automount (tracker, spec