1
/* GIO - GLib Input, Output and Streaming Library
3
* Copyright (C) 2006-2007 Red Hat, Inc.
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2 of the License, or (at your option) any later version.
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
15
* You should have received a copy of the GNU Lesser General
16
* Public License along with this library; if not, write to the
17
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18
* Boston, MA 02111-1307, USA.
20
* Author: Alexander Larsson <alexl@redhat.com>
28
#include <dbus/dbus.h>
29
#include "gdaemonvfs.h"
30
#include "gvfsuriutils.h"
31
#include "gdaemonfile.h"
33
#include <gvfsdaemonprotocol.h>
35
#include "gvfsdaemondbus.h"
36
#include "gvfsdbusutils.h"
37
#include "gmountspec.h"
38
#include "gvfsurimapper.h"
39
#include "gdaemonvolumemonitor.h"
41
#include "gvfsiconloadable.h"
42
#include <glib/gi18n-lib.h>
43
#include <glib/gstdio.h>
48
char **scheme_aliases;
50
gboolean host_is_inet;
57
DBusConnection *async_bus;
64
GHashTable *from_uri_hash;
65
GHashTable *to_uri_hash;
67
MountableInfo **mountable_info;
68
char **supported_uri_schemes;
71
struct _GDaemonVfsClass
73
GVfsClass parent_class;
76
G_DEFINE_DYNAMIC_TYPE (GDaemonVfs, g_daemon_vfs, G_TYPE_VFS)
78
static GDaemonVfs *the_vfs = NULL;
80
G_LOCK_DEFINE_STATIC(mount_cache);
83
static void fill_mountable_info (GDaemonVfs *vfs);
86
g_daemon_vfs_finalize (GObject *object)
90
vfs = G_DAEMON_VFS (object);
92
if (vfs->from_uri_hash)
93
g_hash_table_destroy (vfs->from_uri_hash);
96
g_hash_table_destroy (vfs->to_uri_hash);
98
g_strfreev (vfs->supported_uri_schemes);
102
dbus_connection_close (vfs->async_bus);
103
dbus_connection_unref (vfs->async_bus);
106
if (vfs->wrapped_vfs)
107
g_object_unref (vfs->wrapped_vfs);
110
G_OBJECT_CLASS (g_daemon_vfs_parent_class)->finalize (object);
113
static MountableInfo *
114
get_mountable_info_for_scheme (GDaemonVfs *vfs,
120
if (vfs->mountable_info == NULL)
123
for (i = 0; vfs->mountable_info[i] != NULL; i++)
125
info = vfs->mountable_info[i];
127
if (info->scheme != NULL && strcmp (info->scheme, scheme) == 0)
130
if (info->scheme_aliases != NULL)
132
for (j = 0; info->scheme_aliases[j] != NULL; j++)
134
if (strcmp (info->scheme_aliases[j], scheme) == 0)
144
static MountableInfo *
145
get_mountable_info_for_type (GDaemonVfs *vfs,
151
if (vfs->mountable_info == NULL)
154
for (i = 0; vfs->mountable_info[i] != NULL; i++)
156
info = vfs->mountable_info[i];
158
if (strcmp (info->type, type) == 0)
166
str_tolower_inplace (char *str)
172
*p = g_ascii_tolower (*p);
179
get_mountspec_from_uri (GDaemonVfs *vfs,
181
GMountSpec **spec_out,
186
GVfsUriMapper *mapper;
188
GVfsUriMountInfo *info;
190
scheme = g_uri_parse_scheme (uri);
194
/* convert the scheme to lower case since g_uri_parse_scheme
195
* doesn't do that and we compare with g_str_equal */
196
str_tolower_inplace (scheme);
201
mapper = g_hash_table_lookup (vfs->from_uri_hash, scheme);
205
info = g_vfs_uri_mapper_from_uri (mapper, uri);
208
spec = g_mount_spec_new_from_data (info->keys, NULL);
210
/* We took over ownership of info parts, custom free: */
217
GDecodedUri *decoded;
218
MountableInfo *mountable;
222
decoded = g_vfs_decode_uri (uri);
225
mountable = get_mountable_info_for_scheme (vfs, decoded->scheme);
228
type = mountable->type;
230
type = decoded->scheme;
232
spec = g_mount_spec_new (type);
234
if (decoded->host && *decoded->host)
236
if (mountable && mountable->host_is_inet)
238
/* Convert hostname to lower case */
239
str_tolower_inplace (decoded->host);
241
/* Remove brackets aroung ipv6 addresses */
242
l = strlen (decoded->host);
243
if (decoded->host[0] == '[' &&
244
decoded->host[l - 1] == ']')
245
g_mount_spec_set_with_len (spec, "host", decoded->host+1, l - 2);
247
g_mount_spec_set (spec, "host", decoded->host);
250
g_mount_spec_set (spec, "host", decoded->host);
253
if (decoded->userinfo && *decoded->userinfo)
254
g_mount_spec_set (spec, "user", decoded->userinfo);
256
if (decoded->port != -1 &&
257
(mountable == NULL ||
258
mountable->default_port == 0 ||
259
mountable->default_port != decoded->port))
261
char *port = g_strdup_printf ("%d", decoded->port);
262
g_mount_spec_set (spec, "port", port);
266
if (decoded->query && *decoded->query)
267
g_mount_spec_set (spec, "query", decoded->query);
268
if (decoded->fragment && *decoded->fragment)
269
g_mount_spec_set (spec, "fragment", decoded->fragment);
271
path = g_strdup (decoded->path);
273
g_vfs_decoded_uri_free (decoded);
289
g_daemon_vfs_init (GDaemonVfs *vfs)
293
const char * const *schemes, * const *mount_types;
294
GVfsUriMapper *mapper;
299
bindtextdomain (GETTEXT_PACKAGE, GVFS_LOCALEDIR);
300
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
302
if (g_thread_supported ())
303
dbus_threads_init_default ();
305
vfs->async_bus = dbus_bus_get_private (DBUS_BUS_SESSION, NULL);
307
if (vfs->async_bus == NULL)
308
return; /* Not supported, return here and return false in vfs_is_active() */
310
g_assert (the_vfs == NULL);
313
/* We disable SIGPIPE globally. This is sort of bad
314
for s library to do since its a global resource.
315
However, without this there is no way to be able
316
to handle mount daemons dying without client apps
317
crashing, which is much worse.
319
I blame Unix, there really should be a portable
320
way to do this on all unixes, but there isn't,
321
even for somewhat modern ones like solaris.
323
signal (SIGPIPE, SIG_IGN);
325
fill_mountable_info (vfs);
327
vfs->wrapped_vfs = g_vfs_get_local ();
329
file = g_build_filename (g_get_home_dir(), ".gvfs", NULL);
330
vfs->fuse_root = g_vfs_get_file_for_path (vfs->wrapped_vfs, file);
333
dbus_connection_set_exit_on_disconnect (vfs->async_bus, FALSE);
335
_g_dbus_connection_integrate_with_main (vfs->async_bus);
337
modules = g_io_modules_load_all_in_directory (GVFS_MODULE_DIR);
339
vfs->from_uri_hash = g_hash_table_new (g_str_hash, g_str_equal);
340
vfs->to_uri_hash = g_hash_table_new (g_str_hash, g_str_equal);
342
mappers = g_type_children (G_VFS_TYPE_URI_MAPPER, &n_mappers);
344
for (i = 0; i < n_mappers; i++)
347
mapper = g_object_new (mappers[i], NULL);
349
schemes = g_vfs_uri_mapper_get_handled_schemes (mapper);
351
for (j = 0; schemes != NULL && schemes[j] != NULL; j++)
352
g_hash_table_insert (vfs->from_uri_hash, (char *)schemes[j], mapper);
354
mount_types = g_vfs_uri_mapper_get_handled_mount_types (mapper);
355
for (j = 0; mount_types != NULL && mount_types[j] != NULL; j++)
356
g_hash_table_insert (vfs->to_uri_hash, (char *)mount_types[j], mapper);
359
/* The above should have ref:ed the modules anyway */
360
g_list_foreach (modules, (GFunc)g_type_module_unuse, NULL);
361
g_list_free (modules);
366
g_daemon_vfs_new (void)
368
return g_object_new (G_TYPE_DAEMON_VFS, NULL);
371
/* This unrefs file if its changed */
373
convert_fuse_path (GVfs *vfs,
377
char *fuse_path, *mount_path;
378
GMountInfo *mount_info;
380
fuse_root = ((GDaemonVfs *)vfs)->fuse_root;
381
if (g_file_has_prefix (file, fuse_root))
383
fuse_path = g_file_get_path (file);
384
mount_info = _g_daemon_vfs_get_mount_info_by_fuse_sync (fuse_path, &mount_path);
388
g_object_unref (file);
389
file = g_daemon_file_new (mount_info->mount_spec, mount_path);
391
g_mount_info_unref (mount_info);
398
g_daemon_vfs_get_file_for_path (GVfs *vfs,
403
file = g_vfs_get_file_for_path (G_DAEMON_VFS (vfs)->wrapped_vfs, path);
404
file = convert_fuse_path (vfs, file);
409
g_daemon_vfs_get_file_for_uri (GVfs *vfs,
412
GDaemonVfs *daemon_vfs;
417
daemon_vfs = G_DAEMON_VFS (vfs);
419
if (g_ascii_strncasecmp (uri, "file:", 5) == 0)
421
path = g_filename_from_uri (uri, NULL, NULL);
425
return g_vfs_get_file_for_uri (G_DAEMON_VFS (vfs)->wrapped_vfs, uri);
427
file = g_daemon_vfs_get_file_for_path (vfs, path);
432
if (get_mountspec_from_uri (daemon_vfs, uri, &spec, &path))
434
file = g_daemon_file_new (spec, path);
435
g_mount_spec_unref (spec);
441
return g_vfs_get_file_for_uri (G_DAEMON_VFS (vfs)->wrapped_vfs, uri);
445
_g_daemon_vfs_get_mount_spec_for_path (GMountSpec *spec,
447
const char *new_path)
450
GVfsUriMapper *mapper;
451
GMountSpec *new_spec;
453
type = g_mount_spec_get_type (spec);
456
return g_mount_spec_ref (spec);
459
mapper = g_hash_table_lookup (the_vfs->to_uri_hash, type);
462
GVfsUriMountInfo info, *new_info;
463
info.keys = spec->items;
464
info.path = (char *)path;
465
new_info = g_vfs_uri_mapper_get_mount_info_for_path (mapper, &info, new_path);
466
if (new_info != NULL)
468
new_spec = g_mount_spec_new_from_data (new_info->keys, NULL);
469
/* We took over ownership of parts of new_info, custom free: */
470
g_free (new_info->path);
475
if (new_spec == NULL)
476
new_spec = g_mount_spec_ref (spec);
482
_g_daemon_vfs_get_uri_for_mountspec (GMountSpec *spec,
488
GVfsUriMapper *mapper;
490
type = g_mount_spec_get_type (spec);
493
GString *string = g_string_new ("unknown://");
495
g_string_append_uri_escaped (string,
500
return g_string_free (string, FALSE);
504
mapper = g_hash_table_lookup (the_vfs->to_uri_hash, type);
507
GVfsUriMountInfo info;
508
info.keys = spec->items;
510
uri = g_vfs_uri_mapper_to_uri (mapper, &info, allow_utf8);
516
MountableInfo *mountable;
520
memset (&decoded, 0, sizeof (decoded));
523
mountable = get_mountable_info_for_type (the_vfs, type);
526
decoded.scheme = mountable->scheme;
528
decoded.scheme = (char *)type;
529
decoded.host = (char *)g_mount_spec_get (spec, "host");
531
if (mountable && mountable->host_is_inet && decoded.host != NULL && strchr (decoded.host, ':') != NULL)
534
decoded.host = g_strconcat ("[", decoded.host, "]", NULL);
537
decoded.userinfo = (char *)g_mount_spec_get (spec, "user");
538
port = g_mount_spec_get (spec, "port");
540
decoded.port = atoi (port);
547
decoded.query = (char *)g_mount_spec_get (spec, "query");
548
decoded.fragment = (char *)g_mount_spec_get (spec, "fragment");
550
uri = g_vfs_encode_uri (&decoded, FALSE);
553
g_free (decoded.host);
560
_g_daemon_vfs_mountspec_get_uri_scheme (GMountSpec *spec)
562
const char *type, *scheme;
563
GVfsUriMapper *mapper;
564
MountableInfo *mountable;
566
type = g_mount_spec_get_type (spec);
567
mapper = g_hash_table_lookup (the_vfs->to_uri_hash, type);
572
GVfsUriMountInfo info;
574
info.keys = spec->items;
577
scheme = g_vfs_uri_mapper_to_uri_scheme (mapper, &info);
582
mountable = get_mountable_info_for_type (the_vfs, type);
584
scheme = mountable->scheme;
593
find_string (GPtrArray *array, const char *find_me)
597
g_return_val_if_fail (find_me != NULL, -1);
599
for (i = 0; i < array->len; ++i)
601
if (strcmp (g_ptr_array_index (array, i), find_me) == 0)
610
fill_mountable_info (GDaemonVfs *vfs)
612
DBusMessage *message, *reply;
614
DBusMessageIter iter, array_iter, struct_iter;
616
GPtrArray *infos, *uri_schemes;
619
message = dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
620
G_VFS_DBUS_MOUNTTRACKER_PATH,
621
G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
622
G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNTABLE_INFO);
627
dbus_message_set_auto_start (message, TRUE);
629
dbus_error_init (&error);
630
reply = dbus_connection_send_with_reply_and_block (vfs->async_bus,
632
G_VFS_DBUS_TIMEOUT_MSECS,
634
dbus_message_unref (message);
636
if (dbus_error_is_set (&error))
638
dbus_error_free (&error);
645
dbus_message_iter_init (reply, &iter);
647
dbus_message_iter_recurse (&iter, &array_iter);
649
infos = g_ptr_array_new ();
650
uri_schemes = g_ptr_array_new ();
651
g_ptr_array_add (uri_schemes, g_strdup ("file"));
654
char *type, *scheme, **scheme_aliases;
655
int scheme_aliases_len;
657
dbus_bool_t host_is_inet;
659
if (dbus_message_iter_get_arg_type (&array_iter) != DBUS_TYPE_STRUCT)
662
dbus_message_iter_recurse (&array_iter, &struct_iter);
664
if (!_g_dbus_message_iter_get_args (&struct_iter, NULL,
665
DBUS_TYPE_STRING, &type,
666
DBUS_TYPE_STRING, &scheme,
667
DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &scheme_aliases, &scheme_aliases_len,
668
DBUS_TYPE_INT32, &default_port,
669
DBUS_TYPE_BOOLEAN, &host_is_inet,
673
info = g_new0 (MountableInfo, 1);
674
info->type = g_strdup (type);
677
info->scheme = g_strdup (scheme);
678
if (find_string (uri_schemes, scheme) == -1)
679
g_ptr_array_add (uri_schemes, g_strdup (scheme));
682
if (scheme_aliases_len > 0)
684
info->scheme_aliases = g_new (char *, scheme_aliases_len + 1);
685
for (i = 0; i < scheme_aliases_len; i++)
687
info->scheme_aliases[i] = g_strdup (scheme_aliases[i]);
688
if (find_string (uri_schemes, scheme_aliases[i]) == -1)
689
g_ptr_array_add (uri_schemes, g_strdup (scheme_aliases[i]));
691
info->scheme_aliases[scheme_aliases_len] = NULL;
694
info->default_port = default_port;
695
info->host_is_inet = host_is_inet;
697
g_ptr_array_add (infos, info);
699
g_strfreev (scheme_aliases);
701
while (dbus_message_iter_next (&array_iter));
703
dbus_message_unref (reply);
705
g_ptr_array_add (uri_schemes, NULL);
706
g_ptr_array_add (infos, NULL);
707
vfs->mountable_info = (MountableInfo **)g_ptr_array_free (infos, FALSE);
708
vfs->supported_uri_schemes = (char **)g_ptr_array_free (uri_schemes, FALSE);
712
static const gchar * const *
713
g_daemon_vfs_get_supported_uri_schemes (GVfs *vfs)
715
return (const gchar * const *) G_DAEMON_VFS (vfs)->supported_uri_schemes;
719
lookup_mount_info_in_cache_locked (GMountSpec *spec,
726
for (l = the_vfs->mount_cache; l != NULL; l = l->next)
728
GMountInfo *mount_info = l->data;
730
if (g_mount_spec_match_with_path (mount_info->mount_spec, spec, path))
732
info = g_mount_info_ref (mount_info);
741
lookup_mount_info_in_cache (GMountSpec *spec,
746
G_LOCK (mount_cache);
747
info = lookup_mount_info_in_cache_locked (spec, path);
748
G_UNLOCK (mount_cache);
754
lookup_mount_info_by_fuse_path_in_cache (const char *fuse_path,
760
G_LOCK (mount_cache);
762
for (l = the_vfs->mount_cache; l != NULL; l = l->next)
764
GMountInfo *mount_info = l->data;
766
if (mount_info->fuse_mountpoint != NULL &&
767
g_str_has_prefix (fuse_path, mount_info->fuse_mountpoint))
769
int len = strlen (mount_info->fuse_mountpoint);
770
if (fuse_path[len] == 0 ||
771
fuse_path[len] == '/')
773
if (fuse_path[len] == 0)
774
*mount_path = g_strdup ("/");
776
*mount_path = g_strdup (fuse_path + len);
777
info = g_mount_info_ref (mount_info);
782
G_UNLOCK (mount_cache);
789
_g_daemon_vfs_invalidate_dbus_id (const char *dbus_id)
793
G_LOCK (mount_cache);
794
for (l = the_vfs->mount_cache; l != NULL; l = next)
796
GMountInfo *mount_info = l->data;
799
if (strcmp (mount_info->dbus_id, dbus_id) == 0)
801
the_vfs->mount_cache = g_list_delete_link (the_vfs->mount_cache, l);
802
g_mount_info_unref (mount_info);
806
G_UNLOCK (mount_cache);
811
handler_lookup_mount_reply (DBusMessage *reply,
816
DBusMessageIter iter;
821
if (_g_error_from_message (reply, error))
824
dbus_error_init (&derror);
825
dbus_message_iter_init (reply, &iter);
827
info = g_mount_info_from_dbus (&iter);
830
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
831
_("Error while getting mount info: %s"),
836
G_LOCK (mount_cache);
839
/* Already in cache from other thread? */
840
for (l = the_vfs->mount_cache; l != NULL; l = l->next)
842
GMountInfo *cached_info = l->data;
844
if (g_mount_info_equal (info, cached_info))
847
g_mount_info_unref (info);
848
info = g_mount_info_ref (cached_info);
853
/* No, lets add it to the cache */
855
the_vfs->mount_cache = g_list_prepend (the_vfs->mount_cache, g_mount_info_ref (info));
857
G_UNLOCK (mount_cache);
863
GMountInfoLookupCallback callback;
869
async_get_mount_info_response (DBusMessage *reply,
873
GetMountInfoData *data = _data;
878
data->callback (NULL, data->user_data, io_error);
882
info = handler_lookup_mount_reply (reply, &error);
884
data->callback (info, data->user_data, error);
887
g_mount_info_unref (info);
890
g_error_free (error);
897
async_get_mount_info_cache_hit (gpointer _data)
899
GetMountInfoData *data = _data;
900
data->callback (data->info, data->user_data, NULL);
901
g_mount_info_unref (data->info);
907
_g_daemon_vfs_get_mount_info_async (GMountSpec *spec,
909
GMountInfoLookupCallback callback,
913
GetMountInfoData *data;
914
DBusMessage *message;
915
DBusMessageIter iter;
917
data = g_new0 (GetMountInfoData, 1);
918
data->callback = callback;
919
data->user_data = user_data;
921
info = lookup_mount_info_in_cache (spec, path);
926
g_idle_add (async_get_mount_info_cache_hit, data);
931
dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
932
G_VFS_DBUS_MOUNTTRACKER_PATH,
933
G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
934
G_VFS_DBUS_MOUNTTRACKER_OP_LOOKUP_MOUNT);
935
dbus_message_set_auto_start (message, TRUE);
937
dbus_message_iter_init_append (message, &iter);
938
g_mount_spec_to_dbus_with_path (&iter, spec, path);
941
_g_dbus_connection_call_async (the_vfs->async_bus, message, G_VFS_DBUS_TIMEOUT_MSECS,
942
async_get_mount_info_response,
945
dbus_message_unref (message);
950
_g_daemon_vfs_get_mount_info_sync (GMountSpec *spec,
955
DBusConnection *conn;
956
DBusMessage *message, *reply;
957
DBusMessageIter iter;
960
info = lookup_mount_info_in_cache (spec, path);
965
conn = _g_dbus_connection_get_sync (NULL, error);
970
dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
971
G_VFS_DBUS_MOUNTTRACKER_PATH,
972
G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
973
G_VFS_DBUS_MOUNTTRACKER_OP_LOOKUP_MOUNT);
974
dbus_message_set_auto_start (message, TRUE);
976
dbus_message_iter_init_append (message, &iter);
977
g_mount_spec_to_dbus_with_path (&iter, spec, path);
979
dbus_error_init (&derror);
980
reply = dbus_connection_send_with_reply_and_block (conn, message, -1, &derror);
981
dbus_message_unref (message);
985
_g_error_from_dbus (&derror, error);
986
dbus_error_free (&derror);
990
info = handler_lookup_mount_reply (reply, error);
992
dbus_message_unref (reply);
998
_g_daemon_vfs_get_mount_info_by_fuse_sync (const char *fuse_path,
1002
DBusConnection *conn;
1003
DBusMessage *message, *reply;
1004
DBusMessageIter iter;
1007
const char *mount_path_end;
1009
info = lookup_mount_info_by_fuse_path_in_cache (fuse_path,
1014
conn = _g_dbus_connection_get_sync (NULL, NULL);
1019
dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
1020
G_VFS_DBUS_MOUNTTRACKER_PATH,
1021
G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
1022
G_VFS_DBUS_MOUNTTRACKER_OP_LOOKUP_MOUNT_BY_FUSE_PATH);
1023
dbus_message_set_auto_start (message, TRUE);
1025
dbus_message_iter_init_append (message, &iter);
1026
_g_dbus_message_iter_append_cstring (&iter, fuse_path);
1028
dbus_error_init (&derror);
1029
reply = dbus_connection_send_with_reply_and_block (conn, message, -1, &derror);
1030
dbus_message_unref (message);
1033
dbus_error_free (&derror);
1037
info = handler_lookup_mount_reply (reply, NULL);
1038
dbus_message_unref (reply);
1042
if (info->fuse_mountpoint)
1044
len = strlen (info->fuse_mountpoint);
1045
if (fuse_path[len] == 0)
1046
mount_path_end = "/";
1048
mount_path_end = fuse_path + len;
1050
*mount_path = g_build_filename (info->mount_spec->mount_prefix,
1051
mount_path_end, NULL);
1055
/* This could happen if we race with the gvfs fuse mount
1056
* at startup of gvfsd... */
1057
g_mount_info_unref (info);
1067
g_daemon_vfs_parse_name (GVfs *vfs,
1068
const char *parse_name)
1072
if (g_path_is_absolute (parse_name) ||
1075
file = g_vfs_parse_name (G_DAEMON_VFS (vfs)->wrapped_vfs, parse_name);
1076
file = convert_fuse_path (vfs, file);
1080
file = g_daemon_vfs_get_file_for_uri (vfs, parse_name);
1087
enumerate_keys_callback (const char *key,
1092
GFileInfo *info = user_data;
1095
attr = g_strconcat ("metadata::", key, NULL);
1097
if (type == META_KEY_TYPE_STRING)
1098
g_file_info_set_attribute_string (info, attr, (char *)value);
1100
g_file_info_set_attribute_stringv (info, attr, (char **)value);
1108
g_daemon_vfs_local_file_add_info (GVfs *vfs,
1109
const char *filename,
1111
GFileAttributeMatcher *matcher,
1113
GCancellable *cancellable,
1114
gpointer *extra_data,
1115
GDestroyNotify *extra_data_free)
1117
MetaLookupCache *cache;
1123
/* Filename may or may not be a symlink, but we should not follow it.
1124
However, we want to follow symlinks for all parents that have the same
1126
all = g_file_attribute_matcher_enumerate_namespace (matcher, "metadata");
1131
first = g_file_attribute_matcher_enumerate_next (matcher);
1134
return; /* No match */
1137
if (*extra_data == NULL)
1139
*extra_data = meta_lookup_cache_new ();
1140
*extra_data_free = (GDestroyNotify)meta_lookup_cache_free;
1142
cache = (MetaLookupCache *)*extra_data;
1144
tree = meta_lookup_cache_lookup_path (cache,
1152
meta_tree_enumerate_keys (tree, tree_path,
1153
enumerate_keys_callback, info);
1154
meta_tree_unref (tree);
1160
g_daemon_vfs_add_writable_namespaces (GVfs *vfs,
1161
GFileAttributeInfoList *list)
1163
g_file_attribute_info_list_add (list,
1165
G_FILE_ATTRIBUTE_TYPE_STRING, /* Also STRINGV, but no way express this ... */
1166
G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE |
1167
G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED);
1171
send_message_oneway (DBusMessage *message)
1173
DBusConnection *connection;
1175
connection = _g_dbus_connection_get_sync (NULL, NULL);
1176
if (connection == NULL)
1179
dbus_connection_send (connection, message, NULL);
1180
dbus_connection_flush (connection);
1183
/* Sends a message on the session bus and blocks for the reply,
1184
using the thread local connection */
1186
_g_daemon_vfs_send_message_sync (DBusMessage *message,
1187
GCancellable *cancellable,
1190
DBusConnection *connection;
1194
connection = _g_dbus_connection_get_sync (NULL, NULL);
1195
if (connection == NULL)
1197
g_set_error (error, G_IO_ERROR,
1199
_("Error setting file metadata: %s"),
1200
_("Can't contact session bus"));
1204
dbus_error_init (&derror);
1205
/* TODO: Handle cancellable */
1206
reply = dbus_connection_send_with_reply_and_block (connection, message,
1207
G_VFS_DBUS_TIMEOUT_MSECS,
1211
_g_error_from_dbus (&derror, error);
1212
dbus_error_free (&derror);
1216
dbus_message_unref (reply);
1222
strv_equal (char **a, char **b)
1226
if (g_strv_length (a) != g_strv_length (b))
1229
for (i = 0; a[i] != NULL; i++)
1231
if (strcmp (a[i], b[i]) != 0)
1237
/* -1 => error, otherwise number of added items */
1239
_g_daemon_vfs_append_metadata_for_set (DBusMessage *message,
1242
const char *attribute,
1243
GFileAttributeType type,
1249
key = attribute + strlen ("metadata::");
1252
if (type == G_FILE_ATTRIBUTE_TYPE_STRING)
1255
const char *val = (char *)value;
1257
current = meta_tree_lookup_string (tree, path, key);
1258
if (current == NULL || strcmp (current, val) != 0)
1261
_g_dbus_message_append_args (message,
1262
DBUS_TYPE_STRING, &key,
1263
DBUS_TYPE_STRING, &val,
1268
else if (type == G_FILE_ATTRIBUTE_TYPE_STRINGV)
1271
char **val = (char **)value;
1272
current = meta_tree_lookup_stringv (tree, path, key);
1273
if (current == NULL || !strv_equal (current, val))
1276
_g_dbus_message_append_args (message,
1277
DBUS_TYPE_STRING, &key,
1278
DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &val, g_strv_length (val),
1281
g_strfreev (current);
1283
else if (type == G_FILE_ATTRIBUTE_TYPE_INVALID)
1285
if (meta_tree_lookup_key_type (tree, path, key) != META_KEY_TYPE_NONE)
1290
_g_dbus_message_append_args (message,
1291
DBUS_TYPE_STRING, &key,
1303
g_daemon_vfs_local_file_set_attributes (GVfs *vfs,
1304
const char *filename,
1306
GFileQueryInfoFlags flags,
1307
GCancellable *cancellable,
1310
GFileAttributeType type;
1311
MetaLookupCache *cache;
1312
const char *metatreefile;
1313
struct stat statbuf;
1319
DBusMessage *message;
1325
if (g_file_info_has_namespace (info, "metadata"))
1327
attributes = g_file_info_list_attributes (info, "metadata");
1329
if (g_lstat (filename, &statbuf) != 0)
1332
g_set_error (error, G_IO_ERROR,
1333
g_io_error_from_errno (errsv),
1334
_("Error setting file metadata: %s"),
1335
g_strerror (errsv));
1336
error = NULL; /* Don't set further errors */
1338
for (i = 0; attributes[i] != NULL; i++)
1339
g_file_info_set_attribute_status (info, attributes[i],
1340
G_FILE_ATTRIBUTE_STATUS_ERROR_SETTING);
1346
cache = meta_lookup_cache_new ();
1347
tree = meta_lookup_cache_lookup_path (cache,
1353
dbus_message_new_method_call (G_VFS_DBUS_METADATA_NAME,
1354
G_VFS_DBUS_METADATA_PATH,
1355
G_VFS_DBUS_METADATA_INTERFACE,
1356
G_VFS_DBUS_METADATA_OP_SET);
1357
g_assert (message != NULL);
1358
metatreefile = meta_tree_get_filename (tree);
1359
_g_dbus_message_append_args (message,
1360
G_DBUS_TYPE_CSTRING, &metatreefile,
1361
G_DBUS_TYPE_CSTRING, &tree_path,
1363
meta_lookup_cache_free (cache);
1366
for (i = 0; attributes[i] != NULL; i++)
1368
if (g_file_info_get_attribute_data (info, attributes[i], &type, &value, NULL))
1370
appended = _g_daemon_vfs_append_metadata_for_set (message,
1378
num_set += appended;
1379
g_file_info_set_attribute_status (info, attributes[i],
1380
G_FILE_ATTRIBUTE_STATUS_SET);
1385
g_set_error (error, G_IO_ERROR,
1386
G_IO_ERROR_INVALID_ARGUMENT,
1387
_("Error setting file metadata: %s"),
1388
_("values must be string or list of strings"));
1389
error = NULL; /* Don't set further errors */
1390
g_file_info_set_attribute_status (info, attributes[i],
1391
G_FILE_ATTRIBUTE_STATUS_ERROR_SETTING);
1396
meta_tree_unref (tree);
1400
!_g_daemon_vfs_send_message_sync (message,
1401
cancellable, error))
1404
error = NULL; /* Don't set further errors */
1405
for (i = 0; attributes[i] != NULL; i++)
1406
g_file_info_set_attribute_status (info, attributes[i],
1407
G_FILE_ATTRIBUTE_STATUS_ERROR_SETTING);
1410
dbus_message_unref (message);
1413
g_strfreev (attributes);
1420
g_daemon_vfs_local_file_removed (GVfs *vfs,
1421
const char *filename)
1423
MetaLookupCache *cache;
1424
DBusMessage *message;
1425
const char *metatreefile;
1429
cache = meta_lookup_cache_new ();
1430
tree = meta_lookup_cache_lookup_path (cache,
1438
dbus_message_new_method_call (G_VFS_DBUS_METADATA_NAME,
1439
G_VFS_DBUS_METADATA_PATH,
1440
G_VFS_DBUS_METADATA_INTERFACE,
1441
G_VFS_DBUS_METADATA_OP_REMOVE);
1442
g_assert (message != NULL);
1443
metatreefile = meta_tree_get_filename (tree);
1444
_g_dbus_message_append_args (message,
1445
G_DBUS_TYPE_CSTRING, &metatreefile,
1446
G_DBUS_TYPE_CSTRING, &tree_path,
1448
send_message_oneway (message);
1449
dbus_message_unref (message);
1450
meta_tree_unref (tree);
1454
meta_lookup_cache_free (cache);
1458
g_daemon_vfs_local_file_moved (GVfs *vfs,
1462
MetaLookupCache *cache;
1463
DBusMessage *message;
1464
const char *metatreefile;
1465
MetaTree *tree1, *tree2;
1466
char *tree_path1, *tree_path2;
1468
cache = meta_lookup_cache_new ();
1469
tree1 = meta_lookup_cache_lookup_path (cache,
1474
tree2 = meta_lookup_cache_lookup_path (cache,
1479
if (tree1 && tree2 && tree1 == tree2)
1482
dbus_message_new_method_call (G_VFS_DBUS_METADATA_NAME,
1483
G_VFS_DBUS_METADATA_PATH,
1484
G_VFS_DBUS_METADATA_INTERFACE,
1485
G_VFS_DBUS_METADATA_OP_MOVE);
1486
g_assert (message != NULL);
1487
metatreefile = meta_tree_get_filename (tree1);
1488
_g_dbus_message_append_args (message,
1489
G_DBUS_TYPE_CSTRING, &metatreefile,
1490
G_DBUS_TYPE_CSTRING, &tree_path1,
1491
G_DBUS_TYPE_CSTRING, &tree_path2,
1493
send_message_oneway (message);
1494
dbus_message_unref (message);
1499
meta_tree_unref (tree1);
1500
g_free (tree_path1);
1505
meta_tree_unref (tree2);
1506
g_free (tree_path2);
1509
meta_lookup_cache_free (cache);
1513
_g_daemon_vfs_get_async_bus (void)
1515
return the_vfs->async_bus;
1519
g_daemon_vfs_is_active (GVfs *vfs)
1521
GDaemonVfs *daemon_vfs = G_DAEMON_VFS (vfs);
1522
return daemon_vfs->async_bus != NULL;
1526
g_daemon_vfs_class_finalize (GDaemonVfsClass *klass)
1531
g_daemon_vfs_class_init (GDaemonVfsClass *class)
1533
GObjectClass *object_class;
1534
GVfsClass *vfs_class;
1536
object_class = (GObjectClass *) class;
1538
g_daemon_vfs_parent_class = g_type_class_peek_parent (class);
1540
object_class->finalize = g_daemon_vfs_finalize;
1542
vfs_class = G_VFS_CLASS (class);
1544
vfs_class->is_active = g_daemon_vfs_is_active;
1545
vfs_class->get_file_for_path = g_daemon_vfs_get_file_for_path;
1546
vfs_class->get_file_for_uri = g_daemon_vfs_get_file_for_uri;
1547
vfs_class->get_supported_uri_schemes = g_daemon_vfs_get_supported_uri_schemes;
1548
vfs_class->parse_name = g_daemon_vfs_parse_name;
1549
vfs_class->local_file_add_info = g_daemon_vfs_local_file_add_info;
1550
vfs_class->add_writable_namespaces = g_daemon_vfs_add_writable_namespaces;
1551
vfs_class->local_file_set_attributes = g_daemon_vfs_local_file_set_attributes;
1552
vfs_class->local_file_removed = g_daemon_vfs_local_file_removed;
1553
vfs_class->local_file_moved = g_daemon_vfs_local_file_moved;
1558
void g_vfs_uri_mapper_smb_register (GIOModule *module);
1559
void g_vfs_uri_mapper_http_register (GIOModule *module);
1560
void g_vfs_uri_mapper_sftp_register (GIOModule *module);
1563
g_io_module_load (GIOModule *module)
1565
/* This is so that system daemons can use gio
1566
* without spawning private dbus instances.
1569
if (g_getenv ("DBUS_SESSION_BUS_ADDRESS") == NULL)
1572
/* Make this module resident so that we ground the common
1573
* library. If that is unloaded we could get into all kinds
1574
* of strange situations. This is safe to do even if we loaded
1575
* some other common-using module first as all modules are loaded
1576
* before any are freed.
1578
g_type_module_use (G_TYPE_MODULE (module));
1580
g_daemon_vfs_register_type (G_TYPE_MODULE (module));
1581
g_daemon_volume_monitor_register_types (G_TYPE_MODULE (module));
1583
/* We implement GLoadableIcon only on client side.
1584
see comment in common/giconvfs.c */
1585
_g_vfs_icon_add_loadable_interface ();
1587
g_io_extension_point_implement (G_VFS_EXTENSION_POINT_NAME,
1592
g_vfs_uri_mapper_register (module);
1593
g_vfs_uri_mapper_smb_register (module);
1594
g_vfs_uri_mapper_http_register (module);
1598
g_io_module_unload (GIOModule *module)
1603
g_io_module_query (void)
1606
G_VFS_EXTENSION_POINT_NAME,
1607
G_VOLUME_MONITOR_EXTENSION_POINT_NAME,
1610
return g_strdupv (eps);