nautilus-3.6.3/libnautilus-private/nautilus-file-operations.c

Location Tool Test ID Function Issue
nautilus-file-operations.c:5223:32 clang-analyzer Access to field 'data' results in a dereference of a null pointer (loaded from variable 'files')*
nautilus-file-operations.c:5547:32 clang-analyzer Access to field 'data' results in a dereference of a null pointer (loaded from variable 'files')
nautilus-file-operations.c:5848:32 clang-analyzer Access to field 'data' results in a dereference of a null pointer (loaded from variable 'locations')*
   1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
   2 
   3 /* nautilus-file-operations.c - Nautilus file operations.
   4 
   5    Copyright (C) 1999, 2000 Free Software Foundation
   6    Copyright (C) 2000, 2001 Eazel, Inc.
   7    Copyright (C) 2007 Red Hat, Inc.
   8 
   9    This program is free software; you can redistribute it and/or
  10    modify it under the terms of the GNU General Public License as
  11    published by the Free Software Foundation; either version 2 of the
  12    License, or (at your option) any later version.
  13    
  14    This program is distributed in the hope that it will be useful,
  15    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17    General Public License for more details.
  18    
  19    You should have received a copy of the GNU General Public
  20    License along with this program; if not, write to the
  21    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  22    Boston, MA 02111-1307, USA.
  23    
  24    Authors: Alexander Larsson <alexl@redhat.com>
  25             Ettore Perazzoli <ettore@gnu.org> 
  26             Pavel Cisler <pavel@eazel.com> 
  27  */
  28 
  29 #include <config.h>
  30 #include <string.h>
  31 #include <stdio.h>
  32 #include <stdarg.h>
  33 #include <locale.h>
  34 #include <math.h>
  35 #include <unistd.h>
  36 #include <sys/types.h>
  37 #include <stdlib.h>
  38 
  39 #include "nautilus-file-operations.h"
  40 
  41 #include "nautilus-file-changes-queue.h"
  42 #include "nautilus-lib-self-check-functions.h"
  43 
  44 #include "nautilus-progress-info.h"
  45 
  46 #include <eel/eel-glib-extensions.h>
  47 #include <eel/eel-gtk-extensions.h>
  48 #include <eel/eel-stock-dialogs.h>
  49 #include <eel/eel-vfs-extensions.h>
  50 
  51 #include <glib/gi18n.h>
  52 #include <glib/gstdio.h>
  53 #include <gdk/gdk.h>
  54 #include <gtk/gtk.h>
  55 #include <gio/gio.h>
  56 #include <glib.h>
  57 #include "nautilus-file-changes-queue.h"
  58 #include "nautilus-file-private.h"
  59 #include "nautilus-desktop-icon-file.h"
  60 #include "nautilus-desktop-link-monitor.h"
  61 #include "nautilus-global-preferences.h"
  62 #include "nautilus-link.h"
  63 #include "nautilus-trash-monitor.h"
  64 #include "nautilus-file-utilities.h"
  65 #include "nautilus-file-conflict-dialog.h"
  66 #include "nautilus-file-undo-operations.h"
  67 #include "nautilus-file-undo-manager.h"
  68 
  69 /* TODO: TESTING!!! */
  70 
  71 typedef struct {
  72 	GIOSchedulerJob *io_job;	
  73 	GTimer *time;
  74 	GtkWindow *parent_window;
  75 	int screen_num;
  76 	int inhibit_cookie;
  77 	NautilusProgressInfo *progress;
  78 	GCancellable *cancellable;
  79 	GHashTable *skip_files;
  80 	GHashTable *skip_readdir_error;
  81 	NautilusFileUndoInfo *undo_info;
  82 	gboolean skip_all_error;
  83 	gboolean skip_all_conflict;
  84 	gboolean merge_all;
  85 	gboolean replace_all;
  86 	gboolean delete_all;
  87 } CommonJob;
  88 
  89 typedef struct {
  90 	CommonJob common;
  91 	gboolean is_move;
  92 	GList *files;
  93 	GFile *destination;
  94 	GFile *desktop_location;
  95 	GFile *fake_display_source;
  96 	GdkPoint *icon_positions;
  97 	int n_icon_positions;
  98 	GHashTable *debuting_files;
  99 	gchar *target_name;
 100 	NautilusCopyCallback  done_callback;
 101 	gpointer done_callback_data;
 102 } CopyMoveJob;
 103 
 104 typedef struct {
 105 	CommonJob common;
 106 	GList *files;
 107 	gboolean try_trash;
 108 	gboolean user_cancel;
 109 	NautilusDeleteCallback done_callback;
 110 	gpointer done_callback_data;
 111 } DeleteJob;
 112 
 113 typedef struct {
 114 	CommonJob common;
 115 	GFile *dest_dir;
 116 	char *filename;
 117 	gboolean make_dir;
 118 	GFile *src;
 119 	char *src_data;
 120 	int length;
 121 	GdkPoint position;
 122 	gboolean has_position;
 123 	GFile *created_file;
 124 	NautilusCreateCallback done_callback;
 125 	gpointer done_callback_data;
 126 } CreateJob;
 127 
 128 
 129 typedef struct {
 130 	CommonJob common;
 131 	GList *trash_dirs;
 132 	gboolean should_confirm;
 133 	NautilusOpCallback done_callback;
 134 	gpointer done_callback_data;
 135 } EmptyTrashJob;
 136 
 137 typedef struct {
 138 	CommonJob common;
 139 	GFile *file;
 140 	gboolean interactive;
 141 	NautilusOpCallback done_callback;
 142 	gpointer done_callback_data;
 143 } MarkTrustedJob;
 144 
 145 typedef struct {
 146 	CommonJob common;
 147 	GFile *file;
 148 	NautilusOpCallback done_callback;
 149 	gpointer done_callback_data;
 150 	guint32 file_permissions;
 151 	guint32 file_mask;
 152 	guint32 dir_permissions;
 153 	guint32 dir_mask;
 154 } SetPermissionsJob;
 155 
 156 typedef enum {
 157 	OP_KIND_COPY,
 158 	OP_KIND_MOVE,
 159 	OP_KIND_DELETE,
 160 	OP_KIND_TRASH
 161 } OpKind;
 162 
 163 typedef struct {
 164 	int num_files;
 165 	goffset num_bytes;
 166 	int num_files_since_progress;
 167 	OpKind op;
 168 } SourceInfo;
 169 
 170 typedef struct {
 171 	int num_files;
 172 	goffset num_bytes;
 173 	OpKind op;
 174 	guint64 last_report_time;
 175 	int last_reported_files_left;
 176 } TransferInfo;
 177 
 178 #define SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE 15
 179 #define NSEC_PER_MICROSEC 1000
 180 
 181 #define MAXIMUM_DISPLAYED_FILE_NAME_LENGTH 50
 182 
 183 #define IS_IO_ERROR(__error, KIND) (((__error)->domain == G_IO_ERROR && (__error)->code == G_IO_ERROR_ ## KIND))
 184 
 185 #define SKIP _("_Skip")
 186 #define SKIP_ALL _("S_kip All")
 187 #define RETRY _("_Retry")
 188 #define DELETE_ALL _("Delete _All")
 189 #define REPLACE _("_Replace")
 190 #define REPLACE_ALL _("Replace _All")
 191 #define MERGE _("_Merge")
 192 #define MERGE_ALL _("Merge _All")
 193 #define COPY_FORCE _("Copy _Anyway")
 194 
 195 static void
 196 mark_desktop_file_trusted (CommonJob *common,
 197 			   GCancellable *cancellable,
 198 			   GFile *file,
 199 			   gboolean interactive);
 200 
 201 static gboolean
 202 is_all_button_text (const char *button_text)
 203 {
 204 	g_assert (button_text != NULL);
 205 
 206 	return !strcmp (button_text, SKIP_ALL) ||
 207 	       !strcmp (button_text, REPLACE_ALL) ||
 208 	       !strcmp (button_text, DELETE_ALL) ||
 209 	       !strcmp (button_text, MERGE_ALL);
 210 }
 211 
 212 static void scan_sources (GList *files,
 213 			  SourceInfo *source_info,
 214 			  CommonJob *job,
 215 			  OpKind kind);
 216 
 217 
 218 static gboolean empty_trash_job (GIOSchedulerJob *io_job,
 219 				 GCancellable *cancellable,
 220 				 gpointer user_data);
 221 
 222 static char * query_fs_type (GFile *file,
 223 			     GCancellable *cancellable);
 224 
 225 /* keep in time with format_time()
 226  *
 227  * This counts and outputs the number of “time units”
 228  * formatted and displayed by format_time().
 229  * For instance, if format_time outputs “3 hours, 4 minutes”
 230  * it yields 7.
 231  */
 232 static int
 233 seconds_count_format_time_units (int seconds)
 234 {
 235 	int minutes;
 236 	int hours;
 237 
 238 	if (seconds < 0) {
 239 		/* Just to make sure... */
 240 		seconds = 0;
 241 	}
 242 
 243 	if (seconds < 60) {
 244 		/* seconds */
 245 		return seconds;
 246 	}
 247 
 248 	if (seconds < 60*60) {
 249 		/* minutes */
 250 		minutes = seconds / 60;
 251 		return minutes;
 252 	}
 253 
 254 	hours = seconds / (60*60);
 255 
 256 	if (seconds < 60*60*4) {
 257 		/* minutes + hours */
 258 		minutes = (seconds - hours * 60 * 60) / 60;
 259 		return minutes + hours;
 260 	}
 261 
 262 	return hours;
 263 }
 264 
 265 static char *
 266 format_time (int seconds)
 267 {
 268 	int minutes;
 269 	int hours;
 270 	char *res;
 271 
 272 	if (seconds < 0) {
 273 		/* Just to make sure... */
 274 		seconds = 0;
 275 	}
 276 	
 277 	if (seconds < 60) {
 278 		return g_strdup_printf (ngettext ("%'d second","%'d seconds", (int) seconds), (int) seconds);
 279 	}
 280 
 281 	if (seconds < 60*60) {
 282 		minutes = seconds / 60;
 283 		return g_strdup_printf (ngettext ("%'d minute", "%'d minutes", minutes), minutes);
 284 	}
 285 
 286 	hours = seconds / (60*60);
 287 	
 288 	if (seconds < 60*60*4) {
 289 		char *h, *m;
 290 
 291 		minutes = (seconds - hours * 60 * 60) / 60;
 292 		
 293 		h = g_strdup_printf (ngettext ("%'d hour", "%'d hours", hours), hours);
 294 		m = g_strdup_printf (ngettext ("%'d minute", "%'d minutes", minutes), minutes);
 295 		res = g_strconcat (h, ", ", m, NULL);
 296 		g_free (h);
 297 		g_free (m);
 298 		return res;
 299 	}
 300 	
 301 	return g_strdup_printf (ngettext ("approximately %'d hour",
 302 					  "approximately %'d hours",
 303 					  hours), hours);
 304 }
 305 
 306 static char *
 307 shorten_utf8_string (const char *base, int reduce_by_num_bytes)
 308 {
 309 	int len;
 310 	char *ret;
 311 	const char *p;
 312 	
 313 	len = strlen (base);
 314 	len -= reduce_by_num_bytes;
 315 	
 316 	if (len <= 0) {
 317 		return NULL;
 318 	}
 319 
 320 	ret = g_new (char, len + 1);
 321 
 322 	p = base;
 323 	while (len) {
 324 		char *next;
 325 		next = g_utf8_next_char (p);
 326 		if (next - p > len || *next == '\0') {
 327 			break;
 328 		}
 329 		
 330 		len -= next - p;
 331 		p = next;
 332 	}
 333 	
 334 	if (p - base == 0) {
 335 		g_free (ret);
 336 		return NULL;
 337 	} else {
 338 		memcpy (ret, base, p - base);
 339 		ret[p - base] = '\0';
 340 		return ret;
 341 	}
 342 }
 343 
 344 /* Note that we have these two separate functions with separate format
 345  * strings for ease of localization.
 346  */
 347 
 348 static char *
 349 get_link_name (const char *name, int count, int max_length)
 350 {
 351 	const char *format;
 352 	char *result;
 353 	int unshortened_length;
 354 	gboolean use_count;
 355 	
 356 	g_assert (name != NULL);
 357 
 358 	if (count < 0) {
 359 		g_warning ("bad count in get_link_name");
 360 		count = 0;
 361 	}
 362 
 363 	if (count <= 2) {
 364 		/* Handle special cases for low numbers.
 365 		 * Perhaps for some locales we will need to add more.
 366 		 */
 367 		switch (count) {
 368 		default:
 369 			g_assert_not_reached ();
 370 			/* fall through */
 371 		case 0:
 372 			/* duplicate original file name */
 373 			format = "%s";
 374 			break;
 375 		case 1:
 376 			/* appended to new link file */
 377 			format = _("Link to %s");
 378 			break;
 379 		case 2:
 380 			/* appended to new link file */
 381 			format = _("Another link to %s");
 382 			break;
 383 		}
 384 
 385 		use_count = FALSE;
 386 	} else {
 387 		/* Handle special cases for the first few numbers of each ten.
 388 		 * For locales where getting this exactly right is difficult,
 389 		 * these can just be made all the same as the general case below.
 390 		 */
 391 		switch (count % 10) {
 392 		case 1:
 393 			/* Localizers: Feel free to leave out the "st" suffix
 394 			 * if there's no way to do that nicely for a
 395 			 * particular language.
 396 			 */
 397 			format = _("%'dst link to %s");
 398 			break;
 399 		case 2:
 400 			/* appended to new link file */
 401 			format = _("%'dnd link to %s");
 402 			break;
 403 		case 3:
 404 			/* appended to new link file */
 405 			format = _("%'drd link to %s");
 406 			break;
 407 		default:
 408 			/* appended to new link file */
 409 			format = _("%'dth link to %s");
 410 			break;
 411 		}
 412 
 413 		use_count = TRUE;
 414 	}
 415 
 416 	if (use_count)
 417 		result = g_strdup_printf (format, count, name);
 418 	else
 419 		result = g_strdup_printf (format, name);
 420 
 421 	if (max_length > 0 && (unshortened_length = strlen (result)) > max_length) {
 422 		char *new_name;
 423 
 424 		new_name = shorten_utf8_string (name, unshortened_length - max_length);
 425 		if (new_name) {
 426 			g_free (result);
 427 
 428 			if (use_count)
 429 				result = g_strdup_printf (format, count, new_name);
 430 			else
 431 				result = g_strdup_printf (format, new_name);
 432 
 433 			g_assert (strlen (result) <= max_length);
 434 			g_free (new_name);
 435 		}
 436 	}
 437 
 438 	return result;
 439 }
 440 
 441 
 442 /* Localizers: 
 443  * Feel free to leave out the st, nd, rd and th suffix or
 444  * make some or all of them match.
 445  */
 446 
 447 /* localizers: tag used to detect the first copy of a file */
 448 static const char untranslated_copy_duplicate_tag[] = N_(" (copy)");
 449 /* localizers: tag used to detect the second copy of a file */
 450 static const char untranslated_another_copy_duplicate_tag[] = N_(" (another copy)");
 451 
 452 /* localizers: tag used to detect the x11th copy of a file */
 453 static const char untranslated_x11th_copy_duplicate_tag[] = N_("th copy)");
 454 /* localizers: tag used to detect the x12th copy of a file */
 455 static const char untranslated_x12th_copy_duplicate_tag[] = N_("th copy)");
 456 /* localizers: tag used to detect the x13th copy of a file */
 457 static const char untranslated_x13th_copy_duplicate_tag[] = N_("th copy)");
 458 
 459 /* localizers: tag used to detect the x1st copy of a file */
 460 static const char untranslated_st_copy_duplicate_tag[] = N_("st copy)");
 461 /* localizers: tag used to detect the x2nd copy of a file */
 462 static const char untranslated_nd_copy_duplicate_tag[] = N_("nd copy)");
 463 /* localizers: tag used to detect the x3rd copy of a file */
 464 static const char untranslated_rd_copy_duplicate_tag[] = N_("rd copy)");
 465 
 466 /* localizers: tag used to detect the xxth copy of a file */
 467 static const char untranslated_th_copy_duplicate_tag[] = N_("th copy)");
 468 
 469 #define COPY_DUPLICATE_TAG _(untranslated_copy_duplicate_tag)
 470 #define ANOTHER_COPY_DUPLICATE_TAG _(untranslated_another_copy_duplicate_tag)
 471 #define X11TH_COPY_DUPLICATE_TAG _(untranslated_x11th_copy_duplicate_tag)
 472 #define X12TH_COPY_DUPLICATE_TAG _(untranslated_x12th_copy_duplicate_tag)
 473 #define X13TH_COPY_DUPLICATE_TAG _(untranslated_x13th_copy_duplicate_tag)
 474 
 475 #define ST_COPY_DUPLICATE_TAG _(untranslated_st_copy_duplicate_tag)
 476 #define ND_COPY_DUPLICATE_TAG _(untranslated_nd_copy_duplicate_tag)
 477 #define RD_COPY_DUPLICATE_TAG _(untranslated_rd_copy_duplicate_tag)
 478 #define TH_COPY_DUPLICATE_TAG _(untranslated_th_copy_duplicate_tag)
 479 
 480 /* localizers: appended to first file copy */
 481 static const char untranslated_first_copy_duplicate_format[] = N_("%s (copy)%s");
 482 /* localizers: appended to second file copy */
 483 static const char untranslated_second_copy_duplicate_format[] = N_("%s (another copy)%s");
 484 
 485 /* localizers: appended to x11th file copy */
 486 static const char untranslated_x11th_copy_duplicate_format[] = N_("%s (%'dth copy)%s");
 487 /* localizers: appended to x12th file copy */
 488 static const char untranslated_x12th_copy_duplicate_format[] = N_("%s (%'dth copy)%s");
 489 /* localizers: appended to x13th file copy */
 490 static const char untranslated_x13th_copy_duplicate_format[] = N_("%s (%'dth copy)%s");
 491 
 492 /* localizers: if in your language there's no difference between 1st, 2nd, 3rd and nth
 493  * plurals, you can leave the st, nd, rd suffixes out and just make all the translated
 494  * strings look like "%s (copy %'d)%s".
 495  */
 496 
 497 /* localizers: appended to x1st file copy */
 498 static const char untranslated_st_copy_duplicate_format[] = N_("%s (%'dst copy)%s");
 499 /* localizers: appended to x2nd file copy */
 500 static const char untranslated_nd_copy_duplicate_format[] = N_("%s (%'dnd copy)%s");
 501 /* localizers: appended to x3rd file copy */
 502 static const char untranslated_rd_copy_duplicate_format[] = N_("%s (%'drd copy)%s");
 503 /* localizers: appended to xxth file copy */
 504 static const char untranslated_th_copy_duplicate_format[] = N_("%s (%'dth copy)%s");
 505 
 506 #define FIRST_COPY_DUPLICATE_FORMAT _(untranslated_first_copy_duplicate_format)
 507 #define SECOND_COPY_DUPLICATE_FORMAT _(untranslated_second_copy_duplicate_format)
 508 #define X11TH_COPY_DUPLICATE_FORMAT _(untranslated_x11th_copy_duplicate_format)
 509 #define X12TH_COPY_DUPLICATE_FORMAT _(untranslated_x12th_copy_duplicate_format)
 510 #define X13TH_COPY_DUPLICATE_FORMAT _(untranslated_x13th_copy_duplicate_format)
 511 
 512 #define ST_COPY_DUPLICATE_FORMAT _(untranslated_st_copy_duplicate_format)
 513 #define ND_COPY_DUPLICATE_FORMAT _(untranslated_nd_copy_duplicate_format)
 514 #define RD_COPY_DUPLICATE_FORMAT _(untranslated_rd_copy_duplicate_format)
 515 #define TH_COPY_DUPLICATE_FORMAT _(untranslated_th_copy_duplicate_format)
 516 
 517 static char *
 518 extract_string_until (const char *original, const char *until_substring)
 519 {
 520 	char *result;
 521 	
 522 	g_assert ((int) strlen (original) >= until_substring - original);
 523 	g_assert (until_substring - original >= 0);
 524 
 525 	result = g_malloc (until_substring - original + 1);
 526 	strncpy (result, original, until_substring - original);
 527 	result[until_substring - original] = '\0';
 528 	
 529 	return result;
 530 }
 531 
 532 /* Dismantle a file name, separating the base name, the file suffix and removing any
 533  * (xxxcopy), etc. string. Figure out the count that corresponds to the given
 534  * (xxxcopy) substring.
 535  */
 536 static void
 537 parse_previous_duplicate_name (const char *name,
 538 			       char **name_base,
 539 			       const char **suffix,
 540 			       int *count)
 541 {
 542 	const char *tag;
 543 
 544 	g_assert (name[0] != '\0');
 545 
 546 	*suffix = eel_filename_get_extension_offset (name);
 547 
 548 	if (*suffix == NULL || (*suffix)[1] == '\0') {
 549 		/* no suffix */
 550 		*suffix = "";
 551 	}
 552 
 553 	tag = strstr (name, COPY_DUPLICATE_TAG);
 554 	if (tag != NULL) {
 555 		if (tag > *suffix) {
 556 			/* handle case "foo. (copy)" */
 557 			*suffix = "";
 558 		}
 559 		*name_base = extract_string_until (name, tag);
 560 		*count = 1;
 561 		return;
 562 	}
 563 
 564 
 565 	tag = strstr (name, ANOTHER_COPY_DUPLICATE_TAG);
 566 	if (tag != NULL) {
 567 		if (tag > *suffix) {
 568 			/* handle case "foo. (another copy)" */
 569 			*suffix = "";
 570 		}
 571 		*name_base = extract_string_until (name, tag);
 572 		*count = 2;
 573 		return;
 574 	}
 575 
 576 
 577 	/* Check to see if we got one of st, nd, rd, th. */
 578 	tag = strstr (name, X11TH_COPY_DUPLICATE_TAG);
 579 
 580 	if (tag == NULL) {
 581 		tag = strstr (name, X12TH_COPY_DUPLICATE_TAG);
 582 	}
 583 	if (tag == NULL) {
 584 		tag = strstr (name, X13TH_COPY_DUPLICATE_TAG);
 585 	}
 586 
 587 	if (tag == NULL) {
 588 		tag = strstr (name, ST_COPY_DUPLICATE_TAG);
 589 	}
 590 	if (tag == NULL) {
 591 		tag = strstr (name, ND_COPY_DUPLICATE_TAG);
 592 	}
 593 	if (tag == NULL) {
 594 		tag = strstr (name, RD_COPY_DUPLICATE_TAG);
 595 	}
 596 	if (tag == NULL) {
 597 		tag = strstr (name, TH_COPY_DUPLICATE_TAG);
 598 	}
 599 
 600 	/* If we got one of st, nd, rd, th, fish out the duplicate number. */
 601 	if (tag != NULL) {
 602 		/* localizers: opening parentheses to match the "th copy)" string */
 603 		tag = strstr (name, _(" ("));
 604 		if (tag != NULL) {
 605 			if (tag > *suffix) {
 606 				/* handle case "foo. (22nd copy)" */
 607 				*suffix = "";
 608 			}
 609 			*name_base = extract_string_until (name, tag);
 610 			/* localizers: opening parentheses of the "th copy)" string */
 611 			if (sscanf (tag, _(" (%'d"), count) == 1) {
 612 				if (*count < 1 || *count > 1000000) {
 613 					/* keep the count within a reasonable range */
 614 					*count = 0;
 615 				}
 616 				return;
 617 			}
 618 			*count = 0;
 619 			return;
 620 		}
 621 	}
 622 
 623 	
 624 	*count = 0;
 625 	if (**suffix != '\0') {
 626 		*name_base = extract_string_until (name, *suffix);
 627 	} else {
 628 		*name_base = g_strdup (name);
 629 	}
 630 }
 631 
 632 static char *
 633 make_next_duplicate_name (const char *base, const char *suffix, int count, int max_length)
 634 {
 635 	const char *format;
 636 	char *result;
 637 	int unshortened_length;
 638 	gboolean use_count;
 639 
 640 	if (count < 1) {
 641 		g_warning ("bad count %d in get_duplicate_name", count);
 642 		count = 1;
 643 	}
 644 
 645 	if (count <= 2) {
 646 
 647 		/* Handle special cases for low numbers.
 648 		 * Perhaps for some locales we will need to add more.
 649 		 */
 650 		switch (count) {
 651 		default:
 652 			g_assert_not_reached ();
 653 			/* fall through */
 654 		case 1:
 655 			format = FIRST_COPY_DUPLICATE_FORMAT;
 656 			break;
 657 		case 2:
 658 			format = SECOND_COPY_DUPLICATE_FORMAT;
 659 			break;
 660 
 661 		}
 662 
 663 		use_count = FALSE;
 664 	} else {
 665 
 666 		/* Handle special cases for the first few numbers of each ten.
 667 		 * For locales where getting this exactly right is difficult,
 668 		 * these can just be made all the same as the general case below.
 669 		 */
 670 
 671 		/* Handle special cases for x11th - x20th.
 672 		 */
 673 		switch (count % 100) {
 674 		case 11:
 675 			format = X11TH_COPY_DUPLICATE_FORMAT;
 676 			break;
 677 		case 12:
 678 			format = X12TH_COPY_DUPLICATE_FORMAT;
 679 			break;
 680 		case 13:
 681 			format = X13TH_COPY_DUPLICATE_FORMAT;
 682 			break;
 683 		default:
 684 			format = NULL;
 685 			break;
 686 		}
 687 
 688 		if (format == NULL) {
 689 			switch (count % 10) {
 690 			case 1:
 691 				format = ST_COPY_DUPLICATE_FORMAT;
 692 				break;
 693 			case 2:
 694 				format = ND_COPY_DUPLICATE_FORMAT;
 695 				break;
 696 			case 3:
 697 				format = RD_COPY_DUPLICATE_FORMAT;
 698 				break;
 699 			default:
 700 				/* The general case. */
 701 				format = TH_COPY_DUPLICATE_FORMAT;
 702 				break;
 703 			}
 704 		}
 705 
 706 		use_count = TRUE;
 707 
 708 	}
 709 
 710 	if (use_count)
 711 		result = g_strdup_printf (format, base, count, suffix);
 712 	else
 713 		result = g_strdup_printf (format, base, suffix);
 714 
 715 	if (max_length > 0 && (unshortened_length = strlen (result)) > max_length) {
 716 		char *new_base;
 717 
 718 		new_base = shorten_utf8_string (base, unshortened_length - max_length);
 719 		if (new_base) {
 720 			g_free (result);
 721 
 722 			if (use_count)
 723 				result = g_strdup_printf (format, new_base, count, suffix);
 724 			else
 725 				result = g_strdup_printf (format, new_base, suffix);
 726 
 727 			g_assert (strlen (result) <= max_length);
 728 			g_free (new_base);
 729 		}
 730 	}
 731 
 732 	return result;
 733 }
 734 
 735 static char *
 736 get_duplicate_name (const char *name, int count_increment, int max_length)
 737 {
 738 	char *result;
 739 	char *name_base;
 740 	const char *suffix;
 741 	int count;
 742 
 743 	parse_previous_duplicate_name (name, &name_base, &suffix, &count);
 744 	result = make_next_duplicate_name (name_base, suffix, count + count_increment, max_length);
 745 
 746 	g_free (name_base);
 747 
 748 	return result;
 749 }
 750 
 751 static gboolean
 752 has_invalid_xml_char (char *str)
 753 {
 754 	gunichar c;
 755 
 756 	while (*str != 0) {
 757 		c = g_utf8_get_char (str);
 758 		/* characters XML permits */
 759 		if (!(c == 0x9 ||
 760 		      c == 0xA ||
 761 		      c == 0xD ||
 762 		      (c >= 0x20 && c <= 0xD7FF) ||
 763 		      (c >= 0xE000 && c <= 0xFFFD) ||
 764 		      (c >= 0x10000 && c <= 0x10FFFF))) {
 765 			return TRUE;
 766 		}
 767 		str = g_utf8_next_char (str);
 768 	}
 769 	return FALSE;
 770 }
 771 
 772 
 773 static char *
 774 custom_full_name_to_string (char *format, va_list va)
 775 {
 776 	GFile *file;
 777 	
 778 	file = va_arg (va, GFile *);
 779 	
 780 	return g_file_get_parse_name (file);
 781 }
 782 
 783 static void
 784 custom_full_name_skip (va_list *va)
 785 {
 786 	(void) va_arg (*va, GFile *);
 787 }
 788 
 789 static char *
 790 custom_basename_to_string (char *format, va_list va)
 791 {
 792 	GFile *file;
 793 	GFileInfo *info;
 794 	char *name, *basename, *tmp;
 795 
 796 	file = va_arg (va, GFile *);
 797 
 798 	info = g_file_query_info (file,
 799 				  G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
 800 				  0,
 801 				  g_cancellable_get_current (),
 802 				  NULL);
 803 	
 804 	name = NULL;
 805 	if (info) {
 806 		name = g_strdup (g_file_info_get_display_name (info));
 807 		g_object_unref (info);
 808 	}
 809 	
 810 	if (name == NULL) {
 811 		basename = g_file_get_basename (file);
 812 		if (g_utf8_validate (basename, -1, NULL)) {
 813 			name = basename;
 814 		} else {
 815 			name = g_uri_escape_string (basename, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, TRUE);
 816 			g_free (basename);
 817 		}
 818 	}
 819 
 820 	/* Some chars can't be put in the markup we use for the dialogs... */
 821 	if (has_invalid_xml_char (name)) {
 822 		tmp = name;
 823 		name = g_uri_escape_string (name, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, TRUE);
 824 		g_free (tmp);
 825 	}
 826 
 827 	/* Finally, if the string is too long, truncate it. */
 828 	if (name != NULL) {
 829 		tmp = name;
 830 		name = eel_str_middle_truncate (tmp, MAXIMUM_DISPLAYED_FILE_NAME_LENGTH);
 831 		g_free (tmp);
 832 	}
 833 
 834 	
 835 	return name;
 836 }
 837 
 838 static void
 839 custom_basename_skip (va_list *va)
 840 {
 841 	(void) va_arg (*va, GFile *);
 842 }
 843 
 844 
 845 static char *
 846 custom_size_to_string (char *format, va_list va)
 847 {
 848 	goffset size;
 849 
 850 	size = va_arg (va, goffset);
 851 	return g_format_size (size);
 852 }
 853 
 854 static void
 855 custom_size_skip (va_list *va)
 856 {
 857 	(void) va_arg (*va, goffset);
 858 }
 859 
 860 static char *
 861 custom_time_to_string (char *format, va_list va)
 862 {
 863 	int secs;
 864 
 865 	secs = va_arg (va, int);
 866 	return format_time (secs);
 867 }
 868 
 869 static void
 870 custom_time_skip (va_list *va)
 871 {
 872 	(void) va_arg (*va, int);
 873 }
 874 
 875 static char *
 876 custom_mount_to_string (char *format, va_list va)
 877 {
 878 	GMount *mount;
 879 
 880 	mount = va_arg (va, GMount *);
 881 	return g_mount_get_name (mount);
 882 }
 883 
 884 static void
 885 custom_mount_skip (va_list *va)
 886 {
 887 	(void) va_arg (*va, GMount *);
 888 }
 889 
 890 
 891 static EelPrintfHandler handlers[] = {
 892 	{ 'F', custom_full_name_to_string, custom_full_name_skip },
 893 	{ 'B', custom_basename_to_string, custom_basename_skip },
 894 	{ 'S', custom_size_to_string, custom_size_skip },
 895 	{ 'T', custom_time_to_string, custom_time_skip },
 896 	{ 'V', custom_mount_to_string, custom_mount_skip },
 897 	{ 0 }
 898 };
 899 
 900 
 901 static char *
 902 f (const char *format, ...) {
 903 	va_list va;
 904 	char *res;
 905 	
 906 	va_start (va, format);
 907 	res = eel_strdup_vprintf_with_custom (handlers, format, va);
 908 	va_end (va);
 909 
 910 	return res;
 911 }
 912 
 913 #define op_job_new(__type, parent_window) ((__type *)(init_common (sizeof(__type), parent_window)))
 914 
 915 static gpointer
 916 init_common (gsize job_size,
 917 	     GtkWindow *parent_window)
 918 {
 919 	CommonJob *common;
 920 	GdkScreen *screen;
 921 
 922 	common = g_malloc0 (job_size);
 923 
 924 	if (parent_window) {
 925 		common->parent_window = parent_window;
 926 		g_object_add_weak_pointer (G_OBJECT (common->parent_window),
 927 					   (gpointer *) &common->parent_window);
 928 
 929 	}
 930 	common->progress = nautilus_progress_info_new ();
 931 	common->cancellable = nautilus_progress_info_get_cancellable (common->progress);
 932 	common->time = g_timer_new ();
 933 	common->inhibit_cookie = -1;
 934 	common->screen_num = 0;
 935 	if (parent_window) {
 936 		screen = gtk_widget_get_screen (GTK_WIDGET (parent_window));
 937 		common->screen_num = gdk_screen_get_number (screen);
 938 	}
 939 	
 940 	return common;
 941 }
 942 
 943 static void
 944 finalize_common (CommonJob *common)
 945 {
 946 	nautilus_progress_info_finish (common->progress);
 947 
 948 	if (common->inhibit_cookie != -1) {
 949 		gtk_application_uninhibit (GTK_APPLICATION (g_application_get_default ()),
 950 					   common->inhibit_cookie);
 951 	}
 952 
 953 	common->inhibit_cookie = -1;
 954 	g_timer_destroy (common->time);
 955 
 956 	if (common->parent_window) {
 957 		g_object_remove_weak_pointer (G_OBJECT (common->parent_window),
 958 					      (gpointer *) &common->parent_window);
 959 	}
 960 
 961 	if (common->skip_files) {
 962 		g_hash_table_destroy (common->skip_files);
 963 	}
 964 	if (common->skip_readdir_error) {
 965 		g_hash_table_destroy (common->skip_readdir_error);
 966 	}
 967 
 968 	if (common->undo_info != NULL) {
 969 		nautilus_file_undo_manager_set_action (common->undo_info);
 970 		g_object_unref (common->undo_info);
 971 	}
 972 
 973 	g_object_unref (common->progress);
 974 	g_object_unref (common->cancellable);
 975 	g_free (common);
 976 }
 977 
 978 static void
 979 skip_file (CommonJob *common,
 980 	   GFile *file)
 981 {
 982 	if (common->skip_files == NULL) {
 983 		common->skip_files =
 984 			g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL);
 985 	}
 986 
 987 	g_hash_table_insert (common->skip_files, g_object_ref (file), file);
 988 }
 989 
 990 static void
 991 skip_readdir_error (CommonJob *common,
 992 		    GFile *dir)
 993 {
 994 	if (common->skip_readdir_error == NULL) {
 995 		common->skip_readdir_error =
 996 			g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL);
 997 	}
 998 
 999 	g_hash_table_insert (common->skip_readdir_error, g_object_ref (dir), dir);
