gvfs r1078 - in trunk: . daemon



Author: alexl
Date: Tue Jan  8 15:07:59 2008
New Revision: 1078
URL: http://svn.gnome.org/viewvc/gvfs?rev=1078&view=rev

Log:
2008-01-08  Alexander Larsson  <alexl redhat com>

        * daemon/Makefile.am:
        * daemon/computer.mount.in:
        * daemon/gvfsbackendcomputer.[ch]:
	Add initial computer backend
	
        * daemon/gvfsbackend.h:
        * daemon/gvfsjobunmountmountable.[ch]:
	Add umount_mountable calls




Added:
   trunk/daemon/computer.mount.in
   trunk/daemon/gvfsbackendcomputer.c
   trunk/daemon/gvfsbackendcomputer.h
   trunk/daemon/gvfsjobunmountmountable.c
   trunk/daemon/gvfsjobunmountmountable.h
Modified:
   trunk/ChangeLog
   trunk/daemon/Makefile.am
   trunk/daemon/gvfsbackend.h

Modified: trunk/daemon/Makefile.am
==============================================================================
--- trunk/daemon/Makefile.am	(original)
+++ trunk/daemon/Makefile.am	Tue Jan  8 15:07:59 2008
@@ -30,10 +30,10 @@
 %.mount: %.mount.in ../config.log
 	sed -e "s|\ libexecdir\@|$(libexecdir)|" $< > $@
 
-libexec_PROGRAMS=gvfsd gvfsd-ftp gvfsd-sftp gvfsd-trash
+libexec_PROGRAMS=gvfsd gvfsd-ftp gvfsd-sftp gvfsd-trash gvfsd-computer
 
-mount_in_files = ftp.mount.in sftp.mount.in trash.mount.in
-mount_DATA = ftp.mount sftp.mount trash.mount
+mount_in_files = ftp.mount.in sftp.mount.in trash.mount.in computer.mount.in
+mount_DATA = ftp.mount sftp.mount trash.mount computer.mount
 
 if HAVE_SAMBA
 mount_in_files += smb.mount.in smb-browse.mount.in
@@ -70,6 +70,7 @@
 	gvfsjobmount.c gvfsjobmount.h \
 	gvfsjobunmount.c gvfsjobunmount.h \
 	gvfsjobmountmountable.c gvfsjobmountmountable.h \
+	gvfsjobunmountmountable.c gvfsjobunmountmountable.h \
 	gvfsjobopenforread.c gvfsjobopenforread.h \
 	gvfsjobread.c gvfsjobread.h \
 	gvfsjobseekread.c gvfsjobseekread.h \
@@ -180,6 +181,19 @@
 
 gvfsd_trash_LDADD = $(libraries)
 
+gvfsd_computer_SOURCES = \
+	gvfsbackendcomputer.c gvfsbackendcomputer.h \
+	daemon-main.c daemon-main.h \
+	daemon-main-generic.c 
+
+gvfsd_computer_CPPFLAGS = \
+	-DBACKEND_HEADER=gvfsbackendcomputer.h \
+	-DDEFAULT_BACKEND_TYPE=computer \
+	-DMAX_JOB_THREADS=1 \
+	-DBACKEND_TYPES='"computer", G_VFS_TYPE_BACKEND_COMPUTER,'
+
+gvfsd_computer_LDADD = $(libraries)
+
 gvfsd_cdda_SOURCES = \
 	gvfsbackendcdda.c gvfsbackendcdda.h \
 	daemon-main.c daemon-main.h \

Added: trunk/daemon/computer.mount.in
==============================================================================
--- (empty file)
+++ trunk/daemon/computer.mount.in	Tue Jan  8 15:07:59 2008
@@ -0,0 +1,5 @@
+[Mount]
+Type=computer
+Exec= libexecdir@/gvfsd-computer
+AutoMount=true
+

