diff options
author | Gene Z. Ragan <gzr@eazel.com> | 2000-08-02 22:04:26 +0000 |
---|---|---|
committer | Gene Ragan <gzr@src.gnome.org> | 2000-08-02 22:04:26 +0000 |
commit | 1d671db24c6695931e8eb5294380ecf0bfbed04f (patch) | |
tree | 2b28bd70bdd62c2c5cac989f4d8c8a3024623666 | |
parent | 9bd742ccffb88bc8e6a9a442a521da5778e80bbe (diff) | |
download | nautilus-1d671db24c6695931e8eb5294380ecf0bfbed04f.tar.gz |
Fixed bug 1866, Turn volume mounting code into an object.
2000-08-02 Gene Z. Ragan <gzr@eazel.com>
Fixed bug 1866, Turn volume mounting code into an object.
Monitor now emits a signal, volume_mounted, when a mount occurs.
Removed the old fm-desktop-mounting files and added
new nautilus-volume-monitor files.
* libnautilus-extensions/Makefile.am:
* src/file-manager/Makefile.am:
Added new files and removed old ones.
* libnautilus-extensions/nautilus-cdrom-extensions.h:
New file
* libnautilus-extensions/nautilus-iso9660.h:
New file
* libnautilus-extensions/nautilus-volume-monitor.c:
New file
(nautilus_volume_monitor_initialize),
(nautilus_volume_monitor_initialize_class),
(nautilus_volume_monitor_destroy), (nautilus_volume_monitor_get),
(floppy_sort), (fm_desktop_get_removable_volume_list),
(nautilus_volume_monitor_volume_is_mounted),
(mount_device_is_mounted), (mount_device_cdrom_set_state),
(mount_device_floppy_set_state), (mount_device_ext2_set_state),
(mount_device_set_state), (device_set_state_empty),
(mount_device_mount), (mount_device_activate_cdrom),
(mount_device_activate_floppy), (mount_device_activate_ext2),
(mount_device_activate), (eject_cdrom), (mount_device_deactivate),
(mount_device_do_nothing), (mount_device_check_change),
(mount_devices_update_is_mounted), (mount_devices_check_status),
(check_permissions), (mount_device_floppy_add),
(mount_device_ext2_add), (cdrom_ioctl_frenzy),
(mount_device_iso9660_add), (mount_device_add_aliases),
(add_mount_device), (mntent_is_removable_fs), (mntent_has_option),
(nautilus_volume_monitor_find_mount_devices),
(nautilus_volume_monitor_mount_unmount_removable),
(remove_mount_link), (free_device_info), (get_iso9660_volume_name),
(get_ext2_volume_name), (get_floppy_volume_name):
* libnautilus-extensions/nautilus-volume-monitor.h:
New file
* src/file-manager/fm-cdrom-extensions.h:
* src/file-manager/fm-desktop-icon-view.c:
(fm_desktop_icon_view_destroy), (fm_desktop_icon_view_initialize),
(fm_desktop_icon_view_create_background_context_menu_items),
(fm_desktop_icon_view_trash_state_changed_callback),
(mount_unmount_removable), (place_home_directory):
* src/file-manager/fm-desktop-icon-view.h:
* src/file-manager/fm-desktop-mounting.c:
* src/file-manager/fm-desktop-mounting.h:
* src/file-manager/iso9660.h:
All old files that have been removed from build.
-rw-r--r-- | ChangeLog | 58 | ||||
-rw-r--r-- | libnautilus-extensions/Makefile.am | 1 | ||||
-rw-r--r-- | libnautilus-extensions/nautilus-cdrom-extensions.h (renamed from src/file-manager/fm-cdrom-extensions.h) | 0 | ||||
-rw-r--r-- | libnautilus-extensions/nautilus-iso9660.h (renamed from src/file-manager/iso9660.h) | 0 | ||||
-rw-r--r-- | libnautilus-extensions/nautilus-volume-monitor.c (renamed from src/file-manager/fm-desktop-mounting.c) | 379 | ||||
-rw-r--r-- | libnautilus-extensions/nautilus-volume-monitor.h | 105 | ||||
-rw-r--r-- | libnautilus-private/Makefile.am | 1 | ||||
-rw-r--r-- | libnautilus-private/nautilus-cdrom-extensions.h | 222 | ||||
-rw-r--r-- | libnautilus-private/nautilus-iso9660.h | 106 | ||||
-rw-r--r-- | libnautilus-private/nautilus-volume-monitor.c | 977 | ||||
-rw-r--r-- | libnautilus-private/nautilus-volume-monitor.h | 105 | ||||
-rw-r--r-- | src/file-manager/Makefile.am | 1 | ||||
-rw-r--r-- | src/file-manager/fm-desktop-icon-view.c | 85 | ||||
-rw-r--r-- | src/file-manager/fm-desktop-icon-view.h | 6 | ||||
-rw-r--r-- | src/file-manager/fm-desktop-mounting.h | 78 |
15 files changed, 1853 insertions, 271 deletions
@@ -1,3 +1,61 @@ +2000-08-02 Gene Z. Ragan <gzr@eazel.com> + + Fixed bug 1866, Turn volume mounting code into an object. + + Monitor now emits a signal, volume_mounted, when a mount occurs. + + Removed the old fm-desktop-mounting files and added + new nautilus-volume-monitor files. + + * libnautilus-extensions/Makefile.am: + * src/file-manager/Makefile.am: + Added new files and removed old ones. + + * libnautilus-extensions/nautilus-cdrom-extensions.h: + New file + + * libnautilus-extensions/nautilus-iso9660.h: + New file + + * libnautilus-extensions/nautilus-volume-monitor.c: + New file + (nautilus_volume_monitor_initialize), + (nautilus_volume_monitor_initialize_class), + (nautilus_volume_monitor_destroy), (nautilus_volume_monitor_get), + (floppy_sort), (fm_desktop_get_removable_volume_list), + (nautilus_volume_monitor_volume_is_mounted), + (mount_device_is_mounted), (mount_device_cdrom_set_state), + (mount_device_floppy_set_state), (mount_device_ext2_set_state), + (mount_device_set_state), (device_set_state_empty), + (mount_device_mount), (mount_device_activate_cdrom), + (mount_device_activate_floppy), (mount_device_activate_ext2), + (mount_device_activate), (eject_cdrom), (mount_device_deactivate), + (mount_device_do_nothing), (mount_device_check_change), + (mount_devices_update_is_mounted), (mount_devices_check_status), + (check_permissions), (mount_device_floppy_add), + (mount_device_ext2_add), (cdrom_ioctl_frenzy), + (mount_device_iso9660_add), (mount_device_add_aliases), + (add_mount_device), (mntent_is_removable_fs), (mntent_has_option), + (nautilus_volume_monitor_find_mount_devices), + (nautilus_volume_monitor_mount_unmount_removable), + (remove_mount_link), (free_device_info), (get_iso9660_volume_name), + (get_ext2_volume_name), (get_floppy_volume_name): + + * libnautilus-extensions/nautilus-volume-monitor.h: + New file + + * src/file-manager/fm-cdrom-extensions.h: + * src/file-manager/fm-desktop-icon-view.c: + (fm_desktop_icon_view_destroy), (fm_desktop_icon_view_initialize), + (fm_desktop_icon_view_create_background_context_menu_items), + (fm_desktop_icon_view_trash_state_changed_callback), + (mount_unmount_removable), (place_home_directory): + * src/file-manager/fm-desktop-icon-view.h: + * src/file-manager/fm-desktop-mounting.c: + * src/file-manager/fm-desktop-mounting.h: + * src/file-manager/iso9660.h: + All old files that have been removed from build. + 2000-08-02 Arlo Rose <arlo@eazel.com> * icons/eazel/Back.png: diff --git a/libnautilus-extensions/Makefile.am b/libnautilus-extensions/Makefile.am index 003aeb4e6..d2843e72f 100644 --- a/libnautilus-extensions/Makefile.am +++ b/libnautilus-extensions/Makefile.am @@ -103,6 +103,7 @@ libnautilus_extensions_la_SOURCES = \ nautilus-undo-signal-handlers.c \ nautilus-user-level-manager.c \ nautilus-view-identifier.c \ + nautilus-volume-monitor.c \ nautilus-xml-extensions.c \ $(NULL) diff --git a/src/file-manager/fm-cdrom-extensions.h b/libnautilus-extensions/nautilus-cdrom-extensions.h index 17770e5e9..17770e5e9 100644 --- a/src/file-manager/fm-cdrom-extensions.h +++ b/libnautilus-extensions/nautilus-cdrom-extensions.h diff --git a/src/file-manager/iso9660.h b/libnautilus-extensions/nautilus-iso9660.h index ad68b15fa..ad68b15fa 100644 --- a/src/file-manager/iso9660.h +++ b/libnautilus-extensions/nautilus-iso9660.h diff --git a/src/file-manager/fm-desktop-mounting.c b/libnautilus-extensions/nautilus-volume-monitor.c index d29bb5034..052823f5b 100644 --- a/src/file-manager/fm-desktop-mounting.c +++ b/libnautilus-extensions/nautilus-volume-monitor.c @@ -1,6 +1,6 @@ /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* fm-desktop-mounting.c - Desktop volume mounting routines. +/* nautilus-volume-monitor.c - Desktop volume mounting routines. Copyright (C) 2000 Eazel, Inc. @@ -23,12 +23,6 @@ */ #include <config.h> -#include "fm-desktop-mounting.h" - -#include "fm-cdrom-extensions.h" -#include "fm-desktop-icon-view.h" -#include "fm-icon-view.h" -#include "iso9660.h" #include <errno.h> #include <fcntl.h> @@ -38,16 +32,28 @@ #include <libgnome/gnome-i18n.h> #include <libgnomevfs/gnome-vfs.h> #include <mntent.h> +#include <libnautilus-extensions/nautilus-cdrom-extensions.h> #include <libnautilus-extensions/nautilus-directory-private.h> #include <libnautilus-extensions/nautilus-file-utilities.h> +#include <libnautilus-extensions/nautilus-gtk-extensions.h> +#include <libnautilus-extensions/nautilus-gtk-macros.h> +#include <libnautilus-extensions/nautilus-iso9660.h> #include <libnautilus-extensions/nautilus-link.h> +#include <libnautilus-extensions/nautilus-volume-monitor.h> + +#include <parser.h> +#include <stdlib.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/types.h> +#include <xmlmemory.h> + /* FIXME: Remove messages when this code is done. */ #define MESSAGE g_message +NautilusVolumeMonitor *global_volume_monitor = NULL; + const char * const state_names[] = { "ACTIVE", "INACTIVE", @@ -61,21 +67,102 @@ const char * const type_names[] = { "OTHER" }; +/* The NautilusVolumeMonitor signals. */ +enum { + VOLUME_MOUNTED, + LAST_SIGNAL +}; +static guint signals[LAST_SIGNAL]; + +static void nautilus_volume_monitor_initialize (NautilusVolumeMonitor *desktop_mounter); +static void nautilus_volume_monitor_initialize_class (NautilusVolumeMonitorClass *klass); +static void nautilus_volume_monitor_destroy (GtkObject *object); +static void remove_mount_link (DeviceInfo *device); +static void get_iso9660_volume_name (DeviceInfo *device); +static void get_ext2_volume_name (DeviceInfo *device); +static void get_floppy_volume_name (DeviceInfo *device); +static void mount_device_mount (NautilusVolumeMonitor *view, + DeviceInfo *device); +static gboolean mount_device_is_mounted (DeviceInfo *device); +static void mount_device_activate (NautilusVolumeMonitor *view, + DeviceInfo *device); +static void mount_device_deactivate (NautilusVolumeMonitor *monitor, + DeviceInfo *device); +static void mount_device_activate_floppy (NautilusVolumeMonitor *view, + DeviceInfo *device); +static gboolean mntent_is_removable_fs (struct mntent *ent); +static void free_device_info (DeviceInfo *device, + NautilusVolumeMonitor *monitor); + + +NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusVolumeMonitor, nautilus_volume_monitor, GTK_TYPE_OBJECT) + +static void +nautilus_volume_monitor_initialize (NautilusVolumeMonitor *monitor) +{ + /* Set up details */ + monitor->details = g_new0 (NautilusVolumeMonitorDetails, 1); + monitor->details->devices_by_fsname = g_hash_table_new (g_str_hash, g_str_equal); + monitor->details->devices = NULL; +} + +static void +nautilus_volume_monitor_initialize_class (NautilusVolumeMonitorClass *klass) +{ + GtkObjectClass *object_class; + + object_class = GTK_OBJECT_CLASS (klass); + + object_class->destroy = nautilus_volume_monitor_destroy; + + signals[VOLUME_MOUNTED] + = gtk_signal_new ("volume_mounted", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (NautilusVolumeMonitorClass, + volume_mounted), + nautilus_gtk_marshal_STRING__NONE, + GTK_TYPE_STRING, 0); +} + +static void +nautilus_volume_monitor_destroy (GtkObject *object) +{ + NautilusVolumeMonitor *monitor; + + monitor = NAUTILUS_VOLUME_MONITOR (object); + + /* Remove timer function */ + gtk_timeout_remove (monitor->details->mount_device_timer_id); + + /* Clean up other device info */ + g_list_foreach (monitor->details->devices, (GFunc)free_device_info, monitor); + + /* Remove timer function */ + gtk_timeout_remove (monitor->details->mount_device_timer_id); + + /* Clean up details */ + g_hash_table_destroy (monitor->details->devices_by_fsname); + g_list_free (monitor->details->devices); + g_free (monitor->details); + + NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object)); +} -static void remove_mount_link (DeviceInfo *device); -static void get_iso9660_volume_name (DeviceInfo *device); -static void get_ext2_volume_name (DeviceInfo *device); -static void get_floppy_volume_name (DeviceInfo *device); -static void mount_device_mount (FMDesktopIconView *view, - DeviceInfo *device); -static gboolean mount_device_is_mounted (DeviceInfo *device); -static void mount_device_activate (FMDesktopIconView *view, - DeviceInfo *device); -static void mount_device_deactivate (FMDesktopIconView *icon_view, - DeviceInfo *device); -static void mount_device_activate_floppy (FMDesktopIconView *view, - DeviceInfo *device); -static gboolean mntent_is_removable_fs (struct mntent *ent); +/* Return the global instance of the NautilusVolumeMonitor. Create one + * if we have not done so already + */ +NautilusVolumeMonitor * +nautilus_volume_monitor_get (void) +{ + if (global_volume_monitor == NULL) { + global_volume_monitor = NAUTILUS_VOLUME_MONITOR + (gtk_object_new (nautilus_volume_monitor_get_type(), + NULL)); + } + + return global_volume_monitor; +} static int floppy_sort (const char *name_1, const char *name_2) @@ -119,58 +206,8 @@ fm_desktop_get_removable_volume_list (void) return list; } -void -fm_desktop_mount_unmount_removable (GtkCheckMenuItem *item, FMDesktopIconView *icon_view) -{ - gboolean is_mounted, found_device; - char *mount_point; - char *argv[3]; - GList *element; - DeviceInfo *device; - int exec_err; - - is_mounted = FALSE; - found_device = FALSE; - device = NULL; - - /* Locate our mount point data */ - mount_point = gtk_object_get_data (GTK_OBJECT (item), "mount_point"); - if (mount_point != NULL) { - /* Locate DeviceInfo for mount point */ - for (element = icon_view->details->devices; element != NULL; element = element->next) { - device = element->data; - if (strcmp (mount_point, device->mount_path) == 0) { - found_device = TRUE; - break; - } - } - - /* Get mount state and then decide to mount/unmount the volume */ - if (found_device) { - is_mounted = fm_desktop_volume_is_mounted (mount_point); - argv[1] = mount_point; - argv[2] = NULL; - - if (is_mounted) { - /* Unount */ - argv[0] = "/bin/umount"; - exec_err = gnome_execute_async (g_get_home_dir(), 2, argv); - is_mounted = FALSE; - } else { - /* Mount */ - argv[0] = "/bin/mount"; - exec_err = gnome_execute_async (g_get_home_dir(), 2, argv); - is_mounted = TRUE; - } - } - } - - /* Set the check state of menu item even thought the user may not see it */ - gtk_check_menu_item_set_active (item, is_mounted); -} - gboolean -fm_desktop_volume_is_mounted (const char *mount_point) +nautilus_volume_monitor_volume_is_mounted (const char *mount_point) { FILE *fh; char line[PATH_MAX * 3]; @@ -201,7 +238,7 @@ mount_device_is_mounted (DeviceInfo *device) } static void -mount_device_cdrom_set_state (FMDesktopIconView *icon_view, DeviceInfo *device) +mount_device_cdrom_set_state (NautilusVolumeMonitor *monitor, DeviceInfo *device) { if (device->device_fd < 0) { device->device_fd = open (device->fsname, O_RDONLY|O_NONBLOCK); @@ -246,10 +283,10 @@ mount_device_cdrom_set_state (FMDesktopIconView *icon_view, DeviceInfo *device) static void -mount_device_floppy_set_state (FMDesktopIconView *icon_view, DeviceInfo *device) +mount_device_floppy_set_state (NautilusVolumeMonitor *monitor, DeviceInfo *device) { /* If the floppy is not in mtab, then we set it to empty */ - if (fm_desktop_volume_is_mounted (device->mount_path)) { + if (nautilus_volume_monitor_volume_is_mounted (device->mount_path)) { device->state = STATE_ACTIVE; } else { device->state = STATE_EMPTY; @@ -257,25 +294,25 @@ mount_device_floppy_set_state (FMDesktopIconView *icon_view, DeviceInfo *device) } static void -mount_device_ext2_set_state (FMDesktopIconView *icon_view, DeviceInfo *device) +mount_device_ext2_set_state (NautilusVolumeMonitor *monitor, DeviceInfo *device) { device->state = STATE_ACTIVE; } static void -mount_device_set_state (DeviceInfo *device, FMDesktopIconView *icon_view) +mount_device_set_state (DeviceInfo *device, NautilusVolumeMonitor *monitor) { switch (device->type) { case DEVICE_CDROM: - mount_device_cdrom_set_state (icon_view, device); + mount_device_cdrom_set_state (monitor, device); break; case DEVICE_FLOPPY: - mount_device_floppy_set_state (icon_view, device); + mount_device_floppy_set_state (monitor, device); break; case DEVICE_EXT2: - mount_device_ext2_set_state (icon_view, device); + mount_device_ext2_set_state (monitor, device); break; default: @@ -284,22 +321,19 @@ mount_device_set_state (DeviceInfo *device, FMDesktopIconView *icon_view) } static void -device_set_state_empty (DeviceInfo *device, FMDesktopIconView *icon_view) +device_set_state_empty (DeviceInfo *device, NautilusVolumeMonitor *monitor) { device->state = STATE_EMPTY; } static void -mount_device_mount (FMDesktopIconView *view, DeviceInfo *device) +mount_device_mount (NautilusVolumeMonitor *view, DeviceInfo *device) { char *target_uri, *desktop_path; const char *icon_name; - NautilusIconContainer *container; gboolean result; int index; - container = NAUTILUS_ICON_CONTAINER (GTK_BIN (view)->child); - desktop_path = nautilus_get_desktop_directory (); target_uri = nautilus_get_uri_from_local_path (device->mount_path); @@ -354,7 +388,7 @@ mount_device_mount (FMDesktopIconView *view, DeviceInfo *device) } static void -mount_device_activate_cdrom (FMDesktopIconView *icon_view, DeviceInfo *device) +mount_device_activate_cdrom (NautilusVolumeMonitor *monitor, DeviceInfo *device) { int disctype; @@ -375,7 +409,7 @@ mount_device_activate_cdrom (FMDesktopIconView *icon_view, DeviceInfo *device) case CDS_MIXED: /* Get volume name */ get_iso9660_volume_name (device); - mount_device_mount (icon_view, device); + mount_device_mount (monitor, device); break; default: @@ -390,7 +424,7 @@ mount_device_activate_cdrom (FMDesktopIconView *icon_view, DeviceInfo *device) } static void -mount_device_activate_floppy (FMDesktopIconView *view, DeviceInfo *device) +mount_device_activate_floppy (NautilusVolumeMonitor *view, DeviceInfo *device) { /* Get volume name */ get_floppy_volume_name (device); @@ -399,7 +433,7 @@ mount_device_activate_floppy (FMDesktopIconView *view, DeviceInfo *device) } static void -mount_device_activate_ext2 (FMDesktopIconView *view, DeviceInfo *device) +mount_device_activate_ext2 (NautilusVolumeMonitor *view, DeviceInfo *device) { /* Get volume name */ get_ext2_volume_name (device); @@ -407,28 +441,32 @@ mount_device_activate_ext2 (FMDesktopIconView *view, DeviceInfo *device) mount_device_mount (view, device); } -typedef void (* ChangeDeviceInfoFunction) (FMDesktopIconView *view, DeviceInfo *device); +typedef void (* ChangeDeviceInfoFunction) (NautilusVolumeMonitor *view, DeviceInfo *device); static void -mount_device_activate (FMDesktopIconView *view, DeviceInfo *device) +mount_device_activate (NautilusVolumeMonitor *monitor, DeviceInfo *device) { switch (device->type) { case DEVICE_CDROM: - mount_device_activate_cdrom (view, device); + mount_device_activate_cdrom (monitor, device); break; case DEVICE_FLOPPY: - mount_device_activate_floppy (view, device); + mount_device_activate_floppy (monitor, device); break; case DEVICE_EXT2: - mount_device_activate_ext2 (view, device); + mount_device_activate_ext2 (monitor, device); break; default: g_assert_not_reached (); break; } + + gtk_signal_emit (GTK_OBJECT (monitor), + signals[VOLUME_MOUNTED], + &device->mount_path); } @@ -453,7 +491,7 @@ eject_cdrom (DeviceInfo *device) } static void -mount_device_deactivate (FMDesktopIconView *icon_view, DeviceInfo *device) +mount_device_deactivate (NautilusVolumeMonitor *monitor, DeviceInfo *device) { GList dummy_list; @@ -477,7 +515,7 @@ mount_device_deactivate (FMDesktopIconView *icon_view, DeviceInfo *device) } static void -mount_device_do_nothing (FMDesktopIconView *icon_view, DeviceInfo *device) +mount_device_do_nothing (NautilusVolumeMonitor *monitor, DeviceInfo *device) { } @@ -494,18 +532,18 @@ mount_device_check_change (gpointer data, gpointer callback_data) }; DeviceInfo *device; - FMDesktopIconView *icon_view; + NautilusVolumeMonitor *monitor; DeviceState old_state; ChangeDeviceInfoFunction f; g_assert (data != NULL); device = data; - icon_view = FM_DESKTOP_ICON_VIEW (callback_data); + monitor = NAUTILUS_VOLUME_MONITOR (callback_data); old_state = device->state; - mount_device_set_state (device, icon_view); + mount_device_set_state (device, monitor); if (old_state != device->state) { f = state_transitions[device->state][old_state]; @@ -513,12 +551,12 @@ mount_device_check_change (gpointer data, gpointer callback_data) MESSAGE ("State on %s changed from %s to %s, running %p", device->fsname, state_names[old_state], state_names[device->state], f); - (* f) (icon_view, device); + (* f) (monitor, device); } } static void -mount_devices_update_is_mounted (FMDesktopIconView *icon_view) +mount_devices_update_is_mounted (NautilusVolumeMonitor *monitor) { FILE *fh; char line[PATH_MAX * 3], mntpoint[PATH_MAX], devname[PATH_MAX]; @@ -526,7 +564,7 @@ mount_devices_update_is_mounted (FMDesktopIconView *icon_view) DeviceInfo *device; /* Toggle mount state to off and then recheck in mtab. */ - for (element = icon_view->details->devices; element != NULL; element = element->next) { + for (element = monitor->details->devices; element != NULL; element = element->next) { device = element->data; device->is_mounted = FALSE; } @@ -539,7 +577,7 @@ mount_devices_update_is_mounted (FMDesktopIconView *icon_view) while (fgets (line, sizeof(line), fh)) { sscanf(line, "%s %s", devname, mntpoint); - device = g_hash_table_lookup (icon_view->details->devices_by_fsname, devname); + device = g_hash_table_lookup (monitor->details->devices_by_fsname, devname); if(device) { device->is_mounted = TRUE; @@ -550,13 +588,13 @@ mount_devices_update_is_mounted (FMDesktopIconView *icon_view) } static gint -mount_devices_check_status (FMDesktopIconView *icon_view) +mount_devices_check_status (NautilusVolumeMonitor *monitor) { - mount_devices_update_is_mounted (icon_view); + mount_devices_update_is_mounted (monitor); - g_list_foreach (icon_view->details->devices, + g_list_foreach (monitor->details->devices, mount_device_check_change, - icon_view); + monitor); return TRUE; } @@ -597,7 +635,7 @@ check_permissions (gchar *filename, int mode) } static gboolean -mount_device_floppy_add (FMDesktopIconView *icon_view, DeviceInfo *device) +mount_device_floppy_add (NautilusVolumeMonitor *monitor, DeviceInfo *device) { device->mount_type = g_strdup ("floppy"); device->type = DEVICE_FLOPPY; @@ -640,7 +678,7 @@ cdrom_ioctl_frenzy (int fd) static gboolean -mount_device_iso9660_add (FMDesktopIconView *icon_view, DeviceInfo *device) +mount_device_iso9660_add (NautilusVolumeMonitor *monitor, DeviceInfo *device) { device->device_fd = open (device->fsname, O_RDONLY|O_NONBLOCK); if(device->device_fd < 0) { @@ -665,12 +703,12 @@ mount_device_iso9660_add (FMDesktopIconView *icon_view, DeviceInfo *device) /* This is here because mtab lists devices by their symlink-followed names rather than what is listed in fstab. *sigh* */ static void -mount_device_add_aliases (FMDesktopIconView *icon_view, const char *alias, DeviceInfo *device) +mount_device_add_aliases (NautilusVolumeMonitor *monitor, const char *alias, DeviceInfo *device) { char buf[PATH_MAX]; int buflen; - g_hash_table_insert (icon_view->details->devices_by_fsname, (gpointer)alias, device); + g_hash_table_insert (monitor->details->devices_by_fsname, (gpointer)alias, device); buflen = readlink (alias, buf, sizeof(buf)); if(buflen < 1) { @@ -688,12 +726,12 @@ mount_device_add_aliases (FMDesktopIconView *icon_view, const char *alias, Devic strcpy(buf, buf2); } - mount_device_add_aliases (icon_view, g_strdup(buf), device); + mount_device_add_aliases (monitor, g_strdup(buf), device); } static void -add_mount_device (FMDesktopIconView *icon_view, struct mntent *ent) +add_mount_device (NautilusVolumeMonitor *monitor, struct mntent *ent) { DeviceInfo *newdev = NULL; gboolean mounted; @@ -710,9 +748,9 @@ add_mount_device (FMDesktopIconView *icon_view, struct mntent *ent) mounted = FALSE; if (strcmp (ent->mnt_type, MOUNT_TYPE_ISO9660) == 0) { - mounted = mount_device_iso9660_add (icon_view, newdev); + mounted = mount_device_iso9660_add (monitor, newdev); } else if (strncmp (ent->mnt_fsname, "/dev/fd", strlen("/dev/fd")) == 0) { - mounted = mount_device_floppy_add (icon_view, newdev); + mounted = mount_device_floppy_add (monitor, newdev); } else if (strcmp (ent->mnt_type, MOUNT_TYPE_EXT2) == 0) { mounted = mount_device_ext2_add (newdev); } else { @@ -721,8 +759,8 @@ add_mount_device (FMDesktopIconView *icon_view, struct mntent *ent) } if (mounted) { - icon_view->details->devices = g_list_append (icon_view->details->devices, newdev); - mount_device_add_aliases (icon_view, newdev->fsname, newdev); + monitor->details->devices = g_list_append (monitor->details->devices, newdev); + mount_device_add_aliases (monitor, newdev->fsname, newdev); MESSAGE ("Device %s came through (type %s)", newdev->fsname, type_names[newdev->type]); } else { close (newdev->device_fd); @@ -770,12 +808,12 @@ mntent_has_option(const char *optlist, const char *option) #endif void -fm_desktop_find_mount_devices (FMDesktopIconView *icon_view, const char *fstab_path) +nautilus_volume_monitor_find_mount_devices (NautilusVolumeMonitor *monitor) { FILE *mef; struct mntent *ent; - mef = setmntent (fstab_path, "r"); + mef = setmntent (_PATH_MNTTAB, "r"); g_return_if_fail (mef); while ((ent = getmntent (mef))) { @@ -794,20 +832,65 @@ fm_desktop_find_mount_devices (FMDesktopIconView *icon_view, const char *fstab_p } #endif /* Add it to our list of mount points */ - add_mount_device (icon_view, ent); + add_mount_device (monitor, ent); } endmntent (mef); - g_list_foreach (icon_view->details->devices, (GFunc) mount_device_set_state, icon_view); + g_list_foreach (monitor->details->devices, (GFunc) mount_device_set_state, monitor); /* Manually set state of all volumes to empty so we update */ - g_list_foreach (icon_view->details->devices, (GFunc) device_set_state_empty, icon_view); + g_list_foreach (monitor->details->devices, (GFunc) device_set_state_empty, monitor); /* Add a timer function to check for status change in mounted devices */ - icon_view->details->mount_device_timer_id = - gtk_timeout_add (CHECK_INTERVAL, (GtkFunction) mount_devices_check_status, icon_view); + monitor->details->mount_device_timer_id = + gtk_timeout_add (CHECK_INTERVAL, (GtkFunction) mount_devices_check_status, monitor); +} + + +gboolean +nautilus_volume_monitor_mount_unmount_removable (NautilusVolumeMonitor *monitor, const char *mount_point) +{ + gboolean is_mounted, found_device; + char *argv[3]; + GList *element; + DeviceInfo *device; + int exec_err; + + is_mounted = FALSE; + found_device = FALSE; + device = NULL; + + /* Locate DeviceInfo for mount point */ + for (element = monitor->details->devices; element != NULL; element = element->next) { + device = element->data; + if (strcmp (mount_point, device->mount_path) == 0) { + found_device = TRUE; + break; + } + } + + /* Get mount state and then decide to mount/unmount the volume */ + if (found_device) { + is_mounted = nautilus_volume_monitor_volume_is_mounted (mount_point); + argv[1] = (char *)mount_point; + argv[2] = NULL; + + if (is_mounted) { + /* Unount */ + argv[0] = "/bin/umount"; + exec_err = gnome_execute_async (g_get_home_dir(), 2, argv); + is_mounted = FALSE; + } else { + /* Mount */ + argv[0] = "/bin/mount"; + exec_err = gnome_execute_async (g_get_home_dir(), 2, argv); + is_mounted = TRUE; + } + } + + return is_mounted; } @@ -827,16 +910,8 @@ remove_mount_link (DeviceInfo *device) } } - -void -fm_desktop_remove_mount_links (DeviceInfo *device, FMDesktopIconView *icon_view) -{ - remove_mount_link (device); -} - - -void -fm_desktop_free_device_info (DeviceInfo *device, FMDesktopIconView *icon_view) +static void +free_device_info (DeviceInfo *device, NautilusVolumeMonitor *monitor) { if (device->device_fd != -1) { @@ -900,39 +975,3 @@ get_floppy_volume_name (DeviceInfo *device) { device->volume_name = g_strdup ("Floppy"); } - -/* fm_dekstop_place_home_directory - * - * Add an icon representing the user's home directory on the desktop. - * Create if necessary - */ -void -fm_desktop_place_home_directory (FMDesktopIconView *icon_view) -{ - char *desktop_path, *home_link_name, *home_link_path, *home_link_uri, *home_dir_uri; - GnomeVFSResult result; - GnomeVFSFileInfo info; - - desktop_path = nautilus_get_desktop_directory (); - home_link_name = g_strdup_printf ("%s's Home", g_get_user_name ()); - home_link_path = nautilus_make_path (desktop_path, home_link_name); - home_link_uri = nautilus_get_uri_from_local_path (home_link_path); - - result = gnome_vfs_get_file_info (home_link_uri, &info, 0); - if (result != GNOME_VFS_OK) { - /* FIXME: Maybe we should only create if the error was "not found". */ - /* There was no link file. Create it and add it to the desktop view */ - home_dir_uri = nautilus_get_uri_from_local_path (g_get_home_dir ()); - result = nautilus_link_create (desktop_path, home_link_name, "temp-home.png", home_dir_uri); - g_free (home_dir_uri); - if (result != GNOME_VFS_OK) { - /* FIXME: Is a message to the console acceptable here? */ - MESSAGE ("Unable to create home link: %s", gnome_vfs_result_to_string (result)); - } - } - - g_free (home_link_uri); - g_free (home_link_path); - g_free (home_link_name); - g_free (desktop_path); -} diff --git a/libnautilus-extensions/nautilus-volume-monitor.h b/libnautilus-extensions/nautilus-volume-monitor.h new file mode 100644 index 000000000..3fb9ce9ef --- /dev/null +++ b/libnautilus-extensions/nautilus-volume-monitor.h @@ -0,0 +1,105 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* nautilus-volume-monitor.h - interface for desktop mounting functions. + + Copyright (C) 2000 Eazel, Inc. + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Authors: Gene Z. Ragan <gzr@eazel.com> +*/ + +#ifndef NAUTILUS_VOLUME_MONITOR_H +#define NAUTILUS_VOLUME_MONITOR_H + +#include <glib.h> +#include <gtk/gtk.h> +#include "nautilus-icon-container.h" + +typedef struct NautilusVolumeMonitor NautilusVolumeMonitor; +typedef struct NautilusVolumeMonitorClass NautilusVolumeMonitorClass; +typedef struct NautilusVolumeMonitorDetails NautilusVolumeMonitorDetails; + +#define NAUTILUS_TYPE_VOLUME_MONITOR (nautilus_volume_monitor_get_type()) +#define NAUTILUS_VOLUME_MONITOR(obj) (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_VOLUME_MONITOR, NautilusVolumeMonitor)) +#define NAUTILUS_VOLUME_MONITOR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_VOLUME_MONITOR, NautilusVolumeMonitorClass)) +#define IS_NAUTILUS_VOLUME_MONITOR(obj) (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_VOLUME_MONITOR)) + +struct NautilusVolumeMonitor { + GtkObject parent; + NautilusVolumeMonitorDetails *details; +}; + +struct NautilusVolumeMonitorClass { + GtkObjectClass parent_class; + + /* Signals */ + char * (* volume_mounted) (NautilusVolumeMonitor *monitor); +}; + +struct NautilusVolumeMonitorDetails +{ + GHashTable *devices_by_fsname; + GList *devices; + guint mount_device_timer_id; +}; + + +#define MOUNT_TYPE_ISO9660 "iso9660" +#define MOUNT_TYPE_EXT2 "ext2" +#define MOUNT_OPTIONS_USER "user" +#define MOUNT_OPTIONS_OWNER "owner" + +#define CHECK_INTERVAL 2000 + +typedef enum { + STATE_ACTIVE = 0, + STATE_INACTIVE, + STATE_EMPTY, + STATE_LAST, +} DeviceState; + +typedef enum { + DEVICE_CDROM, + DEVICE_FLOPPY, + DEVICE_EXT2, + DEVICE_OTHER +} DeviceType; + +typedef struct { + DeviceType type; + DeviceState state; + int device_fd; + + char *fsname; + char *mount_path; + char *mount_type; + char *volume_name; + char *link_uri; + + gboolean is_mounted; + gboolean did_mount; +} DeviceInfo; + +GtkType nautilus_volume_monitor_get_type (void); +NautilusVolumeMonitor *nautilus_volume_monitor_get (void); +GList *fm_desktop_get_removable_volume_list (void); +gboolean nautilus_volume_monitor_volume_is_mounted (const char *mount_point); +void nautilus_volume_monitor_find_mount_devices (NautilusVolumeMonitor *icon_view); +gboolean nautilus_volume_monitor_mount_unmount_removable (NautilusVolumeMonitor *monitor, + const char *mount_point); + +#endif
\ No newline at end of file diff --git a/libnautilus-private/Makefile.am b/libnautilus-private/Makefile.am index 003aeb4e6..d2843e72f 100644 --- a/libnautilus-private/Makefile.am +++ b/libnautilus-private/Makefile.am @@ -103,6 +103,7 @@ libnautilus_extensions_la_SOURCES = \ nautilus-undo-signal-handlers.c \ nautilus-user-level-manager.c \ nautilus-view-identifier.c \ + nautilus-volume-monitor.c \ nautilus-xml-extensions.c \ $(NULL) diff --git a/libnautilus-private/nautilus-cdrom-extensions.h b/libnautilus-private/nautilus-cdrom-extensions.h new file mode 100644 index 000000000..17770e5e9 --- /dev/null +++ b/libnautilus-private/nautilus-cdrom-extensions.h @@ -0,0 +1,222 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* fm-cdrom-extension.c - CDROM handliong constants copied from <linux/cdrom.h>. + + Copyright (C) 2000 Eazel, Inc. + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Authors: Gene Z. Ragan <gzr@eazel.com> +*/ + +#ifndef FM_CDROM_EXTENSIONS_H +#define FM_CDROM_EXTENSIONS_H + +/******************************************************* + * The CD-ROM IOCTL commands -- these should be supported by + * all the various cdrom drivers. For the CD-ROM ioctls, we + * will commandeer byte 0x53, or 'S'. + *******************************************************/ +#define CDROMPAUSE 0x5301 /* Pause Audio Operation */ +#define CDROMRESUME 0x5302 /* Resume paused Audio Operation */ +#define CDROMPLAYMSF 0x5303 /* Play Audio MSF (struct cdrom_msf) */ +#define CDROMPLAYTRKIND 0x5304 /* Play Audio Track/index + (struct cdrom_ti) */ +#define CDROMREADTOCHDR 0x5305 /* Read TOC header + (struct cdrom_tochdr) */ +#define CDROMREADTOCENTRY 0x5306 /* Read TOC entry + (struct cdrom_tocentry) */ +#define CDROMSTOP 0x5307 /* Stop the cdrom drive */ +#define CDROMSTART 0x5308 /* Start the cdrom drive */ +#define CDROMEJECT 0x5309 /* Ejects the cdrom media */ +#define CDROMVOLCTRL 0x530a /* Control output volume + (struct cdrom_volctrl) */ +#define CDROMSUBCHNL 0x530b /* Read subchannel data + (struct cdrom_subchnl) */ +#define CDROMREADMODE2 0x530c /* Read CDROM mode 2 data (2336 Bytes) + (struct cdrom_read) */ +#define CDROMREADMODE1 0x530d /* Read CDROM mode 1 data (2048 Bytes) + (struct cdrom_read) */ +#define CDROMREADAUDIO 0x530e /* (struct cdrom_read_audio) */ +#define CDROMEJECT_SW 0x530f /* enable(1)/disable(0) auto-ejecting */ +#define CDROMMULTISESSION 0x5310 /* Obtain the start-of-last-session + address of multi session disks + (struct cdrom_multisession) */ +#define CDROM_GET_MCN 0x5311 /* Obtain the "Universal Product Code" + if available (struct cdrom_mcn) */ +#define CDROM_GET_UPC CDROM_GET_MCN /* This one is depricated, + but here anyway for compatability */ +#define CDROMRESET 0x5312 /* hard-reset the drive */ +#define CDROMVOLREAD 0x5313 /* Get the drive's volume setting + (struct cdrom_volctrl) */ +#define CDROMREADRAW 0x5314 /* read data in raw mode (2352 Bytes) + (struct cdrom_read) */ +/* + * These ioctls are used only used in aztcd.c and optcd.c + */ +#define CDROMREADCOOKED 0x5315 /* read data in cooked mode */ +#define CDROMSEEK 0x5316 /* seek msf address */ + +/* + * This ioctl is only used by the scsi-cd driver. + It is for playing audio in logical block addressing mode. + */ +#define CDROMPLAYBLK 0x5317 /* (struct cdrom_blk) */ + +/* + * These ioctls are only used in optcd.c + */ +#define CDROMREADALL 0x5318 /* read all 2646 bytes */ + +/* + * These ioctls are (now) only in ide-cd.c for controlling + * drive spindown time. They should be implemented in the + * Uniform driver, via generic packet commands, GPCMD_MODE_SELECT_10, + * GPCMD_MODE_SENSE_10 and the GPMODE_POWER_PAGE... + * -Erik + */ +#define CDROMGETSPINDOWN 0x531d +#define CDROMSETSPINDOWN 0x531e + +/* + * These ioctls are implemented through the uniform CD-ROM driver + * They _will_ be adopted by all CD-ROM drivers, when all the CD-ROM + * drivers are eventually ported to the uniform CD-ROM driver interface. + */ +#define CDROMCLOSETRAY 0x5319 /* pendant of CDROMEJECT */ +#define CDROM_SET_OPTIONS 0x5320 /* Set behavior options */ +#define CDROM_CLEAR_OPTIONS 0x5321 /* Clear behavior options */ +#define CDROM_SELECT_SPEED 0x5322 /* Set the CD-ROM speed */ +#define CDROM_SELECT_DISC 0x5323 /* Select disc (for juke-boxes) */ +#define CDROM_MEDIA_CHANGED 0x5325 /* Check is media changed */ +#define CDROM_DRIVE_STATUS 0x5326 /* Get tray position, etc. */ +#define CDROM_DISC_STATUS 0x5327 /* Get disc type, etc. */ +#define CDROM_CHANGER_NSLOTS 0x5328 /* Get number of slots */ +#define CDROM_LOCKDOOR 0x5329 /* lock or unlock door */ +#define CDROM_DEBUG 0x5330 /* Turn debug messages on/off */ +#define CDROM_GET_CAPABILITY 0x5331 /* get capabilities */ + +/* This ioctl is only used by sbpcd at the moment */ +#define CDROMAUDIOBUFSIZ 0x5382 /* set the audio buffer size */ + +/* DVD-ROM Specific ioctls */ +#define DVD_READ_STRUCT 0x5390 /* Read structure */ +#define DVD_WRITE_STRUCT 0x5391 /* Write structure */ +#define DVD_AUTH 0x5392 /* Authentication */ + +#define CDROM_SEND_PACKET 0x5393 /* send a packet to the drive */ +#define CDROM_NEXT_WRITABLE 0x5394 /* get next writable block */ +#define CDROM_LAST_WRITTEN 0x5395 /* get last block written on disc */ + +/* Some generally useful CD-ROM information -- mostly based on the above */ +#define CD_MINS 74 /* max. minutes per CD, not really a limit */ +#define CD_SECS 60 /* seconds per minute */ +#define CD_FRAMES 75 /* frames per second */ +#define CD_SYNC_SIZE 12 /* 12 sync bytes per raw data frame */ +#define CD_MSF_OFFSET 150 /* MSF numbering offset of first frame */ +#define CD_CHUNK_SIZE 24 /* lowest-level "data bytes piece" */ +#define CD_NUM_OF_CHUNKS 98 /* chunks per frame */ +#define CD_FRAMESIZE_SUB 96 /* subchannel data "frame" size */ +#define CD_HEAD_SIZE 4 /* header (address) bytes per raw data frame */ +#define CD_SUBHEAD_SIZE 8 /* subheader bytes per raw XA data frame */ +#define CD_EDC_SIZE 4 /* bytes EDC per most raw data frame types */ +#define CD_ZERO_SIZE 8 /* bytes zero per yellow book mode 1 frame */ +#define CD_ECC_SIZE 276 /* bytes ECC per most raw data frame types */ +#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */ +#define CD_FRAMESIZE_RAW 2352 /* bytes per frame, "raw" mode */ +#define CD_FRAMESIZE_RAWER 2646 /* The maximum possible returned bytes */ +/* most drives don't deliver everything: */ +#define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /*2340*/ +#define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /*2336*/ + +#define CD_XA_HEAD (CD_HEAD_SIZE+CD_SUBHEAD_SIZE) /* "before data" part of raw XA frame */ +#define CD_XA_TAIL (CD_EDC_SIZE+CD_ECC_SIZE) /* "after data" part of raw XA frame */ +#define CD_XA_SYNC_HEAD (CD_SYNC_SIZE+CD_XA_HEAD) /* sync bytes + header of XA frame */ + +/* CD-ROM address types (cdrom_tocentry.cdte_format) */ +#define CDROM_LBA 0x01 /* "logical block": first frame is #0 */ +#define CDROM_MSF 0x02 /* "minute-second-frame": binary, not bcd here! */ + +/* bit to tell whether track is data or audio (cdrom_tocentry.cdte_ctrl) */ +#define CDROM_DATA_TRACK 0x04 + +/* The leadout track is always 0xAA, regardless of # of tracks on disc */ +#define CDROM_LEADOUT 0xAA + +/* audio states (from SCSI-2, but seen with other drives, too) */ +#define CDROM_AUDIO_INVALID 0x00 /* audio status not supported */ +#define CDROM_AUDIO_PLAY 0x11 /* audio play operation in progress */ +#define CDROM_AUDIO_PAUSED 0x12 /* audio play operation paused */ +#define CDROM_AUDIO_COMPLETED 0x13 /* audio play successfully completed */ +#define CDROM_AUDIO_ERROR 0x14 /* audio play stopped due to error */ +#define CDROM_AUDIO_NO_STATUS 0x15 /* no current audio status to return */ + +/* capability flags used with the uniform CD-ROM driver */ +#define CDC_CLOSE_TRAY 0x1 /* caddy systems _can't_ close */ +#define CDC_OPEN_TRAY 0x2 /* but _can_ eject. */ +#define CDC_LOCK 0x4 /* disable manual eject */ +#define CDC_SELECT_SPEED 0x8 /* programmable speed */ +#define CDC_SELECT_DISC 0x10 /* select disc from juke-box */ +#define CDC_MULTI_SESSION 0x20 /* read sessions>1 */ +#define CDC_MCN 0x40 /* Medium Catalog Number */ +#define CDC_MEDIA_CHANGED 0x80 /* media changed */ +#define CDC_PLAY_AUDIO 0x100 /* audio functions */ +#define CDC_RESET 0x200 /* hard reset device */ +#define CDC_IOCTLS 0x400 /* driver has non-standard ioctls */ +#define CDC_DRIVE_STATUS 0x800 /* driver implements drive status */ +#define CDC_GENERIC_PACKET 0x1000 /* driver implements generic packets */ +#define CDC_CD_R 0x2000 /* drive is a CD-R */ +#define CDC_CD_RW 0x4000 /* drive is a CD-RW */ +#define CDC_DVD 0x8000 /* drive is a DVD */ +#define CDC_DVD_R 0x10000 /* drive can write DVD-R */ +#define CDC_DVD_RAM 0x20000 /* drive can write DVD-RAM */ + +/* drive status possibilities returned by CDROM_DRIVE_STATUS ioctl */ +#define CDS_NO_INFO 0 /* if not implemented */ +#define CDS_NO_DISC 1 +#define CDS_TRAY_OPEN 2 +#define CDS_DRIVE_NOT_READY 3 +#define CDS_DISC_OK 4 + +/* return values for the CDROM_DISC_STATUS ioctl */ +/* can also return CDS_NO_[INFO|DISC], from above */ +#define CDS_AUDIO 100 +#define CDS_DATA_1 101 +#define CDS_DATA_2 102 +#define CDS_XA_2_1 103 +#define CDS_XA_2_2 104 +#define CDS_MIXED 105 + +/* User-configurable behavior options for the uniform CD-ROM driver */ +#define CDO_AUTO_CLOSE 0x1 /* close tray on first open() */ +#define CDO_AUTO_EJECT 0x2 /* open tray on last release() */ +#define CDO_USE_FFLAGS 0x4 /* use O_NONBLOCK information on open */ +#define CDO_LOCK 0x8 /* lock tray on open files */ +#define CDO_CHECK_TYPE 0x10 /* check type on open for data */ + +/* Special codes used when specifying changer slots. */ +#define CDSL_NONE ((int) (~0U>>1)-1) +#define CDSL_CURRENT ((int) (~0U>>1)) + +/* For partition based multisession access. IDE can handle 64 partitions + * per drive - SCSI CD-ROM's use minors to differentiate between the + * various drives, so we can't do multisessions the same way there. + * Use the -o session=x option to mount on them. + */ +#define CD_PART_MAX 64 +#define CD_PART_MASK (CD_PART_MAX - 1) + +#endif /* FM_CDROM_EXTENSIONS_H */ diff --git a/libnautilus-private/nautilus-iso9660.h b/libnautilus-private/nautilus-iso9660.h new file mode 100644 index 000000000..ad68b15fa --- /dev/null +++ b/libnautilus-private/nautilus-iso9660.h @@ -0,0 +1,106 @@ +/* + * Header file iso9660.h - assorted structure definitions and typecasts. + * specific to iso9660 filesystem. + + Written by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef _ISOFS_FS_H +#define _ISOFS_FS_H + +/* + * The isofs filesystem constants/structures + */ + +#define ISODCL(from, to) (to - from + 1) + +struct iso_volume_descriptor { + char type[ISODCL(1,1)]; /* 711 */ + char id[ISODCL(2,6)]; + char version[ISODCL(7,7)]; + char data[ISODCL(8,2048)]; +}; + +/* volume descriptor types */ +#define ISO_VD_PRIMARY 1 +#define ISO_VD_END 255 + +#define ISO_STANDARD_ID "CD001" + +struct iso_primary_descriptor { + char type [ISODCL ( 1, 1)]; /* 711 */ + char id [ISODCL ( 2, 6)]; + char version [ISODCL ( 7, 7)]; /* 711 */ + char unused1 [ISODCL ( 8, 8)]; + char system_id [ISODCL ( 9, 40)]; /* achars */ + char volume_id [ISODCL ( 41, 72)]; /* dchars */ + char unused2 [ISODCL ( 73, 80)]; + char volume_space_size [ISODCL ( 81, 88)]; /* 733 */ + char unused3 [ISODCL ( 89, 120)]; + char volume_set_size [ISODCL (121, 124)]; /* 723 */ + char volume_sequence_number [ISODCL (125, 128)]; /* 723 */ + char logical_block_size [ISODCL (129, 132)]; /* 723 */ + char path_table_size [ISODCL (133, 140)]; /* 733 */ + char type_l_path_table [ISODCL (141, 144)]; /* 731 */ + char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */ + char type_m_path_table [ISODCL (149, 152)]; /* 732 */ + char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */ + char root_directory_record [ISODCL (157, 190)]; /* 9.1 */ + char volume_set_id [ISODCL (191, 318)]; /* dchars */ + char publisher_id [ISODCL (319, 446)]; /* achars */ + char preparer_id [ISODCL (447, 574)]; /* achars */ + char application_id [ISODCL (575, 702)]; /* achars */ + char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */ + char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */ + char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */ + char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */ + char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */ + char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */ + char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */ + char file_structure_version [ISODCL (882, 882)]; /* 711 */ + char unused4 [ISODCL (883, 883)]; + char application_data [ISODCL (884, 1395)]; + char unused5 [ISODCL (1396, 2048)]; +}; + +/* We use this to help us look up the parent inode numbers. */ + +struct iso_path_table{ + unsigned char name_len[2]; /* 721 */ + char extent[4]; /* 731 */ + char parent[2]; /* 721 */ + char name[1]; +}; + +struct iso_directory_record { + unsigned char length [ISODCL (1, 1)]; /* 711 */ + char ext_attr_length [ISODCL (2, 2)]; /* 711 */ + char extent [ISODCL (3, 10)]; /* 733 */ + char size [ISODCL (11, 18)]; /* 733 */ + char date [ISODCL (19, 25)]; /* 7 by 711 */ + char flags [ISODCL (26, 26)]; + char file_unit_size [ISODCL (27, 27)]; /* 711 */ + char interleave [ISODCL (28, 28)]; /* 711 */ + char volume_sequence_number [ISODCL (29, 32)]; /* 723 */ + unsigned char name_len [ISODCL (33, 33)]; /* 711 */ + char name [34]; /* Not really, but we need something here */ +}; +#endif + + + diff --git a/libnautilus-private/nautilus-volume-monitor.c b/libnautilus-private/nautilus-volume-monitor.c new file mode 100644 index 000000000..052823f5b --- /dev/null +++ b/libnautilus-private/nautilus-volume-monitor.c @@ -0,0 +1,977 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* nautilus-volume-monitor.c - Desktop volume mounting routines. + + Copyright (C) 2000 Eazel, Inc. + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Authors: Gene Z. Ragan <gzr@eazel.com> +*/ + +#include <config.h> + +#include <errno.h> +#include <fcntl.h> +#include <fstab.h> +#include <glib.h> +#include <gnome.h> +#include <libgnome/gnome-i18n.h> +#include <libgnomevfs/gnome-vfs.h> +#include <mntent.h> +#include <libnautilus-extensions/nautilus-cdrom-extensions.h> +#include <libnautilus-extensions/nautilus-directory-private.h> +#include <libnautilus-extensions/nautilus-file-utilities.h> +#include <libnautilus-extensions/nautilus-gtk-extensions.h> +#include <libnautilus-extensions/nautilus-gtk-macros.h> +#include <libnautilus-extensions/nautilus-iso9660.h> +#include <libnautilus-extensions/nautilus-link.h> +#include <libnautilus-extensions/nautilus-volume-monitor.h> + +#include <parser.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <xmlmemory.h> + + +/* FIXME: Remove messages when this code is done. */ +#define MESSAGE g_message + +NautilusVolumeMonitor *global_volume_monitor = NULL; + +const char * const state_names[] = { + "ACTIVE", + "INACTIVE", + "EMPTY" +}; + +const char * const type_names[] = { + "CDROM", + "FLOPPY", + "LOCAL_DISK", + "OTHER" +}; + +/* The NautilusVolumeMonitor signals. */ +enum { + VOLUME_MOUNTED, + LAST_SIGNAL +}; +static guint signals[LAST_SIGNAL]; + +static void nautilus_volume_monitor_initialize (NautilusVolumeMonitor *desktop_mounter); +static void nautilus_volume_monitor_initialize_class (NautilusVolumeMonitorClass *klass); +static void nautilus_volume_monitor_destroy (GtkObject *object); +static void remove_mount_link (DeviceInfo *device); +static void get_iso9660_volume_name (DeviceInfo *device); +static void get_ext2_volume_name (DeviceInfo *device); +static void get_floppy_volume_name (DeviceInfo *device); +static void mount_device_mount (NautilusVolumeMonitor *view, + DeviceInfo *device); +static gboolean mount_device_is_mounted (DeviceInfo *device); +static void mount_device_activate (NautilusVolumeMonitor *view, + DeviceInfo *device); +static void mount_device_deactivate (NautilusVolumeMonitor *monitor, + DeviceInfo *device); +static void mount_device_activate_floppy (NautilusVolumeMonitor *view, + DeviceInfo *device); +static gboolean mntent_is_removable_fs (struct mntent *ent); +static void free_device_info (DeviceInfo *device, + NautilusVolumeMonitor *monitor); + + +NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusVolumeMonitor, nautilus_volume_monitor, GTK_TYPE_OBJECT) + +static void +nautilus_volume_monitor_initialize (NautilusVolumeMonitor *monitor) +{ + /* Set up details */ + monitor->details = g_new0 (NautilusVolumeMonitorDetails, 1); + monitor->details->devices_by_fsname = g_hash_table_new (g_str_hash, g_str_equal); + monitor->details->devices = NULL; +} + +static void +nautilus_volume_monitor_initialize_class (NautilusVolumeMonitorClass *klass) +{ + GtkObjectClass *object_class; + + object_class = GTK_OBJECT_CLASS (klass); + + object_class->destroy = nautilus_volume_monitor_destroy; + + signals[VOLUME_MOUNTED] + = gtk_signal_new ("volume_mounted", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (NautilusVolumeMonitorClass, + volume_mounted), + nautilus_gtk_marshal_STRING__NONE, + GTK_TYPE_STRING, 0); +} + +static void +nautilus_volume_monitor_destroy (GtkObject *object) +{ + NautilusVolumeMonitor *monitor; + + monitor = NAUTILUS_VOLUME_MONITOR (object); + + /* Remove timer function */ + gtk_timeout_remove (monitor->details->mount_device_timer_id); + + /* Clean up other device info */ + g_list_foreach (monitor->details->devices, (GFunc)free_device_info, monitor); + + /* Remove timer function */ + gtk_timeout_remove (monitor->details->mount_device_timer_id); + + /* Clean up details */ + g_hash_table_destroy (monitor->details->devices_by_fsname); + g_list_free (monitor->details->devices); + g_free (monitor->details); + + NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object)); +} + +/* Return the global instance of the NautilusVolumeMonitor. Create one + * if we have not done so already + */ +NautilusVolumeMonitor * +nautilus_volume_monitor_get (void) +{ + if (global_volume_monitor == NULL) { + global_volume_monitor = NAUTILUS_VOLUME_MONITOR + (gtk_object_new (nautilus_volume_monitor_get_type(), + NULL)); + } + + return global_volume_monitor; +} + +static int +floppy_sort (const char *name_1, const char *name_2) +{ + /* If both are floppies, we don't care yet */ + if ((strncmp (name_1, "/mnt/fd", strlen("/mnt/fd")) == 0) && + (strncmp (name_2, "/mnt/fd", strlen("/mnt/fd")) == 0)) { + return 0; + } + + if (strncmp (name_1, "/mnt/fd", strlen("/mnt/fd")) != 0) { + return 1; + } + + return -1; +} + +GList * +fm_desktop_get_removable_volume_list (void) +{ + GList *list; + FILE *mef; + struct mntent *ent; + + list = NULL; + + mef = setmntent (_PATH_FSTAB, "r"); + g_return_val_if_fail (mef, NULL); + + while ((ent = getmntent (mef))) { + if (mntent_is_removable_fs (ent)) { + list = g_list_append (list, g_strdup (ent->mnt_dir)); + continue; + } + } + endmntent (mef); + + /* Move all floppy mounts to top of list */ + list = g_list_sort (list, (GCompareFunc) floppy_sort); + + return list; +} + +gboolean +nautilus_volume_monitor_volume_is_mounted (const char *mount_point) +{ + FILE *fh; + char line[PATH_MAX * 3]; + char mntpoint[PATH_MAX], devname[PATH_MAX]; + + /* Open mtab */ + fh = fopen (_PATH_MOUNTED, "r"); + if (!fh) { + return FALSE; + } + + while (fgets (line, sizeof(line), fh)) { + sscanf(line, "%s %s", devname, mntpoint); + if (strcmp (mntpoint, mount_point) == 0) { + fclose (fh); + return TRUE; + } + } + + fclose (fh); + return FALSE; +} + +static gboolean +mount_device_is_mounted (DeviceInfo *device) +{ + return device->is_mounted; +} + +static void +mount_device_cdrom_set_state (NautilusVolumeMonitor *monitor, DeviceInfo *device) +{ + if (device->device_fd < 0) { + device->device_fd = open (device->fsname, O_RDONLY|O_NONBLOCK); + } + + if (ioctl (device->device_fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) == CDS_DISC_OK) { + int disctype; + + disctype = ioctl (device->device_fd, CDROM_DISC_STATUS, CDSL_CURRENT); + switch (disctype) { + case CDS_AUDIO: + /* It's pretty hard to know whether it is actually in use */ + device->state = STATE_INACTIVE; + break; + + case CDS_DATA_1: + case CDS_DATA_2: + case CDS_XA_2_1: + case CDS_XA_2_2: + case CDS_MIXED: + /* Check if it is mounted */ + if (mount_device_is_mounted (device)) { + device->state = STATE_ACTIVE; + } else { + device->state = STATE_EMPTY; + } + break; + + default: + device->state = STATE_EMPTY; + break; + } + } else { + device->state = STATE_EMPTY; + } + + if(device->device_fd >= 0) { + close (device->device_fd); + device->device_fd = -1; + } +} + + +static void +mount_device_floppy_set_state (NautilusVolumeMonitor *monitor, DeviceInfo *device) +{ + /* If the floppy is not in mtab, then we set it to empty */ + if (nautilus_volume_monitor_volume_is_mounted (device->mount_path)) { + device->state = STATE_ACTIVE; + } else { + device->state = STATE_EMPTY; + } +} + +static void +mount_device_ext2_set_state (NautilusVolumeMonitor *monitor, DeviceInfo *device) +{ + device->state = STATE_ACTIVE; +} + +static void +mount_device_set_state (DeviceInfo *device, NautilusVolumeMonitor *monitor) +{ + switch (device->type) { + case DEVICE_CDROM: + mount_device_cdrom_set_state (monitor, device); + break; + + case DEVICE_FLOPPY: + mount_device_floppy_set_state (monitor, device); + break; + + case DEVICE_EXT2: + mount_device_ext2_set_state (monitor, device); + break; + + default: + break; + } +} + +static void +device_set_state_empty (DeviceInfo *device, NautilusVolumeMonitor *monitor) +{ + device->state = STATE_EMPTY; +} + +static void +mount_device_mount (NautilusVolumeMonitor *view, DeviceInfo *device) +{ + char *target_uri, *desktop_path; + const char *icon_name; + gboolean result; + int index; + + desktop_path = nautilus_get_desktop_directory (); + target_uri = nautilus_get_uri_from_local_path (device->mount_path); + + /* Make volume name link "nice" */ + + /* Strip whitespace from the end of the name. */ + for (index = strlen (device->volume_name) - 1; index > 0; index--) { + if (device->volume_name [index] != ' ') { + break; + } + device->volume_name [index] = '\0'; + } + + /* The volume name may have '/' characters. We need to convert + * them to something legal. + */ + for (index = 0; ; index++) { + if (device->volume_name [index] == '\0') { + break; + } + if (device->volume_name [index] == '/') { + device->volume_name [index] = '-'; + } + } + + /* Clean up old link, This should have been done earlier, but + * we double check to be sure. + */ + remove_mount_link (device); + + /* Get icon type */ + if (strcmp (device->mount_type, "cdrom") == 0) { + icon_name = "i-cdrom.png"; + } else if (strcmp (device->mount_type, "floppy") == 0) { + icon_name = "i-floppy.png"; + } else { + icon_name = "i-blockdev.png"; + } + + /* Create link */ + result = nautilus_link_create (desktop_path, device->volume_name, icon_name, target_uri); + if (result) { + device->link_uri = nautilus_make_path (desktop_path, device->volume_name); + } else { + MESSAGE ("Unable to create mount link"); + } + + g_free (desktop_path); + g_free (target_uri); + + device->did_mount = TRUE; +} + +static void +mount_device_activate_cdrom (NautilusVolumeMonitor *monitor, DeviceInfo *device) +{ + int disctype; + + if (device->device_fd < 0) { + device->device_fd = open (device->fsname, O_RDONLY|O_NONBLOCK); + } + + disctype = ioctl (device->device_fd, CDROM_DISC_STATUS, CDSL_CURRENT); + switch (disctype) { + case CDS_AUDIO: + /* Should we run a CD player here? */ + break; + + case CDS_DATA_1: + case CDS_DATA_2: + case CDS_XA_2_1: + case CDS_XA_2_2: + case CDS_MIXED: + /* Get volume name */ + get_iso9660_volume_name (device); + mount_device_mount (monitor, device); + break; + + default: + MESSAGE ("Unknown CDROM type"); + break; + } + + if (device->device_fd >= 0) { + close (device->device_fd); + device->device_fd = -1; + } +} + +static void +mount_device_activate_floppy (NautilusVolumeMonitor *view, DeviceInfo *device) +{ + /* Get volume name */ + get_floppy_volume_name (device); + + mount_device_mount (view, device); +} + +static void +mount_device_activate_ext2 (NautilusVolumeMonitor *view, DeviceInfo *device) +{ + /* Get volume name */ + get_ext2_volume_name (device); + + mount_device_mount (view, device); +} + +typedef void (* ChangeDeviceInfoFunction) (NautilusVolumeMonitor *view, DeviceInfo *device); + +static void +mount_device_activate (NautilusVolumeMonitor *monitor, DeviceInfo *device) +{ + switch (device->type) { + case DEVICE_CDROM: + mount_device_activate_cdrom (monitor, device); + break; + + case DEVICE_FLOPPY: + mount_device_activate_floppy (monitor, device); + break; + + case DEVICE_EXT2: + mount_device_activate_ext2 (monitor, device); + break; + + default: + g_assert_not_reached (); + break; + } + + gtk_signal_emit (GTK_OBJECT (monitor), + signals[VOLUME_MOUNTED], + &device->mount_path); +} + + +static void +eject_cdrom (DeviceInfo *device) +{ +#if 0 + if (device->device_fd < 0) { + device->device_fd = open (device->fsname, O_RDONLY|O_NONBLOCK); + } + + if(device->device_fd < 0) { + return; + } + + g_message ("Trying to eject"); + ioctl (device->device_fd, CDROMEJECT, 0); + + close (device->device_fd); + device->device_fd = -1; +#endif +} + +static void +mount_device_deactivate (NautilusVolumeMonitor *monitor, DeviceInfo *device) +{ + GList dummy_list; + + /* Remove mounted device icon from desktop */ + dummy_list.data = device->link_uri; + dummy_list.next = NULL; + dummy_list.prev = NULL; + nautilus_directory_notify_files_removed (&dummy_list); + + /* Clean up old link */ + remove_mount_link (device); + + switch (device->type) { + case DEVICE_CDROM: + eject_cdrom (device); + break; + + default: + break; + } +} + +static void +mount_device_do_nothing (NautilusVolumeMonitor *monitor, DeviceInfo *device) +{ +} + +static void +mount_device_check_change (gpointer data, gpointer callback_data) +{ + /* What functions to run for particular state transitions */ + static const ChangeDeviceInfoFunction state_transitions[STATE_LAST][STATE_LAST] = { + /************ from: ACTIVE INACTIVE EMPTY */ + /* to */ + /* ACTIVE */ { mount_device_do_nothing, mount_device_activate, mount_device_activate }, + /* INACTIVE */ { mount_device_deactivate, mount_device_do_nothing, mount_device_do_nothing }, + /* EMPTY */ { mount_device_deactivate, mount_device_deactivate, mount_device_do_nothing } + }; + + DeviceInfo *device; + NautilusVolumeMonitor *monitor; + DeviceState old_state; + ChangeDeviceInfoFunction f; + + g_assert (data != NULL); + + device = data; + monitor = NAUTILUS_VOLUME_MONITOR (callback_data); + + old_state = device->state; + + mount_device_set_state (device, monitor); + + if (old_state != device->state) { + f = state_transitions[device->state][old_state]; + + MESSAGE ("State on %s changed from %s to %s, running %p", + device->fsname, state_names[old_state], state_names[device->state], f); + + (* f) (monitor, device); + } +} + +static void +mount_devices_update_is_mounted (NautilusVolumeMonitor *monitor) +{ + FILE *fh; + char line[PATH_MAX * 3], mntpoint[PATH_MAX], devname[PATH_MAX]; + GList *element; + DeviceInfo *device; + + /* Toggle mount state to off and then recheck in mtab. */ + for (element = monitor->details->devices; element != NULL; element = element->next) { + device = element->data; + device->is_mounted = FALSE; + } + + /* Open mtab */ + fh = fopen (_PATH_MOUNTED, "r"); + if (!fh) { + return; + } + + while (fgets (line, sizeof(line), fh)) { + sscanf(line, "%s %s", devname, mntpoint); + device = g_hash_table_lookup (monitor->details->devices_by_fsname, devname); + + if(device) { + device->is_mounted = TRUE; + } + } + + fclose (fh); +} + +static gint +mount_devices_check_status (NautilusVolumeMonitor *monitor) +{ + mount_devices_update_is_mounted (monitor); + + g_list_foreach (monitor->details->devices, + mount_device_check_change, + monitor); + + return TRUE; +} + + +/* Like access, but a bit more accurate - access will let + * root do anything. Does not get read-only or no-exec + * filesystems right. + */ +static gboolean +check_permissions (gchar *filename, int mode) +{ + int euid = geteuid(); + int egid = getegid(); + + struct stat statbuf; + + if (stat (filename, &statbuf) == 0) { + if ((mode & R_OK) && + !((statbuf.st_mode & S_IROTH) || + ((statbuf.st_mode & S_IRUSR) && euid == statbuf.st_uid) || + ((statbuf.st_mode & S_IRGRP) && egid == statbuf.st_gid))) + return FALSE; + if ((mode & W_OK) && + !((statbuf.st_mode & S_IWOTH) || + ((statbuf.st_mode & S_IWUSR) && euid == statbuf.st_uid) || + ((statbuf.st_mode & S_IWGRP) && egid == statbuf.st_gid))) + return FALSE; + if ((mode & X_OK) && + !((statbuf.st_mode & S_IXOTH) || + ((statbuf.st_mode & S_IXUSR) && euid == statbuf.st_uid) || + ((statbuf.st_mode & S_IXGRP) && egid == statbuf.st_gid))) + return FALSE; + + return TRUE; + } + return FALSE; +} + +static gboolean +mount_device_floppy_add (NautilusVolumeMonitor *monitor, DeviceInfo *device) +{ + device->mount_type = g_strdup ("floppy"); + device->type = DEVICE_FLOPPY; + return TRUE; +#if 0 + if (check_permissions (device->fsname, R_OK)) { + return FALSE; + } + + return TRUE; +#endif +} + +static gboolean +mount_device_ext2_add (DeviceInfo *device) +{ + if (check_permissions (device->fsname, R_OK)) { + return FALSE; + } + + /* Only mount root partition for now */ + if ( strcmp (device->mount_path, "/") != 0) { + return FALSE; + } + + device->mount_type = g_strdup ("blockdevice"); + device->type = DEVICE_EXT2; + + return TRUE; +} + + +static void +cdrom_ioctl_frenzy (int fd) +{ + ioctl (fd, CDROM_CLEAR_OPTIONS, CDO_LOCK|CDO_AUTO_CLOSE | CDO_AUTO_EJECT); + ioctl (fd, CDROM_SET_OPTIONS, CDO_USE_FFLAGS | CDO_CHECK_TYPE); + ioctl (fd, CDROM_LOCKDOOR, 0); +} + + +static gboolean +mount_device_iso9660_add (NautilusVolumeMonitor *monitor, DeviceInfo *device) +{ + device->device_fd = open (device->fsname, O_RDONLY|O_NONBLOCK); + if(device->device_fd < 0) { + return FALSE; + } + + device->type = DEVICE_CDROM; + + /* It's probably not a CD-ROM drive */ + if (ioctl (device->device_fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) < 0) { + return FALSE; + } + + cdrom_ioctl_frenzy (device->device_fd); + close (device->device_fd); device->device_fd = -1; + + device->mount_type = g_strdup ("cdrom"); + + return TRUE; +} + + +/* This is here because mtab lists devices by their symlink-followed names rather than what is listed in fstab. *sigh* */ +static void +mount_device_add_aliases (NautilusVolumeMonitor *monitor, const char *alias, DeviceInfo *device) +{ + char buf[PATH_MAX]; + int buflen; + + g_hash_table_insert (monitor->details->devices_by_fsname, (gpointer)alias, device); + + buflen = readlink (alias, buf, sizeof(buf)); + if(buflen < 1) { + return; + } + + buf[buflen] = '\0'; + + if(buf[0] != '/') { + char buf2[PATH_MAX]; + char *dn; + dn = g_dirname(alias); + sprintf(buf2, "%s/%s", dn, buf); + g_free(dn); + strcpy(buf, buf2); + } + + mount_device_add_aliases (monitor, g_strdup(buf), device); +} + + +static void +add_mount_device (NautilusVolumeMonitor *monitor, struct mntent *ent) +{ + DeviceInfo *newdev = NULL; + gboolean mounted; + + newdev = g_new0 (DeviceInfo, 1); + g_assert (newdev); + newdev->device_fd = -1; + newdev->fsname = g_strdup (ent->mnt_fsname); + newdev->mount_path = g_strdup (ent->mnt_dir); + newdev->volume_name = NULL; + newdev->link_uri = NULL; + newdev->state = STATE_EMPTY; + + mounted = FALSE; + + if (strcmp (ent->mnt_type, MOUNT_TYPE_ISO9660) == 0) { + mounted = mount_device_iso9660_add (monitor, newdev); + } else if (strncmp (ent->mnt_fsname, "/dev/fd", strlen("/dev/fd")) == 0) { + mounted = mount_device_floppy_add (monitor, newdev); + } else if (strcmp (ent->mnt_type, MOUNT_TYPE_EXT2) == 0) { + mounted = mount_device_ext2_add (newdev); + } else { + /* FIXME: Is this a reasonable way to report this error? */ + MESSAGE ("Unknown file system: %s", ent->mnt_type); + } + + if (mounted) { + monitor->details->devices = g_list_append (monitor->details->devices, newdev); + mount_device_add_aliases (monitor, newdev->fsname, newdev); + MESSAGE ("Device %s came through (type %s)", newdev->fsname, type_names[newdev->type]); + } else { + close (newdev->device_fd); + g_free (newdev->fsname); + g_free (newdev->mount_path); + g_free (newdev); + } +} + +static gboolean +mntent_is_removable_fs (struct mntent *ent) +{ + if (strcmp (ent->mnt_type, MOUNT_TYPE_ISO9660) == 0) { + return TRUE; + } + + if (strncmp (ent->mnt_fsname, "/dev/fd", strlen("/dev/fd")) == 0) { + return TRUE; + } + + return FALSE; +} + +#if 0 +static gboolean +mntent_has_option(const char *optlist, const char *option) +{ + gboolean retval = FALSE; + char **options; + int i; + + options = g_strsplit (optlist, ",", -1); + + for(i = 0; options[i]; i++) { + if (strcmp (options[i], option) == 0) { + retval = TRUE; + break; + } + } + + g_strfreev (options); + + return retval; +} +#endif + +void +nautilus_volume_monitor_find_mount_devices (NautilusVolumeMonitor *monitor) +{ + FILE *mef; + struct mntent *ent; + + mef = setmntent (_PATH_MNTTAB, "r"); + g_return_if_fail (mef); + + while ((ent = getmntent (mef))) { + MESSAGE ("Checking device %s", ent->mnt_fsname); + +#if 0 + /* Think some more about these checks */ + /* Check for removable device */ + if (!mntent_is_removable_fs (ent)) { + continue; + } + + if (!mntent_has_option (ent->mnt_opts, MOUNT_OPTIONS_USER) + && !mntent_has_option (ent->mnt_opts, MOUNT_OPTIONS_OWNER)) { + continue; + } +#endif + /* Add it to our list of mount points */ + add_mount_device (monitor, ent); + } + + + endmntent (mef); + + g_list_foreach (monitor->details->devices, (GFunc) mount_device_set_state, monitor); + + /* Manually set state of all volumes to empty so we update */ + g_list_foreach (monitor->details->devices, (GFunc) device_set_state_empty, monitor); + + /* Add a timer function to check for status change in mounted devices */ + monitor->details->mount_device_timer_id = + gtk_timeout_add (CHECK_INTERVAL, (GtkFunction) mount_devices_check_status, monitor); +} + + +gboolean +nautilus_volume_monitor_mount_unmount_removable (NautilusVolumeMonitor *monitor, const char *mount_point) +{ + gboolean is_mounted, found_device; + char *argv[3]; + GList *element; + DeviceInfo *device; + int exec_err; + + is_mounted = FALSE; + found_device = FALSE; + device = NULL; + + /* Locate DeviceInfo for mount point */ + for (element = monitor->details->devices; element != NULL; element = element->next) { + device = element->data; + if (strcmp (mount_point, device->mount_path) == 0) { + found_device = TRUE; + break; + } + } + + /* Get mount state and then decide to mount/unmount the volume */ + if (found_device) { + is_mounted = nautilus_volume_monitor_volume_is_mounted (mount_point); + argv[1] = (char *)mount_point; + argv[2] = NULL; + + if (is_mounted) { + /* Unount */ + argv[0] = "/bin/umount"; + exec_err = gnome_execute_async (g_get_home_dir(), 2, argv); + is_mounted = FALSE; + } else { + /* Mount */ + argv[0] = "/bin/mount"; + exec_err = gnome_execute_async (g_get_home_dir(), 2, argv); + is_mounted = TRUE; + } + } + + return is_mounted; +} + + +static void +remove_mount_link (DeviceInfo *device) +{ + GnomeVFSResult result; + + if (device->link_uri != NULL) { + result = gnome_vfs_unlink (device->link_uri); + if (result != GNOME_VFS_OK) { + /* FIXME: Is a message to the console acceptable here? */ + MESSAGE ("Unable to remove mount link: %s", gnome_vfs_result_to_string (result)); + } + g_free (device->link_uri); + device->link_uri = NULL; + } +} + +static void +free_device_info (DeviceInfo *device, NautilusVolumeMonitor *monitor) +{ + + if (device->device_fd != -1) { + close (device->device_fd); + device->device_fd = -1; + } + + if (device->fsname != NULL) { + g_free (device->fsname); + device->fsname = NULL; + } + + if (device->mount_path != NULL) { + g_free (device->mount_path); + device->mount_path = NULL; + } + + if (device->mount_type != NULL) { + g_free (device->mount_type); + device->mount_type = NULL; + } + + if (device->volume_name != NULL) { + g_free (device->volume_name); + device->volume_name = NULL; + } + + if (device->link_uri != NULL) { + g_free (device->link_uri); + device->link_uri = NULL; + } +} + +static void +get_iso9660_volume_name (DeviceInfo *device) +{ + struct iso_primary_descriptor iso_buffer; + + lseek (device->device_fd, (off_t) 2048*16, SEEK_SET); + read (device->device_fd, &iso_buffer, 2048); + + if (device->volume_name != NULL) { + g_free (device->volume_name); + } + + device->volume_name = g_strdup (iso_buffer.volume_id); + if (device->volume_name == NULL) { + device->volume_name = g_strdup (device->mount_type); + } +} + + +static void +get_ext2_volume_name (DeviceInfo *device) +{ + device->volume_name = g_strdup ("Ext2 Volume"); +} + +static void +get_floppy_volume_name (DeviceInfo *device) +{ + device->volume_name = g_strdup ("Floppy"); +} diff --git a/libnautilus-private/nautilus-volume-monitor.h b/libnautilus-private/nautilus-volume-monitor.h new file mode 100644 index 000000000..3fb9ce9ef --- /dev/null +++ b/libnautilus-private/nautilus-volume-monitor.h @@ -0,0 +1,105 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* nautilus-volume-monitor.h - interface for desktop mounting functions. + + Copyright (C) 2000 Eazel, Inc. + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Authors: Gene Z. Ragan <gzr@eazel.com> +*/ + +#ifndef NAUTILUS_VOLUME_MONITOR_H +#define NAUTILUS_VOLUME_MONITOR_H + +#include <glib.h> +#include <gtk/gtk.h> +#include "nautilus-icon-container.h" + +typedef struct NautilusVolumeMonitor NautilusVolumeMonitor; +typedef struct NautilusVolumeMonitorClass NautilusVolumeMonitorClass; +typedef struct NautilusVolumeMonitorDetails NautilusVolumeMonitorDetails; + +#define NAUTILUS_TYPE_VOLUME_MONITOR (nautilus_volume_monitor_get_type()) +#define NAUTILUS_VOLUME_MONITOR(obj) (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_VOLUME_MONITOR, NautilusVolumeMonitor)) +#define NAUTILUS_VOLUME_MONITOR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_VOLUME_MONITOR, NautilusVolumeMonitorClass)) +#define IS_NAUTILUS_VOLUME_MONITOR(obj) (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_VOLUME_MONITOR)) + +struct NautilusVolumeMonitor { + GtkObject parent; + NautilusVolumeMonitorDetails *details; +}; + +struct NautilusVolumeMonitorClass { + GtkObjectClass parent_class; + + /* Signals */ + char * (* volume_mounted) (NautilusVolumeMonitor *monitor); +}; + +struct NautilusVolumeMonitorDetails +{ + GHashTable *devices_by_fsname; + GList *devices; + guint mount_device_timer_id; +}; + + +#define MOUNT_TYPE_ISO9660 "iso9660" +#define MOUNT_TYPE_EXT2 "ext2" +#define MOUNT_OPTIONS_USER "user" +#define MOUNT_OPTIONS_OWNER "owner" + +#define CHECK_INTERVAL 2000 + +typedef enum { + STATE_ACTIVE = 0, + STATE_INACTIVE, + STATE_EMPTY, + STATE_LAST, +} DeviceState; + +typedef enum { + DEVICE_CDROM, + DEVICE_FLOPPY, + DEVICE_EXT2, + DEVICE_OTHER +} DeviceType; + +typedef struct { + DeviceType type; + DeviceState state; + int device_fd; + + char *fsname; + char *mount_path; + char *mount_type; + char *volume_name; + char *link_uri; + + gboolean is_mounted; + gboolean did_mount; +} DeviceInfo; + +GtkType nautilus_volume_monitor_get_type (void); +NautilusVolumeMonitor *nautilus_volume_monitor_get (void); +GList *fm_desktop_get_removable_volume_list (void); +gboolean nautilus_volume_monitor_volume_is_mounted (const char *mount_point); +void nautilus_volume_monitor_find_mount_devices (NautilusVolumeMonitor *icon_view); +gboolean nautilus_volume_monitor_mount_unmount_removable (NautilusVolumeMonitor *monitor, + const char *mount_point); + +#endif
\ No newline at end of file diff --git a/src/file-manager/Makefile.am b/src/file-manager/Makefile.am index ac4e23199..8dec493a6 100644 --- a/src/file-manager/Makefile.am +++ b/src/file-manager/Makefile.am @@ -28,7 +28,6 @@ libnautilus_file_manager_la_SOURCES= \ dfos-xfer.c \ dfos.c \ fm-desktop-icon-view.c \ - fm-desktop-mounting.c \ fm-directory-view.c \ fm-error-reporting.c \ fm-icon-text-window.c \ diff --git a/src/file-manager/fm-desktop-icon-view.c b/src/file-manager/fm-desktop-icon-view.c index 440ccbaa1..ac5187c03 100644 --- a/src/file-manager/fm-desktop-icon-view.c +++ b/src/file-manager/fm-desktop-icon-view.c @@ -25,8 +25,6 @@ #include <config.h> #include "fm-desktop-icon-view.h" - -#include "fm-desktop-mounting.h" #include "fm-icon-view.h" #include <fcntl.h> @@ -39,6 +37,7 @@ #include <libnautilus-extensions/nautilus-gnome-extensions.h> #include <libnautilus-extensions/nautilus-gtk-macros.h> #include <libnautilus-extensions/nautilus-link.h> +#include <libnautilus-extensions/nautilus-volume-monitor.h> #include <mntent.h> #include <unistd.h> @@ -67,6 +66,10 @@ static void fm_desktop_icon_view_set_directory_auto_layout (FMIco static void fm_desktop_icon_view_trash_state_changed_callback (NautilusTrashMonitor *trash, gboolean state, gpointer callback_data); + +static void mount_unmount_removable (GtkCheckMenuItem *item, + FMDesktopIconView *icon_view); +static void place_home_directory (FMDesktopIconView *icon_view); NAUTILUS_DEFINE_CLASS_BOILERPLATE (FMDesktopIconView, fm_desktop_icon_view, FM_TYPE_ICON_VIEW); @@ -86,20 +89,10 @@ fm_desktop_icon_view_destroy (GtkObject *object) icon_view = FM_DESKTOP_ICON_VIEW (object); - /* Remove timer function */ - gtk_timeout_remove (icon_view->details->mount_device_timer_id); - - /* Remove mount link files */ - g_list_foreach (icon_view->details->devices, (GFunc)fm_desktop_remove_mount_links, icon_view); - - /* Clean up other device info */ - g_list_foreach (icon_view->details->devices, (GFunc)fm_desktop_free_device_info, icon_view); - /* Clean up details */ - g_hash_table_destroy (icon_view->details->devices_by_fsname); - g_list_free (icon_view->details->devices); g_free (icon_view->details); + NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object)); } @@ -175,11 +168,10 @@ fm_desktop_icon_view_initialize (FMDesktopIconView *desktop_icon_view) /* Set up details */ desktop_icon_view->details = g_new0 (FMDesktopIconViewDetails, 1); - desktop_icon_view->details->devices_by_fsname = g_hash_table_new (g_str_hash, g_str_equal); - desktop_icon_view->details->devices = NULL; + desktop_icon_view->details->volume_monitor = nautilus_volume_monitor_get (); /* Setup home directory link */ - fm_desktop_place_home_directory (desktop_icon_view); + place_home_directory (desktop_icon_view); gtk_signal_connect (GTK_OBJECT (icon_container), "middle_click", @@ -192,7 +184,7 @@ fm_desktop_icon_view_initialize (FMDesktopIconView *desktop_icon_view) desktop_icon_view); /* Check for mountable devices */ - fm_desktop_find_mount_devices (desktop_icon_view, _PATH_MNTTAB); + nautilus_volume_monitor_find_mount_devices (desktop_icon_view->details->volume_monitor); } static void @@ -253,7 +245,7 @@ fm_desktop_icon_view_create_background_context_menu_items (FMDirectoryView *view } /* Add check mark if volume is mounted */ - active = fm_desktop_volume_is_mounted (element->data); + active = nautilus_volume_monitor_volume_is_mounted (element->data); gtk_check_menu_item_set_show_toggle (GTK_CHECK_MENU_ITEM (check_menu_item), TRUE); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (check_menu_item), active); @@ -263,7 +255,7 @@ fm_desktop_icon_view_create_background_context_menu_items (FMDirectoryView *view gtk_signal_connect (GTK_OBJECT (check_menu_item), "activate", - GTK_SIGNAL_FUNC (fm_desktop_mount_unmount_removable), + GTK_SIGNAL_FUNC (mount_unmount_removable), FM_DESKTOP_ICON_VIEW (view)); gtk_menu_append (sub_menu, check_menu_item); @@ -326,3 +318,58 @@ fm_desktop_icon_view_trash_state_changed_callback (NautilusTrashMonitor *trash_m g_free (path); g_free (desktop_directory_path); } + +static void +mount_unmount_removable (GtkCheckMenuItem *item, FMDesktopIconView *icon_view) +{ + gboolean is_mounted; + char *mount_point; + + is_mounted = FALSE; + + /* Locate our mount point data */ + mount_point = gtk_object_get_data (GTK_OBJECT (item), "mount_point"); + if (mount_point != NULL) { + is_mounted = nautilus_volume_monitor_mount_unmount_removable + (icon_view->details->volume_monitor, mount_point); + } + + /* Set the check state of menu item even thought the user may not see it */ + gtk_check_menu_item_set_active (item, is_mounted); +} + +/* fm_desktop_place_home_directory + * + * Add an icon representing the user's home directory on the desktop. + * Create if necessary + */ +static void +place_home_directory (FMDesktopIconView *icon_view) +{ + char *desktop_path, *home_link_name, *home_link_path, *home_link_uri, *home_dir_uri; + GnomeVFSResult result; + GnomeVFSFileInfo info; + + desktop_path = nautilus_get_desktop_directory (); + home_link_name = g_strdup_printf ("%s's Home", g_get_user_name ()); + home_link_path = nautilus_make_path (desktop_path, home_link_name); + home_link_uri = nautilus_get_uri_from_local_path (home_link_path); + + result = gnome_vfs_get_file_info (home_link_uri, &info, 0); + if (result != GNOME_VFS_OK) { + /* FIXME: Maybe we should only create if the error was "not found". */ + /* There was no link file. Create it and add it to the desktop view */ + home_dir_uri = nautilus_get_uri_from_local_path (g_get_home_dir ()); + result = nautilus_link_create (desktop_path, home_link_name, "temp-home.png", home_dir_uri); + g_free (home_dir_uri); + if (result != GNOME_VFS_OK) { + /* FIXME: Is a message to the console acceptable here? */ + g_message ("Unable to create home link: %s", gnome_vfs_result_to_string (result)); + } + } + + g_free (home_link_uri); + g_free (home_link_path); + g_free (home_link_name); + g_free (desktop_path); +} diff --git a/src/file-manager/fm-desktop-icon-view.h b/src/file-manager/fm-desktop-icon-view.h index cb0eabda8..2bad48c60 100644 --- a/src/file-manager/fm-desktop-icon-view.h +++ b/src/file-manager/fm-desktop-icon-view.h @@ -26,6 +26,7 @@ #define FM_DESKSTOP_ICON_VIEW_H #include "fm-icon-view.h" +#include <libnautilus-extensions/nautilus-volume-monitor.h> typedef struct FMDesktopIconView FMDesktopIconView; typedef struct FMDesktopIconViewClass FMDesktopIconViewClass; @@ -48,12 +49,11 @@ struct FMDesktopIconViewClass { struct FMDesktopIconViewDetails { - GHashTable *devices_by_fsname; - GList *devices; - guint mount_device_timer_id; + NautilusVolumeMonitor *volume_monitor; }; + /* GtkObject support */ GtkType fm_desktop_icon_view_get_type (void); diff --git a/src/file-manager/fm-desktop-mounting.h b/src/file-manager/fm-desktop-mounting.h deleted file mode 100644 index de3d4e4d9..000000000 --- a/src/file-manager/fm-desktop-mounting.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* fm-desktop-mounting.h - interface for desktop mounting functions. - - Copyright (C) 2000 Eazel, Inc. - - The Gnome Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The Gnome 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the Gnome Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Authors: Gene Z. Ragan <gzr@eazel.com> -*/ - -#ifndef FM_DESKSTOP_MOUTING -#define FM_DESKSTOP_MOUTING - -#include "fm-desktop-icon-view.h" - -#define MOUNT_TYPE_ISO9660 "iso9660" -#define MOUNT_TYPE_EXT2 "ext2" -#define MOUNT_OPTIONS_USER "user" -#define MOUNT_OPTIONS_OWNER "owner" - -#define CHECK_INTERVAL 2000 - -typedef enum { - STATE_ACTIVE = 0, - STATE_INACTIVE, - STATE_EMPTY, - STATE_LAST, -} DeviceState; - -typedef enum { - DEVICE_CDROM, - DEVICE_FLOPPY, - DEVICE_EXT2, - DEVICE_OTHER -} DeviceType; - -typedef struct { - DeviceType type; - DeviceState state; - int device_fd; - - char *fsname; - char *mount_path; - char *mount_type; - char *volume_name; - char *link_uri; - - gboolean is_mounted; - gboolean did_mount; -} DeviceInfo; - -GList *fm_desktop_get_removable_volume_list (void); -void fm_desktop_remove_mount_links (DeviceInfo *device, - FMDesktopIconView *icon_view); -void fm_desktop_place_home_directory (FMDesktopIconView *icon_view); -void fm_desktop_free_device_info (DeviceInfo *device, - FMDesktopIconView *icon_view); -void fm_desktop_find_mount_devices (FMDesktopIconView *icon_view, - const char *fstab_path); -void fm_desktop_mount_unmount_removable (GtkCheckMenuItem *item, - FMDesktopIconView *icon_view); -gboolean fm_desktop_volume_is_mounted (const char *mount_point); - -#endif
\ No newline at end of file |