Index: gvfs-1.52.0/daemon/gvfsbackendnvvfs.c =================================================================== --- /dev/null +++ gvfs-1.52.0/daemon/gvfsbackendnvvfs.c @@ -0,0 +1,591 @@ +/* -*- 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. + * + * Authors: Alexander Larsson + * Cosimo Cecchi + */ + + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "gvfsbackendnvvfs.h" +#include "gvfsmonitor.h" +#include "gvfsjobopenforread.h" +#include "gvfsjobread.h" +#include "gvfsjobseekread.h" +#include "gvfsjobopenforwrite.h" +#include "gvfsjobwrite.h" +#include "gvfsjobclosewrite.h" +#include "gvfsjobseekwrite.h" +#include "gvfsjobsetdisplayname.h" +#include "gvfsjobmountmountable.h" +#include "gvfsjobqueryinfo.h" +#include "gvfsjobdelete.h" +#include "gvfsjobqueryfsinfo.h" +#include "gvfsjobqueryattributes.h" +#include "gvfsjobenumerate.h" +#include "gvfsjobcreatemonitor.h" +#include "gvfsdaemonprotocol.h" + + + +typedef struct { + char *filename; + char *display_name; + GIcon *icon; + GFile *root; + int prio; + gboolean can_mount; + gboolean can_unmount; + gboolean can_eject; +} NovellNautilus; + +static NovellNautilus root = { "/" }; + +struct _GVfsBackendNvvfs +{ + GVfsBackend parent_instance; + + GVolumeMonitor *volume_monitor; + + GVfsMonitor *root_monitor; + + GList *files; + + guint recompute_idle_tag; + + GMountSpec *mount_spec; +}; + +G_DEFINE_TYPE (GVfsBackendNvvfs, g_vfs_backend_nvvfs, G_VFS_TYPE_BACKEND) + +static void +nvvfs_file_free (NovellNautilus *file) +{ + g_free (file->filename); + g_free (file->display_name); + if (file->icon) + g_object_unref (file->icon); + if (file->root) + g_object_unref (file->root); + + g_slice_free (NovellNautilus, file); +} + +/* Assumes filename equal */ +static gboolean +nvvfs_file_equal (NovellNautilus *a, + NovellNautilus *b) +{ + if (strcmp (a->display_name, b->display_name) != 0) + return FALSE; + + if (!g_icon_equal (a->icon, b->icon)) + return FALSE; + + if ((a->root != NULL && b->root != NULL && + !g_file_equal (a->root, b->root)) || + (a->root != NULL && b->root == NULL) || + (a->root == NULL && b->root != NULL)) + return FALSE; + + if (a->prio != b->prio) + return FALSE; + + if (a->can_mount != b->can_mount || + a->can_unmount != b->can_unmount || + a->can_eject != b->can_eject) + return FALSE; + + return TRUE; +} + +static void object_changed (GVolumeMonitor *monitor, + gpointer object, + GVfsBackendNvvfs *backend); + +static void +g_vfs_backend_nvvfs_finalize (GObject *object) +{ + GVfsBackendNvvfs *backend; + + backend = G_VFS_BACKEND_NVVFS (object); + + if (backend->volume_monitor) + { + g_signal_handlers_disconnect_by_func(backend->volume_monitor, object_changed, backend); + g_object_unref (backend->volume_monitor); + } + + g_mount_spec_unref (backend->mount_spec); + + if (backend->recompute_idle_tag) + { + g_source_remove (backend->recompute_idle_tag); + backend->recompute_idle_tag = 0; + } + + g_object_unref (backend->root_monitor); + + if (G_OBJECT_CLASS (g_vfs_backend_nvvfs_parent_class)->finalize) + (*G_OBJECT_CLASS (g_vfs_backend_nvvfs_parent_class)->finalize) (object); +} + +static void +g_vfs_backend_nvvfs_init (GVfsBackendNvvfs *nvvfs_backend) +{ + GVfsBackend *backend = G_VFS_BACKEND (nvvfs_backend); + GMountSpec *mount_spec; + + g_vfs_backend_set_display_name (backend, _("Nvvfs")); + g_vfs_backend_set_icon_name (backend, "gnome-fs-client"); + g_vfs_backend_set_user_visible (backend, FALSE); + + mount_spec = g_mount_spec_new ("nvvfs"); + g_vfs_backend_set_mount_spec (backend, mount_spec); + nvvfs_backend->mount_spec = mount_spec; +} + +static gboolean +filename_is_used (GList *files, const char *filename) +{ + NovellNautilus *file; + + while (files != NULL) + { + file = files->data; + + if (file->filename == NULL) + return FALSE; + + if (strcmp (file->filename, filename) == 0) + return TRUE; + + files = files->next; + } + return FALSE; +} + +static int +sort_file_by_filename (NovellNautilus *a, NovellNautilus *b) +{ + return strcmp (a->filename, b->filename); +} + +static void +convert_slashes (char *str) +{ + char *s; + + while ((s = strchr (str, '/')) != NULL) + *s = '\\'; +} + +static void +update_from_files (GVfsBackendNvvfs *backend, + GList *files) +{ + GList *old_files; + GList *oldl, *newl; + char *filename; + NovellNautilus *old, *new; + int cmp; + + old_files = backend->files; + backend->files = files; + + /* Generate change events */ + oldl = old_files; + newl = files; + while (oldl != NULL || newl != NULL) + { + if (oldl == NULL) + { + cmp = 1; + new = newl->data; + old = NULL; + } + else if (newl == NULL) + { + cmp = -1; + new = NULL; + old = oldl->data; + } + else + { + new = newl->data; + old = oldl->data; + cmp = strcmp (old->filename, new->filename); + } + + if (cmp == 0) + { + if (!nvvfs_file_equal (old, new)) + { + filename = g_strconcat ("/", new->filename, NULL); + g_vfs_monitor_emit_event (backend->root_monitor, + G_FILE_MONITOR_EVENT_CHANGED, + filename, + NULL); + g_free (filename); + } + + oldl = oldl->next; + newl = newl->next; + } + else if (cmp < 0) + { + filename = g_strconcat ("/", old->filename, NULL); + g_vfs_monitor_emit_event (backend->root_monitor, + G_FILE_MONITOR_EVENT_DELETED, + filename, + NULL); + g_free (filename); + oldl = oldl->next; + } + else + { + filename = g_strconcat ("/", new->filename, NULL); + g_vfs_monitor_emit_event (backend->root_monitor, + G_FILE_MONITOR_EVENT_CREATED, + filename, + NULL); + g_free (filename); + newl = newl->next; + } + } + + g_list_foreach (old_files, (GFunc)nvvfs_file_free, NULL); +} + +static void +recompute_files (GVfsBackendNvvfs *backend) +{ + GVolumeMonitor *volume_monitor; + GList *drives, *volumes, *mounts, *l, *ll; + GDrive *drive; + GVolume *volume; + GMount *mount; + NovellNautilus *file; + GList *files; + char *basename, *filename; + const char *extension; + int uniq; + + gchar *nclmnt_path = "/var/opt/novell/nclmnt/"; + gchar *user_name=NULL; + gchar *path_ncl=NULL; + + volume_monitor = backend->volume_monitor; + + files = NULL; + + +// Im building the path for Novell Client mounts + user_name = g_get_user_name(); + path_ncl = g_strconcat(nclmnt_path,user_name,NULL); + + file = g_slice_new0 (NovellNautilus); + file->filename = g_strdup ("root.link"); + file->display_name = g_strdup (_("Available Connections")); + file->icon = g_themed_icon_new("ncl-logo"); + file->root = g_file_new_for_path (path_ncl); + file->prio = 0; + + files = g_list_prepend (files, file); + + file = g_slice_new0 (NovellNautilus); + file->filename = g_strdup ("root.lnk"); + file->display_name = g_strdup (_("All Connections")); + file->icon = g_themed_icon_new("ncl-logo"); + file->root = g_file_new_for_path (path_ncl); + file->prio = 0; + + files = g_list_prepend (files, file); + + files = g_list_reverse (files); + + files = g_list_sort (files, (GCompareFunc)sort_file_by_filename); + + update_from_files (backend, files); +} + +static gboolean +recompute_files_in_idle (GVfsBackendNvvfs *backend) +{ + backend->recompute_idle_tag = 0; + + recompute_files (backend); + + return FALSE; +} + +static void +object_changed (GVolumeMonitor *monitor, + gpointer object, + GVfsBackendNvvfs *backend) +{ + if (backend->recompute_idle_tag == 0) + backend->recompute_idle_tag = + g_idle_add ((GSourceFunc)recompute_files_in_idle, + backend); +} + +static gboolean +try_mount (GVfsBackend *backend, + GVfsJobMount *job, + GMountSpec *mount_spec, + GMountSource *mount_source, + gboolean is_automount) +{ + GVfsBackendNvvfs *nvvfs_backend = G_VFS_BACKEND_NVVFS (backend); + int i; + char *signals[] = { + "volume-added", + "volume-removed", + "volume-changed", + "mount-added", + "mount-removed", + "mount-changed", + "drive-connected", + "drive-disconnected", + "drive-changed", + NULL + }; + + nvvfs_backend->volume_monitor = g_volume_monitor_get (); + + /* TODO: connect all signals to object_changed */ + + for (i = 0; signals[i] != NULL; i++) + g_signal_connect_data (nvvfs_backend->volume_monitor, + signals[i], + (GCallback)object_changed, + backend, + NULL, 0); + + nvvfs_backend->root_monitor = g_vfs_monitor_new (backend); + + recompute_files (nvvfs_backend); + + g_vfs_job_succeeded (G_VFS_JOB (job)); + + return TRUE; +} + +static NovellNautilus * +lookup (GVfsBackendNvvfs *backend, + GVfsJob *job, + const char *filename) +{ + GList *l; + NovellNautilus *file; + + if (*filename != '/') + goto out; + + while (*filename == '/') + filename++; + + if (*filename == 0) + return &root; + + if (strchr (filename, '/') != NULL) + goto out; + + for (l = backend->files; l != NULL; l = l->next) + { + file = l->data; + + if (strcmp (file->filename, filename) == 0) + return file; + } + + out: + g_vfs_job_failed (job, G_IO_ERROR, + G_IO_ERROR_NOT_FOUND, + _("File doesn't exist")); + return NULL; +} + + +static gboolean +try_open_for_read (GVfsBackend *backend, + GVfsJobOpenForRead *job, + const char *filename) +{ + NovellNautilus *file; + + file = lookup (G_VFS_BACKEND_NVVFS (backend), + G_VFS_JOB (job), filename); + + if (file == &root) + g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, + G_IO_ERROR_IS_DIRECTORY, + _("Can't open directory")); + else if (file != NULL) + g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + _("Can't open mountable file")); + return TRUE; +} + +static void +file_info_from_file (NovellNautilus *file, + GFileInfo *info) +{ + char *uri; + + g_file_info_set_name (info, file->filename); + g_file_info_set_display_name (info, file->display_name); + + if (file->icon) + g_file_info_set_icon (info, file->icon); + + if (file->root) + { + uri = g_file_get_uri (file->root); + + g_file_info_set_attribute_string (info, + G_FILE_ATTRIBUTE_STANDARD_TARGET_URI, + uri); + g_free (uri); + } + + g_file_info_set_sort_order (info, file->prio); + + g_file_info_set_file_type (info, G_FILE_TYPE_MOUNTABLE); + g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT, file->can_mount); + g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT, file->can_unmount); + g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT, file->can_eject); + + 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); +} + +static gboolean +try_enumerate (GVfsBackend *backend, + GVfsJobEnumerate *job, + const char *filename, + GFileAttributeMatcher *attribute_matcher, + GFileQueryInfoFlags flags) +{ + NovellNautilus *file; + GList *l; + GFileInfo *info; + + file = lookup (G_VFS_BACKEND_NVVFS (backend), + G_VFS_JOB (job), filename); + + 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_NVVFS (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 *filename, + GFileQueryInfoFlags flags, + GFileInfo *info, + GFileAttributeMatcher *matcher) +{ + NovellNautilus *file; + + file = lookup (G_VFS_BACKEND_NVVFS (backend), + G_VFS_JOB (job), filename); + + if (file == &root) + { + GIcon *icon; + + g_file_info_set_name (info, "/"); + g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY); + g_file_info_set_display_name (info, _("Nvvfs")); + icon = g_themed_icon_new ("gnome-fs-client"); + 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 +g_vfs_backend_nvvfs_class_init (GVfsBackendNvvfsClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (klass); + + gobject_class->finalize = g_vfs_backend_nvvfs_finalize; + + backend_class->try_mount = try_mount; + backend_class->try_open_for_read = try_open_for_read; + backend_class->try_query_info = try_query_info; + backend_class->try_enumerate = try_enumerate; +} Index: gvfs-1.52.0/daemon/gvfsbackendnvvfs.h =================================================================== --- /dev/null +++ gvfs-1.52.0/daemon/gvfsbackendnvvfs.h @@ -0,0 +1,50 @@ +/* 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 + */ + +#ifndef __G_VFS_BACKEND_NVVFS_H__ +#define __G_VFS_BACKEND_NVVFS_H__ + +#include +#include + +G_BEGIN_DECLS + +#define G_VFS_TYPE_BACKEND_NVVFS (g_vfs_backend_nvvfs_get_type ()) +#define G_VFS_BACKEND_NVVFS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_BACKEND_NVVFS, GVfsBackendNvvfs)) +#define G_VFS_BACKEND_NVVFS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_BACKEND_NVVFS, GVfsBackendNvvfsClass)) +#define G_VFS_IS_BACKEND_NVVFS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_BACKEND_NVVFS)) +#define G_VFS_IS_BACKEND_NVVFS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_BACKEND_NVVFS)) +#define G_VFS_BACKEND_NVVFS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_BACKEND_NVVFS, GVfsBackendNvvfsClass)) + +typedef struct _GVfsBackendNvvfs GVfsBackendNvvfs; +typedef struct _GVfsBackendNvvfsClass GVfsBackendNvvfsClass; + +struct _GVfsBackendNvvfsClass +{ + GVfsBackendClass parent_class; +}; + +GType g_vfs_backend_nvvfs_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __G_VFS_BACKEND_NVVFS_H__ */ Index: gvfs-1.52.0/daemon/meson.build =================================================================== --- gvfs-1.52.0.orig/daemon/meson.build +++ gvfs-1.52.0/daemon/meson.build @@ -557,6 +557,20 @@ if enable_nfs mounts += ['nfs'] endif +if enable_nvvfs + sources = daemon_main_sources + files('gvfsbackendnvvfs.c') + + cflags = [ + '-DBACKEND_HEADER=gvfsbackendnvvfs.h', + '-DDEFAULT_BACKEND_TYPE=nvvfs', + '-DBACKEND_TYPES="nvvfs", G_VFS_TYPE_BACKEND_NVVFS,', + '-DMA_JOB_THREADS=1', + ] + + programs += {'gvfsd-nvvfs': {'sources': sources, 'dependencies': [gio_unix_dep], 'c_args': cflags}} + mounts += ['nvvfs'] +endif + foreach program, options: programs kwargs = { 'sources': daemon_main_sources + options.get('sources', []), Index: gvfs-1.52.0/daemon/nvvfs.mount.in =================================================================== --- /dev/null +++ gvfs-1.52.0/daemon/nvvfs.mount.in @@ -0,0 +1,5 @@ +[Mount] +Type=nvvfs +Exec=@libexecdir@/gvfsd-nvvfs +AutoMount=false +Scheme=nvvfs Index: gvfs-1.52.0/meson.build =================================================================== --- gvfs-1.52.0.orig/meson.build +++ gvfs-1.52.0/meson.build @@ -462,6 +462,9 @@ if enable_nfs libnfs_dep = dependency('libnfs', version: '>= 1.9.8') endif +# *** NVVFS backend *** +enable_nvvfs = get_option('nvvfs') + # *** SFTP backend *** enable_sftp = get_option('sftp') @@ -512,6 +515,7 @@ summary({ 'http': enable_http, 'mtp': enable_mtp, 'nds': enable_nds, + 'nvvfs': enable_nvvfs, 'nfs': enable_nfs, 'sftp': enable_sftp, 'smb': enable_samba, Index: gvfs-1.52.0/meson_options.txt =================================================================== --- gvfs-1.52.0.orig/meson_options.txt +++ gvfs-1.52.0/meson_options.txt @@ -15,6 +15,7 @@ option('http', type: 'boolean', value: t 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('nvvfs', type: 'boolean', value: true, description: 'build with nvvfs backend') option('sftp', type: 'boolean', value: true, description: 'build with sftp backend') option('smb', type: 'boolean', value: true, description: 'build with smb backends') option('udisks2', type: 'boolean', value: true, description: 'build with udisks2 volume monitor')