diff options
author | Alexander Larsson <alexl@redhat.com> | 2008-02-22 14:36:54 +0000 |
---|---|---|
committer | Alexander Larsson <alexl@src.gnome.org> | 2008-02-22 14:36:54 +0000 |
commit | a4621dcfa1ce0343e7ce88fdac5b957ddefea75d (patch) | |
tree | 0378ffdcaffa07b13f4c196e0b55b8ce0ba1e69a | |
parent | 06e0fe76fc9e3308f636bd661cd5af27f60a3e19 (diff) | |
download | gvfs-a4621dcfa1ce0343e7ce88fdac5b957ddefea75d.tar.gz |
Landed initial version of dns-sd backend.
2008-02-22 Alexander Larsson <alexl@redhat.com>
* configure.ac:
* daemon/Makefile.am:
* daemon/dns-sd.mount.in:
* daemon/gvfsbackenddnssd.[ch]:
Landed initial version of dns-sd backend.
svn path=/trunk/; revision=1334
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | configure.ac | 18 | ||||
-rw-r--r-- | daemon/Makefile.am | 21 | ||||
-rw-r--r-- | daemon/dns-sd.mount.in | 4 | ||||
-rw-r--r-- | daemon/gvfsbackenddnssd.c | 731 | ||||
-rw-r--r-- | daemon/gvfsbackenddnssd.h | 50 |
6 files changed, 832 insertions, 0 deletions
@@ -1,3 +1,11 @@ +2008-02-22 Alexander Larsson <alexl@redhat.com> + + * configure.ac: + * daemon/Makefile.am: + * daemon/dns-sd.mount.in: + * daemon/gvfsbackenddnssd.[ch]: + Landed initial version of dns-sd backend. + 2007-02-22 Christian Neumair <cneumair@gnome.org> * gconf/gconf-module.c: (g_io_module_load): diff --git a/configure.ac b/configure.ac index b7b224a9..b60a5a3d 100644 --- a/configure.ac +++ b/configure.ac @@ -130,6 +130,23 @@ AC_SUBST(HTTP_LIBS) AM_CONDITIONAL(HAVE_HTTP, [test "$msg_http" = "yes"]) dnl ************************************************** +dnl *** Check if we should build with DNS-SD backend *** +dnl ************************************************** +AM_CONDITIONAL(HAVE_AVAHI, false) + +AC_ARG_ENABLE(avahi, [ --disable-avahi build without avahi support]) +msg_avahi=no +if test "x$enable_avahi" != "xno"; then + PKG_CHECK_MODULES(AVAHI, avahi-glib >= 0.6 avahi-client >= 0.6, + [AM_CONDITIONAL(HAVE_AVAHI, true) + AC_DEFINE(HAVE_AVAHI, [], [Set if we can use avahi])] + msg_avahi=yes, + [AM_CONDITIONAL(HAVE_AVAHI, false)]) + AC_SUBST(AVAHI_CFLAGS) + AC_SUBST(AVAHI_LIBS) +fi + +dnl ************************************************** dnl *** Check if we should build with CDDA backend *** dnl ************************************************** AC_ARG_ENABLE(cdda, [ --disable-cdda build without CDDA backend]) @@ -388,6 +405,7 @@ echo " FUSE support: $msg_fuse CDDA support: $msg_cdda GConf support: $msg_gconf + DNS-SD support: $msg_avahi Use HAL for volume monitor: $msg_hal (with fast init path: $have_hal_fast_init) GNOME Keyring support: $msg_keyring " diff --git a/daemon/Makefile.am b/daemon/Makefile.am index bd17372a..05f0f18c 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -63,6 +63,12 @@ mount_DATA += network.mount libexec_PROGRAMS += gvfsd-network endif +mount_in_files += dns-sd.mount.in +if HAVE_AVAHI +mount_DATA += dns-sd.mount +libexec_PROGRAMS += gvfsd-dnssd +endif + EXTRA_DIST = gvfs-daemon.service.in $(mount_in_files) DISTCLEANFILES = gvfs-daemon.service $(mount_DATA) @@ -240,6 +246,21 @@ gvfsd_network_CPPFLAGS = \ gvfsd_network_LDADD = $(libraries) $(GCONF_LIBS) +gvfsd_dnssd_SOURCES = \ + gvfsbackenddnssd.c gvfsbackenddnssd.h \ + daemon-main.c daemon-main.h \ + daemon-main-generic.c + +gvfsd_dnssd_CPPFLAGS = \ + -DBACKEND_HEADER=gvfsbackenddnssd.h \ + -DDEFAULT_BACKEND_TYPE=dns-sd \ + -DMAX_JOB_THREADS=1 \ + $(AVAHI_CFLAGS) \ + -DBACKEND_TYPES='"dns-sd", G_VFS_TYPE_BACKEND_DNS_SD,' + +gvfsd_dnssd_LDADD = $(libraries) $(AVAHI_LIBS) + + gvfsd_burn_SOURCES = \ gvfsbackendburn.c gvfsbackendburn.h \ daemon-main.c daemon-main.h \ diff --git a/daemon/dns-sd.mount.in b/daemon/dns-sd.mount.in new file mode 100644 index 00000000..4e02907d --- /dev/null +++ b/daemon/dns-sd.mount.in @@ -0,0 +1,4 @@ +[Mount] +Type=network +Exec=@libexecdir@/gvfsd-network +AutoMount=true diff --git a/daemon/gvfsbackenddnssd.c b/daemon/gvfsbackenddnssd.c new file mode 100644 index 00000000..6ee9aa46 --- /dev/null +++ b/daemon/gvfsbackenddnssd.c @@ -0,0 +1,731 @@ +/* GIO - GLib Input, Output and Streaming Library + * Original work, Copyright (C) 2003 Red Hat, Inc + * GVFS port, Copyright (c) 2008 Andrew Walton. + * + * 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 Library General Public + * License along with the Gnome Library; see the file COPYING.LIB. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Authors: + * Alexander Larsson <alexl@redhat.com> + */ + +#include <config.h> + +#include <string.h> +#include <glib.h> +#include <glib/gi18n.h> +#include <glib/gurifuncs.h> +#include <gio/gio.h> + +#include <avahi-client/client.h> +#include <avahi-client/lookup.h> +#include <avahi-common/error.h> +#include <avahi-common/timeval.h> +#include <avahi-glib/glib-watch.h> +#include <avahi-glib/glib-malloc.h> + +#include "gvfsbackenddnssd.h" + +#include "gvfsdaemonprotocol.h" +#include "gvfsjobcreatemonitor.h" +#include "gvfsjobenumerate.h" +#include "gvfsjobqueryinfo.h" +#include "gvfsmonitor.h" + +static struct { + char *type; + char *method; + char *icon; + gpointer handle; +} dns_sd_types[] = { + {"_ftp._tcp", "ftp", "gnome-fs-ftp"}, + {"_webdav._tcp", "dav", "gnome-fs-share"}, + {"_webdavs._tcp", "davs", "gnome-fs-share"}, + {"_sftp-ssh._tcp", "sftp", "gnome-fs-ssh"}, +}; + +static AvahiClient *global_client = NULL; +static gboolean avahi_initialized = FALSE; + +static GList *dnssd_backends = NULL; + +typedef struct { + char *file_name; + char *name; + char *type; + char *target_uri; + GIcon *icon; +} LinkFile; + +static LinkFile root = { "/" }; + +struct _GVfsBackendDnsSd +{ + GVfsBackend parent_instance; + GVfsMonitor *root_monitor; + char *domain; + GMountSpec *mount_spec; + GList *files; /* list of LinkFiles */ + + GList *browsers; +}; + +typedef struct _GVfsBackendDnsSd GVfsBackendDnsSd; + +G_DEFINE_TYPE (GVfsBackendDnsSd, g_vfs_backend_dns_sd, G_VFS_TYPE_BACKEND) + +static void add_browsers (GVfsBackendDnsSd *backend); +static void remove_browsers (GVfsBackendDnsSd *backend); +static AvahiClient *get_global_avahi_client (void); + +/* Callback for state changes on the Client */ +static void +avahi_client_callback (AvahiClient *client, AvahiClientState state, void *userdata) +{ + /* We need to set this early, as the add_browsers call below may reenter + when this is called from the client creation call */ + if (global_client == NULL) + global_client = client; + + if (state == AVAHI_CLIENT_FAILURE) + { + if (avahi_client_errno (client) == AVAHI_ERR_DISCONNECTED) + { + /* Remove the service browsers from the handles */ + g_list_foreach (dnssd_backends, (GFunc)remove_browsers, NULL); + + /* Destroy old client */ + avahi_client_free (client); + global_client = NULL; + avahi_initialized = FALSE; + + /* Reconnect */ + get_global_avahi_client (); + } + } + else if (state == AVAHI_CLIENT_S_RUNNING) + { + /* Start browsing again */ + g_list_foreach (dnssd_backends, (GFunc)add_browsers, NULL); + } +} + +static AvahiClient * +get_global_avahi_client (void) +{ + static AvahiGLibPoll *glib_poll = NULL; + int error; + + if (!avahi_initialized) + { + avahi_initialized = TRUE; + + if (glib_poll == NULL) + { + avahi_set_allocator (avahi_glib_allocator ()); + glib_poll = avahi_glib_poll_new (NULL, G_PRIORITY_DEFAULT); + } + + /* Create a new AvahiClient instance */ + global_client = avahi_client_new (avahi_glib_poll_get (glib_poll), + AVAHI_CLIENT_NO_FAIL, + avahi_client_callback, + glib_poll, + &error); + + if (global_client == NULL) + { + /* Print out the error string */ + g_warning ("Error initializing Avahi: %s", avahi_strerror (error)); + return NULL; + } + } + + return global_client; +} + +static GIcon * +get_icon_for_type (const char *type) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (dns_sd_types); i++) + { + if (strcmp (type, dns_sd_types[i].type) == 0) + return g_themed_icon_new (dns_sd_types[i].icon); + } + + return g_themed_icon_new ("text-x-generic"); +} + +static const char * +get_method_for_type (const char *type) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (dns_sd_types); i++) + { + if (strcmp (type, dns_sd_types[i].type) == 0) + return dns_sd_types[i].method; + } + + return NULL; +} + +static char * +encode_filename (const char *service, + const char *type) +{ + GString *string; + const char *p; + + string = g_string_new (NULL); + + p = service; + + while (*p) + { + if (*p == '\\') + g_string_append (string, "\\\\"); + else if (*p == '.') + g_string_append (string, "\\."); + else if (*p == '/') + g_string_append (string, "\\s"); + else + g_string_append_c (string, *p); + p++; + } + + g_string_append_c (string, '.'); + g_string_append (string, type); + + return g_string_free (string, FALSE); +} + +static LinkFile * +link_file_new (const char *name, + const char *type, + const char *domain, + const char *host_name, + AvahiProtocol protocol, + const AvahiAddress *address, + uint16_t port, + AvahiStringList *txt) +{ + LinkFile *file; + char *path, *user, *user_str; + AvahiStringList *path_l, *user_l; + char a[128]; + const char *method; + + file = g_slice_new0 (LinkFile); + + file->name = g_strdup (name); + file->type = g_strdup (type); + file->file_name = encode_filename (name, type); + file->icon = get_icon_for_type (type); + + + path = NULL; + user_str = NULL; + if (txt != NULL) + { + path_l = avahi_string_list_find (txt, "path"); + if (path_l != NULL) + avahi_string_list_get_pair (path_l, NULL, &path, NULL); + + user_l = avahi_string_list_find (txt, "u"); + if (user_l != NULL) + { + avahi_string_list_get_pair (user_l, NULL, &user, NULL); + + user_str = g_strconcat (user, "@", NULL); + } + } + + if (path == NULL) + path = g_strdup ("/"); + + avahi_address_snprint (a, sizeof(a), address); + + method = get_method_for_type (type); + + if (protocol == AVAHI_PROTO_INET6) + /* an ipv6 address, follow rfc2732 */ + file->target_uri = g_strdup_printf ("%s://%s[%s]:%d%s", + method, + user_str?user_str:"", + a, port, path); + else + file->target_uri = g_strdup_printf ("%s://%s%s:%d%s", + method, + user_str?user_str:"", + a, port, path); + g_free (user_str); + g_free (path); + + return file; +} + +static void +link_file_free (LinkFile *file) +{ + g_free (file->file_name); + g_free (file->name); + g_free (file->type); + g_free (file->target_uri); + + if (file->icon) + g_object_unref (file->icon); + + g_slice_free (LinkFile, file); +} + +static LinkFile * +lookup_link_file_by_name_and_type (GVfsBackendDnsSd *backend, + const char *name, + const char *type) +{ + GList *l; + LinkFile *file; + + for (l = backend->files; l != NULL; l = l->next) + { + file = l->data; + if (strcmp (file->name, name) == 0 && + strcmp (file->type, type) == 0) + return file; + } + + return NULL; +} + +static LinkFile * +lookup_link_file (GVfsBackendDnsSd *backend, + GVfsJob *job, + const char *file_name) +{ + GList *l; + LinkFile *file; + + if (*file_name != '/') + goto out; + + while (*file_name == '/') + file_name++; + + if (*file_name == 0) + return &root; + + if (strchr (file_name, '/') != NULL) + goto out; + + for (l = backend->files; l != NULL; l = l->next) + { + file = l->data; + if (strcmp (file->file_name, file_name) == 0) + return file; + } + + out: + g_vfs_job_failed (job, G_IO_ERROR, + G_IO_ERROR_NOT_FOUND, + _("File doesn't exist")); + + return NULL; +} + + +static void +file_info_from_file (LinkFile *file, + GFileInfo *info) +{ + g_return_if_fail (file != NULL || info != NULL); + + g_file_info_set_name (info, file->file_name); + g_file_info_set_display_name (info, file->name); + + if (file->icon) + g_file_info_set_icon (info, file->icon); + + g_file_info_set_file_type (info, G_FILE_TYPE_SHORTCUT); + g_file_info_set_size(info, 0); + g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, FALSE); + g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, FALSE); + g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, FALSE); + g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_STANDARD_IS_VIRTUAL, TRUE); + g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI, + file->target_uri); +} + +/* Backend Functions */ +static gboolean +try_enumerate (GVfsBackend *backend, + GVfsJobEnumerate *job, + const char *file_name, + GFileAttributeMatcher *attribute_matcher, + GFileQueryInfoFlags flags) +{ + LinkFile *file; + GList *l; + GFileInfo *info; + + file = lookup_link_file (G_VFS_BACKEND_DNS_SD (backend), + G_VFS_JOB (job), file_name); + + if (file != &root) + { + if (file != NULL) + g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, + G_IO_ERROR_NOT_DIRECTORY, + _("The file is not a directory")); + return TRUE; + } + + g_vfs_job_succeeded (G_VFS_JOB(job)); + + /* Enumerate root */ + for (l = G_VFS_BACKEND_DNS_SD (backend)->files; l != NULL; l = l->next) + { + file = l->data; + info = g_file_info_new (); + file_info_from_file (file, info); + g_vfs_job_enumerate_add_info (job, info); + g_object_unref (info); + } + + g_vfs_job_enumerate_done (job); + + return TRUE; +} + +static gboolean +try_query_info (GVfsBackend *backend, + GVfsJobQueryInfo *job, + const char *file_name, + GFileQueryInfoFlags flags, + GFileInfo *info, + GFileAttributeMatcher *matcher) +{ + LinkFile *file; + + file = lookup_link_file (G_VFS_BACKEND_DNS_SD (backend), + G_VFS_JOB (job), file_name); + + if (file == &root) + { + GIcon *icon; + g_file_info_set_name (info, "/"); + g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY); + /* TODO: Name */ + g_file_info_set_display_name (info, _("dns-sd")); + icon = g_themed_icon_new ("network-workgroup"); + g_file_info_set_icon (info, icon); + g_object_unref (icon); + g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, FALSE); + g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, FALSE); + g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, FALSE); + g_file_info_set_content_type (info, "inode/directory"); + g_vfs_job_succeeded (G_VFS_JOB (job)); + } + else if (file != NULL) + { + file_info_from_file (file, info); + g_vfs_job_succeeded (G_VFS_JOB (job)); + } + + return TRUE; +} + + +static void +resolve_callback (AvahiServiceResolver *r, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiResolverEvent event, + const char *name, + const char *type, + const char *domain, + const char *host_name, + const AvahiAddress *address, + uint16_t port, + AvahiStringList *txt, + AvahiLookupResultFlags flags, + void *userdata) +{ + GVfsBackendDnsSd *backend = userdata; + LinkFile *file; + char *path; + + if (event == AVAHI_RESOLVER_FAILURE) + return; + + /* Link-local ipv6 address, can't make a uri from this, ignore */ + if (address->proto == AVAHI_PROTO_INET6 && + address->data.ipv6.address[0] == 0xfe && + address->data.ipv6.address[1] == 0x80) + return; + + file = lookup_link_file_by_name_and_type (backend, + name, type); + + if (file != NULL) + return; + + file = link_file_new (name, type, domain, host_name, protocol, + address, port, txt); + + backend->files = g_list_prepend (backend->files, file); + + path = g_strconcat ("/", file->file_name, NULL); + g_vfs_monitor_emit_event (backend->root_monitor, + G_FILE_MONITOR_EVENT_CREATED, + path, + NULL); + g_free (path); +} + +static void +browse_callback (AvahiServiceBrowser *b, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiBrowserEvent event, + const char *name, + const char *type, + const char *domain, + AvahiLookupResultFlags flags, + void *userdata) +{ + GVfsBackendDnsSd *backend = userdata; + AvahiServiceResolver *sr; + AvahiClient *client; + LinkFile *file; + char *path; + + switch (event) + { + case AVAHI_BROWSER_FAILURE: + break; + + case AVAHI_BROWSER_NEW: + client = get_global_avahi_client (); + + /* We ignore the returned resolver object. In the callback + function we free it. If the server is terminated before + the callback function is called the server will free + the resolver for us. */ + + sr = avahi_service_resolver_new (client, interface, protocol, + name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, backend); + + if (sr == NULL) + g_warning ("Failed to resolve service name '%s': %s\n", name, avahi_strerror (avahi_client_errno (client))); + + break; + + case AVAHI_BROWSER_REMOVE: + file = lookup_link_file_by_name_and_type (backend, + name, type); + + if (file != NULL) + { + backend->files = g_list_remove (backend->files, file); + + path = g_strconcat ("/", file->file_name, NULL); + g_vfs_monitor_emit_event (backend->root_monitor, + G_FILE_MONITOR_EVENT_DELETED, + path, + NULL); + g_free (path); + + link_file_free (file); + } + + break; + + case AVAHI_BROWSER_ALL_FOR_NOW: + case AVAHI_BROWSER_CACHE_EXHAUSTED: + break; + } +} + +static void +browse_type (GVfsBackendDnsSd *backend, + const char *type) +{ + AvahiClient *client; + AvahiServiceBrowser *sb; + const char *domain; + + client = get_global_avahi_client (); + + domain = NULL; + if (strcmp (backend->domain, "local") != 0) + domain = backend->domain; + + sb = avahi_service_browser_new (client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, + type, domain, 0, browse_callback, backend); + + if (sb == NULL) + { + g_warning ("Failed to create service browser: %s\n", avahi_strerror( avahi_client_errno (client))); + return; + } + + backend->browsers = g_list_prepend (backend->browsers, sb); + +} + +static void +add_browsers (GVfsBackendDnsSd *backend) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (dns_sd_types); i++) + browse_type (backend, dns_sd_types[i].type); +} + +static void +remove_browsers (GVfsBackendDnsSd *backend) +{ + g_list_free (backend->browsers); + backend->browsers = NULL; +} + +static gboolean +try_mount (GVfsBackend *backend, + GVfsJobMount *job, + GMountSpec *mount_spec, + GMountSource *mount_source, + gboolean is_automount) +{ + GVfsBackendDnsSd *op_backend = G_VFS_BACKEND_DNS_SD (backend); + GMountSpec *real_mount_spec; + const char *domain; + + domain = g_mount_spec_get (mount_spec, "host"); + + if (domain == NULL) + { + g_vfs_job_failed (G_VFS_JOB (job), + G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + "No domain specified for dns-sd share"); + return TRUE; + } + + op_backend->domain = g_strdup (domain); + + if (get_global_avahi_client() == NULL) + { + g_vfs_job_failed (G_VFS_JOB (job), + G_IO_ERROR, G_IO_ERROR_FAILED, + "Unable to initialize avahi"); + return TRUE; + } + + real_mount_spec = g_mount_spec_new ("dns-sd"); + g_mount_spec_set (real_mount_spec, "host", op_backend->domain); + g_vfs_backend_set_mount_spec (backend, real_mount_spec); + op_backend->mount_spec = real_mount_spec; + + op_backend->root_monitor = g_vfs_monitor_new (backend); + + g_vfs_job_succeeded (G_VFS_JOB (job)); + + return TRUE; +} + +/* handles both file and dir monitors, + * as we really don't "support" (e.g. fire events for) either, yet. */ +static gboolean +try_create_monitor (GVfsBackend *backend, + GVfsJobCreateMonitor *job, + const char *file_name, + GFileMonitorFlags flags) +{ + LinkFile *file; + GVfsBackendDnsSd *network_backend; + + network_backend = G_VFS_BACKEND_DNS_SD (backend); + + file = lookup_link_file (network_backend, G_VFS_JOB (job), file_name); + + if (file != &root) + { + g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + _("Can't monitor file or directory.")); + return TRUE; + } + + g_vfs_job_create_monitor_set_monitor (job, network_backend->root_monitor); + g_vfs_job_succeeded (G_VFS_JOB (job)); + + return TRUE; +} + +static void +g_vfs_backend_dns_sd_init (GVfsBackendDnsSd *network_backend) +{ + GVfsBackend *backend = G_VFS_BACKEND (network_backend); + + dnssd_backends = g_list_prepend (dnssd_backends, backend); + + /* TODO: Names, etc */ + g_vfs_backend_set_display_name (backend, _("Dns-SD")); + g_vfs_backend_set_stable_name (backend, _("Network")); + g_vfs_backend_set_icon_name (backend, "network-workgroup"); + g_vfs_backend_set_user_visible (backend, FALSE); + +} + +static void +g_vfs_backend_dns_sd_finalize (GObject *object) +{ + GVfsBackendDnsSd *backend; + + backend = G_VFS_BACKEND_DNS_SD (object); + + dnssd_backends = g_list_remove (dnssd_backends, backend); + + if (backend->mount_spec) + g_mount_spec_unref (backend->mount_spec); + + if (backend->root_monitor) + g_object_unref (backend->root_monitor); + + g_free (backend->domain); + + g_list_foreach (backend->files, (GFunc)link_file_free, NULL); + + if (G_OBJECT_CLASS (g_vfs_backend_dns_sd_parent_class)->finalize) + (*G_OBJECT_CLASS (g_vfs_backend_dns_sd_parent_class)->finalize) (object); +} + +static void +g_vfs_backend_dns_sd_class_init (GVfsBackendDnsSdClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (klass); + + gobject_class->finalize = g_vfs_backend_dns_sd_finalize; + + backend_class->try_mount = try_mount; + backend_class->try_query_info = try_query_info; + backend_class->try_enumerate = try_enumerate; + backend_class->try_create_dir_monitor = try_create_monitor; + backend_class->try_create_file_monitor = try_create_monitor; +} + diff --git a/daemon/gvfsbackenddnssd.h b/daemon/gvfsbackenddnssd.h new file mode 100644 index 00000000..8648fc29 --- /dev/null +++ b/daemon/gvfsbackenddnssd.h @@ -0,0 +1,50 @@ +/* gvfs-backend-dns_sd.h - GIO - GLib Input, Output and Streaming Library + * Original work, Copyright (C) 2003 Red Hat, Inc + * GVFS port, Copyright (c) 2008 Andrew Walton. + * + * 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 Library General Public + * License along with the Gnome Library; see the file COPYING.LIB. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Authors: + * Alexander Larsson <alexl@redhat.com> + */ + +#ifndef __G_VFS_BACKEND_DNS_SD_H__ +#define __G_VFS_BACKEND_DNS_SD_H__ + +#include <gvfsbackend.h> +#include <gmountspec.h> + +G_BEGIN_DECLS + +#define G_VFS_TYPE_BACKEND_DNS_SD (g_vfs_backend_dns_sd_get_type ()) +#define G_VFS_BACKEND_DNS_SD(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_BACKEND_DNS_SD, GVfsBackendDnsSd)) +#define G_VFS_BACKEND_DNS_SD_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_BACKEND_DNS_SD, GVfsBackendDnsSdClass)) +#define G_VFS_IS_BACKEND_DNS_SD(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_BACKEND_DNS_SD)) +#define G_VFS_IS_BACKEND_DNS_SD_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_BACKEND_DNS_SD)) +#define G_VFS_BACKEND_DNS_SD_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_BACKEND_DNS_SD, GVfsBackendDnsSdClass)) + +typedef struct _GVfsBackendDnsSdClass GVfsBackendDnsSdClass; + +struct _GVfsBackendDnsSdClass +{ + GVfsBackendClass parent_class; +}; + +GType g_vfs_backend_dns_sd_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __G_VFS_BACKEND_DNS_SD_H__ */ |