Bug Summary

File:nautilus-file-operations.c
Location:line 5885, column 32
Description:Access to field 'data' results in a dereference of a null pointer (loaded from variable 'locations')

Annotated Source Code

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
71typedef 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
89typedef 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
104typedef 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
113typedef 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
129typedef struct {
130 CommonJob common;
131 GList *trash_dirs;
132 gboolean should_confirm;
133 NautilusOpCallback done_callback;
134 gpointer done_callback_data;
135} EmptyTrashJob;
136
137typedef struct {
138 CommonJob common;
139 GFile *file;
140 gboolean interactive;
141 NautilusOpCallback done_callback;
142 gpointer done_callback_data;
143} MarkTrustedJob;
144
145typedef 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
156typedef enum {
157 OP_KIND_COPY,
158 OP_KIND_MOVE,
159 OP_KIND_DELETE,
160 OP_KIND_TRASH
161} OpKind;
162
163typedef struct {
164 int num_files;
165 goffset num_bytes;
166 int num_files_since_progress;
167 OpKind op;
168} SourceInfo;
169
170typedef 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_RATE15 15
179#define NSEC_PER_MICROSEC1000 1000
180
181#define MAXIMUM_DISPLAYED_FILE_NAME_LENGTH50 50
182
183#define IS_IO_ERROR(__error, KIND)(((__error)->domain == g_io_error_quark() && (__error
)->code == G_IO_ERROR_KIND))
(((__error)->domain == G_IO_ERRORg_io_error_quark() && (__error)->code == G_IO_ERROR_ ## KIND))
184
185#define CANCELgettext ("_Cancel") _("_Cancel")gettext ("_Cancel")
186#define SKIPgettext ("_Skip") _("_Skip")gettext ("_Skip")
187#define SKIP_ALLgettext ("S_kip All") _("S_kip All")gettext ("S_kip All")
188#define RETRYgettext ("_Retry") _("_Retry")gettext ("_Retry")
189#define DELETEgettext ("_Delete") _("_Delete")gettext ("_Delete")
190#define DELETE_ALLgettext ("Delete _All") _("Delete _All")gettext ("Delete _All")
191#define REPLACEgettext ("_Replace") _("_Replace")gettext ("_Replace")
192#define REPLACE_ALLgettext ("Replace _All") _("Replace _All")gettext ("Replace _All")
193#define MERGEgettext ("_Merge") _("_Merge")gettext ("_Merge")
194#define MERGE_ALLgettext ("Merge _All") _("Merge _All")gettext ("Merge _All")
195#define COPY_FORCEgettext ("Copy _Anyway") _("Copy _Anyway")gettext ("Copy _Anyway")
196
197static void
198mark_desktop_file_trusted (CommonJob *common,
199 GCancellable *cancellable,
200 GFile *file,
201 gboolean interactive);
202
203static gboolean
204is_all_button_text (const char *button_text)
205{
206 g_assert (button_text != NULL)do { if (button_text != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "nautilus-file-operations.c", 206, ((const char
*) (__func__)), "button_text != NULL"); } while (0)
;
207
208 return !strcmp (button_text, SKIP_ALLgettext ("S_kip All")) ||
209 !strcmp (button_text, REPLACE_ALLgettext ("Replace _All")) ||
210 !strcmp (button_text, DELETE_ALLgettext ("Delete _All")) ||
211 !strcmp (button_text, MERGE_ALLgettext ("Merge _All"));
212}
213
214static void scan_sources (GList *files,
215 SourceInfo *source_info,
216 CommonJob *job,
217 OpKind kind);
218
219
220static gboolean empty_trash_job (GIOSchedulerJob *io_job,
221 GCancellable *cancellable,
222 gpointer user_data);
223
224static char * query_fs_type (GFile *file,
225 GCancellable *cancellable);
226
227/* keep in time with format_time()
228 *
229 * This counts and outputs the number of “time units”
230 * formatted and displayed by format_time().
231 * For instance, if format_time outputs “3 hours, 4 minutes”
232 * it yields 7.
233 */
234static int
235seconds_count_format_time_units (int seconds)
236{
237 int minutes;
238 int hours;
239
240 if (seconds < 0) {
241 /* Just to make sure... */
242 seconds = 0;
243 }
244
245 if (seconds < 60) {
246 /* seconds */
247 return seconds;
248 }
249
250 if (seconds < 60*60) {
251 /* minutes */
252 minutes = seconds / 60;
253 return minutes;
254 }
255
256 hours = seconds / (60*60);
257
258 if (seconds < 60*60*4) {
259 /* minutes + hours */
260 minutes = (seconds - hours * 60 * 60) / 60;
261 return minutes + hours;
262 }
263
264 return hours;
265}
266
267static char *
268format_time (int seconds)
269{
270 int minutes;
271 int hours;
272 char *res;
273
274 if (seconds < 0) {
275 /* Just to make sure... */
276 seconds = 0;
277 }
278
279 if (seconds < 60) {
280 return g_strdup_printf (ngettext ("%'d second","%'d seconds", (int) seconds), (int) seconds);
281 }
282
283 if (seconds < 60*60) {
284 minutes = seconds / 60;
285 return g_strdup_printf (ngettext ("%'d minute", "%'d minutes", minutes), minutes);
286 }
287
288 hours = seconds / (60*60);
289
290 if (seconds < 60*60*4) {
291 char *h, *m;
292
293 minutes = (seconds - hours * 60 * 60) / 60;
294
295 h = g_strdup_printf (ngettext ("%'d hour", "%'d hours", hours), hours);
296 m = g_strdup_printf (ngettext ("%'d minute", "%'d minutes", minutes), minutes);
297 res = g_strconcat (h, ", ", m, NULL((void*)0));
298 g_free (h);
299 g_free (m);
300 return res;
301 }
302
303 return g_strdup_printf (ngettext ("approximately %'d hour",
304 "approximately %'d hours",
305 hours), hours);
306}
307
308static char *
309shorten_utf8_string (const char *base, int reduce_by_num_bytes)
310{
311 int len;
312 char *ret;
313 const char *p;
314
315 len = strlen (base);
316 len -= reduce_by_num_bytes;
317
318 if (len <= 0) {
319 return NULL((void*)0);
320 }
321
322 ret = g_new (char, len + 1)((char *) g_malloc_n ((len + 1), sizeof (char)));
323
324 p = base;
325 while (len) {
326 char *next;
327 next = g_utf8_next_char (p)(char *)((p) + g_utf8_skip[*(const guchar *)(p)]);
328 if (next - p > len || *next == '\0') {
329 break;
330 }
331
332 len -= next - p;
333 p = next;
334 }
335
336 if (p - base == 0) {
337 g_free (ret);
338 return NULL((void*)0);
339 } else {
340 memcpy (ret, base, p - base);
341 ret[p - base] = '\0';
342 return ret;
343 }
344}
345
346/* Note that we have these two separate functions with separate format
347 * strings for ease of localization.
348 */
349
350static char *
351get_link_name (const char *name, int count, int max_length)
352{
353 const char *format;
354 char *result;
355 int unshortened_length;
356 gboolean use_count;
357
358 g_assert (name != NULL)do { if (name != ((void*)0)) ; else g_assertion_message_expr (
((gchar*) 0), "nautilus-file-operations.c", 358, ((const char
*) (__func__)), "name != NULL"); } while (0)
;
359
360 if (count < 0) {
361 g_warning ("bad count in get_link_name");
362 count = 0;
363 }
364
365 if (count <= 2) {
366 /* Handle special cases for low numbers.
367 * Perhaps for some locales we will need to add more.
368 */
369 switch (count) {
370 default:
371 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 371, ((const char*) (__func__)), ((void*)0)); } while (0)
;
372 /* fall through */
373 case 0:
374 /* duplicate original file name */
375 format = "%s";
376 break;
377 case 1:
378 /* appended to new link file */
379 format = _("Link to %s")gettext ("Link to %s");
380 break;
381 case 2:
382 /* appended to new link file */
383 format = _("Another link to %s")gettext ("Another link to %s");
384 break;
385 }
386
387 use_count = FALSE(0);
388 } else {
389 /* Handle special cases for the first few numbers of each ten.
390 * For locales where getting this exactly right is difficult,
391 * these can just be made all the same as the general case below.
392 */
393 switch (count % 10) {
394 case 1:
395 /* Localizers: Feel free to leave out the "st" suffix
396 * if there's no way to do that nicely for a
397 * particular language.
398 */
399 format = _("%'dst link to %s")gettext ("%'dst link to %s");
400 break;
401 case 2:
402 /* appended to new link file */
403 format = _("%'dnd link to %s")gettext ("%'dnd link to %s");
404 break;
405 case 3:
406 /* appended to new link file */
407 format = _("%'drd link to %s")gettext ("%'drd link to %s");
408 break;
409 default:
410 /* appended to new link file */
411 format = _("%'dth link to %s")gettext ("%'dth link to %s");
412 break;
413 }
414
415 use_count = TRUE(!(0));
416 }
417
418 if (use_count)
419 result = g_strdup_printf (format, count, name);
420 else
421 result = g_strdup_printf (format, name);
422
423 if (max_length > 0 && (unshortened_length = strlen (result)) > max_length) {
424 char *new_name;
425
426 new_name = shorten_utf8_string (name, unshortened_length - max_length);
427 if (new_name) {
428 g_free (result);
429
430 if (use_count)
431 result = g_strdup_printf (format, count, new_name);
432 else
433 result = g_strdup_printf (format, new_name);
434
435 g_assert (strlen (result) <= max_length)do { if (strlen (result) <= max_length) ; else g_assertion_message_expr
(((gchar*) 0), "nautilus-file-operations.c", 435, ((const char
*) (__func__)), "strlen (result) <= max_length"); } while (
0)
;
436 g_free (new_name);
437 }
438 }
439
440 return result;
441}
442
443
444/* Localizers:
445 * Feel free to leave out the st, nd, rd and th suffix or
446 * make some or all of them match.
447 */
448
449/* localizers: tag used to detect the first copy of a file */
450static const char untranslated_copy_duplicate_tag[] = N_(" (copy)")(" (copy)");
451/* localizers: tag used to detect the second copy of a file */
452static const char untranslated_another_copy_duplicate_tag[] = N_(" (another copy)")(" (another copy)");
453
454/* localizers: tag used to detect the x11th copy of a file */
455static const char untranslated_x11th_copy_duplicate_tag[] = N_("th copy)")("th copy)");
456/* localizers: tag used to detect the x12th copy of a file */
457static const char untranslated_x12th_copy_duplicate_tag[] = N_("th copy)")("th copy)");
458/* localizers: tag used to detect the x13th copy of a file */
459static const char untranslated_x13th_copy_duplicate_tag[] = N_("th copy)")("th copy)");
460
461/* localizers: tag used to detect the x1st copy of a file */
462static const char untranslated_st_copy_duplicate_tag[] = N_("st copy)")("st copy)");
463/* localizers: tag used to detect the x2nd copy of a file */
464static const char untranslated_nd_copy_duplicate_tag[] = N_("nd copy)")("nd copy)");
465/* localizers: tag used to detect the x3rd copy of a file */
466static const char untranslated_rd_copy_duplicate_tag[] = N_("rd copy)")("rd copy)");
467
468/* localizers: tag used to detect the xxth copy of a file */
469static const char untranslated_th_copy_duplicate_tag[] = N_("th copy)")("th copy)");
470
471#define COPY_DUPLICATE_TAGgettext (untranslated_copy_duplicate_tag) _(untranslated_copy_duplicate_tag)gettext (untranslated_copy_duplicate_tag)
472#define ANOTHER_COPY_DUPLICATE_TAGgettext (untranslated_another_copy_duplicate_tag) _(untranslated_another_copy_duplicate_tag)gettext (untranslated_another_copy_duplicate_tag)
473#define X11TH_COPY_DUPLICATE_TAGgettext (untranslated_x11th_copy_duplicate_tag) _(untranslated_x11th_copy_duplicate_tag)gettext (untranslated_x11th_copy_duplicate_tag)
474#define X12TH_COPY_DUPLICATE_TAGgettext (untranslated_x12th_copy_duplicate_tag) _(untranslated_x12th_copy_duplicate_tag)gettext (untranslated_x12th_copy_duplicate_tag)
475#define X13TH_COPY_DUPLICATE_TAGgettext (untranslated_x13th_copy_duplicate_tag) _(untranslated_x13th_copy_duplicate_tag)gettext (untranslated_x13th_copy_duplicate_tag)
476
477#define ST_COPY_DUPLICATE_TAGgettext (untranslated_st_copy_duplicate_tag) _(untranslated_st_copy_duplicate_tag)gettext (untranslated_st_copy_duplicate_tag)
478#define ND_COPY_DUPLICATE_TAGgettext (untranslated_nd_copy_duplicate_tag) _(untranslated_nd_copy_duplicate_tag)gettext (untranslated_nd_copy_duplicate_tag)
479#define RD_COPY_DUPLICATE_TAGgettext (untranslated_rd_copy_duplicate_tag) _(untranslated_rd_copy_duplicate_tag)gettext (untranslated_rd_copy_duplicate_tag)
480#define TH_COPY_DUPLICATE_TAGgettext (untranslated_th_copy_duplicate_tag) _(untranslated_th_copy_duplicate_tag)gettext (untranslated_th_copy_duplicate_tag)
481
482/* localizers: appended to first file copy */
483static const char untranslated_first_copy_duplicate_format[] = N_("%s (copy)%s")("%s (copy)%s");
484/* localizers: appended to second file copy */
485static const char untranslated_second_copy_duplicate_format[] = N_("%s (another copy)%s")("%s (another copy)%s");
486
487/* localizers: appended to x11th file copy */
488static const char untranslated_x11th_copy_duplicate_format[] = N_("%s (%'dth copy)%s")("%s (%'dth copy)%s");
489/* localizers: appended to x12th file copy */
490static const char untranslated_x12th_copy_duplicate_format[] = N_("%s (%'dth copy)%s")("%s (%'dth copy)%s");
491/* localizers: appended to x13th file copy */
492static const char untranslated_x13th_copy_duplicate_format[] = N_("%s (%'dth copy)%s")("%s (%'dth copy)%s");
493
494/* localizers: if in your language there's no difference between 1st, 2nd, 3rd and nth
495 * plurals, you can leave the st, nd, rd suffixes out and just make all the translated
496 * strings look like "%s (copy %'d)%s".
497 */
498
499/* localizers: appended to x1st file copy */
500static const char untranslated_st_copy_duplicate_format[] = N_("%s (%'dst copy)%s")("%s (%'dst copy)%s");
501/* localizers: appended to x2nd file copy */
502static const char untranslated_nd_copy_duplicate_format[] = N_("%s (%'dnd copy)%s")("%s (%'dnd copy)%s");
503/* localizers: appended to x3rd file copy */
504static const char untranslated_rd_copy_duplicate_format[] = N_("%s (%'drd copy)%s")("%s (%'drd copy)%s");
505/* localizers: appended to xxth file copy */
506static const char untranslated_th_copy_duplicate_format[] = N_("%s (%'dth copy)%s")("%s (%'dth copy)%s");
507
508#define FIRST_COPY_DUPLICATE_FORMATgettext (untranslated_first_copy_duplicate_format) _(untranslated_first_copy_duplicate_format)gettext (untranslated_first_copy_duplicate_format)
509#define SECOND_COPY_DUPLICATE_FORMATgettext (untranslated_second_copy_duplicate_format) _(untranslated_second_copy_duplicate_format)gettext (untranslated_second_copy_duplicate_format)
510#define X11TH_COPY_DUPLICATE_FORMATgettext (untranslated_x11th_copy_duplicate_format) _(untranslated_x11th_copy_duplicate_format)gettext (untranslated_x11th_copy_duplicate_format)
511#define X12TH_COPY_DUPLICATE_FORMATgettext (untranslated_x12th_copy_duplicate_format) _(untranslated_x12th_copy_duplicate_format)gettext (untranslated_x12th_copy_duplicate_format)
512#define X13TH_COPY_DUPLICATE_FORMATgettext (untranslated_x13th_copy_duplicate_format) _(untranslated_x13th_copy_duplicate_format)gettext (untranslated_x13th_copy_duplicate_format)
513
514#define ST_COPY_DUPLICATE_FORMATgettext (untranslated_st_copy_duplicate_format) _(untranslated_st_copy_duplicate_format)gettext (untranslated_st_copy_duplicate_format)
515#define ND_COPY_DUPLICATE_FORMATgettext (untranslated_nd_copy_duplicate_format) _(untranslated_nd_copy_duplicate_format)gettext (untranslated_nd_copy_duplicate_format)
516#define RD_COPY_DUPLICATE_FORMATgettext (untranslated_rd_copy_duplicate_format) _(untranslated_rd_copy_duplicate_format)gettext (untranslated_rd_copy_duplicate_format)
517#define TH_COPY_DUPLICATE_FORMATgettext (untranslated_th_copy_duplicate_format) _(untranslated_th_copy_duplicate_format)gettext (untranslated_th_copy_duplicate_format)
518
519static char *
520extract_string_until (const char *original, const char *until_substring)
521{
522 char *result;
523
524 g_assert ((int) strlen (original) >= until_substring - original)do { if ((int) strlen (original) >= until_substring - original
) ; else g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 524, ((const char*) (__func__)), "(int) strlen (original) >= until_substring - original"
); } while (0)
;
525 g_assert (until_substring - original >= 0)do { if (until_substring - original >= 0) ; else g_assertion_message_expr
(((gchar*) 0), "nautilus-file-operations.c", 525, ((const char
*) (__func__)), "until_substring - original >= 0"); } while
(0)
;
526
527 result = g_malloc (until_substring - original + 1);
528 strncpy (result, original, until_substring - original);
529 result[until_substring - original] = '\0';
530
531 return result;
532}
533
534/* Dismantle a file name, separating the base name, the file suffix and removing any
535 * (xxxcopy), etc. string. Figure out the count that corresponds to the given
536 * (xxxcopy) substring.
537 */
538static void
539parse_previous_duplicate_name (const char *name,
540 char **name_base,
541 const char **suffix,
542 int *count)
543{
544 const char *tag;
545
546 g_assert (name[0] != '\0')do { if (name[0] != '\0') ; else g_assertion_message_expr (((
gchar*) 0), "nautilus-file-operations.c", 546, ((const char*)
(__func__)), "name[0] != '\\0'"); } while (0)
;
547
548 *suffix = eel_filename_get_extension_offset (name);
549
550 if (*suffix == NULL((void*)0) || (*suffix)[1] == '\0') {
551 /* no suffix */
552 *suffix = "";
553 }
554
555 tag = strstr (name, COPY_DUPLICATE_TAGgettext (untranslated_copy_duplicate_tag));
556 if (tag != NULL((void*)0)) {
557 if (tag > *suffix) {
558 /* handle case "foo. (copy)" */
559 *suffix = "";
560 }
561 *name_base = extract_string_until (name, tag);
562 *count = 1;
563 return;
564 }
565
566
567 tag = strstr (name, ANOTHER_COPY_DUPLICATE_TAGgettext (untranslated_another_copy_duplicate_tag));
568 if (tag != NULL((void*)0)) {
569 if (tag > *suffix) {
570 /* handle case "foo. (another copy)" */
571 *suffix = "";
572 }
573 *name_base = extract_string_until (name, tag);
574 *count = 2;
575 return;
576 }
577
578
579 /* Check to see if we got one of st, nd, rd, th. */
580 tag = strstr (name, X11TH_COPY_DUPLICATE_TAGgettext (untranslated_x11th_copy_duplicate_tag));
581
582 if (tag == NULL((void*)0)) {
583 tag = strstr (name, X12TH_COPY_DUPLICATE_TAGgettext (untranslated_x12th_copy_duplicate_tag));
584 }
585 if (tag == NULL((void*)0)) {
586 tag = strstr (name, X13TH_COPY_DUPLICATE_TAGgettext (untranslated_x13th_copy_duplicate_tag));
587 }
588
589 if (tag == NULL((void*)0)) {
590 tag = strstr (name, ST_COPY_DUPLICATE_TAGgettext (untranslated_st_copy_duplicate_tag));
591 }
592 if (tag == NULL((void*)0)) {
593 tag = strstr (name, ND_COPY_DUPLICATE_TAGgettext (untranslated_nd_copy_duplicate_tag));
594 }
595 if (tag == NULL((void*)0)) {
596 tag = strstr (name, RD_COPY_DUPLICATE_TAGgettext (untranslated_rd_copy_duplicate_tag));
597 }
598 if (tag == NULL((void*)0)) {
599 tag = strstr (name, TH_COPY_DUPLICATE_TAGgettext (untranslated_th_copy_duplicate_tag));
600 }
601
602 /* If we got one of st, nd, rd, th, fish out the duplicate number. */
603 if (tag != NULL((void*)0)) {
604 /* localizers: opening parentheses to match the "th copy)" string */
605 tag = strstr (name, _(" (")gettext (" ("));
606 if (tag != NULL((void*)0)) {
607 if (tag > *suffix) {
608 /* handle case "foo. (22nd copy)" */
609 *suffix = "";
610 }
611 *name_base = extract_string_until (name, tag);
612 /* localizers: opening parentheses of the "th copy)" string */
613 if (sscanf (tag, _(" (%'d")gettext (" (%'d"), count) == 1) {
614 if (*count < 1 || *count > 1000000) {
615 /* keep the count within a reasonable range */
616 *count = 0;
617 }
618 return;
619 }
620 *count = 0;
621 return;
622 }
623 }
624
625
626 *count = 0;
627 if (**suffix != '\0') {
628 *name_base = extract_string_until (name, *suffix);
629 } else {
630 *name_base = g_strdup (name);
631 }
632}
633
634static char *
635make_next_duplicate_name (const char *base, const char *suffix, int count, int max_length)
636{
637 const char *format;
638 char *result;
639 int unshortened_length;
640 gboolean use_count;
641
642 if (count < 1) {
643 g_warning ("bad count %d in get_duplicate_name", count);
644 count = 1;
645 }
646
647 if (count <= 2) {
648
649 /* Handle special cases for low numbers.
650 * Perhaps for some locales we will need to add more.
651 */
652 switch (count) {
653 default:
654 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 654, ((const char*) (__func__)), ((void*)0)); } while (0)
;
655 /* fall through */
656 case 1:
657 format = FIRST_COPY_DUPLICATE_FORMATgettext (untranslated_first_copy_duplicate_format);
658 break;
659 case 2:
660 format = SECOND_COPY_DUPLICATE_FORMATgettext (untranslated_second_copy_duplicate_format);
661 break;
662
663 }
664
665 use_count = FALSE(0);
666 } else {
667
668 /* Handle special cases for the first few numbers of each ten.
669 * For locales where getting this exactly right is difficult,
670 * these can just be made all the same as the general case below.
671 */
672
673 /* Handle special cases for x11th - x20th.
674 */
675 switch (count % 100) {
676 case 11:
677 format = X11TH_COPY_DUPLICATE_FORMATgettext (untranslated_x11th_copy_duplicate_format);
678 break;
679 case 12:
680 format = X12TH_COPY_DUPLICATE_FORMATgettext (untranslated_x12th_copy_duplicate_format);
681 break;
682 case 13:
683 format = X13TH_COPY_DUPLICATE_FORMATgettext (untranslated_x13th_copy_duplicate_format);
684 break;
685 default:
686 format = NULL((void*)0);
687 break;
688 }
689
690 if (format == NULL((void*)0)) {
691 switch (count % 10) {
692 case 1:
693 format = ST_COPY_DUPLICATE_FORMATgettext (untranslated_st_copy_duplicate_format);
694 break;
695 case 2:
696 format = ND_COPY_DUPLICATE_FORMATgettext (untranslated_nd_copy_duplicate_format);
697 break;
698 case 3:
699 format = RD_COPY_DUPLICATE_FORMATgettext (untranslated_rd_copy_duplicate_format);
700 break;
701 default:
702 /* The general case. */
703 format = TH_COPY_DUPLICATE_FORMATgettext (untranslated_th_copy_duplicate_format);
704 break;
705 }
706 }
707
708 use_count = TRUE(!(0));
709
710 }
711
712 if (use_count)
713 result = g_strdup_printf (format, base, count, suffix);
714 else
715 result = g_strdup_printf (format, base, suffix);
716
717 if (max_length > 0 && (unshortened_length = strlen (result)) > max_length) {
718 char *new_base;
719
720 new_base = shorten_utf8_string (base, unshortened_length - max_length);
721 if (new_base) {
722 g_free (result);
723
724 if (use_count)
725 result = g_strdup_printf (format, new_base, count, suffix);
726 else
727 result = g_strdup_printf (format, new_base, suffix);
728
729 g_assert (strlen (result) <= max_length)do { if (strlen (result) <= max_length) ; else g_assertion_message_expr
(((gchar*) 0), "nautilus-file-operations.c", 729, ((const char
*) (__func__)), "strlen (result) <= max_length"); } while (
0)
;
730 g_free (new_base);
731 }
732 }
733
734 return result;
735}
736
737static char *
738get_duplicate_name (const char *name, int count_increment, int max_length)
739{
740 char *result;
741 char *name_base;
742 const char *suffix;
743 int count;
744
745 parse_previous_duplicate_name (name, &name_base, &suffix, &count);
746 result = make_next_duplicate_name (name_base, suffix, count + count_increment, max_length);
747
748 g_free (name_base);
749
750 return result;
751}
752
753static gboolean
754has_invalid_xml_char (char *str)
755{
756 gunichar c;
757
758 while (*str != 0) {
759 c = g_utf8_get_char (str);
760 /* characters XML permits */
761 if (!(c == 0x9 ||
762 c == 0xA ||
763 c == 0xD ||
764 (c >= 0x20 && c <= 0xD7FF) ||
765 (c >= 0xE000 && c <= 0xFFFD) ||
766 (c >= 0x10000 && c <= 0x10FFFF))) {
767 return TRUE(!(0));
768 }
769 str = g_utf8_next_char (str)(char *)((str) + g_utf8_skip[*(const guchar *)(str)]);
770 }
771 return FALSE(0);
772}
773
774
775static char *
776custom_full_name_to_string (char *format, va_list va)
777{
778 GFile *file;
779
780 file = va_arg (va, GFile *)__builtin_va_arg(va, GFile *);
781
782 return g_file_get_parse_name (file);
783}
784
785static void
786custom_full_name_skip (va_list *va)
787{
788 (void) va_arg (*va, GFile *)__builtin_va_arg(*va, GFile *);
789}
790
791static char *
792custom_basename_to_string (char *format, va_list va)
793{
794 GFile *file;
795 GFileInfo *info;
796 char *name, *basename, *tmp;
797
798 file = va_arg (va, GFile *)__builtin_va_arg(va, GFile *);
799
800 info = g_file_query_info (file,
801 G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME"standard::display-name",
802 0,
803 g_cancellable_get_current (),
804 NULL((void*)0));
805
806 name = NULL((void*)0);
807 if (info) {
808 name = g_strdup (g_file_info_get_display_name (info));
809 g_object_unref (info);
810 }
811
812 if (name == NULL((void*)0)) {
813 basename = g_file_get_basename (file);
814 if (g_utf8_validate (basename, -1, NULL((void*)0))) {
815 name = basename;
816 } else {
817 name = g_uri_escape_string (basename, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH"!$&'()*+,;=" ":@" "/", TRUE(!(0)));
818 g_free (basename);
819 }
820 }
821
822 /* Some chars can't be put in the markup we use for the dialogs... */
823 if (has_invalid_xml_char (name)) {
824 tmp = name;
825 name = g_uri_escape_string (name, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH"!$&'()*+,;=" ":@" "/", TRUE(!(0)));
826 g_free (tmp);
827 }
828
829 /* Finally, if the string is too long, truncate it. */
830 if (name != NULL((void*)0)) {
831 tmp = name;
832 name = eel_str_middle_truncate (tmp, MAXIMUM_DISPLAYED_FILE_NAME_LENGTH50);
833 g_free (tmp);
834 }
835
836
837 return name;
838}
839
840static void
841custom_basename_skip (va_list *va)
842{
843 (void) va_arg (*va, GFile *)__builtin_va_arg(*va, GFile *);
844}
845
846
847static char *
848custom_size_to_string (char *format, va_list va)
849{
850 goffset size;
851
852 size = va_arg (va, goffset)__builtin_va_arg(va, goffset);
853 return g_format_size (size);
854}
855
856static void
857custom_size_skip (va_list *va)
858{
859 (void) va_arg (*va, goffset)__builtin_va_arg(*va, goffset);
860}
861
862static char *
863custom_time_to_string (char *format, va_list va)
864{
865 int secs;
866
867 secs = va_arg (va, int)__builtin_va_arg(va, int);
868 return format_time (secs);
869}
870
871static void
872custom_time_skip (va_list *va)
873{
874 (void) va_arg (*va, int)__builtin_va_arg(*va, int);
875}
876
877static char *
878custom_mount_to_string (char *format, va_list va)
879{
880 GMount *mount;
881
882 mount = va_arg (va, GMount *)__builtin_va_arg(va, GMount *);
883 return g_mount_get_name (mount);
884}
885
886static void
887custom_mount_skip (va_list *va)
888{
889 (void) va_arg (*va, GMount *)__builtin_va_arg(*va, GMount *);
890}
891
892
893static EelPrintfHandler handlers[] = {
894 { 'F', custom_full_name_to_string, custom_full_name_skip },
895 { 'B', custom_basename_to_string, custom_basename_skip },
896 { 'S', custom_size_to_string, custom_size_skip },
897 { 'T', custom_time_to_string, custom_time_skip },
898 { 'V', custom_mount_to_string, custom_mount_skip },
899 { 0 }
900};
901
902
903static char *
904f (const char *format, ...) {
905 va_list va;
906 char *res;
907
908 va_start (va, format)__builtin_va_start(va, format);
909 res = eel_strdup_vprintf_with_custom (handlers, format, va);
910 va_end (va)__builtin_va_end(va);
911
912 return res;
913}
914
915#define op_job_new(__type, parent_window)((__type *)(init_common (sizeof(__type), parent_window))) ((__type *)(init_common (sizeof(__type), parent_window)))
916
917static gpointer
918init_common (gsize job_size,
919 GtkWindow *parent_window)
920{
921 CommonJob *common;
922 GdkScreen *screen;
923
924 common = g_malloc0 (job_size);
925
926 if (parent_window) {
927 common->parent_window = parent_window;
928 g_object_add_weak_pointer (G_OBJECT (common->parent_window)((((GObject*) g_type_check_instance_cast ((GTypeInstance*) ((
common->parent_window)), (((GType) ((20) << (2))))))
))
,
929 (gpointer *) &common->parent_window);
930
931 }
932 common->progress = nautilus_progress_info_new ();
933 common->cancellable = nautilus_progress_info_get_cancellable (common->progress);
934 common->time = g_timer_new ();
935 common->inhibit_cookie = -1;
936 common->screen_num = 0;
937 if (parent_window) {
938 screen = gtk_widget_get_screen (GTK_WIDGET (parent_window)((((GtkWidget*) g_type_check_instance_cast ((GTypeInstance*) (
(parent_window)), ((gtk_widget_get_type ()))))))
);
939 common->screen_num = gdk_screen_get_number (screen);
940 }
941
942 return common;
943}
944
945static void
946finalize_common (CommonJob *common)
947{
948 nautilus_progress_info_finish (common->progress);
949
950 if (common->inhibit_cookie != -1) {
951 gtk_application_uninhibit (GTK_APPLICATION (g_application_get_default ())((((GtkApplication*) g_type_check_instance_cast ((GTypeInstance
*) ((g_application_get_default ())), ((gtk_application_get_type
()))))))
,
952 common->inhibit_cookie);
953 }
954
955 common->inhibit_cookie = -1;
956 g_timer_destroy (common->time);
957
958 if (common->parent_window) {
959 g_object_remove_weak_pointer (G_OBJECT (common->parent_window)((((GObject*) g_type_check_instance_cast ((GTypeInstance*) ((
common->parent_window)), (((GType) ((20) << (2))))))
))
,
960 (gpointer *) &common->parent_window);
961 }
962
963 if (common->skip_files) {
964 g_hash_table_destroy (common->skip_files);
965 }
966 if (common->skip_readdir_error) {
967 g_hash_table_destroy (common->skip_readdir_error);
968 }
969
970 if (common->undo_info != NULL((void*)0)) {
971 nautilus_file_undo_manager_set_action (common->undo_info);
972 g_object_unref (common->undo_info);
973 }
974
975 g_object_unref (common->progress);
976 g_object_unref (common->cancellable);
977 g_free (common);
978}
979
980static void
981skip_file (CommonJob *common,
982 GFile *file)
983{
984 if (common->skip_files == NULL((void*)0)) {
985 common->skip_files =
986 g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
987 }
988
989 g_hash_table_insert (common->skip_files, g_object_ref (file), file);
990}
991
992static void
993skip_readdir_error (CommonJob *common,
994 GFile *dir)
995{
996 if (common->skip_readdir_error == NULL((void*)0)) {
997 common->skip_readdir_error =
998 g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
999 }
1000
1001 g_hash_table_insert (common->skip_readdir_error, g_object_ref (dir), dir);
1002}
1003
1004static gboolean
1005should_skip_file (CommonJob *common,
1006 GFile *file)
1007{
1008 if (common->skip_files != NULL((void*)0)) {
1009 return g_hash_table_lookup (common->skip_files, file) != NULL((void*)0);
1010 }
1011 return FALSE(0);
1012}
1013
1014static gboolean
1015should_skip_readdir_error (CommonJob *common,
1016 GFile *dir)
1017{
1018 if (common->skip_readdir_error != NULL((void*)0)) {
1019 return g_hash_table_lookup (common->skip_readdir_error, dir) != NULL((void*)0);
1020 }
1021 return FALSE(0);
1022}
1023
1024static gboolean
1025can_delete_without_confirm (GFile *file)
1026{
1027 if (g_file_has_uri_scheme (file, "burn") ||
1028 g_file_has_uri_scheme (file, "recent") ||
1029 g_file_has_uri_scheme (file, "x-nautilus-desktop")) {
1030 return TRUE(!(0));
1031 }
1032
1033 return FALSE(0);
1034}
1035
1036static gboolean
1037can_delete_files_without_confirm (GList *files)
1038{
1039 g_assert (files != NULL)do { if (files != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "nautilus-file-operations.c", 1039, ((const char
*) (__func__)), "files != NULL"); } while (0)
;
1040
1041 while (files != NULL((void*)0)) {
1042 if (!can_delete_without_confirm (files->data)) {
1043 return FALSE(0);
1044 }
1045
1046 files = files->next;
1047 }
1048
1049 return TRUE(!(0));
1050}
1051
1052typedef struct {
1053 GtkWindow **parent_window;
1054 gboolean ignore_close_box;
1055 GtkMessageType message_type;
1056 const char *primary_text;
1057 const char *secondary_text;
1058 const char *details_text;
1059 const char **button_titles;
1060 gboolean show_all;
1061
1062 int result;
1063} RunSimpleDialogData;
1064
1065static gboolean
1066do_run_simple_dialog (gpointer _data)
1067{
1068 RunSimpleDialogData *data = _data;
1069 const char *button_title;
1070 GtkWidget *dialog;
1071 int result;
1072 int response_id;
1073
1074 /* Create the dialog. */
1075 dialog = gtk_message_dialog_new (*data->parent_window,
1076 0,
1077 data->message_type,
1078 GTK_BUTTONS_NONE,
1079 NULL((void*)0));
1080
1081 g_object_set (dialog,
1082 "text", data->primary_text,
1083 "secondary-text", data->secondary_text,
1084 NULL((void*)0));
1085
1086 for (response_id = 0;
1087 data->button_titles[response_id] != NULL((void*)0);
1088 response_id++) {
1089 button_title = data->button_titles[response_id];
1090 if (!data->show_all && is_all_button_text (button_title)) {
1091 continue;
1092 }
1093
1094 gtk_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) g_type_check_instance_cast ((GTypeInstance*) (
(dialog)), ((gtk_dialog_get_type ()))))))
, button_title, response_id);
1095 gtk_dialog_set_default_response (GTK_DIALOG (dialog)((((GtkDialog*) g_type_check_instance_cast ((GTypeInstance*) (
(dialog)), ((gtk_dialog_get_type ()))))))
, response_id);
1096 }
1097
1098 if (data->details_text) {
1099 eel_gtk_message_dialog_set_details_label (GTK_MESSAGE_DIALOG (dialog)((((GtkMessageDialog*) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((gtk_message_dialog_get_type ()))))))
,
1100 data->details_text);
1101 }
1102
1103 /* Run it. */
1104 result = gtk_dialog_run (GTK_DIALOG (dialog)((((GtkDialog*) g_type_check_instance_cast ((GTypeInstance*) (
(dialog)), ((gtk_dialog_get_type ()))))))
);
1105
1106 while ((result == GTK_RESPONSE_NONE || result == GTK_RESPONSE_DELETE_EVENT) && data->ignore_close_box) {
1107 result = gtk_dialog_run (GTK_DIALOG (dialog)((((GtkDialog*) g_type_check_instance_cast ((GTypeInstance*) (
(dialog)), ((gtk_dialog_get_type ()))))))
);
1108 }
1109
1110 gtk_widget_destroy (dialog);
1111
1112 data->result = result;
1113
1114 return FALSE(0);
1115}
1116
1117/* NOTE: This frees the primary / secondary strings, in order to
1118 avoid doing that everywhere. So, make sure they are strduped */
1119
1120static int
1121run_simple_dialog_va (CommonJob *job,
1122 gboolean ignore_close_box,
1123 GtkMessageType message_type,
1124 char *primary_text,
1125 char *secondary_text,
1126 const char *details_text,
1127 gboolean show_all,
1128 va_list varargs)
1129{
1130 RunSimpleDialogData *data;
1131 int res;
1132 const char *button_title;
1133 GPtrArray *ptr_array;
1134
1135 g_timer_stop (job->time);
1136
1137 data = g_new0 (RunSimpleDialogData, 1)((RunSimpleDialogData *) g_malloc0_n ((1), sizeof (RunSimpleDialogData
)))
;
1138 data->parent_window = &job->parent_window;
1139 data->ignore_close_box = ignore_close_box;
1140 data->message_type = message_type;
1141 data->primary_text = primary_text;
1142 data->secondary_text = secondary_text;
1143 data->details_text = details_text;
1144 data->show_all = show_all;
1145
1146 ptr_array = g_ptr_array_new ();
1147 while ((button_title = va_arg (varargs, const char *)__builtin_va_arg(varargs, const char *)) != NULL((void*)0)) {
1148 g_ptr_array_add (ptr_array, (char *)button_title);
1149 }
1150 g_ptr_array_add (ptr_array, NULL((void*)0));
1151 data->button_titles = (const char **)g_ptr_array_free (ptr_array, FALSE(0));
1152
1153 nautilus_progress_info_pause (job->progress);
1154 g_io_scheduler_job_send_to_mainloop (job->io_job,
1155 do_run_simple_dialog,
1156 data,
1157 NULL((void*)0));
1158 nautilus_progress_info_resume (job->progress);
1159 res = data->result;
1160
1161 g_free (data->button_titles);
1162 g_free (data);
1163
1164 g_timer_continue (job->time);
1165
1166 g_free (primary_text);
1167 g_free (secondary_text);
1168
1169 return res;
1170}
1171
1172#if 0 /* Not used at the moment */
1173static int
1174run_simple_dialog (CommonJob *job,
1175 gboolean ignore_close_box,
1176 GtkMessageType message_type,
1177 char *primary_text,
1178 char *secondary_text,
1179 const char *details_text,
1180 ...)
1181{
1182 va_list varargs;
1183 int res;
1184
1185 va_start (varargs, details_text)__builtin_va_start(varargs, details_text);
1186 res = run_simple_dialog_va (job,
1187 ignore_close_box,
1188 message_type,
1189 primary_text,
1190 secondary_text,
1191 details_text,
1192 varargs);
1193 va_end (varargs)__builtin_va_end(varargs);
1194 return res;
1195}
1196#endif
1197
1198static int
1199run_error (CommonJob *job,
1200 char *primary_text,
1201 char *secondary_text,
1202 const char *details_text,
1203 gboolean show_all,
1204 ...)
1205{
1206 va_list varargs;
1207 int res;
1208
1209 va_start (varargs, show_all)__builtin_va_start(varargs, show_all);
1210 res = run_simple_dialog_va (job,
1211 FALSE(0),
1212 GTK_MESSAGE_ERROR,
1213 primary_text,
1214 secondary_text,
1215 details_text,
1216 show_all,
1217 varargs);
1218 va_end (varargs)__builtin_va_end(varargs);
1219 return res;
1220}
1221
1222static int
1223run_warning (CommonJob *job,
1224 char *primary_text,
1225 char *secondary_text,
1226 const char *details_text,
1227 gboolean show_all,
1228 ...)
1229{
1230 va_list varargs;
1231 int res;
1232
1233 va_start (varargs, show_all)__builtin_va_start(varargs, show_all);
1234 res = run_simple_dialog_va (job,
1235 FALSE(0),
1236 GTK_MESSAGE_WARNING,
1237 primary_text,
1238 secondary_text,
1239 details_text,
1240 show_all,
1241 varargs);
1242 va_end (varargs)__builtin_va_end(varargs);
1243 return res;
1244}
1245
1246static int
1247run_question (CommonJob *job,
1248 char *primary_text,
1249 char *secondary_text,
1250 const char *details_text,
1251 gboolean show_all,
1252 ...)
1253{
1254 va_list varargs;
1255 int res;
1256
1257 va_start (varargs, show_all)__builtin_va_start(varargs, show_all);
1258 res = run_simple_dialog_va (job,
1259 FALSE(0),
1260 GTK_MESSAGE_QUESTION,
1261 primary_text,
1262 secondary_text,
1263 details_text,
1264 show_all,
1265 varargs);
1266 va_end (varargs)__builtin_va_end(varargs);
1267 return res;
1268}
1269
1270static int
1271run_cancel_or_skip_warning (CommonJob *job,
1272 char *primary_text,
1273 char *secondary_text,
1274 const char *details_text,
1275 int total_operations,
1276 int operations_remaining)
1277{
1278 int response;
1279
1280 if (total_operations == 1) {
1281 response = run_warning (job,
1282 primary_text,
1283 secondary_text,
1284 details_text,
1285 FALSE(0),
1286 CANCELgettext ("_Cancel"),
1287 NULL((void*)0));
1288 } else {
1289 response = run_warning (job,
1290 primary_text,
1291 secondary_text,
1292 details_text,
1293 operations_remaining > 1,
1294 CANCELgettext ("_Cancel"), SKIP_ALLgettext ("S_kip All"), SKIPgettext ("_Skip"),
1295 NULL((void*)0));
1296 }
1297
1298 return response;
1299}
1300
1301static void
1302inhibit_power_manager (CommonJob *job, const char *message)
1303{
1304 job->inhibit_cookie = gtk_application_inhibit (GTK_APPLICATION (g_application_get_default ())((((GtkApplication*) g_type_check_instance_cast ((GTypeInstance
*) ((g_application_get_default ())), ((gtk_application_get_type
()))))))
,
1305 GTK_WINDOW (job->parent_window)((((GtkWindow*) g_type_check_instance_cast ((GTypeInstance*) (
(job->parent_window)), ((gtk_window_get_type ()))))))
,
1306 GTK_APPLICATION_INHIBIT_LOGOUT |
1307 GTK_APPLICATION_INHIBIT_SUSPEND,
1308 message);
1309}
1310
1311static void
1312abort_job (CommonJob *job)
1313{
1314 /* destroy the undo action data too */
1315 g_clear_object (&job->undo_info)do { typedef char _GStaticAssertCompileTimeAssertion_27[(sizeof
*((&job->undo_info)) == sizeof (gpointer)) ? 1 : -1] __attribute__
((__unused__)); gpointer *_pp = (gpointer *) ((&job->undo_info
)); gpointer _p; GDestroyNotify _destroy = (GDestroyNotify) (
g_object_unref); (void) (0 ? (gpointer) *((&job->undo_info
)) : 0); do _p = (__extension__ ({ typedef char _GStaticAssertCompileTimeAssertion_28
[(sizeof *(_pp) == sizeof (gpointer)) ? 1 : -1] __attribute__
((__unused__)); __sync_synchronize (); (gpointer) *(_pp); }))
; while (!(__extension__ ({ typedef char _GStaticAssertCompileTimeAssertion_29
[(sizeof *(_pp) == sizeof (gpointer)) ? 1 : -1] __attribute__
((__unused__)); (void) (0 ? (gpointer) *(_pp) : 0); (gboolean
) __sync_bool_compare_and_swap ((_pp), (_p), (((void*)0))); }
))); if (_p) _destroy (_p); } while (0)
;
1316
1317 g_cancellable_cancel (job->cancellable);
1318}
1319
1320static gboolean
1321job_aborted (CommonJob *job)
1322{
1323 return g_cancellable_is_cancelled (job->cancellable);
1324}
1325
1326/* Since this happens on a thread we can't use the global prefs object */
1327static gboolean
1328should_confirm_trash (void)
1329{
1330 GSettings *prefs;
1331 gboolean confirm_trash;
1332
1333 prefs = g_settings_new ("org.gnome.nautilus.preferences");
1334 confirm_trash = g_settings_get_boolean (prefs, NAUTILUS_PREFERENCES_CONFIRM_TRASH"confirm-trash");
1335 g_object_unref (prefs);
1336 return confirm_trash;
1337}
1338
1339static gboolean
1340confirm_delete_from_trash (CommonJob *job,
1341 GList *files)
1342{
1343 char *prompt;
1344 int file_count;
1345 int response;
1346
1347 /* Just Say Yes if the preference says not to confirm. */
1348 if (!should_confirm_trash ()) {
1349 return TRUE(!(0));
1350 }
1351
1352 file_count = g_list_length (files);
1353 g_assert (file_count > 0)do { if (file_count > 0) ; else g_assertion_message_expr (
((gchar*) 0), "nautilus-file-operations.c", 1353, ((const char
*) (__func__)), "file_count > 0"); } while (0)
;
1354
1355 if (file_count == 1) {
1356 prompt = f (_("Are you sure you want to permanently delete “%B” "gettext ("Are you sure you want to permanently delete “%B” "
"from the trash?")
1357 "from the trash?")gettext ("Are you sure you want to permanently delete “%B” "
"from the trash?")
, files->data);
1358 } else {
1359 prompt = f (ngettext("Are you sure you want to permanently delete "
1360 "the %'d selected item from the trash?",
1361 "Are you sure you want to permanently delete "
1362 "the %'d selected items from the trash?",
1363 file_count),
1364 file_count);
1365 }
1366
1367 response = run_warning (job,
1368 prompt,
1369 f (_("If you delete an item, it will be permanently lost.")gettext ("If you delete an item, it will be permanently lost."
)
),
1370 NULL((void*)0),
1371 FALSE(0),
1372 CANCELgettext ("_Cancel"), DELETEgettext ("_Delete"),
1373 NULL((void*)0));
1374
1375 return (response == 1);
1376}
1377
1378static gboolean
1379confirm_empty_trash (CommonJob *job)
1380{
1381 char *prompt;
1382 int response;
1383
1384 /* Just Say Yes if the preference says not to confirm. */
1385 if (!should_confirm_trash ()) {
1386 return TRUE(!(0));
1387 }
1388
1389 prompt = f (_("Empty all items from Trash?")gettext ("Empty all items from Trash?"));
1390
1391 response = run_warning (job,
1392 prompt,
1393 f(_("All items in the Trash will be permanently deleted.")gettext ("All items in the Trash will be permanently deleted."
)
),
1394 NULL((void*)0),
1395 FALSE(0),
1396 CANCELgettext ("_Cancel"), _("Empty _Trash")gettext ("Empty _Trash"),
1397 NULL((void*)0));
1398
1399 return (response == 1);
1400}
1401
1402static gboolean
1403confirm_delete_directly (CommonJob *job,
1404 GList *files)
1405{
1406 char *prompt;
1407 int file_count;
1408 int response;
1409
1410 /* Just Say Yes if the preference says not to confirm. */
1411 if (!should_confirm_trash ()) {
1412 return TRUE(!(0));
1413 }
1414
1415 file_count = g_list_length (files);
1416 g_assert (file_count > 0)do { if (file_count > 0) ; else g_assertion_message_expr (
((gchar*) 0), "nautilus-file-operations.c", 1416, ((const char
*) (__func__)), "file_count > 0"); } while (0)
;
1417
1418 if (can_delete_files_without_confirm (files)) {
1419 return TRUE(!(0));
1420 }
1421
1422 if (file_count == 1) {
1423 prompt = f (_("Are you sure you want to permanently delete “%B”?")gettext ("Are you sure you want to permanently delete “%B”?"
)
,
1424 files->data);
1425 } else {
1426 prompt = f (ngettext("Are you sure you want to permanently delete "
1427 "the %'d selected item?",
1428 "Are you sure you want to permanently delete "
1429 "the %'d selected items?", file_count),
1430 file_count);
1431 }
1432
1433 response = run_warning (job,
1434 prompt,
1435 f (_("If you delete an item, it will be permanently lost.")gettext ("If you delete an item, it will be permanently lost."
)
),
1436 NULL((void*)0),
1437 FALSE(0),
1438 CANCELgettext ("_Cancel"), DELETEgettext ("_Delete"),
1439 NULL((void*)0));
1440
1441 return response == 1;
1442}
1443
1444static void
1445report_delete_progress (CommonJob *job,
1446 SourceInfo *source_info,
1447 TransferInfo *transfer_info)
1448{
1449 int files_left;
1450 double elapsed, transfer_rate;
1451 int remaining_time;
1452 gint64 now;
1453 char *files_left_s;
1454
1455 now = g_get_monotonic_time ();
1456 if (transfer_info->last_report_time != 0 &&
1457 ABS ((gint64)(transfer_info->last_report_time - now))((((gint64)(transfer_info->last_report_time - now)) < 0
) ? -((gint64)(transfer_info->last_report_time - now)) : (
(gint64)(transfer_info->last_report_time - now)))
< 100 * NSEC_PER_MICROSEC1000) {
1458 return;
1459 }
1460 transfer_info->last_report_time = now;
1461
1462 files_left = source_info->num_files - transfer_info->num_files;
1463
1464 /* Races and whatnot could cause this to be negative... */
1465 if (files_left < 0) {
1466 files_left = 1;
1467 }
1468
1469 files_left_s = f (ngettext ("%'d file left to delete",
1470 "%'d files left to delete",
1471 files_left),
1472 files_left);
1473
1474 nautilus_progress_info_take_status (job->progress,
1475 f (_("Deleting files")gettext ("Deleting files")));
1476
1477 elapsed = g_timer_elapsed (job->time, NULL((void*)0));
1478 if (elapsed < SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE15) {
1479
1480 nautilus_progress_info_set_details (job->progress, files_left_s);
1481 } else {
1482 char *details, *time_left_s;
1483 transfer_rate = transfer_info->num_files / elapsed;
1484 remaining_time = files_left / transfer_rate;
1485
1486 /* To translators: %T will expand to a time like "2 minutes".
1487 * The singular/plural form will be used depending on the remaining time (i.e. the %T argument).
1488 */
1489 time_left_s = f (ngettext ("%T left",
1490 "%T left",
1491 seconds_count_format_time_units (remaining_time)),
1492 remaining_time);
1493
1494 details = g_strconcat (files_left_s, "\xE2\x80\x94", time_left_s, NULL((void*)0));
1495 nautilus_progress_info_take_details (job->progress, details);
1496
1497 g_free (time_left_s);
1498 }
1499
1500 g_free (files_left_s);
1501
1502 if (source_info->num_files != 0) {
1503 nautilus_progress_info_set_progress (job->progress, transfer_info->num_files, source_info->num_files);
1504 }
1505}
1506
1507static void delete_file (CommonJob *job, GFile *file,
1508 gboolean *skipped_file,
1509 SourceInfo *source_info,
1510 TransferInfo *transfer_info,
1511 gboolean toplevel);
1512
1513static void
1514delete_dir (CommonJob *job, GFile *dir,
1515 gboolean *skipped_file,
1516 SourceInfo *source_info,
1517 TransferInfo *transfer_info,
1518 gboolean toplevel)
1519{
1520 GFileInfo *info;
1521 GError *error;
1522 GFile *file;
1523 GFileEnumerator *enumerator;
1524 char *primary, *secondary, *details;
1525 int response;
1526 gboolean skip_error;
1527 gboolean local_skipped_file;
1528
1529 local_skipped_file = FALSE(0);
1530
1531 skip_error = should_skip_readdir_error (job, dir);
1532 retry:
1533 error = NULL((void*)0);
1534 enumerator = g_file_enumerate_children (dir,
1535 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name",
1536 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
1537 job->cancellable,
1538 &error);
1539 if (enumerator) {
1540 error = NULL((void*)0);
1541
1542 while (!job_aborted (job) &&
1543 (info = g_file_enumerator_next_file (enumerator, job->cancellable, skip_error?NULL((void*)0):&error)) != NULL((void*)0)) {
1544 file = g_file_get_child (dir,
1545 g_file_info_get_name (info));
1546 delete_file (job, file, &local_skipped_file, source_info, transfer_info, FALSE(0));
1547 g_object_unref (file);
1548 g_object_unref (info);
1549 }
1550 g_file_enumerator_close (enumerator, job->cancellable, NULL((void*)0));
1551 g_object_unref (enumerator);
1552
1553 if (error && IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
1554 g_error_free (error);
1555 } else if (error) {
1556 primary = f (_("Error while deleting.")gettext ("Error while deleting."));
1557 details = NULL((void*)0);
1558
1559 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
1560 secondary = f (_("Files in the folder “%B” cannot be deleted because you do "gettext ("Files in the folder “%B” cannot be deleted because you do "
"not have permissions to see them.")
1561 "not have permissions to see them.")gettext ("Files in the folder “%B” cannot be deleted because you do "
"not have permissions to see them.")
, dir);
1562 } else {
1563 secondary = f (_("There was an error getting information about the files in the folder “%B”.")gettext ("There was an error getting information about the files in the folder “%B”."
)
, dir);
1564 details = error->message;
1565 }
1566
1567 response = run_warning (job,
1568 primary,
1569 secondary,
1570 details,
1571 FALSE(0),
1572 CANCELgettext ("_Cancel"), _("_Skip files")gettext ("_Skip files"),
1573 NULL((void*)0));
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(!(0));
1582 } else {
1583 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 1583, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1584 }
1585 }
1586
1587 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
1588 g_error_free (error);
1589 } else {
1590 primary = f (_("Error while deleting.")gettext ("Error while deleting."));
1591 details = NULL((void*)0);
1592 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
1593 secondary = f (_("The folder “%B” cannot be deleted because you do not have "gettext ("The folder “%B” cannot be deleted because you do not have "
"permissions to read it.")
1594 "permissions to read it.")gettext ("The folder “%B” cannot be deleted because you do not have "
"permissions to read it.")
, dir);
1595 } else {
1596 secondary = f (_("There was an error reading the folder “%B”.")gettext ("There was an error reading the folder “%B”."), dir);
1597 details = error->message;
1598 }
1599
1600 response = run_warning (job,
1601 primary,
1602 secondary,
1603 details,
1604 FALSE(0),
1605 CANCELgettext ("_Cancel"), SKIPgettext ("_Skip"), RETRYgettext ("_Retry"),
1606 NULL((void*)0));
1607
1608 g_error_free (error);
1609
1610 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1611 abort_job (job);
1612 } else if (response == 1) {
1613 /* Skip: Do Nothing */
1614 local_skipped_file = TRUE(!(0));
1615 } else if (response == 2) {
1616 goto retry;
1617 } else {
1618 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 1618, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1619 }
1620 }
1621
1622 if (!job_aborted (job) &&
1623 /* Don't delete dir if there was a skipped file */
1624 !local_skipped_file) {
1625 if (!g_file_delete (dir, job->cancellable, &error)) {
1626 if (job->skip_all_error) {
1627 goto skip;
1628 }
1629 primary = f (_("Error while deleting.")gettext ("Error while deleting."));
1630 secondary = f (_("Could not remove the folder %B.")gettext ("Could not remove the folder %B."), dir);
1631 details = error->message;
1632
1633 response = run_cancel_or_skip_warning (job,
1634 primary,
1635 secondary,
1636 details,
1637 source_info->num_files,
1638 source_info->num_files - transfer_info->num_files);
1639
1640 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1641 abort_job (job);
1642 } else if (response == 1) { /* skip all */
1643 job->skip_all_error = TRUE(!(0));
1644 local_skipped_file = TRUE(!(0));
1645 } else if (response == 2) { /* skip */
1646 local_skipped_file = TRUE(!(0));
1647 } else {
1648 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 1648, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1649 }
1650
1651 skip:
1652 g_error_free (error);
1653 } else {
1654 nautilus_file_changes_queue_file_removed (dir);
1655 transfer_info->num_files ++;
1656 report_delete_progress (job, source_info, transfer_info);
1657 return;
1658 }
1659 }
1660
1661 if (local_skipped_file) {
1662 *skipped_file = TRUE(!(0));
1663 }
1664}
1665
1666static void
1667delete_file (CommonJob *job, GFile *file,
1668 gboolean *skipped_file,
1669 SourceInfo *source_info,
1670 TransferInfo *transfer_info,
1671 gboolean toplevel)
1672{
1673 GError *error;
1674 char *primary, *secondary, *details;
1675 int response;
1676
1677 if (should_skip_file (job, file)) {
1678 *skipped_file = TRUE(!(0));
1679 return;
1680 }
1681
1682 error = NULL((void*)0);
1683 if (g_file_delete (file, job->cancellable, &error)) {
1684 nautilus_file_changes_queue_file_removed (file);
1685 transfer_info->num_files ++;
1686 report_delete_progress (job, source_info, transfer_info);
1687 return;
1688 }
1689
1690 if (IS_IO_ERROR (error, NOT_EMPTY)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_EMPTY))
) {
1691 g_error_free (error);
1692 delete_dir (job, file,
1693 skipped_file,
1694 source_info, transfer_info,
1695 toplevel);
1696 return;
1697
1698 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
1699 g_error_free (error);
1700
1701 } else {
1702 if (job->skip_all_error) {
1703 goto skip;
1704 }
1705 primary = f (_("Error while deleting.")gettext ("Error while deleting."));
1706 secondary = f (_("There was an error deleting %B.")gettext ("There was an error deleting %B."), file);
1707 details = error->message;
1708
1709 response = run_cancel_or_skip_warning (job,
1710 primary,
1711 secondary,
1712 details,
1713 source_info->num_files,
1714 source_info->num_files - transfer_info->num_files);
1715
1716 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1717 abort_job (job);
1718 } else if (response == 1) { /* skip all */
1719 job->skip_all_error = TRUE(!(0));
1720 } else if (response == 2) { /* skip */
1721 /* do nothing */
1722 } else {
1723 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 1723, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1724 }
1725 skip:
1726 g_error_free (error);
1727 }
1728
1729 *skipped_file = TRUE(!(0));
1730}
1731
1732static void
1733delete_files (CommonJob *job, GList *files, int *files_skipped)
1734{
1735 GList *l;
1736 GFile *file;
1737 SourceInfo source_info;
1738 TransferInfo transfer_info;
1739 gboolean skipped_file;
1740
1741 if (job_aborted (job)) {
1742 return;
1743 }
1744
1745 scan_sources (files,
1746 &source_info,
1747 job,
1748 OP_KIND_DELETE);
1749 if (job_aborted (job)) {
1750 return;
1751 }
1752
1753 g_timer_start (job->time);
1754
1755 memset (&transfer_info, 0, sizeof (transfer_info));
1756 report_delete_progress (job, &source_info, &transfer_info);
1757
1758 for (l = files;
1759 l != NULL((void*)0) && !job_aborted (job);
1760 l = l->next) {
1761 file = l->data;
1762
1763 skipped_file = FALSE(0);
1764 delete_file (job, file,
1765 &skipped_file,
1766 &source_info, &transfer_info,
1767 TRUE(!(0)));
1768 if (skipped_file) {
1769 (*files_skipped)++;
1770 }
1771 }
1772}
1773
1774static void
1775report_trash_progress (CommonJob *job,
1776 int files_trashed,
1777 int total_files)
1778{
1779 int files_left;
1780 char *s;
1781
1782 files_left = total_files - files_trashed;
1783
1784 nautilus_progress_info_take_status (job->progress,
1785 f (_("Moving files to trash")gettext ("Moving files to trash")));
1786
1787 s = f (ngettext ("%'d file left to trash",
1788 "%'d files left to trash",
1789 files_left),
1790 files_left);
1791 nautilus_progress_info_take_details (job->progress, s);
1792
1793 if (total_files != 0) {
1794 nautilus_progress_info_set_progress (job->progress, files_trashed, total_files);
1795 }
1796}
1797
1798
1799static void
1800trash_files (CommonJob *job, GList *files, int *files_skipped)
1801{
1802 GList *l;
1803 GFile *file;
1804 GList *to_delete;
1805 GError *error;
1806 int total_files, files_trashed;
1807 char *primary, *secondary, *details;
1808 int response;
1809
1810 if (job_aborted (job)) {
1811 return;
1812 }
1813
1814 total_files = g_list_length (files);
1815 files_trashed = 0;
1816
1817 report_trash_progress (job, files_trashed, total_files);
1818
1819 to_delete = NULL((void*)0);
1820 for (l = files;
1821 l != NULL((void*)0) && !job_aborted (job);
1822 l = l->next) {
1823 file = l->data;
1824
1825 error = NULL((void*)0);
1826
1827 if (!g_file_trash (file, job->cancellable, &error)) {
1828 if (job->skip_all_error) {
1829 (*files_skipped)++;
1830 goto skip;
1831 }
1832
1833 if (job->delete_all) {
1834 to_delete = g_list_prepend (to_delete, file);
1835 goto skip;
1836 }
1837
1838 /* Translators: %B is a file name */
1839 primary = f (_("“%B” can't be put in the trash. Do you want to delete it immediately?")gettext ("“%B” can't be put in the trash. Do you want to delete it immediately?"
)
, file);
1840 details = NULL((void*)0);
1841 secondary = NULL((void*)0);
1842 if (!IS_IO_ERROR (error, NOT_SUPPORTED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_SUPPORTED))
) {
1843 details = error->message;
1844 } else if (!g_file_is_native (file)) {
1845 secondary = f (_("This remote location does not support sending items to the trash.")gettext ("This remote location does not support sending items to the trash."
)
);
1846 }
1847
1848 response = run_question (job,
1849 primary,
1850 secondary,
1851 details,
1852 (total_files - files_trashed) > 1,
1853 CANCELgettext ("_Cancel"), SKIP_ALLgettext ("S_kip All"), SKIPgettext ("_Skip"), DELETE_ALLgettext ("Delete _All"), DELETEgettext ("_Delete"),
1854 NULL((void*)0));
1855
1856 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1857 ((DeleteJob *) job)->user_cancel = TRUE(!(0));
1858 abort_job (job);
1859 } else if (response == 1) { /* skip all */
1860 (*files_skipped)++;
1861 job->skip_all_error = TRUE(!(0));
1862 } else if (response == 2) { /* skip */
1863 (*files_skipped)++;
1864 } else if (response == 3) { /* delete all */
1865 to_delete = g_list_prepend (to_delete, file);
1866 job->delete_all = TRUE(!(0));
1867 } else if (response == 4) { /* delete */
1868 to_delete = g_list_prepend (to_delete, file);
1869 }
1870
1871 skip:
1872 g_error_free (error);
1873 total_files--;
1874 } else {
1875 nautilus_file_changes_queue_file_removed (file);
1876
1877 if (job->undo_info != NULL((void*)0)) {
1878 nautilus_file_undo_info_trash_add_file (NAUTILUS_FILE_UNDO_INFO_TRASH (job->undo_info)((((NautilusFileUndoInfoTrash*) g_type_check_instance_cast ((
GTypeInstance*) ((job->undo_info)), ((nautilus_file_undo_info_trash_get_type
()))))))
, file);
1879 }
1880
1881 files_trashed++;
1882 report_trash_progress (job, files_trashed, total_files);
1883 }
1884 }
1885
1886 if (to_delete) {
1887 to_delete = g_list_reverse (to_delete);
1888 delete_files (job, to_delete, files_skipped);
1889 g_list_free (to_delete);
1890 }
1891}
1892
1893static gboolean
1894delete_job_done (gpointer user_data)
1895{
1896 DeleteJob *job;
1897 GHashTable *debuting_uris;
1898
1899 job = user_data;
1900
1901 g_list_free_full (job->files, g_object_unref);
1902
1903 if (job->done_callback) {
1904 debuting_uris = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
1905 job->done_callback (debuting_uris, job->user_cancel, job->done_callback_data);
1906 g_hash_table_unref (debuting_uris);
1907 }
1908
1909 finalize_common ((CommonJob *)job);
1910
1911 nautilus_file_changes_consume_changes (TRUE(!(0)));
1912
1913 return FALSE(0);
1914}
1915
1916static gboolean
1917delete_job (GIOSchedulerJob *io_job,
1918 GCancellable *cancellable,
1919 gpointer user_data)
1920{
1921 DeleteJob *job = user_data;
1922 GList *to_trash_files;
1923 GList *to_delete_files;
1924 GList *l;
1925 GFile *file;
1926 gboolean confirmed;
1927 CommonJob *common;
1928 gboolean must_confirm_delete_in_trash;
1929 gboolean must_confirm_delete;
1930 int files_skipped;
1931
1932 common = (CommonJob *)job;
1933 common->io_job = io_job;
1934
1935 nautilus_progress_info_start (job->common.progress);
1936
1937 to_trash_files = NULL((void*)0);
1938 to_delete_files = NULL((void*)0);
1939
1940 must_confirm_delete_in_trash = FALSE(0);
1941 must_confirm_delete = FALSE(0);
1942 files_skipped = 0;
1943
1944 for (l = job->files; l != NULL((void*)0); l = l->next) {
1945 file = l->data;
1946
1947 if (job->try_trash &&
1948 g_file_has_uri_scheme (file, "trash")) {
1949 must_confirm_delete_in_trash = TRUE(!(0));
1950 to_delete_files = g_list_prepend (to_delete_files, file);
1951 } else if (can_delete_without_confirm (file)) {
1952 to_delete_files = g_list_prepend (to_delete_files, file);
1953 } else {
1954 if (job->try_trash) {
1955 to_trash_files = g_list_prepend (to_trash_files, file);
1956 } else {
1957 must_confirm_delete = TRUE(!(0));
1958 to_delete_files = g_list_prepend (to_delete_files, file);
1959 }
1960 }
1961 }
1962
1963 if (to_delete_files != NULL((void*)0)) {
1964 to_delete_files = g_list_reverse (to_delete_files);
1965 confirmed = TRUE(!(0));
1966 if (must_confirm_delete_in_trash) {
1967 confirmed = confirm_delete_from_trash (common, to_delete_files);
1968 } else if (must_confirm_delete) {
1969 confirmed = confirm_delete_directly (common, to_delete_files);
1970 }
1971 if (confirmed) {
1972 delete_files (common, to_delete_files, &files_skipped);
1973 } else {
1974 job->user_cancel = TRUE(!(0));
1975 }
1976 }
1977
1978 if (to_trash_files != NULL((void*)0)) {
1979 to_trash_files = g_list_reverse (to_trash_files);
1980
1981 trash_files (common, to_trash_files, &files_skipped);
1982 }
1983
1984 g_list_free (to_trash_files);
1985 g_list_free (to_delete_files);
1986
1987 if (files_skipped == g_list_length (job->files)) {
1988 /* User has skipped all files, report user cancel */
1989 job->user_cancel = TRUE(!(0));
1990 }
1991
1992 g_io_scheduler_job_send_to_mainloop_async (io_job,
1993 delete_job_done,
1994 job,
1995 NULL((void*)0));
1996
1997 return FALSE(0);
1998}
1999
2000static void
2001trash_or_delete_internal (GList *files,
2002 GtkWindow *parent_window,
2003 gboolean try_trash,
2004 NautilusDeleteCallback done_callback,
2005 gpointer done_callback_data)
2006{
2007 DeleteJob *job;
2008
2009 /* TODO: special case desktop icon link files ... */
2010
2011 job = op_job_new (DeleteJob, parent_window)((DeleteJob *)(init_common (sizeof(DeleteJob), parent_window)
))
;
2012 job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL((void*)0));
2013 job->try_trash = try_trash;
2014 job->user_cancel = FALSE(0);
2015 job->done_callback = done_callback;
2016 job->done_callback_data = done_callback_data;
2017
2018 if (try_trash) {
2019 inhibit_power_manager ((CommonJob *)job, _("Trashing Files")gettext ("Trashing Files"));
2020 } else {
2021 inhibit_power_manager ((CommonJob *)job, _("Deleting Files")gettext ("Deleting Files"));
2022 }
2023
2024 if (try_trash && !nautilus_file_undo_manager_pop_flag ()) {
2025 job->common.undo_info = nautilus_file_undo_info_trash_new (g_list_length (files));
2026 }
2027
2028 g_io_scheduler_push_job (delete_job,
2029 job,
2030 NULL((void*)0),
2031 0,
2032 NULL((void*)0));
2033}
2034
2035void
2036nautilus_file_operations_trash_or_delete (GList *files,
2037 GtkWindow *parent_window,
2038 NautilusDeleteCallback done_callback,
2039 gpointer done_callback_data)
2040{
2041 trash_or_delete_internal (files, parent_window,
2042 TRUE(!(0)),
2043 done_callback, done_callback_data);
2044}
2045
2046void
2047nautilus_file_operations_delete (GList *files,
2048 GtkWindow *parent_window,
2049 NautilusDeleteCallback done_callback,
2050 gpointer done_callback_data)
2051{
2052 trash_or_delete_internal (files, parent_window,
2053 FALSE(0),
2054 done_callback, done_callback_data);
2055}
2056
2057
2058
2059typedef struct {
2060 gboolean eject;
2061 GMount *mount;
2062 GMountOperation *mount_operation;
2063 GtkWindow *parent_window;
2064 NautilusUnmountCallback callback;
2065 gpointer callback_data;
2066} UnmountData;
2067
2068static void
2069unmount_data_free (UnmountData *data)
2070{
2071 if (data->parent_window) {
2072 g_object_remove_weak_pointer (G_OBJECT (data->parent_window)((((GObject*) g_type_check_instance_cast ((GTypeInstance*) ((
data->parent_window)), (((GType) ((20) << (2))))))))
,
2073 (gpointer *) &data->parent_window);
2074 }
2075
2076 g_clear_object (&data->mount_operation)do { typedef char _GStaticAssertCompileTimeAssertion_30[(sizeof
*((&data->mount_operation)) == sizeof (gpointer)) ? 1
: -1] __attribute__((__unused__)); gpointer *_pp = (gpointer
*) ((&data->mount_operation)); gpointer _p; GDestroyNotify
_destroy = (GDestroyNotify) (g_object_unref); (void) (0 ? (gpointer
) *((&data->mount_operation)) : 0); do _p = (__extension__
({ typedef char _GStaticAssertCompileTimeAssertion_31[(sizeof
*(_pp) == sizeof (gpointer)) ? 1 : -1] __attribute__((__unused__
)); __sync_synchronize (); (gpointer) *(_pp); })); while (!(__extension__
({ typedef char _GStaticAssertCompileTimeAssertion_32[(sizeof
*(_pp) == sizeof (gpointer)) ? 1 : -1] __attribute__((__unused__
)); (void) (0 ? (gpointer) *(_pp) : 0); (gboolean) __sync_bool_compare_and_swap
((_pp), (_p), (((void*)0))); }))); if (_p) _destroy (_p); } while
(0)
;
2077 g_object_unref (data->mount);
2078 g_free (data);
2079}
2080
2081static void
2082unmount_mount_callback (GObject *source_object,
2083 GAsyncResult *res,
2084 gpointer user_data)
2085{
2086 UnmountData *data = user_data;
2087 GError *error;
2088 char *primary;
2089 gboolean unmounted;
2090
2091 error = NULL((void*)0);
2092 if (data->eject) {
2093 unmounted = g_mount_eject_with_operation_finish (G_MOUNT (source_object)((((GMount*) g_type_check_instance_cast ((GTypeInstance*) ((source_object
)), ((g_mount_get_type ()))))))
,
2094 res, &error);
2095 } else {
2096 unmounted = g_mount_unmount_with_operation_finish (G_MOUNT (source_object)((((GMount*) g_type_check_instance_cast ((GTypeInstance*) ((source_object
)), ((g_mount_get_type ()))))))
,
2097 res, &error);
2098 }
2099
2100 if (! unmounted) {
2101 if (error->code != G_IO_ERROR_FAILED_HANDLED) {
2102 if (data->eject) {
2103 primary = f (_("Unable to eject %V")gettext ("Unable to eject %V"), source_object);
2104 } else {
2105 primary = f (_("Unable to unmount %V")gettext ("Unable to unmount %V"), source_object);
2106 }
2107 eel_show_error_dialog (primary,
2108 error->message,
2109 data->parent_window);
2110 g_free (primary);
2111 }
2112 }
2113
2114 if (data->callback) {
2115 data->callback (data->callback_data);
2116 }
2117
2118 if (error != NULL((void*)0)) {
2119 g_error_free (error);
2120 }
2121
2122 unmount_data_free (data);
2123}
2124
2125static void
2126do_unmount (UnmountData *data)
2127{
2128 GMountOperation *mount_op;
2129
2130 if (data->mount_operation) {
2131 mount_op = g_object_ref (data->mount_operation);
2132 } else {
2133 mount_op = gtk_mount_operation_new (data->parent_window);
2134 }
2135 if (data->eject) {
2136 g_mount_eject_with_operation (data->mount,
2137 0,
2138 mount_op,
2139 NULL((void*)0),
2140 unmount_mount_callback,
2141 data);
2142 } else {
2143 g_mount_unmount_with_operation (data->mount,
2144 0,
2145 mount_op,
2146 NULL((void*)0),
2147 unmount_mount_callback,
2148 data);
2149 }
2150 g_object_unref (mount_op);
2151}
2152
2153static gboolean
2154dir_has_files (GFile *dir)
2155{
2156 GFileEnumerator *enumerator;
2157 gboolean res;
2158 GFileInfo *file_info;
2159
2160 res = FALSE(0);
2161
2162 enumerator = g_file_enumerate_children (dir,
2163 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name",
2164 0,
2165 NULL((void*)0), NULL((void*)0));
2166 if (enumerator) {
2167 file_info = g_file_enumerator_next_file (enumerator, NULL((void*)0), NULL((void*)0));
2168 if (file_info != NULL((void*)0)) {
2169 res = TRUE(!(0));
2170 g_object_unref (file_info);
2171 }
2172
2173 g_file_enumerator_close (enumerator, NULL((void*)0), NULL((void*)0));
2174 g_object_unref (enumerator);
2175 }
2176
2177
2178 return res;
2179}
2180
2181static GList *
2182get_trash_dirs_for_mount (GMount *mount)
2183{
2184 GFile *root;
2185 GFile *trash;
2186 char *relpath;
2187 GList *list;
2188
2189 root = g_mount_get_root (mount);
2190 if (root == NULL((void*)0)) {
2191 return NULL((void*)0);
2192 }
2193
2194 list = NULL((void*)0);
2195
2196 if (g_file_is_native (root)) {
2197 relpath = g_strdup_printf (".Trash/%d", getuid ());
2198 trash = g_file_resolve_relative_path (root, relpath);
2199 g_free (relpath);
2200
2201 list = g_list_prepend (list, g_file_get_child (trash, "files"));
2202 list = g_list_prepend (list, g_file_get_child (trash, "info"));
2203
2204 g_object_unref (trash);
2205
2206 relpath = g_strdup_printf (".Trash-%d", getuid ());
2207 trash = g_file_get_child (root, relpath);
2208 g_free (relpath);
2209
2210 list = g_list_prepend (list, g_file_get_child (trash, "files"));
2211 list = g_list_prepend (list, g_file_get_child (trash, "info"));
2212
2213 g_object_unref (trash);
2214 }
2215
2216 g_object_unref (root);
2217
2218 return list;
2219}
2220
2221static gboolean
2222has_trash_files (GMount *mount)
2223{
2224 GList *dirs, *l;
2225 GFile *dir;
2226 gboolean res;
2227
2228 dirs = get_trash_dirs_for_mount (mount);
2229
2230 res = FALSE(0);
2231
2232 for (l = dirs; l != NULL((void*)0); l = l->next) {
2233 dir = l->data;
2234
2235 if (dir_has_files (dir)) {
2236 res = TRUE(!(0));
2237 break;
2238 }
2239 }
2240
2241 g_list_free_full (dirs, g_object_unref);
2242
2243 return res;
2244}
2245
2246
2247static gint
2248prompt_empty_trash (GtkWindow *parent_window)
2249{
2250 gint result;
2251 GtkWidget *dialog;
2252 GdkScreen *screen;
2253
2254 screen = NULL((void*)0);
2255 if (parent_window != NULL((void*)0)) {
2256 screen = gtk_widget_get_screen (GTK_WIDGET (parent_window)((((GtkWidget*) g_type_check_instance_cast ((GTypeInstance*) (
(parent_window)), ((gtk_widget_get_type ()))))))
);
2257 }
2258
2259 /* Do we need to be modal ? */
2260 dialog = gtk_message_dialog_new (NULL((void*)0), GTK_DIALOG_MODAL,
2261 GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
2262 _("Do you want to empty the trash before you unmount?")gettext ("Do you want to empty the trash before you unmount?"
)
);
2263 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog)((((GtkMessageDialog*) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((gtk_message_dialog_get_type ()))))))
,
2264 _("In order to regain the "gettext ("In order to regain the " "free space on this volume "
"the trash must be emptied. " "All trashed items on the volume "
"will be permanently lost.")
2265 "free space on this volume "gettext ("In order to regain the " "free space on this volume "
"the trash must be emptied. " "All trashed items on the volume "
"will be permanently lost.")
2266 "the trash must be emptied. "gettext ("In order to regain the " "free space on this volume "
"the trash must be emptied. " "All trashed items on the volume "
"will be permanently lost.")
2267 "All trashed items on the volume "gettext ("In order to regain the " "free space on this volume "
"the trash must be emptied. " "All trashed items on the volume "
"will be permanently lost.")
2268 "will be permanently lost.")gettext ("In order to regain the " "free space on this volume "
"the trash must be emptied. " "All trashed items on the volume "
"will be permanently lost.")
);
2269 gtk_dialog_add_buttons (GTK_DIALOG (dialog)((((GtkDialog*) g_type_check_instance_cast ((GTypeInstance*) (
(dialog)), ((gtk_dialog_get_type ()))))))
,
2270 _("Do _not Empty Trash")gettext ("Do _not Empty Trash"), GTK_RESPONSE_REJECT,
2271 CANCELgettext ("_Cancel"), GTK_RESPONSE_CANCEL,
2272 _("Empty _Trash")gettext ("Empty _Trash"), GTK_RESPONSE_ACCEPT, NULL((void*)0));
2273 gtk_dialog_set_default_response (GTK_DIALOG (dialog)((((GtkDialog*) g_type_check_instance_cast ((GTypeInstance*) (
(dialog)), ((gtk_dialog_get_type ()))))))
, GTK_RESPONSE_ACCEPT);
2274 gtk_window_set_title (GTK_WINDOW (dialog)((((GtkWindow*) g_type_check_instance_cast ((GTypeInstance*) (
(dialog)), ((gtk_window_get_type ()))))))
, ""); /* as per HIG */
2275 gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog)((((GtkWindow*) g_type_check_instance_cast ((GTypeInstance*) (
(dialog)), ((gtk_window_get_type ()))))))
, TRUE(!(0)));
2276 if (screen) {
2277 gtk_window_set_screen (GTK_WINDOW (dialog)((((GtkWindow*) g_type_check_instance_cast ((GTypeInstance*) (
(dialog)), ((gtk_window_get_type ()))))))
, screen);
2278 }
2279 atk_object_set_role (gtk_widget_get_accessible (dialog), ATK_ROLE_ALERT);
2280 gtk_window_set_wmclass (GTK_WINDOW (dialog)((((GtkWindow*) g_type_check_instance_cast ((GTypeInstance*) (
(dialog)), ((gtk_window_get_type ()))))))
, "empty_trash",
2281 "Nautilus");
2282
2283 /* Make transient for the window group */
2284 gtk_widget_realize (dialog);
2285 if (screen != NULL((void*)0)) {
2286 gdk_window_set_transient_for (gtk_widget_get_window (GTK_WIDGET (dialog)((((GtkWidget*) g_type_check_instance_cast ((GTypeInstance*) (
(dialog)), ((gtk_widget_get_type ()))))))
),
2287 gdk_screen_get_root_window (screen));
2288 }
2289
2290 result = gtk_dialog_run (GTK_DIALOG (dialog)((((GtkDialog*) g_type_check_instance_cast ((GTypeInstance*) (
(dialog)), ((gtk_dialog_get_type ()))))))
);
2291 gtk_widget_destroy (dialog);
2292 return result;
2293}
2294
2295static void
2296empty_trash_for_unmount_done (gboolean success,
2297 gpointer user_data)
2298{
2299 UnmountData *data = user_data;
2300 do_unmount (data);
2301}
2302
2303void
2304nautilus_file_operations_unmount_mount_full (GtkWindow *parent_window,
2305 GMount *mount,
2306 GMountOperation *mount_operation,
2307 gboolean eject,
2308 gboolean check_trash,
2309 NautilusUnmountCallback callback,
2310 gpointer callback_data)
2311{
2312 UnmountData *data;
2313 int response;
2314
2315 data = g_new0 (UnmountData, 1)((UnmountData *) g_malloc0_n ((1), sizeof (UnmountData)));
2316 data->callback = callback;
2317 data->callback_data = callback_data;
2318 if (parent_window) {
2319 data->parent_window = parent_window;
2320 g_object_add_weak_pointer (G_OBJECT (data->parent_window)((((GObject*) g_type_check_instance_cast ((GTypeInstance*) ((
data->parent_window)), (((GType) ((20) << (2))))))))
,
2321 (gpointer *) &data->parent_window);
2322
2323 }
2324 if (mount_operation) {
2325 data->mount_operation = g_object_ref (mount_operation);
2326 }
2327 data->eject = eject;
2328 data->mount = g_object_ref (mount);
2329
2330 if (check_trash && has_trash_files (mount)) {
2331 response = prompt_empty_trash (parent_window);
2332
2333 if (response == GTK_RESPONSE_ACCEPT) {
2334 EmptyTrashJob *job;
2335
2336 job = op_job_new (EmptyTrashJob, parent_window)((EmptyTrashJob *)(init_common (sizeof(EmptyTrashJob), parent_window
)))
;
2337 job->should_confirm = FALSE(0);
2338 job->trash_dirs = get_trash_dirs_for_mount (mount);
2339 job->done_callback = empty_trash_for_unmount_done;
2340 job->done_callback_data = data;
2341 g_io_scheduler_push_job (empty_trash_job,
2342 job,
2343 NULL((void*)0),
2344 0,
2345 NULL((void*)0));
2346 return;
2347 } else if (response == GTK_RESPONSE_CANCEL) {
2348 if (callback) {
2349 callback (callback_data);
2350 }
2351
2352 unmount_data_free (data);
2353 return;
2354 }
2355 }
2356
2357 do_unmount (data);
2358}
2359
2360void
2361nautilus_file_operations_unmount_mount (GtkWindow *parent_window,
2362 GMount *mount,
2363 gboolean eject,
2364 gboolean check_trash)
2365{
2366 nautilus_file_operations_unmount_mount_full (parent_window, mount, NULL((void*)0), eject,
2367 check_trash, NULL((void*)0), NULL((void*)0));
2368}
2369
2370static void
2371mount_callback_data_notify (gpointer data,
2372 GObject *object)
2373{
2374 GMountOperation *mount_op;
2375
2376 mount_op = G_MOUNT_OPERATION (data)((((GMountOperation*) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((g_mount_operation_get_type ()))))))
;
2377 g_object_set_data (G_OBJECT (mount_op)((((GObject*) g_type_check_instance_cast ((GTypeInstance*) ((
mount_op)), (((GType) ((20) << (2))))))))
, "mount-callback", NULL((void*)0));
2378 g_object_set_data (G_OBJECT (mount_op)((((GObject*) g_type_check_instance_cast ((GTypeInstance*) ((
mount_op)), (((GType) ((20) << (2))))))))
, "mount-callback-data", NULL((void*)0));
2379}
2380
2381static void
2382volume_mount_cb (GObject *source_object,
2383 GAsyncResult *res,
2384 gpointer user_data)
2385{
2386 NautilusMountCallback mount_callback;
2387 GObject *mount_callback_data_object;
2388 GMountOperation *mount_op = user_data;
2389 GError *error;
2390 char *primary;
2391 char *name;
2392 gboolean success;
2393
2394 success = TRUE(!(0));
2395 error = NULL((void*)0);
2396 if (!g_volume_mount_finish (G_VOLUME (source_object)((((GVolume*) g_type_check_instance_cast ((GTypeInstance*) ((
source_object)), ((g_volume_get_type ()))))))
, res, &error)) {
2397 if (error->code != G_IO_ERROR_FAILED_HANDLED &&
2398 error->code != G_IO_ERROR_ALREADY_MOUNTED) {
2399 GtkWindow *parent;
2400
2401 parent = gtk_mount_operation_get_parent (GTK_MOUNT_OPERATION (mount_op)((((GtkMountOperation*) g_type_check_instance_cast ((GTypeInstance
*) ((mount_op)), ((gtk_mount_operation_get_type ()))))))
);
2402 name = g_volume_get_name (G_VOLUME (source_object)((((GVolume*) g_type_check_instance_cast ((GTypeInstance*) ((
source_object)), ((g_volume_get_type ()))))))
);
2403 primary = g_strdup_printf (_("Unable to access “%s”")gettext ("Unable to access “%s”"), name);
2404 g_free (name);
2405 success = FALSE(0);
2406 eel_show_error_dialog (primary,
2407 error->message,
2408 parent);
2409 g_free (primary);
2410 }
2411 g_error_free (error);
2412 }
2413
2414 mount_callback = (NautilusMountCallback)
2415 g_object_get_data (G_OBJECT (mount_op)((((GObject*) g_type_check_instance_cast ((GTypeInstance*) ((
mount_op)), (((GType) ((20) << (2))))))))
, "mount-callback");
2416 mount_callback_data_object =
2417 g_object_get_data (G_OBJECT (mount_op)((((GObject*) g_type_check_instance_cast ((GTypeInstance*) ((
mount_op)), (((GType) ((20) << (2))))))))
, "mount-callback-data");
2418
2419 if (mount_callback != NULL((void*)0)) {
2420 (* mount_callback) (G_VOLUME (source_object)((((GVolume*) g_type_check_instance_cast ((GTypeInstance*) ((
source_object)), ((g_volume_get_type ()))))))
,
2421 success,
2422 mount_callback_data_object);
2423
2424 if (mount_callback_data_object != NULL((void*)0)) {
2425 g_object_weak_unref (mount_callback_data_object,
2426 mount_callback_data_notify,
2427 mount_op);
2428 }
2429 }
2430
2431 g_object_unref (mount_op);
2432}
2433
2434
2435void
2436nautilus_file_operations_mount_volume (GtkWindow *parent_window,
2437 GVolume *volume)
2438{
2439 nautilus_file_operations_mount_volume_full (parent_window, volume,
2440 NULL((void*)0), NULL((void*)0));
2441}
2442
2443void
2444nautilus_file_operations_mount_volume_full (GtkWindow *parent_window,
2445 GVolume *volume,
2446 NautilusMountCallback mount_callback,
2447 GObject *mount_callback_data_object)
2448{
2449 GMountOperation *mount_op;
2450
2451 mount_op = gtk_mount_operation_new (parent_window);
2452 g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
2453 g_object_set_data (G_OBJECT (mount_op)((((GObject*) g_type_check_instance_cast ((GTypeInstance*) ((
mount_op)), (((GType) ((20) << (2))))))))
,
2454 "mount-callback",
2455 mount_callback);
2456
2457 if (mount_callback != NULL((void*)0) &&
2458 mount_callback_data_object != NULL((void*)0)) {
2459 g_object_weak_ref (mount_callback_data_object,
2460 mount_callback_data_notify,
2461 mount_op);
2462 }
2463 g_object_set_data (G_OBJECT (mount_op)((((GObject*) g_type_check_instance_cast ((GTypeInstance*) ((
mount_op)), (((GType) ((20) << (2))))))))
,
2464 "mount-callback-data",
2465 mount_callback_data_object);
2466
2467 g_volume_mount (volume, 0, mount_op, NULL((void*)0), volume_mount_cb, mount_op);
2468}
2469
2470static void
2471report_count_progress (CommonJob *job,
2472 SourceInfo *source_info)
2473{
2474 char *s;
2475
2476 switch (source_info->op) {
2477 default:
2478 case OP_KIND_COPY:
2479 s = f (ngettext("Preparing to copy %'d file (%S)",
2480 "Preparing to copy %'d files (%S)",
2481 source_info->num_files),
2482 source_info->num_files, source_info->num_bytes);
2483 break;
2484 case OP_KIND_MOVE:
2485 s = f (ngettext("Preparing to move %'d file (%S)",
2486 "Preparing to move %'d files (%S)",
2487 source_info->num_files),
2488 source_info->num_files, source_info->num_bytes);
2489 break;
2490 case OP_KIND_DELETE:
2491 s = f (ngettext("Preparing to delete %'d file (%S)",
2492 "Preparing to delete %'d files (%S)",
2493 source_info->num_files),
2494 source_info->num_files, source_info->num_bytes);
2495 break;
2496 case OP_KIND_TRASH:
2497 s = f (ngettext("Preparing to trash %'d file",
2498 "Preparing to trash %'d files",
2499 source_info->num_files),
2500 source_info->num_files);
2501 break;
2502 }
2503
2504 nautilus_progress_info_take_details (job->progress, s);
2505 nautilus_progress_info_pulse_progress (job->progress);
2506}
2507
2508static void
2509count_file (GFileInfo *info,
2510 CommonJob *job,
2511 SourceInfo *source_info)
2512{
2513 source_info->num_files += 1;
2514 source_info->num_bytes += g_file_info_get_size (info);
2515
2516 if (source_info->num_files_since_progress++ > 100) {
2517 report_count_progress (job, source_info);
2518 source_info->num_files_since_progress = 0;
2519 }
2520}
2521
2522static char *
2523get_scan_primary (OpKind kind)
2524{
2525 switch (kind) {
2526 default:
2527 case OP_KIND_COPY:
2528 return f (_("Error while copying.")gettext ("Error while copying."));
2529 case OP_KIND_MOVE:
2530 return f (_("Error while moving.")gettext ("Error while moving."));
2531 case OP_KIND_DELETE:
2532 return f (_("Error while deleting.")gettext ("Error while deleting."));
2533 case OP_KIND_TRASH:
2534 return f (_("Error while moving files to trash.")gettext ("Error while moving files to trash."));
2535 }
2536}
2537
2538static void
2539scan_dir (GFile *dir,
2540 SourceInfo *source_info,
2541 CommonJob *job,
2542 GQueue *dirs)
2543{
2544 GFileInfo *info;
2545 GError *error;
2546 GFile *subdir;
2547 GFileEnumerator *enumerator;
2548 char *primary, *secondary, *details;
2549 int response;
2550 SourceInfo saved_info;
2551
2552 saved_info = *source_info;
2553
2554 retry:
2555 error = NULL((void*)0);
2556 enumerator = g_file_enumerate_children (dir,
2557 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name"","
2558 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
2559 G_FILE_ATTRIBUTE_STANDARD_SIZE"standard::size",
2560 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
2561 job->cancellable,
2562 &error);
2563 if (enumerator) {
2564 error = NULL((void*)0);
2565 while ((info = g_file_enumerator_next_file (enumerator, job->cancellable, &error)) != NULL((void*)0)) {
2566 count_file (info, job, source_info);
2567
2568 if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
2569 subdir = g_file_get_child (dir,
2570 g_file_info_get_name (info));
2571
2572 /* Push to head, since we want depth-first */
2573 g_queue_push_head (dirs, subdir);
2574 }
2575
2576 g_object_unref (info);
2577 }
2578 g_file_enumerator_close (enumerator, job->cancellable, NULL((void*)0));
2579 g_object_unref (enumerator);
2580
2581 if (error && IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
2582 g_error_free (error);
2583 } else if (error) {
2584 primary = get_scan_primary (source_info->op);
2585 details = NULL((void*)0);
2586
2587 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
2588 secondary = f (_("Files in the folder “%B” cannot be handled because you do "gettext ("Files in the folder “%B” cannot be handled because you do "
"not have permissions to see them.")
2589 "not have permissions to see them.")gettext ("Files in the folder “%B” cannot be handled because you do "
"not have permissions to see them.")
, dir);
2590 } else {
2591 secondary = f (_("There was an error getting information about the files in the folder “%B”.")gettext ("There was an error getting information about the files in the folder “%B”."
)
, dir);
2592 details = error->message;
2593 }
2594
2595 response = run_warning (job,
2596 primary,
2597 secondary,
2598 details,
2599 FALSE(0),
2600 CANCELgettext ("_Cancel"), RETRYgettext ("_Retry"), SKIPgettext ("_Skip"),
2601 NULL((void*)0));
2602
2603 g_error_free (error);
2604
2605 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2606 abort_job (job);
2607 } else if (response == 1) {
2608 *source_info = saved_info;
2609 goto retry;
2610 } else if (response == 2) {
2611 skip_readdir_error (job, dir);
2612 } else {
2613 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 2613, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2614 }
2615 }
2616
2617 } else if (job->skip_all_error) {
2618 g_error_free (error);
2619 skip_file (job, dir);
2620 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
2621 g_error_free (error);
2622 } else {
2623 primary = get_scan_primary (source_info->op);
2624 details = NULL((void*)0);
2625
2626 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
2627 secondary = f (_("The folder “%B” cannot be handled because you do not have "gettext ("The folder “%B” cannot be handled because you do not have "
"permissions to read it.")
2628 "permissions to read it.")gettext ("The folder “%B” cannot be handled because you do not have "
"permissions to read it.")
, dir);
2629 } else {
2630 secondary = f (_("There was an error reading the folder “%B”.")gettext ("There was an error reading the folder “%B”."), dir);
2631 details = error->message;
2632 }
2633 /* set show_all to TRUE here, as we don't know how many
2634 * files we'll end up processing yet.
2635 */
2636 response = run_warning (job,
2637 primary,
2638 secondary,
2639 details,
2640 TRUE(!(0)),
2641 CANCELgettext ("_Cancel"), SKIP_ALLgettext ("S_kip All"), SKIPgettext ("_Skip"), RETRYgettext ("_Retry"),
2642 NULL((void*)0));
2643
2644 g_error_free (error);
2645
2646 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2647 abort_job (job);
2648 } else if (response == 1 || response == 2) {
2649 if (response == 1) {
2650 job->skip_all_error = TRUE(!(0));
2651 }
2652 skip_file (job, dir);
2653 } else if (response == 3) {
2654 goto retry;
2655 } else {
2656 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 2656, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2657 }
2658 }
2659}
2660
2661static void
2662scan_file (GFile *file,
2663 SourceInfo *source_info,
2664 CommonJob *job)
2665{
2666 GFileInfo *info;
2667 GError *error;
2668 GQueue *dirs;
2669 GFile *dir;
2670 char *primary;
2671 char *secondary;
2672 char *details;
2673 int response;
2674
2675 dirs = g_queue_new ();
2676
2677 retry:
2678 error = NULL((void*)0);
2679 info = g_file_query_info (file,
2680 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
2681 G_FILE_ATTRIBUTE_STANDARD_SIZE"standard::size",
2682 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
2683 job->cancellable,
2684 &error);
2685
2686 if (info) {
2687 count_file (info, job, source_info);
2688
2689 if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
2690 g_queue_push_head (dirs, g_object_ref (file));
2691 }
2692
2693 g_object_unref (info);
2694 } else if (job->skip_all_error) {
2695 g_error_free (error);
2696 skip_file (job, file);
2697 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
2698 g_error_free (error);
2699 } else {
2700 primary = get_scan_primary (source_info->op);
2701 details = NULL((void*)0);
2702
2703 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
2704 secondary = f (_("The file “%B” cannot be handled because you do not have "gettext ("The file “%B” cannot be handled because you do not have "
"permissions to read it.")
2705 "permissions to read it.")gettext ("The file “%B” cannot be handled because you do not have "
"permissions to read it.")
, file);
2706 } else {
2707 secondary = f (_("There was an error getting information about “%B”.")gettext ("There was an error getting information about “%B”."
)
, file);
2708 details = error->message;
2709 }
2710 /* set show_all to TRUE here, as we don't know how many
2711 * files we'll end up processing yet.
2712 */
2713 response = run_warning (job,
2714 primary,
2715 secondary,
2716 details,
2717 TRUE(!(0)),
2718 CANCELgettext ("_Cancel"), SKIP_ALLgettext ("S_kip All"), SKIPgettext ("_Skip"), RETRYgettext ("_Retry"),
2719 NULL((void*)0));
2720
2721 g_error_free (error);
2722
2723 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2724 abort_job (job);
2725 } else if (response == 1 || response == 2) {
2726 if (response == 1) {
2727 job->skip_all_error = TRUE(!(0));
2728 }
2729 skip_file (job, file);
2730 } else if (response == 3) {
2731 goto retry;
2732 } else {
2733 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 2733, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2734 }
2735 }
2736
2737 while (!job_aborted (job) &&
2738 (dir = g_queue_pop_head (dirs)) != NULL((void*)0)) {
2739 scan_dir (dir, source_info, job, dirs);
2740 g_object_unref (dir);
2741 }
2742
2743 /* Free all from queue if we exited early */
2744 g_queue_foreach (dirs, (GFunc)g_object_unref, NULL((void*)0));
2745 g_queue_free (dirs);
2746}
2747
2748static void
2749scan_sources (GList *files,
2750 SourceInfo *source_info,
2751 CommonJob *job,
2752 OpKind kind)
2753{
2754 GList *l;
2755 GFile *file;
2756
2757 memset (source_info, 0, sizeof (SourceInfo));
2758 source_info->op = kind;
2759
2760 report_count_progress (job, source_info);
2761
2762 for (l = files; l != NULL((void*)0) && !job_aborted (job); l = l->next) {
2763 file = l->data;
2764
2765 scan_file (file,
2766 source_info,
2767 job);
2768 }
2769
2770 /* Make sure we report the final count */
2771 report_count_progress (job, source_info);
2772}
2773
2774static void
2775verify_destination (CommonJob *job,
2776 GFile *dest,
2777 char **dest_fs_id,
2778 goffset required_size)
2779{
2780 GFileInfo *info, *fsinfo;
2781 GError *error;
2782 guint64 free_size;
2783 guint64 size_difference;
2784 char *primary, *secondary, *details;
2785 int response;
2786 GFileType file_type;
2787 gboolean dest_is_symlink = FALSE(0);
2788
2789 if (dest_fs_id) {
2790 *dest_fs_id = NULL((void*)0);
2791 }
2792
2793 retry:
2794
2795 error = NULL((void*)0);
2796 info = g_file_query_info (dest,
2797 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
2798 G_FILE_ATTRIBUTE_ID_FILESYSTEM"id::filesystem",
2799 dest_is_symlink ? G_FILE_QUERY_INFO_NONE : G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
2800 job->cancellable,
2801 &error);
2802
2803 if (info == NULL((void*)0)) {
2804 if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
2805 g_error_free (error);
2806 return;
2807 }
2808
2809 primary = f (_("Error while copying to “%B”.")gettext ("Error while copying to “%B”."), dest);
2810 details = NULL((void*)0);
2811
2812 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
2813 secondary = f (_("You do not have permissions to access the destination folder.")gettext ("You do not have permissions to access the destination folder."
)
);
2814 } else {
2815 secondary = f (_("There was an error getting information about the destination.")gettext ("There was an error getting information about the destination."
)
);
2816 details = error->message;
2817 }
2818
2819 response = run_error (job,
2820 primary,
2821 secondary,
2822 details,
2823 FALSE(0),
2824 CANCELgettext ("_Cancel"), RETRYgettext ("_Retry"),
2825 NULL((void*)0));
2826
2827 g_error_free (error);
2828
2829 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2830 abort_job (job);
2831 } else if (response == 1) {
2832 goto retry;
2833 } else {
2834 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 2834, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2835 }
2836
2837 return;
2838 }
2839
2840 file_type = g_file_info_get_file_type (info);
2841 if (!dest_is_symlink && file_type == G_FILE_TYPE_SYMBOLIC_LINK) {
2842 /* Record that destination is a symlink and do real stat() once again */
2843 dest_is_symlink = TRUE(!(0));
2844 g_object_unref (info);
2845 goto retry;
2846 }
2847
2848 if (dest_fs_id) {
2849 *dest_fs_id =
2850 g_strdup (g_file_info_get_attribute_string (info,
2851 G_FILE_ATTRIBUTE_ID_FILESYSTEM"id::filesystem"));
2852 }
2853
2854 g_object_unref (info);
2855
2856 if (file_type != G_FILE_TYPE_DIRECTORY) {
2857 primary = f (_("Error while copying to “%B”.")gettext ("Error while copying to “%B”."), dest);
2858 secondary = f (_("The destination is not a folder.")gettext ("The destination is not a folder."));
2859
2860 run_error (job,
2861 primary,
2862 secondary,
2863 NULL((void*)0),
2864 FALSE(0),
2865 CANCELgettext ("_Cancel"),
2866 NULL((void*)0));
2867
2868 abort_job (job);
2869 return;
2870 }
2871
2872 if (dest_is_symlink) {
2873 /* We can't reliably statfs() destination if it's a symlink, thus not doing any further checks. */
2874 return;
2875 }
2876
2877 fsinfo = g_file_query_filesystem_info (dest,
2878 G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free"","
2879 G_FILE_ATTRIBUTE_FILESYSTEM_READONLY"filesystem::readonly",
2880 job->cancellable,
2881 NULL((void*)0));
2882 if (fsinfo == NULL((void*)0)) {
2883 /* All sorts of things can go wrong getting the fs info (like not supported)
2884 * only check these things if the fs returns them
2885 */
2886 return;
2887 }
2888
2889 if (required_size > 0 &&
2890 g_file_info_has_attribute (fsinfo, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free")) {
2891 free_size = g_file_info_get_attribute_uint64 (fsinfo,
2892 G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free");
2893
2894 if (free_size < required_size) {
2895 size_difference = required_size - free_size;
2896 primary = f (_("Error while copying to “%B”.")gettext ("Error while copying to “%B”."), dest);
2897 secondary = f (_("There is not enough space on the destination. Try to remove files to make space.")gettext ("There is not enough space on the destination. Try to remove files to make space."
)
);
2898
2899 details = f (_("%S more space is required to copy to the destination.")gettext ("%S more space is required to copy to the destination."
)
, size_difference);
2900
2901 response = run_warning (job,
2902 primary,
2903 secondary,
2904 details,
2905 FALSE(0),
2906 CANCELgettext ("_Cancel"),
2907 COPY_FORCEgettext ("Copy _Anyway"),
2908 RETRYgettext ("_Retry"),
2909 NULL((void*)0));
2910
2911 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2912 abort_job (job);
2913 } else if (response == 2) {
2914 goto retry;
2915 } else if (response == 1) {
2916 /* We are forced to copy - just fall through ... */
2917 } else {
2918 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 2918, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2919 }
2920 }
2921 }
2922
2923 if (!job_aborted (job) &&
2924 g_file_info_get_attribute_boolean (fsinfo,
2925 G_FILE_ATTRIBUTE_FILESYSTEM_READONLY"filesystem::readonly")) {
2926 primary = f (_("Error while copying to “%B”.")gettext ("Error while copying to “%B”."), dest);
2927 secondary = f (_("The destination is read-only.")gettext ("The destination is read-only."));
2928
2929 run_error (job,
2930 primary,
2931 secondary,
2932 NULL((void*)0),
2933 FALSE(0),
2934 CANCELgettext ("_Cancel"),
2935 NULL((void*)0));
2936
2937 g_error_free (error);
2938
2939 abort_job (job);
2940 }
2941
2942 g_object_unref (fsinfo);
2943}
2944
2945static void
2946report_copy_progress (CopyMoveJob *copy_job,
2947 SourceInfo *source_info,
2948 TransferInfo *transfer_info)
2949{
2950 int files_left;
2951 goffset total_size;
2952 double elapsed, transfer_rate;
2953 int remaining_time;
2954 guint64 now;
2955 CommonJob *job;
2956 gboolean is_move;
2957
2958 job = (CommonJob *)copy_job;
2959
2960 is_move = copy_job->is_move;
2961
2962 now = g_get_monotonic_time ();
2963
2964 if (transfer_info->last_report_time != 0 &&
2965 ABS ((gint64)(transfer_info->last_report_time - now))((((gint64)(transfer_info->last_report_time - now)) < 0
) ? -((gint64)(transfer_info->last_report_time - now)) : (
(gint64)(transfer_info->last_report_time - now)))
< 100 * NSEC_PER_MICROSEC1000) {
2966 return;
2967 }
2968 transfer_info->last_report_time = now;
2969
2970 files_left = source_info->num_files - transfer_info->num_files;
2971
2972 /* Races and whatnot could cause this to be negative... */
2973 if (files_left < 0) {
2974 files_left = 1;
2975 }
2976
2977 if (files_left != transfer_info->last_reported_files_left ||
2978 transfer_info->last_reported_files_left == 0) {
2979 /* Avoid changing this unless files_left changed since last time */
2980 transfer_info->last_reported_files_left = files_left;
2981
2982 if (source_info->num_files == 1) {
2983 if (copy_job->destination != NULL((void*)0)) {
2984 nautilus_progress_info_take_status (job->progress,
2985 f (is_move ?
2986 _("Moving “%B” to “%B”")gettext ("Moving “%B” to “%B”"):
2987 _("Copying “%B” to “%B”")gettext ("Copying “%B” to “%B”"),
2988 copy_job->fake_display_source != NULL((void*)0) ?
2989 copy_job->fake_display_source :
2990 (GFile *)copy_job->files->data,
2991 copy_job->destination));
2992 } else {
2993 nautilus_progress_info_take_status (job->progress,
2994 f (_("Duplicating “%B”")gettext ("Duplicating “%B”"),
2995 (GFile *)copy_job->files->data));
2996 }
2997 } else if (copy_job->files != NULL((void*)0) &&
2998 copy_job->files->next == NULL((void*)0)) {
2999 if (copy_job->destination != NULL((void*)0)) {
3000 nautilus_progress_info_take_status (job->progress,
3001 f (is_move ?
3002 _("Moving file %'d of %'d (in “%B”) to “%B”")gettext ("Moving file %'d of %'d (in “%B”) to “%B”")
3003 :
3004 _("Copying file %'d of %'d (in “%B”) to “%B”")gettext ("Copying file %'d of %'d (in “%B”) to “%B”"),
3005 transfer_info->num_files + 1,
3006 source_info->num_files,
3007 (GFile *)copy_job->files->data,
3008 copy_job->destination));
3009 } else {
3010 nautilus_progress_info_take_status (job->progress,
3011 f (_("Duplicating file %'d of %'d (in “%B”)")gettext ("Duplicating file %'d of %'d (in “%B”)"),
3012 transfer_info->num_files + 1,
3013 source_info->num_files,
3014 (GFile *)copy_job->files->data));
3015 }
3016 } else {
3017 if (copy_job->destination != NULL((void*)0)) {
3018 nautilus_progress_info_take_status (job->progress,
3019 f (is_move ?
3020 _("Moving file %'d of %'d to “%B”")gettext ("Moving file %'d of %'d to “%B”")
3021 :
3022 _ ("Copying file %'d of %'d to “%B”")gettext ("Copying file %'d of %'d to “%B”"),
3023 transfer_info->num_files + 1,
3024 source_info->num_files,
3025 copy_job->destination));
3026 } else {
3027 nautilus_progress_info_take_status (job->progress,
3028 f (_("Duplicating file %'d of %'d")gettext ("Duplicating file %'d of %'d"),
3029 transfer_info->num_files + 1,
3030 source_info->num_files));
3031 }
3032 }
3033 }
3034
3035 total_size = MAX (source_info->num_bytes, transfer_info->num_bytes)(((source_info->num_bytes) > (transfer_info->num_bytes
)) ? (source_info->num_bytes) : (transfer_info->num_bytes
))
;
3036
3037 elapsed = g_timer_elapsed (job->time, NULL((void*)0));
3038 transfer_rate = 0;
3039 if (elapsed > 0) {
3040 transfer_rate = transfer_info->num_bytes / elapsed;
3041 }
3042
3043 if (elapsed < SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE15 &&
3044 transfer_rate > 0) {
3045 char *s;
3046 /* To translators: %S will expand to a size like "2 bytes" or "3 MB", so something like "4 kb of 4 MB" */
3047 s = f (_("%S of %S")gettext ("%S of %S"), transfer_info->num_bytes, total_size);
3048 nautilus_progress_info_take_details (job->progress, s);
3049 } else {
3050 char *s;
3051 remaining_time = (total_size - transfer_info->num_bytes) / transfer_rate;
3052
3053 /* To translators: %S will expand to a size like "2 bytes" or "3 MB", %T to a time duration like
3054 * "2 minutes". So the whole thing will be something like "2 kb of 4 MB -- 2 hours left (4kb/sec)"
3055 *
3056 * The singular/plural form will be used depending on the remaining time (i.e. the %T argument).
3057 */
3058 s = f (ngettext ("%S of %S \xE2\x80\x94 %T left (%S/sec)",
3059 "%S of %S \xE2\x80\x94 %T left (%S/sec)",
3060 seconds_count_format_time_units (remaining_time)),
3061 transfer_info->num_bytes, total_size,
3062 remaining_time,
3063 (goffset)transfer_rate);
3064 nautilus_progress_info_take_details (job->progress, s);
3065 }
3066
3067 nautilus_progress_info_set_progress (job->progress, transfer_info->num_bytes, total_size);
3068}
3069
3070static int
3071get_max_name_length (GFile *file_dir)
3072{
3073 int max_length;
3074 char *dir;
3075 long max_path;
3076 long max_name;
3077
3078 max_length = -1;
3079
3080 if (!g_file_has_uri_scheme (file_dir, "file"))
3081 return max_length;
3082
3083 dir = g_file_get_path (file_dir);
3084 if (!dir)
3085 return max_length;
3086
3087 max_path = pathconf (dir, _PC_PATH_MAX_PC_PATH_MAX);
3088 max_name = pathconf (dir, _PC_NAME_MAX_PC_NAME_MAX);
3089
3090 if (max_name == -1 && max_path == -1) {
3091 max_length = -1;
3092 } else if (max_name == -1 && max_path != -1) {
3093 max_length = max_path - (strlen (dir) + 1);
3094 } else if (max_name != -1 && max_path == -1) {
3095 max_length = max_name;
3096 } else {
3097 int leftover;
3098
3099 leftover = max_path - (strlen (dir) + 1);
3100
3101 max_length = MIN (leftover, max_name)(((leftover) < (max_name)) ? (leftover) : (max_name));
3102 }
3103
3104 g_free (dir);
3105
3106 return max_length;
3107}
3108
3109#define FAT_FORBIDDEN_CHARACTERS"/:;*?\"<>" "/:;*?\"<>"
3110
3111static gboolean
3112fat_str_replace (char *str,
3113 char replacement)
3114{
3115 gboolean success;
3116 int i;
3117
3118 success = FALSE(0);
3119 for (i = 0; str[i] != '\0'; i++) {
3120 if (strchr (FAT_FORBIDDEN_CHARACTERS"/:;*?\"<>", str[i]) ||
3121 str[i] < 32) {
3122 success = TRUE(!(0));
3123 str[i] = replacement;
3124 }
3125 }
3126
3127 return success;
3128}
3129
3130static gboolean
3131make_file_name_valid_for_dest_fs (char *filename,
3132 const char *dest_fs_type)
3133{
3134 if (dest_fs_type != NULL((void*)0) && filename != NULL((void*)0)) {
3135 if (!strcmp (dest_fs_type, "fat") ||
3136 !strcmp (dest_fs_type, "vfat") ||
3137 !strcmp (dest_fs_type, "msdos") ||
3138 !strcmp (dest_fs_type, "msdosfs")) {
3139 gboolean ret;
3140 int i, old_len;
3141
3142 ret = fat_str_replace (filename, '_');
3143
3144 old_len = strlen (filename);
3145 for (i = 0; i < old_len; i++) {
3146 if (filename[i] != ' ') {
3147 g_strchomp (filename);
3148 ret |= (old_len != strlen (filename));
3149 break;
3150 }
3151 }
3152
3153 return ret;
3154 }
3155 }
3156
3157 return FALSE(0);
3158}
3159
3160static GFile *
3161get_unique_target_file (GFile *src,
3162 GFile *dest_dir,
3163 gboolean same_fs,
3164 const char *dest_fs_type,
3165 int count)
3166{
3167 const char *editname, *end;
3168 char *basename, *new_name;
3169 GFileInfo *info;
3170 GFile *dest;
3171 int max_length;
3172
3173 max_length = get_max_name_length (dest_dir);
3174
3175 dest = NULL((void*)0);
3176 info = g_file_query_info (src,
3177 G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME"standard::edit-name",
3178 0, NULL((void*)0), NULL((void*)0));
3179 if (info != NULL((void*)0)) {
3180 editname = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME"standard::edit-name");
3181
3182 if (editname != NULL((void*)0)) {
3183 new_name = get_duplicate_name (editname, count, max_length);
3184 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3185 dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL((void*)0));
3186 g_free (new_name);
3187 }
3188
3189 g_object_unref (info);
3190 }
3191
3192 if (dest == NULL((void*)0)) {
3193 basename = g_file_get_basename (src);
3194
3195 if (g_utf8_validate (basename, -1, NULL((void*)0))) {
3196 new_name = get_duplicate_name (basename, count, max_length);
3197 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3198 dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL((void*)0));
3199 g_free (new_name);
3200 }
3201
3202 if (dest == NULL((void*)0)) {
3203 end = strrchr (basename, '.');
3204 if (end != NULL((void*)0)) {
3205 count += atoi (end + 1);
3206 }
3207 new_name = g_strdup_printf ("%s.%d", basename, count);
3208 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3209 dest = g_file_get_child (dest_dir, new_name);
3210 g_free (new_name);
3211 }
3212
3213 g_free (basename);
3214 }
3215
3216 return dest;
3217}
3218
3219static GFile *
3220get_target_file_for_link (GFile *src,
3221 GFile *dest_dir,
3222 const char *dest_fs_type,
3223 int count)
3224{
3225 const char *editname;
3226 char *basename, *new_name;
3227 GFileInfo *info;
3228 GFile *dest;
3229 int max_length;
3230
3231 max_length = get_max_name_length (dest_dir);
3232
3233 dest = NULL((void*)0);
3234 info = g_file_query_info (src,
3235 G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME"standard::edit-name",
3236 0, NULL((void*)0), NULL((void*)0));
3237 if (info != NULL((void*)0)) {
3238 editname = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME"standard::edit-name");
3239
3240 if (editname != NULL((void*)0)) {
3241 new_name = get_link_name (editname, count, max_length);
3242 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3243 dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL((void*)0));
3244 g_free (new_name);
3245 }
3246
3247 g_object_unref (info);
3248 }
3249
3250 if (dest == NULL((void*)0)) {
3251 basename = g_file_get_basename (src);
3252 make_file_name_valid_for_dest_fs (basename, dest_fs_type);
3253
3254 if (g_utf8_validate (basename, -1, NULL((void*)0))) {
3255 new_name = get_link_name (basename, count, max_length);
3256 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3257 dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL((void*)0));
3258 g_free (new_name);
3259 }
3260
3261 if (dest == NULL((void*)0)) {
3262 if (count == 1) {
3263 new_name = g_strdup_printf ("%s.lnk", basename);
3264 } else {
3265 new_name = g_strdup_printf ("%s.lnk%d", basename, count);
3266 }
3267 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3268 dest = g_file_get_child (dest_dir, new_name);
3269 g_free (new_name);
3270 }
3271
3272 g_free (basename);
3273 }
3274
3275 return dest;
3276}
3277
3278static GFile *
3279get_target_file_with_custom_name (GFile *src,
3280 GFile *dest_dir,
3281 const char *dest_fs_type,
3282 gboolean same_fs,
3283 const gchar *custom_name)
3284{
3285 char *basename;
3286 GFile *dest;
3287 GFileInfo *info;
3288 char *copyname;
3289
3290 dest = NULL((void*)0);
3291
3292 if (custom_name != NULL((void*)0)) {
3293 copyname = g_strdup (custom_name);
3294 make_file_name_valid_for_dest_fs (copyname, dest_fs_type);
3295 dest = g_file_get_child_for_display_name (dest_dir, copyname, NULL((void*)0));
3296
3297 g_free (copyname);
3298 }
3299
3300 if (dest == NULL((void*)0) && !same_fs) {
3301 info = g_file_query_info (src,
3302 G_FILE_ATTRIBUTE_STANDARD_COPY_NAME"standard::copy-name" ","
3303 G_FILE_ATTRIBUTE_TRASH_ORIG_PATH"trash::orig-path",
3304 0, NULL((void*)0), NULL((void*)0));
3305
3306 if (info) {
3307 copyname = NULL((void*)0);
3308
3309 /* if file is being restored from trash make sure it uses its original name */
3310 if (g_file_has_uri_scheme (src, "trash")) {
3311 copyname = g_strdup (g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_TRASH_ORIG_PATH"trash::orig-path"));
3312 }
3313
3314 if (copyname == NULL((void*)0)) {
3315 copyname = g_strdup (g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_COPY_NAME"standard::copy-name"));
3316 }
3317
3318 if (copyname) {
3319 make_file_name_valid_for_dest_fs (copyname, dest_fs_type);
3320 dest = g_file_get_child_for_display_name (dest_dir, copyname, NULL((void*)0));
3321 g_free (copyname);
3322 }
3323
3324 g_object_unref (info);
3325 }
3326 }
3327
3328 if (dest == NULL((void*)0)) {
3329 basename = g_file_get_basename (src);
3330 make_file_name_valid_for_dest_fs (basename, dest_fs_type);
3331 dest = g_file_get_child (dest_dir, basename);
3332 g_free (basename);
3333 }
3334
3335 return dest;
3336}
3337
3338static GFile *
3339get_target_file (GFile *src,
3340 GFile *dest_dir,
3341 const char *dest_fs_type,
3342 gboolean same_fs)
3343{
3344 return get_target_file_with_custom_name (src, dest_dir, dest_fs_type, same_fs, NULL((void*)0));
3345}
3346
3347static gboolean
3348has_fs_id (GFile *file, const char *fs_id)
3349{
3350 const char *id;
3351 GFileInfo *info;
3352 gboolean res;
3353
3354 res = FALSE(0);
3355 info = g_file_query_info (file,
3356 G_FILE_ATTRIBUTE_ID_FILESYSTEM"id::filesystem",
3357 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3358 NULL((void*)0), NULL((void*)0));
3359
3360 if (info) {
3361 id = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILESYSTEM"id::filesystem");
3362
3363 if (id && strcmp (id, fs_id) == 0) {
3364 res = TRUE(!(0));
3365 }
3366
3367 g_object_unref (info);
3368 }
3369
3370 return res;
3371}
3372
3373static gboolean
3374is_dir (GFile *file)
3375{
3376 GFileInfo *info;
3377 gboolean res;
3378
3379 res = FALSE(0);
3380 info = g_file_query_info (file,
3381 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type",
3382 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3383 NULL((void*)0), NULL((void*)0));
3384 if (info) {
3385 res = g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY;
3386 g_object_unref (info);
3387 }
3388
3389 return res;
3390}
3391
3392static void copy_move_file (CopyMoveJob *job,
3393 GFile *src,
3394 GFile *dest_dir,
3395 gboolean same_fs,
3396 gboolean unique_names,
3397 char **dest_fs_type,
3398 SourceInfo *source_info,
3399 TransferInfo *transfer_info,
3400 GHashTable *debuting_files,
3401 GdkPoint *point,
3402 gboolean overwrite,
3403 gboolean *skipped_file,
3404 gboolean readonly_source_fs);
3405
3406typedef enum {
3407 CREATE_DEST_DIR_RETRY,
3408 CREATE_DEST_DIR_FAILED,
3409 CREATE_DEST_DIR_SUCCESS
3410} CreateDestDirResult;
3411
3412static CreateDestDirResult
3413create_dest_dir (CommonJob *job,
3414 GFile *src,
3415 GFile **dest,
3416 gboolean same_fs,
3417 char **dest_fs_type)
3418{
3419 GError *error;
3420 GFile *new_dest, *dest_dir;
3421 char *primary, *secondary, *details;
3422 int response;
3423 gboolean handled_invalid_filename;
3424
3425 handled_invalid_filename = *dest_fs_type != NULL((void*)0);
3426
3427 retry:
3428 /* First create the directory, then copy stuff to it before
3429 copying the attributes, because we need to be sure we can write to it */
3430
3431 error = NULL((void*)0);
3432 if (!g_file_make_directory (*dest, job->cancellable, &error)) {
3433 if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
3434 g_error_free (error);
3435 return CREATE_DEST_DIR_FAILED;
3436 } else if (IS_IO_ERROR (error, INVALID_FILENAME)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_INVALID_FILENAME))
&&
3437 !handled_invalid_filename) {
3438 handled_invalid_filename = TRUE(!(0));
3439
3440 g_assert (*dest_fs_type == NULL)do { if (*dest_fs_type == ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "nautilus-file-operations.c", 3440, ((const char
*) (__func__)), "*dest_fs_type == NULL"); } while (0)
;
3441
3442 dest_dir = g_file_get_parent (*dest);
3443
3444 if (dest_dir != NULL((void*)0)) {
3445 *dest_fs_type = query_fs_type (dest_dir, job->cancellable);
3446
3447 new_dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs);
3448 g_object_unref (dest_dir);
3449
3450 if (!g_file_equal (*dest, new_dest)) {
3451 g_object_unref (*dest);
3452 *dest = new_dest;
3453 g_error_free (error);
3454 return CREATE_DEST_DIR_RETRY;
3455 } else {
3456 g_object_unref (new_dest);
3457 }
3458 }
3459 }
3460
3461 primary = f (_("Error while copying.")gettext ("Error while copying."));
3462 details = NULL((void*)0);
3463
3464 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
3465 secondary = f (_("The folder “%B” cannot be copied because you do not have "gettext ("The folder “%B” cannot be copied because you do not have "
"permissions to create it in the destination.")
3466 "permissions to create it in the destination.")gettext ("The folder “%B” cannot be copied because you do not have "
"permissions to create it in the destination.")
, src);
3467 } else {
3468 secondary = f (_("There was an error creating the folder “%B”.")gettext ("There was an error creating the folder “%B”."), src);
3469 details = error->message;
3470 }
3471
3472 response = run_warning (job,
3473 primary,
3474 secondary,
3475 details,
3476 FALSE(0),
3477 CANCELgettext ("_Cancel"), SKIPgettext ("_Skip"), RETRYgettext ("_Retry"),
3478 NULL((void*)0));
3479
3480 g_error_free (error);
3481
3482 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3483 abort_job (job);
3484 } else if (response == 1) {
3485 /* Skip: Do Nothing */
3486 } else if (response == 2) {
3487 goto retry;
3488 } else {
3489 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 3489, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3490 }
3491 return CREATE_DEST_DIR_FAILED;
3492 }
3493 nautilus_file_changes_queue_file_added (*dest);
3494
3495 if (job->undo_info != NULL((void*)0)) {
3496 nautilus_file_undo_info_ext_add_origin_target_pair (NAUTILUS_FILE_UNDO_INFO_EXT (job->undo_info)((((NautilusFileUndoInfoExt*) g_type_check_instance_cast ((GTypeInstance
*) ((job->undo_info)), ((nautilus_file_undo_info_ext_get_type
()))))))
,
3497 src, *dest);
3498 }
3499
3500 return CREATE_DEST_DIR_SUCCESS;
3501}
3502
3503/* a return value of FALSE means retry, i.e.
3504 * the destination has changed and the source
3505 * is expected to re-try the preceeding
3506 * g_file_move() or g_file_copy() call with
3507 * the new destination.
3508 */
3509static gboolean
3510copy_move_directory (CopyMoveJob *copy_job,
3511 GFile *src,
3512 GFile **dest,
3513 gboolean same_fs,
3514 gboolean create_dest,
3515 char **parent_dest_fs_type,
3516 SourceInfo *source_info,
3517 TransferInfo *transfer_info,
3518 GHashTable *debuting_files,
3519 gboolean *skipped_file,
3520 gboolean readonly_source_fs)
3521{
3522 GFileInfo *info;
3523 GError *error;
3524 GFile *src_file;
3525 GFileEnumerator *enumerator;
3526 char *primary, *secondary, *details;
3527 char *dest_fs_type;
3528 int response;
3529 gboolean skip_error;
3530 gboolean local_skipped_file;
3531 CommonJob *job;
3532 GFileCopyFlags flags;
3533
3534 job = (CommonJob *)copy_job;
3535
3536 if (create_dest) {
3537 switch (create_dest_dir (job, src, dest, same_fs, parent_dest_fs_type)) {
3538 case CREATE_DEST_DIR_RETRY:
3539 /* next time copy_move_directory() is called,
3540 * create_dest will be FALSE if a directory already
3541 * exists under the new name (i.e. WOULD_RECURSE)
3542 */
3543 return FALSE(0);
3544
3545 case CREATE_DEST_DIR_FAILED:
3546 *skipped_file = TRUE(!(0));
3547 return TRUE(!(0));
3548
3549 case CREATE_DEST_DIR_SUCCESS:
3550 default:
3551 break;
3552 }
3553
3554 if (debuting_files) {
3555 g_hash_table_replace (debuting_files, g_object_ref (*dest), GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
3556 }
3557
3558 }
3559
3560 local_skipped_file = FALSE(0);
3561 dest_fs_type = NULL((void*)0);
3562
3563 skip_error = should_skip_readdir_error (job, src);
3564 retry:
3565 error = NULL((void*)0);
3566 enumerator = g_file_enumerate_children (src,
3567 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name",
3568 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3569 job->cancellable,
3570 &error);
3571 if (enumerator) {
3572 error = NULL((void*)0);
3573
3574 while (!job_aborted (job) &&
3575 (info = g_file_enumerator_next_file (enumerator, job->cancellable, skip_error?NULL((void*)0):&error)) != NULL((void*)0)) {
3576 src_file = g_file_get_child (src,
3577 g_file_info_get_name (info));
3578 copy_move_file (copy_job, src_file, *dest, same_fs, FALSE(0), &dest_fs_type,
3579 source_info, transfer_info, NULL((void*)0), NULL((void*)0), FALSE(0), &local_skipped_file,
3580 readonly_source_fs);
3581 g_object_unref (src_file);
3582 g_object_unref (info);
3583 }
3584 g_file_enumerator_close (enumerator, job->cancellable, NULL((void*)0));
3585 g_object_unref (enumerator);
3586
3587 if (error && IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
3588 g_error_free (error);
3589 } else if (error) {
3590 if (copy_job->is_move) {
3591 primary = f (_("Error while moving.")gettext ("Error while moving."));
3592 } else {
3593 primary = f (_("Error while copying.")gettext ("Error while copying."));
3594 }
3595 details = NULL((void*)0);
3596
3597 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
3598 secondary = f (_("Files in the folder “%B” cannot be copied because you do "gettext ("Files in the folder “%B” cannot be copied because you do "
"not have permissions to see them.")
3599 "not have permissions to see them.")gettext ("Files in the folder “%B” cannot be copied because you do "
"not have permissions to see them.")
, src);
3600 } else {
3601 secondary = f (_("There was an error getting information about the files in the folder “%B”.")gettext ("There was an error getting information about the files in the folder “%B”."
)
, src);
3602 details = error->message;
3603 }
3604
3605 response = run_warning (job,
3606 primary,
3607 secondary,
3608 details,
3609 FALSE(0),
3610 CANCELgettext ("_Cancel"), _("_Skip files")gettext ("_Skip files"),
3611 NULL((void*)0));
3612
3613 g_error_free (error);
3614
3615 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3616 abort_job (job);
3617 } else if (response == 1) {
3618 /* Skip: Do Nothing */
3619 local_skipped_file = TRUE(!(0));
3620 } else {
3621 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 3621, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3622 }
3623 }
3624
3625 /* Count the copied directory as a file */
3626 transfer_info->num_files ++;
3627 report_copy_progress (copy_job, source_info, transfer_info);
3628
3629 if (debuting_files) {
3630 g_hash_table_replace (debuting_files, g_object_ref (*dest), GINT_TO_POINTER (create_dest)((gpointer) (glong) (create_dest)));
3631 }
3632 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
3633 g_error_free (error);
3634 } else {
3635 if (copy_job->is_move) {
3636 primary = f (_("Error while moving.")gettext ("Error while moving."));
3637 } else {
3638 primary = f (_("Error while copying.")gettext ("Error while copying."));
3639 }
3640 details = NULL((void*)0);
3641
3642 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
3643 secondary = f (_("The folder “%B” cannot be copied because you do not have "gettext ("The folder “%B” cannot be copied because you do not have "
"permissions to read it.")
3644 "permissions to read it.")gettext ("The folder “%B” cannot be copied because you do not have "
"permissions to read it.")
, src);
3645 } else {
3646 secondary = f (_("There was an error reading the folder “%B”.")gettext ("There was an error reading the folder “%B”."), src);
3647 details = error->message;
3648 }
3649
3650 response = run_warning (job,
3651 primary,
3652 secondary,
3653 details,
3654 FALSE(0),
3655 CANCELgettext ("_Cancel"), SKIPgettext ("_Skip"), RETRYgettext ("_Retry"),
3656 NULL((void*)0));
3657
3658 g_error_free (error);
3659
3660 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3661 abort_job (job);
3662 } else if (response == 1) {
3663 /* Skip: Do Nothing */
3664 local_skipped_file = TRUE(!(0));
3665 } else if (response == 2) {
3666 goto retry;
3667 } else {
3668 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 3668, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3669 }
3670 }
3671
3672 if (create_dest) {
3673 flags = (readonly_source_fs) ? G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_TARGET_DEFAULT_PERMS
3674 : G_FILE_COPY_NOFOLLOW_SYMLINKS;
3675 /* Ignore errors here. Failure to copy metadata is not a hard error */
3676 g_file_copy_attributes (src, *dest,
3677 flags,
3678 job->cancellable, NULL((void*)0));
3679 }
3680
3681 if (!job_aborted (job) && copy_job->is_move &&
3682 /* Don't delete source if there was a skipped file */
3683 !local_skipped_file) {
3684 if (!g_file_delete (src, job->cancellable, &error)) {
3685 if (job->skip_all_error) {
3686 goto skip;
3687 }
3688 primary = f (_("Error while moving “%B”.")gettext ("Error while moving “%B”."), src);
3689 secondary = f (_("Could not remove the source folder.")gettext ("Could not remove the source folder."));
3690 details = error->message;
3691
3692 response = run_cancel_or_skip_warning (job,
3693 primary,
3694 secondary,
3695 details,
3696 source_info->num_files,
3697 source_info->num_files - transfer_info->num_files);
3698
3699 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3700 abort_job (job);
3701 } else if (response == 1) { /* skip all */
3702 job->skip_all_error = TRUE(!(0));
3703 local_skipped_file = TRUE(!(0));
3704 } else if (response == 2) { /* skip */
3705 local_skipped_file = TRUE(!(0));
3706 } else {
3707 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 3707, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3708 }
3709
3710 skip:
3711 g_error_free (error);
3712 }
3713 }
3714
3715 if (local_skipped_file) {
3716 *skipped_file = TRUE(!(0));
3717 }
3718
3719 g_free (dest_fs_type);
3720 return TRUE(!(0));
3721}
3722
3723static gboolean
3724remove_target_recursively (CommonJob *job,
3725 GFile *src,
3726 GFile *toplevel_dest,
3727 GFile *file)
3728{
3729 GFileEnumerator *enumerator;
3730 GError *error;
3731 GFile *child;
3732 gboolean stop;
3733 char *primary, *secondary, *details;
3734 int response;
3735 GFileInfo *info;
3736
3737 stop = FALSE(0);
3738
3739 error = NULL((void*)0);
3740 enumerator = g_file_enumerate_children (file,
3741 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name",
3742 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3743 job->cancellable,
3744 &error);
3745 if (enumerator) {
3746 error = NULL((void*)0);
3747
3748 while (!job_aborted (job) &&
3749 (info = g_file_enumerator_next_file (enumerator, job->cancellable, &error)) != NULL((void*)0)) {
3750 child = g_file_get_child (file,
3751 g_file_info_get_name (info));
3752 if (!remove_target_recursively (job, src, toplevel_dest, child)) {
3753 stop = TRUE(!(0));
3754 break;
3755 }
3756 g_object_unref (child);
3757 g_object_unref (info);
3758 }
3759 g_file_enumerator_close (enumerator, job->cancellable, NULL((void*)0));
3760 g_object_unref (enumerator);
3761
3762 } else if (IS_IO_ERROR (error, NOT_DIRECTORY)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_DIRECTORY))
) {
3763 /* Not a dir, continue */
3764 g_error_free (error);
3765
3766 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
3767 g_error_free (error);
3768 } else {
3769 if (job->skip_all_error) {
3770 goto skip1;
3771 }
3772
3773 primary = f (_("Error while copying “%B”.")gettext ("Error while copying “%B”."), src);
3774 secondary = f (_("Could not remove files from the already existing folder %F.")gettext ("Could not remove files from the already existing folder %F."
)
, file);
3775 details = error->message;
3776
3777 /* set show_all to TRUE here, as we don't know how many
3778 * files we'll end up processing yet.
3779 */
3780 response = run_warning (job,
3781 primary,
3782 secondary,
3783 details,
3784 TRUE(!(0)),
3785 CANCELgettext ("_Cancel"), SKIP_ALLgettext ("S_kip All"), SKIPgettext ("_Skip"),
3786 NULL((void*)0));
3787
3788 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3789 abort_job (job);
3790 } else if (response == 1) { /* skip all */
3791 job->skip_all_error = TRUE(!(0));
3792 } else if (response == 2) { /* skip */
3793 /* do nothing */
3794 } else {
3795 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 3795, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3796 }
3797 skip1:
3798 g_error_free (error);
3799
3800 stop = TRUE(!(0));
3801 }
3802
3803 if (stop) {
3804 return FALSE(0);
3805 }
3806
3807 error = NULL((void*)0);
3808
3809 if (!g_file_delete (file, job->cancellable, &error)) {
3810 if (job->skip_all_error ||
3811 IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
3812 goto skip2;
3813 }
3814 primary = f (_("Error while copying “%B”.")gettext ("Error while copying “%B”."), src);
3815 secondary = f (_("Could not remove the already existing file %F.")gettext ("Could not remove the already existing file %F."), file);
3816 details = error->message;
3817
3818 /* set show_all to TRUE here, as we don't know how many
3819 * files we'll end up processing yet.
3820 */
3821 response = run_warning (job,
3822 primary,
3823 secondary,
3824 details,
3825 TRUE(!(0)),
3826 CANCELgettext ("_Cancel"), SKIP_ALLgettext ("S_kip All"), SKIPgettext ("_Skip"),
3827 NULL((void*)0));
3828
3829 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3830 abort_job (job);
3831 } else if (response == 1) { /* skip all */
3832 job->skip_all_error = TRUE(!(0));
3833 } else if (response == 2) { /* skip */
3834 /* do nothing */
3835 } else {
3836 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 3836, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3837 }
3838
3839 skip2:
3840 g_error_free (error);
3841
3842 return FALSE(0);
3843 }
3844 nautilus_file_changes_queue_file_removed (file);
3845
3846 return TRUE(!(0));
3847
3848}
3849
3850typedef struct {
3851 CopyMoveJob *job;
3852 goffset last_size;
3853 SourceInfo *source_info;
3854 TransferInfo *transfer_info;
3855} ProgressData;
3856
3857static void
3858copy_file_progress_callback (goffset current_num_bytes,
3859 goffset total_num_bytes,
3860 gpointer user_data)
3861{
3862 ProgressData *pdata;
3863 goffset new_size;
3864
3865 pdata = user_data;
3866
3867 new_size = current_num_bytes - pdata->last_size;
3868
3869 if (new_size > 0) {
3870 pdata->transfer_info->num_bytes += new_size;
3871 pdata->last_size = current_num_bytes;
3872 report_copy_progress (pdata->job,
3873 pdata->source_info,
3874 pdata->transfer_info);
3875 }
3876}
3877
3878static gboolean
3879test_dir_is_parent (GFile *child, GFile *root)
3880{
3881 GFile *f, *tmp;
3882
3883 f = g_file_dup (child);
3884 while (f) {
3885 if (g_file_equal (f, root)) {
3886 g_object_unref (f);
3887 return TRUE(!(0));
3888 }
3889 tmp = f;
3890 f = g_file_get_parent (f);
3891 g_object_unref (tmp);
3892 }
3893 if (f) {
3894 g_object_unref (f);
3895 }
3896 return FALSE(0);
3897}
3898
3899static char *
3900query_fs_type (GFile *file,
3901 GCancellable *cancellable)
3902{
3903 GFileInfo *fsinfo;
3904 char *ret;
3905
3906 ret = NULL((void*)0);
3907
3908 fsinfo = g_file_query_filesystem_info (file,
3909 G_FILE_ATTRIBUTE_FILESYSTEM_TYPE"filesystem::type",
3910 cancellable,
3911 NULL((void*)0));
3912 if (fsinfo != NULL((void*)0)) {
3913 ret = g_strdup (g_file_info_get_attribute_string (fsinfo, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE"filesystem::type"));
3914 g_object_unref (fsinfo);
3915 }
3916
3917 if (ret == NULL((void*)0)) {
3918 /* ensure that we don't attempt to query
3919 * the FS type for each file in a given
3920 * directory, if it can't be queried. */
3921 ret = g_strdup ("");
3922 }
3923
3924 return ret;
3925}
3926
3927static gboolean
3928is_trusted_desktop_file (GFile *file,
3929 GCancellable *cancellable)
3930{
3931 char *basename;
3932 gboolean res;
3933 GFileInfo *info;
3934
3935 /* Don't trust non-local files */
3936 if (!g_file_is_native (file)) {
3937 return FALSE(0);
3938 }
3939
3940 basename = g_file_get_basename (file);
3941 if (!g_str_has_suffix (basename, ".desktop")) {
3942 g_free (basename);
3943 return FALSE(0);
3944 }
3945 g_free (basename);
3946
3947 info = g_file_query_info (file,
3948 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type" ","
3949 G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute",
3950 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3951 cancellable,
3952 NULL((void*)0));
3953
3954 if (info == NULL((void*)0)) {
3955 return FALSE(0);
3956 }
3957
3958 res = FALSE(0);
3959
3960 /* Weird file => not trusted,
3961 Already executable => no need to mark trusted */
3962 if (g_file_info_get_file_type (info) == G_FILE_TYPE_REGULAR &&
3963 !g_file_info_get_attribute_boolean (info,
3964 G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute") &&
3965 nautilus_is_in_system_dir (file)) {
3966 res = TRUE(!(0));
3967 }
3968 g_object_unref (info);
3969
3970 return res;
3971}
3972
3973typedef struct {
3974 int id;
3975 char *new_name;
3976 gboolean apply_to_all;
3977} ConflictResponseData;
3978
3979typedef struct {
3980 GFile *src;
3981 GFile *dest;
3982 GFile *dest_dir;
3983 GtkWindow *parent;
3984 ConflictResponseData *resp_data;
3985} ConflictDialogData;
3986
3987static gboolean
3988do_run_conflict_dialog (gpointer _data)
3989{
3990 ConflictDialogData *data = _data;
3991 GtkWidget *dialog;
3992 int response;
3993
3994 dialog = nautilus_file_conflict_dialog_new (data->parent,
3995 data->src,
3996 data->dest,
3997 data->dest_dir);
3998 response = gtk_dialog_run (GTK_DIALOG (dialog)((((GtkDialog*) g_type_check_instance_cast ((GTypeInstance*) (
(dialog)), ((gtk_dialog_get_type ()))))))
);
3999
4000 if (response == CONFLICT_RESPONSE_RENAME) {
4001 data->resp_data->new_name =
4002 nautilus_file_conflict_dialog_get_new_name (NAUTILUS_FILE_CONFLICT_DIALOG (dialog)((((NautilusFileConflictDialog*) g_type_check_instance_cast (
(GTypeInstance*) ((dialog)), ((nautilus_file_conflict_dialog_get_type
()))))))
);
4003 } else if (response != GTK_RESPONSE_CANCEL ||
4004 response != GTK_RESPONSE_NONE) {
4005 data->resp_data->apply_to_all =
4006 nautilus_file_conflict_dialog_get_apply_to_all
4007 (NAUTILUS_FILE_CONFLICT_DIALOG (dialog)((((NautilusFileConflictDialog*) g_type_check_instance_cast (
(GTypeInstance*) ((dialog)), ((nautilus_file_conflict_dialog_get_type
()))))))
);
4008 }
4009
4010 data->resp_data->id = response;
4011
4012 gtk_widget_destroy (dialog);
4013
4014 return FALSE(0);
4015}
4016
4017static ConflictResponseData *
4018run_conflict_dialog (CommonJob *job,
4019 GFile *src,
4020 GFile *dest,
4021 GFile *dest_dir)
4022{
4023 ConflictDialogData *data;
4024 ConflictResponseData *resp_data;
4025
4026 g_timer_stop (job->time);
4027
4028 data = g_slice_new0 (ConflictDialogData)((ConflictDialogData*) g_slice_alloc0 (sizeof (ConflictDialogData
)))
;
4029 data->parent = job->parent_window;
4030 data->src = src;
4031 data->dest = dest;
4032 data->dest_dir = dest_dir;
4033
4034 resp_data = g_slice_new0 (ConflictResponseData)((ConflictResponseData*) g_slice_alloc0 (sizeof (ConflictResponseData
)))
;
4035 resp_data->new_name = NULL((void*)0);
4036 data->resp_data = resp_data;
4037
4038 nautilus_progress_info_pause (job->progress);
4039 g_io_scheduler_job_send_to_mainloop (job->io_job,
4040 do_run_conflict_dialog,
4041 data,
4042 NULL((void*)0));
4043 nautilus_progress_info_resume (job->progress);
4044
4045 g_slice_free (ConflictDialogData, data)do { if (1) g_slice_free1 (sizeof (ConflictDialogData), (data
)); else (void) ((ConflictDialogData*) 0 == (data)); } while (
0)
;
4046
4047 g_timer_continue (job->time);
4048
4049 return resp_data;
4050}
4051
4052static void
4053conflict_response_data_free (ConflictResponseData *data)
4054{
4055 g_free (data->new_name);
4056 g_slice_free (ConflictResponseData, data)do { if (1) g_slice_free1 (sizeof (ConflictResponseData), (data
)); else (void) ((ConflictResponseData*) 0 == (data)); } while
(0)
;
4057}
4058
4059static GFile *
4060get_target_file_for_display_name (GFile *dir,
4061 const gchar *name)
4062{
4063 GFile *dest;
4064
4065 dest = NULL((void*)0);
4066 dest = g_file_get_child_for_display_name (dir, name, NULL((void*)0));
4067
4068 if (dest == NULL((void*)0)) {
4069 dest = g_file_get_child (dir, name);
4070 }
4071
4072 return dest;
4073}
4074
4075/* Debuting files is non-NULL only for toplevel items */
4076static void
4077copy_move_file (CopyMoveJob *copy_job,
4078 GFile *src,
4079 GFile *dest_dir,
4080 gboolean same_fs,
4081 gboolean unique_names,
4082 char **dest_fs_type,
4083 SourceInfo *source_info,
4084 TransferInfo *transfer_info,
4085 GHashTable *debuting_files,
4086 GdkPoint *position,
4087 gboolean overwrite,
4088 gboolean *skipped_file,
4089 gboolean readonly_source_fs)
4090{
4091 GFile *dest, *new_dest;
4092 GError *error;
4093 GFileCopyFlags flags;
4094 char *primary, *secondary, *details;
4095 int response;
4096 ProgressData pdata;
4097 gboolean would_recurse, is_merge;
4098 CommonJob *job;
4099 gboolean res;
4100 int unique_name_nr;
4101 gboolean handled_invalid_filename;
4102
4103 job = (CommonJob *)copy_job;
4104
4105 if (should_skip_file (job, src)) {
4106 *skipped_file = TRUE(!(0));
4107 return;
4108 }
4109
4110 unique_name_nr = 1;
4111
4112 /* another file in the same directory might have handled the invalid
4113 * filename condition for us
4114 */
4115 handled_invalid_filename = *dest_fs_type != NULL((void*)0);
4116
4117 if (unique_names) {
4118 dest = get_unique_target_file (src, dest_dir, same_fs, *dest_fs_type, unique_name_nr++);
4119 } else if (copy_job->target_name != NULL((void*)0)) {
4120 dest = get_target_file_with_custom_name (src, dest_dir, *dest_fs_type, same_fs,
4121 copy_job->target_name);
4122 } else {
4123 dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs);
4124 }
4125
4126 /* Don't allow recursive move/copy into itself.
4127 * (We would get a file system error if we proceeded but it is nicer to
4128 * detect and report it at this level) */
4129 if (test_dir_is_parent (dest_dir, src)) {
4130 if (job->skip_all_error) {
4131 goto out;
4132 }
4133
4134 /* the run_warning() frees all strings passed in automatically */
4135 primary = copy_job->is_move ? g_strdup (_("You cannot move a folder into itself.")gettext ("You cannot move a folder into itself."))
4136 : g_strdup (_("You cannot copy a folder into itself.")gettext ("You cannot copy a folder into itself."));
4137 secondary = g_strdup (_("The destination folder is inside the source folder.")gettext ("The destination folder is inside the source folder."
)
);
4138
4139 response = run_cancel_or_skip_warning (job,
4140 primary,
4141 secondary,
4142 NULL((void*)0),
4143 source_info->num_files,
4144 source_info->num_files - transfer_info->num_files);
4145
4146 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4147 abort_job (job);
4148 } else if (response == 1) { /* skip all */
4149 job->skip_all_error = TRUE(!(0));
4150 } else if (response == 2) { /* skip */
4151 /* do nothing */
4152 } else {
4153 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 4153, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4154 }
4155
4156 goto out;
4157 }
4158
4159 /* Don't allow copying over the source or one of the parents of the source.
4160 */
4161 if (test_dir_is_parent (src, dest)) {
4162 if (job->skip_all_error) {
4163 goto out;
4164 }
4165
4166 /* the run_warning() frees all strings passed in automatically */
4167 primary = copy_job->is_move ? g_strdup (_("You cannot move a file over itself.")gettext ("You cannot move a file over itself."))
4168 : g_strdup (_("You cannot copy a file over itself.")gettext ("You cannot copy a file over itself."));
4169 secondary = g_strdup (_("The source file would be overwritten by the destination.")gettext ("The source file would be overwritten by the destination."
)
);
4170
4171 response = run_cancel_or_skip_warning (job,
4172 primary,
4173 secondary,
4174 NULL((void*)0),
4175 source_info->num_files,
4176 source_info->num_files - transfer_info->num_files);
4177
4178 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4179 abort_job (job);
4180 } else if (response == 1) { /* skip all */
4181 job->skip_all_error = TRUE(!(0));
4182 } else if (response == 2) { /* skip */
4183 /* do nothing */
4184 } else {
4185 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 4185, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4186 }
4187
4188 goto out;
4189 }
4190
4191
4192 retry:
4193
4194 error = NULL((void*)0);
4195 flags = G_FILE_COPY_NOFOLLOW_SYMLINKS;
4196 if (overwrite) {
4197 flags |= G_FILE_COPY_OVERWRITE;
4198 }
4199 if (readonly_source_fs) {
4200 flags |= G_FILE_COPY_TARGET_DEFAULT_PERMS;
4201 }
4202
4203 pdata.job = copy_job;
4204 pdata.last_size = 0;
4205 pdata.source_info = source_info;
4206 pdata.transfer_info = transfer_info;
4207
4208 if (copy_job->is_move) {
4209 res = g_file_move (src, dest,
4210 flags,
4211 job->cancellable,
4212 copy_file_progress_callback,
4213 &pdata,
4214 &error);
4215 } else {
4216 res = g_file_copy (src, dest,
4217 flags,
4218 job->cancellable,
4219 copy_file_progress_callback,
4220 &pdata,
4221 &error);
4222 }
4223
4224 if (res) {
4225 transfer_info->num_files ++;
4226 report_copy_progress (copy_job, source_info, transfer_info);
4227
4228 if (debuting_files) {
4229 if (position) {
4230 nautilus_file_changes_queue_schedule_position_set (dest, *position, job->screen_num);
4231 } else {
4232 nautilus_file_changes_queue_schedule_position_remove (dest);
4233 }
4234
4235 g_hash_table_replace (debuting_files, g_object_ref (dest), GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
4236 }
4237 if (copy_job->is_move) {
4238 nautilus_file_changes_queue_file_moved (src, dest);
4239 } else {
4240 nautilus_file_changes_queue_file_added (dest);
4241 }
4242
4243 /* If copying a trusted desktop file to the desktop,
4244 mark it as trusted. */
4245 if (copy_job->desktop_location != NULL((void*)0) &&
4246 g_file_equal (copy_job->desktop_location, dest_dir) &&
4247 is_trusted_desktop_file (src, job->cancellable)) {
4248 mark_desktop_file_trusted (job,
4249 job->cancellable,
4250 dest,
4251 FALSE(0));
4252 }
4253
4254 if (job->undo_info != NULL((void*)0)) {
4255 nautilus_file_undo_info_ext_add_origin_target_pair (NAUTILUS_FILE_UNDO_INFO_EXT (job->undo_info)((((NautilusFileUndoInfoExt*) g_type_check_instance_cast ((GTypeInstance
*) ((job->undo_info)), ((nautilus_file_undo_info_ext_get_type
()))))))
,
4256 src, dest);
4257 }
4258
4259 g_object_unref (dest);
4260 return;
4261 }
4262
4263 if (!handled_invalid_filename &&
4264 IS_IO_ERROR (error, INVALID_FILENAME)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_INVALID_FILENAME))
) {
4265 handled_invalid_filename = TRUE(!(0));
4266
4267 g_assert (*dest_fs_type == NULL)do { if (*dest_fs_type == ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "nautilus-file-operations.c", 4267, ((const char
*) (__func__)), "*dest_fs_type == NULL"); } while (0)
;
4268 *dest_fs_type = query_fs_type (dest_dir, job->cancellable);
4269
4270 if (unique_names) {
4271 new_dest = get_unique_target_file (src, dest_dir, same_fs, *dest_fs_type, unique_name_nr);
4272 } else {
4273 new_dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs);
4274 }
4275
4276 if (!g_file_equal (dest, new_dest)) {
4277 g_object_unref (dest);
4278 dest = new_dest;
4279
4280 g_error_free (error);
4281 goto retry;
4282 } else {
4283 g_object_unref (new_dest);
4284 }
4285 }
4286
4287 /* Conflict */
4288 if (!overwrite &&
4289 IS_IO_ERROR (error, EXISTS)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_EXISTS))
) {
4290 gboolean is_merge;
4291 ConflictResponseData *response;
4292
4293 g_error_free (error);
4294
4295 if (unique_names) {
4296 g_object_unref (dest);
4297 dest = get_unique_target_file (src, dest_dir, same_fs, *dest_fs_type, unique_name_nr++);
4298 goto retry;
4299 }
4300
4301 is_merge = FALSE(0);
4302
4303 if (is_dir (dest) && is_dir (src)) {
4304 is_merge = TRUE(!(0));
4305 }
4306
4307 if ((is_merge && job->merge_all) ||
4308 (!is_merge && job->replace_all)) {
4309 overwrite = TRUE(!(0));
4310 goto retry;
4311 }
4312
4313 if (job->skip_all_conflict) {
4314 goto out;
4315 }
4316
4317 response = run_conflict_dialog (job, src, dest, dest_dir);
4318
4319 if (response->id == GTK_RESPONSE_CANCEL ||
4320 response->id == GTK_RESPONSE_DELETE_EVENT) {
4321 conflict_response_data_free (response);
4322 abort_job (job);
4323 } else if (response->id == CONFLICT_RESPONSE_SKIP) {
4324 if (response->apply_to_all) {
4325 job->skip_all_conflict = TRUE(!(0));
4326 }
4327 conflict_response_data_free (response);
4328 } else if (response->id == CONFLICT_RESPONSE_REPLACE) { /* merge/replace */
4329 if (response->apply_to_all) {
4330 if (is_merge) {
4331 job->merge_all = TRUE(!(0));
4332 } else {
4333 job->replace_all = TRUE(!(0));
4334 }
4335 }
4336 overwrite = TRUE(!(0));
4337 conflict_response_data_free (response);
4338 goto retry;
4339 } else if (response->id == CONFLICT_RESPONSE_RENAME) {
4340 g_object_unref (dest);
4341 dest = get_target_file_for_display_name (dest_dir,
4342 response->new_name);
4343 conflict_response_data_free (response);
4344 goto retry;
4345 } else {
4346 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 4346, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4347 }
4348 }
4349
4350 else if (overwrite &&
4351 IS_IO_ERROR (error, IS_DIRECTORY)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_IS_DIRECTORY))
) {
4352
4353 g_error_free (error);
4354
4355 if (remove_target_recursively (job, src, dest, dest)) {
4356 goto retry;
4357 }
4358 }
4359
4360 /* Needs to recurse */
4361 else if (IS_IO_ERROR (error, WOULD_RECURSE)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_WOULD_RECURSE))
||
4362 IS_IO_ERROR (error, WOULD_MERGE)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_WOULD_MERGE))
) {
4363 is_merge = error->code == G_IO_ERROR_WOULD_MERGE;
4364 would_recurse = error->code == G_IO_ERROR_WOULD_RECURSE;
4365 g_error_free (error);
4366
4367 if (overwrite && would_recurse) {
4368 error = NULL((void*)0);
4369
4370 /* Copying a dir onto file, first remove the file */
4371 if (!g_file_delete (dest, job->cancellable, &error) &&
4372 !IS_IO_ERROR (error, NOT_FOUND)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_FOUND))
) {
4373 if (job->skip_all_error) {
4374 g_error_free (error);
4375 goto out;
4376 }
4377 if (copy_job->is_move) {
4378 primary = f (_("Error while moving “%B”.")gettext ("Error while moving “%B”."), src);
4379 } else {
4380 primary = f (_("Error while copying “%B”.")gettext ("Error while copying “%B”."), src);
4381 }
4382 secondary = f (_("Could not remove the already existing file with the same name in %F.")gettext ("Could not remove the already existing file with the same name in %F."
)
, dest_dir);
4383 details = error->message;
4384
4385 /* setting TRUE on show_all here, as we could have
4386 * another error on the same file later.
4387 */
4388 response = run_warning (job,
4389 primary,
4390 secondary,
4391 details,
4392 TRUE(!(0)),
4393 CANCELgettext ("_Cancel"), SKIP_ALLgettext ("S_kip All"), SKIPgettext ("_Skip"),
4394 NULL((void*)0));
4395
4396 g_error_free (error);
4397
4398 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4399 abort_job (job);
4400 } else if (response == 1) { /* skip all */
4401 job->skip_all_error = TRUE(!(0));
4402 } else if (response == 2) { /* skip */
4403 /* do nothing */
4404 } else {
4405 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 4405, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4406 }
4407 goto out;
4408
4409 }
4410 if (error) {
4411 g_error_free (error);
4412 error = NULL((void*)0);
4413 }
4414 nautilus_file_changes_queue_file_removed (dest);
4415 }
4416
4417 if (is_merge) {
4418 /* On merge we now write in the target directory, which may not
4419 be in the same directory as the source, even if the parent is
4420 (if the merged directory is a mountpoint). This could cause
4421 problems as we then don't transcode filenames.
4422 We just set same_fs to FALSE which is safe but a bit slower. */
4423 same_fs = FALSE(0);
4424 }
4425
4426 if (!copy_move_directory (copy_job, src, &dest, same_fs,
4427 would_recurse, dest_fs_type,
4428 source_info, transfer_info,
4429 debuting_files, skipped_file,
4430 readonly_source_fs)) {
4431 /* destination changed, since it was an invalid file name */
4432 g_assert (*dest_fs_type != NULL)do { if (*dest_fs_type != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "nautilus-file-operations.c", 4432, ((const char
*) (__func__)), "*dest_fs_type != NULL"); } while (0)
;
4433 handled_invalid_filename = TRUE(!(0));
4434 goto retry;
4435 }
4436
4437 g_object_unref (dest);
4438 return;
4439 }
4440
4441 else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
4442 g_error_free (error);
4443 }
4444
4445 /* Other error */
4446 else {
4447 if (job->skip_all_error) {
4448 g_error_free (error);
4449 goto out;
4450 }
4451 primary = f (_("Error while copying “%B”.")gettext ("Error while copying “%B”."), src);
4452 secondary = f (_("There was an error copying the file into %F.")gettext ("There was an error copying the file into %F."), dest_dir);
4453 details = error->message;
4454
4455 response = run_cancel_or_skip_warning (job,
4456 primary,
4457 secondary,
4458 details,
4459 source_info->num_files,
4460 source_info->num_files - transfer_info->num_files);
4461
4462 g_error_free (error);
4463
4464 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4465 abort_job (job);
4466 } else if (response == 1) { /* skip all */
4467 job->skip_all_error = TRUE(!(0));
4468 } else if (response == 2) { /* skip */
4469 /* do nothing */
4470 } else {
4471 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 4471, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4472 }
4473 }
4474 out:
4475 *skipped_file = TRUE(!(0)); /* Or aborted, but same-same */
4476 g_object_unref (dest);
4477}
4478
4479static void
4480copy_files (CopyMoveJob *job,
4481 const char *dest_fs_id,
4482 SourceInfo *source_info,
4483 TransferInfo *transfer_info)
4484{
4485 CommonJob *common;
4486 GList *l;
4487 GFile *src;
4488 gboolean same_fs;
4489 int i;
4490 GdkPoint *point;
4491 gboolean skipped_file;
4492 gboolean unique_names;
4493 GFile *dest;
4494 GFile *source_dir;
4495 char *dest_fs_type;
4496 GFileInfo *inf;
4497 gboolean readonly_source_fs;
4498
4499 dest_fs_type = NULL((void*)0);
4500 readonly_source_fs = FALSE(0);
4501
4502 common = &job->common;
4503
4504 report_copy_progress (job, source_info, transfer_info);
4505
4506 /* Query the source dir, not the file because if its a symlink we'll follow it */
4507 source_dir = g_file_get_parent ((GFile *) job->files->data);
4508 if (source_dir) {
4509 inf = g_file_query_filesystem_info (source_dir, "filesystem::readonly", NULL((void*)0), NULL((void*)0));
4510 if (inf != NULL((void*)0)) {
4511 readonly_source_fs = g_file_info_get_attribute_boolean (inf, "filesystem::readonly");
4512 g_object_unref (inf);
4513 }
4514 g_object_unref (source_dir);
4515 }
4516
4517 unique_names = (job->destination == NULL((void*)0));
4518 i = 0;
4519 for (l = job->files;
4520 l != NULL((void*)0) && !job_aborted (common);
4521 l = l->next) {
4522 src = l->data;
4523
4524 if (i < job->n_icon_positions) {
4525 point = &job->icon_positions[i];
4526 } else {
4527 point = NULL((void*)0);
4528 }
4529
4530
4531 same_fs = FALSE(0);
4532 if (dest_fs_id) {
4533 same_fs = has_fs_id (src, dest_fs_id);
4534 }
4535
4536 if (job->destination) {
4537 dest = g_object_ref (job->destination);
4538 } else {
4539 dest = g_file_get_parent (src);
4540
4541 }
4542 if (dest) {
4543 skipped_file = FALSE(0);
4544 copy_move_file (job, src, dest,
4545 same_fs, unique_names,
4546 &dest_fs_type,
4547 source_info, transfer_info,
4548 job->debuting_files,
4549 point, FALSE(0), &skipped_file,
4550 readonly_source_fs);
4551 g_object_unref (dest);
4552 }
4553 i++;
4554 }
4555
4556 g_free (dest_fs_type);
4557}
4558
4559static gboolean
4560copy_job_done (gpointer user_data)
4561{
4562 CopyMoveJob *job;
4563
4564 job = user_data;
4565 if (job->done_callback) {
4566 job->done_callback (job->debuting_files,
4567 !job_aborted ((CommonJob *) job),
4568 job->done_callback_data);
4569 }
4570
4571 g_list_free_full (job->files, g_object_unref);
4572 if (job->destination) {
4573 g_object_unref (job->destination);
4574 }
4575 if (job->desktop_location) {
4576 g_object_unref (job->desktop_location);
4577 }
4578 g_hash_table_unref (job->debuting_files);
4579 g_free (job->icon_positions);
4580 g_free (job->target_name);
4581
4582 g_clear_object (&job->fake_display_source)do { typedef char _GStaticAssertCompileTimeAssertion_33[(sizeof
*((&job->fake_display_source)) == sizeof (gpointer)) ?
1 : -1] __attribute__((__unused__)); gpointer *_pp = (gpointer
*) ((&job->fake_display_source)); gpointer _p; GDestroyNotify
_destroy = (GDestroyNotify) (g_object_unref); (void) (0 ? (gpointer
) *((&job->fake_display_source)) : 0); do _p = (__extension__
({ typedef char _GStaticAssertCompileTimeAssertion_34[(sizeof
*(_pp) == sizeof (gpointer)) ? 1 : -1] __attribute__((__unused__
)); __sync_synchronize (); (gpointer) *(_pp); })); while (!(__extension__
({ typedef char _GStaticAssertCompileTimeAssertion_35[(sizeof
*(_pp) == sizeof (gpointer)) ? 1 : -1] __attribute__((__unused__
)); (void) (0 ? (gpointer) *(_pp) : 0); (gboolean) __sync_bool_compare_and_swap
((_pp), (_p), (((void*)0))); }))); if (_p) _destroy (_p); } while
(0)
;
4583
4584 finalize_common ((CommonJob *)job);
4585
4586 nautilus_file_changes_consume_changes (TRUE(!(0)));
4587 return FALSE(0);
4588}
4589
4590static gboolean
4591copy_job (GIOSchedulerJob *io_job,
4592 GCancellable *cancellable,
4593 gpointer user_data)
4594{
4595 CopyMoveJob *job;
4596 CommonJob *common;
4597 SourceInfo source_info;
4598 TransferInfo transfer_info;
4599 char *dest_fs_id;
4600 GFile *dest;
4601
4602 job = user_data;
4603 common = &job->common;
4604 common->io_job = io_job;
4605
4606 dest_fs_id = NULL((void*)0);
4607
4608 nautilus_progress_info_start (job->common.progress);
4609
4610 scan_sources (job->files,
4611 &source_info,
4612 common,
4613 OP_KIND_COPY);
4614 if (job_aborted (common)) {
4615 goto aborted;
4616 }
4617
4618 if (job->destination) {
4619 dest = g_object_ref (job->destination);
4620 } else {
4621 /* Duplication, no dest,
4622 * use source for free size, etc
4623 */
4624 dest = g_file_get_parent (job->files->data);
4625 }
4626
4627 verify_destination (&job->common,
4628 dest,
4629 &dest_fs_id,
4630 source_info.num_bytes);
4631 g_object_unref (dest);
4632 if (job_aborted (common)) {
4633 goto aborted;
4634 }
4635
4636 g_timer_start (job->common.time);
4637
4638 memset (&transfer_info, 0, sizeof (transfer_info));
4639 copy_files (job,
4640 dest_fs_id,
4641 &source_info, &transfer_info);
4642
4643 aborted:
4644
4645 g_free (dest_fs_id);
4646
4647 g_io_scheduler_job_send_to_mainloop_async (io_job,
4648 copy_job_done,
4649 job,
4650 NULL((void*)0));
4651
4652 return FALSE(0);
4653}
4654
4655void
4656nautilus_file_operations_copy_file (GFile *source_file,
4657 GFile *target_dir,
4658 const gchar *source_display_name,
4659 const gchar *new_name,
4660 GtkWindow *parent_window,
4661 NautilusCopyCallback done_callback,
4662 gpointer done_callback_data)
4663{
4664 CopyMoveJob *job;
4665
4666 job = op_job_new (CopyMoveJob, parent_window)((CopyMoveJob *)(init_common (sizeof(CopyMoveJob), parent_window
)))
;
4667 job->done_callback = done_callback;
4668 job->done_callback_data = done_callback_data;
4669 job->files = g_list_append (NULL((void*)0), g_object_ref (source_file));
4670 job->destination = g_object_ref (target_dir);
4671 job->target_name = g_strdup (new_name);
4672 job->debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
4673
4674 if (source_display_name != NULL((void*)0)) {
4675 gchar *path;
4676
4677 path = g_build_filename ("/", source_display_name, NULL((void*)0));
4678 job->fake_display_source = g_file_new_for_path (path);
4679
4680 g_free (path);
4681 }
4682
4683 inhibit_power_manager ((CommonJob *)job, _("Copying Files")gettext ("Copying Files"));
4684
4685 g_io_scheduler_push_job (copy_job,
4686 job,
4687 NULL((void*)0), /* destroy notify */
4688 0,
4689 job->common.cancellable);
4690}
4691
4692void
4693nautilus_file_operations_copy (GList *files,
4694 GArray *relative_item_points,
4695 GFile *target_dir,
4696 GtkWindow *parent_window,
4697 NautilusCopyCallback done_callback,
4698 gpointer done_callback_data)
4699{
4700 CopyMoveJob *job;
4701
4702 job = op_job_new (CopyMoveJob, parent_window)((CopyMoveJob *)(init_common (sizeof(CopyMoveJob), parent_window
)))
;
4703 job->desktop_location = nautilus_get_desktop_location ();
4704 job->done_callback = done_callback;
4705 job->done_callback_data = done_callback_data;
4706 job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL((void*)0));
4707 job->destination = g_object_ref (target_dir);
4708 if (relative_item_points != NULL((void*)0) &&
4709 relative_item_points->len > 0) {
4710 job->icon_positions =
4711 g_memdup (relative_item_points->data,
4712 sizeof (GdkPoint) * relative_item_points->len);
4713 job->n_icon_positions = relative_item_points->len;
4714 }
4715 job->debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
4716
4717 inhibit_power_manager ((CommonJob *)job, _("Copying Files")gettext ("Copying Files"));
4718
4719 if (!nautilus_file_undo_manager_pop_flag ()) {
4720 GFile* src_dir;
4721
4722 src_dir = g_file_get_parent (files->data);
4723 job->common.undo_info = nautilus_file_undo_info_ext_new (NAUTILUS_FILE_UNDO_OP_COPY,
4724 g_list_length (files),
4725 src_dir, target_dir);
4726
4727 g_object_unref (src_dir);
4728 }
4729
4730 g_io_scheduler_push_job (copy_job,
4731 job,
4732 NULL((void*)0), /* destroy notify */
4733 0,
4734 job->common.cancellable);
4735}
4736
4737static void
4738report_move_progress (CopyMoveJob *move_job, int total, int left)
4739{
4740 CommonJob *job;
4741
4742 job = (CommonJob *)move_job;
4743
4744 nautilus_progress_info_take_status (job->progress,
4745 f (_("Preparing to Move to “%B”")gettext ("Preparing to Move to “%B”"),
4746 move_job->destination));
4747
4748 nautilus_progress_info_take_details (job->progress,
4749 f (ngettext ("Preparing to move %'d file",
4750 "Preparing to move %'d files",
4751 left), left));
4752
4753 nautilus_progress_info_pulse_progress (job->progress);
4754}
4755
4756typedef struct {
4757 GFile *file;
4758 gboolean overwrite;
4759 gboolean has_position;
4760 GdkPoint position;
4761} MoveFileCopyFallback;
4762
4763static MoveFileCopyFallback *
4764move_copy_file_callback_new (GFile *file,
4765 gboolean overwrite,
4766 GdkPoint *position)
4767{
4768 MoveFileCopyFallback *fallback;
4769
4770 fallback = g_new (MoveFileCopyFallback, 1)((MoveFileCopyFallback *) g_malloc_n ((1), sizeof (MoveFileCopyFallback
)))
;
4771 fallback->file = file;
4772 fallback->overwrite = overwrite;
4773 if (position) {
4774 fallback->has_position = TRUE(!(0));
4775 fallback->position = *position;
4776 } else {
4777 fallback->has_position = FALSE(0);
4778 }
4779
4780 return fallback;
4781}
4782
4783static GList *
4784get_files_from_fallbacks (GList *fallbacks)
4785{
4786 MoveFileCopyFallback *fallback;
4787 GList *res, *l;
4788
4789 res = NULL((void*)0);
4790 for (l = fallbacks; l != NULL((void*)0); l = l->next) {
4791 fallback = l->data;
4792 res = g_list_prepend (res, fallback->file);
4793 }
4794 return g_list_reverse (res);
4795}
4796
4797static void
4798move_file_prepare (CopyMoveJob *move_job,
4799 GFile *src,
4800 GFile *dest_dir,
4801 gboolean same_fs,
4802 char **dest_fs_type,
4803 GHashTable *debuting_files,
4804 GdkPoint *position,
4805 GList **fallback_files,
4806 int files_left)
4807{
4808 GFile *dest, *new_dest;
4809 GError *error;
4810 CommonJob *job;
4811 gboolean overwrite;
4812 char *primary, *secondary, *details;
4813 int response;
4814 GFileCopyFlags flags;
4815 MoveFileCopyFallback *fallback;
4816 gboolean handled_invalid_filename;
4817
4818 overwrite = FALSE(0);
4819 handled_invalid_filename = *dest_fs_type != NULL((void*)0);
4820
4821 job = (CommonJob *)move_job;
4822
4823 dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs);
4824
4825
4826 /* Don't allow recursive move/copy into itself.
4827 * (We would get a file system error if we proceeded but it is nicer to
4828 * detect and report it at this level) */
4829 if (test_dir_is_parent (dest_dir, src)) {
4830 if (job->skip_all_error) {
4831 goto out;
4832 }
4833
4834 /* the run_warning() frees all strings passed in automatically */
4835 primary = move_job->is_move ? g_strdup (_("You cannot move a folder into itself.")gettext ("You cannot move a folder into itself."))
4836 : g_strdup (_("You cannot copy a folder into itself.")gettext ("You cannot copy a folder into itself."));
4837 secondary = g_strdup (_("The destination folder is inside the source folder.")gettext ("The destination folder is inside the source folder."
)
);
4838
4839 response = run_warning (job,
4840 primary,
4841 secondary,
4842 NULL((void*)0),
4843 files_left > 1,
4844 CANCELgettext ("_Cancel"), SKIP_ALLgettext ("S_kip All"), SKIPgettext ("_Skip"),
4845 NULL((void*)0));
4846
4847 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4848 abort_job (job);
4849 } else if (response == 1) { /* skip all */
4850 job->skip_all_error = TRUE(!(0));
4851 } else if (response == 2) { /* skip */
4852 /* do nothing */
4853 } else {
4854 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 4854, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4855 }
4856
4857 goto out;
4858 }
4859
4860 retry:
4861
4862 flags = G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_NO_FALLBACK_FOR_MOVE;
4863 if (overwrite) {
4864 flags |= G_FILE_COPY_OVERWRITE;
4865 }
4866
4867 error = NULL((void*)0);
4868 if (g_file_move (src, dest,
4869 flags,
4870 job->cancellable,
4871 NULL((void*)0),
4872 NULL((void*)0),
4873 &error)) {
4874
4875 if (debuting_files) {
4876 g_hash_table_replace (debuting_files, g_object_ref (dest), GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
4877 }
4878
4879 nautilus_file_changes_queue_file_moved (src, dest);
4880
4881 if (position) {
4882 nautilus_file_changes_queue_schedule_position_set (dest, *position, job->screen_num);
4883 } else {
4884 nautilus_file_changes_queue_schedule_position_remove (dest);
4885 }
4886
4887 if (job->undo_info != NULL((void*)0)) {
4888 nautilus_file_undo_info_ext_add_origin_target_pair (NAUTILUS_FILE_UNDO_INFO_EXT (job->undo_info)((((NautilusFileUndoInfoExt*) g_type_check_instance_cast ((GTypeInstance
*) ((job->undo_info)), ((nautilus_file_undo_info_ext_get_type
()))))))
,
4889 src, dest);
4890 }
4891
4892 return;
4893 }
4894
4895 if (IS_IO_ERROR (error, INVALID_FILENAME)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_INVALID_FILENAME))
&&
4896 !handled_invalid_filename) {
4897 g_error_free (error);
4898
4899 handled_invalid_filename = TRUE(!(0));
4900
4901 g_assert (*dest_fs_type == NULL)do { if (*dest_fs_type == ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "nautilus-file-operations.c", 4901, ((const char
*) (__func__)), "*dest_fs_type == NULL"); } while (0)
;
4902 *dest_fs_type = query_fs_type (dest_dir, job->cancellable);
4903
4904 new_dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs);
4905 if (!g_file_equal (dest, new_dest)) {
4906 g_object_unref (dest);
4907 dest = new_dest;
4908 goto retry;
4909 } else {
4910 g_object_unref (new_dest);
4911 }
4912 }
4913
4914 /* Conflict */
4915 else if (!overwrite &&
4916 IS_IO_ERROR (error, EXISTS)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_EXISTS))
) {
4917 gboolean is_merge;
4918 ConflictResponseData *response;
4919
4920 g_error_free (error);
4921
4922 is_merge = FALSE(0);
4923 if (is_dir (dest) && is_dir (src)) {
4924 is_merge = TRUE(!(0));
4925 }
4926
4927 if ((is_merge && job->merge_all) ||
4928 (!is_merge && job->replace_all)) {
4929 overwrite = TRUE(!(0));
4930 goto retry;
4931 }
4932
4933 if (job->skip_all_conflict) {
4934 goto out;
4935 }
4936
4937 response = run_conflict_dialog (job, src, dest, dest_dir);
4938
4939 if (response->id == GTK_RESPONSE_CANCEL ||
4940 response->id == GTK_RESPONSE_DELETE_EVENT) {
4941 conflict_response_data_free (response);
4942 abort_job (job);
4943 } else if (response->id == CONFLICT_RESPONSE_SKIP) {
4944 if (response->apply_to_all) {
4945 job->skip_all_conflict = TRUE(!(0));
4946 }
4947 conflict_response_data_free (response);
4948 } else if (response->id == CONFLICT_RESPONSE_REPLACE) { /* merge/replace */
4949 if (response->apply_to_all) {
4950 if (is_merge) {
4951 job->merge_all = TRUE(!(0));
4952 } else {
4953 job->replace_all = TRUE(!(0));
4954 }
4955 }
4956 overwrite = TRUE(!(0));
4957 conflict_response_data_free (response);
4958 goto retry;
4959 } else if (response->id == CONFLICT_RESPONSE_RENAME) {
4960 g_object_unref (dest);
4961 dest = get_target_file_for_display_name (dest_dir,
4962 response->new_name);
4963 conflict_response_data_free (response);
4964 goto retry;
4965 } else {
4966 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 4966, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4967 }
4968 }
4969
4970 else if (IS_IO_ERROR (error, WOULD_RECURSE)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_WOULD_RECURSE))
||
4971 IS_IO_ERROR (error, WOULD_MERGE)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_WOULD_MERGE))
||
4972 IS_IO_ERROR (error, NOT_SUPPORTED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_SUPPORTED))
||
4973 (overwrite && IS_IO_ERROR (error, IS_DIRECTORY)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_IS_DIRECTORY))
)) {
4974 g_error_free (error);
4975
4976 fallback = move_copy_file_callback_new (src,
4977 overwrite,
4978 position);
4979 *fallback_files = g_list_prepend (*fallback_files, fallback);
4980 }
4981
4982 else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
4983 g_error_free (error);
4984 }
4985
4986 /* Other error */
4987 else {
4988 if (job->skip_all_error) {
4989 g_error_free (error);
4990 goto out;
4991 }
4992 primary = f (_("Error while moving “%B”.")gettext ("Error while moving “%B”."), src);
4993 secondary = f (_("There was an error moving the file into %F.")gettext ("There was an error moving the file into %F."), dest_dir);
4994 details = error->message;
4995
4996 response = run_warning (job,
4997 primary,
4998 secondary,
4999 details,
5000 files_left > 1,
5001 CANCELgettext ("_Cancel"), SKIP_ALLgettext ("S_kip All"), SKIPgettext ("_Skip"),
5002 NULL((void*)0));
5003
5004 g_error_free (error);
5005
5006 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
5007 abort_job (job);
5008 } else if (response == 1) { /* skip all */
5009 job->skip_all_error = TRUE(!(0));
5010 } else if (response == 2) { /* skip */
5011 /* do nothing */
5012 } else {
5013 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 5013, ((const char*) (__func__)), ((void*)0)); } while (0)
;
5014 }
5015 }
5016
5017 out:
5018 g_object_unref (dest);
5019}
5020
5021static void
5022move_files_prepare (CopyMoveJob *job,
5023 const char *dest_fs_id,
5024 char **dest_fs_type,
5025 GList **fallbacks)
5026{
5027 CommonJob *common;
5028 GList *l;
5029 GFile *src;
5030 gboolean same_fs;
5031 int i;
5032 GdkPoint *point;
5033 int total, left;
5034
5035 common = &job->common;
5036
5037 total = left = g_list_length (job->files);
5038
5039 report_move_progress (job, total, left);
5040
5041 i = 0;
5042 for (l = job->files;
5043 l != NULL((void*)0) && !job_aborted (common);
5044 l = l->next) {
5045 src = l->data;
5046
5047 if (i < job->n_icon_positions) {
5048 point = &job->icon_positions[i];
5049 } else {
5050 point = NULL((void*)0);
5051 }
5052
5053
5054 same_fs = FALSE(0);
5055 if (dest_fs_id) {
5056 same_fs = has_fs_id (src, dest_fs_id);
5057 }
5058
5059 move_file_prepare (job, src, job->destination,
5060 same_fs, dest_fs_type,
5061 job->debuting_files,
5062 point,
5063 fallbacks,
5064 left);
5065 report_move_progress (job, total, --left);
5066 i++;
5067 }
5068
5069 *fallbacks = g_list_reverse (*fallbacks);
5070
5071
5072}
5073
5074static void
5075move_files (CopyMoveJob *job,
5076 GList *fallbacks,
5077 const char *dest_fs_id,
5078 char **dest_fs_type,
5079 SourceInfo *source_info,
5080 TransferInfo *transfer_info)
5081{
5082 CommonJob *common;
5083 GList *l;
5084 GFile *src;
5085 gboolean same_fs;
5086 int i;
5087 GdkPoint *point;
5088 gboolean skipped_file;
5089 MoveFileCopyFallback *fallback;
5090common = &job->common;
5091
5092 report_copy_progress (job, source_info, transfer_info);
5093
5094 i = 0;
5095 for (l = fallbacks;
5096 l != NULL((void*)0) && !job_aborted (common);
5097 l = l->next) {
5098 fallback = l->data;
5099 src = fallback->file;
5100
5101 if (fallback->has_position) {
5102 point = &fallback->position;
5103 } else {
5104 point = NULL((void*)0);
5105 }
5106
5107 same_fs = FALSE(0);
5108 if (dest_fs_id) {
5109 same_fs = has_fs_id (src, dest_fs_id);
5110 }
5111
5112 /* Set overwrite to true, as the user has
5113 selected overwrite on all toplevel items */
5114 skipped_file = FALSE(0);
5115 copy_move_file (job, src, job->destination,
5116 same_fs, FALSE(0), dest_fs_type,
5117 source_info, transfer_info,
5118 job->debuting_files,
5119 point, fallback->overwrite, &skipped_file, FALSE(0));
5120 i++;
5121 }
5122}
5123
5124
5125static gboolean
5126move_job_done (gpointer user_data)
5127{
5128 CopyMoveJob *job;
5129
5130 job = user_data;
5131 if (job->done_callback) {
5132 job->done_callback (job->debuting_files,
5133 !job_aborted ((CommonJob *) job),
5134 job->done_callback_data);
5135 }
5136
5137 g_list_free_full (job->files, g_object_unref);
5138 g_object_unref (job->destination);
5139 g_hash_table_unref (job->debuting_files);
5140 g_free (job->icon_positions);
5141
5142 finalize_common ((CommonJob *)job);
5143
5144 nautilus_file_changes_consume_changes (TRUE(!(0)));
5145 return FALSE(0);
5146}
5147
5148static gboolean
5149move_job (GIOSchedulerJob *io_job,
5150 GCancellable *cancellable,
5151 gpointer user_data)
5152{
5153 CopyMoveJob *job;
5154 CommonJob *common;
5155 GList *fallbacks;
5156 SourceInfo source_info;
5157 TransferInfo transfer_info;
5158 char *dest_fs_id;
5159 char *dest_fs_type;
5160 GList *fallback_files;
5161
5162 job = user_data;
5163 common = &job->common;
5164 common->io_job = io_job;
5165
5166 dest_fs_id = NULL((void*)0);
5167 dest_fs_type = NULL((void*)0);
5168
5169 fallbacks = NULL((void*)0);
5170
5171 nautilus_progress_info_start (job->common.progress);
5172
5173 verify_destination (&job->common,
5174 job->destination,
5175 &dest_fs_id,
5176 -1);
5177 if (job_aborted (common)) {
5178 goto aborted;
5179 }
5180
5181 /* This moves all files that we can do without copy + delete */
5182 move_files_prepare (job, dest_fs_id, &dest_fs_type, &fallbacks);
5183 if (job_aborted (common)) {
5184 goto aborted;
5185 }
5186
5187 /* The rest we need to do deep copy + delete behind on,
5188 so scan for size */
5189
5190 fallback_files = get_files_from_fallbacks (fallbacks);
5191 scan_sources (fallback_files,
5192 &source_info,
5193 common,
5194 OP_KIND_MOVE);
5195
5196 g_list_free (fallback_files);
5197
5198 if (job_aborted (common)) {
5199 goto aborted;
5200 }
5201
5202 verify_destination (&job->common,
5203 job->destination,
5204 NULL((void*)0),
5205 source_info.num_bytes);
5206 if (job_aborted (common)) {
5207 goto aborted;
5208 }
5209
5210 memset (&transfer_info, 0, sizeof (transfer_info));
5211 move_files (job,
5212 fallbacks,
5213 dest_fs_id, &dest_fs_type,
5214 &source_info, &transfer_info);
5215
5216 aborted:
5217 g_list_free_full (fallbacks, g_free);
5218
5219 g_free (dest_fs_id);
5220 g_free (dest_fs_type);
5221
5222 g_io_scheduler_job_send_to_mainloop (io_job,
5223 move_job_done,
5224 job,
5225 NULL((void*)0));
5226
5227 return FALSE(0);
5228}
5229
5230void
5231nautilus_file_operations_move (GList *files,
5232 GArray *relative_item_points,
5233 GFile *target_dir,
5234 GtkWindow *parent_window,
5235 NautilusCopyCallback done_callback,
5236 gpointer done_callback_data)
5237{
5238 CopyMoveJob *job;
5239
5240 job = op_job_new (CopyMoveJob, parent_window)((CopyMoveJob *)(init_common (sizeof(CopyMoveJob), parent_window
)))
;
5241 job->is_move = TRUE(!(0));
5242 job->done_callback = done_callback;
5243 job->done_callback_data = done_callback_data;
5244 job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL((void*)0));
5245 job->destination = g_object_ref (target_dir);
5246 if (relative_item_points != NULL((void*)0) &&
5247 relative_item_points->len > 0) {
5248 job->icon_positions =
5249 g_memdup (relative_item_points->data,
5250 sizeof (GdkPoint) * relative_item_points->len);
5251 job->n_icon_positions = relative_item_points->len;
5252 }
5253 job->debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
5254
5255 inhibit_power_manager ((CommonJob *)job, _("Moving Files")gettext ("Moving Files"));
5256
5257 if (!nautilus_file_undo_manager_pop_flag ()) {
5258 GFile* src_dir;
5259
5260 src_dir = g_file_get_parent (files->data);
5261
5262 if (g_file_has_uri_scheme (g_list_first (files)->data, "trash")) {
5263 job->common.undo_info = nautilus_file_undo_info_ext_new (NAUTILUS_FILE_UNDO_OP_RESTORE_FROM_TRASH,
5264 g_list_length (files),
5265 src_dir, target_dir);
5266 } else {
5267 job->common.undo_info = nautilus_file_undo_info_ext_new (NAUTILUS_FILE_UNDO_OP_MOVE,
5268 g_list_length (files),
5269 src_dir, target_dir);
5270 }
5271
5272 g_object_unref (src_dir);
5273 }
5274
5275 g_io_scheduler_push_job (move_job,
5276 job,
5277 NULL((void*)0), /* destroy notify */
5278 0,
5279 job->common.cancellable);
5280}
5281
5282static void
5283report_link_progress (CopyMoveJob *link_job, int total, int left)
5284{
5285 CommonJob *job;
5286
5287 job = (CommonJob *)link_job;
5288
5289 nautilus_progress_info_take_status (job->progress,
5290 f (_("Creating links in “%B”")gettext ("Creating links in “%B”"),
5291 link_job->destination));
5292
5293 nautilus_progress_info_take_details (job->progress,
5294 f (ngettext ("Making link to %'d file",
5295 "Making links to %'d files",
5296 left), left));
5297
5298 nautilus_progress_info_set_progress (job->progress, left, total);
5299}
5300
5301static char *
5302get_abs_path_for_symlink (GFile *file, GFile *destination)
5303{
5304 GFile *root, *parent;
5305 char *relative, *abs;
5306
5307 if (g_file_is_native (file) || g_file_is_native (destination)) {
5308 return g_file_get_path (file);
5309 }
5310
5311 root = g_object_ref (file);
5312 while ((parent = g_file_get_parent (root)) != NULL((void*)0)) {
5313 g_object_unref (root);
5314 root = parent;
5315 }
5316
5317 relative = g_file_get_relative_path (root, file);
5318 g_object_unref (root);
5319 abs = g_strconcat ("/", relative, NULL((void*)0));
5320 g_free (relative);
5321 return abs;
5322}
5323
5324
5325static void
5326link_file (CopyMoveJob *job,
5327 GFile *src, GFile *dest_dir,
5328 char **dest_fs_type,
5329 GHashTable *debuting_files,
5330 GdkPoint *position,
5331 int files_left)
5332{
5333 GFile *src_dir, *dest, *new_dest;
5334 int count;
5335 char *path;
5336 gboolean not_local;
5337 GError *error;
5338 CommonJob *common;
5339 char *primary, *secondary, *details;
5340 int response;
5341 gboolean handled_invalid_filename;
5342
5343 common = (CommonJob *)job;
5344
5345 count = 0;
5346
5347 src_dir = g_file_get_parent (src);
5348 if (g_file_equal (src_dir, dest_dir)) {
5349 count = 1;
5350 }
5351 g_object_unref (src_dir);
5352
5353 handled_invalid_filename = *dest_fs_type != NULL((void*)0);
5354
5355 dest = get_target_file_for_link (src, dest_dir, *dest_fs_type, count);
5356
5357 retry:
5358 error = NULL((void*)0);
5359 not_local = FALSE(0);
5360
5361 path = get_abs_path_for_symlink (src, dest);
5362 if (path == NULL((void*)0)) {
5363 not_local = TRUE(!(0));
5364 } else if (g_file_make_symbolic_link (dest,
5365 path,
5366 common->cancellable,
5367 &error)) {
5368
5369 if (common->undo_info != NULL((void*)0)) {
5370 nautilus_file_undo_info_ext_add_origin_target_pair (NAUTILUS_FILE_UNDO_INFO_EXT (common->undo_info)((((NautilusFileUndoInfoExt*) g_type_check_instance_cast ((GTypeInstance
*) ((common->undo_info)), ((nautilus_file_undo_info_ext_get_type
()))))))
,
5371 src, dest);
5372 }
5373
5374 g_free (path);
5375 if (debuting_files) {
5376 g_hash_table_replace (debuting_files, g_object_ref (dest), GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
5377 }
5378
5379 nautilus_file_changes_queue_file_added (dest);
5380 if (position) {
5381 nautilus_file_changes_queue_schedule_position_set (dest, *position, common->screen_num);
5382 } else {
5383 nautilus_file_changes_queue_schedule_position_remove (dest);
5384 }
5385
5386 g_object_unref (dest);
5387
5388 return;
5389 }
5390 g_free (path);
5391
5392 if (error != NULL((void*)0) &&
5393 IS_IO_ERROR (error, INVALID_FILENAME)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_INVALID_FILENAME))
&&
5394 !handled_invalid_filename) {
5395 handled_invalid_filename = TRUE(!(0));
5396
5397 g_assert (*dest_fs_type == NULL)do { if (*dest_fs_type == ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "nautilus-file-operations.c", 5397, ((const char
*) (__func__)), "*dest_fs_type == NULL"); } while (0)
;
5398 *dest_fs_type = query_fs_type (dest_dir, common->cancellable);
5399
5400 new_dest = get_target_file_for_link (src, dest_dir, *dest_fs_type, count);
5401
5402 if (!g_file_equal (dest, new_dest)) {
5403 g_object_unref (dest);
5404 dest = new_dest;
5405 g_error_free (error);
5406
5407 goto retry;
5408 } else {
5409 g_object_unref (new_dest);
5410 }
5411 }
5412 /* Conflict */
5413 if (error != NULL((void*)0) && IS_IO_ERROR (error, EXISTS)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_EXISTS))
) {
5414 g_object_unref (dest);
5415 dest = get_target_file_for_link (src, dest_dir, *dest_fs_type, count++);
5416 g_error_free (error);
5417 goto retry;
5418 }
5419
5420 else if (error != NULL((void*)0) && IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
5421 g_error_free (error);
5422 }
5423
5424 /* Other error */
5425 else if (error != NULL((void*)0)) {
5426 if (common->skip_all_error) {
5427 goto out;
5428 }
5429 primary = f (_("Error while creating link to %B.")gettext ("Error while creating link to %B."), src);
5430 if (not_local) {
5431 secondary = f (_("Symbolic links only supported for local files")gettext ("Symbolic links only supported for local files"));
5432 details = NULL((void*)0);
5433 } else if (IS_IO_ERROR (error, NOT_SUPPORTED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_SUPPORTED))
) {
5434 secondary = f (_("The target doesn't support symbolic links.")gettext ("The target doesn't support symbolic links."));
5435 details = NULL((void*)0);
5436 } else {
5437 secondary = f (_("There was an error creating the symlink in %F.")gettext ("There was an error creating the symlink in %F."), dest_dir);
5438 details = error->message;
5439 }
5440
5441 response = run_warning (common,
5442 primary,
5443 secondary,
5444 details,
5445 files_left > 1,
5446 CANCELgettext ("_Cancel"), SKIP_ALLgettext ("S_kip All"), SKIPgettext ("_Skip"),
5447 NULL((void*)0));
5448
5449 if (error) {
5450 g_error_free (error);
5451 }
5452
5453 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
5454 abort_job (common);
5455 } else if (response == 1) { /* skip all */
5456 common->skip_all_error = TRUE(!(0));
5457 } else if (response == 2) { /* skip */
5458 /* do nothing */
5459 } else {
5460 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 5460, ((const char*) (__func__)), ((void*)0)); } while (0)
;
5461 }
5462 }
5463
5464 out:
5465 g_object_unref (dest);
5466}
5467
5468static gboolean
5469link_job_done (gpointer user_data)
5470{
5471 CopyMoveJob *job;
5472
5473 job = user_data;
5474 if (job->done_callback) {
5475 job->done_callback (job->debuting_files,
5476 !job_aborted ((CommonJob *) job),
5477 job->done_callback_data);
5478 }
5479
5480 g_list_free_full (job->files, g_object_unref);
5481 g_object_unref (job->destination);
5482 g_hash_table_unref (job->debuting_files);
5483 g_free (job->icon_positions);
5484
5485 finalize_common ((CommonJob *)job);
5486
5487 nautilus_file_changes_consume_changes (TRUE(!(0)));
5488 return FALSE(0);
5489}
5490
5491static gboolean
5492link_job (GIOSchedulerJob *io_job,
5493 GCancellable *cancellable,
5494 gpointer user_data)
5495{
5496 CopyMoveJob *job;
5497 CommonJob *common;
5498 GFile *src;
5499 GdkPoint *point;
5500 char *dest_fs_type;
5501 int total, left;
5502 int i;
5503 GList *l;
5504
5505 job = user_data;
5506 common = &job->common;
5507 common->io_job = io_job;
5508
5509 dest_fs_type = NULL((void*)0);
5510
5511 nautilus_progress_info_start (job->common.progress);
5512
5513 verify_destination (&job->common,
5514 job->destination,
5515 NULL((void*)0),
5516 -1);
5517 if (job_aborted (common)) {
5518 goto aborted;
5519 }
5520
5521 total = left = g_list_length (job->files);
5522
5523 report_link_progress (job, total, left);
5524
5525 i = 0;
5526 for (l = job->files;
5527 l != NULL((void*)0) && !job_aborted (common);
5528 l = l->next) {
5529 src = l->data;
5530
5531 if (i < job->n_icon_positions) {
5532 point = &job->icon_positions[i];
5533 } else {
5534 point = NULL((void*)0);
5535 }
5536
5537
5538 link_file (job, src, job->destination,
5539 &dest_fs_type, job->debuting_files,
5540 point, left);
5541 report_link_progress (job, total, --left);
5542 i++;
5543
5544 }
5545
5546 aborted:
5547 g_free (dest_fs_type);
5548
5549 g_io_scheduler_job_send_to_mainloop (io_job,
5550 link_job_done,
5551 job,
5552 NULL((void*)0));
5553
5554 return FALSE(0);
5555}
5556
5557void
5558nautilus_file_operations_link (GList *files,
5559 GArray *relative_item_points,
5560 GFile *target_dir,
5561 GtkWindow *parent_window,
5562 NautilusCopyCallback done_callback,
5563 gpointer done_callback_data)
5564{
5565 CopyMoveJob *job;
5566
5567 job = op_job_new (CopyMoveJob, parent_window)((CopyMoveJob *)(init_common (sizeof(CopyMoveJob), parent_window
)))
;
5568 job->done_callback = done_callback;
5569 job->done_callback_data = done_callback_data;
5570 job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL((void*)0));
5571 job->destination = g_object_ref (target_dir);
5572 if (relative_item_points != NULL((void*)0) &&
5573 relative_item_points->len > 0) {
5574 job->icon_positions =
5575 g_memdup (relative_item_points->data,
5576 sizeof (GdkPoint) * relative_item_points->len);
5577 job->n_icon_positions = relative_item_points->len;
5578 }
5579 job->debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
5580
5581 if (!nautilus_file_undo_manager_pop_flag ()) {
5582 GFile* src_dir;
5583
5584 src_dir = g_file_get_parent (files->data);
5585 job->common.undo_info = nautilus_file_undo_info_ext_new (NAUTILUS_FILE_UNDO_OP_CREATE_LINK,
5586 g_list_length (files),
5587 src_dir, target_dir);
5588 g_object_unref (src_dir);
5589 }
5590
5591 g_io_scheduler_push_job (link_job,
5592 job,
5593 NULL((void*)0), /* destroy notify */
5594 0,
5595 job->common.cancellable);
5596}
5597
5598
5599void
5600nautilus_file_operations_duplicate (GList *files,
5601 GArray *relative_item_points,
5602 GtkWindow *parent_window,
5603 NautilusCopyCallback done_callback,
5604 gpointer done_callback_data)
5605{
5606 CopyMoveJob *job;
5607
5608 job = op_job_new (CopyMoveJob, parent_window)((CopyMoveJob *)(init_common (sizeof(CopyMoveJob), parent_window
)))
;
5609 job->done_callback = done_callback;
5610 job->done_callback_data = done_callback_data;
5611 job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL((void*)0));
5612 job->destination = NULL((void*)0);
5613 if (relative_item_points != NULL((void*)0) &&
5614 relative_item_points->len > 0) {
5615 job->icon_positions =
5616 g_memdup (relative_item_points->data,
5617 sizeof (GdkPoint) * relative_item_points->len);
5618 job->n_icon_positions = relative_item_points->len;
5619 }
5620 job->debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
5621
5622 if (!nautilus_file_undo_manager_pop_flag ()) {
5623 GFile* src_dir;
5624
5625 src_dir = g_file_get_parent (files->data);
5626 job->common.undo_info =
5627 nautilus_file_undo_info_ext_new (NAUTILUS_FILE_UNDO_OP_DUPLICATE,
5628 g_list_length (files),
5629 src_dir, src_dir);
5630 g_object_unref (src_dir);
5631 }
5632
5633 g_io_scheduler_push_job (copy_job,
5634 job,
5635 NULL((void*)0), /* destroy notify */
5636 0,
5637 job->common.cancellable);
5638}
5639
5640static gboolean
5641set_permissions_job_done (gpointer user_data)
5642{
5643 SetPermissionsJob *job;
5644
5645 job = user_data;
5646
5647 g_object_unref (job->file);
5648
5649 if (job->done_callback) {
5650 job->done_callback (!job_aborted ((CommonJob *) job),
5651 job->done_callback_data);
5652 }
5653
5654 finalize_common ((CommonJob *)job);
5655 return FALSE(0);
5656}
5657
5658static void
5659set_permissions_file (SetPermissionsJob *job,
5660 GFile *file,
5661 GFileInfo *info)
5662{
5663 CommonJob *common;
5664 GFileInfo *child_info;
5665 gboolean free_info;
5666 guint32 current;
5667 guint32 value;
5668 guint32 mask;
5669 GFileEnumerator *enumerator;
5670 GFile *child;
5671
5672 common = (CommonJob *)job;
5673
5674 nautilus_progress_info_pulse_progress (common->progress);
5675
5676 free_info = FALSE(0);
5677 if (info == NULL((void*)0)) {
5678 free_info = TRUE(!(0));
5679 info = g_file_query_info (file,
5680 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
5681 G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
5682 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
5683 common->cancellable,
5684 NULL((void*)0));
5685 /* Ignore errors */
5686 if (info == NULL((void*)0)) {
5687 return;
5688 }
5689 }
5690
5691 if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
5692 value = job->dir_permissions;
5693 mask = job->dir_mask;
5694 } else {
5695 value = job->file_permissions;
5696 mask = job->file_mask;
5697 }
5698
5699
5700 if (!job_aborted (common) &&
5701 g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode")) {
5702 current = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");
5703
5704 if (common->undo_info != NULL((void*)0)) {
5705 nautilus_file_undo_info_rec_permissions_add_file (NAUTILUS_FILE_UNDO_INFO_REC_PERMISSIONS (common->undo_info)((((NautilusFileUndoInfoRecPermissions*) g_type_check_instance_cast
((GTypeInstance*) ((common->undo_info)), ((nautilus_file_undo_info_rec_permissions_get_type
()))))))
,
5706 file, current);
5707 }
5708
5709 current = (current & ~mask) | value;
5710
5711 g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
5712 current, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
5713 common->cancellable, NULL((void*)0));
5714 }
5715
5716 if (!job_aborted (common) &&
5717 g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
5718 enumerator = g_file_enumerate_children (file,
5719 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name"","
5720 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
5721 G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
5722 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
5723 common->cancellable,
5724 NULL((void*)0));
5725 if (enumerator) {
5726 while (!job_aborted (common) &&
5727 (child_info = g_file_enumerator_next_file (enumerator, common->cancellable, NULL((void*)0))) != NULL((void*)0)) {
5728 child = g_file_get_child (file,
5729 g_file_info_get_name (child_info));
5730 set_permissions_file (job, child, child_info);
5731 g_object_unref (child);
5732 g_object_unref (child_info);
5733 }
5734 g_file_enumerator_close (enumerator, common->cancellable, NULL((void*)0));
5735 g_object_unref (enumerator);
5736 }
5737 }
5738 if (free_info) {
5739 g_object_unref (info);
5740 }
5741}
5742
5743
5744static gboolean
5745set_permissions_job (GIOSchedulerJob *io_job,
5746 GCancellable *cancellable,
5747 gpointer user_data)
5748{
5749 SetPermissionsJob *job = user_data;
5750 CommonJob *common;
5751
5752 common = (CommonJob *)job;
5753 common->io_job = io_job;
5754
5755 nautilus_progress_info_set_status (common->progress,
5756 _("Setting permissions")gettext ("Setting permissions"));
5757
5758 nautilus_progress_info_start (job->common.progress);
5759
5760 set_permissions_file (job, job->file, NULL((void*)0));
5761
5762 g_io_scheduler_job_send_to_mainloop_async (io_job,
5763 set_permissions_job_done,
5764 job,
5765 NULL((void*)0));
5766
5767 return FALSE(0);
5768}
5769
5770
5771
5772void
5773nautilus_file_set_permissions_recursive (const char *directory,
5774 guint32 file_permissions,
5775 guint32 file_mask,
5776 guint32 dir_permissions,
5777 guint32 dir_mask,
5778 NautilusOpCallback callback,
5779 gpointer callback_data)
5780{
5781 SetPermissionsJob *job;
5782
5783 job = op_job_new (SetPermissionsJob, NULL)((SetPermissionsJob *)(init_common (sizeof(SetPermissionsJob)
, ((void*)0))))
;
5784 job->file = g_file_new_for_uri (directory);
5785 job->file_permissions = file_permissions;
5786 job->file_mask = file_mask;
5787 job->dir_permissions = dir_permissions;
5788 job->dir_mask = dir_mask;
5789 job->done_callback = callback;
5790 job->done_callback_data = callback_data;
5791
5792 if (!nautilus_file_undo_manager_pop_flag ()) {
5793 job->common.undo_info =
5794 nautilus_file_undo_info_rec_permissions_new (job->file,
5795 file_permissions, file_mask,
5796 dir_permissions, dir_mask);
5797 }
5798
5799 g_io_scheduler_push_job (set_permissions_job,
5800 job,
5801 NULL((void*)0),
5802 0,
5803 NULL((void*)0));
5804}
5805
5806static GList *
5807location_list_from_uri_list (const GList *uris)
5808{
5809 const GList *l;
5810 GList *files;
5811 GFile *f;
5812
5813 files = NULL((void*)0);
5814 for (l = uris; l != NULL((void*)0); l = l->next) {
5815 f = g_file_new_for_uri (l->data);
5816 files = g_list_prepend (files, f);
5817 }
5818
5819 return g_list_reverse (files);
5820}
5821
5822typedef struct {
5823 NautilusCopyCallback real_callback;
5824 gpointer real_data;
5825} MoveTrashCBData;
5826
5827static void
5828callback_for_move_to_trash (GHashTable *debuting_uris,
5829 gboolean user_cancelled,
5830 MoveTrashCBData *data)
5831{
5832 if (data->real_callback)
5833 data->real_callback (debuting_uris, !user_cancelled, data->real_data);
5834 g_slice_free (MoveTrashCBData, data)do { if (1) g_slice_free1 (sizeof (MoveTrashCBData), (data));
else (void) ((MoveTrashCBData*) 0 == (data)); } while (0)
;
5835}
5836
5837void
5838nautilus_file_operations_copy_move (const GList *item_uris,
5839 GArray *relative_item_points,
5840 const char *target_dir,
5841 GdkDragAction copy_action,
5842 GtkWidget *parent_view,
5843 NautilusCopyCallback done_callback,
5844 gpointer done_callback_data)
5845{
5846 GList *locations;
5847 GList *p;
5848 GFile *dest, *src_dir;
5849 GtkWindow *parent_window;
5850 gboolean target_is_mapping;
5851 gboolean have_nonmapping_source;
5852
5853 dest = NULL((void*)0);
5854 target_is_mapping = FALSE(0);
5855 have_nonmapping_source = FALSE(0);
5856
5857 if (target_dir) {
1
Assuming 'target_dir' is null
2
Taking false branch
5858 dest = g_file_new_for_uri (target_dir);
5859 if (g_file_has_uri_scheme (dest, "burn")) {
5860 target_is_mapping = TRUE(!(0));
5861 }
5862 }
5863
5864 locations = location_list_from_uri_list (item_uris);
3
Value assigned to 'locations'
5865
5866 for (p = locations; p != NULL((void*)0); p = p->next) {
4
Assuming 'p' is equal to null
5
Loop condition is false. Execution continues on line 5872
5867 if (!g_file_has_uri_scheme ((GFile* )p->data, "burn")) {
5868 have_nonmapping_source = TRUE(!(0));
5869 }
5870 }
5871
5872 if (target_is_mapping && have_nonmapping_source && copy_action == GDK_ACTION_MOVE) {
5873 /* never move to "burn:///", but fall back to copy.
5874 * This is a workaround, because otherwise the source files would be removed.
5875 */
5876 copy_action = GDK_ACTION_COPY;
5877 }
5878
5879 parent_window = NULL((void*)0);
5880 if (parent_view) {
6
Assuming 'parent_view' is null
7
Taking false branch
5881 parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW(gtk_window_get_type ()));
5882 }
5883
5884 if (copy_action == GDK_ACTION_COPY) {
8
Assuming 'copy_action' is equal to GDK_ACTION_COPY
9
Taking true branch
5885 src_dir = g_file_get_parent (locations->data);
10
Access to field 'data' results in a dereference of a null pointer (loaded from variable 'locations')
5886 if (target_dir == NULL((void*)0) ||
5887 (src_dir != NULL((void*)0) &&
5888 g_file_equal (src_dir, dest))) {
5889
5890 nautilus_file_operations_duplicate (locations,
5891 relative_item_points,
5892 parent_window,
5893 done_callback, done_callback_data);
5894 } else {
5895 nautilus_file_operations_copy (locations,
5896 relative_item_points,
5897 dest,
5898 parent_window,
5899 done_callback, done_callback_data);
5900 }
5901 if (src_dir) {
5902 g_object_unref (src_dir);
5903 }
5904
5905 } else if (copy_action == GDK_ACTION_MOVE) {
5906 if (g_file_has_uri_scheme (dest, "trash")) {
5907 MoveTrashCBData *cb_data;
5908
5909 cb_data = g_slice_new0 (MoveTrashCBData)((MoveTrashCBData*) g_slice_alloc0 (sizeof (MoveTrashCBData))
)
;
5910 cb_data->real_callback = done_callback;
5911 cb_data->real_data = done_callback_data;
5912
5913 nautilus_file_operations_trash_or_delete (locations,
5914 parent_window,
5915 (NautilusDeleteCallback) callback_for_move_to_trash,
5916 cb_data);
5917 } else {
5918
5919 nautilus_file_operations_move (locations,
5920 relative_item_points,
5921 dest,
5922 parent_window,
5923 done_callback, done_callback_data);
5924 }
5925 } else {
5926
5927 nautilus_file_operations_link (locations,
5928 relative_item_points,
5929 dest,
5930 parent_window,
5931 done_callback, done_callback_data);
5932 }
5933
5934 g_list_free_full (locations, g_object_unref);
5935 if (dest) {
5936 g_object_unref (dest);
5937 }
5938}
5939
5940static gboolean
5941create_job_done (gpointer user_data)
5942{
5943 CreateJob *job;
5944
5945 job = user_data;
5946 if (job->done_callback) {
5947 job->done_callback (job->created_file,
5948 !job_aborted ((CommonJob *) job),
5949 job->done_callback_data);
5950 }
5951
5952 g_object_unref (job->dest_dir);
5953 if (job->src) {
5954 g_object_unref (job->src);
5955 }
5956 g_free (job->src_data);
5957 g_free (job->filename);
5958 if (job->created_file) {
5959 g_object_unref (job->created_file);
5960 }
5961
5962 finalize_common ((CommonJob *)job);
5963
5964 nautilus_file_changes_consume_changes (TRUE(!(0)));
5965 return FALSE(0);
5966}
5967
5968static gboolean
5969create_job (GIOSchedulerJob *io_job,
5970 GCancellable *cancellable,
5971 gpointer user_data)
5972{
5973 CreateJob *job;
5974 CommonJob *common;
5975 int count;
5976 GFile *dest;
5977 char *basename;
5978 char *filename, *filename2, *new_filename;
5979 char *filename_base, *suffix;
5980 char *dest_fs_type;
5981 GError *error;
5982 gboolean res;
5983 gboolean filename_is_utf8;
5984 char *primary, *secondary, *details;
5985 int response;
5986 char *data;
5987 int length;
5988 GFileOutputStream *out;
5989 gboolean handled_invalid_filename;
5990 int max_length, offset;
5991
5992 job = user_data;
5993 common = &job->common;
5994 common->io_job = io_job;
5995
5996 nautilus_progress_info_start (job->common.progress);
5997
5998 handled_invalid_filename = FALSE(0);
5999
6000 dest_fs_type = NULL((void*)0);
6001 filename = NULL((void*)0);
6002 dest = NULL((void*)0);
6003
6004 max_length = get_max_name_length (job->dest_dir);
6005
6006 verify_destination (common,
6007 job->dest_dir,
6008 NULL((void*)0), -1);
6009 if (job_aborted (common)) {
6010 goto aborted;
6011 }
6012
6013 filename = g_strdup (job->filename);
6014 filename_is_utf8 = FALSE(0);
6015 if (filename) {
6016 filename_is_utf8 = g_utf8_validate (filename, -1, NULL((void*)0));
6017 }
6018 if (filename == NULL((void*)0)) {
6019 if (job->make_dir) {
6020 /* localizers: the initial name of a new folder */
6021 filename = g_strdup (_("Untitled Folder")gettext ("Untitled Folder"));
6022 filename_is_utf8 = TRUE(!(0)); /* Pass in utf8 */
6023 } else {
6024 if (job->src != NULL((void*)0)) {
6025 basename = g_file_get_basename (job->src);
6026 /* localizers: the initial name of a new template document */
6027 filename = g_strdup_printf (_("Untitled %s")gettext ("Untitled %s"), basename);
6028
6029 g_free (basename);
6030 }
6031 if (filename == NULL((void*)0)) {
6032 /* localizers: the initial name of a new empty document */
6033 filename = g_strdup (_("Untitled Document")gettext ("Untitled Document"));
6034 filename_is_utf8 = TRUE(!(0)); /* Pass in utf8 */
6035 }
6036 }
6037 }
6038
6039 make_file_name_valid_for_dest_fs (filename, dest_fs_type);
6040 if (filename_is_utf8) {
6041 dest = g_file_get_child_for_display_name (job->dest_dir, filename, NULL((void*)0));
6042 }
6043 if (dest == NULL((void*)0)) {
6044 dest = g_file_get_child (job->dest_dir, filename);
6045 }
6046 count = 1;
6047
6048 retry:
6049
6050 error = NULL((void*)0);
6051 if (job->make_dir) {
6052 res = g_file_make_directory (dest,
6053 common->cancellable,
6054 &error);
6055
6056 if (res && common->undo_info != NULL((void*)0)) {
6057 nautilus_file_undo_info_create_set_data (NAUTILUS_FILE_UNDO_INFO_CREATE (common->undo_info)((((NautilusFileUndoInfoCreate*) g_type_check_instance_cast (
(GTypeInstance*) ((common->undo_info)), ((nautilus_file_undo_info_create_get_type
()))))))
,
6058 dest, NULL((void*)0), 0);
6059 }
6060
6061 } else {
6062 if (job->src) {
6063 res = g_file_copy (job->src,
6064 dest,
6065 G_FILE_COPY_NONE,
6066 common->cancellable,
6067 NULL((void*)0), NULL((void*)0),
6068 &error);
6069
6070 if (res && common->undo_info != NULL((void*)0)) {
6071 gchar *uri;
6072
6073 uri = g_file_get_uri (job->src);
6074 nautilus_file_undo_info_create_set_data (NAUTILUS_FILE_UNDO_INFO_CREATE (common->undo_info)((((NautilusFileUndoInfoCreate*) g_type_check_instance_cast (
(GTypeInstance*) ((common->undo_info)), ((nautilus_file_undo_info_create_get_type
()))))))
,
6075 dest, uri, 0);
6076
6077 g_free (uri);
6078 }
6079
6080 } else {
6081 data = "";
6082 length = 0;
6083 if (job->src_data) {
6084 data = job->src_data;
6085 length = job->length;
6086 }
6087
6088 out = g_file_create (dest,
6089 G_FILE_CREATE_NONE,
6090 common->cancellable,
6091 &error);
6092 if (out) {
6093 res = g_output_stream_write_all (G_OUTPUT_STREAM (out)((((GOutputStream*) g_type_check_instance_cast ((GTypeInstance
*) ((out)), ((g_output_stream_get_type ()))))))
,
6094 data, length,
6095 NULL((void*)0),
6096 common->cancellable,
6097 &error);
6098 if (res) {
6099 res = g_output_stream_close (G_OUTPUT_STREAM (out)((((GOutputStream*) g_type_check_instance_cast ((GTypeInstance
*) ((out)), ((g_output_stream_get_type ()))))))
,
6100 common->cancellable,
6101 &error);
6102
6103 if (res && common->undo_info != NULL((void*)0)) {
6104 nautilus_file_undo_info_create_set_data (NAUTILUS_FILE_UNDO_INFO_CREATE (common->undo_info)((((NautilusFileUndoInfoCreate*) g_type_check_instance_cast (
(GTypeInstance*) ((common->undo_info)), ((nautilus_file_undo_info_create_get_type
()))))))
,
6105 dest, data, length);
6106 }
6107 }
6108
6109 /* This will close if the write failed and we didn't close */
6110 g_object_unref (out);
6111 } else {
6112 res = FALSE(0);
6113 }
6114 }
6115 }
6116
6117 if (res) {
6118 job->created_file = g_object_ref (dest);
6119 nautilus_file_changes_queue_file_added (dest);
6120 if (job->has_position) {
6121 nautilus_file_changes_queue_schedule_position_set (dest, job->position, common->screen_num);
6122 } else {
6123 nautilus_file_changes_queue_schedule_position_remove (dest);
6124 }
6125 } else {
6126 g_assert (error != NULL)do { if (error != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "nautilus-file-operations.c", 6126, ((const char
*) (__func__)), "error != NULL"); } while (0)
;
6127
6128 if (IS_IO_ERROR (error, INVALID_FILENAME)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_INVALID_FILENAME))
&&
6129 !handled_invalid_filename) {
6130 handled_invalid_filename = TRUE(!(0));
6131
6132 g_assert (dest_fs_type == NULL)do { if (dest_fs_type == ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "nautilus-file-operations.c", 6132, ((const char
*) (__func__)), "dest_fs_type == NULL"); } while (0)
;
6133 dest_fs_type = query_fs_type (job->dest_dir, common->cancellable);
6134
6135 if (count == 1) {
6136 new_filename = g_strdup (filename);
6137 } else {
6138 filename_base = eel_filename_strip_extension (filename);
6139 offset = strlen (filename_base);
6140 suffix = g_strdup (filename + offset);
6141
6142 filename2 = g_strdup_printf ("%s %d%s", filename_base, count, suffix);
6143
6144 new_filename = NULL((void*)0);
6145 if (max_length > 0 && strlen (filename2) > max_length) {
6146 new_filename = shorten_utf8_string (filename2, strlen (filename2) - max_length);
6147 }
6148
6149 if (new_filename == NULL((void*)0)) {
6150 new_filename = g_strdup (filename2);
6151 }
6152
6153 g_free (filename2);
6154 g_free (suffix);
6155 }
6156
6157 if (make_file_name_valid_for_dest_fs (new_filename, dest_fs_type)) {
6158 g_object_unref (dest);
6159
6160 if (filename_is_utf8) {
6161 dest = g_file_get_child_for_display_name (job->dest_dir, new_filename, NULL((void*)0));
6162 }
6163 if (dest == NULL((void*)0)) {
6164 dest = g_file_get_child (job->dest_dir, new_filename);
6165 }
6166
6167 g_free (new_filename);
6168 g_error_free (error);
6169 goto retry;
6170 }
6171 g_free (new_filename);
6172 }
6173
6174 if (IS_IO_ERROR (error, EXISTS)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_EXISTS))
) {
6175 g_object_unref (dest);
6176 dest = NULL((void*)0);
6177 filename_base = eel_filename_strip_extension (filename);
6178 offset = strlen (filename_base);
6179 suffix = g_strdup (filename + offset);
6180
6181 filename2 = g_strdup_printf ("%s %d%s", filename_base, ++count, suffix);
6182
6183 if (max_length > 0 && strlen (filename2) > max_length) {
6184 new_filename = shorten_utf8_string (filename2, strlen (filename2) - max_length);
6185 if (new_filename != NULL((void*)0)) {
6186 g_free (filename2);
6187 filename2 = new_filename;
6188 }
6189 }
6190
6191 make_file_name_valid_for_dest_fs (filename2, dest_fs_type);
6192 if (filename_is_utf8) {
6193 dest = g_file_get_child_for_display_name (job->dest_dir, filename2, NULL((void*)0));
6194 }
6195 if (dest == NULL((void*)0)) {
6196 dest = g_file_get_child (job->dest_dir, filename2);
6197 }
6198 g_free (filename2);
6199 g_free (suffix);
6200 g_error_free (error);
6201 goto retry;
6202 }
6203
6204 else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
6205 g_error_free (error);
6206 }
6207
6208 /* Other error */
6209 else {
6210 if (job->make_dir) {
6211 primary = f (_("Error while creating directory %B.")gettext ("Error while creating directory %B."), dest);
6212 } else {
6213 primary = f (_("Error while creating file %B.")gettext ("Error while creating file %B."), dest);
6214 }
6215 secondary = f (_("There was an error creating the directory in %F.")gettext ("There was an error creating the directory in %F."), job->dest_dir);
6216 details = error->message;
6217
6218 response = run_warning (common,
6219 primary,
6220 secondary,
6221 details,
6222 FALSE(0),
6223 CANCELgettext ("_Cancel"), SKIPgettext ("_Skip"),
6224 NULL((void*)0));
6225
6226 g_error_free (error);
6227
6228 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
6229 abort_job (common);
6230 } else if (response == 1) { /* skip */
6231 /* do nothing */
6232 } else {
6233 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 6233, ((const char*) (__func__)), ((void*)0)); } while (0)
;
6234 }
6235 }
6236 }
6237
6238 aborted:
6239 if (dest) {
6240 g_object_unref (dest);
6241 }
6242 g_free (filename);
6243 g_free (dest_fs_type);
6244 g_io_scheduler_job_send_to_mainloop_async (io_job,
6245 create_job_done,
6246 job,
6247 NULL((void*)0));
6248
6249 return FALSE(0);
6250}
6251
6252void
6253nautilus_file_operations_new_folder (GtkWidget *parent_view,
6254 GdkPoint *target_point,
6255 const char *parent_dir,
6256 NautilusCreateCallback done_callback,
6257 gpointer done_callback_data)
6258{
6259 CreateJob *job;
6260 GtkWindow *parent_window;
6261
6262 parent_window = NULL((void*)0);
6263 if (parent_view) {
6264 parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW(gtk_window_get_type ()));
6265 }
6266
6267 job = op_job_new (CreateJob, parent_window)((CreateJob *)(init_common (sizeof(CreateJob), parent_window)
))
;
6268 job->done_callback = done_callback;
6269 job->done_callback_data = done_callback_data;
6270 job->dest_dir = g_file_new_for_uri (parent_dir);
6271 job->make_dir = TRUE(!(0));
6272 if (target_point != NULL((void*)0)) {
6273 job->position = *target_point;
6274 job->has_position = TRUE(!(0));
6275 }
6276
6277 if (!nautilus_file_undo_manager_pop_flag ()) {
6278 job->common.undo_info = nautilus_file_undo_info_create_new (NAUTILUS_FILE_UNDO_OP_CREATE_FOLDER);
6279 }
6280
6281 g_io_scheduler_push_job (create_job,
6282 job,
6283 NULL((void*)0), /* destroy notify */
6284 0,
6285 job->common.cancellable);
6286}
6287
6288void
6289nautilus_file_operations_new_file_from_template (GtkWidget *parent_view,
6290 GdkPoint *target_point,
6291 const char *parent_dir,
6292 const char *target_filename,
6293 const char *template_uri,
6294 NautilusCreateCallback done_callback,
6295 gpointer done_callback_data)
6296{
6297 CreateJob *job;
6298 GtkWindow *parent_window;
6299
6300 parent_window = NULL((void*)0);
6301 if (parent_view) {
6302 parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW(gtk_window_get_type ()));
6303 }
6304
6305 job = op_job_new (CreateJob, parent_window)((CreateJob *)(init_common (sizeof(CreateJob), parent_window)
))
;
6306 job->done_callback = done_callback;
6307 job->done_callback_data = done_callback_data;
6308 job->dest_dir = g_file_new_for_uri (parent_dir);
6309 if (target_point != NULL((void*)0)) {
6310 job->position = *target_point;
6311 job->has_position = TRUE(!(0));
6312 }
6313 job->filename = g_strdup (target_filename);
6314
6315 if (template_uri) {
6316 job->src = g_file_new_for_uri (template_uri);
6317 }
6318
6319 if (!nautilus_file_undo_manager_pop_flag ()) {
6320 job->common.undo_info = nautilus_file_undo_info_create_new (NAUTILUS_FILE_UNDO_OP_CREATE_FILE_FROM_TEMPLATE);
6321 }
6322
6323 g_io_scheduler_push_job (create_job,
6324 job,
6325 NULL((void*)0), /* destroy notify */
6326 0,
6327 job->common.cancellable);
6328}
6329
6330void
6331nautilus_file_operations_new_file (GtkWidget *parent_view,
6332 GdkPoint *target_point,
6333 const char *parent_dir,
6334 const char *target_filename,
6335 const char *initial_contents,
6336 int length,
6337 NautilusCreateCallback done_callback,
6338 gpointer done_callback_data)
6339{
6340 CreateJob *job;
6341 GtkWindow *parent_window;
6342
6343 parent_window = NULL((void*)0);
6344 if (parent_view) {
6345 parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW(gtk_window_get_type ()));
6346 }
6347
6348 job = op_job_new (CreateJob, parent_window)((CreateJob *)(init_common (sizeof(CreateJob), parent_window)
))
;
6349 job->done_callback = done_callback;
6350 job->done_callback_data = done_callback_data;
6351 job->dest_dir = g_file_new_for_uri (parent_dir);
6352 if (target_point != NULL((void*)0)) {
6353 job->position = *target_point;
6354 job->has_position = TRUE(!(0));
6355 }
6356 job->src_data = g_memdup (initial_contents, length);
6357 job->length = length;
6358 job->filename = g_strdup (target_filename);
6359
6360 if (!nautilus_file_undo_manager_pop_flag ()) {
6361 job->common.undo_info = nautilus_file_undo_info_create_new (NAUTILUS_FILE_UNDO_OP_CREATE_EMPTY_FILE);
6362 }
6363
6364 g_io_scheduler_push_job (create_job,
6365 job,
6366 NULL((void*)0), /* destroy notify */
6367 0,
6368 job->common.cancellable);
6369}
6370
6371
6372
6373static void
6374delete_trash_file (CommonJob *job,
6375 GFile *file,
6376 gboolean del_file,
6377 gboolean del_children)
6378{
6379 GFileInfo *info;
6380 GFile *child;
6381 GFileEnumerator *enumerator;
6382
6383 if (job_aborted (job)) {
6384 return;
6385 }
6386
6387 if (del_children) {
6388 enumerator = g_file_enumerate_children (file,
6389 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name" ","
6390 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type",
6391 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
6392 job->cancellable,
6393 NULL((void*)0));
6394 if (enumerator) {
6395 while (!job_aborted (job) &&
6396 (info = g_file_enumerator_next_file (enumerator, job->cancellable, NULL((void*)0))) != NULL((void*)0)) {
6397 child = g_file_get_child (file,
6398 g_file_info_get_name (info));
6399 delete_trash_file (job, child, TRUE(!(0)),
6400 g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY);
6401 g_object_unref (child);
6402 g_object_unref (info);
6403 }
6404 g_file_enumerator_close (enumerator, job->cancellable, NULL((void*)0));
6405 g_object_unref (enumerator);
6406 }
6407 }
6408
6409 if (!job_aborted (job) && del_file) {
6410 g_file_delete (file, job->cancellable, NULL((void*)0));
6411 }
6412}
6413
6414static gboolean
6415empty_trash_job_done (gpointer user_data)
6416{
6417 EmptyTrashJob *job;
6418
6419 job = user_data;
6420
6421 g_list_free_full (job->trash_dirs, g_object_unref);
6422
6423 if (job->done_callback) {
6424 job->done_callback (!job_aborted ((CommonJob *) job),
6425 job->done_callback_data);
6426 }
6427
6428 finalize_common ((CommonJob *)job);
6429 return FALSE(0);
6430}
6431
6432static gboolean
6433empty_trash_job (GIOSchedulerJob *io_job,
6434 GCancellable *cancellable,
6435 gpointer user_data)
6436{
6437 EmptyTrashJob *job = user_data;
6438 CommonJob *common;
6439 GList *l;
6440 gboolean confirmed;
6441
6442 common = (CommonJob *)job;
6443 common->io_job = io_job;
6444
6445 nautilus_progress_info_start (job->common.progress);
6446
6447 if (job->should_confirm) {
6448 confirmed = confirm_empty_trash (common);
6449 } else {
6450 confirmed = TRUE(!(0));
6451 }
6452 if (confirmed) {
6453 for (l = job->trash_dirs;
6454 l != NULL((void*)0) && !job_aborted (common);
6455 l = l->next) {
6456 delete_trash_file (common, l->data, FALSE(0), TRUE(!(0)));
6457 }
6458 }
6459
6460 g_io_scheduler_job_send_to_mainloop_async (io_job,
6461 empty_trash_job_done,
6462 job,
6463 NULL((void*)0));
6464
6465 return FALSE(0);
6466}
6467
6468void
6469nautilus_file_operations_empty_trash (GtkWidget *parent_view)
6470{
6471 EmptyTrashJob *job;
6472 GtkWindow *parent_window;
6473
6474 parent_window = NULL((void*)0);
6475 if (parent_view) {
6476 parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW(gtk_window_get_type ()));
6477 }
6478
6479 job = op_job_new (EmptyTrashJob, parent_window)((EmptyTrashJob *)(init_common (sizeof(EmptyTrashJob), parent_window
)))
;
6480 job->trash_dirs = g_list_prepend (job->trash_dirs,
6481 g_file_new_for_uri ("trash:"));
6482 job->should_confirm = TRUE(!(0));
6483
6484 inhibit_power_manager ((CommonJob *)job, _("Emptying Trash")gettext ("Emptying Trash"));
6485
6486 g_io_scheduler_push_job (empty_trash_job,
6487 job,
6488 NULL((void*)0),
6489 0,
6490 NULL((void*)0));
6491}
6492
6493static gboolean
6494mark_trusted_job_done (gpointer user_data)
6495{
6496 MarkTrustedJob *job = user_data;
6497
6498 g_object_unref (job->file);
6499
6500 if (job->done_callback) {
6501 job->done_callback (!job_aborted ((CommonJob *) job),
6502 job->done_callback_data);
6503 }
6504
6505 finalize_common ((CommonJob *)job);
6506 return FALSE(0);
6507}
6508
6509#define TRUSTED_SHEBANG"#!/usr/bin/env xdg-open\n" "#!/usr/bin/env xdg-open\n"
6510
6511static void
6512mark_desktop_file_trusted (CommonJob *common,
6513 GCancellable *cancellable,
6514 GFile *file,
6515 gboolean interactive)
6516{
6517 char *contents, *new_contents;
6518 gsize length, new_length;
6519 GError *error;
6520 guint32 current_perms, new_perms;
6521 int response;
6522 GFileInfo *info;
6523
6524 retry:
6525 error = NULL((void*)0);
6526 if (!g_file_load_contents (file,
6527 cancellable,
6528 &contents, &length,
6529 NULL((void*)0), &error)) {
6530 if (interactive) {
6531 response = run_error (common,
6532 g_strdup (_("Unable to mark launcher trusted (executable)")gettext ("Unable to mark launcher trusted (executable)")),
6533 error->message,
6534 NULL((void*)0),
6535 FALSE(0),
6536 CANCELgettext ("_Cancel"), RETRYgettext ("_Retry"),
6537 NULL((void*)0));
6538 } else {
6539 response = 0;
6540 }
6541
6542
6543 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
6544 abort_job (common);
6545 } else if (response == 1) {
6546 goto retry;
6547 } else {
6548 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 6548, ((const char*) (__func__)), ((void*)0)); } while (0)
;
6549 }
6550
6551 goto out;
6552 }
6553
6554 if (!g_str_has_prefix (contents, "#!")) {
6555 new_length = length + strlen (TRUSTED_SHEBANG"#!/usr/bin/env xdg-open\n");
6556 new_contents = g_malloc (new_length);
6557
6558 strcpy (new_contents, TRUSTED_SHEBANG"#!/usr/bin/env xdg-open\n");
6559 memcpy (new_contents + strlen (TRUSTED_SHEBANG"#!/usr/bin/env xdg-open\n"),
6560 contents, length);
6561
6562 if (!g_file_replace_contents (file,
6563 new_contents,
6564 new_length,
6565 NULL((void*)0),
6566 FALSE(0), 0,
6567 NULL((void*)0), cancellable, &error)) {
6568 g_free (contents);
6569 g_free (new_contents);
6570
6571 if (interactive) {
6572 response = run_error (common,
6573 g_strdup (_("Unable to mark launcher trusted (executable)")gettext ("Unable to mark launcher trusted (executable)")),
6574 error->message,
6575 NULL((void*)0),
6576 FALSE(0),
6577 CANCELgettext ("_Cancel"), RETRYgettext ("_Retry"),
6578 NULL((void*)0));
6579 } else {
6580 response = 0;
6581 }
6582
6583 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
6584 abort_job (common);
6585 } else if (response == 1) {
6586 goto retry;
6587 } else {
6588 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 6588, ((const char*) (__func__)), ((void*)0)); } while (0)
;
6589 }
6590
6591 goto out;
6592 }
6593 g_free (new_contents);
6594
6595 }
6596 g_free (contents);
6597
6598 info = g_file_query_info (file,
6599 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
6600 G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
6601 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
6602 common->cancellable,
6603 &error);
6604
6605 if (info == NULL((void*)0)) {
6606 if (interactive) {
6607 response = run_error (common,
6608 g_strdup (_("Unable to mark launcher trusted (executable)")gettext ("Unable to mark launcher trusted (executable)")),
6609 error->message,
6610 NULL((void*)0),
6611 FALSE(0),
6612 CANCELgettext ("_Cancel"), RETRYgettext ("_Retry"),
6613 NULL((void*)0));
6614 } else {
6615 response = 0;
6616 }
6617
6618 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
6619 abort_job (common);
6620 } else if (response == 1) {
6621 goto retry;
6622 } else {
6623 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 6623, ((const char*) (__func__)), ((void*)0)); } while (0)
;
6624 }
6625
6626 goto out;
6627 }
6628
6629
6630 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode")) {
6631 current_perms = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");
6632 new_perms = current_perms | S_IXGRP(0100 >> 3) | S_IXUSR0100 | S_IXOTH((0100 >> 3) >> 3);
6633
6634 if ((current_perms != new_perms) &&
6635 !g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
6636 new_perms, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
6637 common->cancellable, &error))
6638 {
6639 g_object_unref (info);
6640
6641 if (interactive) {
6642 response = run_error (common,
6643 g_strdup (_("Unable to mark launcher trusted (executable)")gettext ("Unable to mark launcher trusted (executable)")),
6644 error->message,
6645 NULL((void*)0),
6646 FALSE(0),
6647 CANCELgettext ("_Cancel"), RETRYgettext ("_Retry"),
6648 NULL((void*)0));
6649 } else {
6650 response = 0;
6651 }
6652
6653 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
6654 abort_job (common);
6655 } else if (response == 1) {
6656 goto retry;
6657 } else {
6658 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "nautilus-file-operations.c"
, 6658, ((const char*) (__func__)), ((void*)0)); } while (0)
;
6659 }
6660
6661 goto out;
6662 }
6663 }
6664 g_object_unref (info);
6665 out:
6666 ;
6667}
6668
6669static gboolean
6670mark_trusted_job (GIOSchedulerJob *io_job,
6671 GCancellable *cancellable,
6672 gpointer user_data)
6673{
6674 MarkTrustedJob *job = user_data;
6675 CommonJob *common;
6676
6677 common = (CommonJob *)job;
6678 common->io_job = io_job;
6679
6680 nautilus_progress_info_start (job->common.progress);
6681
6682 mark_desktop_file_trusted (common,
6683 cancellable,
6684 job->file,
6685 job->interactive);
6686
6687 g_io_scheduler_job_send_to_mainloop_async (io_job,
6688 mark_trusted_job_done,
6689 job,
6690 NULL((void*)0));
6691
6692 return FALSE(0);
6693}
6694
6695void
6696nautilus_file_mark_desktop_file_trusted (GFile *file,
6697 GtkWindow *parent_window,
6698 gboolean interactive,
6699 NautilusOpCallback done_callback,
6700 gpointer done_callback_data)
6701{
6702 MarkTrustedJob *job;
6703
6704 job = op_job_new (MarkTrustedJob, parent_window)((MarkTrustedJob *)(init_common (sizeof(MarkTrustedJob), parent_window
)))
;
6705 job->file = g_object_ref (file);
6706 job->interactive = interactive;
6707 job->done_callback = done_callback;
6708 job->done_callback_data = done_callback_data;
6709
6710 g_io_scheduler_push_job (mark_trusted_job,
6711 job,
6712 NULL((void*)0),
6713 0,
6714 NULL((void*)0));
6715}
6716
6717#if !defined (NAUTILUS_OMIT_SELF_CHECK1)
6718
6719void
6720nautilus_self_check_file_operations (void)
6721{
6722 setlocale (LC_MESSAGES5, "C");
6723
6724
6725 /* test the next duplicate name generator */
6726 EEL_CHECK_STRING_RESULT (get_duplicate_name (" (copy)", 1, -1), " (another copy)")do { eel_before_check ("get_duplicate_name (\" (copy)\", 1, -1)"
, "nautilus-file-operations.c", 6726); eel_check_string_result
(get_duplicate_name (" (copy)", 1, -1), " (another copy)"); }
while (0)
;
6727 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo", 1, -1), "foo (copy)")do { eel_before_check ("get_duplicate_name (\"foo\", 1, -1)",
"nautilus-file-operations.c", 6727); eel_check_string_result
(get_duplicate_name ("foo", 1, -1), "foo (copy)"); } while (
0)
;
6728 EEL_CHECK_STRING_RESULT (get_duplicate_name (".bashrc", 1, -1), ".bashrc (copy)")do { eel_before_check ("get_duplicate_name (\".bashrc\", 1, -1)"
, "nautilus-file-operations.c", 6728); eel_check_string_result
(get_duplicate_name (".bashrc", 1, -1), ".bashrc (copy)"); }
while (0)
;
6729 EEL_CHECK_STRING_RESULT (get_duplicate_name (".foo.txt", 1, -1), ".foo (copy).txt")do { eel_before_check ("get_duplicate_name (\".foo.txt\", 1, -1)"
, "nautilus-file-operations.c", 6729); eel_check_string_result
(get_duplicate_name (".foo.txt", 1, -1), ".foo (copy).txt");
} while (0)
;
6730 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo", 1, -1), "foo foo (copy)")do { eel_before_check ("get_duplicate_name (\"foo foo\", 1, -1)"
, "nautilus-file-operations.c", 6730); eel_check_string_result
(get_duplicate_name ("foo foo", 1, -1), "foo foo (copy)"); }
while (0)
;
6731 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo.txt", 1, -1), "foo (copy).txt")do { eel_before_check ("get_duplicate_name (\"foo.txt\", 1, -1)"
, "nautilus-file-operations.c", 6731); eel_check_string_result
(get_duplicate_name ("foo.txt", 1, -1), "foo (copy).txt"); }
while (0)
;
6732 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo.txt", 1, -1), "foo foo (copy).txt")do { eel_before_check ("get_duplicate_name (\"foo foo.txt\", 1, -1)"
, "nautilus-file-operations.c", 6732); eel_check_string_result
(get_duplicate_name ("foo foo.txt", 1, -1), "foo foo (copy).txt"
); } while (0)
;
6733 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo.txt txt", 1, -1), "foo foo (copy).txt txt")do { eel_before_check ("get_duplicate_name (\"foo foo.txt txt\", 1, -1)"
, "nautilus-file-operations.c", 6733); eel_check_string_result
(get_duplicate_name ("foo foo.txt txt", 1, -1), "foo foo (copy).txt txt"
); } while (0)
;
6734 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo...txt", 1, -1), "foo.. (copy).txt")do { eel_before_check ("get_duplicate_name (\"foo...txt\", 1, -1)"
, "nautilus-file-operations.c", 6734); eel_check_string_result
(get_duplicate_name ("foo...txt", 1, -1), "foo.. (copy).txt"
); } while (0)
;
6735 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo...", 1, -1), "foo... (copy)")do { eel_before_check ("get_duplicate_name (\"foo...\", 1, -1)"
, "nautilus-file-operations.c", 6735); eel_check_string_result
(get_duplicate_name ("foo...", 1, -1), "foo... (copy)"); } while
(0)
;
6736 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo. (copy)", 1, -1), "foo. (another copy)")do { eel_before_check ("get_duplicate_name (\"foo. (copy)\", 1, -1)"
, "nautilus-file-operations.c", 6736); eel_check_string_result
(get_duplicate_name ("foo. (copy)", 1, -1), "foo. (another copy)"
); } while (0)
;
6737 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (copy)", 1, -1), "foo (another copy)")do { eel_before_check ("get_duplicate_name (\"foo (copy)\", 1, -1)"
, "nautilus-file-operations.c", 6737); eel_check_string_result
(get_duplicate_name ("foo (copy)", 1, -1), "foo (another copy)"
); } while (0)
;
6738 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (copy).txt", 1, -1), "foo (another copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (copy).txt\", 1, -1)"
, "nautilus-file-operations.c", 6738); eel_check_string_result
(get_duplicate_name ("foo (copy).txt", 1, -1), "foo (another copy).txt"
); } while (0)
;
6739 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (another copy)", 1, -1), "foo (3rd copy)")do { eel_before_check ("get_duplicate_name (\"foo (another copy)\", 1, -1)"
, "nautilus-file-operations.c", 6739); eel_check_string_result
(get_duplicate_name ("foo (another copy)", 1, -1), "foo (3rd copy)"
); } while (0)
;
6740 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (another copy).txt", 1, -1), "foo (3rd copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (another copy).txt\", 1, -1)"
, "nautilus-file-operations.c", 6740); eel_check_string_result
(get_duplicate_name ("foo (another copy).txt", 1, -1), "foo (3rd copy).txt"
); } while (0)
;
6741 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (another copy).txt", 1, -1), "foo foo (3rd copy).txt")do { eel_before_check ("get_duplicate_name (\"foo foo (another copy).txt\", 1, -1)"
, "nautilus-file-operations.c", 6741); eel_check_string_result
(get_duplicate_name ("foo foo (another copy).txt", 1, -1), "foo foo (3rd copy).txt"
); } while (0)
;
6742 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (13th copy)", 1, -1), "foo (14th copy)")do { eel_before_check ("get_duplicate_name (\"foo (13th copy)\", 1, -1)"
, "nautilus-file-operations.c", 6742); eel_check_string_result
(get_duplicate_name ("foo (13th copy)", 1, -1), "foo (14th copy)"
); } while (0)
;
6743 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (13th copy).txt", 1, -1), "foo (14th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (13th copy).txt\", 1, -1)"
, "nautilus-file-operations.c", 6743); eel_check_string_result
(get_duplicate_name ("foo (13th copy).txt", 1, -1), "foo (14th copy).txt"
); } while (0)
;
6744 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (21st copy)", 1, -1), "foo (22nd copy)")do { eel_before_check ("get_duplicate_name (\"foo (21st copy)\", 1, -1)"
, "nautilus-file-operations.c", 6744); eel_check_string_result
(get_duplicate_name ("foo (21st copy)", 1, -1), "foo (22nd copy)"
); } while (0)
;
6745 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (21st copy).txt", 1, -1), "foo (22nd copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (21st copy).txt\", 1, -1)"
, "nautilus-file-operations.c", 6745); eel_check_string_result
(get_duplicate_name ("foo (21st copy).txt", 1, -1), "foo (22nd copy).txt"
); } while (0)
;
6746 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (22nd copy)", 1, -1), "foo (23rd copy)")do { eel_before_check ("get_duplicate_name (\"foo (22nd copy)\", 1, -1)"
, "nautilus-file-operations.c", 6746); eel_check_string_result
(get_duplicate_name ("foo (22nd copy)", 1, -1), "foo (23rd copy)"
); } while (0)
;
6747 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (22nd copy).txt", 1, -1), "foo (23rd copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (22nd copy).txt\", 1, -1)"
, "nautilus-file-operations.c", 6747); eel_check_string_result
(get_duplicate_name ("foo (22nd copy).txt", 1, -1), "foo (23rd copy).txt"
); } while (0)
;
6748 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (23rd copy)", 1, -1), "foo (24th copy)")do { eel_before_check ("get_duplicate_name (\"foo (23rd copy)\", 1, -1)"
, "nautilus-file-operations.c", 6748); eel_check_string_result
(get_duplicate_name ("foo (23rd copy)", 1, -1), "foo (24th copy)"
); } while (0)
;
6749 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (23rd copy).txt", 1, -1), "foo (24th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (23rd copy).txt\", 1, -1)"
, "nautilus-file-operations.c", 6749); eel_check_string_result
(get_duplicate_name ("foo (23rd copy).txt", 1, -1), "foo (24th copy).txt"
); } while (0)
;
6750 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (24th copy)", 1, -1), "foo (25th copy)")do { eel_before_check ("get_duplicate_name (\"foo (24th copy)\", 1, -1)"
, "nautilus-file-operations.c", 6750); eel_check_string_result
(get_duplicate_name ("foo (24th copy)", 1, -1), "foo (25th copy)"
); } while (0)
;
6751 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (24th copy).txt", 1, -1), "foo (25th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (24th copy).txt\", 1, -1)"
, "nautilus-file-operations.c", 6751); eel_check_string_result
(get_duplicate_name ("foo (24th copy).txt", 1, -1), "foo (25th copy).txt"
); } while (0)
;
6752 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (24th copy)", 1, -1), "foo foo (25th copy)")do { eel_before_check ("get_duplicate_name (\"foo foo (24th copy)\", 1, -1)"
, "nautilus-file-operations.c", 6752); eel_check_string_result
(get_duplicate_name ("foo foo (24th copy)", 1, -1), "foo foo (25th copy)"
); } while (0)
;
6753 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (24th copy).txt", 1, -1), "foo foo (25th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo foo (24th copy).txt\", 1, -1)"
, "nautilus-file-operations.c", 6753); eel_check_string_result
(get_duplicate_name ("foo foo (24th copy).txt", 1, -1), "foo foo (25th copy).txt"
); } while (0)
;
6754 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (100000000000000th copy).txt", 1, -1), "foo foo (copy).txt")do { eel_before_check ("get_duplicate_name (\"foo foo (100000000000000th copy).txt\", 1, -1)"
, "nautilus-file-operations.c", 6754); eel_check_string_result
(get_duplicate_name ("foo foo (100000000000000th copy).txt",
1, -1), "foo foo (copy).txt"); } while (0)
;
6755 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (10th copy)", 1, -1), "foo (11th copy)")do { eel_before_check ("get_duplicate_name (\"foo (10th copy)\", 1, -1)"
, "nautilus-file-operations.c", 6755); eel_check_string_result
(get_duplicate_name ("foo (10th copy)", 1, -1), "foo (11th copy)"
); } while (0)
;
6756 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (10th copy).txt", 1, -1), "foo (11th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (10th copy).txt\", 1, -1)"
, "nautilus-file-operations.c", 6756); eel_check_string_result
(get_duplicate_name ("foo (10th copy).txt", 1, -1), "foo (11th copy).txt"
); } while (0)
;
6757 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (11th copy)", 1, -1), "foo (12th copy)")do { eel_before_check ("get_duplicate_name (\"foo (11th copy)\", 1, -1)"
, "nautilus-file-operations.c", 6757); eel_check_string_result
(get_duplicate_name ("foo (11th copy)", 1, -1), "foo (12th copy)"
); } while (0)
;
6758 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (11th copy).txt", 1, -1), "foo (12th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (11th copy).txt\", 1, -1)"
, "nautilus-file-operations.c", 6758); eel_check_string_result
(get_duplicate_name ("foo (11th copy).txt", 1, -1), "foo (12th copy).txt"
); } while (0)
;
6759 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (12th copy)", 1, -1), "foo (13th copy)")do { eel_before_check ("get_duplicate_name (\"foo (12th copy)\", 1, -1)"
, "nautilus-file-operations.c", 6759); eel_check_string_result
(get_duplicate_name ("foo (12th copy)", 1, -1), "foo (13th copy)"
); } while (0)
;
6760 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (12th copy).txt", 1, -1), "foo (13th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (12th copy).txt\", 1, -1)"
, "nautilus-file-operations.c", 6760); eel_check_string_result
(get_duplicate_name ("foo (12th copy).txt", 1, -1), "foo (13th copy).txt"
); } while (0)
;
6761 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (110th copy)", 1, -1), "foo (111th copy)")do { eel_before_check ("get_duplicate_name (\"foo (110th copy)\", 1, -1)"
, "nautilus-file-operations.c", 6761); eel_check_string_result
(get_duplicate_name ("foo (110th copy)", 1, -1), "foo (111th copy)"
); } while (0)
;
6762 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (110th copy).txt", 1, -1), "foo (111th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (110th copy).txt\", 1, -1)"
, "nautilus-file-operations.c", 6762); eel_check_string_result
(get_duplicate_name ("foo (110th copy).txt", 1, -1), "foo (111th copy).txt"
); } while (0)
;
6763 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (122nd copy)", 1, -1), "foo (123rd copy)")do { eel_before_check ("get_duplicate_name (\"foo (122nd copy)\", 1, -1)"
, "nautilus-file-operations.c", 6763); eel_check_string_result
(get_duplicate_name ("foo (122nd copy)", 1, -1), "foo (123rd copy)"
); } while (0)
;
6764 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (122nd copy).txt", 1, -1), "foo (123rd copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (122nd copy).txt\", 1, -1)"
, "nautilus-file-operations.c", 6764); eel_check_string_result
(get_duplicate_name ("foo (122nd copy).txt", 1, -1), "foo (123rd copy).txt"
); } while (0)
;
6765 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (123rd copy)", 1, -1), "foo (124th copy)")do { eel_before_check ("get_duplicate_name (\"foo (123rd copy)\", 1, -1)"
, "nautilus-file-operations.c", 6765); eel_check_string_result
(get_duplicate_name ("foo (123rd copy)", 1, -1), "foo (124th copy)"
); } while (0)
;
6766 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (123rd copy).txt", 1, -1), "foo (124th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (123rd copy).txt\", 1, -1)"
, "nautilus-file-operations.c", 6766); eel_check_string_result
(get_duplicate_name ("foo (123rd copy).txt", 1, -1), "foo (124th copy).txt"
); } while (0)
;
6767
6768 setlocale (LC_MESSAGES5, "");
6769}
6770
6771#endif