[PATCH] 312707: moving a file or folder onto itself destroys it
- From: Tuukka Tolvanen <tuukka tolvanen gmail com>
- To: gnome-vfs-list gnome org
- Subject: [PATCH] 312707: moving a file or folder onto itself destroys it
- Date: Sat, 06 Aug 2005 03:16:35 +0300
Steps to reproduce:
1. mkdir -p parent1/folder
2. ln -s parent1 parent2
3. nautilus parent1 parent2
4. drag 'folder' across
5. confirm replace
Actual results:
'folder' deleted
The attached patch is not quite a correct fix -- when move+replacing
identical but separate hardlinks it fails to remove the source.
http://bugzilla.gnome.org/show_bug.cgi?id=312707#c2
't.
? gnome-vfs-xfer.loT
Index: gnome-vfs-xfer.c
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-xfer.c,v
retrieving revision 1.125
diff -p -U9 -r1.125 gnome-vfs-xfer.c
--- gnome-vfs-xfer.c 8 Jul 2005 08:53:18 -0000 1.125
+++ gnome-vfs-xfer.c 5 Aug 2005 23:33:11 -0000
@@ -998,81 +998,100 @@ handle_name_conflicts (GList **source_ur
if (conflict_count == 0) {
/* No conflicts, we are done. */
return GNOME_VFS_OK;
}
/* Pass in the conflict count so that we can decide to present the Replace All
* for multiple conflicts.
*/
progress->progress_info->duplicate_count = conflict_count;
-
+
+ source_info = gnome_vfs_file_info_new ();
target_info = gnome_vfs_file_info_new ();
/* Go through the list of names again, present overwrite alerts for each. */
for (target_item = *target_uri_list, source_item = *source_uri_list;
target_item != NULL;) {
gboolean replace;
gboolean skip;
- gboolean is_move_to_self;
+ gboolean is_move;
+ gboolean to_self;
GnomeVFSURI *uri, *source_uri;
gboolean must_copy;
+ gboolean have_source_info = FALSE;
+ gboolean have_target_info = FALSE;
must_copy = FALSE;
skip = FALSE;
source_uri = (GnomeVFSURI *)source_item->data;
uri = (GnomeVFSURI *)target_item->data;
- is_move_to_self = (xfer_options & GNOME_VFS_XFER_REMOVESOURCE) != 0
- && gnome_vfs_uri_equal (source_uri, uri);
- if (!is_move_to_self &&
- gnome_vfs_get_file_info_uri (uri, target_info, GNOME_VFS_FILE_INFO_DEFAULT) == GNOME_VFS_OK) {
+ is_move = (xfer_options & GNOME_VFS_XFER_REMOVESOURCE) != 0;
+ to_self = gnome_vfs_uri_equal (source_uri, uri);
+
+ /* FIXME gnome_vfs_file_info_matches is a subtly wrong check
+ * for to_self; if source and target are identical hardlinks,
+ * source won't be deleted on move. A correct solution could
+ * be e.g. a hypothetical physical_uri_equal (realpath on
+ * file:), or renaming (or Trashing) the target and seeing if
+ * the source disappeared...
+ */
+ if (!(is_move && to_self)) {
+ have_target_info = (GNOME_VFS_OK == gnome_vfs_get_file_info_uri (uri, target_info, GNOME_VFS_FILE_INFO_DEFAULT));
+ if (have_target_info) {
+ have_source_info = (GNOME_VFS_OK == gnome_vfs_get_file_info_uri (source_uri, source_info, GNOME_VFS_FILE_INFO_DEFAULT));
+ if (have_source_info) {
+ to_self = gnome_vfs_file_info_matches (source_info, target_info);
+ }
+ }
+ }
+
+ if (!(is_move && to_self) && have_target_info) {
progress_set_source_target_uris (progress, source_uri, uri);
/* no error getting info -- file exists, ask what to do */
replace = handle_overwrite (&result, progress, error_mode,
overwrite_mode, &replace, &skip);
/* FIXME bugzilla.eazel.com 1207:
* move items to Trash here
*/
/* get rid of the conflicting file */
if (replace) {
progress_set_source_target_uris (progress, uri, NULL);
if (target_info->type == GNOME_VFS_FILE_TYPE_DIRECTORY) {
if (move_source_is_in_target (source_uri, uri)) {
/* Would like a better error here */
result = GNOME_VFS_ERROR_DIRECTORY_NOT_EMPTY;
} else {
- source_info = gnome_vfs_file_info_new ();
if (!link &&
- gnome_vfs_get_file_info_uri (source_uri, source_info, GNOME_VFS_FILE_INFO_DEFAULT) == GNOME_VFS_OK &&
+ (have_source_info || GNOME_VFS_OK == gnome_vfs_get_file_info_uri (source_uri, source_info, GNOME_VFS_FILE_INFO_DEFAULT)) &&
source_info->type == GNOME_VFS_FILE_TYPE_DIRECTORY) {
if (move || (xfer_options & GNOME_VFS_XFER_RECURSIVE)) {
result = handle_merged_directory_name_conflicts (xfer_options, error_mode,
progress, source_uri, uri);
}
must_copy = TRUE;
} else {
result = remove_directory (uri, TRUE, progress,
xfer_options, error_mode, &skip);
}
- gnome_vfs_file_info_unref (source_info);
}
} else {
result = remove_file (uri, progress,
xfer_options, error_mode, &skip);
}
}
-
- gnome_vfs_file_info_clear (target_info);
}
-
+ gnome_vfs_file_info_clear (source_info);
+ gnome_vfs_file_info_clear (target_info);
+
if (result != GNOME_VFS_OK) {
break;
}
if (skip) {
/* skipping a file, remove it's name from the source and target name
* lists.
*/
source_item_to_remove = source_item;
@@ -1103,18 +1122,20 @@ handle_name_conflicts (GList **source_ur
*source_uri_list = g_list_remove_link (*source_uri_list, source_item_to_remove);
*target_uri_list = g_list_remove_link (*target_uri_list, target_item_to_remove);
continue;
}
target_item = target_item->next;
source_item = source_item->next;
}
+
+ gnome_vfs_file_info_unref (source_info);
gnome_vfs_file_info_unref (target_info);
return result;
}
/* Create new directory. If GNOME_VFS_XFER_USE_UNIQUE_NAMES is set,
* return with an error if a name conflict occurs, else
* handle the overwrite.
* On success, opens the new directory
@@ -2348,18 +2369,19 @@ gnome_vfs_xfer_uri_internal (const GList
handle_error (&result, progress, &error_mode, &skip);
gnome_vfs_uri_unref (target_dir_uri);
return result;
}
move = (xfer_options & GNOME_VFS_XFER_REMOVESOURCE) != 0;
link = (xfer_options & GNOME_VFS_XFER_LINK_ITEMS) != 0;
if (move && link) {
+ gnome_vfs_uri_unref (target_dir_uri);
return GNOME_VFS_ERROR_BAD_PARAMETERS;
}
/* Create an owning list of source and destination uris.
* We want to be able to remove items that we decide to skip during
* name conflict check.
*/
source_uri_list = gnome_vfs_uri_list_copy ((GList *)source_uris);
target_uri_list = gnome_vfs_uri_list_copy ((GList *)target_uris);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]