Index: gvfs-1.9.0/daemon/gvfsbackendnds.c
===================================================================
--- /dev/null
+++ gvfs-1.9.0/daemon/gvfsbackendnds.c
@@ -0,0 +1,753 @@
+/* GIO - GLib Input, Output and Streaming Library
+ * 
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * 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 Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include<stdlib.h>
+#include<stdio.h>
+
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include<dlfcn.h>
+#include <sys/utsname.h>
+
+#include "gvfsbackendnds.h"
+#include "gvfsjobmountmountable.h"
+#include "gvfsjobopenforread.h"
+#include "gvfsjobread.h"
+#include "gvfsjobseekread.h"
+#include "gvfsjobqueryinfo.h"
+#include "gvfsjobenumerate.h"
+#include "gvfsdaemonprotocol.h"
+#include "gmounttracker.h"
+#include "gvfsmonitor.h"
+
+
+
+typedef struct {
+  char *name;
+  char *name_normalized;
+  char *name_utf8;
+} BrowseEntry;
+
+struct _GVfsBackendNds
+{
+  GVfsBackend parent_instance;
+
+  char *server;
+  char *mounted_server; 
+
+  GMutex *entries_lock;
+  GList *entries;
+  int entry_errno;
+};
+
+static GMountTracker *mount_tracker = NULL;
+
+G_DEFINE_TYPE (GVfsBackendNds, g_vfs_backend_nds, G_VFS_TYPE_BACKEND)
+
+static gboolean
+is_root (const char *filename)
+{
+  const char *p;
+
+  p = filename;
+  while (*p == '/')
+    p++;
+
+  return *p == 0;
+}
+
+static char *
+normalize_nds_name_helper (const char *name, gssize len, gboolean valid_utf8)
+{
+  if (valid_utf8)
+    return g_utf8_casefold (name, len);
+  else
+    return g_ascii_strdown (name, len);
+}
+
+static char *
+normalize_nds_name (const char *name, gssize len)
+{
+  gboolean valid_utf8;
+
+  valid_utf8 = g_utf8_validate (name, len, NULL);
+  return normalize_nds_name_helper (name, len, valid_utf8);
+}
+
+static char *
+nds_name_to_utf8 (const char *name, gboolean *valid_utf8_out)
+{
+  GString *string;
+  const gchar *remainder, *invalid;
+  gint remaining_bytes, valid_bytes;
+  gboolean valid_utf8;
+      
+  remainder = name;
+  remaining_bytes = strlen (name);
+  valid_utf8 = TRUE;
+  
+  string = g_string_sized_new (remaining_bytes);
+  while (remaining_bytes != 0) 
+    {
+      if (g_utf8_validate (remainder, remaining_bytes, &invalid)) 
+	break;
+      valid_utf8 = FALSE;
+      
+      valid_bytes = invalid - remainder;
+      
+      g_string_append_len (string, remainder, valid_bytes);
+      /* append U+FFFD REPLACEMENT CHARACTER */
+      g_string_append (string, "\357\277\275");
+      
+      remaining_bytes -= valid_bytes + 1;
+      remainder = invalid + 1;
+    }
+  
+  g_string_append (string, remainder);
+  
+  if (valid_utf8_out)
+    *valid_utf8_out = valid_utf8;
+  
+  return g_string_free (string, FALSE);
+}
+
+static void
+browse_entry_free (BrowseEntry *entry)
+{
+if(entry->name != NULL)
+  g_free (entry->name);
+if(entry != NULL)
+  g_free (entry);
+}
+
+
+static void
+g_vfs_backend_nds_finalize (GObject *object)
+{
+  GVfsBackendNds *backend;
+
+  backend = G_VFS_BACKEND_NDS (object);
+
+if(backend->mounted_server != NULL)
+  g_free (backend->mounted_server);
+if(backend->server != NULL)
+  g_free (backend->server);
+  
+  g_mutex_free (backend->entries_lock);
+  
+  g_list_foreach (backend->entries, (GFunc)browse_entry_free, NULL);
+if(backend->entries != NULL)
+  g_list_free (backend->entries);
+  
+  if (G_OBJECT_CLASS (g_vfs_backend_nds_parent_class)->finalize)
+    (*G_OBJECT_CLASS (g_vfs_backend_nds_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_backend_nds_init (GVfsBackendNds *backend)
+{
+  backend->entries_lock = g_mutex_new ();
+
+  if (mount_tracker == NULL)
+    mount_tracker = g_mount_tracker_new (NULL);
+}
+
+
+static void
+update_cache (GVfsBackendNds *backend,const char *filename)
+{
+  GString *uri;
+  GList *entries;
+  int entry_errno;
+  char *objectname=NULL;
+  char *treename=NULL;
+  GList *objectlist=NULL;
+  GList *object=NULL;
+  GList *l;
+  FILE *fptr=NULL;
+  void *handle=NULL; //handle for dlopen
+  int res;
+  char *ptr=NULL;
+  char *server_name=NULL;
+  struct utsname utsbuf;
+/* Function Pointer to /opt/novell/lib/libinterface.so */
+  int (*retrieve_children)(char *,char ***,int *);
+  char **object_list_array=NULL;
+  int num_objects=0;
+  int i;
+
+  entries = NULL;
+  entry_errno = 0;
+ 
+if(backend->server != NULL)
+{
+	server_name = g_strdup(backend->server);
+	if((ptr = strchr(server_name,'%')) != NULL)
+		*ptr = '\0';
+	
+}
+
+if(backend->server == NULL)  //retrieve Tree names
+{
+	treename = (char *)malloc(sizeof(char) * 80);
+        system("/opt/novell/ncl/bin/retrieve_trees.pl");
+	fptr = fopen("/tmp/ndstrees.txt","r");
+	if(fptr == NULL)
+	{
+		entry_errno = -1;
+		goto out;
+	}
+	while (fgets(treename,80,fptr) != NULL)
+	{
+		objectlist = g_list_append(objectlist,g_strdup(treename));
+		memset(treename,'\0',80);
+	}
+	fclose(fptr);
+	free(treename);
+}
+ 
+else  //retrieve object names      
+{
+	uname(&utsbuf);
+	if(!strcmp(utsbuf.machine,"x86_64"))
+		handle = dlopen("/usr/lib64/libinterface.so",RTLD_NOW | RTLD_DEEPBIND);
+	else
+		handle = dlopen("/usr/lib/libinterface.so",RTLD_NOW | RTLD_DEEPBIND);
+
+	if(handle == NULL)
+	{
+		return;
+	}
+	*(void **)(&retrieve_children) = dlsym(handle,"retrieve_children");
+	
+	if(retrieve_children != NULL)
+	{	
+	        res = (*retrieve_children)(server_name,&object_list_array,&num_objects);
+		if(res == 0)
+		{
+			for(i=0;i < num_objects; i++)
+			{
+				objectlist = g_list_append(objectlist,g_strdup(*(object_list_array+ i)));
+			}
+		}
+	}	
+	else
+	{
+		return;
+	}
+	dlclose(handle);
+}	
+ 
+ 
+	      gboolean valid_utf8;
+	      BrowseEntry *entry;
+
+for(object = objectlist;object != NULL;object = object->next)
+{
+	      entry = g_new (BrowseEntry, 1);
+	      objectname = object->data;
+	      entry->name = g_strdup (objectname);
+	      entry->name_utf8 = nds_name_to_utf8 (objectname, &valid_utf8);
+	      entry->name_normalized = normalize_nds_name_helper (objectname, -1, valid_utf8);
+	      
+	      entries = g_list_append (entries, entry);
+}
+	    
+//if(objectlist != NULL)
+//g_list_free(objectlist);
+
+ out:
+
+	if(entry_errno == 0)
+	{
+		g_mutex_lock (backend->entries_lock);
+		backend->entries = entries;
+		g_mutex_unlock (backend->entries_lock);
+	}
+	backend->entry_errno = entry_errno;
+  
+}
+
+static BrowseEntry *
+find_entry_unlocked (GVfsBackendNds *backend,
+		     const char *filename)
+{
+  BrowseEntry *entry, *found;
+  GList *l;
+  char *end;
+  int len;
+  char *normalized;
+
+  while (*filename == '/')
+    filename++;
+
+  end = strchr (filename, '/');
+  if (end)
+    {
+      len = end - filename;
+
+      while (*end == '/')
+	end++;
+
+      if (*end != 0)
+	return NULL;
+    }
+  else
+    len = strlen (filename);
+
+  /* First look for an exact filename match */
+  found = NULL;
+  for (l = backend->entries; l != NULL; l = l->next)
+    {
+      entry = l->data;
+      
+      if (strncmp (filename, entry->name, len) == 0 &&
+	  strlen (entry->name) == len)
+	{
+	  found = entry;
+	  break;
+	}
+    }
+
+  if (found == NULL)
+    {
+      /* That failed, try normalizing the filename */
+      normalized = normalize_nds_name (filename, len);
+      
+      for (l = backend->entries; l != NULL; l = l->next)
+	{
+	  entry = l->data;
+	  
+	  if (strcmp (normalized, entry->name_normalized) == 0)
+	    {
+	      found = entry;
+	      break;
+	    }
+	}
+if(normalized != NULL)
+      g_free (normalized);
+    }
+  
+  return found;
+}
+
+static GMountSpec *
+get_mount_spec_for_share (const char *server, const char *share)
+{
+  GMountSpec *mount_spec;
+  char *normalized;
+  
+  mount_spec = g_mount_spec_new ("nds");
+  g_mount_spec_set (mount_spec, "host", server);
+  g_mount_spec_set (mount_spec, "share", share);
+  
+  return mount_spec;
+}
+
+
+
+static void
+do_mount (GVfsBackend *backend,
+	  GVfsJobMount *job,
+	  GMountSpec *mount_spec,
+	  GMountSource *mount_source,
+	  gboolean is_automount)
+{
+  GVfsBackendNds *op_backend = G_VFS_BACKEND_NDS (backend);
+  char *display_name;
+  char *icon;
+  GMountSpec *browse_mount_spec;
+  char *ptr = NULL;
+
+
+  icon = NULL;
+  if (op_backend->server == NULL)
+    {
+      display_name = g_strdup (_("NVVFS Top Directory"));
+      browse_mount_spec = g_mount_spec_new ("nds");
+      icon = "network-workgroup";
+    }
+  else
+    {
+      display_name = g_strdup_printf (_("NVVFS Objects"));
+      browse_mount_spec = g_mount_spec_new ("nds");
+      //g_mount_spec_set (browse_mount_spec, "host", op_backend->mounted_server);
+      g_mount_spec_set (browse_mount_spec, "host", op_backend->server);
+      icon = "network-server";
+    }
+  
+  g_vfs_backend_set_display_name (backend, display_name);
+  g_free (display_name);
+  if (icon)
+    g_vfs_backend_set_icon_name (backend, icon);
+  g_vfs_backend_set_user_visible (backend, FALSE);  
+  g_vfs_backend_set_mount_spec (backend, browse_mount_spec);
+  g_mount_spec_unref (browse_mount_spec);
+
+  g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static gboolean
+try_mount (GVfsBackend *backend,
+	   GVfsJobMount *job,
+	   GMountSpec *mount_spec,
+	   GMountSource *mount_source,
+	   gboolean is_automount)
+{
+  GVfsBackendNds *op_backend = G_VFS_BACKEND_NDS (backend);
+  char *server;
+  char *share;
+
+  server = g_mount_spec_get (mount_spec, "host");
+  if (server)
+  {
+    op_backend->server = g_strdup (server);
+    op_backend->mounted_server = g_strdup (server);
+  }
+  else
+  {
+    op_backend->server = NULL;
+    op_backend->mounted_server = NULL;
+  }
+ 
+  return FALSE;
+}
+
+static void
+run_mount_mountable (GVfsBackendNds *backend,
+		     GVfsJobMountMountable *job,
+		     const char *filename,
+		     GMountSource *mount_source)
+{
+  BrowseEntry *entry;
+  GError *error = NULL;
+  GMountSpec *mount_spec;
+
+  g_mutex_lock (backend->entries_lock);
+  
+backend->server = g_strdup(filename);
+
+	  mount_spec = get_mount_spec_for_share (backend->server, filename);
+	  g_vfs_job_mount_mountable_set_target (job, mount_spec, "/", TRUE);
+          g_mount_spec_unref (mount_spec);
+  g_mutex_unlock (backend->entries_lock);
+
+    g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+
+static gboolean
+do_mount_mountable (GVfsBackend *backend,
+                    GVfsJobMountMountable *job,
+                    const char *filename,
+                    GMountSource *mount_source)
+{
+  GVfsBackendNds *op_backend = G_VFS_BACKEND_NDS (backend);
+
+update_cache (op_backend,filename);
+
+  run_mount_mountable (op_backend,
+		       job,
+		       filename,
+		       mount_source);
+  return TRUE;
+}
+
+static gboolean
+try_mount_mountable (GVfsBackend *backend,
+		     GVfsJobMountMountable *job,
+		     const char *filename,
+		     GMountSource *mount_source)
+{
+  GVfsBackendNds *op_backend = G_VFS_BACKEND_NDS (backend);
+
+
+ if (is_root (filename))
+ {
+   g_vfs_job_failed (G_VFS_JOB (job),
+                     G_IO_ERROR, G_IO_ERROR_NOT_MOUNTABLE_FILE,
+                     _("The file is not a mountable"));
+   return TRUE;
+ }
+
+update_cache (op_backend,filename);
+
+  run_mount_mountable (op_backend,
+		       job,
+		       filename,
+		       mount_source);
+  return TRUE;
+}
+
+
+
+#define SUB_DELIM_CHARS  "!$&'()*+,;="
+
+static gboolean
+is_valid (char c, const char *reserved_chars_allowed)
+{
+  if (g_ascii_isalnum (c) ||
+      c == '-' ||
+      c == '.' ||
+      c == '_' ||
+      c == '~')
+    return TRUE;
+
+  if (reserved_chars_allowed &&
+      strchr (reserved_chars_allowed, c) != NULL)
+    return TRUE;
+  
+  return FALSE;
+}
+
+static void
+g_string_append_encoded (GString *string,
+			 const char *encoded,
+			 const char *encoded_end,
+			 const char *reserved_chars_allowed)
+{
+  char c;
+  static const gchar hex[16] = "0123456789ABCDEF";
+
+  if (encoded_end == NULL)
+    encoded_end = encoded + strlen (encoded);
+  
+  while (encoded < encoded_end)
+    {
+      c = *encoded++;
+      
+      if (is_valid (c, reserved_chars_allowed))
+	g_string_append_c (string, c);
+      else
+	{
+	  g_string_append_c (string, '%');
+	  g_string_append_c (string, hex[((guchar)c) >> 4]);
+	  g_string_append_c (string, hex[((guchar)c) & 0xf]);
+	}
+    }
+}
+
+static void
+get_file_info_from_entry (GVfsBackendNds *backend, BrowseEntry *entry, GFileInfo *info)
+{
+  GMountSpec *mount_spec;
+  GString *uri;
+  GIcon *icon;
+  
+  g_file_info_set_name (info, entry->name);
+  g_file_info_set_display_name (info, entry->name_utf8);
+  g_file_info_set_edit_name (info, entry->name_utf8);
+  g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_STANDARD_IS_VIRTUAL, TRUE);
+
+  if(backend->server == NULL) //NDS-Tree icon
+	  icon = g_themed_icon_new ("ncl-ndstree");
+  else
+	  icon = g_themed_icon_new ("ncl-nwcontext");
+  
+  if (icon)
+    {
+      g_file_info_set_icon (info, icon);
+      g_object_unref (icon);
+    }
+  
+  mount_spec = NULL;
+
+    g_file_info_set_file_type (info, G_FILE_TYPE_SHORTCUT);
+
+    uri = g_string_new ("nds://");
+    g_string_append_encoded (uri, entry->name, NULL, NULL);
+    g_string_append_c (uri, '/');
+
+    g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI, uri->str);
+
+    g_string_free (uri, TRUE);
+
+}
+
+static void
+run_query_info (GVfsBackendNds *backend,
+		GVfsJobQueryInfo *job,
+		const char *filename,
+		GFileInfo *info,
+		GFileAttributeMatcher *matcher)
+{
+  BrowseEntry *entry;
+
+  g_mutex_lock (backend->entries_lock);
+  
+  entry = find_entry_unlocked (backend, filename);
+
+  if (entry)
+    get_file_info_from_entry (backend, entry, info);
+      
+  g_mutex_unlock (backend->entries_lock);
+
+  if (entry)
+    g_vfs_job_succeeded (G_VFS_JOB (job));
+  else
+    g_vfs_job_failed (G_VFS_JOB (job),
+		      G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+		      _("File doesn't exist"));
+}
+
+static void
+do_query_info (GVfsBackend *backend,
+	       GVfsJobQueryInfo *job,
+	       const char *filename,
+	       GFileQueryInfoFlags flags,
+	       GFileInfo *info,
+	       GFileAttributeMatcher *matcher)
+{
+  GVfsBackendNds *op_backend = G_VFS_BACKEND_NDS (backend);
+
+  run_query_info (op_backend, job, filename, info, matcher);
+}
+
+static gboolean
+try_query_info (GVfsBackend *backend,
+		GVfsJobQueryInfo *job,
+		const char *filename,
+		GFileQueryInfoFlags flags,
+		GFileInfo *info,
+		GFileAttributeMatcher *matcher)
+{
+  GVfsBackendNds *op_backend = G_VFS_BACKEND_NDS (backend);
+  const char *icon_name = NULL;
+  GIcon *icon;
+
+  if (filename && is_root (filename))
+  {
+    g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
+    g_file_info_set_name (info, "/");
+    g_file_info_set_display_name (info, g_vfs_backend_get_display_name (backend));
+    /* FIXME: This API does not seem to be in gvfs-1.2.0. Find a suitable replacement? */
+    /* icon_name = g_vfs_backend_get_icon_name (backend); */
+    if (icon_name)
+    {
+      icon = g_themed_icon_new (icon_name);
+      g_file_info_set_icon (info, icon);
+      g_object_unref (icon);
+    }
+    g_vfs_job_succeeded (G_VFS_JOB (job));
+    
+    return TRUE;
+  }
+
+  return FALSE;
+
+ run_query_info (op_backend, job, filename, info, matcher);
+ return TRUE;
+}
+
+static void
+run_enumerate (GVfsBackendNds *backend,
+	       GVfsJobEnumerate *job,
+	       const char *filename,
+	       GFileAttributeMatcher *matcher)
+{
+  GList *files, *l;
+  GFileInfo *info;
+
+  g_vfs_job_succeeded (G_VFS_JOB (job));
+
+  files = NULL;
+  g_mutex_lock (backend->entries_lock);
+  for (l = backend->entries; l != NULL; l = l->next)
+    {
+      BrowseEntry *entry = l->data;
+
+      info = g_file_info_new ();
+      get_file_info_from_entry (backend, entry, info);
+
+      files = g_list_prepend (files, info);
+    }
+  g_mutex_unlock (backend->entries_lock);
+  
+  files = g_list_reverse (files);
+
+  g_vfs_job_enumerate_add_infos (job, files);
+  g_list_foreach (files, (GFunc)g_object_unref, NULL);
+  g_list_free (files);
+
+  g_vfs_job_enumerate_done (job);
+}
+
+static void
+do_enumerate (GVfsBackend *backend,
+	      GVfsJobEnumerate *job,
+	      const char *filename,
+	      GFileAttributeMatcher *matcher,
+	      GFileQueryInfoFlags flags)
+{
+  GVfsBackendNds *op_backend = G_VFS_BACKEND_NDS (backend);
+
+  update_cache (op_backend,filename);
+
+  run_enumerate (op_backend, job, filename, matcher);
+}
+
+static gboolean
+try_enumerate (GVfsBackend *backend,
+	       GVfsJobEnumerate *job,
+	       const char *filename,
+	       GFileAttributeMatcher *matcher,
+	       GFileQueryInfoFlags flags)
+{
+  GVfsBackendNds *op_backend = G_VFS_BACKEND_NDS (backend);
+
+  update_cache (op_backend,filename);
+
+  run_enumerate (op_backend, job, filename, matcher);
+  return TRUE;
+}
+
+
+static void
+g_vfs_backend_nds_class_init (GVfsBackendNdsClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (klass);
+
+  gobject_class->finalize = g_vfs_backend_nds_finalize;
+
+  backend_class->mount = do_mount;
+  backend_class->try_mount = try_mount;
+  backend_class->query_info = do_query_info;
+  backend_class->try_query_info = try_query_info;
+  backend_class->enumerate = do_enumerate;
+  backend_class->try_enumerate = try_enumerate;
+}
+
+void
+g_vfs_nds_daemon_init (void)
+{
+  g_set_application_name (_("Displaying Embedded Objects"));
+}
Index: gvfs-1.9.0/daemon/gvfsbackendnds.h
===================================================================
--- /dev/null
+++ gvfs-1.9.0/daemon/gvfsbackendnds.h
@@ -0,0 +1,53 @@
+/* GIO - GLib Input, Output and Streaming Library
+ * 
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * 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 Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_BACKEND_NDS_H__
+#define __G_VFS_BACKEND_NDS_H__
+
+#include <gvfsbackend.h>
+#include <gmountspec.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_BACKEND_NDS         (g_vfs_backend_nds_get_type ())
+#define G_VFS_BACKEND_NDS(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_BACKEND_NDS, GVfsBackendNds))
+#define G_VFS_BACKEND_NDS_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_BACKEND_NDS, GVfsBackendNdsClass))
+#define G_VFS_IS_BACKEND_NDS(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_BACKEND_NDS))
+#define G_VFS_IS_BACKEND_NDS_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_BACKEND_NDS))
+#define G_VFS_BACKEND_NDS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_BACKEND_NDS, GVfsBackendNdsClass))
+
+typedef struct _GVfsBackendNds        GVfsBackendNds;
+typedef struct _GVfsBackendNdsClass   GVfsBackendNdsClass;
+
+struct _GVfsBackendNdsClass
+{
+  GVfsBackendClass parent_class;
+};
+
+GType g_vfs_backend_nds_get_type (void) G_GNUC_CONST;
+  
+#define BACKEND_SETUP_FUNC g_vfs_nds_daemon_init
+void g_vfs_nds_daemon_init (void);
+  
+G_END_DECLS
+
+#endif /* __G_VFS_BACKEND_NDS_H__ */
Index: gvfs-1.9.0/daemon/Makefile.am
===================================================================
--- gvfs-1.9.0.orig/daemon/Makefile.am
+++ gvfs-1.9.0/daemon/Makefile.am
@@ -113,6 +113,10 @@ mount_in_files += nvvfs.mount.in
 mount_DATA += nvvfs.mount
 libexec_PROGRAMS += gvfsd-nvvfs
 
+mount_in_files += nds.mount.in
+mount_DATA += nds.mount
+libexec_PROGRAMS += gvfsd-nds
+
 EXTRA_DIST = 				\
 	gvfs-daemon.service.in		\
 	$(mount_in_files)		\
@@ -449,6 +453,19 @@ gvfsd_http_CPPFLAGS = \
 
 gvfsd_http_LDADD = $(libraries) $(HTTP_LIBS)
 
+gvfsd_nds_SOURCES = \
+        gvfsbackendnds.c gvfsbackendnds.h \
+        daemon-main.c daemon-main.h \
+        daemon-main-generic.c
+
+gvfsd_nds_CPPFLAGS = $(flags) \
+        -DBACKEND_HEADER=gvfsbackendnds.h \
+        -DDEFAULT_BACKEND_TYPE=nds \
+        -DMAX_JOB_THREADS=1 \
+        -DBACKEND_TYPES='"nds", G_VFS_TYPE_BACKEND_NDS,'
+
+gvfsd_nds_LDADD = $(libraries) -ldl
+
 gvfsd_nvvfs_SOURCES = \
         gvfsbackendnvvfs.c gvfsbackendnvvfs.h \
         daemon-main.c daemon-main.h \
Index: gvfs-1.9.0/daemon/nds.mount.in
===================================================================
--- /dev/null
+++ gvfs-1.9.0/daemon/nds.mount.in
@@ -0,0 +1,5 @@
+[Mount]
+Type=nds
+Exec=@libexecdir@/gvfsd-nds
+AutoMount=false
+Scheme=nds