File: | nautilus-file-operations.c |
Location: | line 5584, column 32 |
Description: | Access to field 'data' results in a dereference of a null pointer (loaded from variable 'files') |
1 | /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ | |||
2 | ||||
3 | /* nautilus-file-operations.c - Nautilus file operations. | |||
4 | ||||
5 | Copyright (C) 1999, 2000 Free Software Foundation | |||
6 | Copyright (C) 2000, 2001 Eazel, Inc. | |||
7 | Copyright (C) 2007 Red Hat, Inc. | |||
8 | ||||
9 | This program is free software; you can redistribute it and/or | |||
10 | modify it under the terms of the GNU General Public License as | |||
11 | published by the Free Software Foundation; either version 2 of the | |||
12 | License, or (at your option) any later version. | |||
13 | ||||
14 | This program is distributed in the hope that it will be useful, | |||
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
17 | General Public License for more details. | |||
18 | ||||
19 | You should have received a copy of the GNU General Public | |||
20 | License along with this program; if not, write to the | |||
21 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |||
22 | Boston, MA 02111-1307, USA. | |||
23 | ||||
24 | Authors: Alexander Larsson <alexl@redhat.com> | |||
25 | Ettore Perazzoli <ettore@gnu.org> | |||
26 | Pavel Cisler <pavel@eazel.com> | |||
27 | */ | |||
28 | ||||
29 | #include <config.h> | |||
30 | #include <string.h> | |||
31 | #include <stdio.h> | |||
32 | #include <stdarg.h> | |||
33 | #include <locale.h> | |||
34 | #include <math.h> | |||
35 | #include <unistd.h> | |||
36 | #include <sys/types.h> | |||
37 | #include <stdlib.h> | |||
38 | ||||
39 | #include "nautilus-file-operations.h" | |||
40 | ||||
41 | #include "nautilus-file-changes-queue.h" | |||
42 | #include "nautilus-lib-self-check-functions.h" | |||
43 | ||||
44 | #include "nautilus-progress-info.h" | |||
45 | ||||
46 | #include <eel/eel-glib-extensions.h> | |||
47 | #include <eel/eel-gtk-extensions.h> | |||
48 | #include <eel/eel-stock-dialogs.h> | |||
49 | #include <eel/eel-vfs-extensions.h> | |||
50 | ||||
51 | #include <glib/gi18n.h> | |||
52 | #include <glib/gstdio.h> | |||
53 | #include <gdk/gdk.h> | |||
54 | #include <gtk/gtk.h> | |||
55 | #include <gio/gio.h> | |||
56 | #include <glib.h> | |||
57 | #include "nautilus-file-changes-queue.h" | |||
58 | #include "nautilus-file-private.h" | |||
59 | #include "nautilus-desktop-icon-file.h" | |||
60 | #include "nautilus-desktop-link-monitor.h" | |||
61 | #include "nautilus-global-preferences.h" | |||
62 | #include "nautilus-link.h" | |||
63 | #include "nautilus-trash-monitor.h" | |||
64 | #include "nautilus-file-utilities.h" | |||
65 | #include "nautilus-file-conflict-dialog.h" | |||
66 | #include "nautilus-file-undo-operations.h" | |||
67 | #include "nautilus-file-undo-manager.h" | |||
68 | ||||
69 | /* TODO: TESTING!!! */ | |||
70 | ||||
71 | typedef struct { | |||
72 | GIOSchedulerJob *io_job; | |||
73 | GTimer *time; | |||
74 | GtkWindow *parent_window; | |||
75 | int screen_num; | |||
76 | int inhibit_cookie; | |||
77 | NautilusProgressInfo *progress; | |||
78 | GCancellable *cancellable; | |||
79 | GHashTable *skip_files; | |||
80 | GHashTable *skip_readdir_error; | |||
81 | NautilusFileUndoInfo *undo_info; | |||
82 | gboolean skip_all_error; | |||
83 | gboolean skip_all_conflict; | |||
84 | gboolean merge_all; | |||
85 | gboolean replace_all; | |||
86 | gboolean delete_all; | |||
87 | } CommonJob; | |||
88 | ||||
89 | typedef struct { | |||
90 | CommonJob common; | |||
91 | gboolean is_move; | |||
92 | GList *files; | |||
93 | GFile *destination; | |||
94 | GFile *desktop_location; | |||
95 | GFile *fake_display_source; | |||
96 | GdkPoint *icon_positions; | |||
97 | int n_icon_positions; | |||
98 | GHashTable *debuting_files; | |||
99 | gchar *target_name; | |||
100 | NautilusCopyCallback done_callback; | |||
101 | gpointer done_callback_data; | |||
102 | } CopyMoveJob; | |||
103 | ||||
104 | typedef struct { | |||
105 | CommonJob common; | |||
106 | GList *files; | |||
107 | gboolean try_trash; | |||
108 | gboolean user_cancel; | |||
109 | NautilusDeleteCallback done_callback; | |||
110 | gpointer done_callback_data; | |||
111 | } DeleteJob; | |||
112 | ||||
113 | typedef struct { | |||
114 | CommonJob common; | |||
115 | GFile *dest_dir; | |||
116 | char *filename; | |||
117 | gboolean make_dir; | |||
118 | GFile *src; | |||
119 | char *src_data; | |||
120 | int length; | |||
121 | GdkPoint position; | |||
122 | gboolean has_position; | |||
123 | GFile *created_file; | |||
124 | NautilusCreateCallback done_callback; | |||
125 | gpointer done_callback_data; | |||
126 | } CreateJob; | |||
127 | ||||
128 | ||||
129 | typedef struct { | |||
130 | CommonJob common; | |||
131 | GList *trash_dirs; | |||
132 | gboolean should_confirm; | |||
133 | NautilusOpCallback done_callback; | |||
134 | gpointer done_callback_data; | |||
135 | } EmptyTrashJob; | |||
136 | ||||
137 | typedef struct { | |||
138 | CommonJob common; | |||
139 | GFile *file; | |||
140 | gboolean interactive; | |||
141 | NautilusOpCallback done_callback; | |||
142 | gpointer done_callback_data; | |||
143 | } MarkTrustedJob; | |||
144 | ||||
145 | typedef struct { | |||
146 | CommonJob common; | |||
147 | GFile *file; | |||
148 | NautilusOpCallback done_callback; | |||
149 | gpointer done_callback_data; | |||
150 | guint32 file_permissions; | |||
151 | guint32 file_mask; | |||
152 | guint32 dir_permissions; | |||
153 | guint32 dir_mask; | |||
154 | } SetPermissionsJob; | |||
155 | ||||
156 | typedef enum { | |||
157 | OP_KIND_COPY, | |||
158 | OP_KIND_MOVE, | |||
159 | OP_KIND_DELETE, | |||
160 | OP_KIND_TRASH | |||
161 | } OpKind; | |||
162 | ||||
163 | typedef struct { | |||
164 | int num_files; | |||
165 | goffset num_bytes; | |||
166 | int num_files_since_progress; | |||
167 | OpKind op; | |||
168 | } SourceInfo; | |||
169 | ||||
170 | typedef struct { | |||
171 | int num_files; | |||
172 | goffset num_bytes; | |||
173 | OpKind op; | |||
174 | guint64 last_report_time; | |||
175 | int last_reported_files_left; | |||
176 | } TransferInfo; | |||
177 | ||||
178 | #define SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_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 | ||||
197 | static void | |||
198 | mark_desktop_file_trusted (CommonJob *common, | |||
199 | GCancellable *cancellable, | |||
200 | GFile *file, | |||
201 | gboolean interactive); | |||
202 | ||||
203 | static gboolean | |||
204 | is_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 | ||||
214 | static void scan_sources (GList *files, | |||
215 | SourceInfo *source_info, | |||
216 | CommonJob *job, | |||
217 | OpKind kind); | |||
218 | ||||
219 | ||||
220 | static gboolean empty_trash_job (GIOSchedulerJob *io_job, | |||
221 | GCancellable *cancellable, | |||
222 | gpointer user_data); | |||
223 | ||||
224 | static 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 | */ | |||
234 | static int | |||
235 | seconds_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 | ||||
267 | static char * | |||
268 | format_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 | ||||
308 | static char * | |||
309 | shorten_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 | ||||
350 | static char * | |||
351 | get_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 */ | |||
450 | static const char untranslated_copy_duplicate_tag[] = N_(" (copy)")(" (copy)"); | |||
451 | /* localizers: tag used to detect the second copy of a file */ | |||
452 | static 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 */ | |||
455 | static const char untranslated_x11th_copy_duplicate_tag[] = N_("th copy)")("th copy)"); | |||
456 | /* localizers: tag used to detect the x12th copy of a file */ | |||
457 | static const char untranslated_x12th_copy_duplicate_tag[] = N_("th copy)")("th copy)"); | |||
458 | /* localizers: tag used to detect the x13th copy of a file */ | |||
459 | static 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 */ | |||
462 | static const char untranslated_st_copy_duplicate_tag[] = N_("st copy)")("st copy)"); | |||
463 | /* localizers: tag used to detect the x2nd copy of a file */ | |||
464 | static const char untranslated_nd_copy_duplicate_tag[] = N_("nd copy)")("nd copy)"); | |||
465 | /* localizers: tag used to detect the x3rd copy of a file */ | |||
466 | static 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 */ | |||
469 | static 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 */ | |||
483 | static const char untranslated_first_copy_duplicate_format[] = N_("%s (copy)%s")("%s (copy)%s"); | |||
484 | /* localizers: appended to second file copy */ | |||
485 | static const char untranslated_second_copy_duplicate_format[] = N_("%s (another copy)%s")("%s (another copy)%s"); | |||
486 | ||||
487 | /* localizers: appended to x11th file copy */ | |||
488 | static const char untranslated_x11th_copy_duplicate_format[] = N_("%s (%'dth copy)%s")("%s (%'dth copy)%s"); | |||
489 | /* localizers: appended to x12th file copy */ | |||
490 | static const char untranslated_x12th_copy_duplicate_format[] = N_("%s (%'dth copy)%s")("%s (%'dth copy)%s"); | |||
491 | /* localizers: appended to x13th file copy */ | |||
492 | static 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 */ | |||
500 | static const char untranslated_st_copy_duplicate_format[] = N_("%s (%'dst copy)%s")("%s (%'dst copy)%s"); | |||
501 | /* localizers: appended to x2nd file copy */ | |||
502 | static const char untranslated_nd_copy_duplicate_format[] = N_("%s (%'dnd copy)%s")("%s (%'dnd copy)%s"); | |||
503 | /* localizers: appended to x3rd file copy */ | |||
504 | static const char untranslated_rd_copy_duplicate_format[] = N_("%s (%'drd copy)%s")("%s (%'drd copy)%s"); | |||
505 | /* localizers: appended to xxth file copy */ | |||
506 | static 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 | ||||
519 | static char * | |||
520 | extract_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 | */ | |||
538 | static void | |||
539 | parse_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 | ||||
634 | static char * | |||
635 | make_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 | ||||
737 | static char * | |||
738 | get_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 | ||||
753 | static gboolean | |||
754 | has_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 | ||||
775 | static char * | |||
776 | custom_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 | ||||
785 | static void | |||
786 | custom_full_name_skip (va_list *va) | |||
787 | { | |||
788 | (void) va_arg (*va, GFile *)__builtin_va_arg(*va, GFile *); | |||
789 | } | |||
790 | ||||
791 | static char * | |||
792 | custom_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 | ||||
840 | static void | |||
841 | custom_basename_skip (va_list *va) | |||
842 | { | |||
843 | (void) va_arg (*va, GFile *)__builtin_va_arg(*va, GFile *); | |||
844 | } | |||
845 | ||||
846 | ||||
847 | static char * | |||
848 | custom_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 | ||||
856 | static void | |||
857 | custom_size_skip (va_list *va) | |||
858 | { | |||
859 | (void) va_arg (*va, goffset)__builtin_va_arg(*va, goffset); | |||
860 | } | |||
861 | ||||
862 | static char * | |||
863 | custom_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 | ||||
871 | static void | |||
872 | custom_time_skip (va_list *va) | |||
873 | { | |||
874 | (void) va_arg (*va, int)__builtin_va_arg(*va, int); | |||
875 | } | |||
876 | ||||
877 | static char * | |||
878 | custom_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 | ||||
886 | static void | |||
887 | custom_mount_skip (va_list *va) | |||
888 | { | |||
889 | (void) va_arg (*va, GMount *)__builtin_va_arg(*va, GMount *); | |||
890 | } | |||
891 | ||||
892 | ||||
893 | static 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 | ||||
903 | static char * | |||
904 | f (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 | ||||
917 | static gpointer | |||
918 | init_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 | ||||
945 | static void | |||
946 | finalize_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 | ||||
980 | static void | |||
981 | skip_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 | ||||
992 | static void | |||
993 | skip_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 | ||||
1004 | static gboolean | |||
1005 | should_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 | ||||
1014 | static gboolean | |||
1015 | should_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 | ||||
1024 | static gboolean | |||
1025 | can_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 | ||||
1036 | static gboolean | |||
1037 | can_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 | ||||
1052 | typedef 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 | ||||
1065 | static gboolean | |||
1066 | do_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 | ||||
1120 | static int | |||
1121 | run_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 */ | |||
1173 | static int | |||
1174 | run_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 | ||||
1198 | static int | |||
1199 | run_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 | ||||
1222 | static int | |||
1223 | run_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 | ||||
1246 | static int | |||
1247 | run_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 | ||||
1270 | static int | |||
1271 | run_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 | ||||
1301 | static void | |||
1302 | inhibit_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 | ||||
1311 | static void | |||
1312 | abort_job (CommonJob *job) | |||
1313 | { | |||
1314 | /* destroy the undo action data too */ | |||
1315 | g_clear_object (&job->undo_info)do { typedef char _GStaticAssertCompileTimeAssertion_18[(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_19 [(sizeof *(_pp) == sizeof (gpointer)) ? 1 : -1] __attribute__ ((__unused__)); __sync_synchronize (); (gpointer) *(_pp); })) ; while (!(__extension__ ({ typedef char _GStaticAssertCompileTimeAssertion_20 [(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 | ||||
1320 | static gboolean | |||
1321 | job_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 */ | |||
1327 | static gboolean | |||
1328 | should_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 | ||||
1339 | static gboolean | |||
1340 | confirm_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 | ||||
1378 | static gboolean | |||
1379 | confirm_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 | ||||
1402 | static gboolean | |||
1403 | confirm_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 | ||||
1444 | static void | |||
1445 | report_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 | ||||
1507 | static void delete_file (CommonJob *job, GFile *file, | |||
1508 | gboolean *skipped_file, | |||
1509 | SourceInfo *source_info, | |||
1510 | TransferInfo *transfer_info, | |||
1511 | gboolean toplevel); | |||
1512 | ||||
1513 | static void | |||
1514 | delete_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 | ||||
1666 | static void | |||
1667 | delete_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 | ||||
1732 | static void | |||
1733 | delete_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 | ||||
1774 | static void | |||
1775 | report_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 | ||||
1799 | static void | |||
1800 | trash_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 | ||||
1893 | static gboolean | |||
1894 | delete_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 | ||||
1916 | static gboolean | |||
1917 | delete_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 | ||||
2000 | static void | |||
2001 | trash_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 | ||||
2035 | void | |||
2036 | nautilus_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 | ||||
2046 | void | |||
2047 | nautilus_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 | ||||
2059 | typedef 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 | ||||
2068 | static void | |||
2069 | unmount_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_21[(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_22[(sizeof *(_pp) == sizeof (gpointer)) ? 1 : -1] __attribute__((__unused__ )); __sync_synchronize (); (gpointer) *(_pp); })); while (!(__extension__ ({ typedef char _GStaticAssertCompileTimeAssertion_23[(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 | ||||
2081 | static void | |||
2082 | unmount_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 | ||||
2125 | static void | |||
2126 | do_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 | ||||
2153 | static gboolean | |||
2154 | dir_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 | ||||
2181 | static GList * | |||
2182 | get_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 | ||||
2221 | static gboolean | |||
2222 | has_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 | ||||
2247 | static gint | |||
2248 | prompt_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 | ||||
2295 | static void | |||
2296 | empty_trash_for_unmount_done (gboolean success, | |||
2297 | gpointer user_data) | |||
2298 | { | |||
2299 | UnmountData *data = user_data; | |||
2300 | do_unmount (data); | |||
2301 | } | |||
2302 | ||||
2303 | void | |||
2304 | nautilus_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 | ||||
2360 | void | |||
2361 | nautilus_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 | ||||
2370 | static void | |||
2371 | mount_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 | ||||
2381 | static void | |||
2382 | volume_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 | ||||
2435 | void | |||
2436 | nautilus_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 | ||||
2443 | void | |||
2444 | nautilus_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 | ||||
2470 | static void | |||
2471 | report_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 | ||||
2508 | static void | |||
2509 | count_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 | ||||
2522 | static char * | |||
2523 | get_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 | ||||
2538 | static void | |||
2539 | scan_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 | ||||
2661 | static void | |||
2662 | scan_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 | ||||
2748 | static void | |||
2749 | scan_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 | ||||
2774 | static void | |||
2775 | verify_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 | ||||
2945 | static void | |||
2946 | report_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 | ||||
3070 | static int | |||
3071 | get_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 | ||||
3111 | static gboolean | |||
3112 | fat_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 | ||||
3130 | static gboolean | |||
3131 | make_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 | ||||
3160 | static GFile * | |||
3161 | get_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 | ||||
3219 | static GFile * | |||
3220 | get_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 | ||||
3278 | static GFile * | |||
3279 | get_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 | ||||
3338 | static GFile * | |||
3339 | get_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 | ||||
3347 | static gboolean | |||
3348 | has_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 | ||||
3373 | static gboolean | |||
3374 | is_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 | ||||
3392 | static 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 | ||||
3406 | typedef enum { | |||
3407 | CREATE_DEST_DIR_RETRY, | |||
3408 | CREATE_DEST_DIR_FAILED, | |||
3409 | CREATE_DEST_DIR_SUCCESS | |||
3410 | } CreateDestDirResult; | |||
3411 | ||||
3412 | static CreateDestDirResult | |||
3413 | create_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 | */ | |||
3509 | static gboolean | |||
3510 | copy_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 | ||||
3723 | static gboolean | |||
3724 | remove_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 | ||||
3850 | typedef struct { | |||
3851 | CopyMoveJob *job; | |||
3852 | goffset last_size; | |||
3853 | SourceInfo *source_info; | |||
3854 | TransferInfo *transfer_info; | |||
3855 | } ProgressData; | |||
3856 | ||||
3857 | static void | |||
3858 | copy_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 | ||||
3878 | static gboolean | |||
3879 | test_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 | ||||
3899 | static char * | |||
3900 | query_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 | ||||
3927 | static gboolean | |||
3928 | is_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 | ||||
3973 | typedef struct { | |||
3974 | int id; | |||
3975 | char *new_name; | |||
3976 | gboolean apply_to_all; | |||
3977 | } ConflictResponseData; | |||
3978 | ||||
3979 | typedef struct { | |||
3980 | GFile *src; | |||
3981 | GFile *dest; | |||
3982 | GFile *dest_dir; | |||
3983 | GtkWindow *parent; | |||
3984 | ConflictResponseData *resp_data; | |||
3985 | } ConflictDialogData; | |||
3986 | ||||
3987 | static gboolean | |||
3988 | do_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 | ||||
4017 | static ConflictResponseData * | |||
4018 | run_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 | ||||
4052 | static void | |||
4053 | conflict_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 | ||||
4059 | static GFile * | |||
4060 | get_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 */ | |||
4076 | static void | |||
4077 | copy_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 | ||||
4479 | static void | |||
4480 | copy_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 | ||||
4559 | static gboolean | |||
4560 | copy_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_24[(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_25[(sizeof *(_pp) == sizeof (gpointer)) ? 1 : -1] __attribute__((__unused__ )); __sync_synchronize (); (gpointer) *(_pp); })); while (!(__extension__ ({ typedef char _GStaticAssertCompileTimeAssertion_26[(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 | ||||
4590 | static gboolean | |||
4591 | copy_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 | ||||
4655 | void | |||
4656 | nautilus_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 | ||||
4692 | void | |||
4693 | nautilus_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 | ||||
4737 | static void | |||
4738 | report_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 | ||||
4756 | typedef struct { | |||
4757 | GFile *file; | |||
4758 | gboolean overwrite; | |||
4759 | gboolean has_position; | |||
4760 | GdkPoint position; | |||
4761 | } MoveFileCopyFallback; | |||
4762 | ||||
4763 | static MoveFileCopyFallback * | |||
4764 | move_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 | ||||
4783 | static GList * | |||
4784 | get_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 | ||||
4797 | static void | |||
4798 | move_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 | ||||
5021 | static void | |||
5022 | move_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 | ||||
5074 | static void | |||
5075 | move_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; | |||
5090 | common = &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 | ||||
5125 | static gboolean | |||
5126 | move_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 | ||||
5148 | static gboolean | |||
5149 | move_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 | ||||
5230 | void | |||
5231 | nautilus_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 | ||||
5282 | static void | |||
5283 | report_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 | ||||
5301 | static char * | |||
5302 | get_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 | ||||
5325 | static void | |||
5326 | link_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 | ||||
5468 | static gboolean | |||
5469 | link_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 | ||||
5491 | static gboolean | |||
5492 | link_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 | ||||
5557 | void | |||
5558 | nautilus_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 | ||||
5599 | void | |||
5600 | nautilus_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 | ||||
5640 | static gboolean | |||
5641 | set_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 | ||||
5658 | static void | |||
5659 | set_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 | ||||
5744 | static gboolean | |||
5745 | set_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 | ||||
5772 | void | |||
5773 | nautilus_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 | ||||
5806 | static GList * | |||
5807 | location_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 | ||||
5822 | typedef struct { | |||
5823 | NautilusCopyCallback real_callback; | |||
5824 | gpointer real_data; | |||
5825 | } MoveTrashCBData; | |||
5826 | ||||
5827 | static void | |||
5828 | callback_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 | ||||
5837 | void | |||
5838 | nautilus_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) { | |||
| ||||
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); | |||
5865 | ||||
5866 | for (p = locations; p != NULL((void*)0); p = p->next) { | |||
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) { | |||
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) { | |||
5885 | src_dir = g_file_get_parent (locations->data); | |||
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 | ||||
5940 | static gboolean | |||
5941 | create_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 | ||||
5968 | static gboolean | |||
5969 | create_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 | ||||
6252 | void | |||
6253 | nautilus_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 | ||||
6288 | void | |||
6289 | nautilus_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 | ||||
6330 | void | |||
6331 | nautilus_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 | ||||
6373 | static void | |||
6374 | delete_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 | ||||
6414 | static gboolean | |||
6415 | empty_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 | ||||
6432 | static gboolean | |||
6433 | empty_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 | ||||
6468 | void | |||
6469 | nautilus_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 | ||||
6493 | static gboolean | |||
6494 | mark_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 | ||||
6511 | static void | |||
6512 | mark_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 | ||||
6669 | static gboolean | |||
6670 | mark_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 | ||||
6695 | void | |||
6696 | nautilus_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 | ||||
6719 | void | |||
6720 | nautilus_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 |