1000 }
1001 
1002 static gboolean
1003 should_skip_file (CommonJob *common,
1004 		  GFile *file)
1005 {
1006 	if (common->skip_files != NULL) {
1007 		return g_hash_table_lookup (common->skip_files, file) != NULL;
1008 	}
1009 	return FALSE;
1010 }
1011 
1012 static gboolean
1013 should_skip_readdir_error (CommonJob *common,
1014 			   GFile *dir)
1015 {
1016 	if (common->skip_readdir_error != NULL) {
1017 		return g_hash_table_lookup (common->skip_readdir_error, dir) != NULL;
1018 	}
1019 	return FALSE;
1020 }
1021 
1022 static gboolean
1023 can_delete_without_confirm (GFile *file)
1024 {
1025 	if (g_file_has_uri_scheme (file, "burn") ||
1026 	    g_file_has_uri_scheme (file, "recent") ||
1027 	    g_file_has_uri_scheme (file, "x-nautilus-desktop")) {
1028 		return TRUE;
1029 	}
1030 
1031 	return FALSE;
1032 }
1033 
1034 static gboolean
1035 can_delete_files_without_confirm (GList *files)
1036 {
1037 	g_assert (files != NULL);
1038 
1039 	while (files != NULL) {
1040 		if (!can_delete_without_confirm (files->data)) {
1041 			return FALSE;
1042 		}
1043 
1044 		files = files->next;
1045 	}
1046 
1047 	return TRUE;
1048 }
1049 
1050 typedef struct {
1051 	GtkWindow **parent_window;
1052 	gboolean ignore_close_box;
1053 	GtkMessageType message_type;
1054 	const char *primary_text;
1055 	const char *secondary_text;
1056 	const char *details_text;
1057 	const char **button_titles;
1058 	gboolean show_all;
1059 	
1060 	int result;
1061 } RunSimpleDialogData;
1062 
1063 static gboolean
1064 do_run_simple_dialog (gpointer _data)
1065 {
1066 	RunSimpleDialogData *data = _data;
1067 	const char *button_title;
1068         GtkWidget *dialog;
1069 	int result;
1070 	int response_id;
1071 
1072 	/* Create the dialog. */
1073 	dialog = gtk_message_dialog_new (*data->parent_window,
1074 					 0,
1075 					 data->message_type,
1076 					 GTK_BUTTONS_NONE,
1077 					 NULL);
1078 
1079 	g_object_set (dialog,
1080 		      "text", data->primary_text,
1081 		      "secondary-text", data->secondary_text,
1082 		      NULL);
1083 
1084 	for (response_id = 0;
1085 	     data->button_titles[response_id] != NULL;
1086 	     response_id++) {
1087 		button_title = data->button_titles[response_id];
1088 		if (!data->show_all && is_all_button_text (button_title)) {
1089 			continue;
1090 		}
1091 
1092 		gtk_dialog_add_button (GTK_DIALOG (dialog), button_title, response_id);
1093 		gtk_dialog_set_default_response (GTK_DIALOG (dialog), response_id);
1094 	}
1095 
1096 	if (data->details_text) {
1097 		eel_gtk_message_dialog_set_details_label (GTK_MESSAGE_DIALOG (dialog),
1098 							  data->details_text);
1099 	}
1100 	
1101 	/* Run it. */
1102         result = gtk_dialog_run (GTK_DIALOG (dialog));
1103 	
1104 	while ((result == GTK_RESPONSE_NONE || result == GTK_RESPONSE_DELETE_EVENT) && data->ignore_close_box) {
1105 		result = gtk_dialog_run (GTK_DIALOG (dialog));
1106 	}
1107 	
1108 	gtk_widget_destroy (dialog);
1109 
1110 	data->result = result;
1111 	
1112 	return FALSE;
1113 }
1114 
1115 /* NOTE: This frees the primary / secondary strings, in order to
1116    avoid doing that everywhere. So, make sure they are strduped */
1117 
1118 static int
1119 run_simple_dialog_va (CommonJob *job,
1120 		      gboolean ignore_close_box,
1121 		      GtkMessageType message_type,
1122 		      char *primary_text,
1123 		      char *secondary_text,
1124 		      const char *details_text,
1125 		      gboolean show_all,
1126 		      va_list varargs)
1127 {
1128 	RunSimpleDialogData *data;
1129 	int res;
1130 	const char *button_title;
1131 	GPtrArray *ptr_array;
1132 
1133 	g_timer_stop (job->time);
1134 	
1135 	data = g_new0 (RunSimpleDialogData, 1);
1136 	data->parent_window = &job->parent_window;
1137 	data->ignore_close_box = ignore_close_box;
1138 	data->message_type = message_type;
1139 	data->primary_text = primary_text;
1140 	data->secondary_text = secondary_text;
1141 	data->details_text = details_text;
1142 	data->show_all = show_all;
1143 
1144 	ptr_array = g_ptr_array_new ();
1145 	while ((button_title = va_arg (varargs, const char *)) != NULL) {
1146 		g_ptr_array_add (ptr_array, (char *)button_title);
1147 	}
1148 	g_ptr_array_add (ptr_array, NULL);
1149 	data->button_titles = (const char **)g_ptr_array_free (ptr_array, FALSE);
1150 
1151 	nautilus_progress_info_pause (job->progress);
1152 	g_io_scheduler_job_send_to_mainloop (job->io_job,
1153 					     do_run_simple_dialog,
1154 					     data,
1155 					     NULL);
1156 	nautilus_progress_info_resume (job->progress);
1157 	res = data->result;
1158 
1159 	g_free (data->button_titles);
1160 	g_free (data);
1161 
1162 	g_timer_continue (job->time);
1163 
1164 	g_free (primary_text);
1165 	g_free (secondary_text);
1166 	
1167 	return res;
1168 }
1169 
1170 #if 0 /* Not used at the moment */
1171 static int
1172 run_simple_dialog (CommonJob *job,
1173 		   gboolean ignore_close_box,
1174 		   GtkMessageType message_type,
1175 		   char *primary_text,
1176 		   char *secondary_text,
1177 		   const char *details_text,
1178 		   ...)
1179 {
1180 	va_list varargs;
1181 	int res;
1182 
1183 	va_start (varargs, details_text);
1184 	res = run_simple_dialog_va (job,
1185 				    ignore_close_box,
1186 				    message_type,
1187 				    primary_text,
1188 				    secondary_text,
1189 				    details_text,
1190 				    varargs);
1191 	va_end (varargs);
1192 	return res;
1193 }
1194 #endif
1195 
1196 static int
1197 run_error (CommonJob *job,
1198 	   char *primary_text,
1199 	   char *secondary_text,
1200 	   const char *details_text,
1201 	   gboolean show_all,
1202 	   ...)
1203 {
1204 	va_list varargs;
1205 	int res;
1206 
1207 	va_start (varargs, show_all);
1208 	res = run_simple_dialog_va (job,
1209 				    FALSE,
1210 				    GTK_MESSAGE_ERROR,
1211 				    primary_text,
1212 				    secondary_text,
1213 				    details_text,
1214 				    show_all,
1215 				    varargs);
1216 	va_end (varargs);
1217 	return res;
1218 }
1219 
1220 static int
1221 run_warning (CommonJob *job,
1222 	     char *primary_text,
1223 	     char *secondary_text,
1224 	     const char *details_text,
1225 	     gboolean show_all,
1226 	     ...)
1227 {
1228 	va_list varargs;
1229 	int res;
1230 
1231 	va_start (varargs, show_all);
1232 	res = run_simple_dialog_va (job,
1233 				    FALSE,
1234 				    GTK_MESSAGE_WARNING,
1235 				    primary_text,
1236 				    secondary_text,
1237 				    details_text,
1238 				    show_all,
1239 				    varargs);
1240 	va_end (varargs);
1241 	return res;
1242 }
1243 
1244 static int
1245 run_question (CommonJob *job,
1246 	      char *primary_text,
1247 	      char *secondary_text,
1248 	      const char *details_text,
1249 	      gboolean show_all,
1250 	      ...)
1251 {
1252 	va_list varargs;
1253 	int res;
1254 
1255 	va_start (varargs, show_all);
1256 	res = run_simple_dialog_va (job,
1257 				    FALSE,
1258 				    GTK_MESSAGE_QUESTION,
1259 				    primary_text,
1260 				    secondary_text,
1261 				    details_text,
1262 				    show_all,
1263 				    varargs);
1264 	va_end (varargs);
1265 	return res;
1266 }
1267 
1268 static void
1269 inhibit_power_manager (CommonJob *job, const char *message)
1270 {
1271 	job->inhibit_cookie = gtk_application_inhibit (GTK_APPLICATION (g_application_get_default ()),
1272 						       GTK_WINDOW (job->parent_window),
1273 						       GTK_APPLICATION_INHIBIT_LOGOUT |
1274 						       GTK_APPLICATION_INHIBIT_SUSPEND,
1275 						       message);
1276 }
1277 
1278 static void
1279 abort_job (CommonJob *job)
1280 {
1281 	/* destroy the undo action data too */
1282 	g_clear_object (&job->undo_info);
1283 
1284 	g_cancellable_cancel (job->cancellable);
1285 }
1286 
1287 static gboolean
1288 job_aborted (CommonJob *job)
1289 {
1290 	return g_cancellable_is_cancelled (job->cancellable);
1291 }
1292 
1293 /* Since this happens on a thread we can't use the global prefs object */
1294 static gboolean
1295 should_confirm_trash (void)
1296 {
1297 	GSettings *prefs;
1298 	gboolean confirm_trash;
1299 
1300 	prefs = g_settings_new ("org.gnome.nautilus.preferences");
1301 	confirm_trash = g_settings_get_boolean (prefs, NAUTILUS_PREFERENCES_CONFIRM_TRASH);
1302 	g_object_unref (prefs);
1303 	return confirm_trash;
1304 }
1305 
1306 static gboolean
1307 confirm_delete_from_trash (CommonJob *job,
1308 			   GList *files)
1309 {
1310 	char *prompt;
1311 	int file_count;
1312 	int response;
1313 
1314 	/* Just Say Yes if the preference says not to confirm. */
1315 	if (!should_confirm_trash ()) {
1316 		return TRUE;
1317 	}
1318 
1319 	file_count = g_list_length (files);
1320 	g_assert (file_count > 0);
1321 	
1322 	if (file_count == 1) {
1323 		prompt = f (_("Are you sure you want to permanently delete “%B” "
1324 					    "from the trash?"), files->data);
1325 	} else {
1326 		prompt = f (ngettext("Are you sure you want to permanently delete "
1327 				     "the %'d selected item from the trash?",
1328 				     "Are you sure you want to permanently delete "
1329 				     "the %'d selected items from the trash?",
1330 				     file_count), 
1331 			    file_count);
1332 	}
1333 
1334 	response = run_warning (job,
1335 				prompt,
1336 				f (_("If you delete an item, it will be permanently lost.")),
1337 				NULL,
1338 				FALSE,
1339 				GTK_STOCK_CANCEL, GTK_STOCK_DELETE,
1340 				NULL);
1341 	
1342 	return (response == 1);
1343 }
1344 
1345 static gboolean
1346 confirm_empty_trash (CommonJob *job)
1347 {
1348 	char *prompt;
1349 	int response;
1350 
1351 	/* Just Say Yes if the preference says not to confirm. */
1352 	if (!should_confirm_trash ()) {
1353 		return TRUE;
1354 	}
1355 
1356 	prompt = f (_("Empty all items from Trash?"));
1357 
1358 	response = run_warning (job,
1359 				prompt,
1360 				f(_("All items in the Trash will be permanently deleted.")),
1361 				NULL,
1362 				FALSE,
1363 				GTK_STOCK_CANCEL, _("Empty _Trash"),
1364 				NULL);
1365 
1366 	return (response == 1);
1367 }
1368 
1369 static gboolean
1370 confirm_delete_directly (CommonJob *job,
1371 			 GList *files)
1372 {
1373 	char *prompt;
1374 	int file_count;
1375 	int response;
1376 
1377 	/* Just Say Yes if the preference says not to confirm. */
1378 	if (!should_confirm_trash ()) {
1379 		return TRUE;
1380 	}
1381 
1382 	file_count = g_list_length (files);
1383 	g_assert (file_count > 0);
1384 
1385 	if (can_delete_files_without_confirm (files)) {
1386 		return TRUE;
1387 	}
1388 
1389 	if (file_count == 1) {
1390 		prompt = f (_("Are you sure you want to permanently delete “%B”?"), 
1391 			    files->data);
1392 	} else {
1393 		prompt = f (ngettext("Are you sure you want to permanently delete "
1394 				     "the %'d selected item?",
1395 				     "Are you sure you want to permanently delete "
1396 				     "the %'d selected items?", file_count),
1397 			    file_count);
1398 	}
1399 	
1400 	response = run_warning (job, 
1401 				prompt,
1402 				f (_("If you delete an item, it will be permanently lost.")),
1403 				NULL,
1404 				FALSE,
1405 				GTK_STOCK_CANCEL, GTK_STOCK_DELETE,
1406 				NULL);
1407 
1408 	return response == 1;
1409 }
1410 
1411 static void
1412 report_delete_progress (CommonJob *job,
1413 			SourceInfo *source_info,
1414 			TransferInfo *transfer_info)
1415 {
1416 	int files_left;
1417 	double elapsed, transfer_rate;
1418 	int remaining_time;
1419 	gint64 now;
1420 	char *files_left_s;
1421 
1422 	now = g_get_monotonic_time ();
1423 	if (transfer_info->last_report_time != 0 &&
1424 	    ABS ((gint64)(transfer_info->last_report_time - now)) < 100 * NSEC_PER_MICROSEC) {
1425 		return;
1426 	}
1427 	transfer_info->last_report_time = now;
1428 	
1429 	files_left = source_info->num_files - transfer_info->num_files;
1430 
1431 	/* Races and whatnot could cause this to be negative... */
1432 	if (files_left < 0) {
1433 		files_left = 1;
1434 	}
1435 
1436 	files_left_s = f (ngettext ("%'d file left to delete",
1437 				    "%'d files left to delete",
1438 				    files_left),
1439 			  files_left);
1440 
1441 	nautilus_progress_info_take_status (job->progress,
1442 					    f (_("Deleting files")));
1443 
1444 	elapsed = g_timer_elapsed (job->time, NULL);
1445 	if (elapsed < SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE) {
1446 
1447 		nautilus_progress_info_set_details (job->progress, files_left_s);
1448 	} else {
1449 		char *details, *time_left_s;
1450 		transfer_rate = transfer_info->num_files / elapsed;
1451 		remaining_time = files_left / transfer_rate;
1452 
1453 		/* To translators: %T will expand to a time like "2 minutes".
1454  		 * The singular/plural form will be used depending on the remaining time (i.e. the %T argument).
1455  		 */
1456 		time_left_s = f (ngettext ("%T left",
1457 					   "%T left",
1458 					   seconds_count_format_time_units (remaining_time)),
1459 				 remaining_time);
1460 
1461 		details = g_strconcat (files_left_s, "\xE2\x80\x94", time_left_s, NULL);
1462 		nautilus_progress_info_take_details (job->progress, details);
1463 
1464 		g_free (time_left_s);
1465 	}
1466 
1467 	g_free (files_left_s);
1468 
1469 	if (source_info->num_files != 0) {
1470 		nautilus_progress_info_set_progress (job->progress, transfer_info->num_files, source_info->num_files);
1471 	}
1472 }
1473 
1474 static void delete_file (CommonJob *job, GFile *file,
1475 			 gboolean *skipped_file,
1476 			 SourceInfo *source_info,
1477 			 TransferInfo *transfer_info,
1478 			 gboolean toplevel);
1479 
1480 static void
1481 delete_dir (CommonJob *job, GFile *dir,
1482 	    gboolean *skipped_file,
1483 	    SourceInfo *source_info,
1484 	    TransferInfo *transfer_info,
1485 	    gboolean toplevel)
1486 {
1487 	GFileInfo *info;
1488 	GError *error;
1489 	GFile *file;
1490 	GFileEnumerator *enumerator;
1491 	char *primary, *secondary, *details;
1492 	int response;
1493 	gboolean skip_error;
1494 	gboolean local_skipped_file;
1495 
1496 	local_skipped_file = FALSE;
1497 	
1498 	skip_error = should_skip_readdir_error (job, dir);
1499  retry:
1500 	error = NULL;
1501 	enumerator = g_file_enumerate_children (dir,
1502 						G_FILE_ATTRIBUTE_STANDARD_NAME,
1503 						G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
1504 						job->cancellable,
1505 						&error);
1506 	if (enumerator) {
1507 		error = NULL;
1508 		
1509 		while (!job_aborted (job) &&
1510 		       (info = g_file_enumerator_next_file (enumerator, job->cancellable, skip_error?NULL:&error)) != NULL) {
1511 			file = g_file_get_child (dir,
1512 						 g_file_info_get_name (info));
1513 			delete_file (job, file, &local_skipped_file, source_info, transfer_info, FALSE);
1514 			g_object_unref (file);
1515 			g_object_unref (info);
1516 		}
1517 		g_file_enumerator_close (enumerator, job->cancellable, NULL);
1518 		g_object_unref (enumerator);
1519 		
1520 		if (error && IS_IO_ERROR (error, CANCELLED)) {
1521 			g_error_free (error);
1522 		} else if (error) {
1523 			primary = f (_("Error while deleting."));
1524 			details = NULL;
1525 			
1526 			if (IS_IO_ERROR (error, PERMISSION_DENIED)) {
1527 				secondary = f (_("Files in the folder “%B” cannot be deleted because you do "
1528 						 "not have permissions to see them."), dir);
1529 			} else {
1530 				secondary = f (_("There was an error getting information about the files in the folder “%B”."), dir);
1531 				details = error->message;
1532 			}
1533 			
1534 			response = run_warning (job,
1535 						primary,
1536 						secondary,
1537 						details,
1538 						FALSE,
1539 						GTK_STOCK_CANCEL, _("_Skip files"),
1540 						NULL);
1541 			
1542 			g_error_free (error);
1543 			
1544 			if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1545 				abort_job (job);
1546 			} else if (response == 1) {
1547 				/* Skip: Do Nothing */
1548 				local_skipped_file = TRUE;
1549 			} else {
1550 				g_assert_not_reached ();
1551 			}
1552 		}
1553 		
1554 	} else if (IS_IO_ERROR (error, CANCELLED)) {
1555 		g_error_free (error);
1556 	} else {
1557 		primary = f (_("Error while deleting."));
1558 		details = NULL;
1559 		if (IS_IO_ERROR (error, PERMISSION_DENIED)) {
1560 			secondary = f (_("The folder “%B” cannot be deleted because you do not have "
1561 					 "permissions to read it."), dir);
1562 		} else {
1563 			secondary = f (_("There was an error reading the folder “%B”."), dir);
1564 			details = error->message;
1565 		}
1566 		
1567 		response = run_warning (job,
1568 					primary,
1569 					secondary,
1570 					details,
1571 					FALSE,
1572 					GTK_STOCK_CANCEL, SKIP, RETRY,
1573 					NULL);
1574 
1575 		g_error_free (error);
1576 
1577 		if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1578 			abort_job (job);
1579 		} else if (response == 1) {
1580 			/* Skip: Do Nothing  */
1581 			local_skipped_file = TRUE;
1582 		} else if (response == 2) {
1583 			goto retry;
1584 		} else {
1585 			g_assert_not_reached ();
1586 		}
1587 	}
1588 
1589 	if (!job_aborted (job) &&
1590 	    /* Don't delete dir if there was a skipped file */
1591 	    !local_skipped_file) {
1592 		if (!g_file_delete (dir, job->cancellable, &error)) {
1593 			if (job->skip_all_error) {
1594 				goto skip;
1595 			}
1596 			primary = f (_("Error while deleting."));
1597 			secondary = f (_("Could not remove the folder %B."), dir);
1598 			details = error->message;
1599 			
1600 			response = run_warning (job,
1601 						primary,
1602 						secondary,
1603 						details,
1604 						(source_info->num_files - transfer_info->num_files) > 1,
1605 						GTK_STOCK_CANCEL, SKIP_ALL, SKIP,
1606 						NULL);
1607 			
1608 			if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1609 				abort_job (job);
1610 			} else if (response == 1) { /* skip all */
1611 				job->skip_all_error = TRUE;
1612 				local_skipped_file = TRUE;
1613 			} else if (response == 2) { /* skip */
1614 				local_skipped_file = TRUE;
1615 			} else {
1616 				g_assert_not_reached ();
1617 			}
1618 			
1619 		skip:
1620 			g_error_free (error);
1621 		} else {
1622 			nautilus_file_changes_queue_file_removed (dir);
1623 			transfer_info->num_files ++;
1624 			report_delete_progress (job, source_info, transfer_info);
1625 			return;
1626 		}
1627 	}
1628 
1629 	if (local_skipped_file) {
1630 		*skipped_file = TRUE;
1631 	}
1632 }
1633 
1634 static void
1635 delete_file (CommonJob *job, GFile *file,
1636 	     gboolean *skipped_file,
1637 	     SourceInfo *source_info,
1638 	     TransferInfo *transfer_info,
1639 	     gboolean toplevel)
1640 {
1641 	GError *error;
1642 	char *primary, *secondary, *details;
1643 	int response;
1644 
1645 	if (should_skip_file (job, file)) {
1646 		*skipped_file = TRUE;
1647 		return;
1648 	}
1649 	
1650 	error = NULL;
1651 	if (g_file_delete (file, job->cancellable, &error)) {
1652 		nautilus_file_changes_queue_file_removed (file);
1653 		transfer_info->num_files ++;
1654 		report_delete_progress (job, source_info, transfer_info);
1655 		return;
1656 	}
1657 
1658 	if (IS_IO_ERROR (error, NOT_EMPTY)) {
1659 		g_error_free (error);
1660 		delete_dir (job, file,
1661 			    skipped_file,
1662 			    source_info, transfer_info,
1663 			    toplevel);
1664 		return;
1665 		
1666 	} else if (IS_IO_ERROR (error, CANCELLED)) {
1667 		g_error_free (error);
1668 		
1669 	} else {
1670 		if (job->skip_all_error) {
1671 			goto skip;
1672 		}
1673 		primary = f (_("Error while deleting."));
1674 		secondary = f (_("There was an error deleting %B."), file);
1675 		details = error->message;
1676 		
1677 		response = run_warning (job,
1678 					primary,
1679 					secondary,
1680 					details,
1681 					(source_info->num_files - transfer_info->num_files) > 1,
1682 					GTK_STOCK_CANCEL, SKIP_ALL, SKIP,
1683 					NULL);
1684 
1685 		if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1686 			abort_job (job);
1687 		} else if (response == 1) { /* skip all */
1688 			job->skip_all_error = TRUE;
1689 		} else if (response == 2) { /* skip */
1690 			/* do nothing */
1691 		} else {
1692 			g_assert_not_reached ();
1693 		}
1694 	skip:
1695 		g_error_free (error);
1696 	}
1697 	
1698 	*skipped_file = TRUE;
1699 }
1700 
1701 static void
1702 delete_files (CommonJob *job, GList *files, int *files_skipped)
1703 {
1704 	GList *l;
1705 	GFile *file;
1706 	SourceInfo source_info;
1707 	TransferInfo transfer_info;
1708 	gboolean skipped_file;
1709 	
1710 	if (job_aborted (job)) {
1711 		return;
1712 	}
1713 
1714 	scan_sources (files,
1715 		      &source_info,
1716 		      job,
1717 		      OP_KIND_DELETE);
1718 	if (job_aborted (job)) {
1719 		return;
1720 	}
1721 
1722 	g_timer_start (job->time);
1723 	
1724 	memset (&transfer_info, 0, sizeof (transfer_info));
1725 	report_delete_progress (job, &source_info, &transfer_info);
1726 	
1727 	for (l = files;
1728 	     l != NULL && !job_aborted (job);
1729 	     l = l->next) {
1730 		file = l->data;
1731 
1732 		skipped_file = FALSE;
1733 		delete_file (job, file,
1734 			     &skipped_file,
1735 			     &source_info, &transfer_info,
1736 			     TRUE);
1737 		if (skipped_file) {
1738 			(*files_skipped)++;
1739 		}
1740 	}
1741 }
1742 
1743 static void
1744 report_trash_progress (CommonJob *job,
1745 		       int files_trashed,
1746 		       int total_files)
1747 {
1748 	int files_left;
1749 	char *s;
1750 
1751 	files_left = total_files - files_trashed;
1752 
1753 	nautilus_progress_info_take_status (job->progress,
1754 					    f (_("Moving files to trash")));
1755 
1756 	s = f (ngettext ("%'d file left to trash",
1757 			 "%'d files left to trash",
1758 			 files_left),
1759 	       files_left);
1760 	nautilus_progress_info_take_details (job->progress, s);
1761 
1762 	if (total_files != 0) {
1763 		nautilus_progress_info_set_progress (job->progress, files_trashed, total_files);
1764 	}
1765 }
1766 
1767 
1768 static void
1769 trash_files (CommonJob *job, GList *files, int *files_skipped)
1770 {
1771 	GList *l;
1772 	GFile *file;
1773 	GList *to_delete;
1774 	GError *error;
1775 	int total_files, files_trashed;
1776 	char *primary, *secondary, *details;
1777 	int response;
1778 
1779 	if (job_aborted (job)) {
1780 		return;
1781 	}
1782 
1783 	total_files = g_list_length (files);
1784 	files_trashed = 0;
1785 
1786 	report_trash_progress (job, files_trashed, total_files);
1787 
1788 	to_delete = NULL;
1789 	for (l = files;
1790 	     l != NULL && !job_aborted (job);
1791 	     l = l->next) {
1792 		file = l->data;
1793 
1794 		error = NULL;
1795 
1796 		if (!g_file_trash (file, job->cancellable, &error)) {
1797 			if (job->skip_all_error) {
1798 				(*files_skipped)++;
1799 				goto skip;
1800 			}
1801 
1802 			if (job->delete_all) {
1803 				to_delete = g_list_prepend (to_delete, file);
1804 				goto skip;
1805 			}
1806 
1807 			/* Translators: %B is a file name */
1808 			primary = f (_("“%B” can't be put in the trash. Do you want to delete it immediately?"), file);
1809 			details = NULL;
1810 			secondary = NULL;
1811 			if (!IS_IO_ERROR (error, NOT_SUPPORTED)) {
1812 				details = error->message;
1813 			} else if (!g_file_is_native (file)) {
1814 				secondary = f (_("This remote location does not support sending items to the trash."));
1815 			}
1816 
1817 			response = run_question (job,
1818 						 primary,
1819 						 secondary,
1820 						 details,
1821 						 (total_files - files_trashed) > 1,
1822 						 GTK_STOCK_CANCEL, SKIP_ALL, SKIP, DELETE_ALL, GTK_STOCK_DELETE,
1823 						 NULL);
1824 
1825 			if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1826 				((DeleteJob *) job)->user_cancel = TRUE;				
1827 				abort_job (job);
1828 			} else if (response == 1) { /* skip all */
1829 				(*files_skipped)++;
1830 				job->skip_all_error = TRUE;
1831 			} else if (response == 2) { /* skip */
1832 				(*files_skipped)++;
1833 			} else if (response == 3) { /* delete all */
1834 				to_delete = g_list_prepend (to_delete, file);
1835 				job->delete_all = TRUE;
1836 			} else if (response == 4) { /* delete */
1837 				to_delete = g_list_prepend (to_delete, file);
1838 			}
1839 
1840 		skip:
1841 			g_error_free (error);
1842 			total_files--;
1843 		} else {
1844 			nautilus_file_changes_queue_file_removed (file);
1845 
1846 			if (job->undo_info != NULL) {
1847 				nautilus_file_undo_info_trash_add_file (NAUTILUS_FILE_UNDO_INFO_TRASH (job->undo_info), file);
1848 			}
1849 
1850 			files_trashed++;
1851 			report_trash_progress (job, files_trashed, total_files);
1852 		}
1853 	}
1854 
1855 	if (to_delete) {
1856 		to_delete = g_list_reverse (to_delete);
1857 		delete_files (job, to_delete, files_skipped);
1858 		g_list_free (to_delete);
1859 	}
1860 }
1861 
1862 static gboolean
1863 delete_job_done (gpointer user_data)
1864 {
1865 	DeleteJob *job;
1866 	GHashTable *debuting_uris;
1867 
1868 	job = user_data;
1869 
1870 	g_list_free_full (job->files, g_object_unref);
1871 
1872 	if (job->done_callback) {
1873 		debuting_uris = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL);
1874 		job->done_callback (debuting_uris, job->user_cancel, job->done_callback_data);
1875 		g_hash_table_unref (debuting_uris);
1876 	}
1877 	
1878 	finalize_common ((CommonJob *)job);
1879 
1880 	nautilus_file_changes_consume_changes (TRUE);
1881 
1882 	return FALSE;
1883 }
1884 
1885 static gboolean
1886 delete_job (GIOSchedulerJob *io_job,
1887 	    GCancellable *cancellable,
1888 	    gpointer user_data)
1889 {
1890 	DeleteJob *job = user_data;
1891 	GList *to_trash_files;
1892 	GList *to_delete_files;
1893 	GList *l;
1894 	GFile *file;
1895 	gboolean confirmed;
1896 	CommonJob *common;
1897 	gboolean must_confirm_delete_in_trash;
1898 	gboolean must_confirm_delete;
1899 	int files_skipped;
1900 
1901 	common = (CommonJob *)job;
1902 	common->io_job = io_job;
1903 
1904 	nautilus_progress_info_start (job->common.progress);
1905 	
1906 	to_trash_files = NULL;
1907 	to_delete_files = NULL;
1908 
1909 	must_confirm_delete_in_trash = FALSE;
1910 	must_confirm_delete = FALSE;
1911 	files_skipped = 0;
1912 	
1913 	for (l = job->files; l != NULL; l = l->next) {
1914 		file = l->data;
1915 		
1916 		if (job->try_trash &&
1917 		    g_file_has_uri_scheme (file, "trash")) {
1918 			must_confirm_delete_in_trash = TRUE;
1919 			to_delete_files = g_list_prepend (to_delete_files, file);
1920 		} else if (can_delete_without_confirm (file)) {
1921 			to_delete_files = g_list_prepend (to_delete_files, file);
1922 		} else {
1923 			if (job->try_trash) {
1924 				to_trash_files = g_list_prepend (to_trash_files, file);
1925 			} else {
1926 				must_confirm_delete = TRUE;
1927 				to_delete_files = g_list_prepend (to_delete_files, file);
1928 			}
1929 		}
1930 	}
1931 	
1932 	if (to_delete_files != NULL) {
1933 		to_delete_files = g_list_reverse (to_delete_files);
1934 		confirmed = TRUE;
1935 		if (must_confirm_delete_in_trash) {
1936 			confirmed = confirm_delete_from_trash (common, to_delete_files);
1937 		} else if (must_confirm_delete) {
1938 			confirmed = confirm_delete_directly (common, to_delete_files);
1939 		}
1940 		if (confirmed) {
1941 			delete_files (common, to_delete_files, &files_skipped);
1942 		} else {
1943 			job->user_cancel = TRUE;
1944 		}
1945 	}
1946 	
1947 	if (to_trash_files != NULL) {
1948 		to_trash_files = g_list_reverse (to_trash_files);
1949 		
1950 		trash_files (common, to_trash_files, &files_skipped);
1951 	}
1952 	
1953 	g_list_free (to_trash_files);
1954 	g_list_free (to_delete_files);
1955 	
1956 	if (files_skipped == g_list_length (job->files)) {
1957 		/* User has skipped all files, report user cancel */
1958 		job->user_cancel = TRUE;
1959 	}
1960 
1961 	g_io_scheduler_job_send_to_mainloop_async (io_job,
1962 						   delete_job_done,
1963 						   job,
1964 						   NULL);
1965 
1966 	return FALSE;
1967 }
1968 
1969 static void
1970 trash_or_delete_internal (GList                  *files,
1971 			  GtkWindow              *parent_window,
1972 			  gboolean                try_trash,			  
1973 			  NautilusDeleteCallback  done_callback,
1974 			  gpointer                done_callback_data)
1975 {
1976 	DeleteJob *job;
1977 
1978 	/* TODO: special case desktop icon link files ... */
1979 
1980 	job = op_job_new (DeleteJob, parent_window);
1981 	job->files = eel_g_object_list_copy (files);
1982 	job->try_trash = try_trash;
1983 	job->user_cancel = FALSE;
1984 	job->done_callback = done_callback;
1985 	job->done_callback_data = done_callback_data;
1986 
1987 	if (try_trash) {
1988 		inhibit_power_manager ((CommonJob *)job, _("Trashing Files"));
1989 	} else {
1990 		inhibit_power_manager ((CommonJob *)job, _("Deleting Files"));
1991 	}
1992 	
1993 	if (try_trash && !nautilus_file_undo_manager_pop_flag ()) {
1994 		job->common.undo_info = nautilus_file_undo_info_trash_new (g_list_length (files));
1995 	}
1996 
1997 	g_io_scheduler_push_job (delete_job,
1998 			   job,
1999 			   NULL,
2000 			   0,
2001 			   NULL);
2002 }
2003 
2004 void
2005 nautilus_file_operations_trash_or_delete (GList                  *files,
2006 					  GtkWindow              *parent_window,
2007 					  NautilusDeleteCallback  done_callback,
2008 					  gpointer                done_callback_data)
2009 {
2010 	trash_or_delete_internal (files, parent_window,
2011 				  TRUE,
2012 				  done_callback,  done_callback_data);
2013 }
2014 
2015 void
2016 nautilus_file_operations_delete (GList                  *files, 
2017 				 GtkWindow              *parent_window,
2018 				 NautilusDeleteCallback  done_callback,
2019 				 gpointer                done_callback_data)
2020 {
2021 	trash_or_delete_internal (files, parent_window,
2022 				  FALSE,			  
2023 				  done_callback,  done_callback_data);
2024 }
2025 
2026 
2027 
2028 typedef struct {
2029 	gboolean eject;
2030 	GMount *mount;
2031 	GMountOperation *mount_operation;
2032 	GtkWindow *parent_window;
2033 	NautilusUnmountCallback callback;
2034 	gpointer callback_data;
2035 } UnmountData;
2036 
2037 static void
2038 unmount_data_free (UnmountData *data)
2039 {
2040 	if (data->parent_window) {
2041 		g_object_remove_weak_pointer (G_OBJECT (data->parent_window),
2042 					      (gpointer *) &data->parent_window);
2043 	}
2044 
2045 	g_clear_object (&data->mount_operation);
2046 	g_object_unref (data->mount);
2047 	g_free (data);
2048 }
2049 
2050 static void
2051 unmount_mount_callback (GObject *source_object,
2052 			GAsyncResult *res,
2053 			gpointer user_data)
2054 {
2055 	UnmountData *data = user_data;
2056 	GError *error;
2057 	char *primary;
2058 	gboolean unmounted;
2059 
2060 	error = NULL;
2061 	if (data->eject) {
2062 		unmounted = g_mount_eject_with_operation_finish (G_MOUNT (source_object),
2063 								 res, &error);
2064 	} else {
2065 		unmounted = g_mount_unmount_with_operation_finish (G_MOUNT (source_object),
2066 								   res, &error);
2067 	}
2068 	
2069 	if (! unmounted) {
2070 		if (error->code != G_IO_ERROR_FAILED_HANDLED) {
2071 			if (data->eject) {
2072 				primary = f (_("Unable to eject %V"), source_object);
2073 			} else {
2074 				primary = f (_("Unable to unmount %V"), source_object);
2075 			}
2076 			eel_show_error_dialog (primary,
2077 					       error->message,
2078 					       data->parent_window);
2079 			g_free (primary);
2080 		}
2081 	}
2082 
2083 	if (data->callback) {
2084 		data->callback (data->callback_data);
2085 	}
2086 
2087 	if (error != NULL) {
2088 		g_error_free (error);
2089 	}
2090 
2091 	unmount_data_free (data);
2092 }
2093 
2094 static void
2095 do_unmount (UnmountData *data)
2096 {
2097 	GMountOperation *mount_op;
2098 
2099 	if (data->mount_operation) {
2100 		mount_op = g_object_ref (data->mount_operation);
2101 	} else {
2102 		mount_op = gtk_mount_operation_new (data->parent_window);
2103 	}
2104 	if (data->eject) {
2105 		g_mount_eject_with_operation (data->mount,
2106 					      0,
2107 					      mount_op,
2108 					      NULL,
2109 					      unmount_mount_callback,
2110 					      data);
2111 	} else {
2112 		g_mount_unmount_with_operation (data->mount,
2113 						0,
2114 						mount_op,
2115 						NULL,
2116 						unmount_mount_callback,
2117 						data);
2118 	}
2119 	g_object_unref (mount_op);
2120 }
2121 
2122 static gboolean
2123 dir_has_files (GFile *dir)
2124 {
2125 	GFileEnumerator *enumerator;
2126 	gboolean res;
2127 	GFileInfo *file_info;
2128 
2129 	res = FALSE;
2130 	
2131 	enumerator = g_file_enumerate_children (dir,
2132 						G_FILE_ATTRIBUTE_STANDARD_NAME,
2133 						0,
2134 						NULL, NULL);
2135 	if (enumerator) {
2136 		file_info = g_file_enumerator_next_file (enumerator, NULL, NULL);
2137 		if (file_info != NULL) {
2138 			res = TRUE;
2139 			g_object_unref (file_info);
2140 		}
2141 		
2142 		g_file_enumerator_close (enumerator, NULL, NULL);
2143 		g_object_unref (enumerator);
2144 	}
2145 	
2146 
2147 	return res;
2148 }
2149 
2150 static GList *
2151 get_trash_dirs_for_mount (GMount *mount)
2152 {
2153 	GFile *root;
2154 	GFile *trash;
2155 	char *relpath;
2156 	GList *list;
2157 
2158 	root = g_mount_get_root (mount);
2159 	if (root == NULL) {
2160 		return NULL;
2161 	}
2162 
2163 	list = NULL;
2164 	
2165 	if (g_file_is_native (root)) {
2166 		relpath = g_strdup_printf (".Trash/%d", getuid ());
2167 		trash = g_file_resolve_relative_path (root, relpath);
2168 		g_free (relpath);
2169 
2170 		list = g_list_prepend (list, g_file_get_child (trash, "files"));
2171 		list = g_list_prepend (list, g_file_get_child (trash, "info"));
2172 		
2173 		g_object_unref (trash);
2174 		
2175 		relpath = g_strdup_printf (".Trash-%d", getuid ());
2176 		trash = g_file_get_child (root, relpath);
2177 		g_free (relpath);
2178 
2179 		list = g_list_prepend (list, g_file_get_child (trash, "files"));
2180 		list = g_list_prepend (list, g_file_get_child (trash, "info"));
2181 		
2182 		g_object_unref (trash);
2183 	}
2184 	
2185 	g_object_unref (root);
2186 	
2187 	return list;
2188 }
2189 
2190 static gboolean
2191 has_trash_files (GMount *mount)
2192 {
2193 	GList *dirs, *l;
2194 	GFile *dir;
2195 	gboolean res;
2196 
2197 	dirs = get_trash_dirs_for_mount (mount);
2198 
2199 	res = FALSE;
2200 
2201 	for (l = dirs; l != NULL; l = l->next) {
2202 		dir = l->data;
2203 
2204 		if (dir_has_files (dir)) {
2205 			res = TRUE;
2206 			break;
2207 		}
2208 	}
2209 
2210 	g_list_free_full (dirs, g_object_unref);
2211 	
2212 	return res;
2213 }
2214 
2215 
2216 static gint
2217 prompt_empty_trash (GtkWindow *parent_window)
2218 {
2219 	gint                    result;
2220 	GtkWidget               *dialog;
2221 	GdkScreen               *screen;
2222 
2223 	screen = NULL;
2224 	if (parent_window != NULL) {
2225 		screen = gtk_widget_get_screen (GTK_WIDGET (parent_window));
2226 	}
2227 
2228 	/* Do we need to be modal ? */
2229 	dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL,
2230 					 GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
2231 					 _("Do you want to empty the trash before you unmount?"));
2232 	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
2233 						  _("In order to regain the "
2234 						    "free space on this volume "
2235 						    "the trash must be emptied. "
2236 						    "All trashed items on the volume "
2237 						    "will be permanently lost."));
2238 	gtk_dialog_add_buttons (GTK_DIALOG (dialog), 
2239 	                        _("Do _not Empty Trash"), GTK_RESPONSE_REJECT, 
2240 	                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, 
2241 	                        _("Empty _Trash"), GTK_RESPONSE_ACCEPT, NULL);
2242 	gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
2243 	gtk_window_set_title (GTK_WINDOW (dialog), ""); /* as per HIG */
2244 	gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), TRUE);
2245 	if (screen) {
2246 		gtk_window_set_screen (GTK_WINDOW (dialog), screen);
2247 	}
2248 	atk_object_set_role (gtk_widget_get_accessible (dialog), ATK_ROLE_ALERT);
2249 	gtk_window_set_wmclass (GTK_WINDOW (dialog), "empty_trash",
2250 				"Nautilus");
2251 	
2252 	/* Make transient for the window group */
2253 	gtk_widget_realize (dialog);
2254 	if (screen != NULL) {
2255 		gdk_window_set_transient_for (gtk_widget_get_window (GTK_WIDGET (dialog)),
2256 				      		gdk_screen_get_root_window (screen));
2257 	}
2258 	
2259 	result = gtk_dialog_run (GTK_DIALOG (dialog));
2260 	gtk_widget_destroy (dialog);
2261 	return result;
2262 }
2263 
2264 static void
2265 empty_trash_for_unmount_done (gboolean success,
2266 			      gpointer user_data)
2267 {
2268 	UnmountData *data = user_data;
2269 	do_unmount (data);
2270 }
2271 
2272 void
2273 nautilus_file_operations_unmount_mount_full (GtkWindow                      *parent_window,
2274 					     GMount                         *mount,
2275 					     GMountOperation                *mount_operation,
2276 					     gboolean                        eject,
2277 					     gboolean                        check_trash,
2278 					     NautilusUnmountCallback         callback,
2279 					     gpointer                        callback_data)
2280 {
2281 	UnmountData *data;
2282 	int response;
2283 
2284 	data = g_new0 (UnmountData, 1);
2285 	data->callback = callback;
2286 	data->callback_data = callback_data;
2287 	if (parent_window) {
2288 		data->parent_window = parent_window;
2289 		g_object_add_weak_pointer (G_OBJECT (data->parent_window),
2290 					   (gpointer *) &data->parent_window);
2291 		
2292 	}
2293 	if (mount_operation) {
2294 		data->mount_operation = g_object_ref (mount_operation);
2295 	}
2296 	data->eject = eject;
2297 	data->mount = g_object_ref (mount);
2298 
2299 	if (check_trash && has_trash_files (mount)) {
2300 		response = prompt_empty_trash (parent_window);
2301 
2302 		if (response == GTK_RESPONSE_ACCEPT) {
2303 			EmptyTrashJob *job;
2304 			
2305 			job = op_job_new (EmptyTrashJob, parent_window);
2306 			job->should_confirm = FALSE;
2307 			job->trash_dirs = get_trash_dirs_for_mount (mount);
2308 			job->done_callback = empty_trash_for_unmount_done;
2309 			job->done_callback_data = data;
2310 			g_io_scheduler_push_job (empty_trash_job,
2311 					   job,
2312 					   NULL,
2313 					   0,
2314 					   NULL);
2315 			return;
2316 		} else if (response == GTK_RESPONSE_CANCEL) {
2317 			if (callback) {
2318 				callback (callback_data);
2319 			}
2320 
2321 			unmount_data_free (data);
2322 			return;
2323 		}
2324 	}
2325 	
2326 	do_unmount (data);
2327 }
2328 
2329 void
2330 nautilus_file_operations_unmount_mount (GtkWindow                      *parent_window,
2331 					GMount                         *mount,
2332 					gboolean                        eject,
2333 					gboolean                        check_trash)
2334 {
2335 	nautilus_file_operations_unmount_mount_full (parent_window, mount, NULL, eject,
2336 						     check_trash, NULL, NULL);
2337 }
2338 
2339 static void
2340 mount_callback_data_notify (gpointer data,
2341 			    GObject *object)
2342 {
2343 	GMountOperation *mount_op;
2344 
2345 	mount_op = G_MOUNT_OPERATION (data);
2346 	g_object_set_data (G_OBJECT (mount_op), "mount-callback", NULL);
2347 	g_object_set_data (G_OBJECT (mount_op), "mount-callback-data", NULL);
2348 }
2349 
2350 static void
2351 volume_mount_cb (GObject *source_object,
2352 		 GAsyncResult *res,
2353 		 gpointer user_data)
2354 {
2355 	NautilusMountCallback mount_callback;
2356 	GObject *mount_callback_data_object;
2357 	GMountOperation *mount_op = user_data;
2358 	GError *error;
2359 	char *primary;
2360 	char *name;
2361 	gboolean success;
2362 
2363 	success = TRUE;
2364 	error = NULL;
2365 	if (!g_volume_mount_finish (G_VOLUME (source_object), res, &error)) {
2366 		if (error->code != G_IO_ERROR_FAILED_HANDLED &&
2367                     error->code != G_IO_ERROR_ALREADY_MOUNTED) {
2368 			GtkWindow *parent;
2369 
2370 			parent = gtk_mount_operation_get_parent (GTK_MOUNT_OPERATION (mount_op));
2371 			name = g_volume_get_name (G_VOLUME (source_object));
2372 			primary = g_strdup_printf (_("Unable to access “%s”"), name);
2373 			g_free (name);
2374 			success = FALSE;
2375 			eel_show_error_dialog (primary,
2376 					       error->message,
2377 					       parent);
2378 			g_free (primary);
2379 		}
2380 		g_error_free (error);
2381 	}
2382 
2383 	mount_callback = (NautilusMountCallback)
2384 		g_object_get_data (G_OBJECT (mount_op), "mount-callback");
2385 	mount_callback_data_object =
2386 		g_object_get_data (G_OBJECT (mount_op), "mount-callback-data");
2387 
2388 	if (mount_callback != NULL) {
2389 		(* mount_callback) (G_VOLUME (source_object),
2390 				    success,
2391 				    mount_callback_data_object);
2392 
2393 	    	if (mount_callback_data_object != NULL) {
2394 			g_object_weak_unref (mount_callback_data_object,
2395 					     mount_callback_data_notify,
2396 					     mount_op);
2397 		}
2398 	}
2399 
2400 	g_object_unref (mount_op);
2401 }
2402 
2403 
2404 void
2405 nautilus_file_operations_mount_volume (GtkWindow *parent_window,
2406 				       GVolume *volume)
2407 {
2408 	nautilus_file_operations_mount_volume_full (parent_window, volume,
2409 						    NULL, NULL);
2410 }
2411 
2412 void
2413 nautilus_file_operations_mount_volume_full (GtkWindow *parent_window,
2414 					    GVolume *volume,
2415 					    NautilusMountCallback mount_callback,
2416 					    GObject *mount_callback_data_object)
2417 {
2418 	GMountOperation *mount_op;
2419 
2420 	mount_op = gtk_mount_operation_new (parent_window);
2421 	g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
2422 	g_object_set_data (G_OBJECT (mount_op),
2423 			   "mount-callback",
2424 			   mount_callback);
2425 
2426 	if (mount_callback != NULL &&
2427 	    mount_callback_data_object != NULL) {
2428 		g_object_weak_ref (mount_callback_data_object,
2429 				   mount_callback_data_notify,
2430 				   mount_op);
2431 	}
2432 	g_object_set_data (G_OBJECT (mount_op),
2433 			   "mount-callback-data",
2434 			   mount_callback_data_object);
2435 
2436 	g_volume_mount (volume, 0, mount_op, NULL, volume_mount_cb, mount_op);
2437 }
2438 
2439 static void
2440 report_count_progress (CommonJob *job,
2441 		       SourceInfo *source_info)
2442 {
2443 	char *s;
2444 
2445 	switch (source_info->op) {
2446 	default:
2447 	case OP_KIND_COPY:
2448 		s = f (ngettext("Preparing to copy %'d file (%S)",
2449 		                "Preparing to copy %'d files (%S)",
2450 		                source_info->num_files),
2451 		       source_info->num_files, source_info->num_bytes);
2452 		break;
2453 	case OP_KIND_MOVE:
2454 		s = f (ngettext("Preparing to move %'d file (%S)",
2455 		                "Preparing to move %'d files (%S)",
2456 		                source_info->num_files),
2457 		       source_info->num_files, source_info->num_bytes);
2458 		break;
2459 	case OP_KIND_DELETE:
2460 		s = f (ngettext("Preparing to delete %'d file (%S)",
2461 		                "Preparing to delete %'d files (%S)",
2462 		                source_info->num_files),
2463 		       source_info->num_files, source_info->num_bytes);
2464 		break;
2465 	case OP_KIND_TRASH:
2466 		s = f (ngettext("Preparing to trash %'d file",
2467 		                "Preparing to trash %'d files",
2468 		                source_info->num_files),
2469 		       source_info->num_files);
2470 		break;
2471 	} 
2472 
2473 	nautilus_progress_info_take_details (job->progress, s);
2474 	nautilus_progress_info_pulse_progress (job->progress);
2475 }
2476 
2477 static void
2478 count_file (GFileInfo *info,
2479 	    CommonJob *job,
2480 	    SourceInfo *source_info)
2481 {
2482 	source_info->num_files += 1;
2483 	source_info->num_bytes += g_file_info_get_size (info);
2484 
2485 	if (source_info->num_files_since_progress++ > 100) {
2486 		report_count_progress (job, source_info);
2487 		source_info->num_files_since_progress = 0;
2488 	}
2489 }
2490 
2491 static char *
2492 get_scan_primary (OpKind kind)
2493 {
2494 	switch (kind) {
2495 	default:
2496 	case OP_KIND_COPY:
2497 		return f (_("Error while copying."));
2498 	case OP_KIND_MOVE:
2499 		return f (_("Error while moving."));
2500 	case OP_KIND_DELETE:
2501 		return f (_("Error while deleting."));
2502 	case OP_KIND_TRASH:
2503 		return f (_("Error while moving files to trash."));
2504 	}
2505 }
2506 
2507 static void
2508 scan_dir (GFile *dir,
2509 	  SourceInfo *source_info,
2510 	  CommonJob *job,
2511 	  GQueue *dirs)
2512 {
2513 	GFileInfo *info;
2514 	GError *error;
2515 	GFile *subdir;
2516 	GFileEnumerator *enumerator;
2517 	char *primary, *secondary, *details;
2518 	int response;
2519 	SourceInfo saved_info;
2520 
2521 	saved_info = *source_info;
2522 
2523  retry:
2524 	error = NULL;
2525 	enumerator = g_file_enumerate_children (dir,
2526 						G_FILE_ATTRIBUTE_STANDARD_NAME","
2527 						G_FILE_ATTRIBUTE_STANDARD_TYPE","
2528 						G_FILE_ATTRIBUTE_STANDARD_SIZE,
2529 						G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
2530 						job->cancellable,
2531 						&error);
2532 	if (enumerator) {
2533 		error = NULL;
2534 		while ((info = g_file_enumerator_next_file (enumerator, job->cancellable, &error)) != NULL) {
2535 			count_file (info, job, source_info);
2536 
2537 			if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
2538 				subdir = g_file_get_child (dir,
2539 							   g_file_info_get_name (info));
2540 				
2541 				/* Push to head, since we want depth-first */
2542 				g_queue_push_head (dirs, subdir);
2543 			}
2544 
2545 			g_object_unref (info);
2546 		}
2547 		g_file_enumerator_close (enumerator, job->cancellable, NULL);
2548 		g_object_unref (enumerator);
2549 		
2550 		if (error && IS_IO_ERROR (error, CANCELLED)) {
2551 			g_error_free (error);
2552 		} else if (error) {
2553 			primary = get_scan_primary (source_info->op);
2554 			details = NULL;
2555 			
2556 			if (IS_IO_ERROR (error, PERMISSION_DENIED)) {
2557 				secondary = f (_("Files in the folder “%B” cannot be handled because you do "
2558 						 "not have permissions to see them."), dir);
2559 			} else {
2560 				secondary = f (_("There was an error getting information about the files in the folder “%B”."), dir);
2561 				details = error->message;
2562 			}
2563 			
2564 			response = run_warning (job,
2565 						primary,
2566 						secondary,
2567 						details,
2568 						FALSE,
2569 						GTK_STOCK_CANCEL, RETRY, SKIP,
2570 						NULL);
2571 
2572 			g_error_free (error);
2573 			
2574 			if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2575 				abort_job (job);
2576 			} else if (response == 1) {
2577 				*source_info = saved_info;
2578 				goto retry;
2579 			} else if (response == 2) {
2580 				skip_readdir_error (job, dir);
2581 			} else {
2582 				g_assert_not_reached ();
2583 			}
2584 		}
2585 		
2586 	} else if (job->skip_all_error) {
2587 		g_error_free (error);
2588 		skip_file (job, dir);
2589 	} else if (IS_IO_ERROR (error, CANCELLED)) {
2590 		g_error_free (error);
2591 	} else {	
2592 		primary = get_scan_primary (source_info->op);
2593 		details = NULL;
2594 		
2595 		if (IS_IO_ERROR (error, PERMISSION_DENIED)) {
2596 			secondary = f (_("The folder “%B” cannot be handled because you do not have "
2597 					 "permissions to read it."), dir);
2598 		} else {
2599 			secondary = f (_("There was an error reading the folder “%B”."), dir);
2600 			details = error->message;
2601 		}
2602 		/* set show_all to TRUE here, as we don't know how many
2603 		 * files we'll end up processing yet.
2604 		 */
2605 		response = run_warning (job,
2606 					primary,
2607 					secondary,
2608 					details,
2609 					TRUE,
2610 					GTK_STOCK_CANCEL, SKIP_ALL, SKIP, RETRY,
2611 					NULL);
2612 		
2613 		g_error_free (error);
2614 
2615 		if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2616 			abort_job (job);
2617 		} else if (response == 1 || response == 2) {
2618 			if (response == 1) {
2619 				job->skip_all_error = TRUE;
2620 			}
2621 			skip_file (job, dir);
2622 		} else if (response == 3) {
2623 			goto retry;
2624 		} else {
2625 			g_assert_not_reached ();
2626 		}
2627 	}
2628 }	
2629 
2630 static void
2631 scan_file (GFile *file,
2632 	   SourceInfo *source_info,
2633 	   CommonJob *job)
2634 {
2635 	GFileInfo *info;
2636 	GError *error;
2637 	GQueue *dirs;
2638 	GFile *dir;
2639 	char *primary;
2640 	char *secondary;
2641 	char *details;
2642 	int response;
2643 
2644 	dirs = g_queue_new ();
2645 	
2646  retry:
2647 	error = NULL;
2648 	info = g_file_query_info (file, 
2649 				  G_FILE_ATTRIBUTE_STANDARD_TYPE","
2650 				  G_FILE_ATTRIBUTE_STANDARD_SIZE,
2651 				  G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
2652 				  job->cancellable,
2653 				  &error);
2654 
2655 	if (info) {
2656 		count_file (info, job, source_info);
2657 
2658 		if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
2659 			g_queue_push_head (dirs, g_object_ref (file));
2660 		}
2661 		
2662 		g_object_unref (info);
2663 	} else if (job->skip_all_error) {
2664 		g_error_free (error);
2665 		skip_file (job, file);
2666 	} else if (IS_IO_ERROR (error, CANCELLED)) {
2667 		g_error_free (error);
2668 	} else {
2669 		primary = get_scan_primary (source_info->op);
2670 		details = NULL;
2671 		
2672 		if (IS_IO_ERROR (error, PERMISSION_DENIED)) {
2673 			secondary = f (_("The file “%B” cannot be handled because you do not have "
2674 					 "permissions to read it."), file);
2675 		} else {
2676 			secondary = f (_("There was an error getting information about “%B”."), file);
2677 			details = error->message;
2678 		}
2679 		/* set show_all to TRUE here, as we don't know how many
2680 		 * files we'll end up processing yet.
2681 		 */
2682 		response = run_warning (job,
2683 					primary,
2684 					secondary,
2685 					details,
2686 					TRUE,
2687 					GTK_STOCK_CANCEL, SKIP_ALL, SKIP, RETRY,
2688 					NULL);
2689 		
2690 		g_error_free (error);
2691 
2692 		if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2693 			abort_job (job);
2694 		} else if (response == 1 || response == 2) {
2695 			if (response == 1) {
2696 				job->skip_all_error = TRUE;
2697 			}
2698 			skip_file (job, file);
2699 		} else if (response == 3) {
2700 			goto retry;
2701 		} else {
2702 			g_assert_not_reached ();
2703 		}
2704 	}
2705 		
2706 	while (!job_aborted (job) && 
2707 	       (dir = g_queue_pop_head (dirs)) != NULL) {
2708 		scan_dir (dir, source_info, job, dirs);
2709 		g_object_unref (dir);
2710 	}
2711 
2712 	/* Free all from queue if we exited early */
2713 	g_queue_foreach (dirs, (GFunc)g_object_unref, NULL);
2714 	g_queue_free (dirs);
2715 }
2716 
2717 static void
2718 scan_sources (GList *files,
2719 	      SourceInfo *source_info,
2720 	      CommonJob *job,
2721 	      OpKind kind)
2722 {
2723 	GList *l;
2724 	GFile *file;
2725 
2726 	memset (source_info, 0, sizeof (SourceInfo));
2727 	source_info->op = kind;
2728 
2729 	report_count_progress (job, source_info);
2730 	
2731 	for (l = files; l != NULL && !job_aborted (job); l = l->next) {
2732 		file = l->data;
2733 
2734 		scan_file (file,
2735 			   source_info,
2736 			   job);
2737 	}
2738 
2739 	/* Make sure we report the final count */
2740 	report_count_progress (job, source_info);
2741 }
2742 
2743 static void
2744 verify_destination (CommonJob *job,
2745 		    GFile *dest,
2746 		    char **dest_fs_id,
2747 		    goffset required_size)
2748 {
2749 	GFileInfo *info, *fsinfo;
2750 	GError *error;
2751 	guint64 free_size;
2752 	guint64 size_difference;
2753 	char *primary, *secondary, *details;
2754 	int response;
2755 	GFileType file_type;
2756 	gboolean dest_is_symlink = FALSE;
2757 
2758 	if (dest_fs_id) {
2759 		*dest_fs_id = NULL;
2760 	}
2761 
2762  retry:
2763 	
2764 	error = NULL;
2765 	info = g_file_query_info (dest, 
2766 				  G_FILE_ATTRIBUTE_STANDARD_TYPE","
2767 				  G_FILE_ATTRIBUTE_ID_FILESYSTEM,
2768 				  dest_is_symlink ? G_FILE_QUERY_INFO_NONE : G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
2769 				  job->cancellable,
2770 				  &error);
2771 
2772 	if (info == NULL) {
2773 		if (IS_IO_ERROR (error, CANCELLED)) {
2774 			g_error_free (error);
2775 			return;
2776 		}
2777 		
2778 		primary = f (_("Error while copying to “%B”."), dest);
2779 		details = NULL;
2780 		
2781 		if (IS_IO_ERROR (error, PERMISSION_DENIED)) {
2782 			secondary = f (_("You do not have permissions to access the destination folder."));
2783 		} else {
2784 			secondary = f (_("There was an error getting information about the destination."));
2785 			details = error->message;
2786 		}
2787 
2788 		response = run_error (job,
2789 				      primary,
2790 				      secondary,
2791 				      details,
2792 				      FALSE,
2793 				      GTK_STOCK_CANCEL, RETRY,
2794 				      NULL);
2795 		
2796 		g_error_free (error);
2797 
2798 		if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2799 			abort_job (job);
2800 		} else if (response == 1) {
2801 			goto retry;
2802 		} else {
2803 			g_assert_not_reached ();
2804 		}
2805 
2806 		return;
2807 	}
2808 
2809 	file_type = g_file_info_get_file_type (info);
2810 	if (!dest_is_symlink && file_type == G_FILE_TYPE_SYMBOLIC_LINK) {
2811 		/* Record that destination is a symlink and do real stat() once again */
2812 		dest_is_symlink = TRUE;
2813 		g_object_unref (info);
2814 		goto retry;
2815 	}
2816 
2817 	if (dest_fs_id) {
2818 		*dest_fs_id =
2819 			g_strdup (g_file_info_get_attribute_string (info,
2820 								    G_FILE_ATTRIBUTE_ID_FILESYSTEM));
2821 	}
2822 	
2823 	g_object_unref (info);
2824 	
2825 	if (file_type != G_FILE_TYPE_DIRECTORY) {
2826 		primary = f (_("Error while copying to “%B”."), dest);
2827 		secondary = f (_("The destination is not a folder."));
2828 
2829 		run_error (job,
2830 			   primary,
2831 			   secondary,
2832 			   NULL,
2833 			   FALSE,
2834 			   GTK_STOCK_CANCEL,
2835 			   NULL);
2836 		
2837 		abort_job (job);
2838 		return;
2839 	}
2840 	
2841 	if (dest_is_symlink) {
2842 		/* We can't reliably statfs() destination if it's a symlink, thus not doing any further checks. */
2843 		return;
2844 	}
2845 	
2846 	fsinfo = g_file_query_filesystem_info (dest,
2847 					       G_FILE_ATTRIBUTE_FILESYSTEM_FREE","
2848 					       G_FILE_ATTRIBUTE_FILESYSTEM_READONLY,
2849 					       job->cancellable,
2850 					       NULL);
2851 	if (fsinfo == NULL) {
2852 		/* All sorts of things can go wrong getting the fs info (like not supported)
2853 		 * only check these things if the fs returns them
2854 		 */
2855 		return;
2856 	}
2857 	
2858 	if (required_size > 0 &&
2859 	    g_file_info_has_attribute (fsinfo, G_FILE_ATTRIBUTE_FILESYSTEM_FREE)) {
2860 		free_size = g_file_info_get_attribute_uint64 (fsinfo,
2861 							      G_FILE_ATTRIBUTE_FILESYSTEM_FREE);
2862 		
2863 		if (free_size < required_size) {
2864 			size_difference = required_size - free_size;
2865 			primary = f (_("Error while copying to “%B”."), dest);
2866 			secondary = f (_("There is not enough space on the destination. Try to remove files to make space."));
2867 			
2868 			details = f (_("%S more space is required to copy to the destination."), size_difference);
2869 			
2870 			response = run_warning (job,
2871 						primary,
2872 						secondary,
2873 						details,
2874 						FALSE,
2875 						GTK_STOCK_CANCEL,
2876 						COPY_FORCE,
2877 						RETRY,
2878 						NULL);
2879 			
2880 			if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2881 				abort_job (job);
2882 			} else if (response == 2) {
2883 				goto retry;
2884 			} else if (response == 1) {
2885 				/* We are forced to copy - just fall through ... */
2886 			} else {
2887 				g_assert_not_reached ();
2888 			}
2889 		}
2890 	}
2891 	
2892 	if (!job_aborted (job) &&
2893 	    g_file_info_get_attribute_boolean (fsinfo,
2894 					       G_FILE_ATTRIBUTE_FILESYSTEM_READONLY)) {
2895 		primary = f (_("Error while copying to “%B”."), dest);
2896 		secondary = f (_("The destination is read-only."));
2897 
2898 		run_error (job,
2899 			   primary,
2900 			   secondary,
2901 			   NULL,
2902 			   FALSE,
2903 			   GTK_STOCK_CANCEL,
2904 			   NULL);
2905 		
2906 		g_error_free (error);
2907 
2908 		abort_job (job);
2909 	}
2910 	
2911 	g_object_unref (fsinfo);
2912 }
2913 
2914 static void
2915 report_copy_progress (CopyMoveJob *copy_job,
2916 		      SourceInfo *source_info,
2917 		      TransferInfo *transfer_info)
2918 {
2919 	int files_left;
2920 	goffset total_size;
2921 	double elapsed, transfer_rate;
2922 	int remaining_time;
2923 	guint64 now;
2924 	CommonJob *job;
2925 	gboolean is_move;
2926 
2927 	job = (CommonJob *)copy_job;
2928 
2929 	is_move = copy_job->is_move;
2930 	
2931 	now = g_get_monotonic_time ();
2932 
2933 	if (transfer_info->last_report_time != 0 &&
2934 	    ABS ((gint64)(transfer_info->last_report_time - now)) < 100 * NSEC_PER_MICROSEC) {
2935 		return;
2936 	}
2937 	transfer_info->last_report_time = now;
2938 	
2939 	files_left = source_info->num_files - transfer_info->num_files;
2940 
2941 	/* Races and whatnot could cause this to be negative... */
2942 	if (files_left < 0) {
2943 		files_left = 1;
2944 	}
2945 
2946 	if (files_left != transfer_info->last_reported_files_left ||
2947 	    transfer_info->last_reported_files_left == 0) {
2948 		/* Avoid changing this unless files_left changed since last time */
2949 		transfer_info->last_reported_files_left = files_left;
2950 		
2951 		if (source_info->num_files == 1) {
2952 			if (copy_job->destination != NULL) {
2953 				nautilus_progress_info_take_status (job->progress,
2954 								    f (is_move ?
2955 								       _("Moving “%B” to “%B”"):
2956 								       _("Copying “%B” to “%B”"),
2957 								       copy_job->fake_display_source != NULL ?
2958 								       copy_job->fake_display_source :
2959 								       (GFile *)copy_job->files->data,
2960 								       copy_job->destination));
2961 			} else {
2962 				nautilus_progress_info_take_status (job->progress,
2963 								    f (_("Duplicating “%B”"),
2964 								       (GFile *)copy_job->files->data));
2965 			}
2966 		} else if (copy_job->files != NULL &&
2967 			   copy_job->files->next == NULL) {
2968 			if (copy_job->destination != NULL) {
2969 				nautilus_progress_info_take_status (job->progress,
2970 								    f (is_move ?
2971 								       _("Moving file %'d of %'d (in “%B”) to “%B”")
2972 								       :
2973 								       _("Copying file %'d of %'d (in “%B”) to “%B”"),
2974 								       transfer_info->num_files + 1,
2975 								       source_info->num_files,
2976 								       (GFile *)copy_job->files->data,
2977 								       copy_job->destination));
2978 			} else {
2979 				nautilus_progress_info_take_status (job->progress,
2980 								    f (_("Duplicating file %'d of %'d (in “%B”)"),
2981 								       transfer_info->num_files + 1,
2982 								       source_info->num_files,
2983 								       (GFile *)copy_job->files->data));
2984 			}
2985 		} else {
2986 			if (copy_job->destination != NULL) {
2987 				nautilus_progress_info_take_status (job->progress,
2988 								    f (is_move ?
2989 								       _("Moving file %'d of %'d to “%B”")
2990 								       :
2991 								       _ ("Copying file %'d of %'d to “%B”"),
2992 								       transfer_info->num_files + 1,
2993 								       source_info->num_files,
2994 								       copy_job->destination));
2995 			} else {
2996 				nautilus_progress_info_take_status (job->progress,
2997 								    f (_("Duplicating file %'d of %'d"),
2998 								       transfer_info->num_files + 1,
2999 								       source_info->num_files));
3000 			}
3001 		}
3002 	}
3003 	
3004 	total_size = MAX (source_info->num_bytes, transfer_info->num_bytes);
3005 	
3006 	elapsed = g_timer_elapsed (job->time, NULL);
3007 	transfer_rate = 0;
3008 	if (elapsed > 0) {
3009 		transfer_rate = transfer_info->num_bytes / elapsed;
3010 	}
3011 
3012 	if (elapsed < SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE &&
3013 	    transfer_rate > 0) {
3014 		char *s;
3015 		/* To translators: %S will expand to a size like "2 bytes" or "3 MB", so something like "4 kb of 4 MB" */		
3016 		s = f (_("%S of %S"), transfer_info->num_bytes, total_size);
3017 		nautilus_progress_info_take_details (job->progress, s);
3018 	} else {
3019 		char *s;
3020 		remaining_time = (total_size - transfer_info->num_bytes) / transfer_rate;
3021 
3022 		/* To translators: %S will expand to a size like "2 bytes" or "3 MB", %T to a time duration like
3023 		 * "2 minutes". So the whole thing will be something like "2 kb of 4 MB -- 2 hours left (4kb/sec)"
3024 		 *
3025 		 * The singular/plural form will be used depending on the remaining time (i.e. the %T argument).
3026 		 */		
3027 		s = f (ngettext ("%S of %S \xE2\x80\x94 %T left (%S/sec)",
3028 				 "%S of %S \xE2\x80\x94 %T left (%S/sec)",
3029 				 seconds_count_format_time_units (remaining_time)),
3030 		       transfer_info->num_bytes, total_size,
3031 		       remaining_time,
3032 		       (goffset)transfer_rate);
3033 		nautilus_progress_info_take_details (job->progress, s);
3034 	}
3035 
3036 	nautilus_progress_info_set_progress (job->progress, transfer_info->num_bytes, total_size);
3037 }
3038 
3039 static int
3040 get_max_name_length (GFile *file_dir)
3041 {
3042 	int max_length;
3043 	char *dir;
3044 	long max_path;
3045 	long max_name;
3046 
3047 	max_length = -1;
3048 
3049 	if (!g_file_has_uri_scheme (file_dir, "file"))
3050 		return max_length;
3051 
3052 	dir = g_file_get_path (file_dir);
3053 	if (!dir)
3054 		return max_length;
3055 
3056 	max_path = pathconf (dir, _PC_PATH_MAX);
3057 	max_name = pathconf (dir, _PC_NAME_MAX);
3058 
3059 	if (max_name == -1 && max_path == -1) {
3060 		max_length = -1;
3061 	} else if (max_name == -1 && max_path != -1) {
3062 		max_length = max_path - (strlen (dir) + 1);
3063 	} else if (max_name != -1 && max_path == -1) {
3064 		max_length = max_name;
3065 	} else {
3066 		int leftover;
3067 
3068 		leftover = max_path - (strlen (dir) + 1);
3069 
3070 		max_length = MIN (leftover, max_name);
3071 	}
3072 
3073 	g_free (dir);
3074 
3075 	return max_length;
3076 }
3077 
3078 #define FAT_FORBIDDEN_CHARACTERS "/:;*?\"<>"
3079 
3080 static gboolean
3081 str_replace (char *str,
3082 	     const char *chars_to_replace,
3083 	     char replacement)
3084 {
3085 	gboolean success;
3086 	int i;
3087 
3088 	success = FALSE;
3089 	for (i = 0; str[i] != '\0'; i++) {
3090 		if (strchr (chars_to_replace, str[i])) {
3091 			success = TRUE;
3092 			str[i] = replacement;
3093 		}
3094 	}
3095 
3096 	return success;
3097 }
3098 
3099 static gboolean
3100 make_file_name_valid_for_dest_fs (char *filename,
3101 				 const char *dest_fs_type)
3102 {
3103 	if (dest_fs_type != NULL && filename != NULL) {
3104 		if (!strcmp (dest_fs_type, "fat")  ||
3105 		    !strcmp (dest_fs_type, "vfat") ||
3106 		    !strcmp (dest_fs_type, "msdos") ||
3107 		    !strcmp (dest_fs_type, "msdosfs")) {
3108 			gboolean ret;
3109 			int i, old_len;
3110 
3111 			ret = str_replace (filename, FAT_FORBIDDEN_CHARACTERS, '_');
3112 
3113 			old_len = strlen (filename);
3114 			for (i = 0; i < old_len; i++) {
3115 				if (filename[i] != ' ') {
3116 					g_strchomp (filename);
3117 					ret |= (old_len != strlen (filename));
3118 					break;
3119 				}
3120 			}
3121 
3122 			return ret;
3123 		}
3124 	}
3125 
3126 	return FALSE;
3127 }
3128 
3129 static GFile *
3130 get_unique_target_file (GFile *src,
3131 			GFile *dest_dir,
3132 			gboolean same_fs,
3133 			const char *dest_fs_type,
3134 			int count)
3135 {
3136 	const char *editname, *end;
3137 	char *basename, *new_name;
3138 	GFileInfo *info;
3139 	GFile *dest;
3140 	int max_length;
3141 
3142 	max_length = get_max_name_length (dest_dir);
3143 	
3144 	dest = NULL;
3145 	info = g_file_query_info (src,
3146 				  G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME,
3147 				  0, NULL, NULL);
3148 	if (info != NULL) {
3149 		editname = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME);
3150 		
3151 		if (editname != NULL) {
3152 			new_name = get_duplicate_name (editname, count, max_length);
3153 			make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3154 			dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL);
3155 			g_free (new_name);
3156 		}
3157 		
3158 		g_object_unref (info);
3159 	}
3160 
3161 	if (dest == NULL) {
3162 		basename = g_file_get_basename (src);
3163 
3164 		if (g_utf8_validate (basename, -1, NULL)) {
3165 			new_name = get_duplicate_name (basename, count, max_length);
3166 			make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3167 			dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL);
3168 			g_free (new_name);
3169 		} 
3170 
3171 		if (dest == NULL) {
3172 			end = strrchr (basename, '.');
3173 			if (end != NULL) {
3174 				count += atoi (end + 1);
3175 			}
3176 			new_name = g_strdup_printf ("%s.%d", basename, count);
3177 			make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3178 			dest = g_file_get_child (dest_dir, new_name);
3179 			g_free (new_name);
3180 		}
3181 		
3182 		g_free (basename);
3183 	}
3184 
3185 	return dest;
3186 }
3187 
3188 static GFile *
3189 get_target_file_for_link (GFile *src,
3190 			  GFile *dest_dir,
3191 			  const char *dest_fs_type,
3192 			  int count)
3193 {
3194 	const char *editname;
3195 	char *basename, *new_name;
3196 	GFileInfo *info;
3197 	GFile *dest;
3198 	int max_length;
3199 
3200 	max_length = get_max_name_length (dest_dir);
3201 
3202 	dest = NULL;
3203 	info = g_file_query_info (src,
3204 				  G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME,
3205 				  0, NULL, NULL);
3206 	if (info != NULL) {
3207 		editname = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME);
3208 		
3209 		if (editname != NULL) {
3210 			new_name = get_link_name (editname, count, max_length);
3211 			make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3212 			dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL);
3213 			g_free (new_name);
3214 		}
3215 		
3216 		g_object_unref (info);
3217 	}
3218 
3219 	if (dest == NULL) {
3220 		basename = g_file_get_basename (src);
3221 		make_file_name_valid_for_dest_fs (basename, dest_fs_type);
3222 
3223 		if (g_utf8_validate (basename, -1, NULL)) {
3224 			new_name = get_link_name (basename, count, max_length);
3225 			make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3226 			dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL);
3227 			g_free (new_name);
3228 		} 
3229 
3230 		if (dest == NULL) {
3231 			if (count == 1) {
3232 				new_name = g_strdup_printf ("%s.lnk", basename);
3233 			} else {
3234 				new_name = g_strdup_printf ("%s.lnk%d", basename, count);
3235 			}
3236 			make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3237 			dest = g_file_get_child (dest_dir, new_name);
3238 			g_free (new_name);
3239 		}
3240 		
3241 		g_free (basename);
3242 	}
3243 
3244 	return dest;
3245 }
3246 
3247 static GFile *
3248 get_target_file_with_custom_name (GFile *src,
3249 				  GFile *dest_dir,
3250 				  const char *dest_fs_type,
3251 				  gboolean same_fs,
3252 				  const gchar *custom_name)
3253 {
3254 	char *basename;
3255 	GFile *dest;
3256 	GFileInfo *info;
3257 	char *copyname;
3258 
3259 	dest = NULL;
3260 
3261 	if (custom_name != NULL) {
3262 		copyname = g_strdup (custom_name);
3263 		make_file_name_valid_for_dest_fs (copyname, dest_fs_type);
3264 		dest = g_file_get_child_for_display_name (dest_dir, copyname, NULL);
3265 
3266 		g_free (copyname);
3267 	}
3268 
3269 	if (dest == NULL && !same_fs) {
3270 		info = g_file_query_info (src,
3271 					  G_FILE_ATTRIBUTE_STANDARD_COPY_NAME,
3272 					  0, NULL, NULL);
3273 		
3274 		if (info) {
3275 			copyname = g_strdup (g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_COPY_NAME));
3276 
3277 			if (copyname) {
3278 				make_file_name_valid_for_dest_fs (copyname, dest_fs_type);
3279 				dest = g_file_get_child_for_display_name (dest_dir, copyname, NULL);
3280 				g_free (copyname);
3281 			}
3282 			
3283 			g_object_unref (info);
3284 		}
3285 	}
3286 
3287 	if (dest == NULL) {
3288 		basename = g_file_get_basename (src);
3289 		make_file_name_valid_for_dest_fs (basename, dest_fs_type);
3290 		dest = g_file_get_child (dest_dir, basename);
3291 		g_free (basename);
3292 	}
3293 	
3294 	return dest;
3295 }
3296 
3297 static GFile *
3298 get_target_file (GFile *src,
3299 		 GFile *dest_dir,
3300 		 const char *dest_fs_type,
3301 		 gboolean same_fs)
3302 {
3303 	return get_target_file_with_custom_name (src, dest_dir, dest_fs_type, same_fs, NULL);
3304 }
3305 
3306 static gboolean
3307 has_fs_id (GFile *file, const char *fs_id)
3308 {
3309 	const char *id;
3310 	GFileInfo *info;
3311 	gboolean res;
3312 
3313 	res = FALSE;
3314 	info = g_file_query_info (file,
3315 				  G_FILE_ATTRIBUTE_ID_FILESYSTEM,
3316 				  G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3317 				  NULL, NULL);
3318 
3319 	if (info) {
3320 		id = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILESYSTEM);
3321 		
3322 		if (id && strcmp (id, fs_id) == 0) {
3323 			res = TRUE;
3324 		}
3325 		
3326 		g_object_unref (info);
3327 	}
3328 	
3329 	return res;
3330 }
3331 
3332 static gboolean
3333 is_dir (GFile *file)
3334 {
3335 	GFileInfo *info;
3336 	gboolean res;
3337 
3338 	res = FALSE;
3339 	info = g_file_query_info (file,
3340 				  G_FILE_ATTRIBUTE_STANDARD_TYPE,
3341 				  G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3342 				  NULL, NULL);
3343 	if (info) {
3344 		res = g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY;
3345 		g_object_unref (info);
3346 	}
3347 	
3348 	return res;
3349 }
3350 
3351 static void copy_move_file (CopyMoveJob *job,
3352 			    GFile *src,
3353 			    GFile *dest_dir,
3354 			    gboolean same_fs,
3355 			    gboolean unique_names,
3356 			    char **dest_fs_type,
3357 			    SourceInfo *source_info,
3358 			    TransferInfo *transfer_info,
3359 			    GHashTable *debuting_files,
3360 			    GdkPoint *point,
3361 			    gboolean overwrite,
3362 			    gboolean *skipped_file,
3363 			    gboolean readonly_source_fs);
3364 
3365 typedef enum {
3366 	CREATE_DEST_DIR_RETRY,
3367 	CREATE_DEST_DIR_FAILED,
3368 	CREATE_DEST_DIR_SUCCESS
3369 } CreateDestDirResult;
3370 
3371 static CreateDestDirResult
3372 create_dest_dir (CommonJob *job,
3373 		 GFile *src,
3374 		 GFile **dest,
3375 		 gboolean same_fs,
3376 		 char **dest_fs_type)
3377 {
3378 	GError *error;
3379 	GFile *new_dest, *dest_dir;
3380 	char *primary, *secondary, *details;
3381 	int response;
3382 	gboolean handled_invalid_filename;
3383 
3384 	handled_invalid_filename = *dest_fs_type != NULL;
3385 
3386  retry:
3387 	/* First create the directory, then copy stuff to it before
3388 	   copying the attributes, because we need to be sure we can write to it */
3389 	
3390 	error = NULL;
3391 	if (!g_file_make_directory (*dest, job->cancellable, &error)) {
3392 		if (IS_IO_ERROR (error, CANCELLED)) {
3393 			g_error_free (error);
3394 			return CREATE_DEST_DIR_FAILED;
3395 		} else if (IS_IO_ERROR (error, INVALID_FILENAME) &&
3396 			   !handled_invalid_filename) {
3397 			handled_invalid_filename = TRUE;
3398 
3399 			g_assert (*dest_fs_type == NULL);
3400 
3401 			dest_dir = g_file_get_parent (*dest);
3402 
3403 			if (dest_dir != NULL) {
3404 				*dest_fs_type = query_fs_type (dest_dir, job->cancellable);
3405 
3406 				new_dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs);
3407 				g_object_unref (dest_dir);
3408 
3409 				if (!g_file_equal (*dest, new_dest)) {
3410 					g_object_unref (*dest);
3411 					*dest = new_dest;
3412 					g_error_free (error);
3413 					return CREATE_DEST_DIR_RETRY;
3414 				} else {
3415 					g_object_unref (new_dest);
3416 				}
3417 			}
3418 		}
3419 
3420 		primary = f (_("Error while copying."));
3421 		details = NULL;
3422 		
3423 		if (IS_IO_ERROR (error, PERMISSION_DENIED)) {
3424 			secondary = f (_("The folder “%B” cannot be copied because you do not have "
3425 					 "permissions to create it in the destination."), src);
3426 		} else {
3427 			secondary = f (_("There was an error creating the folder “%B”."), src);
3428 			details = error->message;
3429 		}
3430 		
3431 		response = run_warning (job,
3432 					primary,
3433 					secondary,
3434 					details,
3435 					FALSE,
3436 					GTK_STOCK_CANCEL, SKIP, RETRY,
3437 					NULL);
3438 
3439 		g_error_free (error);
3440 
3441 		if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3442 			abort_job (job);
3443 		} else if (response == 1) {
3444 			/* Skip: Do Nothing  */
3445 		} else if (response == 2) {
3446 			goto retry;
3447 		} else {
3448 			g_assert_not_reached ();
3449 		}
3450 		return CREATE_DEST_DIR_FAILED;
3451 	}
3452 	nautilus_file_changes_queue_file_added (*dest);
3453 
3454 	if (job->undo_info != NULL) {
3455 		nautilus_file_undo_info_ext_add_origin_target_pair (NAUTILUS_FILE_UNDO_INFO_EXT (job->undo_info),
3456 								    src, *dest);
3457 	}
3458 
3459 	return CREATE_DEST_DIR_SUCCESS;
3460 }
3461 
3462 /* a return value of FALSE means retry, i.e.
3463  * the destination has changed and the source
3464  * is expected to re-try the preceeding
3465  * g_file_move() or g_file_copy() call with
3466  * the new destination.
3467  */
3468 static gboolean
3469 copy_move_directory (CopyMoveJob *copy_job,
3470 		     GFile *src,
3471 		     GFile **dest,
3472 		     gboolean same_fs,
3473 		     gboolean create_dest,
3474 		     char **parent_dest_fs_type,
3475 		     SourceInfo *source_info,
3476 		     TransferInfo *transfer_info,
3477 		     GHashTable *debuting_files,
3478 		     gboolean *skipped_file,
3479 		     gboolean readonly_source_fs)
3480 {
3481 	GFileInfo *info;
3482 	GError *error;
3483 	GFile *src_file;
3484 	GFileEnumerator *enumerator;
3485 	char *primary, *secondary, *details;
3486 	char *dest_fs_type;
3487 	int response;
3488 	gboolean skip_error;
3489 	gboolean local_skipped_file;
3490 	CommonJob *job;
3491 	GFileCopyFlags flags;
3492 
3493 	job = (CommonJob *)copy_job;
3494 	
3495 	if (create_dest) {
3496 		switch (create_dest_dir (job, src, dest, same_fs, parent_dest_fs_type)) {
3497 			case CREATE_DEST_DIR_RETRY:
3498 				/* next time copy_move_directory() is called,
3499 				 * create_dest will be FALSE if a directory already
3500 				 * exists under the new name (i.e. WOULD_RECURSE)
3501 				 */
3502 				return FALSE;
3503 
3504 			case CREATE_DEST_DIR_FAILED:
3505 				*skipped_file = TRUE;
3506 				return TRUE;
3507 
3508 			case CREATE_DEST_DIR_SUCCESS:
3509 			default:
3510 				break;
3511 		}
3512 
3513 		if (debuting_files) {
3514 			g_hash_table_replace (debuting_files, g_object_ref (*dest), GINT_TO_POINTER (TRUE));
3515 		}
3516 
3517 	}
3518 
3519 	local_skipped_file = FALSE;
3520 	dest_fs_type = NULL;
3521 	
3522 	skip_error = should_skip_readdir_error (job, src);
3523  retry:
3524 	error = NULL;
3525 	enumerator = g_file_enumerate_children (src,
3526 						G_FILE_ATTRIBUTE_STANDARD_NAME,
3527 						G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3528 						job->cancellable,
3529 						&error);
3530 	if (enumerator) {
3531 		error = NULL;
3532 
3533 		while (!job_aborted (job) &&
3534 		       (info = g_file_enumerator_next_file (enumerator, job->cancellable, skip_error?NULL:&error)) != NULL) {
3535 			src_file = g_file_get_child (src,
3536 						     g_file_info_get_name (info));
3537 			copy_move_file (copy_job, src_file, *dest, same_fs, FALSE, &dest_fs_type,
3538 					source_info, transfer_info, NULL, NULL, FALSE, &local_skipped_file,
3539 					readonly_source_fs);
3540 			g_object_unref (src_file);
3541 			g_object_unref (info);
3542 		}
3543 		g_file_enumerator_close (enumerator, job->cancellable, NULL);
3544 		g_object_unref (enumerator);
3545 		
3546 		if (error && IS_IO_ERROR (error, CANCELLED)) {
3547 			g_error_free (error);
3548 		} else if (error) {
3549 			if (copy_job->is_move) {
3550 				primary = f (_("Error while moving."));
3551 			} else {
3552 				primary = f (_("Error while copying."));
3553 			}
3554 			details = NULL;
3555 			
3556 			if (IS_IO_ERROR (error, PERMISSION_DENIED)) {
3557 				secondary = f (_("Files in the folder “%B” cannot be copied because you do "
3558 						 "not have permissions to see them."), src);
3559 			} else {
3560 				secondary = f (_("There was an error getting information about the files in the folder “%B”."), src);
3561 				details = error->message;
3562 			}
3563 			
3564 			response = run_warning (job,
3565 						primary,
3566 						secondary,
3567 						details,
3568 						FALSE,
3569 						GTK_STOCK_CANCEL, _("_Skip files"),
3570 						NULL);
3571 			
3572 			g_error_free (error);
3573 			
3574 			if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3575 				abort_job (job);
3576 			} else if (response == 1) {
3577 				/* Skip: Do Nothing */
3578 				local_skipped_file = TRUE;
3579 			} else {
3580 				g_assert_not_reached ();
3581 			}
3582 		}
3583 
3584 		/* Count the copied directory as a file */
3585 		transfer_info->num_files ++;
3586 		report_copy_progress (copy_job, source_info, transfer_info);
3587 
3588 		if (debuting_files) {
3589 			g_hash_table_replace (debuting_files, g_object_ref (*dest), GINT_TO_POINTER (create_dest));
3590 		}
3591 	} else if (IS_IO_ERROR (error, CANCELLED)) {
3592 		g_error_free (error);
3593 	} else {
3594 		if (copy_job->is_move) {
3595 			primary = f (_("Error while moving."));
3596 		} else {
3597 			primary = f (_("Error while copying."));
3598 		}
3599 		details = NULL;
3600 		
3601 		if (IS_IO_ERROR (error, PERMISSION_DENIED)) {
3602 			secondary = f (_("The folder “%B” cannot be copied because you do not have "
3603 					 "permissions to read it."), src);
3604 		} else {
3605 			secondary = f (_("There was an error reading the folder “%B”."), src);
3606 			details = error->message;
3607 		}
3608 		
3609 		response = run_warning (job,
3610 					primary,
3611 					secondary,
3612 					details,
3613 					FALSE,
3614 					GTK_STOCK_CANCEL, SKIP, RETRY,
3615 					NULL);
3616 
3617 		g_error_free (error);
3618 
3619 		if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3620 			abort_job (job);
3621 		} else if (response == 1) {
3622 			/* Skip: Do Nothing  */
3623 			local_skipped_file = TRUE;
3624 		} else if (response == 2) {
3625 			goto retry;
3626 		} else {
3627 			g_assert_not_reached ();
3628 		}
3629 	}
3630 
3631 	if (create_dest) {
3632 		flags = (readonly_source_fs) ? G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_TARGET_DEFAULT_PERMS 
3633 					     : G_FILE_COPY_NOFOLLOW_SYMLINKS;
3634 		/* Ignore errors here. Failure to copy metadata is not a hard error */
3635 		g_file_copy_attributes (src, *dest,
3636 					flags,
3637 					job->cancellable, NULL);
3638 	}
3639 
3640 	if (!job_aborted (job) && copy_job->is_move &&
3641 	    /* Don't delete source if there was a skipped file */
3642 	    !local_skipped_file) {
3643 		if (!g_file_delete (src, job->cancellable, &error)) {
3644 			if (job->skip_all_error) {
3645 				goto skip;
3646 			}
3647 			primary = f (_("Error while moving “%B”."), src);
3648 			secondary = f (_("Could not remove the source folder."));
3649 			details = error->message;
3650 			
3651 			response = run_warning (job,
3652 						primary,
3653 						secondary,
3654 						details,
3655 						(source_info->num_files - transfer_info->num_files) > 1,
3656 						GTK_STOCK_CANCEL, SKIP_ALL, SKIP,
3657 						NULL);
3658 			
3659 			if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3660 				abort_job (job);
3661 			} else if (response == 1) { /* skip all */
3662 				job->skip_all_error = TRUE;
3663 				local_skipped_file = TRUE;
3664 			} else if (response == 2) { /* skip */
3665 				local_skipped_file = TRUE;
3666 			} else {
3667 				g_assert_not_reached ();
3668 			}
3669 			
3670 		skip:
3671 			g_error_free (error);
3672 		}
3673 	}
3674 
3675 	if (local_skipped_file) {
3676 		*skipped_file = TRUE;
3677 	}
3678 
3679 	g_free (dest_fs_type);
3680 	return TRUE;
3681 }
3682 
3683 static gboolean
3684 remove_target_recursively (CommonJob *job,
3685 			   GFile *src,
3686 			   GFile *toplevel_dest,
3687 			   GFile *file)
3688 {
3689 	GFileEnumerator *enumerator;
3690 	GError *error;
3691 	GFile *child;
3692 	gboolean stop;
3693 	char *primary, *secondary, *details;
3694 	int response;
3695 	GFileInfo *info;
3696 
3697 	stop = FALSE;
3698 	
3699 	error = NULL;
3700 	enumerator = g_file_enumerate_children (file,
3701 						G_FILE_ATTRIBUTE_STANDARD_NAME,
3702 						G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3703 						job->cancellable,
3704 						&error);
3705 	if (enumerator) {
3706 		error = NULL;
3707 		
3708 		while (!job_aborted (job) &&
3709 		       (info = g_file_enumerator_next_file (enumerator, job->cancellable, &error)) != NULL) {
3710 			child = g_file_get_child (file,
3711 						  g_file_info_get_name (info));
3712 			if (!remove_target_recursively (job, src, toplevel_dest, child)) {
3713 				stop = TRUE;
3714 				break;
3715 			}
3716 			g_object_unref (child);
3717 			g_object_unref (info);
3718 		}
3719 		g_file_enumerator_close (enumerator, job->cancellable, NULL);
3720 		g_object_unref (enumerator);
3721 		
3722 	} else if (IS_IO_ERROR (error, NOT_DIRECTORY)) {
3723 		/* Not a dir, continue */
3724 		g_error_free (error);
3725 		
3726 	} else if (IS_IO_ERROR (error, CANCELLED)) {
3727 		g_error_free (error);
3728 	} else {
3729 		if (job->skip_all_error) {
3730 			goto skip1;
3731 		}
3732 		
3733 		primary = f (_("Error while copying “%B”."), src);
3734 		secondary = f (_("Could not remove files from the already existing folder %F."), file);
3735 		details = error->message;
3736 
3737 		/* set show_all to TRUE here, as we don't know how many
3738 		 * files we'll end up processing yet.
3739 		 */
3740 		response = run_warning (job,
3741 					primary,
3742 					secondary,
3743 					details,
3744 					TRUE,
3745 					GTK_STOCK_CANCEL, SKIP_ALL, SKIP,
3746 					NULL);
3747 		
3748 		if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3749 			abort_job (job);
3750 		} else if (response == 1) { /* skip all */
3751 			job->skip_all_error = TRUE;
3752 		} else if (response == 2) { /* skip */
3753 			/* do nothing */
3754 		} else {
3755 			g_assert_not_reached ();
3756 		}
3757 	skip1:
3758 		g_error_free (error);
3759 		
3760 		stop = TRUE;
3761 	}
3762 
3763 	if (stop) {
3764 		return FALSE;
3765 	}
3766 
3767 	error = NULL;
3768 	
3769 	if (!g_file_delete (file, job->cancellable, &error)) {
3770 		if (job->skip_all_error ||
3771 		    IS_IO_ERROR (error, CANCELLED)) {
3772 			goto skip2;
3773 		}
3774 		primary = f (_("Error while copying “%B”."), src);
3775 		secondary = f (_("Could not remove the already existing file %F."), file);
3776 		details = error->message;
3777 
3778 		/* set show_all to TRUE here, as we don't know how many
3779 		 * files we'll end up processing yet.
3780 		 */
3781 		response = run_warning (job,
3782 					primary,
3783 					secondary,
3784 					details,
3785 					TRUE,
3786 					GTK_STOCK_CANCEL, SKIP_ALL, SKIP,
3787 					NULL);
3788 		
3789 		if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3790 			abort_job (job);
3791 		} else if (response == 1) { /* skip all */
3792 			job->skip_all_error = TRUE;
3793 		} else if (response == 2) { /* skip */
3794 			/* do nothing */
3795 		} else {
3796 			g_assert_not_reached ();
3797 		}
3798 
3799 	skip2:
3800 		g_error_free (error);
3801 		
3802 		return FALSE;
3803 	}
3804 	nautilus_file_changes_queue_file_removed (file);
3805 	
3806 	return TRUE;
3807 	
3808 }
3809 
3810 typedef struct {
3811 	CopyMoveJob *job;
3812 	goffset last_size;
3813 	SourceInfo *source_info;
3814 	TransferInfo *transfer_info;
3815 } ProgressData;
3816 
3817 static void
3818 copy_file_progress_callback (goffset current_num_bytes,
3819 			     goffset total_num_bytes,
3820 			     gpointer user_data)
3821 {
3822 	ProgressData *pdata;
3823 	goffset new_size;
3824 
3825 	pdata = user_data;
3826 	
3827 	new_size = current_num_bytes - pdata->last_size;
3828 
3829 	if (new_size > 0) {
3830 		pdata->transfer_info->num_bytes += new_size;
3831 		pdata->last_size = current_num_bytes;
3832 		report_copy_progress (pdata->job,
3833 				      pdata->source_info,
3834 				      pdata->transfer_info);
3835 	}
3836 }
3837 
3838 static gboolean
3839 test_dir_is_parent (GFile *child, GFile *root)
3840 {
3841 	GFile *f, *tmp;
3842 	
3843 	f = g_file_dup (child);
3844 	while (f) {
3845 		if (g_file_equal (f, root)) {
3846 			g_object_unref (f);
3847 			return TRUE;
3848 		}
3849 		tmp = f;
3850 		f = g_file_get_parent (f);
3851 		g_object_unref (tmp);
3852 	}
3853 	if (f) {
3854 		g_object_unref (f);
3855 	}
3856 	return FALSE;
3857 }
3858 
3859 static char *
3860 query_fs_type (GFile *file,
3861 	       GCancellable *cancellable)
3862 {
3863 	GFileInfo *fsinfo;
3864 	char *ret;
3865 
3866 	ret = NULL;
3867 
3868 	fsinfo = g_file_query_filesystem_info (file,
3869 					       G_FILE_ATTRIBUTE_FILESYSTEM_TYPE,
3870 					       cancellable,
3871 					       NULL);
3872 	if (fsinfo != NULL) {
3873 		ret = g_strdup (g_file_info_get_attribute_string (fsinfo, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE));
3874 		g_object_unref (fsinfo);
3875 	}
3876 
3877 	if (ret == NULL) {
3878 		/* ensure that we don't attempt to query
3879 		 * the FS type for each file in a given
3880 		 * directory, if it can't be queried. */
3881 		ret = g_strdup ("");
3882 	}
3883 
3884 	return ret;
3885 }
3886 
3887 static gboolean
3888 is_trusted_desktop_file (GFile *file,
3889 			 GCancellable *cancellable)
3890 {
3891 	char *basename;
3892 	gboolean res;
3893 	GFileInfo *info;
3894 
3895 	/* Don't trust non-local files */
3896 	if (!g_file_is_native (file)) {
3897 		return FALSE;
3898 	}
3899 	
3900 	basename = g_file_get_basename (file);
3901 	if (!g_str_has_suffix (basename, ".desktop")) {
3902 		g_free (basename);
3903 		return FALSE;
3904 	}
3905 	g_free (basename);
3906 
3907 	info = g_file_query_info (file, 
3908 				  G_FILE_ATTRIBUTE_STANDARD_TYPE ","
3909 				  G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE,
3910 				  G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3911 				  cancellable,
3912 				  NULL);
3913 
3914 	if (info == NULL) {
3915 		return FALSE;
3916 	}
3917 
3918 	res = FALSE;
3919 	
3920 	/* Weird file => not trusted,
3921 	   Already executable => no need to mark trusted */
3922 	if (g_file_info_get_file_type (info) == G_FILE_TYPE_REGULAR &&
3923 	    !g_file_info_get_attribute_boolean (info,
3924 						G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE) &&
3925 	    nautilus_is_in_system_dir (file)) {
3926 		res = TRUE;
3927 	}
3928 	g_object_unref (info);
3929 	
3930 	return res;
3931 }
3932 
3933 typedef struct {
3934 	int id;
3935 	char *new_name;
3936 	gboolean apply_to_all;
3937 } ConflictResponseData;
3938 
3939 typedef struct {
3940 	GFile *src;
3941 	GFile *dest;
3942 	GFile *dest_dir;
3943 	GtkWindow *parent;
3944 	ConflictResponseData *resp_data;
3945 } ConflictDialogData;
3946 
3947 static gboolean
3948 do_run_conflict_dialog (gpointer _data)
3949 {
3950 	ConflictDialogData *data = _data;
3951 	GtkWidget *dialog;
3952 	int response;
3953 
3954 	dialog = nautilus_file_conflict_dialog_new (data->parent,
3955 						    data->src,
3956 						    data->dest,
3957 						    data->dest_dir);
3958 	response = gtk_dialog_run (GTK_DIALOG (dialog));
3959 
3960 	if (response == CONFLICT_RESPONSE_RENAME) {
3961 		data->resp_data->new_name = 
3962 			nautilus_file_conflict_dialog_get_new_name (NAUTILUS_FILE_CONFLICT_DIALOG (dialog));
3963 	} else if (response != GTK_RESPONSE_CANCEL ||
3964 		   response != GTK_RESPONSE_NONE) {
3965 		   data->resp_data->apply_to_all =
3966 			   nautilus_file_conflict_dialog_get_apply_to_all 
3967 				(NAUTILUS_FILE_CONFLICT_DIALOG (dialog));
3968 	}
3969 
3970 	data->resp_data->id = response;
3971 
3972 	gtk_widget_destroy (dialog);
3973 
3974 	return FALSE;
3975 }
3976 
3977 static ConflictResponseData *
3978 run_conflict_dialog (CommonJob *job,
3979 		     GFile *src,
3980 		     GFile *dest,
3981 		     GFile *dest_dir)
3982 {
3983 	ConflictDialogData *data;
3984 	ConflictResponseData *resp_data;
3985 
3986 	g_timer_stop (job->time);
3987 
3988 	data = g_slice_new0 (ConflictDialogData);
3989 	data->parent = job->parent_window;
3990 	data->src = src;
3991 	data->dest = dest;
3992 	data->dest_dir = dest_dir;
3993 
3994 	resp_data = g_slice_new0 (ConflictResponseData);
3995 	resp_data->new_name = NULL;
3996 	data->resp_data = resp_data;
3997 
3998 	nautilus_progress_info_pause (job->progress);
3999 	g_io_scheduler_job_send_to_mainloop (job->io_job,
4000 					     do_run_conflict_dialog,
4001 					     data,
4002 					     NULL);
4003 	nautilus_progress_info_resume (job->progress);
4004 
4005 	g_slice_free (ConflictDialogData, data);
4006 
4007 	g_timer_continue (job->time);
4008 
4009 	return resp_data;
4010 }
4011 
4012 static void
4013 conflict_response_data_free (ConflictResponseData *data)
4014 {
4015 	g_free (data->new_name);
4016 	g_slice_free (ConflictResponseData, data);
4017 }
4018 
4019 static GFile *
4020 get_target_file_for_display_name (GFile *dir,
4021 				  const gchar *name)
4022 {
4023 	GFile *dest;
4024 
4025 	dest = NULL;
4026 	dest = g_file_get_child_for_display_name (dir, name, NULL);
4027 
4028 	if (dest == NULL) {
4029 		dest = g_file_get_child (dir, name);
4030 	}
4031 	
4032 	return dest;		
4033 }
4034 
4035 /* Debuting files is non-NULL only for toplevel items */
4036 static void
4037 copy_move_file (CopyMoveJob *copy_job,
4038 		GFile *src,
4039 		GFile *dest_dir,
4040 		gboolean same_fs,
4041 		gboolean unique_names,
4042 		char **dest_fs_type,
4043 		SourceInfo *source_info,
4044 		TransferInfo *transfer_info,
4045 		GHashTable *debuting_files,
4046 		GdkPoint *position,
4047 		gboolean overwrite,
4048 		gboolean *skipped_file,
4049 		gboolean readonly_source_fs)
4050 {
4051 	GFile *dest, *new_dest;
4052 	GError *error;
4053 	GFileCopyFlags flags;
4054 	char *primary, *secondary, *details;
4055 	int response;
4056 	ProgressData pdata;
4057 	gboolean would_recurse, is_merge;
4058 	CommonJob *job;
4059 	gboolean res;
4060 	int unique_name_nr;
4061 	gboolean handled_invalid_filename;
4062 
4063 	job = (CommonJob *)copy_job;
4064 	
4065 	if (should_skip_file (job, src)) {
4066 		*skipped_file = TRUE;
4067 		return;
4068 	}
4069 
4070 	unique_name_nr = 1;
4071 
4072 	/* another file in the same directory might have handled the invalid
4073 	 * filename condition for us
4074 	 */
4075 	handled_invalid_filename = *dest_fs_type != NULL;
4076 
4077 	if (unique_names) {
4078 		dest = get_unique_target_file (src, dest_dir, same_fs, *dest_fs_type, unique_name_nr++);
4079 	} else if (copy_job->target_name != NULL) {
4080 		dest = get_target_file_with_custom_name (src, dest_dir, *dest_fs_type, same_fs,
4081 							 copy_job->target_name);
4082 	} else {
4083 		dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs);
4084 	}
4085 
4086 	/* Don't allow recursive move/copy into itself.  
4087 	 * (We would get a file system error if we proceeded but it is nicer to 
4088 	 * detect and report it at this level) */
4089 	if (test_dir_is_parent (dest_dir, src)) {
4090 		if (job->skip_all_error) {
4091 			goto out;
4092 		}
4093 		
4094 		/*  the run_warning() frees all strings passed in automatically  */
4095 		primary = copy_job->is_move ? g_strdup (_("You cannot move a folder into itself."))
4096 					    : g_strdup (_("You cannot copy a folder into itself."));
4097 		secondary = g_strdup (_("The destination folder is inside the source folder."));
4098 		
4099 		response = run_warning (job,
4100 					primary,
4101 					secondary,
4102 					NULL,
4103 					(source_info->num_files - transfer_info->num_files) > 1,
4104 					GTK_STOCK_CANCEL, SKIP_ALL, SKIP,
4105 					NULL);
4106 
4107 		if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4108 			abort_job (job);
4109 		} else if (response == 1) { /* skip all */
4110 			job->skip_all_error = TRUE;
4111 		} else if (response == 2) { /* skip */
4112 			/* do nothing */
4113 		} else {
4114 			g_assert_not_reached ();
4115 		}
4116 
4117 		goto out;
4118 	}
4119 
4120 	/* Don't allow copying over the source or one of the parents of the source.
4121 	 */
4122 	if (test_dir_is_parent (src, dest)) {
4123 		if (job->skip_all_error) {
4124 			goto out;
4125 		}
4126 		
4127 		/*  the run_warning() frees all strings passed in automatically  */
4128 		primary = copy_job->is_move ? g_strdup (_("You cannot move a file over itself."))
4129 					    : g_strdup (_("You cannot copy a file over itself."));
4130 		secondary = g_strdup (_("The source file would be overwritten by the destination."));
4131 		
4132 		response = run_warning (job,
4133 					primary,
4134 					secondary,
4135 					NULL,
4136 					(source_info->num_files - transfer_info->num_files) > 1,
4137 					GTK_STOCK_CANCEL, SKIP_ALL, SKIP,
4138 					NULL);
4139 
4140 		if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4141 			abort_job (job);
4142 		} else if (response == 1) { /* skip all */
4143 			job->skip_all_error = TRUE;
4144 		} else if (response == 2) { /* skip */
4145 			/* do nothing */
4146 		} else {
4147 			g_assert_not_reached ();
4148 		}
4149 
4150 		goto out;
4151 	}
4152 
4153 	
4154  retry:
4155 	
4156 	error = NULL;
4157 	flags = G_FILE_COPY_NOFOLLOW_SYMLINKS;
4158 	if (overwrite) {
4159 		flags |= G_FILE_COPY_OVERWRITE;
4160 	}
4161 	if (readonly_source_fs) {
4162 		flags |= G_FILE_COPY_TARGET_DEFAULT_PERMS;
4163 	}
4164 
4165 	pdata.job = copy_job;
4166 	pdata.last_size = 0;
4167 	pdata.source_info = source_info;
4168 	pdata.transfer_info = transfer_info;
4169 
4170 	if (copy_job->is_move) {
4171 		res = g_file_move (src, dest,
4172 				   flags,
4173 				   job->cancellable,
4174 				   copy_file_progress_callback,
4175 				   &pdata,
4176 				   &error);
4177 	} else {
4178 		res = g_file_copy (src, dest,
4179 				   flags,
4180 				   job->cancellable,
4181 				   copy_file_progress_callback,
4182 				   &pdata,
4183 				   &error);
4184 	}
4185 	
4186 	if (res) {
4187 		transfer_info->num_files ++;
4188 		report_copy_progress (copy_job, source_info, transfer_info);
4189 
4190 		if (debuting_files) {
4191 			if (position) {
4192 				nautilus_file_changes_queue_schedule_position_set (dest, *position, job->screen_num);
4193 			} else {
4194 				nautilus_file_changes_queue_schedule_position_remove (dest);
4195 			}
4196 			
4197 			g_hash_table_replace (debuting_files, g_object_ref (dest), GINT_TO_POINTER (TRUE));
4198 		}
4199 		if (copy_job->is_move) {
4200 			nautilus_file_changes_queue_file_moved (src, dest);
4201 		} else {
4202 			nautilus_file_changes_queue_file_added (dest);
4203 		}
4204 
4205 		/* If copying a trusted desktop file to the desktop,
4206 		   mark it as trusted. */
4207 		if (copy_job->desktop_location != NULL &&
4208 		    g_file_equal (copy_job->desktop_location, dest_dir) &&
4209 		    is_trusted_desktop_file (src, job->cancellable)) {
4210 			mark_desktop_file_trusted (job,
4211 						   job->cancellable,
4212 						   dest,
4213 						   FALSE);
4214 		}
4215 
4216 		if (job->undo_info != NULL) {
4217 			nautilus_file_undo_info_ext_add_origin_target_pair (NAUTILUS_FILE_UNDO_INFO_EXT (job->undo_info),
4218 									    src, dest);
4219 		}
4220 
4221 		g_object_unref (dest);
4222 		return;
4223 	}
4224 
4225 	if (!handled_invalid_filename &&
4226 	    IS_IO_ERROR (error, INVALID_FILENAME)) {
4227 		handled_invalid_filename = TRUE;
4228 
4229 		g_assert (*dest_fs_type == NULL);
4230 		*dest_fs_type = query_fs_type (dest_dir, job->cancellable);
4231 
4232 		if (unique_names) {
4233 			new_dest = get_unique_target_file (src, dest_dir, same_fs, *dest_fs_type, unique_name_nr);
4234 		} else {
4235 			new_dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs);
4236 		}
4237 
4238 		if (!g_file_equal (dest, new_dest)) {
4239 			g_object_unref (dest);
4240 			dest = new_dest;
4241 
4242 			g_error_free (error);
4243 			goto retry;
4244 		} else {
4245 			g_object_unref (new_dest);
4246 		}
4247 	}
4248 
4249 	/* Conflict */
4250 	if (!overwrite &&
4251 	    IS_IO_ERROR (error, EXISTS)) {
4252 		gboolean is_merge;
4253 		ConflictResponseData *response;
4254 
4255 		g_error_free (error);
4256 
4257 		if (unique_names) {
4258 			g_object_unref (dest);
4259 			dest = get_unique_target_file (src, dest_dir, same_fs, *dest_fs_type, unique_name_nr++);
4260 			goto retry;
4261 		}
4262 
4263 		is_merge = FALSE;
4264 
4265 		if (is_dir (dest) && is_dir (src)) {
4266 			is_merge = TRUE;
4267 		}
4268 
4269 		if ((is_merge && job->merge_all) ||
4270 		    (!is_merge && job->replace_all)) {
4271 			overwrite = TRUE;
4272 			goto retry;
4273 		}
4274 
4275 		if (job->skip_all_conflict) {
4276 			goto out;
4277 		}
4278 
4279 		response = run_conflict_dialog (job, src, dest, dest_dir);	
4280 
4281 		if (response->id == GTK_RESPONSE_CANCEL ||
4282 		    response->id == GTK_RESPONSE_DELETE_EVENT) {
4283 			conflict_response_data_free (response);
4284 			abort_job (job);
4285 		} else if (response->id == CONFLICT_RESPONSE_SKIP) {
4286 			if (response->apply_to_all) {
4287 				job->skip_all_conflict = TRUE;
4288 			}
4289 			conflict_response_data_free (response);
4290 		} else if (response->id == CONFLICT_RESPONSE_REPLACE) { /* merge/replace */
4291 			if (response->apply_to_all) {
4292 				if (is_merge) {
4293 					job->merge_all = TRUE;
4294 				} else {
4295 					job->replace_all = TRUE;
4296 				}
4297 			}
4298 			overwrite = TRUE;
4299 			conflict_response_data_free (response);
4300 			goto retry;
4301 		} else if (response->id == CONFLICT_RESPONSE_RENAME) {
4302 			g_object_unref (dest);
4303 			dest = get_target_file_for_display_name (dest_dir,
4304 								 response->new_name);
4305 			conflict_response_data_free (response);
4306 			goto retry;
4307 		} else {
4308 			g_assert_not_reached ();
4309 		}
4310 	}
4311 	
4312 	else if (overwrite &&
4313 		 IS_IO_ERROR (error, IS_DIRECTORY)) {
4314 
4315 		g_error_free (error);
4316 		
4317 		if (remove_target_recursively (job, src, dest, dest)) {
4318 			goto retry;
4319 		}
4320 	}
4321 	
4322 	/* Needs to recurse */
4323 	else if (IS_IO_ERROR (error, WOULD_RECURSE) ||
4324 		 IS_IO_ERROR (error, WOULD_MERGE)) {
4325 		is_merge = error->code == G_IO_ERROR_WOULD_MERGE;
4326 		would_recurse = error->code == G_IO_ERROR_WOULD_RECURSE;
4327 		g_error_free (error);
4328 
4329 		if (overwrite && would_recurse) {
4330 			error = NULL;
4331 			
4332 			/* Copying a dir onto file, first remove the file */
4333 			if (!g_file_delete (dest, job->cancellable, &error) &&
4334 			    !IS_IO_ERROR (error, NOT_FOUND)) {
4335 				if (job->skip_all_error) {
4336 					g_error_free (error);
4337 					goto out;
4338 				}
4339 				if (copy_job->is_move) {
4340 					primary = f (_("Error while moving “%B”."), src);
4341 				} else {
4342 					primary = f (_("Error while copying “%B”."), src);
4343 				}
4344 				secondary = f (_("Could not remove the already existing file with the same name in %F."), dest_dir);
4345 				details = error->message;
4346 
4347 				/* setting TRUE on show_all here, as we could have
4348 				 * another error on the same file later.
4349 				 */
4350 				response = run_warning (job,
4351 							primary,
4352 							secondary,
4353 							details,
4354 							TRUE,
4355 							GTK_STOCK_CANCEL, SKIP_ALL, SKIP,
4356 							NULL);
4357 				
4358 				g_error_free (error);
4359 				
4360 				if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4361 					abort_job (job);
4362 				} else if (response == 1) { /* skip all */
4363 					job->skip_all_error = TRUE;
4364 				} else if (response == 2) { /* skip */
4365 					/* do nothing */
4366 				} else {
4367 					g_assert_not_reached ();
4368 				}
4369 				goto out;
4370 				
4371 			}
4372 			if (error) {
4373 				g_error_free (error);
4374 				error = NULL;
4375 			}
4376 			nautilus_file_changes_queue_file_removed (dest);
4377 		}
4378 
4379 		if (is_merge) {
4380 			/* On merge we now write in the target directory, which may not
4381 			   be in the same directory as the source, even if the parent is
4382 			   (if the merged directory is a mountpoint). This could cause
4383 			   problems as we then don't transcode filenames.
4384 			   We just set same_fs to FALSE which is safe but a bit slower. */
4385 			same_fs = FALSE;
4386 		}
4387 		
4388 		if (!copy_move_directory (copy_job, src, &dest, same_fs,
4389 					  would_recurse, dest_fs_type,
4390 					  source_info, transfer_info,
4391 					  debuting_files, skipped_file,
4392 					  readonly_source_fs)) {
4393 			/* destination changed, since it was an invalid file name */
4394 			g_assert (*dest_fs_type != NULL);
4395 			handled_invalid_filename = TRUE;
4396 			goto retry;
4397 		}
4398 
4399 		g_object_unref (dest);
4400 		return;
4401 	}
4402 	
4403 	else if (IS_IO_ERROR (error, CANCELLED)) {
4404 		g_error_free (error);
4405 	}
4406 	
4407 	/* Other error */
4408 	else {
4409 		if (job->skip_all_error) {
4410 			g_error_free (error);
4411 			goto out;
4412 		}
4413 		primary = f (_("Error while copying “%B”."), src);
4414 		secondary = f (_("There was an error copying the file into %F."), dest_dir);
4415 		details = error->message;
4416 		
4417 		response = run_warning (job,
4418 					primary,
4419 					secondary,
4420 					details,
4421 					(source_info->num_files - transfer_info->num_files) > 1,
4422 					GTK_STOCK_CANCEL, SKIP_ALL, SKIP,
4423 					NULL);
4424 
4425 		g_error_free (error);
4426 		
4427 		if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4428 			abort_job (job);
4429 		} else if (response == 1) { /* skip all */
4430 			job->skip_all_error = TRUE;
4431 		} else if (response == 2) { /* skip */
4432 			/* do nothing */
4433 		} else {
4434 			g_assert_not_reached ();
4435 		}
4436 	}
4437  out:
4438 	*skipped_file = TRUE; /* Or aborted, but same-same */
4439 	g_object_unref (dest);
4440 }
4441 
4442 static void
4443 copy_files (CopyMoveJob *job,
4444 	    const char *dest_fs_id,
4445 	    SourceInfo *source_info,
4446 	    TransferInfo *transfer_info)
4447 {
4448 	CommonJob *common;
4449 	GList *l;
4450 	GFile *src;
4451 	gboolean same_fs;
4452 	int i;
4453 	GdkPoint *point;
4454 	gboolean skipped_file;
4455 	gboolean unique_names;
4456 	GFile *dest;
4457 	GFile *source_dir;
4458 	char *dest_fs_type;
4459 	GFileInfo *inf;
4460 	gboolean readonly_source_fs;
4461 
4462 	dest_fs_type = NULL;
4463 	readonly_source_fs = FALSE;
4464 
4465 	common = &job->common;
4466 
4467 	report_copy_progress (job, source_info, transfer_info);
4468 
4469 	/* Query the source dir, not the file because if its a symlink we'll follow it */
4470 	source_dir = g_file_get_parent ((GFile *) job->files->data);
4471 	if (source_dir) {
4472 		inf = g_file_query_filesystem_info (source_dir, "filesystem::readonly", NULL, NULL);