Modified: trunk/daemon/gvfsbackend.h
==============================================================================
--- trunk/daemon/gvfsbackend.h	(original)
+++ trunk/daemon/gvfsbackend.h	Tue Jan  8 15:07:59 2008
@@ -46,6 +46,7 @@
 typedef struct _GVfsJobMount           GVfsJobMount;
 typedef struct _GVfsJobUnmount         GVfsJobUnmount;
 typedef struct _GVfsJobMountMountable  GVfsJobMountMountable;
+typedef struct _GVfsJobUnmountMountable GVfsJobUnmountMountable;
 typedef struct _GVfsJobOpenForRead     GVfsJobOpenForRead;
 typedef struct _GVfsJobSeekRead        GVfsJobSeekRead;
 typedef struct _GVfsJobCloseRead       GVfsJobCloseRead;
@@ -113,6 +114,18 @@
 				 GVfsJobMountMountable *job,
 				 const char *filename,
 				 GMountSource *mount_source);
+  void     (*unmount_mountable) (GVfsBackend *backend,
+				 GVfsJobUnmountMountable *job,
+				 const char *filename);
+  gboolean (*try_unmount_mountable)(GVfsBackend *backend,
+				 GVfsJobUnmountMountable *job,
+				 const char *filename);
+  void     (*eject_mountable)   (GVfsBackend *backend,
+				 GVfsJobUnmountMountable *job,
+				 const char *filename);
+  gboolean (*try_eject_mountable)(GVfsBackend *backend,
+				 GVfsJobUnmountMountable *job,
+				 const char *filename);
   void     (*open_for_read)     (GVfsBackend *backend,
 				 GVfsJobOpenForRead *job,
 				 const char *filename);

