summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog65
-rw-r--r--libnautilus-extensions/nautilus-file-operations.c653
-rw-r--r--libnautilus-extensions/nautilus-trash-directory.c37
-rw-r--r--libnautilus-extensions/nautilus-trash-monitor.c54
-rw-r--r--libnautilus-extensions/nautilus-trash-monitor.h3
-rw-r--r--libnautilus-extensions/nautilus-volume-monitor.c22
-rw-r--r--libnautilus-extensions/nautilus-volume-monitor.h2
-rw-r--r--libnautilus-private/nautilus-file-operations.c653
-rw-r--r--libnautilus-private/nautilus-trash-directory.c37
-rw-r--r--libnautilus-private/nautilus-trash-monitor.c54
-rw-r--r--libnautilus-private/nautilus-trash-monitor.h3
-rw-r--r--libnautilus-private/nautilus-volume-monitor.c22
-rw-r--r--libnautilus-private/nautilus-volume-monitor.h2
13 files changed, 986 insertions, 621 deletions
diff --git a/ChangeLog b/ChangeLog
index 0bfe0e8b1..5a2997096 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,67 @@
+2000-12-12 Pavel Cisler <pavel@eazel.com>
+
+ reviewed by: Darin Adler <darin@eazel.com>
+
+ Fixed 4954 Nautilus crashes attempting to empty a .Trash
+ containing undeletable files
+
+ * libnautilus-extensions/nautilus-file-operations.c:
+ (build_error_string), (handle_xfer_vfs_error)
+ Reworked the error message building logic. Split up
+ the routine into a part that decides what the interesting
+ input for building the error message is and a part that
+ actually builds the error message. Fixed a number
+ of cases where a wrong error message would be used. The
+ actual bug in the bug report was one of the cases -- an assert
+ catching a case that was not handled properly.
+
+ Fixed:
+ part of -- 638 When a new volume gets mounted, integrate its Trash
+ directory.
+ part of -- 4143 Files dragged to trash icon on desktop seem to
+ vanish,
+ part of -- 4963 Files dragged to Trash from floppy don't appear
+ in Trash,
+
+ * libnautilus-extensions/nautilus-trash-monitor.c:
+ * libnautilus-extensions/nautilus-trash-monitor.h:
+ (add_one_volume_trash),
+ (nautilus_trash_monitor_get_trash_directories):
+ Added a new call that returns a list of all the Trash directories
+ on all the mouted volumes.
+
+ * libnautilus-extensions/nautilus-trash-directory.c: (add_volume):
+ Got rid of get_volume_vfs_uri_if_writable.
+ Used the new nautilus_volume_monitor_should_integrate_trash instead
+ to pick the volumes that can support trash.
+
+ * libnautilus-extensions/nautilus-volume-monitor.c:
+ (nautilus_volume_monitor_should_integrate_trash),
+ (nautilus_volume_monitor_get_volume_mount_uri):
+ * libnautilus-extensions/nautilus-volume-monitor.h:
+ Add new helper calls used by the routine that collects all the
+ trash uris from all mouted volumes.
+
+ * libnautilus-extensions/nautilus-file-operations.c:
+ (do_empty_trash):
+ Pass in a list of Trash directories instead of just the
+ single trash in the user's home directory.
+
+ Fixed:
+ 2443 Trash is only found on EXT2 volumes
+ 2444 Trash on read-only volumes is not displayed
+ remaining part of -- 4143 Files dragged to trash icon on desktop
+ seem to vanish,
+ remaining part of -- 4963 Files dragged to Trash from floppy
+ don't appear in Trash,
+
+ * libnautilus-extensions/nautilus-volume-monitor.c:
+ (nautilus_volume_monitor_should_integrate_trash):
+ Removed the old logic from get_volume_vfs_uri_if_writable
+ that only displayed trash from writable ext2 volumes.
+ Enumerated all the file system types that we know can
+ support trash.
+
2000-12-12 Eskil Heyn Olsen <eskil@eazel.com>
* components/services/install/lib/eazel-package-system-private.h:
@@ -149,7 +213,6 @@
that did a hide followed by a show. Corrected an assert that
should have been a return_if_fail.
->>>>>>> 1.3120
2000-12-12 John Sullivan <sullivan@eazel.com>
reviewed by: Darin Adler <darin@eazel.com>
diff --git a/libnautilus-extensions/nautilus-file-operations.c b/libnautilus-extensions/nautilus-file-operations.c
index bda30ff96..a73fc78b0 100644
--- a/libnautilus-extensions/nautilus-file-operations.c
+++ b/libnautilus-extensions/nautilus-file-operations.c
@@ -44,6 +44,7 @@
#include <libnautilus-extensions/nautilus-global-preferences.h>
#include <libnautilus-extensions/nautilus-link.h>
#include <libnautilus-extensions/nautilus-stock-dialogs.h>
+#include <libnautilus-extensions/nautilus-trash-monitor.h>
typedef enum {
XFER_MOVE,
@@ -467,338 +468,451 @@ handle_xfer_ok (const GnomeVFSXferProgressInfo *progress_info,
}
}
+typedef enum {
+ ERROR_READ_ONLY,
+ ERROR_NOT_READABLE,
+ ERROR_NOT_WRITABLE,
+ ERROR_NOT_ENOUGH_PERMISSIONS,
+ ERROR_NO_SPACE,
+ ERROR_OTHER
+} NautilusFileOperationsErrorKind;
-static int
-handle_xfer_vfs_error (const GnomeVFSXferProgressInfo *progress_info,
- XferInfo *xfer_info)
+typedef enum {
+ ERROR_LOCATION_UNKNOWN,
+ ERROR_LOCATION_SOURCE,
+ ERROR_LOCATION_SOURCE_PARENT,
+ ERROR_LOCATION_SOURCE_OR_PARENT,
+ ERROR_LOCATION_TARGET
+} NautilusFileOperationsErrorLocation;
+
+
+static char *
+build_error_string (const char *source_name, const char *target_name,
+ XferKind operation_kind, NautilusFileOperationsErrorKind error_kind,
+ NautilusFileOperationsErrorLocation error_location, GnomeVFSResult error)
{
- /* Notice that the error mode in `xfer_info' is the one we have been
- * requested, but the transfer is always performed in mode
- * `GNOME_VFS_XFER_ERROR_MODE_QUERY'.
- */
+ /* Avoid clever message composing here, just use brute force and
+ * duplicate the different flavors of error messages for all the
+ * possible permutations.
+ * That way localizers have an easier time and can even rearrange the
+ * order of the words in the messages easily.
+ */
- int result;
- char *text;
- char *unescaped_name;
- const char *dialog_title;
const char *error_string;
+ char *result;
- switch (xfer_info->error_mode) {
- case GNOME_VFS_XFER_ERROR_MODE_QUERY:
+ error_string = NULL;
+ result = NULL;
- /* transfer error, prompt the user to continue or stop */
+ if (error_location == ERROR_LOCATION_SOURCE_PARENT) {
- unescaped_name = NULL;
+ switch (operation_kind) {
+ case XFER_MOVE:
+ case XFER_MOVE_TO_TRASH:
+ if (error_kind == ERROR_NOT_ENOUGH_PERMISSIONS) {
+ error_string = _("Error while moving.\n"
+ "\"%s\" cannot be moved because you do not have "
+ "permissions to change its parent folder.");
+ } else if (error_kind == ERROR_READ_ONLY) {
+ error_string = _("Error while moving.\n"
+ "\"%s\" cannot be moved because its parent folder "
+ "is read-only.");
+ } else if (error_kind == ERROR_NOT_WRITABLE) {
+ error_string = _("Error while moving.\n"
+ "\"%s\" cannot be moved because its parent folder "
+ "is not writable.");
+ }
+ break;
- if (progress_info->source_name != NULL) {
- unescaped_name = nautilus_format_name_for_display (progress_info->source_name);
+ case XFER_DELETE:
+ case XFER_EMPTY_TRASH:
+ if (error_kind == ERROR_NOT_ENOUGH_PERMISSIONS) {
+ error_string = _("Error while deleting.\n"
+ "\"%s\" cannot be deleted because you do not have "
+ "permissions to change its parent folder.");
+ } else if (error_kind == ERROR_READ_ONLY) {
+ error_string = _("Error while deleting.\n"
+ "\"%s\" cannot be deleted because its parent folder "
+ "is read-only.");
+ } else if (error_kind == ERROR_NOT_WRITABLE) {
+ error_string = _("Error while moving.\n"
+ "\"%s\" cannot be moved because its parent folder "
+ "is not writable.");
+ }
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ if (error_string != NULL) {
+ g_assert (source_name != NULL);
+ result = g_strdup_printf (error_string, source_name);
}
- /* Resist the temptation to do clever message composing here, just
- * use brute force and duplicate the different flavors of error messages.
- * That way localizers have an easier time and can even rearrange the
- * order of the words in the messages easily.
- */
+ } else if (error_location == ERROR_LOCATION_SOURCE_OR_PARENT) {
- switch (xfer_info->kind) {
- case XFER_COPY:
- case XFER_DUPLICATE:
- dialog_title = _("Error while copying.");
- break;
+ g_assert (source_name != NULL);
+
+ switch (operation_kind) {
case XFER_MOVE:
- dialog_title = _("Error while moving.");
- break;
- case XFER_LINK:
- dialog_title = _("Error while linking.");
+ if (error_kind == ERROR_NOT_ENOUGH_PERMISSIONS) {
+ error_string = _("Error while moving.\n"
+ "\"%s\" cannot be moved because you do not have "
+ "permissions to change it or its parent folder.");
+ }
break;
- case XFER_DELETE:
- case XFER_EMPTY_TRASH:
case XFER_MOVE_TO_TRASH:
- dialog_title = _("Error while deleting.");
+ if (error_kind == ERROR_NOT_ENOUGH_PERMISSIONS) {
+ error_string = _("Error while moving.\n"
+ "\"%s\" cannot be moved to trash because you do not have "
+ "permissions to change it or its parent folder.");
+ }
break;
+
default:
- dialog_title = NULL;
+ g_assert_not_reached ();
break;
}
- /* special case read only target errors or non-readable sources
- * and other predictable failures
- */
-
- if (progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM
- || progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY
- || progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED) {
-
- if ((xfer_info->kind == XFER_MOVE || xfer_info->kind == XFER_MOVE_TO_TRASH)
- && progress_info->phase != GNOME_VFS_XFER_CHECKING_DESTINATION) {
- /* we are failing because we are moving from a directory that
- * is not writable
- */
- if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED) {
- error_string = _("Error while moving.\n"
- "%s cannot be moved because you do not have "
- "permissions to change it's parent folder.");
- } else {
- error_string = _("Error while moving.\n"
- "%s cannot be moved because its parent folder "
- "is read-only.");
- }
- } else if (progress_info->phase == GNOME_VFS_XFER_PHASE_OPENSOURCE
- || progress_info->phase == GNOME_VFS_XFER_PHASE_COLLECTING
- || progress_info->phase == GNOME_VFS_XFER_PHASE_INITIAL) {
-
- if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED) {
- switch (xfer_info->kind) {
- case XFER_COPY:
- case XFER_DUPLICATE:
- error_string = _("Error while copying.\n"
- "You do not have permissions to read %s.");
- break;
- case XFER_MOVE:
- error_string = _("Error while moving.\n"
- "You do not have permissions to read %s.");
- break;
- case XFER_LINK:
- error_string = _("Error while linking.\n"
- "You do not have permissions to read %s.");
- break;
- case XFER_DELETE:
- case XFER_EMPTY_TRASH:
- case XFER_MOVE_TO_TRASH:
- error_string = _("Error while deleting.\n"
- "You do not have permissions to read %s.");
- break;
- default:
- error_string = "";
- break;
- }
- } else {
- switch (xfer_info->kind) {
- case XFER_COPY:
- case XFER_DUPLICATE:
- error_string = _("Error while copying.\n"
- "%s is not readable.");
- break;
- case XFER_MOVE:
- error_string = _("Error while moving.\n"
- "%s is not readable.");
- break;
- case XFER_LINK:
- error_string = _("Error while linking.\n"
- "%s is not readable.");
- break;
- case XFER_DELETE:
- case XFER_EMPTY_TRASH:
- case XFER_MOVE_TO_TRASH:
- error_string = _("Error while deleting.\n"
- "%s is not readable.");
- break;
- default:
- error_string = "";
- break;
- }
- }
+ if (error_string != NULL) {
+ g_assert (source_name != NULL);
+ result = g_strdup_printf (error_string, source_name);
+ }
- } else {
- if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED) {
- switch (xfer_info->kind) {
- case XFER_COPY:
- case XFER_DUPLICATE:
- error_string = _("Error while copying items to \"%s\".\n"
- "You do not have permissions to write to the destination.");
- break;
- case XFER_MOVE_TO_TRASH:
- case XFER_MOVE:
- error_string = _("Error while moving items to \"%s\".\n"
- "You do not have permissions to write to the destination.");
- break;
- case XFER_LINK:
- error_string = _("Error while linking items to \"%s\".\n"
- "You do not have permissions to write to the destination.");
- break;
- default:
- g_assert_not_reached ();
- error_string = "";
- break;
- }
- } else {
- switch (xfer_info->kind) {
- case XFER_COPY:
- case XFER_DUPLICATE:
- error_string = _("Error while copying items to \"%s\".\n"
- "The destination is not writable.");
- break;
- case XFER_MOVE_TO_TRASH:
- case XFER_MOVE:
- error_string = _("Error while moving items to \"%s\".\n"
- "The destination is not writable.");
- break;
- case XFER_LINK:
- error_string = _("Error while linking items to \"%s\".\n"
- "The destination is not writable.");
- break;
- default:
- g_assert_not_reached ();
- error_string = "";
- break;
- }
- }
+ } else if (error_location == ERROR_LOCATION_SOURCE) {
- if (progress_info->target_name != NULL) {
- g_free (unescaped_name);
- unescaped_name = nautilus_format_name_for_display (
- progress_info->target_name);
- }
+ g_assert (source_name != NULL);
+
+ switch (operation_kind) {
+ case XFER_COPY:
+ case XFER_DUPLICATE:
+ if (error_kind == ERROR_NOT_READABLE) {
+ error_string = _("Error while copying.\n"
+ "\"%s\" is not readable.");
}
- text = g_strdup_printf (error_string, unescaped_name);
- g_free (unescaped_name);
-
- result = nautilus_simple_dialog
- (parent_for_error_dialog (xfer_info), TRUE, text,
- dialog_title, _("Stop"), NULL);
- g_free (text);
+ break;
+ case XFER_LINK:
+ if (error_kind == ERROR_NOT_READABLE) {
+ error_string = _("Error while linking\n"
+ "\"%s\" is not readable.");
+ }
+ break;
- return GNOME_VFS_XFER_ERROR_ACTION_ABORT;
+ default:
+ g_assert_not_reached ();
+ break;
}
- /* special case read only target errors */
- if (progress_info->vfs_status == GNOME_VFS_ERROR_NO_SPACE) {
-
- if (unescaped_name != NULL) {
- switch (xfer_info->kind) {
- case XFER_COPY:
- case XFER_DUPLICATE:
- error_string = _("Error while copying \"%s\".\n"
- "There is no space on the destination.");
- break;
- case XFER_MOVE_TO_TRASH:
- case XFER_MOVE:
- error_string = _("Error while moving \"%s\".\n"
- "There is no space on the destination.");
- break;
- case XFER_LINK:
- error_string = _("Error while linking \"%s\".\n"
- "There is no space on the destination.");
- break;
- default:
- g_assert_not_reached ();
- error_string = "";
- break;
- }
- text = g_strdup (error_string);
- } else {
- switch (xfer_info->kind) {
- case XFER_COPY:
- case XFER_DUPLICATE:
- error_string = _("Error while copying.\n"
- "There is no space on the destination.");
- break;
- case XFER_MOVE_TO_TRASH:
- case XFER_MOVE:
- error_string = _("Error while moving.\n"
- "There is no space on the destination.");
- break;
- case XFER_LINK:
- error_string = _("Error while linking.\n"
- "There is no space on the destination.");
- break;
- default:
- g_assert_not_reached ();
- error_string = "";
- break;
- }
- text = g_strdup_printf (error_string, unescaped_name);
- }
- g_free (unescaped_name);
-
- result = nautilus_simple_dialog
- (parent_for_error_dialog (xfer_info), TRUE, text,
- dialog_title, _("Stop"), NULL);
- g_free (text);
- return GNOME_VFS_XFER_ERROR_ACTION_ABORT;
+ if (error_string != NULL) {
+ g_assert (source_name != NULL);
+ result = g_strdup_printf (error_string, source_name);
}
- if (unescaped_name != NULL) {
-
- switch (xfer_info->kind) {
+ } else if (error_location == ERROR_LOCATION_TARGET) {
+
+ if (error_kind == ERROR_NO_SPACE) {
+ switch (operation_kind) {
case XFER_COPY:
case XFER_DUPLICATE:
- error_string = _("Error \"%s\" while copying.\n"
+ error_string = _("Error while copying \"%s\".\n"
+ "There is no space on the destination.");
+ break;
+ case XFER_MOVE_TO_TRASH:
+ case XFER_MOVE:
+ error_string = _("Error while moving \"%s\".\n"
+ "There is no space on the destination.");
+ break;
+ case XFER_LINK:
+ error_string = _("Error while linking \"%s\".\n"
+ "There is no space on the destination.");
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ } else {
+ switch (operation_kind) {
+ case XFER_COPY:
+ case XFER_DUPLICATE:
+ if (error_kind == ERROR_NOT_ENOUGH_PERMISSIONS) {
+ error_string = _("Error while copying items to \"%s\".\n"
+ "You do not have permissions to write to "
+ "the destination.");
+ } else if (error_kind == ERROR_NOT_WRITABLE) {
+ error_string = _("Error while copying items to \"%s\".\n"
+ "The destination is not writable.");
+ }
+ break;
+ case XFER_MOVE:
+ case XFER_MOVE_TO_TRASH:
+ if (error_kind == ERROR_NOT_ENOUGH_PERMISSIONS) {
+ error_string = _("Error while moving items \"%s\".\n"
+ "You do not have permissions to write to "
+ "the destination.");
+ } else if (error_kind == ERROR_NOT_WRITABLE) {
+ error_string = _("Error while moving items \"%s\".\n"
+ "The destination is not writable.");
+ }
+
+ break;
+ case XFER_LINK:
+ if (error_kind == ERROR_NOT_ENOUGH_PERMISSIONS) {
+ error_string = _("Error while creating links in \"%s\".\n"
+ "You do not have permissions to write to "
+ "the destination.");
+ } else if (error_kind == ERROR_NOT_WRITABLE) {
+ error_string = _("Error while creating links in \"%s\".\n"
+ "The destination is not writable.");
+ }
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ }
+ if (error_string != NULL) {
+ g_assert (target_name != NULL);
+ result = g_strdup_printf (error_string, target_name);
+ }
+ }
+
+ if (result == NULL) {
+ /* None of the specific error messages apply, use a catch-all
+ * generic error
+ */
+ if (source_name != NULL) {
+ switch (operation_kind) {
+ case XFER_COPY:
+ case XFER_DUPLICATE:
+ error_string = _("Error \"%s\" while copying \"%s\".\n"
"Would you like to continue?");
break;
case XFER_MOVE:
- error_string = _("Error \"%s\" while moving.\n"
+ error_string = _("Error \"%s\" while moving \"%s\".\n"
"Would you like to continue?");
break;
case XFER_LINK:
- error_string = _("Error \"%s\" while linking.\n"
+ error_string = _("Error \"%s\" while linking \"%s\".\n"
"Would you like to continue?");
break;
case XFER_DELETE:
case XFER_EMPTY_TRASH:
case XFER_MOVE_TO_TRASH:
- error_string = _("Error \"%s\" while deleting.\n"
+ error_string = _("Error \"%s\" while deleting \"%s\".\n"
"Would you like to continue?");
break;
default:
- error_string = "";
+ g_assert_not_reached ();
break;
}
- text = g_strdup_printf (error_string,
- gnome_vfs_result_to_string (progress_info->vfs_status));
+ result = g_strdup_printf (error_string,
+ gnome_vfs_result_to_string (error),
+ source_name);
} else {
-
- switch (xfer_info->kind) {
+ switch (operation_kind) {
case XFER_COPY:
case XFER_DUPLICATE:
- error_string = _("Error \"%s\" while copying \"%s\".\n"
+ error_string = _("Error \"%s\" while copying.\n"
"Would you like to continue?");
break;
case XFER_MOVE:
- error_string = _("Error \"%s\" while moving \"%s\".\n"
+ error_string = _("Error \"%s\" while moving.\n"
"Would you like to continue?");
break;
case XFER_LINK:
- error_string = _("Error \"%s\" while linking \"%s\".\n"
+ error_string = _("Error \"%s\" while linking.\n"
"Would you like to continue?");
break;
case XFER_DELETE:
case XFER_EMPTY_TRASH:
case XFER_MOVE_TO_TRASH:
- error_string = _("Error \"%s\" while deleting \"%s\".\n"
+ error_string = _("Error \"%s\" while deleting.\n"
"Would you like to continue?");
break;
default:
- error_string = "";
+ g_assert_not_reached ();
break;
}
- text = g_strdup_printf (error_string,
- gnome_vfs_result_to_string (progress_info->vfs_status),
- unescaped_name);
+ result = g_strdup_printf (error_string,
+ gnome_vfs_result_to_string (error));
}
- g_free (unescaped_name);
+ }
+ return result;
+}
- result = nautilus_simple_dialog
- (parent_for_error_dialog (xfer_info), TRUE, text,
- dialog_title,
- _("Skip"), _("Retry"), _("Stop"), NULL);
+static int
+handle_xfer_vfs_error (const GnomeVFSXferProgressInfo *progress_info,
+ XferInfo *xfer_info)
+{
+ /* Notice that the error mode in `xfer_info' is the one we have been
+ * requested, but the transfer is always performed in mode
+ * `GNOME_VFS_XFER_ERROR_MODE_QUERY'.
+ */
- g_free (text);
+ int error_dialog_button_pressed;
+ int error_dialog_result;
+ char *text;
+ char *unescaped_source_name;
+ char *unescaped_target_name;
+ const char *dialog_title;
+ NautilusFileOperationsErrorKind error_kind;
+ NautilusFileOperationsErrorLocation error_location;
+
+ switch (xfer_info->error_mode) {
+ case GNOME_VFS_XFER_ERROR_MODE_QUERY:
+
+ /* transfer error, prompt the user to continue or stop */
+
+ unescaped_source_name = NULL;
+ unescaped_target_name = NULL;
+
+ if (progress_info->source_name != NULL) {
+ unescaped_source_name = nautilus_format_name_for_display
+ (progress_info->source_name);
+ }
+
+ if (progress_info->target_name != NULL) {
+ unescaped_target_name = nautilus_format_name_for_display
+ (progress_info->target_name);
+ }
+
+ error_kind = ERROR_OTHER;
+ error_location = ERROR_LOCATION_UNKNOWN;
- switch (result) {
- case 0:
- return GNOME_VFS_XFER_ERROR_ACTION_SKIP;
- case 1:
- return GNOME_VFS_XFER_ERROR_ACTION_RETRY;
+ /* Single out a few common error conditions for which we have
+ * custom-taylored error messages.
+ */
+ if ((progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM
+ || progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY)
+ && (xfer_info->kind == XFER_DELETE
+ || xfer_info->kind == XFER_EMPTY_TRASH)) {
+ error_location = ERROR_LOCATION_SOURCE_PARENT;
+ error_kind = ERROR_READ_ONLY;
+ } else if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED
+ && (xfer_info->kind == XFER_DELETE
+ || xfer_info->kind == XFER_EMPTY_TRASH)) {
+ error_location = ERROR_LOCATION_SOURCE_PARENT;
+ error_kind = ERROR_NOT_ENOUGH_PERMISSIONS;
+ } else if ((progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM
+ || progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY)
+ && (xfer_info->kind == XFER_MOVE
+ || xfer_info->kind == XFER_MOVE_TO_TRASH)
+ && progress_info->phase != GNOME_VFS_XFER_CHECKING_DESTINATION) {
+ error_location = ERROR_LOCATION_SOURCE_PARENT;
+ error_kind = ERROR_READ_ONLY;
+ } else if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED
+ && (xfer_info->kind == XFER_MOVE
+ || xfer_info->kind == XFER_MOVE_TO_TRASH)
+ && progress_info->phase != GNOME_VFS_XFER_CHECKING_DESTINATION) {
+ error_location = ERROR_LOCATION_SOURCE_OR_PARENT;
+ error_kind = ERROR_NOT_ENOUGH_PERMISSIONS;
+ } else if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED
+ && (xfer_info->kind == XFER_COPY
+ || xfer_info->kind == XFER_DUPLICATE)
+ && (progress_info->phase == GNOME_VFS_XFER_PHASE_OPENSOURCE
+ || progress_info->phase == GNOME_VFS_XFER_PHASE_COLLECTING
+ || progress_info->phase == GNOME_VFS_XFER_PHASE_INITIAL)) {
+ error_location = ERROR_LOCATION_SOURCE;
+ error_kind = ERROR_NOT_READABLE;
+ } else if ((progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM
+ || progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY)
+ && progress_info->phase == GNOME_VFS_XFER_CHECKING_DESTINATION) {
+ error_location = ERROR_LOCATION_TARGET;
+ error_kind = ERROR_NOT_WRITABLE;
+ } else if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED
+ && progress_info->phase == GNOME_VFS_XFER_CHECKING_DESTINATION) {
+ error_location = ERROR_LOCATION_TARGET;
+ error_kind = ERROR_NOT_ENOUGH_PERMISSIONS;
+ } else if (progress_info->vfs_status == GNOME_VFS_ERROR_NO_SPACE) {
+ error_location = ERROR_LOCATION_TARGET;
+ error_kind = ERROR_NO_SPACE;
+ }
+
+ text = build_error_string (unescaped_source_name, unescaped_target_name,
+ xfer_info->kind, error_kind, error_location, progress_info->vfs_status);
+
+ switch (xfer_info->kind) {
+ case XFER_COPY:
+ case XFER_DUPLICATE:
+ dialog_title = _("Error while copying.");
+ break;
+ case XFER_MOVE:
+ dialog_title = _("Error while moving.");
+ break;
+ case XFER_LINK:
+ dialog_title = _("Error while linking.");
+ break;
+ case XFER_DELETE:
+ case XFER_EMPTY_TRASH:
+ case XFER_MOVE_TO_TRASH:
+ dialog_title = _("Error while deleting.");
+ break;
default:
- g_assert_not_reached ();
- /* fall through */
- case 2:
- return GNOME_VFS_XFER_ERROR_ACTION_ABORT;
- }
+ dialog_title = NULL;
+ break;
+ }
+ if (error_location == ERROR_LOCATION_TARGET) {
+ /* We can't continue, just tell the user. */
+ nautilus_simple_dialog (parent_for_error_dialog (xfer_info),
+ TRUE, text, dialog_title, _("Stop"), NULL);
+ error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_ABORT;
+
+ } else if ((error_location == ERROR_LOCATION_SOURCE
+ || error_location == ERROR_LOCATION_SOURCE_PARENT
+ || error_location == ERROR_LOCATION_SOURCE_OR_PARENT)
+ && (error_kind == ERROR_NOT_ENOUGH_PERMISSIONS
+ || error_kind == ERROR_NOT_READABLE)) {
+ /* The error could have happened on any of the files
+ * in the moved/copied/deleted hierarchy, we can probably
+ * continue. Allow the user to skip.
+ */
+ error_dialog_button_pressed = nautilus_simple_dialog
+ (parent_for_error_dialog (xfer_info), TRUE, text,
+ dialog_title,
+ _("Skip"), _("Stop"), NULL);
+
+ switch (error_dialog_button_pressed) {
+ case 0:
+ error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_SKIP;
+ break;
+ case 1:
+ error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_ABORT;
+ break;
+ default:
+ g_assert_not_reached ();
+ error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_ABORT;
+ }
+
+ } else {
+ /* Generic error, offer to retry and skip. */
+ error_dialog_button_pressed = nautilus_simple_dialog
+ (parent_for_error_dialog (xfer_info), TRUE, text,
+ dialog_title,
+ _("Skip"), _("Retry"), _("Stop"), NULL);
+
+ switch (error_dialog_button_pressed) {
+ case 0:
+ error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_SKIP;
+ break;
+ case 1:
+ error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_RETRY;
+ break;
+ case 2:
+ error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_ABORT;
+ break;
+ default:
+ g_assert_not_reached ();
+ error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_ABORT;
+ }
+ }
+
+ g_free (text);
+ return error_dialog_result;
case GNOME_VFS_XFER_ERROR_MODE_ABORT:
default:
@@ -1946,24 +2060,11 @@ nautilus_file_operations_delete (const GList *item_uris,
static void
do_empty_trash (GtkWidget *parent_view)
{
- GnomeVFSURI *trash_dir_uri;
- GnomeVFSResult result;
XferInfo *xfer_info;
GList *trash_dir_list;
- /* FIXME bugzilla.eazel.com 638:
- * add the different trash directories from the different volumes
- */
-
- trash_dir_uri = NULL;
- trash_dir_list = NULL;
-
- result = gnome_vfs_find_directory (NULL, GNOME_VFS_DIRECTORY_KIND_TRASH,
- &trash_dir_uri, FALSE, FALSE, 0777);
-
- if (result == GNOME_VFS_OK) {
- g_assert (trash_dir_uri != NULL);
-
+ trash_dir_list = nautilus_trash_monitor_get_trash_directories ();
+ if (trash_dir_list != NULL) {
/* set up the move parameters */
xfer_info = g_new0 (XferInfo, 1);
xfer_info->parent_view = parent_view;
@@ -1982,8 +2083,6 @@ do_empty_trash (GtkWidget *parent_view)
xfer_info->overwrite_mode = GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE;
xfer_info->kind = XFER_EMPTY_TRASH;
- trash_dir_list = g_list_append (NULL, trash_dir_uri);
-
gnome_vfs_async_xfer (&xfer_info->handle, trash_dir_list, NULL,
GNOME_VFS_XFER_EMPTY_DIRECTORIES,
GNOME_VFS_XFER_ERROR_MODE_QUERY,
diff --git a/libnautilus-extensions/nautilus-trash-directory.c b/libnautilus-extensions/nautilus-trash-directory.c
index 01d38f7e3..0e7210881 100644
--- a/libnautilus-extensions/nautilus-trash-directory.c
+++ b/libnautilus-extensions/nautilus-trash-directory.c
@@ -55,32 +55,6 @@ NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusTrashDirectory,
nautilus_trash_directory,
NAUTILUS_TYPE_MERGED_DIRECTORY)
-static GnomeVFSURI *
-get_volume_vfs_uri_if_writable (NautilusVolume *volume)
-{
- char *uri;
- GnomeVFSURI *vfs_uri;
-
- /* FIXME bugzilla.eazel.com 2443:
- * Why is trash only found on EXT2 volumes? This seems
- * like an incorrect check.
- */
-
- /* FIXME bugzilla.eazel.com 2444:
- * Why can't we view the trash on a read-only volume
- * if it happens to be there?
- */
- if (volume->type != NAUTILUS_VOLUME_EXT2 || volume->is_read_only) {
- return NULL;
- }
-
- uri = gnome_vfs_get_uri_from_local_path (volume->mount_path);
- vfs_uri = gnome_vfs_uri_new (uri);
- g_free (uri);
-
- return vfs_uri;
-}
-
static void
find_directory_callback (GnomeVFSAsyncHandle *handle,
GList *results,
@@ -129,7 +103,7 @@ add_volume (NautilusTrashDirectory *trash,
NautilusVolume *volume)
{
TrashVolume *trash_volume;
- GnomeVFSURI *vfs_uri;
+ GnomeVFSURI *volume_mount_uri;
GList vfs_uri_as_list;
/* Quick out if we already know about this volume. */
@@ -139,11 +113,12 @@ add_volume (NautilusTrashDirectory *trash,
return;
}
- /* If we can't get the URI, we jus don't do trash on this volume. */
- vfs_uri = get_volume_vfs_uri_if_writable (volume);
- if (vfs_uri == NULL) {
+ if (!nautilus_volume_monitor_should_integrate_trash (volume)) {
return;
}
+
+ volume_mount_uri = gnome_vfs_uri_new (
+ nautilus_volume_monitor_get_volume_mount_uri (volume));
/* Make the structure used to track the trash for this volume. */
trash_volume = g_new0 (TrashVolume, 1);
@@ -152,7 +127,7 @@ add_volume (NautilusTrashDirectory *trash,
g_hash_table_insert (trash->details->volumes, volume, trash_volume);
/* Find the real trash directory for this one. */
- vfs_uri_as_list.data = vfs_uri;
+ vfs_uri_as_list.data = volume_mount_uri;
vfs_uri_as_list.next = NULL;
vfs_uri_as_list.prev = NULL;
/* Search for Trash directories but don't create new ones. */
diff --git a/libnautilus-extensions/nautilus-trash-monitor.c b/libnautilus-extensions/nautilus-trash-monitor.c
index b70a565da..aca0a9d29 100644
--- a/libnautilus-extensions/nautilus-trash-monitor.c
+++ b/libnautilus-extensions/nautilus-trash-monitor.c
@@ -187,3 +187,57 @@ nautilus_trash_monitor_is_empty (void)
{
return nautilus_trash_monitor_get ()->details->empty;
}
+
+static gboolean
+add_one_volume_trash (const NautilusVolume *volume,
+ gpointer callback_data)
+{
+ GnomeVFSURI *volume_mount_point_uri;
+ GnomeVFSURI *trash_uri;
+ GList **result;
+
+ result = (GList **)callback_data;
+
+ if (nautilus_volume_monitor_should_integrate_trash (volume)) {
+
+ /* Get the uri of the volume mount point as the place
+ * "near" which to look for trash on the given volume.
+ */
+ volume_mount_point_uri = gnome_vfs_uri_new (
+ nautilus_volume_monitor_get_volume_mount_uri (volume));
+
+ g_assert (volume_mount_point_uri != NULL);
+
+ /* Look for trash. It is OK to use a sync call here because
+ * the options we use (don't create, don't look for it if we
+ * already don't know where it is) do not cause any IO.
+ */
+ if (gnome_vfs_find_directory (volume_mount_point_uri,
+ GNOME_VFS_DIRECTORY_KIND_TRASH, &trash_uri,
+ FALSE, FALSE, 0777) == GNOME_VFS_OK) {
+
+ /* found trash, put it on the list */
+ *result = g_list_append (*result, trash_uri);
+ }
+
+ gnome_vfs_uri_unref (volume_mount_point_uri);
+ }
+
+ /* don't stop iterating */
+ return FALSE;
+}
+
+GList *
+nautilus_trash_monitor_get_trash_directories (void)
+{
+ GList *result;
+
+ result = NULL;
+
+ /* Collect the trash directories on all the mounted volumes. */
+ nautilus_volume_monitor_each_mounted_volume
+ (nautilus_volume_monitor_get (), add_one_volume_trash, &result);
+
+ return result;
+}
+
diff --git a/libnautilus-extensions/nautilus-trash-monitor.h b/libnautilus-extensions/nautilus-trash-monitor.h
index 19139d514..41c726dcc 100644
--- a/libnautilus-extensions/nautilus-trash-monitor.h
+++ b/libnautilus-extensions/nautilus-trash-monitor.h
@@ -60,7 +60,6 @@ GtkType nautilus_trash_monitor_get_type (void);
NautilusTrashMonitor *nautilus_trash_monitor_get (void);
gboolean nautilus_trash_monitor_is_empty (void);
-void nautilus_trash_monitor_async_get_trash_directories (GnomeVFSAsyncFindDirectoryCallback callback,
- gpointer context);
+GList * nautilus_trash_monitor_get_trash_directories (void);
#endif
diff --git a/libnautilus-extensions/nautilus-volume-monitor.c b/libnautilus-extensions/nautilus-volume-monitor.c
index 0a75b3c03..dfd98d045 100644
--- a/libnautilus-extensions/nautilus-volume-monitor.c
+++ b/libnautilus-extensions/nautilus-volume-monitor.c
@@ -318,6 +318,28 @@ nautilus_volume_monitor_volume_is_mounted (const NautilusVolume *volume)
return FALSE;
}
+gboolean
+nautilus_volume_monitor_should_integrate_trash (const NautilusVolume *volume)
+{
+ /* Hand-pick a bunch of file system types that we know we can support
+ * trash on. It would probably be harder to keep a list of the ones
+ * we can't try to support trash on because the list would have to be
+ * more definitive.
+ */
+ return volume->type == NAUTILUS_VOLUME_EXT2
+ || volume->type == NAUTILUS_VOLUME_FAT
+ || volume->type == NAUTILUS_VOLUME_NFS
+ || volume->type == NAUTILUS_VOLUME_VFAT
+ || volume->type == NAUTILUS_VOLUME_FLOPPY
+ || volume->type == NAUTILUS_VOLUME_SMB;
+}
+
+const char *
+nautilus_volume_monitor_get_volume_mount_uri (const NautilusVolume *volume)
+{
+ return volume->mount_path;
+}
+
static void
mount_volume_cdrom_set_state (NautilusVolumeMonitor *monitor, NautilusVolume *volume)
{
diff --git a/libnautilus-extensions/nautilus-volume-monitor.h b/libnautilus-extensions/nautilus-volume-monitor.h
index 08984fc65..d376e3b08 100644
--- a/libnautilus-extensions/nautilus-volume-monitor.h
+++ b/libnautilus-extensions/nautilus-volume-monitor.h
@@ -111,6 +111,8 @@ gboolean nautilus_volume_monitor_is_volume_link (con
void nautilus_volume_monitor_each_volume (NautilusVolumeMonitor *monitor,
NautilusEachVolumeFunction function,
gpointer context);
+gboolean nautilus_volume_monitor_should_integrate_trash (const NautilusVolume *volume);
+const char *nautilus_volume_monitor_get_volume_mount_uri (const NautilusVolume *volume);
void nautilus_volume_monitor_each_mounted_volume (NautilusVolumeMonitor *monitor,
NautilusEachVolumeFunction function,
gpointer context);
diff --git a/libnautilus-private/nautilus-file-operations.c b/libnautilus-private/nautilus-file-operations.c
index bda30ff96..a73fc78b0 100644
--- a/libnautilus-private/nautilus-file-operations.c
+++ b/libnautilus-private/nautilus-file-operations.c
@@ -44,6 +44,7 @@
#include <libnautilus-extensions/nautilus-global-preferences.h>
#include <libnautilus-extensions/nautilus-link.h>
#include <libnautilus-extensions/nautilus-stock-dialogs.h>
+#include <libnautilus-extensions/nautilus-trash-monitor.h>
typedef enum {
XFER_MOVE,
@@ -467,338 +468,451 @@ handle_xfer_ok (const GnomeVFSXferProgressInfo *progress_info,
}
}
+typedef enum {
+ ERROR_READ_ONLY,
+ ERROR_NOT_READABLE,
+ ERROR_NOT_WRITABLE,
+ ERROR_NOT_ENOUGH_PERMISSIONS,
+ ERROR_NO_SPACE,
+ ERROR_OTHER
+} NautilusFileOperationsErrorKind;
-static int
-handle_xfer_vfs_error (const GnomeVFSXferProgressInfo *progress_info,
- XferInfo *xfer_info)
+typedef enum {
+ ERROR_LOCATION_UNKNOWN,
+ ERROR_LOCATION_SOURCE,
+ ERROR_LOCATION_SOURCE_PARENT,
+ ERROR_LOCATION_SOURCE_OR_PARENT,
+ ERROR_LOCATION_TARGET
+} NautilusFileOperationsErrorLocation;
+
+
+static char *
+build_error_string (const char *source_name, const char *target_name,
+ XferKind operation_kind, NautilusFileOperationsErrorKind error_kind,
+ NautilusFileOperationsErrorLocation error_location, GnomeVFSResult error)
{
- /* Notice that the error mode in `xfer_info' is the one we have been
- * requested, but the transfer is always performed in mode
- * `GNOME_VFS_XFER_ERROR_MODE_QUERY'.
- */
+ /* Avoid clever message composing here, just use brute force and
+ * duplicate the different flavors of error messages for all the
+ * possible permutations.
+ * That way localizers have an easier time and can even rearrange the
+ * order of the words in the messages easily.
+ */
- int result;
- char *text;
- char *unescaped_name;
- const char *dialog_title;
const char *error_string;
+ char *result;
- switch (xfer_info->error_mode) {
- case GNOME_VFS_XFER_ERROR_MODE_QUERY:
+ error_string = NULL;
+ result = NULL;
- /* transfer error, prompt the user to continue or stop */
+ if (error_location == ERROR_LOCATION_SOURCE_PARENT) {
- unescaped_name = NULL;
+ switch (operation_kind) {
+ case XFER_MOVE:
+ case XFER_MOVE_TO_TRASH:
+ if (error_kind == ERROR_NOT_ENOUGH_PERMISSIONS) {
+ error_string = _("Error while moving.\n"
+ "\"%s\" cannot be moved because you do not have "
+ "permissions to change its parent folder.");
+ } else if (error_kind == ERROR_READ_ONLY) {
+ error_string = _("Error while moving.\n"
+ "\"%s\" cannot be moved because its parent folder "
+ "is read-only.");
+ } else if (error_kind == ERROR_NOT_WRITABLE) {
+ error_string = _("Error while moving.\n"
+ "\"%s\" cannot be moved because its parent folder "
+ "is not writable.");
+ }
+ break;
- if (progress_info->source_name != NULL) {
- unescaped_name = nautilus_format_name_for_display (progress_info->source_name);
+ case XFER_DELETE:
+ case XFER_EMPTY_TRASH:
+ if (error_kind == ERROR_NOT_ENOUGH_PERMISSIONS) {
+ error_string = _("Error while deleting.\n"
+ "\"%s\" cannot be deleted because you do not have "
+ "permissions to change its parent folder.");
+ } else if (error_kind == ERROR_READ_ONLY) {
+ error_string = _("Error while deleting.\n"
+ "\"%s\" cannot be deleted because its parent folder "
+ "is read-only.");
+ } else if (error_kind == ERROR_NOT_WRITABLE) {
+ error_string = _("Error while moving.\n"
+ "\"%s\" cannot be moved because its parent folder "
+ "is not writable.");
+ }
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ if (error_string != NULL) {
+ g_assert (source_name != NULL);
+ result = g_strdup_printf (error_string, source_name);
}
- /* Resist the temptation to do clever message composing here, just
- * use brute force and duplicate the different flavors of error messages.
- * That way localizers have an easier time and can even rearrange the
- * order of the words in the messages easily.
- */
+ } else if (error_location == ERROR_LOCATION_SOURCE_OR_PARENT) {
- switch (xfer_info->kind) {
- case XFER_COPY:
- case XFER_DUPLICATE:
- dialog_title = _("Error while copying.");
- break;
+ g_assert (source_name != NULL);
+
+ switch (operation_kind) {
case XFER_MOVE:
- dialog_title = _("Error while moving.");
- break;
- case XFER_LINK:
- dialog_title = _("Error while linking.");
+ if (error_kind == ERROR_NOT_ENOUGH_PERMISSIONS) {
+ error_string = _("Error while moving.\n"
+ "\"%s\" cannot be moved because you do not have "
+ "permissions to change it or its parent folder.");
+ }
break;
- case XFER_DELETE:
- case XFER_EMPTY_TRASH:
case XFER_MOVE_TO_TRASH:
- dialog_title = _("Error while deleting.");
+ if (error_kind == ERROR_NOT_ENOUGH_PERMISSIONS) {
+ error_string = _("Error while moving.\n"
+ "\"%s\" cannot be moved to trash because you do not have "
+ "permissions to change it or its parent folder.");
+ }
break;
+
default:
- dialog_title = NULL;
+ g_assert_not_reached ();
break;
}
- /* special case read only target errors or non-readable sources
- * and other predictable failures
- */
-
- if (progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM
- || progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY
- || progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED) {
-
- if ((xfer_info->kind == XFER_MOVE || xfer_info->kind == XFER_MOVE_TO_TRASH)
- && progress_info->phase != GNOME_VFS_XFER_CHECKING_DESTINATION) {
- /* we are failing because we are moving from a directory that
- * is not writable
- */
- if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED) {
- error_string = _("Error while moving.\n"
- "%s cannot be moved because you do not have "
- "permissions to change it's parent folder.");
- } else {
- error_string = _("Error while moving.\n"
- "%s cannot be moved because its parent folder "
- "is read-only.");
- }
- } else if (progress_info->phase == GNOME_VFS_XFER_PHASE_OPENSOURCE
- || progress_info->phase == GNOME_VFS_XFER_PHASE_COLLECTING
- || progress_info->phase == GNOME_VFS_XFER_PHASE_INITIAL) {
-
- if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED) {
- switch (xfer_info->kind) {
- case XFER_COPY:
- case XFER_DUPLICATE:
- error_string = _("Error while copying.\n"
- "You do not have permissions to read %s.");
- break;
- case XFER_MOVE:
- error_string = _("Error while moving.\n"
- "You do not have permissions to read %s.");
- break;
- case XFER_LINK:
- error_string = _("Error while linking.\n"
- "You do not have permissions to read %s.");
- break;
- case XFER_DELETE:
- case XFER_EMPTY_TRASH:
- case XFER_MOVE_TO_TRASH:
- error_string = _("Error while deleting.\n"
- "You do not have permissions to read %s.");
- break;
- default:
- error_string = "";
- break;
- }
- } else {
- switch (xfer_info->kind) {
- case XFER_COPY:
- case XFER_DUPLICATE:
- error_string = _("Error while copying.\n"
- "%s is not readable.");
- break;
- case XFER_MOVE:
- error_string = _("Error while moving.\n"
- "%s is not readable.");
- break;
- case XFER_LINK:
- error_string = _("Error while linking.\n"
- "%s is not readable.");
- break;
- case XFER_DELETE:
- case XFER_EMPTY_TRASH:
- case XFER_MOVE_TO_TRASH:
- error_string = _("Error while deleting.\n"
- "%s is not readable.");
- break;
- default:
- error_string = "";
- break;
- }
- }
+ if (error_string != NULL) {
+ g_assert (source_name != NULL);
+ result = g_strdup_printf (error_string, source_name);
+ }
- } else {
- if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED) {
- switch (xfer_info->kind) {
- case XFER_COPY:
- case XFER_DUPLICATE:
- error_string = _("Error while copying items to \"%s\".\n"
- "You do not have permissions to write to the destination.");
- break;
- case XFER_MOVE_TO_TRASH:
- case XFER_MOVE:
- error_string = _("Error while moving items to \"%s\".\n"
- "You do not have permissions to write to the destination.");
- break;
- case XFER_LINK:
- error_string = _("Error while linking items to \"%s\".\n"
- "You do not have permissions to write to the destination.");
- break;
- default:
- g_assert_not_reached ();
- error_string = "";
- break;
- }
- } else {
- switch (xfer_info->kind) {
- case XFER_COPY:
- case XFER_DUPLICATE:
- error_string = _("Error while copying items to \"%s\".\n"
- "The destination is not writable.");
- break;
- case XFER_MOVE_TO_TRASH:
- case XFER_MOVE:
- error_string = _("Error while moving items to \"%s\".\n"
- "The destination is not writable.");
- break;
- case XFER_LINK:
- error_string = _("Error while linking items to \"%s\".\n"
- "The destination is not writable.");
- break;
- default:
- g_assert_not_reached ();
- error_string = "";
- break;
- }
- }
+ } else if (error_location == ERROR_LOCATION_SOURCE) {
- if (progress_info->target_name != NULL) {
- g_free (unescaped_name);
- unescaped_name = nautilus_format_name_for_display (
- progress_info->target_name);
- }
+ g_assert (source_name != NULL);
+
+ switch (operation_kind) {
+ case XFER_COPY:
+ case XFER_DUPLICATE:
+ if (error_kind == ERROR_NOT_READABLE) {
+ error_string = _("Error while copying.\n"
+ "\"%s\" is not readable.");
}
- text = g_strdup_printf (error_string, unescaped_name);
- g_free (unescaped_name);
-
- result = nautilus_simple_dialog
- (parent_for_error_dialog (xfer_info), TRUE, text,
- dialog_title, _("Stop"), NULL);
- g_free (text);
+ break;
+ case XFER_LINK:
+ if (error_kind == ERROR_NOT_READABLE) {
+ error_string = _("Error while linking\n"
+ "\"%s\" is not readable.");
+ }
+ break;
- return GNOME_VFS_XFER_ERROR_ACTION_ABORT;
+ default:
+ g_assert_not_reached ();
+ break;
}
- /* special case read only target errors */
- if (progress_info->vfs_status == GNOME_VFS_ERROR_NO_SPACE) {
-
- if (unescaped_name != NULL) {
- switch (xfer_info->kind) {
- case XFER_COPY:
- case XFER_DUPLICATE:
- error_string = _("Error while copying \"%s\".\n"
- "There is no space on the destination.");
- break;
- case XFER_MOVE_TO_TRASH:
- case XFER_MOVE:
- error_string = _("Error while moving \"%s\".\n"
- "There is no space on the destination.");
- break;
- case XFER_LINK:
- error_string = _("Error while linking \"%s\".\n"
- "There is no space on the destination.");
- break;
- default:
- g_assert_not_reached ();
- error_string = "";
- break;
- }
- text = g_strdup (error_string);
- } else {
- switch (xfer_info->kind) {
- case XFER_COPY:
- case XFER_DUPLICATE:
- error_string = _("Error while copying.\n"
- "There is no space on the destination.");
- break;
- case XFER_MOVE_TO_TRASH:
- case XFER_MOVE:
- error_string = _("Error while moving.\n"
- "There is no space on the destination.");
- break;
- case XFER_LINK:
- error_string = _("Error while linking.\n"
- "There is no space on the destination.");
- break;
- default:
- g_assert_not_reached ();
- error_string = "";
- break;
- }
- text = g_strdup_printf (error_string, unescaped_name);
- }
- g_free (unescaped_name);
-
- result = nautilus_simple_dialog
- (parent_for_error_dialog (xfer_info), TRUE, text,
- dialog_title, _("Stop"), NULL);
- g_free (text);
- return GNOME_VFS_XFER_ERROR_ACTION_ABORT;
+ if (error_string != NULL) {
+ g_assert (source_name != NULL);
+ result = g_strdup_printf (error_string, source_name);
}
- if (unescaped_name != NULL) {
-
- switch (xfer_info->kind) {
+ } else if (error_location == ERROR_LOCATION_TARGET) {
+
+ if (error_kind == ERROR_NO_SPACE) {
+ switch (operation_kind) {
case XFER_COPY:
case XFER_DUPLICATE:
- error_string = _("Error \"%s\" while copying.\n"
+ error_string = _("Error while copying \"%s\".\n"
+ "There is no space on the destination.");
+ break;
+ case XFER_MOVE_TO_TRASH:
+ case XFER_MOVE:
+ error_string = _("Error while moving \"%s\".\n"
+ "There is no space on the destination.");
+ break;
+ case XFER_LINK:
+ error_string = _("Error while linking \"%s\".\n"
+ "There is no space on the destination.");
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ } else {
+ switch (operation_kind) {
+ case XFER_COPY:
+ case XFER_DUPLICATE:
+ if (error_kind == ERROR_NOT_ENOUGH_PERMISSIONS) {
+ error_string = _("Error while copying items to \"%s\".\n"
+ "You do not have permissions to write to "
+ "the destination.");
+ } else if (error_kind == ERROR_NOT_WRITABLE) {
+ error_string = _("Error while copying items to \"%s\".\n"
+ "The destination is not writable.");
+ }
+ break;
+ case XFER_MOVE:
+ case XFER_MOVE_TO_TRASH:
+ if (error_kind == ERROR_NOT_ENOUGH_PERMISSIONS) {
+ error_string = _("Error while moving items \"%s\".\n"
+ "You do not have permissions to write to "
+ "the destination.");
+ } else if (error_kind == ERROR_NOT_WRITABLE) {
+ error_string = _("Error while moving items \"%s\".\n"
+ "The destination is not writable.");
+ }
+
+ break;
+ case XFER_LINK:
+ if (error_kind == ERROR_NOT_ENOUGH_PERMISSIONS) {
+ error_string = _("Error while creating links in \"%s\".\n"
+ "You do not have permissions to write to "
+ "the destination.");
+ } else if (error_kind == ERROR_NOT_WRITABLE) {
+ error_string = _("Error while creating links in \"%s\".\n"
+ "The destination is not writable.");
+ }
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ }
+ if (error_string != NULL) {
+ g_assert (target_name != NULL);
+ result = g_strdup_printf (error_string, target_name);
+ }
+ }
+
+ if (result == NULL) {
+ /* None of the specific error messages apply, use a catch-all
+ * generic error
+ */
+ if (source_name != NULL) {
+ switch (operation_kind) {
+ case XFER_COPY:
+ case XFER_DUPLICATE:
+ error_string = _("Error \"%s\" while copying \"%s\".\n"
"Would you like to continue?");
break;
case XFER_MOVE:
- error_string = _("Error \"%s\" while moving.\n"
+ error_string = _("Error \"%s\" while moving \"%s\".\n"
"Would you like to continue?");
break;
case XFER_LINK:
- error_string = _("Error \"%s\" while linking.\n"
+ error_string = _("Error \"%s\" while linking \"%s\".\n"
"Would you like to continue?");
break;
case XFER_DELETE:
case XFER_EMPTY_TRASH:
case XFER_MOVE_TO_TRASH:
- error_string = _("Error \"%s\" while deleting.\n"
+ error_string = _("Error \"%s\" while deleting \"%s\".\n"
"Would you like to continue?");
break;
default:
- error_string = "";
+ g_assert_not_reached ();
break;
}
- text = g_strdup_printf (error_string,
- gnome_vfs_result_to_string (progress_info->vfs_status));
+ result = g_strdup_printf (error_string,
+ gnome_vfs_result_to_string (error),
+ source_name);
} else {
-
- switch (xfer_info->kind) {
+ switch (operation_kind) {
case XFER_COPY:
case XFER_DUPLICATE:
- error_string = _("Error \"%s\" while copying \"%s\".\n"
+ error_string = _("Error \"%s\" while copying.\n"
"Would you like to continue?");
break;
case XFER_MOVE:
- error_string = _("Error \"%s\" while moving \"%s\".\n"
+ error_string = _("Error \"%s\" while moving.\n"
"Would you like to continue?");
break;
case XFER_LINK:
- error_string = _("Error \"%s\" while linking \"%s\".\n"
+ error_string = _("Error \"%s\" while linking.\n"
"Would you like to continue?");
break;
case XFER_DELETE:
case XFER_EMPTY_TRASH:
case XFER_MOVE_TO_TRASH:
- error_string = _("Error \"%s\" while deleting \"%s\".\n"
+ error_string = _("Error \"%s\" while deleting.\n"
"Would you like to continue?");
break;
default:
- error_string = "";
+ g_assert_not_reached ();
break;
}
- text = g_strdup_printf (error_string,
- gnome_vfs_result_to_string (progress_info->vfs_status),
- unescaped_name);
+ result = g_strdup_printf (error_string,
+ gnome_vfs_result_to_string (error));
}
- g_free (unescaped_name);
+ }
+ return result;
+}
- result = nautilus_simple_dialog
- (parent_for_error_dialog (xfer_info), TRUE, text,
- dialog_title,
- _("Skip"), _("Retry"), _("Stop"), NULL);
+static int
+handle_xfer_vfs_error (const GnomeVFSXferProgressInfo *progress_info,
+ XferInfo *xfer_info)
+{
+ /* Notice that the error mode in `xfer_info' is the one we have been
+ * requested, but the transfer is always performed in mode
+ * `GNOME_VFS_XFER_ERROR_MODE_QUERY'.
+ */
- g_free (text);
+ int error_dialog_button_pressed;
+ int error_dialog_result;
+ char *text;
+ char *unescaped_source_name;
+ char *unescaped_target_name;
+ const char *dialog_title;
+ NautilusFileOperationsErrorKind error_kind;
+ NautilusFileOperationsErrorLocation error_location;
+
+ switch (xfer_info->error_mode) {
+ case GNOME_VFS_XFER_ERROR_MODE_QUERY:
+
+ /* transfer error, prompt the user to continue or stop */
+
+ unescaped_source_name = NULL;
+ unescaped_target_name = NULL;
+
+ if (progress_info->source_name != NULL) {
+ unescaped_source_name = nautilus_format_name_for_display
+ (progress_info->source_name);
+ }
+
+ if (progress_info->target_name != NULL) {
+ unescaped_target_name = nautilus_format_name_for_display
+ (progress_info->target_name);
+ }
+
+ error_kind = ERROR_OTHER;
+ error_location = ERROR_LOCATION_UNKNOWN;
- switch (result) {
- case 0:
- return GNOME_VFS_XFER_ERROR_ACTION_SKIP;
- case 1:
- return GNOME_VFS_XFER_ERROR_ACTION_RETRY;
+ /* Single out a few common error conditions for which we have
+ * custom-taylored error messages.
+ */
+ if ((progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM
+ || progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY)
+ && (xfer_info->kind == XFER_DELETE
+ || xfer_info->kind == XFER_EMPTY_TRASH)) {
+ error_location = ERROR_LOCATION_SOURCE_PARENT;
+ error_kind = ERROR_READ_ONLY;
+ } else if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED
+ && (xfer_info->kind == XFER_DELETE
+ || xfer_info->kind == XFER_EMPTY_TRASH)) {
+ error_location = ERROR_LOCATION_SOURCE_PARENT;
+ error_kind = ERROR_NOT_ENOUGH_PERMISSIONS;
+ } else if ((progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM
+ || progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY)
+ && (xfer_info->kind == XFER_MOVE
+ || xfer_info->kind == XFER_MOVE_TO_TRASH)
+ && progress_info->phase != GNOME_VFS_XFER_CHECKING_DESTINATION) {
+ error_location = ERROR_LOCATION_SOURCE_PARENT;
+ error_kind = ERROR_READ_ONLY;
+ } else if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED
+ && (xfer_info->kind == XFER_MOVE
+ || xfer_info->kind == XFER_MOVE_TO_TRASH)
+ && progress_info->phase != GNOME_VFS_XFER_CHECKING_DESTINATION) {
+ error_location = ERROR_LOCATION_SOURCE_OR_PARENT;
+ error_kind = ERROR_NOT_ENOUGH_PERMISSIONS;
+ } else if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED
+ && (xfer_info->kind == XFER_COPY
+ || xfer_info->kind == XFER_DUPLICATE)
+ && (progress_info->phase == GNOME_VFS_XFER_PHASE_OPENSOURCE
+ || progress_info->phase == GNOME_VFS_XFER_PHASE_COLLECTING
+ || progress_info->phase == GNOME_VFS_XFER_PHASE_INITIAL)) {
+ error_location = ERROR_LOCATION_SOURCE;
+ error_kind = ERROR_NOT_READABLE;
+ } else if ((progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM
+ || progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY)
+ && progress_info->phase == GNOME_VFS_XFER_CHECKING_DESTINATION) {
+ error_location = ERROR_LOCATION_TARGET;
+ error_kind = ERROR_NOT_WRITABLE;
+ } else if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED
+ && progress_info->phase == GNOME_VFS_XFER_CHECKING_DESTINATION) {
+ error_location = ERROR_LOCATION_TARGET;
+ error_kind = ERROR_NOT_ENOUGH_PERMISSIONS;
+ } else if (progress_info->vfs_status == GNOME_VFS_ERROR_NO_SPACE) {
+ error_location = ERROR_LOCATION_TARGET;
+ error_kind = ERROR_NO_SPACE;
+ }
+
+ text = build_error_string (unescaped_source_name, unescaped_target_name,
+ xfer_info->kind, error_kind, error_location, progress_info->vfs_status);
+
+ switch (xfer_info->kind) {
+ case XFER_COPY:
+ case XFER_DUPLICATE:
+ dialog_title = _("Error while copying.");
+ break;
+ case XFER_MOVE:
+ dialog_title = _("Error while moving.");
+ break;
+ case XFER_LINK:
+ dialog_title = _("Error while linking.");
+ break;
+ case XFER_DELETE:
+ case XFER_EMPTY_TRASH:
+ case XFER_MOVE_TO_TRASH:
+ dialog_title = _("Error while deleting.");
+ break;
default:
- g_assert_not_reached ();
- /* fall through */
- case 2:
- return GNOME_VFS_XFER_ERROR_ACTION_ABORT;
- }
+ dialog_title = NULL;
+ break;
+ }
+ if (error_location == ERROR_LOCATION_TARGET) {
+ /* We can't continue, just tell the user. */
+ nautilus_simple_dialog (parent_for_error_dialog (xfer_info),
+ TRUE, text, dialog_title, _("Stop"), NULL);
+ error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_ABORT;
+
+ } else if ((error_location == ERROR_LOCATION_SOURCE
+ || error_location == ERROR_LOCATION_SOURCE_PARENT
+ || error_location == ERROR_LOCATION_SOURCE_OR_PARENT)
+ && (error_kind == ERROR_NOT_ENOUGH_PERMISSIONS
+ || error_kind == ERROR_NOT_READABLE)) {
+ /* The error could have happened on any of the files
+ * in the moved/copied/deleted hierarchy, we can probably
+ * continue. Allow the user to skip.
+ */
+ error_dialog_button_pressed = nautilus_simple_dialog
+ (parent_for_error_dialog (xfer_info), TRUE, text,
+ dialog_title,
+ _("Skip"), _("Stop"), NULL);
+
+ switch (error_dialog_button_pressed) {
+ case 0:
+ error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_SKIP;
+ break;
+ case 1:
+ error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_ABORT;
+ break;
+ default:
+ g_assert_not_reached ();
+ error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_ABORT;
+ }
+
+ } else {
+ /* Generic error, offer to retry and skip. */
+ error_dialog_button_pressed = nautilus_simple_dialog
+ (parent_for_error_dialog (xfer_info), TRUE, text,
+ dialog_title,
+ _("Skip"), _("Retry"), _("Stop"), NULL);
+
+ switch (error_dialog_button_pressed) {
+ case 0:
+ error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_SKIP;
+ break;
+ case 1:
+ error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_RETRY;
+ break;
+ case 2:
+ error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_ABORT;
+ break;
+ default:
+ g_assert_not_reached ();
+ error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_ABORT;
+ }
+ }
+
+ g_free (text);
+ return error_dialog_result;
case GNOME_VFS_XFER_ERROR_MODE_ABORT:
default:
@@ -1946,24 +2060,11 @@ nautilus_file_operations_delete (const GList *item_uris,
static void
do_empty_trash (GtkWidget *parent_view)
{
- GnomeVFSURI *trash_dir_uri;
- GnomeVFSResult result;
XferInfo *xfer_info;
GList *trash_dir_list;
- /* FIXME bugzilla.eazel.com 638:
- * add the different trash directories from the different volumes
- */
-
- trash_dir_uri = NULL;
- trash_dir_list = NULL;
-
- result = gnome_vfs_find_directory (NULL, GNOME_VFS_DIRECTORY_KIND_TRASH,
- &trash_dir_uri, FALSE, FALSE, 0777);
-
- if (result == GNOME_VFS_OK) {
- g_assert (trash_dir_uri != NULL);
-
+ trash_dir_list = nautilus_trash_monitor_get_trash_directories ();
+ if (trash_dir_list != NULL) {
/* set up the move parameters */
xfer_info = g_new0 (XferInfo, 1);
xfer_info->parent_view = parent_view;
@@ -1982,8 +2083,6 @@ do_empty_trash (GtkWidget *parent_view)
xfer_info->overwrite_mode = GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE;
xfer_info->kind = XFER_EMPTY_TRASH;
- trash_dir_list = g_list_append (NULL, trash_dir_uri);
-
gnome_vfs_async_xfer (&xfer_info->handle, trash_dir_list, NULL,
GNOME_VFS_XFER_EMPTY_DIRECTORIES,
GNOME_VFS_XFER_ERROR_MODE_QUERY,
diff --git a/libnautilus-private/nautilus-trash-directory.c b/libnautilus-private/nautilus-trash-directory.c
index 01d38f7e3..0e7210881 100644
--- a/libnautilus-private/nautilus-trash-directory.c
+++ b/libnautilus-private/nautilus-trash-directory.c
@@ -55,32 +55,6 @@ NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusTrashDirectory,
nautilus_trash_directory,
NAUTILUS_TYPE_MERGED_DIRECTORY)
-static GnomeVFSURI *
-get_volume_vfs_uri_if_writable (NautilusVolume *volume)
-{
- char *uri;
- GnomeVFSURI *vfs_uri;
-
- /* FIXME bugzilla.eazel.com 2443:
- * Why is trash only found on EXT2 volumes? This seems
- * like an incorrect check.
- */
-
- /* FIXME bugzilla.eazel.com 2444:
- * Why can't we view the trash on a read-only volume
- * if it happens to be there?
- */
- if (volume->type != NAUTILUS_VOLUME_EXT2 || volume->is_read_only) {
- return NULL;
- }
-
- uri = gnome_vfs_get_uri_from_local_path (volume->mount_path);
- vfs_uri = gnome_vfs_uri_new (uri);
- g_free (uri);
-
- return vfs_uri;
-}
-
static void
find_directory_callback (GnomeVFSAsyncHandle *handle,
GList *results,
@@ -129,7 +103,7 @@ add_volume (NautilusTrashDirectory *trash,
NautilusVolume *volume)
{
TrashVolume *trash_volume;
- GnomeVFSURI *vfs_uri;
+ GnomeVFSURI *volume_mount_uri;
GList vfs_uri_as_list;
/* Quick out if we already know about this volume. */
@@ -139,11 +113,12 @@ add_volume (NautilusTrashDirectory *trash,
return;
}
- /* If we can't get the URI, we jus don't do trash on this volume. */
- vfs_uri = get_volume_vfs_uri_if_writable (volume);
- if (vfs_uri == NULL) {
+ if (!nautilus_volume_monitor_should_integrate_trash (volume)) {
return;
}
+
+ volume_mount_uri = gnome_vfs_uri_new (
+ nautilus_volume_monitor_get_volume_mount_uri (volume));
/* Make the structure used to track the trash for this volume. */
trash_volume = g_new0 (TrashVolume, 1);
@@ -152,7 +127,7 @@ add_volume (NautilusTrashDirectory *trash,
g_hash_table_insert (trash->details->volumes, volume, trash_volume);
/* Find the real trash directory for this one. */
- vfs_uri_as_list.data = vfs_uri;
+ vfs_uri_as_list.data = volume_mount_uri;
vfs_uri_as_list.next = NULL;
vfs_uri_as_list.prev = NULL;
/* Search for Trash directories but don't create new ones. */
diff --git a/libnautilus-private/nautilus-trash-monitor.c b/libnautilus-private/nautilus-trash-monitor.c
index b70a565da..aca0a9d29 100644
--- a/libnautilus-private/nautilus-trash-monitor.c
+++ b/libnautilus-private/nautilus-trash-monitor.c
@@ -187,3 +187,57 @@ nautilus_trash_monitor_is_empty (void)
{
return nautilus_trash_monitor_get ()->details->empty;
}
+
+static gboolean
+add_one_volume_trash (const NautilusVolume *volume,
+ gpointer callback_data)
+{
+ GnomeVFSURI *volume_mount_point_uri;
+ GnomeVFSURI *trash_uri;
+ GList **result;
+
+ result = (GList **)callback_data;
+
+ if (nautilus_volume_monitor_should_integrate_trash (volume)) {
+
+ /* Get the uri of the volume mount point as the place
+ * "near" which to look for trash on the given volume.
+ */
+ volume_mount_point_uri = gnome_vfs_uri_new (
+ nautilus_volume_monitor_get_volume_mount_uri (volume));
+
+ g_assert (volume_mount_point_uri != NULL);
+
+ /* Look for trash. It is OK to use a sync call here because
+ * the options we use (don't create, don't look for it if we
+ * already don't know where it is) do not cause any IO.
+ */
+ if (gnome_vfs_find_directory (volume_mount_point_uri,
+ GNOME_VFS_DIRECTORY_KIND_TRASH, &trash_uri,
+ FALSE, FALSE, 0777) == GNOME_VFS_OK) {
+
+ /* found trash, put it on the list */
+ *result = g_list_append (*result, trash_uri);
+ }
+
+ gnome_vfs_uri_unref (volume_mount_point_uri);
+ }
+
+ /* don't stop iterating */
+ return FALSE;
+}
+
+GList *
+nautilus_trash_monitor_get_trash_directories (void)
+{
+ GList *result;
+
+ result = NULL;
+
+ /* Collect the trash directories on all the mounted volumes. */
+ nautilus_volume_monitor_each_mounted_volume
+ (nautilus_volume_monitor_get (), add_one_volume_trash, &result);
+
+ return result;
+}
+
diff --git a/libnautilus-private/nautilus-trash-monitor.h b/libnautilus-private/nautilus-trash-monitor.h
index 19139d514..41c726dcc 100644
--- a/libnautilus-private/nautilus-trash-monitor.h
+++ b/libnautilus-private/nautilus-trash-monitor.h
@@ -60,7 +60,6 @@ GtkType nautilus_trash_monitor_get_type (void);
NautilusTrashMonitor *nautilus_trash_monitor_get (void);
gboolean nautilus_trash_monitor_is_empty (void);
-void nautilus_trash_monitor_async_get_trash_directories (GnomeVFSAsyncFindDirectoryCallback callback,
- gpointer context);
+GList * nautilus_trash_monitor_get_trash_directories (void);
#endif
diff --git a/libnautilus-private/nautilus-volume-monitor.c b/libnautilus-private/nautilus-volume-monitor.c
index 0a75b3c03..dfd98d045 100644
--- a/libnautilus-private/nautilus-volume-monitor.c
+++ b/libnautilus-private/nautilus-volume-monitor.c
@@ -318,6 +318,28 @@ nautilus_volume_monitor_volume_is_mounted (const NautilusVolume *volume)
return FALSE;
}
+gboolean
+nautilus_volume_monitor_should_integrate_trash (const NautilusVolume *volume)
+{
+ /* Hand-pick a bunch of file system types that we know we can support
+ * trash on. It would probably be harder to keep a list of the ones
+ * we can't try to support trash on because the list would have to be
+ * more definitive.
+ */
+ return volume->type == NAUTILUS_VOLUME_EXT2
+ || volume->type == NAUTILUS_VOLUME_FAT
+ || volume->type == NAUTILUS_VOLUME_NFS
+ || volume->type == NAUTILUS_VOLUME_VFAT
+ || volume->type == NAUTILUS_VOLUME_FLOPPY
+ || volume->type == NAUTILUS_VOLUME_SMB;
+}
+
+const char *
+nautilus_volume_monitor_get_volume_mount_uri (const NautilusVolume *volume)
+{
+ return volume->mount_path;
+}
+
static void
mount_volume_cdrom_set_state (NautilusVolumeMonitor *monitor, NautilusVolume *volume)
{
diff --git a/libnautilus-private/nautilus-volume-monitor.h b/libnautilus-private/nautilus-volume-monitor.h
index 08984fc65..d376e3b08 100644
--- a/libnautilus-private/nautilus-volume-monitor.h
+++ b/libnautilus-private/nautilus-volume-monitor.h
@@ -111,6 +111,8 @@ gboolean nautilus_volume_monitor_is_volume_link (con
void nautilus_volume_monitor_each_volume (NautilusVolumeMonitor *monitor,
NautilusEachVolumeFunction function,
gpointer context);
+gboolean nautilus_volume_monitor_should_integrate_trash (const NautilusVolume *volume);
+const char *nautilus_volume_monitor_get_volume_mount_uri (const NautilusVolume *volume);
void nautilus_volume_monitor_each_mounted_volume (NautilusVolumeMonitor *monitor,
NautilusEachVolumeFunction function,
gpointer context);