From 518a0d444e149bf0fedbd768aa8440417999338e Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Tue, 8 Jan 2008 15:07:59 +0000 Subject: Add initial computer backend 2008-01-08 Alexander Larsson * daemon/Makefile.am: * daemon/computer.mount.in: * daemon/gvfsbackendcomputer.[ch]: Add initial computer backend * daemon/gvfsbackend.h: * daemon/gvfsjobunmountmountable.[ch]: Add umount_mountable calls svn path=/trunk/; revision=1078 --- ChangeLog | 11 + daemon/Makefile.am | 20 +- daemon/computer.mount.in | 5 + daemon/gvfsbackend.h | 13 + daemon/gvfsbackendcomputer.c | 791 +++++++++++++++++++++++++++++++++++++++ daemon/gvfsbackendcomputer.h | 50 +++ daemon/gvfsjobunmountmountable.c | 192 ++++++++++ daemon/gvfsjobunmountmountable.h | 65 ++++ 8 files changed, 1144 insertions(+), 3 deletions(-) create mode 100644 daemon/computer.mount.in create mode 100644 daemon/gvfsbackendcomputer.c create mode 100644 daemon/gvfsbackendcomputer.h create mode 100644 daemon/gvfsjobunmountmountable.c create mode 100644 daemon/gvfsjobunmountmountable.h diff --git a/ChangeLog b/ChangeLog index ccd1999e..9ead94dd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2008-01-08 Alexander Larsson + + * daemon/Makefile.am: + * daemon/computer.mount.in: + * daemon/gvfsbackendcomputer.[ch]: + Add initial computer backend + + * daemon/gvfsbackend.h: + * daemon/gvfsjobunmountmountable.[ch]: + Add umount_mountable calls + 2008-01-07 Alexander Larsson * client/Makefile.am: diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 2762220d..c91a8e7d 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -30,10 +30,10 @@ service_DATA = gvfs-daemon.service %.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 @@ libdaemon_la_SOURCES = \ 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_CPPFLAGS = \ 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 \ diff --git a/daemon/computer.mount.in b/daemon/computer.mount.in new file mode 100644 index 00000000..c021644b --- /dev/null +++ b/daemon/computer.mount.in @@ -0,0 +1,5 @@ +[Mount] +Type=computer +Exec=@libexecdir@/gvfsd-computer +AutoMount=true + diff --git a/daemon/gvfsbackend.h b/daemon/gvfsbackend.h index 744e3a1b..c27eb0ba 100644 --- a/daemon/gvfsbackend.h +++ b/daemon/gvfsbackend.h @@ -46,6 +46,7 @@ typedef struct _GVfsBackendClass GVfsBackendClass; 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 @@ struct _GVfsBackendClass 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); diff --git a/daemon/gvfsbackendcomputer.c b/daemon/gvfsbackendcomputer.c new file mode 100644 index 00000000..90cf7fb8 --- /dev/null +++ b/daemon/gvfsbackendcomputer.c @@ -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 + */ + + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#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; +} diff --git a/daemon/gvfsbackendcomputer.h b/daemon/gvfsbackendcomputer.h new file mode 100644 index 00000000..03d781df --- /dev/null +++ b/daemon/gvfsbackendcomputer.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_COMPUTER_H__ +#define __G_VFS_BACKEND_COMPUTER_H__ + +#include +#include + +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__ */ diff --git a/daemon/gvfsjobunmountmountable.c b/daemon/gvfsjobunmountmountable.c new file mode 100644 index 00000000..89e413f8 --- /dev/null +++ b/daemon/gvfsjobunmountmountable.c @@ -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 + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#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; +} diff --git a/daemon/gvfsjobunmountmountable.h b/daemon/gvfsjobunmountmountable.h new file mode 100644 index 00000000..9f54e041 --- /dev/null +++ b/daemon/gvfsjobunmountmountable.h @@ -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 + */ + +#ifndef __G_VFS_JOB_UNMOUNT_MOUNTABLE_H__ +#define __G_VFS_JOB_UNMOUNT_MOUNTABLE_H__ + +#include +#include +#include +#include + +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__ */ -- cgit v1.2.1