Added: trunk/daemon/gvfsbackendcomputer.c
==============================================================================
--- (empty file)
+++ trunk/daemon/gvfsbackendcomputer.c	Tue Jan  8 15:07:59 2008
@@ -0,0 +1,791 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 <sys/wait.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gio/gunixmounts.h>
+#include <glib/gurifuncs.h>
+
+#include "gvfsbackendcomputer.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 "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;
+  
+  GDrive *drive;
+  GVolume *volume;
+  GMount *mount;
+} ComputerFile;
+
+static ComputerFile root = { "/" };
+
+struct _GVfsBackendComputer
+{
+  GVfsBackend parent_instance;
+
+  GVolumeMonitor *volume_monitor;
+
+  GVfsMonitor *root_monitor;
+  
+  GList *files;
+  
+  guint recompute_idle_tag;
+  
+  GMountSpec *mount_spec;
+};
+
+G_DEFINE_TYPE (GVfsBackendComputer, g_vfs_backend_computer, G_VFS_TYPE_BACKEND);
+
+static void
+computer_file_free (ComputerFile *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);
+  
+  if (file->drive)
+    g_object_unref (file->drive);
+  if (file->volume)
+    g_object_unref (file->volume);
+  if (file->mount)
+    g_object_unref (file->mount);
+  
+  g_slice_free (ComputerFile, file);
+}
+
+/* Assumes filename equal */
+static gboolean
+computer_file_equal (ComputerFile *a,
+                     ComputerFile *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,
+                            GVfsBackendComputer *backend);
+
+static void
+g_vfs_backend_computer_finalize (GObject *object)
+{
+  GVfsBackendComputer *backend;
+
+  backend = G_VFS_BACKEND_COMPUTER (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_computer_parent_class)->finalize)
+    (*G_OBJECT_CLASS (g_vfs_backend_computer_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_backend_computer_init (GVfsBackendComputer *computer_backend)
+{
+  GVfsBackend *backend = G_VFS_BACKEND (computer_backend);
+  GMountSpec *mount_spec;
+  
+  g_vfs_backend_set_display_name (backend, _("Computer"));
+  g_vfs_backend_set_icon_name (backend, "gnome-fs-client");
+  g_vfs_backend_set_user_visible (backend, FALSE);
+
+  mount_spec = g_mount_spec_new ("computer");
+  g_vfs_backend_set_mount_spec (backend, mount_spec);
+  computer_backend->mount_spec = mount_spec;
+}
+
+static gboolean
+filename_is_used (GList *files, const char *filename)
+{
+  ComputerFile *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 (ComputerFile *a, ComputerFile *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 (GVfsBackendComputer *backend,
+                   GList *files)
+{
+  GList *old_files;
+  GList *oldl, *newl;
+  char *filename;
+  ComputerFile *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 (!computer_file_equal (old, new))
+            {
+              filename = g_strconcat ("/", new->filename, NULL);
+              g_vfs_monitor_emit_event (backend->root_monitor,
+                                        G_FILE_MONITOR_EVENT_CHANGED,
+                                        backend->mount_spec, filename,
+                                        NULL, 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,
+                                    backend->mount_spec, filename,
+                                    NULL, 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,
+                                    backend->mount_spec, filename,
+                                    NULL, NULL);
+          g_free (filename);
+          newl = newl->next;
+        }
+    }
+  
+  g_list_foreach (old_files, (GFunc)computer_file_free, NULL);
+}
+
+static void
+recompute_files (GVfsBackendComputer *backend)
+{
+  GVolumeMonitor *volume_monitor;
+  GList *drives, *volumes, *mounts, *l, *ll;
+  GDrive *drive;
+  GVolume *volume;
+  GMount *mount;
+  ComputerFile *file;
+  GList *files;
+  char *basename, *filename;
+  const char *extension;
+  int uniq;
+
+  volume_monitor = backend->volume_monitor;
+
+  files = NULL;
+  
+	/* first go through all connected drives */
+	drives = g_volume_monitor_get_connected_drives (volume_monitor);
+	for (l = drives; l != NULL; l = l->next)
+    {
+      drive = l->data;
+
+      volumes = g_drive_get_volumes (drive);
+      if (volumes != NULL)
+        {
+          for (ll = volumes; ll != NULL; ll = ll->next)
+            {
+              volume = ll->data;
+
+              file = g_slice_new (ComputerFile);
+              file->drive = g_object_ref (drive);
+              file->volume = volume; /* Takes ref */
+              file->mount = g_volume_get_mount (volume);
+              file->prio = -3;
+              files = g_list_prepend (files, file);
+            }
+        }
+      else
+        {
+          /* No volume, single drive */
+          
+          file = g_slice_new0 (ComputerFile);
+          file->drive = g_object_ref (drive);
+          file->volume = NULL;
+          file->mount = NULL;
+          file->prio = -3;
+          
+          files = g_list_prepend (files, file);
+        }
+      
+      g_object_unref (drive);
+    }
+	g_list_free (drives);
+  
+	/* add all volumes that is not associated with a drive */
+	volumes = g_volume_monitor_get_volumes (volume_monitor);
+	for (l = volumes; l != NULL; l = l->next)
+    {
+      volume = l->data;
+      drive = g_volume_get_drive (volume);
+      if (drive == NULL)
+        {
+          file = g_slice_new0 (ComputerFile);
+          file->drive = NULL;
+          file->volume = g_object_ref (volume);
+          file->mount = g_volume_get_mount (volume);
+          file->prio = -2;
+
+          files = g_list_prepend (files, file);
+        }
+      else
+        g_object_unref (drive);
+      
+      g_object_unref (volume);
+    }
+	g_list_free (volumes);
+
+	/* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */
+	mounts = g_volume_monitor_get_mounts (volume_monitor);
+	for (l = mounts; l != NULL; l = l->next)
+    {
+      mount = l->data;
+      volume = g_mount_get_volume (mount);
+      if (volume == NULL)
+        {
+          file = g_slice_new0 (ComputerFile);
+          file->drive = NULL;
+          file->volume = NULL;
+          file->mount = g_object_ref (mount);
+          file->prio = -1;
+
+          files = g_list_prepend (files, file);
+        }
+      else
+        g_object_unref (volume);
+      
+      g_object_unref (mount);
+    }
+	g_list_free (mounts);
+
+  files = g_list_reverse (files);
+  
+  for (l = files; l != NULL; l = l->next)
+    {
+      file = l->data;
+
+      if (file->mount)
+        {
+          file->icon = g_mount_get_icon (file->mount);
+          file->display_name = g_mount_get_name (file->mount);
+          file->root = g_mount_get_root (file->mount);
+          file->can_unmount = g_mount_can_unmount (file->mount);
+          file->can_eject = g_mount_can_eject (file->mount);
+        }
+      else if (file->volume)
+        {
+          file->icon = g_volume_get_icon (file->volume);
+          file->display_name = g_volume_get_name (file->volume);
+          file->can_mount = g_volume_can_mount (file->volume);
+          file->can_eject = g_volume_can_eject (file->volume);
+        }
+      else /* drive */
+        {
+          file->icon = g_drive_get_icon (file->drive);
+          file->display_name = g_drive_get_name (file->drive);
+          file->can_eject = g_drive_can_eject (file->drive);
+        }
+
+      if (file->drive)
+        {
+          basename = g_drive_get_name (file->drive);
+          extension = ".drive";
+        }
+      else if (file->volume)
+        {
+          basename = g_volume_get_name (file->volume);
+          extension = ".volume";
+        }
+      else /* mount */
+        {
+          basename = g_mount_get_name (file->mount);
+          extension = ".mount";
+        }
+
+      convert_slashes (basename); /* No slashes in filenames */
+      uniq = 1;
+      filename = g_strconcat (basename, extension, NULL);
+      while (filename_is_used (files, filename))
+        {
+          g_free (filename);
+          filename = g_strdup_printf ("%s-%d%s",
+                                      basename,
+                                      uniq++,
+                                      extension);
+        }
+      
+      g_free (basename);
+      file->filename = filename;
+    }
+
+  files = g_list_sort (files, (GCompareFunc)sort_file_by_filename);
+
+  update_from_files (backend, files);
+}
+
+static gboolean
+recompute_files_in_idle (GVfsBackendComputer *backend)
+{
+  backend->recompute_idle_tag = 0;
+
+  recompute_files (backend);
+  
+  return FALSE;
+}
+
+static void
+object_changed (GVolumeMonitor *monitor,
+                gpointer object,
+                GVfsBackendComputer *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)
+{
+  GVfsBackendComputer *computer_backend = G_VFS_BACKEND_COMPUTER (backend);
+  int i;
+  char *signals[] = {
+    "volume-added",
+    "volume-removed",
+    "volume-changed",
+    "mount-added",
+    "mount-removed",
+    "mount-changed",
+    "drive-connected",
+    "drive-disconnected",
+    "drive-changed",
+    NULL
+  };
+
+  computer_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 (computer_backend->volume_monitor,
+                           signals[i],
+                           (GCallback)object_changed,
+                           backend,
+                           NULL, 0);
+
+  computer_backend->root_monitor = g_vfs_monitor_new (g_vfs_backend_get_daemon (backend));
+  
+  recompute_files (computer_backend);
+
+  g_vfs_job_succeeded (G_VFS_JOB (job));
+
+  return TRUE;
+}
+
+static ComputerFile *
+lookup (GVfsBackendComputer *backend,
+        GVfsJob *job,
+        const char *filename)
+{
+  GList *l;
+  ComputerFile *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)
+{
+  ComputerFile *file;
+
+  file = lookup (G_VFS_BACKEND_COMPUTER (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 (ComputerFile *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);
+}
+
+static gboolean
+try_enumerate (GVfsBackend *backend,
+               GVfsJobEnumerate *job,
+               const char *filename,
+               GFileAttributeMatcher *attribute_matcher,
+               GFileQueryInfoFlags flags)
+{
+  ComputerFile *file;
+  GList *l;
+  GFileInfo *info;
+
+  file = lookup (G_VFS_BACKEND_COMPUTER (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,
+                          _("Can't enumerate non-directory"));
+      return TRUE;
+    }
+
+  g_vfs_job_succeeded (G_VFS_JOB (job));
+  
+  /* Enumerate root */
+  for (l = G_VFS_BACKEND_COMPUTER (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)
+{
+  ComputerFile *file;
+
+  file = lookup (G_VFS_BACKEND_COMPUTER (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, _("Computer"));
+      icon = g_themed_icon_new ("gnome-fs-client");
+      g_file_info_set_icon (info, icon);
+      g_object_unref (icon);
+    }
+  else if (file != NULL)
+    file_info_from_file (file, info);
+
+  g_vfs_job_succeeded (G_VFS_JOB (job));
+  
+  return TRUE;
+}
+
+static gboolean
+try_create_dir_monitor (GVfsBackend *backend,
+                        GVfsJobCreateMonitor *job,
+                        const char *filename,
+                        GFileMonitorFlags flags)
+{
+  ComputerFile *file;
+  GVfsBackendComputer *computer_backend;
+
+  computer_backend = G_VFS_BACKEND_COMPUTER (backend);
+
+  file = lookup (computer_backend,
+                 G_VFS_JOB (job), filename);
+
+  if (file != &root)
+    {
+      g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+                        G_IO_ERROR_NOT_SUPPORTED,
+                        _("Can't open mountable file"));
+      return TRUE;
+    }
+  
+  g_vfs_job_create_monitor_set_obj_path (job,
+                                         g_vfs_monitor_get_object_path (computer_backend->root_monitor));
+  g_vfs_job_succeeded (G_VFS_JOB (job));
+
+  return TRUE;
+}
+
+static gboolean
+try_mount_mountable (GVfsBackend *backend,
+                     GVfsJobMountMountable *job,
+                     const char *filename,
+                     GMountSource *mount_source)
+{
+  ComputerFile *file;
+
+  file = lookup (G_VFS_BACKEND_COMPUTER (backend),
+                 G_VFS_JOB (job), filename);
+  
+  if (file == &root)
+    g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+                      G_IO_ERROR_NOT_MOUNTABLE_FILE,
+                      _("Can't open directory"));
+  else if (file != NULL)
+    {
+#if 0
+      if (file->volume)
+        {
+          /* TODO: Implement */
+          g_volume_mount (file->volume,
+                          GMountOperation      *mount_operation,
+                          GCancellable         *cancellable,
+                          GAsyncReadyCallback   callback,
+                          gpointer              user_data);
+        }
+      else if (file->drive)
+        {
+          /* TODO: Poll for media? */
+        }
+      else
+#endif
+        {
+          g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+                            G_IO_ERROR_NOT_SUPPORTED,
+                            _("Can't mount file"));
+        }
+    }
+  
+  return TRUE;
+}
+
+static gboolean
+try_unmount_mountable (GVfsBackend *backend,
+                       GVfsJobMountMountable *job,
+                       const char *filename)
+{
+}
+
+static gboolean
+try_eject_mountable (GVfsBackend *backend,
+                     GVfsJobMountMountable *job,
+                     const char *filename)
+{
+}
+
+static void
+g_vfs_backend_computer_class_init (GVfsBackendComputerClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (klass);
+  
+  gobject_class->finalize = g_vfs_backend_computer_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;
+  backend_class->try_create_dir_monitor = try_create_dir_monitor;
+}

Added: trunk/daemon/gvfsbackendcomputer.h
==============================================================================
--- (empty file)
+++ trunk/daemon/gvfsbackendcomputer.h	Tue Jan  8 15:07:59 2008
@@ -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 <alexl redhat com>
+ */
+
+#ifndef __G_VFS_BACKEND_COMPUTER_H__
+#define __G_VFS_BACKEND_COMPUTER_H__
+
+#include <gvfsbackend.h>
+#include <gmountspec.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_BACKEND_COMPUTER         (g_vfs_backend_computer_get_type ())
+#define G_VFS_BACKEND_COMPUTER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_BACKEND_COMPUTER, GVfsBackendComputer))
+#define G_VFS_BACKEND_COMPUTER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_BACKEND_COMPUTER, GVfsBackendComputerClass))
+#define G_VFS_IS_BACKEND_COMPUTER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_BACKEND_COMPUTER))
+#define G_VFS_IS_BACKEND_COMPUTER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_BACKEND_COMPUTER))
+#define G_VFS_BACKEND_COMPUTER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_BACKEND_COMPUTER, GVfsBackendComputerClass))
+
+typedef struct _GVfsBackendComputer        GVfsBackendComputer;
+typedef struct _GVfsBackendComputerClass   GVfsBackendComputerClass;
+
+struct _GVfsBackendComputerClass
+{
+  GVfsBackendClass parent_class;
+};
+
+GType g_vfs_backend_computer_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __G_VFS_BACKEND_COMPUTER_H__ */

Added: trunk/daemon/gvfsjobunmountmountable.c
==============================================================================
--- (empty file)
+++ trunk/daemon/gvfsjobunmountmountable.c	Tue Jan  8 15:07:59 2008
@@ -0,0 +1,192 @@
+/* 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 <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsjobunmountmountable.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonutils.h"
+
+G_DEFINE_TYPE (GVfsJobUnmountMountable, g_vfs_job_unmount_mountable, G_VFS_TYPE_JOB_DBUS);
+
+static void         run          (GVfsJob        *job);
+static gboolean     try          (GVfsJob        *job);
+static DBusMessage *create_reply (GVfsJob        *job,
+				  DBusConnection *connection,
+				  DBusMessage    *message);
+
+static void
+g_vfs_job_unmount_mountable_finalize (GObject *object)
+{
+  GVfsJobUnmountMountable *job;
+
+  job = G_VFS_JOB_UNMOUNT_MOUNTABLE (object);
+
+  g_free (job->filename);
+  
+  if (G_OBJECT_CLASS (g_vfs_job_unmount_mountable_parent_class)->finalize)
+    (*G_OBJECT_CLASS (g_vfs_job_unmount_mountable_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_unmount_mountable_class_init (GVfsJobUnmountMountableClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+  GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
+  
+  gobject_class->finalize = g_vfs_job_unmount_mountable_finalize;
+  job_class->run = run;
+  job_class->try = try;
+  job_dbus_class->create_reply = create_reply;
+}
+
+static void
+g_vfs_job_unmount_mountable_init (GVfsJobUnmountMountable *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_unmount_mountable_new (DBusConnection *connection,
+				 DBusMessage *message,
+				 GVfsBackend *backend,
+				 gboolean eject)
+{
+  GVfsJobUnmountMountable *job;
+  DBusMessage *reply;
+  DBusMessageIter iter;
+  DBusError derror;
+  char *path;
+  const char *dbus_id, *obj_path;
+  
+  dbus_error_init (&derror);
+  dbus_message_iter_init (message, &iter);
+
+  path = NULL;
+  if (!_g_dbus_message_iter_get_args (&iter, &derror, 
+				      G_DBUS_TYPE_CSTRING, &path,
+				      DBUS_TYPE_STRING, &dbus_id,
+				      DBUS_TYPE_OBJECT_PATH, &obj_path,
+				      0))
+    {
+      g_free (path);
+      reply = dbus_message_new_error (message,
+				      derror.name,
+                                      derror.message);
+      dbus_error_free (&derror);
+
+      dbus_connection_send (connection, reply, NULL);
+      return NULL;
+    }
+
+  job = g_object_new (G_VFS_TYPE_JOB_UNMOUNT_MOUNTABLE,
+		      "message", message,
+		      "connection", connection,
+		      NULL);
+
+  job->filename = path;
+  job->backend = backend;
+  job->eject = eject;
+  
+  return G_VFS_JOB (job);
+}
+
+static void
+run (GVfsJob *job)
+{
+  GVfsJobUnmountMountable *op_job = G_VFS_JOB_UNMOUNT_MOUNTABLE (job);
+  GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+  if (op_job->eject)
+    {
+      if (class->eject_mountable == NULL)
+	{
+	  g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+			    _("Operation not supported by backend"));
+	  return;
+	}
+      
+      class->eject_mountable (op_job->backend,
+			      op_job,
+			      op_job->filename);
+    }
+  else
+    {
+      if (class->unmount_mountable == NULL)
+	{
+	  g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+			    _("Operation not supported by backend"));
+	  return;
+	}
+      
+      class->unmount_mountable (op_job->backend,
+				op_job,
+				op_job->filename);
+    }
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+  GVfsJobUnmountMountable *op_job = G_VFS_JOB_UNMOUNT_MOUNTABLE (job);
+  GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+  if (op_job->eject)
+    {
+      if (class->try_eject_mountable == NULL)
+	return FALSE;
+      
+      return class->try_eject_mountable (op_job->backend,
+					 op_job,
+					 op_job->filename);
+    }
+  else
+    {
+      if (class->try_unmount_mountable == NULL)
+	return FALSE;
+      
+      return class->try_unmount_mountable (op_job->backend,
+					   op_job,
+					   op_job->filename);
+    }
+}
+
+/* Might be called on an i/o thread */
+static DBusMessage *
+create_reply (GVfsJob *job,
+	      DBusConnection *connection,
+	      DBusMessage *message)
+{
+  DBusMessage *reply;
+
+  reply = dbus_message_new_method_return (message);
+  
+  return reply;
+}

Added: trunk/daemon/gvfsjobunmountmountable.h
==============================================================================
--- (empty file)
+++ trunk/daemon/gvfsjobunmountmountable.h	Tue Jan  8 15:07:59 2008
@@ -0,0 +1,65 @@
+/* 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_JOB_UNMOUNT_MOUNTABLE_H__
+#define __G_VFS_JOB_UNMOUNT_MOUNTABLE_H__
+
+#include <gio/gio.h>
+#include <gvfsjob.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_UNMOUNT_MOUNTABLE         (g_vfs_job_unmount_mountable_get_type ())
+#define G_VFS_JOB_UNMOUNT_MOUNTABLE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_UNMOUNT_MOUNTABLE, GVfsJobUnmountMountable))
+#define G_VFS_JOB_UNMOUNT_MOUNTABLE_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_UNMOUNT_MOUNTABLE, GVfsJobUnmountMountableClass))
+#define G_VFS_IS_JOB_UNMOUNT_MOUNTABLE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_UNMOUNT_MOUNTABLE))
+#define G_VFS_IS_JOB_UNMOUNT_MOUNTABLE_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_UNMOUNT_MOUNTABLE))
+#define G_VFS_JOB_UNMOUNT_MOUNTABLE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_UNMOUNT_MOUNTABLE, GVfsJobUnmountMountableClass))
+
+typedef struct _GVfsJobUnmountMountableClass   GVfsJobUnmountMountableClass;
+
+struct _GVfsJobUnmountMountable
+{
+  GVfsJobDBus parent_instance;
+
+  GVfsBackend *backend;
+  char *filename;
+  gboolean eject;
+};
+
+struct _GVfsJobUnmountMountableClass
+{
+  GVfsJobDBusClass parent_class;
+};
+
+GType g_vfs_job_unmount_mountable_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_unmount_mountable_new        (DBusConnection        *connection,
+						 DBusMessage           *message,
+						 GVfsBackend           *backend,
+						 gboolean               eject);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_UNMOUNT_MOUNTABLE_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]