Dominique Leuenberger
0052dec8f8
- Use older way than autopatch on SLE/Leap, which is not ready for the macro. - Rebase gvfs-nvvfs.patch. OBS-URL: https://build.opensuse.org/request/show/1120741 OBS-URL: https://build.opensuse.org/package/show/GNOME:Factory/gvfs?expand=0&rev=388
888 lines
23 KiB
Diff
888 lines
23 KiB
Diff
diff --git a/daemon/gvfsbackendnds.c b/daemon/gvfsbackendnds.c
|
|
new file mode 100644
|
|
index 0000000..960d457
|
|
--- /dev/null
|
|
+++ b/daemon/gvfsbackendnds.c
|
|
@@ -0,0 +1,747 @@
|
|
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode; nil; -*- */
|
|
+/* 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_clear (&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)
|
|
+{
|
|
+ g_mutex_init(&backend->entries_lock);
|
|
+
|
|
+ if (mount_tracker == NULL)
|
|
+ mount_tracker = g_mount_tracker_new (NULL, FALSE);
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+update_cache (GVfsBackendNds *backend,const char *filename)
|
|
+{
|
|
+ GList *entries;
|
|
+ int entry_errno;
|
|
+ char *objectname=NULL;
|
|
+ char *treename=NULL;
|
|
+ GList *objectlist=NULL;
|
|
+ GList *object=NULL;
|
|
+ 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;
|
|
+
|
|
+ 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)
|
|
+ {
|
|
+ char *normalized;
|
|
+ /* 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;
|
|
+
|
|
+
|
|
+ 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);
|
|
+ const char *server;
|
|
+
|
|
+ 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)
|
|
+{
|
|
+ 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)
|
|
+{
|
|
+ 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);
|
|
+ }
|
|
+
|
|
+ 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;
|
|
+ backend_class->try_mount_mountable = try_mount_mountable;
|
|
+ backend_class->mount_mountable = do_mount_mountable;
|
|
+}
|
|
+
|
|
+void
|
|
+g_vfs_nds_daemon_init (void)
|
|
+{
|
|
+ g_set_application_name (_("Displaying Embedded Objects"));
|
|
+}
|
|
diff --git a/daemon/gvfsbackendnds.h b/daemon/gvfsbackendnds.h
|
|
new file mode 100644
|
|
index 0000000..0b48ad6
|
|
--- /dev/null
|
|
+++ b/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__ */
|
|
diff --git a/daemon/meson.build b/daemon/meson.build
|
|
index dffeef3..dabdcb2 100644
|
|
--- a/daemon/meson.build
|
|
+++ b/daemon/meson.build
|
|
@@ -530,6 +530,22 @@ if enable_afp
|
|
mounts += ['afp-browse']
|
|
endif
|
|
|
|
+if enable_nds
|
|
+ sources = daemon_main_sources + files('gvfsbackendnds.c')
|
|
+
|
|
+ deps = [libdl_dep]
|
|
+
|
|
+ cflags = [
|
|
+ '-DBACKEND_HEADER=gvfsbackendnds.h',
|
|
+ '-DDEFAULT_BACKEND_TYPE=nds',
|
|
+ '-DBACKEND_TYPES="nds", G_VFS_TYPE_BACKEND_NDS,',
|
|
+ '-DMAX_JOB_THREADS=1',
|
|
+ ]
|
|
+
|
|
+ programs += {'gvfsd-nds': {'sources': sources, 'dependencies': deps, 'c_args': cflags}}
|
|
+ mounts += ['nds']
|
|
+endif
|
|
+
|
|
if enable_nfs
|
|
cflags = [
|
|
'-DBACKEND_HEADER=gvfsbackendnfs.h',
|
|
diff --git a/daemon/nds.mount.in b/daemon/nds.mount.in
|
|
new file mode 100644
|
|
index 0000000..1068344
|
|
--- /dev/null
|
|
+++ b/daemon/nds.mount.in
|
|
@@ -0,0 +1,5 @@
|
|
+[Mount]
|
|
+Type=nds
|
|
+Exec=@libexecdir@/gvfsd-nds
|
|
+AutoMount=false
|
|
+Scheme=nds
|
|
diff --git a/meson.build b/meson.build
|
|
index d844335..34d754f 100644
|
|
--- a/meson.build
|
|
+++ b/meson.build
|
|
@@ -448,6 +448,12 @@ config_h.set('HAVE_LIBMTP', enable_mtp)
|
|
# *** AFP backend ***
|
|
enable_afp = get_option('afp')
|
|
|
|
+# *** NDS backend ***
|
|
+enable_nds = get_option('nds')
|
|
+if enable_nds
|
|
+ libdl_dep = cc.find_library('dl')
|
|
+endif
|
|
+
|
|
# *** NFS backend ***
|
|
enable_nfs = get_option('nfs')
|
|
if enable_nfs
|
|
@@ -507,6 +513,7 @@ summary({
|
|
'gphoto2': enable_gphoto2,
|
|
'http': enable_http,
|
|
'mtp': enable_mtp,
|
|
+ 'nds': enable_nds,
|
|
'nfs': enable_nfs,
|
|
'sftp': enable_sftp,
|
|
'smb': enable_samba,
|
|
diff --git a/meson_options.txt b/meson_options.txt
|
|
index 32f10d4..dced004 100644
|
|
--- a/meson_options.txt
|
|
+++ b/meson_options.txt
|
|
@@ -12,6 +12,7 @@ option('google', type: 'boolean', value: true, description: 'build with google b
|
|
option('gphoto2', type: 'boolean', value: true, description: 'build with gphoto2 backend and volume monitor')
|
|
option('http', type: 'boolean', value: true, description: 'build with http/dav backends')
|
|
option('mtp', type: 'boolean', value: true, description: 'build with mtp backend and volume monitor')
|
|
+option('nds', type: 'boolean', value: true, description: 'build with nds backend')
|
|
option('nfs', type: 'boolean', value: true, description: 'build with nfs backend')
|
|
option('sftp', type: 'boolean', value: true, description: 'build with sftp backend')
|
|
option('smb', type: 'boolean', value: true, description: 'build with smb backends')
|