1 /*
2 * nautilus-file.c: Nautilus file model.
3 *
4 * Copyright (C) 1999, 2000, 2001 Eazel, Inc.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18 *
19 * Author: Darin Adler <darin@bentspoon.com>
20 */
21
22 #include "nautilus-file.h"
23
24 #ifndef NAUTILUS_COMPILATION
25 #define NAUTILUS_COMPILATION
26 #endif
27 #include <libnautilus-extension/nautilus-extension-private.h>
28
29 #include <eel/eel-debug.h>
30 #include <eel/eel-glib-extensions.h>
31 #include <eel/eel-gtk-extensions.h>
32 #include <eel/eel-string.h>
33 #include <eel/eel-vfs-extensions.h>
34 #include <gdesktop-enums.h>
35 #include <gio/gio.h>
36 #include <glib.h>
37 #include <glib/gi18n.h>
38 #include <glib/gstdio.h>
39 #include <gnome-autoar/gnome-autoar.h>
40 #include <grp.h>
41 #include <gtk/gtk.h>
42 #include <libxml/parser.h>
43 #include <sys/types.h>
44 #include <limits.h>
45 #include <pwd.h>
46 #include <stdlib.h>
47 #include <sys/stat.h>
48 #include <sys/time.h>
49 #include <time.h>
50 #include <unistd.h>
51
52 #define DEBUG_FLAG NAUTILUS_DEBUG_FILE
53 #include "nautilus-debug.h"
54
55 #include "nautilus-directory-notify.h"
56 #include "nautilus-directory-private.h"
57 #include "nautilus-enums.h"
58 #include "nautilus-file-operations.h"
59 #include "nautilus-file-private.h"
60 #include "nautilus-file-undo-manager.h"
61 #include "nautilus-file-undo-operations.h"
62 #include "nautilus-file-utilities.h"
63 #include "nautilus-global-preferences.h"
64 #include "nautilus-icon-info.h"
65 #include "nautilus-lib-self-check-functions.h"
66 #include "nautilus-metadata.h"
67 #include "nautilus-module.h"
68 #include "nautilus-signaller.h"
69 #include "nautilus-tag-manager.h"
70 #include "nautilus-thumbnails.h"
71 #include "nautilus-ui-utilities.h"
72 #include "nautilus-vfs-file.h"
73 #include "nautilus-video-mime-types.h"
74
75 #ifdef HAVE_SELINUX
76 #include <selinux/selinux.h>
77 #endif
78
79 /* Time in seconds to cache getpwuid results */
80 #define GETPWUID_CACHE_TIME (5 * 60)
81
82 #define ICON_NAME_THUMBNAIL_LOADING "image-loading"
83
84 #undef NAUTILUS_FILE_DEBUG_REF
85 #undef NAUTILUS_FILE_DEBUG_REF_VALGRIND
86
87 #ifdef NAUTILUS_FILE_DEBUG_REF_VALGRIND
88 #include <valgrind/valgrind.h>
89 #define DEBUG_REF_PRINTF VALGRIND_PRINTF_BACKTRACE
90 #else
91 #define DEBUG_REF_PRINTF printf
92 #endif
93
94 #define MEGA_TO_BASE_RATE 1000000
95
96 /* Files that start with these characters sort after files that don't. */
97 #define SORT_LAST_CHAR1 '.'
98 #define SORT_LAST_CHAR2 '#'
99
100 /* Name of Nautilus trash directories */
101 #define TRASH_DIRECTORY_NAME ".Trash"
102
103 #define METADATA_ID_IS_LIST_MASK (1U << 31)
104
105 typedef enum
106 {
107 SHOW_HIDDEN = 1 << 0,
108 } FilterOptions;
109
110 typedef enum
111 {
112 NAUTILUS_DATE_FORMAT_REGULAR = 0,
113 NAUTILUS_DATE_FORMAT_REGULAR_WITH_TIME = 1,
114 NAUTILUS_DATE_FORMAT_FULL = 2,
115 } NautilusDateFormat;
116
117 typedef void (*ModifyListFunction) (GList **list,
118 NautilusFile *file);
119
120 enum
121 {
122 CHANGED,
123 UPDATED_DEEP_COUNT_IN_PROGRESS,
124 LAST_SIGNAL
125 };
126
127 static guint signals[LAST_SIGNAL];
128
129 static GHashTable *symbolic_links;
130
131 static guint64 cached_thumbnail_limit;
132 static NautilusSpeedTradeoffValue show_file_thumbs;
133
134 static NautilusSpeedTradeoffValue show_directory_item_count;
135
136 static GQuark attribute_name_q,
137 attribute_size_q,
138 attribute_type_q,
139 attribute_detailed_type_q,
140 attribute_modification_date_q,
141 attribute_date_modified_q,
142 attribute_date_modified_full_q,
143 attribute_date_modified_with_time_q,
144 attribute_accessed_date_q,
145 attribute_date_accessed_q,
146 attribute_date_accessed_full_q,
147 attribute_date_created_q,
148 attribute_date_created_full_q,
149 attribute_mime_type_q,
150 attribute_size_detail_q,
151 attribute_deep_size_q,
152 attribute_deep_file_count_q,
153 attribute_deep_directory_count_q,
154 attribute_deep_total_count_q,
155 attribute_search_relevance_q,
156 attribute_trashed_on_q,
157 attribute_trashed_on_full_q,
158 attribute_trash_orig_path_q,
159 attribute_recency_q,
160 attribute_permissions_q,
161 attribute_selinux_context_q,
162 attribute_octal_permissions_q,
163 attribute_owner_q,
164 attribute_group_q,
165 attribute_uri_q,
166 attribute_where_q,
167 attribute_link_target_q,
168 attribute_volume_q,
169 attribute_free_space_q,
170 attribute_starred_q;
171
172 static void nautilus_file_info_iface_init (NautilusFileInfoInterface *iface);
173 static char *nautilus_file_get_owner_as_string (NautilusFile *file,
174 gboolean include_real_name);
175 static char *nautilus_file_get_type_as_string (NautilusFile *file);
176 static char *nautilus_file_get_type_as_string_no_extra_text (NautilusFile *file);
177 static char *nautilus_file_get_detailed_type_as_string (NautilusFile *file);
178 static gboolean update_info_and_name (NautilusFile *file,
179 GFileInfo *info);
180 static const char *nautilus_file_peek_display_name (NautilusFile *file);
181 static const char *nautilus_file_peek_display_name_collation_key (NautilusFile *file);
182 static void file_mount_unmounted (GMount *mount,
183 gpointer data);
184 static void metadata_hash_free (GHashTable *hash);
185
186 G_DEFINE_TYPE_WITH_CODE (NautilusFile, nautilus_file, G_TYPE_OBJECT,
187 G_IMPLEMENT_INTERFACE (NAUTILUS_TYPE_FILE_INFO,
188 nautilus_file_info_iface_init));
189
190 static void
nautilus_file_init(NautilusFile * file)191 nautilus_file_init (NautilusFile *file)
192 {
193 file->details = G_TYPE_INSTANCE_GET_PRIVATE ((file), NAUTILUS_TYPE_FILE, NautilusFileDetails);
194
195 nautilus_file_clear_info (file);
196 nautilus_file_invalidate_extension_info_internal (file);
197
198 file->details->free_space = -1;
199 }
200
201 static GObject *
nautilus_file_constructor(GType type,guint n_construct_properties,GObjectConstructParam * construct_params)202 nautilus_file_constructor (GType type,
203 guint n_construct_properties,
204 GObjectConstructParam *construct_params)
205 {
206 GObject *object;
207 NautilusFile *file;
208
209 object = (*G_OBJECT_CLASS (nautilus_file_parent_class)->constructor)(type,
210 n_construct_properties,
211 construct_params);
212
213 file = NAUTILUS_FILE (object);
214
215 /* Set to default type after full construction */
216 if (NAUTILUS_FILE_GET_CLASS (file)->default_file_type != G_FILE_TYPE_UNKNOWN)
217 {
218 file->details->type = NAUTILUS_FILE_GET_CLASS (file)->default_file_type;
219 }
220
221 return object;
222 }
223
224 gboolean
nautilus_file_set_display_name(NautilusFile * file,const char * display_name,const char * edit_name,gboolean custom)225 nautilus_file_set_display_name (NautilusFile *file,
226 const char *display_name,
227 const char *edit_name,
228 gboolean custom)
229 {
230 gboolean changed;
231
232 if (custom && display_name == NULL)
233 {
234 /* We're re-setting a custom display name, invalidate it if
235 * we already set it so that the old one is re-read */
236 if (file->details->got_custom_display_name)
237 {
238 file->details->got_custom_display_name = FALSE;
239 nautilus_file_invalidate_attributes (file,
240 NAUTILUS_FILE_ATTRIBUTE_INFO);
241 }
242 return FALSE;
243 }
244
245 if (display_name == NULL || *display_name == 0)
246 {
247 return FALSE;
248 }
249
250 if (!custom && file->details->got_custom_display_name)
251 {
252 return FALSE;
253 }
254
255 if (edit_name == NULL)
256 {
257 edit_name = display_name;
258 }
259
260 changed = FALSE;
261
262 if (g_strcmp0 (file->details->display_name, display_name) != 0)
263 {
264 changed = TRUE;
265
266 g_clear_pointer (&file->details->display_name, g_ref_string_release);
267
268 if (g_strcmp0 (file->details->name, display_name) == 0)
269 {
270 file->details->display_name = g_ref_string_acquire (file->details->name);
271 }
272 else
273 {
274 file->details->display_name = g_ref_string_new (display_name);
275 }
276
277 g_free (file->details->display_name_collation_key);
278 file->details->display_name_collation_key = g_utf8_collate_key_for_filename (display_name, -1);
279 }
280
281 if (g_strcmp0 (file->details->edit_name, edit_name) != 0)
282 {
283 changed = TRUE;
284
285 g_clear_pointer (&file->details->edit_name, g_ref_string_release);
286 if (g_strcmp0 (file->details->display_name, edit_name) == 0)
287 {
288 file->details->edit_name = g_ref_string_acquire (file->details->display_name);
289 }
290 else
291 {
292 file->details->edit_name = g_ref_string_new (edit_name);
293 }
294 }
295
296 file->details->got_custom_display_name = custom;
297 return changed;
298 }
299
300 static void
nautilus_file_clear_display_name(NautilusFile * file)301 nautilus_file_clear_display_name (NautilusFile *file)
302 {
303 g_clear_pointer (&file->details->display_name, g_ref_string_release);
304 g_free (file->details->display_name_collation_key);
305 file->details->display_name_collation_key = NULL;
306 g_clear_pointer (&file->details->edit_name, g_ref_string_release);
307 }
308
309 static gboolean
foreach_metadata_free(gpointer key,gpointer value,gpointer user_data)310 foreach_metadata_free (gpointer key,
311 gpointer value,
312 gpointer user_data)
313 {
314 guint id;
315
316 id = GPOINTER_TO_UINT (key);
317
318 if (id & METADATA_ID_IS_LIST_MASK)
319 {
320 g_strfreev ((char **) value);
321 }
322 else
323 {
324 g_free ((char *) value);
325 }
326 return TRUE;
327 }
328
329
330 static void
metadata_hash_free(GHashTable * hash)331 metadata_hash_free (GHashTable *hash)
332 {
333 g_hash_table_foreach_remove (hash,
334 foreach_metadata_free,
335 NULL);
336 g_hash_table_destroy (hash);
337 }
338
339 static gboolean
_g_strv_equal(GStrv a,GStrv b)340 _g_strv_equal (GStrv a,
341 GStrv b)
342 {
343 if (g_strv_length (a) != g_strv_length (b))
344 {
345 return FALSE;
346 }
347
348 for (int i = 0; a[i] != NULL; i++)
349 {
350 if (strcmp (a[i], b[i]) != 0)
351 {
352 return FALSE;
353 }
354 }
355
356 return TRUE;
357 }
358
359 static gboolean
metadata_hash_equal(GHashTable * hash1,GHashTable * hash2)360 metadata_hash_equal (GHashTable *hash1,
361 GHashTable *hash2)
362 {
363 GHashTableIter iter;
364 gpointer key1, value1, value2;
365 guint id;
366
367 if (hash1 == NULL && hash2 == NULL)
368 {
369 return TRUE;
370 }
371
372 if (hash1 == NULL || hash2 == NULL)
373 {
374 return FALSE;
375 }
376
377 if (g_hash_table_size (hash1) !=
378 g_hash_table_size (hash2))
379 {
380 return FALSE;
381 }
382
383 g_hash_table_iter_init (&iter, hash1);
384 while (g_hash_table_iter_next (&iter, &key1, &value1))
385 {
386 value2 = g_hash_table_lookup (hash2, key1);
387 if (value2 == NULL)
388 {
389 return FALSE;
390 }
391 id = GPOINTER_TO_UINT (key1);
392 if (id & METADATA_ID_IS_LIST_MASK)
393 {
394 if (!_g_strv_equal ((char **) value1, (char **) value2))
395 {
396 return FALSE;
397 }
398 }
399 else
400 {
401 if (strcmp ((char *) value1, (char *) value2) != 0)
402 {
403 return FALSE;
404 }
405 }
406 }
407
408 return TRUE;
409 }
410
411 static void
clear_metadata(NautilusFile * file)412 clear_metadata (NautilusFile *file)
413 {
414 if (file->details->metadata)
415 {
416 metadata_hash_free (file->details->metadata);
417 file->details->metadata = NULL;
418 }
419 }
420
421 static GHashTable *
get_metadata_from_info(GFileInfo * info)422 get_metadata_from_info (GFileInfo *info)
423 {
424 GHashTable *metadata;
425 char **attrs;
426 guint id;
427 int i;
428 GFileAttributeType type;
429 gpointer value;
430
431 attrs = g_file_info_list_attributes (info, "metadata");
432
433 metadata = g_hash_table_new (NULL, NULL);
434
435 for (i = 0; attrs[i] != NULL; i++)
436 {
437 id = nautilus_metadata_get_id (attrs[i] + strlen ("metadata::"));
438 if (id == 0)
439 {
440 continue;
441 }
442
443 if (!g_file_info_get_attribute_data (info, attrs[i],
444 &type, &value, NULL))
445 {
446 continue;
447 }
448
449 if (type == G_FILE_ATTRIBUTE_TYPE_STRING)
450 {
451 g_hash_table_insert (metadata, GUINT_TO_POINTER (id),
452 g_strdup ((char *) value));
453 }
454 else if (type == G_FILE_ATTRIBUTE_TYPE_STRINGV)
455 {
456 id |= METADATA_ID_IS_LIST_MASK;
457 g_hash_table_insert (metadata, GUINT_TO_POINTER (id),
458 g_strdupv ((char **) value));
459 }
460 }
461
462 g_strfreev (attrs);
463
464 return metadata;
465 }
466
467 gboolean
nautilus_file_update_metadata_from_info(NautilusFile * file,GFileInfo * info)468 nautilus_file_update_metadata_from_info (NautilusFile *file,
469 GFileInfo *info)
470 {
471 gboolean changed = FALSE;
472
473 if (g_file_info_has_namespace (info, "metadata"))
474 {
475 GHashTable *metadata;
476
477 metadata = get_metadata_from_info (info);
478 if (!metadata_hash_equal (metadata,
479 file->details->metadata))
480 {
481 changed = TRUE;
482 clear_metadata (file);
483 file->details->metadata = metadata;
484 }
485 else
486 {
487 metadata_hash_free (metadata);
488 }
489 }
490 else if (file->details->metadata)
491 {
492 changed = TRUE;
493 clear_metadata (file);
494 }
495 return changed;
496 }
497
498 void
nautilus_file_clear_info(NautilusFile * file)499 nautilus_file_clear_info (NautilusFile *file)
500 {
501 file->details->got_file_info = FALSE;
502 if (file->details->get_info_error)
503 {
504 g_error_free (file->details->get_info_error);
505 file->details->get_info_error = NULL;
506 }
507 /* Reset to default type, which might be other than unknown for
508 * special kinds of files like the desktop or a search directory */
509 file->details->type = NAUTILUS_FILE_GET_CLASS (file)->default_file_type;
510
511 if (!file->details->got_custom_display_name)
512 {
513 nautilus_file_clear_display_name (file);
514 }
515
516 if (!file->details->got_custom_activation_uri &&
517 file->details->activation_uri != NULL)
518 {
519 g_free (file->details->activation_uri);
520 file->details->activation_uri = NULL;
521 }
522
523 if (file->details->icon != NULL)
524 {
525 g_object_unref (file->details->icon);
526 file->details->icon = NULL;
527 }
528
529 g_free (file->details->thumbnail_path);
530 file->details->thumbnail_path = NULL;
531 file->details->thumbnailing_failed = FALSE;
532
533 file->details->is_symlink = FALSE;
534 file->details->is_hidden = FALSE;
535 file->details->is_mountpoint = FALSE;
536 file->details->uid = -1;
537 file->details->gid = -1;
538 file->details->can_read = TRUE;
539 file->details->can_write = TRUE;
540 file->details->can_execute = TRUE;
541 file->details->can_delete = TRUE;
542 file->details->can_trash = TRUE;
543 file->details->can_rename = TRUE;
544 file->details->can_mount = FALSE;
545 file->details->can_unmount = FALSE;
546 file->details->can_eject = FALSE;
547 file->details->can_start = FALSE;
548 file->details->can_start_degraded = FALSE;
549 file->details->can_stop = FALSE;
550 file->details->start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
551 file->details->can_poll_for_media = FALSE;
552 file->details->is_media_check_automatic = FALSE;
553 file->details->has_permissions = FALSE;
554 file->details->permissions = 0;
555 file->details->size = -1;
556 file->details->sort_order = 0;
557 file->details->mtime = 0;
558 file->details->atime = 0;
559 file->details->btime = 0;
560 file->details->trash_time = 0;
561 file->details->recency = 0;
562 g_free (file->details->symlink_name);
563 file->details->symlink_name = NULL;
564 g_clear_pointer (&file->details->mime_type, g_ref_string_release);
565 g_free (file->details->selinux_context);
566 file->details->selinux_context = NULL;
567 g_free (file->details->description);
568 file->details->description = NULL;
569 g_clear_pointer (&file->details->owner, g_ref_string_release);
570 g_clear_pointer (&file->details->owner_real, g_ref_string_release);
571 g_clear_pointer (&file->details->group, g_ref_string_release);
572
573 g_clear_pointer (&file->details->filesystem_id, g_ref_string_release);
574
575 clear_metadata (file);
576 }
577
578 NautilusDirectory *
nautilus_file_get_directory(NautilusFile * file)579 nautilus_file_get_directory (NautilusFile *file)
580 {
581 g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
582
583 return file->details->directory;
584 }
585
586 void
nautilus_file_set_directory(NautilusFile * file,NautilusDirectory * directory)587 nautilus_file_set_directory (NautilusFile *file,
588 NautilusDirectory *directory)
589 {
590 char *parent_uri;
591
592 g_clear_object (&file->details->directory);
593 g_free (file->details->directory_name_collation_key);
594
595 file->details->directory = nautilus_directory_ref (directory);
596
597 parent_uri = nautilus_file_get_parent_uri (file);
598 file->details->directory_name_collation_key = g_utf8_collate_key_for_filename (parent_uri, -1);
599 g_free (parent_uri);
600 }
601
602 static NautilusFile *
nautilus_file_new_from_filename(NautilusDirectory * directory,const char * filename,gboolean self_owned)603 nautilus_file_new_from_filename (NautilusDirectory *directory,
604 const char *filename,
605 gboolean self_owned)
606 {
607 NautilusFile *file;
608
609 g_assert (NAUTILUS_IS_DIRECTORY (directory));
610 g_assert (filename != NULL);
611 g_assert (filename[0] != '\0');
612
613 file = nautilus_directory_new_file_from_filename (directory, filename, self_owned);
614 file->details->name = g_ref_string_new (filename);
615
616 #ifdef NAUTILUS_FILE_DEBUG_REF
617 DEBUG_REF_PRINTF ("%10p ref'd", file);
618 #endif
619
620 return file;
621 }
622
623 static void
modify_link_hash_table(NautilusFile * file,ModifyListFunction modify_function)624 modify_link_hash_table (NautilusFile *file,
625 ModifyListFunction modify_function)
626 {
627 char *target_uri;
628 gboolean found;
629 gpointer original_key;
630 GList **list_ptr;
631
632 /* Check if there is a symlink name. If none, we are OK. */
633 if (file->details->symlink_name == NULL || !nautilus_file_is_symbolic_link (file))
634 {
635 return;
636 }
637
638 /* Create the hash table first time through. */
639 if (symbolic_links == NULL)
640 {
641 symbolic_links = g_hash_table_new (g_str_hash, g_str_equal);
642 }
643
644 target_uri = nautilus_file_get_symbolic_link_target_uri (file);
645
646 /* Find the old contents of the hash table. */
647 found = g_hash_table_lookup_extended
648 (symbolic_links, target_uri,
649 &original_key, (gpointer *) &list_ptr);
650 if (!found)
651 {
652 list_ptr = g_new0 (GList *, 1);
653 original_key = g_strdup (target_uri);
654 g_hash_table_insert (symbolic_links, original_key, list_ptr);
655 }
656 (*modify_function)(list_ptr, file);
657 if (*list_ptr == NULL)
658 {
659 g_hash_table_remove (symbolic_links, target_uri);
660 g_free (list_ptr);
661 g_free (original_key);
662 }
663 g_free (target_uri);
664 }
665
666 static void
symbolic_link_weak_notify(gpointer data,GObject * where_the_object_was)667 symbolic_link_weak_notify (gpointer data,
668 GObject *where_the_object_was)
669 {
670 GList **list = data;
671 /* This really shouldn't happen, but we're seeing some strange things in
672 * bug #358172 where the symlink hashtable isn't correctly updated. */
673 *list = g_list_remove (*list, where_the_object_was);
674 }
675
676 static void
add_to_link_hash_table_list(GList ** list,NautilusFile * file)677 add_to_link_hash_table_list (GList **list,
678 NautilusFile *file)
679 {
680 if (g_list_find (*list, file) != NULL)
681 {
682 g_warning ("Adding file to symlink_table multiple times. "
683 "Please add feedback of what you were doing at http://bugzilla.gnome.org/show_bug.cgi?id=358172\n");
684 return;
685 }
686 g_object_weak_ref (G_OBJECT (file), symbolic_link_weak_notify, list);
687 *list = g_list_prepend (*list, file);
688 }
689
690 static void
add_to_link_hash_table(NautilusFile * file)691 add_to_link_hash_table (NautilusFile *file)
692 {
693 modify_link_hash_table (file, add_to_link_hash_table_list);
694 }
695
696 static void
remove_from_link_hash_table_list(GList ** list,NautilusFile * file)697 remove_from_link_hash_table_list (GList **list,
698 NautilusFile *file)
699 {
700 if (g_list_find (*list, file) != NULL)
701 {
702 g_object_weak_unref (G_OBJECT (file), symbolic_link_weak_notify, list);
703 *list = g_list_remove (*list, file);
704 }
705 }
706
707 static void
remove_from_link_hash_table(NautilusFile * file)708 remove_from_link_hash_table (NautilusFile *file)
709 {
710 modify_link_hash_table (file, remove_from_link_hash_table_list);
711 }
712
713 NautilusFile *
nautilus_file_new_from_info(NautilusDirectory * directory,GFileInfo * info)714 nautilus_file_new_from_info (NautilusDirectory *directory,
715 GFileInfo *info)
716 {
717 NautilusFile *file;
718
719 g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL);
720 g_return_val_if_fail (info != NULL, NULL);
721
722 file = NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_VFS_FILE, NULL));
723 nautilus_file_set_directory (file, directory);
724
725 update_info_and_name (file, info);
726
727 #ifdef NAUTILUS_FILE_DEBUG_REF
728 DEBUG_REF_PRINTF ("%10p ref'd", file);
729 #endif
730
731 return file;
732 }
733
734 static NautilusFileInfo *
nautilus_file_get_internal(GFile * location,gboolean create)735 nautilus_file_get_internal (GFile *location,
736 gboolean create)
737 {
738 gboolean self_owned;
739 NautilusDirectory *directory;
740 NautilusFile *file;
741 GFile *parent;
742 char *basename;
743
744 g_assert (location != NULL);
745
746 parent = g_file_get_parent (location);
747
748 self_owned = FALSE;
749 if (parent == NULL)
750 {
751 self_owned = TRUE;
752 parent = g_object_ref (location);
753 }
754
755 /* Get object that represents the directory. */
756 directory = nautilus_directory_get_internal (parent, create);
757
758 g_object_unref (parent);
759
760 /* Get the name for the file. */
761 if (self_owned && directory != NULL)
762 {
763 basename = nautilus_directory_get_name_for_self_as_new_file (directory);
764 }
765 else
766 {
767 basename = g_file_get_basename (location);
768 }
769 /* Check to see if it's a file that's already known. */
770 if (directory == NULL)
771 {
772 file = NULL;
773 }
774 else if (self_owned)
775 {
776 file = directory->details->as_file;
777 }
778 else
779 {
780 file = nautilus_directory_find_file_by_name (directory, basename);
781 }
782
783 /* Ref or create the file. */
784 if (file != NULL)
785 {
786 nautilus_file_ref (file);
787 }
788 else if (create)
789 {
790 file = nautilus_file_new_from_filename (directory, basename, self_owned);
791 if (self_owned)
792 {
793 g_assert (directory->details->as_file == NULL);
794 directory->details->as_file = file;
795 }
796 else
797 {
798 nautilus_directory_add_file (directory, file);
799 }
800 }
801
802 g_free (basename);
803 nautilus_directory_unref (directory);
804
805 return NAUTILUS_FILE_INFO (file);
806 }
807
808 NautilusFile *
nautilus_file_get(GFile * location)809 nautilus_file_get (GFile *location)
810 {
811 g_return_val_if_fail (G_IS_FILE (location), NULL);
812
813 return NAUTILUS_FILE (nautilus_file_get_internal (location, TRUE));
814 }
815
816 NautilusFile *
nautilus_file_get_existing(GFile * location)817 nautilus_file_get_existing (GFile *location)
818 {
819 g_return_val_if_fail (G_IS_FILE (location), NULL);
820
821 return NAUTILUS_FILE (nautilus_file_get_internal (location, FALSE));
822 }
823
824 NautilusFile *
nautilus_file_get_existing_by_uri(const char * uri)825 nautilus_file_get_existing_by_uri (const char *uri)
826 {
827 g_autoptr (GFile) location = NULL;
828
829 location = g_file_new_for_uri (uri);
830
831 return nautilus_file_get_existing (location);
832 }
833
834 NautilusFile *
nautilus_file_get_by_uri(const char * uri)835 nautilus_file_get_by_uri (const char *uri)
836 {
837 g_autoptr (GFile) location = NULL;
838
839 location = g_file_new_for_uri (uri);
840
841 return nautilus_file_get (location);
842 }
843
844 gboolean
nautilus_file_is_self_owned(NautilusFile * file)845 nautilus_file_is_self_owned (NautilusFile *file)
846 {
847 return file->details->directory->details->as_file == file;
848 }
849
850 static void
finalize(GObject * object)851 finalize (GObject *object)
852 {
853 NautilusDirectory *directory;
854 NautilusFile *file;
855 char *uri;
856
857 file = NAUTILUS_FILE (object);
858
859 g_assert (file->details->operations_in_progress == NULL);
860
861 if (file->details->is_thumbnailing)
862 {
863 uri = nautilus_file_get_uri (file);
864 nautilus_thumbnail_remove_from_queue (uri);
865 g_free (uri);
866 }
867
868 nautilus_async_destroying_file (file);
869
870 remove_from_link_hash_table (file);
871
872 directory = file->details->directory;
873
874 if (nautilus_file_is_self_owned (file))
875 {
876 directory->details->as_file = NULL;
877 }
878 else
879 {
880 if (!file->details->is_gone)
881 {
882 nautilus_directory_remove_file (directory, file);
883 }
884 }
885
886 if (file->details->get_info_error)
887 {
888 g_error_free (file->details->get_info_error);
889 }
890
891 nautilus_directory_unref (directory);
892 g_clear_pointer (&file->details->name, g_ref_string_release);
893 g_clear_pointer (&file->details->display_name, g_ref_string_release);
894 g_free (file->details->display_name_collation_key);
895 g_free (file->details->directory_name_collation_key);
896 g_clear_pointer (&file->details->edit_name, g_ref_string_release);
897 if (file->details->icon)
898 {
899 g_object_unref (file->details->icon);
900 }
901 g_free (file->details->thumbnail_path);
902 g_free (file->details->symlink_name);
903 g_clear_pointer (&file->details->mime_type, g_ref_string_release);
904 g_clear_pointer (&file->details->owner, g_ref_string_release);
905 g_clear_pointer (&file->details->owner_real, g_ref_string_release);
906 g_clear_pointer (&file->details->group, g_ref_string_release);
907 g_free (file->details->selinux_context);
908 g_free (file->details->description);
909 g_free (file->details->activation_uri);
910 g_clear_object (&file->details->custom_icon);
911
912 if (file->details->thumbnail)
913 {
914 g_object_unref (file->details->thumbnail);
915 }
916 if (file->details->scaled_thumbnail)
917 {
918 g_object_unref (file->details->scaled_thumbnail);
919 }
920
921 if (file->details->mount)
922 {
923 g_signal_handlers_disconnect_by_func (file->details->mount, file_mount_unmounted, file);
924 g_object_unref (file->details->mount);
925 }
926
927 g_clear_pointer (&file->details->filesystem_id, g_ref_string_release);
928 g_clear_pointer (&file->details->filesystem_type, g_ref_string_release);
929 g_free (file->details->trash_orig_path);
930
931 g_list_free_full (file->details->mime_list, g_free);
932 g_list_free_full (file->details->pending_extension_emblems, g_free);
933 g_list_free_full (file->details->extension_emblems, g_free);
934 g_list_free_full (file->details->pending_info_providers, g_object_unref);
935
936 if (file->details->pending_extension_attributes)
937 {
938 g_hash_table_destroy (file->details->pending_extension_attributes);
939 }
940
941 if (file->details->extension_attributes)
942 {
943 g_hash_table_destroy (file->details->extension_attributes);
944 }
945
946 if (file->details->metadata)
947 {
948 metadata_hash_free (file->details->metadata);
949 }
950
951 g_free (file->details->fts_snippet);
952
953 G_OBJECT_CLASS (nautilus_file_parent_class)->finalize (object);
954 }
955
956 NautilusFile *
nautilus_file_ref(NautilusFile * file)957 nautilus_file_ref (NautilusFile *file)
958 {
959 if (file == NULL)
960 {
961 return NULL;
962 }
963 g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
964
965 #ifdef NAUTILUS_FILE_DEBUG_REF
966 DEBUG_REF_PRINTF ("%10p ref'd", file);
967 #endif
968
969 return g_object_ref (file);
970 }
971
972 void
nautilus_file_unref(NautilusFile * file)973 nautilus_file_unref (NautilusFile *file)
974 {
975 if (file == NULL)
976 {
977 return;
978 }
979
980 g_return_if_fail (NAUTILUS_IS_FILE (file));
981
982 #ifdef NAUTILUS_FILE_DEBUG_REF
983 DEBUG_REF_PRINTF ("%10p unref'd", file);
984 #endif
985
986 g_object_unref (file);
987 }
988
989 /**
990 * nautilus_file_get_parent_uri_for_display:
991 *
992 * Get the uri for the parent directory.
993 *
994 * @file: The file in question.
995 *
996 * Return value: A string representing the parent's location,
997 * formatted for user display (including stripping "file://").
998 * If the parent is NULL, returns the empty string.
999 */
1000 char *
nautilus_file_get_parent_uri_for_display(NautilusFile * file)1001 nautilus_file_get_parent_uri_for_display (NautilusFile *file)
1002 {
1003 GFile *parent;
1004 char *result;
1005
1006 g_assert (NAUTILUS_IS_FILE (file));
1007
1008 parent = nautilus_file_get_parent_location (file);
1009 if (parent)
1010 {
1011 result = g_file_get_parse_name (parent);
1012 g_object_unref (parent);
1013 }
1014 else
1015 {
1016 result = g_strdup ("");
1017 }
1018
1019 return result;
1020 }
1021
1022 /**
1023 * nautilus_file_get_parent_uri:
1024 *
1025 * Get the uri for the parent directory.
1026 *
1027 * @file: The file in question.
1028 *
1029 * Return value: A string for the parent's location, in "raw URI" form.
1030 * Use nautilus_file_get_parent_uri_for_display instead if the
1031 * result is to be displayed on-screen.
1032 * If the parent is NULL, returns the empty string.
1033 */
1034 char *
nautilus_file_get_parent_uri(NautilusFile * file)1035 nautilus_file_get_parent_uri (NautilusFile *file)
1036 {
1037 g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
1038
1039 return nautilus_file_info_get_parent_uri (NAUTILUS_FILE_INFO (file));
1040 }
1041
1042 GFile *
nautilus_file_get_parent_location(NautilusFile * file)1043 nautilus_file_get_parent_location (NautilusFile *file)
1044 {
1045 g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
1046
1047 return nautilus_file_info_get_parent_location (NAUTILUS_FILE_INFO (file));
1048 }
1049
1050 NautilusFile *
nautilus_file_get_parent(NautilusFile * file)1051 nautilus_file_get_parent (NautilusFile *file)
1052 {
1053 NautilusFileInfo *file_info;
1054
1055 g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
1056
1057 file_info = NAUTILUS_FILE_INFO (file);
1058
1059 return NAUTILUS_FILE (nautilus_file_info_get_parent_info (file_info));
1060 }
1061
1062 /**
1063 * nautilus_file_can_read:
1064 *
1065 * Check whether the user is allowed to read the contents of this file.
1066 *
1067 * @file: The file to check.
1068 *
1069 * Return value: FALSE if the user is definitely not allowed to read
1070 * the contents of the file. If the user has read permission, or
1071 * the code can't tell whether the user has read permission,
1072 * returns TRUE (so failures must always be handled).
1073 */
1074 gboolean
nautilus_file_can_read(NautilusFile * file)1075 nautilus_file_can_read (NautilusFile *file)
1076 {
1077 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1078
1079 return file->details->can_read;
1080 }
1081
1082 /**
1083 * nautilus_file_can_write:
1084 *
1085 * Check whether the user is allowed to write to this file.
1086 *
1087 * @file: The file to check.
1088 *
1089 * Return value: FALSE if the user is definitely not allowed to write
1090 * to the file. If the user has write permission, or
1091 * the code can't tell whether the user has write permission,
1092 * returns TRUE (so failures must always be handled).
1093 */
1094 gboolean
nautilus_file_can_write(NautilusFile * file)1095 nautilus_file_can_write (NautilusFile *file)
1096 {
1097 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1098
1099 return nautilus_file_info_can_write (NAUTILUS_FILE_INFO (file));
1100 }
1101
1102 /**
1103 * nautilus_file_can_execute:
1104 *
1105 * Check whether the user is allowed to execute this file.
1106 *
1107 * @file: The file to check.
1108 *
1109 * Return value: FALSE if the user is definitely not allowed to execute
1110 * the file. If the user has execute permission, or
1111 * the code can't tell whether the user has execute permission,
1112 * returns TRUE (so failures must always be handled).
1113 */
1114 gboolean
nautilus_file_can_execute(NautilusFile * file)1115 nautilus_file_can_execute (NautilusFile *file)
1116 {
1117 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1118
1119 return file->details->can_execute;
1120 }
1121
1122 gboolean
nautilus_file_can_mount(NautilusFile * file)1123 nautilus_file_can_mount (NautilusFile *file)
1124 {
1125 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1126
1127 return file->details->can_mount;
1128 }
1129
1130 gboolean
nautilus_file_can_unmount(NautilusFile * file)1131 nautilus_file_can_unmount (NautilusFile *file)
1132 {
1133 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1134
1135 return file->details->can_unmount ||
1136 (file->details->mount != NULL &&
1137 g_mount_can_unmount (file->details->mount));
1138 }
1139
1140 gboolean
nautilus_file_can_eject(NautilusFile * file)1141 nautilus_file_can_eject (NautilusFile *file)
1142 {
1143 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1144
1145 return file->details->can_eject ||
1146 (file->details->mount != NULL &&
1147 g_mount_can_eject (file->details->mount));
1148 }
1149
1150 gboolean
nautilus_file_can_start(NautilusFile * file)1151 nautilus_file_can_start (NautilusFile *file)
1152 {
1153 gboolean ret;
1154 GDrive *drive;
1155
1156 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1157
1158 ret = FALSE;
1159
1160 if (file->details->can_start)
1161 {
1162 ret = TRUE;
1163 goto out;
1164 }
1165
1166 if (file->details->mount != NULL)
1167 {
1168 drive = g_mount_get_drive (file->details->mount);
1169 if (drive != NULL)
1170 {
1171 ret = g_drive_can_start (drive);
1172 g_object_unref (drive);
1173 }
1174 }
1175
1176 out:
1177 return ret;
1178 }
1179
1180 gboolean
nautilus_file_can_start_degraded(NautilusFile * file)1181 nautilus_file_can_start_degraded (NautilusFile *file)
1182 {
1183 gboolean ret;
1184 GDrive *drive;
1185
1186 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1187
1188 ret = FALSE;
1189
1190 if (file->details->can_start_degraded)
1191 {
1192 ret = TRUE;
1193 goto out;
1194 }
1195
1196 if (file->details->mount != NULL)
1197 {
1198 drive = g_mount_get_drive (file->details->mount);
1199 if (drive != NULL)
1200 {
1201 ret = g_drive_can_start_degraded (drive);
1202 g_object_unref (drive);
1203 }
1204 }
1205
1206 out:
1207 return ret;
1208 }
1209
1210 gboolean
nautilus_file_can_poll_for_media(NautilusFile * file)1211 nautilus_file_can_poll_for_media (NautilusFile *file)
1212 {
1213 gboolean ret;
1214 GDrive *drive;
1215
1216 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1217
1218 ret = FALSE;
1219
1220 if (file->details->can_poll_for_media)
1221 {
1222 ret = TRUE;
1223 goto out;
1224 }
1225
1226 if (file->details->mount != NULL)
1227 {
1228 drive = g_mount_get_drive (file->details->mount);
1229 if (drive != NULL)
1230 {
1231 ret = g_drive_can_poll_for_media (drive);
1232 g_object_unref (drive);
1233 }
1234 }
1235
1236 out:
1237 return ret;
1238 }
1239
1240 gboolean
nautilus_file_is_media_check_automatic(NautilusFile * file)1241 nautilus_file_is_media_check_automatic (NautilusFile *file)
1242 {
1243 gboolean ret;
1244 GDrive *drive;
1245
1246 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1247
1248 ret = FALSE;
1249
1250 if (file->details->is_media_check_automatic)
1251 {
1252 ret = TRUE;
1253 goto out;
1254 }
1255
1256 if (file->details->mount != NULL)
1257 {
1258 drive = g_mount_get_drive (file->details->mount);
1259 if (drive != NULL)
1260 {
1261 ret = g_drive_is_media_check_automatic (drive);
1262 g_object_unref (drive);
1263 }
1264 }
1265
1266 out:
1267 return ret;
1268 }
1269
1270
1271 gboolean
nautilus_file_can_stop(NautilusFile * file)1272 nautilus_file_can_stop (NautilusFile *file)
1273 {
1274 gboolean ret;
1275 GDrive *drive;
1276
1277 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1278
1279 ret = FALSE;
1280
1281 if (file->details->can_stop)
1282 {
1283 ret = TRUE;
1284 goto out;
1285 }
1286
1287 if (file->details->mount != NULL)
1288 {
1289 drive = g_mount_get_drive (file->details->mount);
1290 if (drive != NULL)
1291 {
1292 ret = g_drive_can_stop (drive);
1293 g_object_unref (drive);
1294 }
1295 }
1296
1297 out:
1298 return ret;
1299 }
1300
1301 GDriveStartStopType
nautilus_file_get_start_stop_type(NautilusFile * file)1302 nautilus_file_get_start_stop_type (NautilusFile *file)
1303 {
1304 GDriveStartStopType ret;
1305 GDrive *drive;
1306
1307 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1308
1309 ret = file->details->start_stop_type;
1310 if (ret != G_DRIVE_START_STOP_TYPE_UNKNOWN)
1311 {
1312 goto out;
1313 }
1314
1315 if (file->details->mount != NULL)
1316 {
1317 drive = g_mount_get_drive (file->details->mount);
1318 if (drive != NULL)
1319 {
1320 ret = g_drive_get_start_stop_type (drive);
1321 g_object_unref (drive);
1322 }
1323 }
1324
1325 out:
1326 return ret;
1327 }
1328
1329 void
nautilus_file_mount(NautilusFile * file,GMountOperation * mount_op,GCancellable * cancellable,NautilusFileOperationCallback callback,gpointer callback_data)1330 nautilus_file_mount (NautilusFile *file,
1331 GMountOperation *mount_op,
1332 GCancellable *cancellable,
1333 NautilusFileOperationCallback callback,
1334 gpointer callback_data)
1335 {
1336 GError *error;
1337
1338 if (NAUTILUS_FILE_GET_CLASS (file)->mount == NULL)
1339 {
1340 if (callback)
1341 {
1342 error = NULL;
1343 g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
1344 _("This file cannot be mounted"));
1345 callback (file, NULL, error, callback_data);
1346 g_error_free (error);
1347 }
1348 }
1349 else
1350 {
1351 NAUTILUS_FILE_GET_CLASS (file)->mount (file, mount_op, cancellable, callback, callback_data);
1352 }
1353 }
1354
1355 typedef struct
1356 {
1357 NautilusFile *file;
1358 NautilusFileOperationCallback callback;
1359 gpointer callback_data;
1360 } UnmountData;
1361
1362 static void
unmount_done(void * callback_data)1363 unmount_done (void *callback_data)
1364 {
1365 UnmountData *data;
1366
1367 data = (UnmountData *) callback_data;
1368 if (data->callback)
1369 {
1370 data->callback (data->file, NULL, NULL, data->callback_data);
1371 }
1372 nautilus_file_unref (data->file);
1373 g_free (data);
1374 }
1375
1376 void
nautilus_file_unmount(NautilusFile * file,GMountOperation * mount_op,GCancellable * cancellable,NautilusFileOperationCallback callback,gpointer callback_data)1377 nautilus_file_unmount (NautilusFile *file,
1378 GMountOperation *mount_op,
1379 GCancellable *cancellable,
1380 NautilusFileOperationCallback callback,
1381 gpointer callback_data)
1382 {
1383 GError *error;
1384 UnmountData *data;
1385
1386 if (file->details->can_unmount)
1387 {
1388 if (NAUTILUS_FILE_GET_CLASS (file)->unmount != NULL)
1389 {
1390 NAUTILUS_FILE_GET_CLASS (file)->unmount (file, mount_op, cancellable, callback, callback_data);
1391 }
1392 else
1393 {
1394 if (callback)
1395 {
1396 error = NULL;
1397 g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
1398 _("This file cannot be unmounted"));
1399 callback (file, NULL, error, callback_data);
1400 g_error_free (error);
1401 }
1402 }
1403 }
1404 else if (file->details->mount != NULL &&
1405 g_mount_can_unmount (file->details->mount))
1406 {
1407 data = g_new0 (UnmountData, 1);
1408 data->file = nautilus_file_ref (file);
1409 data->callback = callback;
1410 data->callback_data = callback_data;
1411 nautilus_file_operations_unmount_mount_full (NULL, file->details->mount, NULL, FALSE, TRUE, unmount_done, data);
1412 }
1413 else if (callback)
1414 {
1415 callback (file, NULL, NULL, callback_data);
1416 }
1417 }
1418
1419 void
nautilus_file_eject(NautilusFile * file,GMountOperation * mount_op,GCancellable * cancellable,NautilusFileOperationCallback callback,gpointer callback_data)1420 nautilus_file_eject (NautilusFile *file,
1421 GMountOperation *mount_op,
1422 GCancellable *cancellable,
1423 NautilusFileOperationCallback callback,
1424 gpointer callback_data)
1425 {
1426 GError *error;
1427 UnmountData *data;
1428
1429 if (file->details->can_eject)
1430 {
1431 if (NAUTILUS_FILE_GET_CLASS (file)->eject != NULL)
1432 {
1433 NAUTILUS_FILE_GET_CLASS (file)->eject (file, mount_op, cancellable, callback, callback_data);
1434 }
1435 else
1436 {
1437 if (callback)
1438 {
1439 error = NULL;
1440 g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
1441 _("This file cannot be ejected"));
1442 callback (file, NULL, error, callback_data);
1443 g_error_free (error);
1444 }
1445 }
1446 }
1447 else if (file->details->mount != NULL &&
1448 g_mount_can_eject (file->details->mount))
1449 {
1450 data = g_new0 (UnmountData, 1);
1451 data->file = nautilus_file_ref (file);
1452 data->callback = callback;
1453 data->callback_data = callback_data;
1454 nautilus_file_operations_unmount_mount_full (NULL, file->details->mount, NULL, TRUE, TRUE, unmount_done, data);
1455 }
1456 else if (callback)
1457 {
1458 callback (file, NULL, NULL, callback_data);
1459 }
1460 }
1461
1462 void
nautilus_file_start(NautilusFile * file,GMountOperation * start_op,GCancellable * cancellable,NautilusFileOperationCallback callback,gpointer callback_data)1463 nautilus_file_start (NautilusFile *file,
1464 GMountOperation *start_op,
1465 GCancellable *cancellable,
1466 NautilusFileOperationCallback callback,
1467 gpointer callback_data)
1468 {
1469 GError *error;
1470
1471 if ((file->details->can_start || file->details->can_start_degraded) &&
1472 NAUTILUS_FILE_GET_CLASS (file)->start != NULL)
1473 {
1474 NAUTILUS_FILE_GET_CLASS (file)->start (file, start_op, cancellable, callback, callback_data);
1475 }
1476 else
1477 {
1478 if (callback)
1479 {
1480 error = NULL;
1481 g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
1482 _("This file cannot be started"));
1483 callback (file, NULL, error, callback_data);
1484 g_error_free (error);
1485 }
1486 }
1487 }
1488
1489 static void
file_stop_callback(GObject * source_object,GAsyncResult * res,gpointer callback_data)1490 file_stop_callback (GObject *source_object,
1491 GAsyncResult *res,
1492 gpointer callback_data)
1493 {
1494 NautilusFileOperation *op;
1495 gboolean stopped;
1496 GError *error;
1497
1498 op = callback_data;
1499
1500 error = NULL;
1501 stopped = g_drive_stop_finish (G_DRIVE (source_object),
1502 res, &error);
1503
1504 if (!stopped &&
1505 error->domain == G_IO_ERROR &&
1506 (error->code == G_IO_ERROR_FAILED_HANDLED ||
1507 error->code == G_IO_ERROR_CANCELLED))
1508 {
1509 g_error_free (error);
1510 error = NULL;
1511 }
1512
1513 nautilus_file_operation_complete (op, NULL, error);
1514 if (error)
1515 {
1516 g_error_free (error);
1517 }
1518 }
1519
1520 void
nautilus_file_stop(NautilusFile * file,GMountOperation * mount_op,GCancellable * cancellable,NautilusFileOperationCallback callback,gpointer callback_data)1521 nautilus_file_stop (NautilusFile *file,
1522 GMountOperation *mount_op,
1523 GCancellable *cancellable,
1524 NautilusFileOperationCallback callback,
1525 gpointer callback_data)
1526 {
1527 GError *error;
1528
1529 if (NAUTILUS_FILE_GET_CLASS (file)->stop != NULL)
1530 {
1531 if (file->details->can_stop)
1532 {
1533 NAUTILUS_FILE_GET_CLASS (file)->stop (file, mount_op, cancellable, callback, callback_data);
1534 }
1535 else
1536 {
1537 if (callback)
1538 {
1539 error = NULL;
1540 g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
1541 _("This file cannot be stopped"));
1542 callback (file, NULL, error, callback_data);
1543 g_error_free (error);
1544 }
1545 }
1546 }
1547 else
1548 {
1549 GDrive *drive;
1550
1551 drive = NULL;
1552 if (file->details->mount != NULL)
1553 {
1554 drive = g_mount_get_drive (file->details->mount);
1555 }
1556
1557 if (drive != NULL && g_drive_can_stop (drive))
1558 {
1559 NautilusFileOperation *op;
1560
1561 op = nautilus_file_operation_new (file, callback, callback_data);
1562 if (cancellable)
1563 {
1564 g_object_unref (op->cancellable);
1565 op->cancellable = g_object_ref (cancellable);
1566 }
1567
1568 g_drive_stop (drive,
1569 G_MOUNT_UNMOUNT_NONE,
1570 mount_op,
1571 op->cancellable,
1572 file_stop_callback,
1573 op);
1574 }
1575 else
1576 {
1577 if (callback)
1578 {
1579 error = NULL;
1580 g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
1581 _("This file cannot be stopped"));
1582 callback (file, NULL, error, callback_data);
1583 g_error_free (error);
1584 }
1585 }
1586
1587 if (drive != NULL)
1588 {
1589 g_object_unref (drive);
1590 }
1591 }
1592 }
1593
1594 void
nautilus_file_poll_for_media(NautilusFile * file)1595 nautilus_file_poll_for_media (NautilusFile *file)
1596 {
1597 if (file->details->can_poll_for_media)
1598 {
1599 if (NAUTILUS_FILE_GET_CLASS (file)->stop != NULL)
1600 {
1601 NAUTILUS_FILE_GET_CLASS (file)->poll_for_media (file);
1602 }
1603 }
1604 else if (file->details->mount != NULL)
1605 {
1606 GDrive *drive;
1607 drive = g_mount_get_drive (file->details->mount);
1608 if (drive != NULL)
1609 {
1610 g_drive_poll_for_media (drive,
1611 NULL, /* cancellable */
1612 NULL, /* GAsyncReadyCallback */
1613 NULL); /* user_data */
1614 g_object_unref (drive);
1615 }
1616 }
1617 }
1618
1619 /**
1620 * nautilus_file_can_rename:
1621 *
1622 * Check whether the user is allowed to change the name of the file.
1623 *
1624 * @file: The file to check.
1625 *
1626 * Return value: FALSE if the user is definitely not allowed to change
1627 * the name of the file. If the user is allowed to change the name, or
1628 * the code can't tell whether the user is allowed to change the name,
1629 * returns TRUE (so rename failures must always be handled).
1630 */
1631 gboolean
nautilus_file_can_rename(NautilusFile * file)1632 nautilus_file_can_rename (NautilusFile *file)
1633 {
1634 gboolean can_rename;
1635
1636 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1637
1638 /* Nonexistent files can't be renamed. */
1639 if (nautilus_file_is_gone (file))
1640 {
1641 return FALSE;
1642 }
1643
1644 /* Self-owned files can't be renamed */
1645 if (nautilus_file_is_self_owned (file))
1646 {
1647 return FALSE;
1648 }
1649
1650 if (nautilus_file_is_home (file))
1651 {
1652 return FALSE;
1653 }
1654
1655 can_rename = TRUE;
1656
1657 if (!can_rename)
1658 {
1659 return FALSE;
1660 }
1661
1662 return file->details->can_rename;
1663 }
1664
1665 gboolean
nautilus_file_can_delete(NautilusFile * file)1666 nautilus_file_can_delete (NautilusFile *file)
1667 {
1668 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1669
1670 /* Nonexistent files can't be deleted. */
1671 if (nautilus_file_is_gone (file))
1672 {
1673 return FALSE;
1674 }
1675
1676 /* Self-owned files can't be deleted */
1677 if (nautilus_file_is_self_owned (file))
1678 {
1679 return FALSE;
1680 }
1681
1682 return file->details->can_delete;
1683 }
1684
1685 gboolean
nautilus_file_can_trash(NautilusFile * file)1686 nautilus_file_can_trash (NautilusFile *file)
1687 {
1688 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1689
1690 /* Nonexistent files can't be deleted. */
1691 if (nautilus_file_is_gone (file))
1692 {
1693 return FALSE;
1694 }
1695
1696 /* Self-owned files can't be deleted */
1697 if (nautilus_file_is_self_owned (file))
1698 {
1699 return FALSE;
1700 }
1701
1702 return file->details->can_trash;
1703 }
1704
1705 GFile *
nautilus_file_get_location(NautilusFile * file)1706 nautilus_file_get_location (NautilusFile *file)
1707 {
1708 g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
1709
1710 return nautilus_file_info_get_location (NAUTILUS_FILE_INFO (file));
1711 }
1712
1713 /* Return the actual uri associated with the passed-in file. */
1714 char *
nautilus_file_get_uri(NautilusFile * file)1715 nautilus_file_get_uri (NautilusFile *file)
1716 {
1717 g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
1718
1719 return nautilus_file_info_get_uri (NAUTILUS_FILE_INFO (file));
1720 }
1721
1722 char *
nautilus_file_get_uri_scheme(NautilusFile * file)1723 nautilus_file_get_uri_scheme (NautilusFile *file)
1724 {
1725 g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
1726
1727 return nautilus_file_info_get_uri_scheme (NAUTILUS_FILE_INFO (file));
1728 }
1729
1730
1731 gboolean
nautilus_file_opens_in_view(NautilusFile * file)1732 nautilus_file_opens_in_view (NautilusFile *file)
1733 {
1734 return nautilus_file_is_directory (file);
1735 }
1736
1737 NautilusFileOperation *
nautilus_file_operation_new(NautilusFile * file,NautilusFileOperationCallback callback,gpointer callback_data)1738 nautilus_file_operation_new (NautilusFile *file,
1739 NautilusFileOperationCallback callback,
1740 gpointer callback_data)
1741 {
1742 NautilusFileOperation *op;
1743
1744 op = g_new0 (NautilusFileOperation, 1);
1745 op->file = nautilus_file_ref (file);
1746 op->callback = callback;
1747 op->callback_data = callback_data;
1748 op->cancellable = g_cancellable_new ();
1749
1750 op->file->details->operations_in_progress = g_list_prepend
1751 (op->file->details->operations_in_progress, op);
1752
1753 return op;
1754 }
1755
1756 static void
nautilus_file_operation_remove(NautilusFileOperation * op)1757 nautilus_file_operation_remove (NautilusFileOperation *op)
1758 {
1759 GList *l;
1760 NautilusFile *file;
1761
1762 op->file->details->operations_in_progress = g_list_remove
1763 (op->file->details->operations_in_progress, op);
1764
1765
1766 for (l = op->files; l != NULL; l = l->next)
1767 {
1768 file = NAUTILUS_FILE (l->data);
1769 file->details->operations_in_progress = g_list_remove
1770 (file->details->operations_in_progress, op);
1771 }
1772 }
1773
1774 void
nautilus_file_operation_free(NautilusFileOperation * op)1775 nautilus_file_operation_free (NautilusFileOperation *op)
1776 {
1777 nautilus_file_operation_remove (op);
1778
1779 if (op->files == NULL)
1780 {
1781 nautilus_file_unref (op->file);
1782 }
1783 else
1784 {
1785 nautilus_file_list_free (op->files);
1786 }
1787
1788 g_object_unref (op->cancellable);
1789 if (op->free_data)
1790 {
1791 op->free_data (op->data);
1792 }
1793
1794 if (op->undo_info != NULL)
1795 {
1796 nautilus_file_undo_manager_set_action (op->undo_info);
1797 g_object_unref (op->undo_info);
1798 }
1799
1800 g_free (op);
1801 }
1802
1803 void
nautilus_file_operation_complete(NautilusFileOperation * op,GFile * result_file,GError * error)1804 nautilus_file_operation_complete (NautilusFileOperation *op,
1805 GFile *result_file,
1806 GError *error)
1807 {
1808 /* Claim that something changed even if the operation failed.
1809 * This makes it easier for some clients who see the "reverting"
1810 * as "changing back".
1811 */
1812 nautilus_file_operation_remove (op);
1813
1814 if (op->files == NULL)
1815 {
1816 nautilus_file_changed (op->file);
1817 }
1818
1819 if (op->callback)
1820 {
1821 (*op->callback)(op->file, result_file, error, op->callback_data);
1822 }
1823
1824 if (error != NULL)
1825 {
1826 g_clear_object (&op->undo_info);
1827 }
1828
1829 nautilus_file_operation_free (op);
1830 }
1831
1832 void
nautilus_file_operation_cancel(NautilusFileOperation * op)1833 nautilus_file_operation_cancel (NautilusFileOperation *op)
1834 {
1835 /* Cancel the operation if it's still in progress. */
1836 g_cancellable_cancel (op->cancellable);
1837 }
1838
1839 static void
rename_get_info_callback(GObject * source_object,GAsyncResult * res,gpointer callback_data)1840 rename_get_info_callback (GObject *source_object,
1841 GAsyncResult *res,
1842 gpointer callback_data)
1843 {
1844 NautilusFileOperation *op;
1845 NautilusDirectory *directory;
1846 NautilusFile *existing_file;
1847 char *old_uri;
1848 char *new_uri;
1849 const char *new_name;
1850 GFileInfo *new_info;
1851 GError *error;
1852
1853 op = callback_data;
1854
1855 error = NULL;
1856 new_info = g_file_query_info_finish (G_FILE (source_object), res, &error);
1857 if (new_info != NULL)
1858 {
1859 g_autoptr (NautilusTagManager) tag_manager = nautilus_tag_manager_get ();
1860 g_autoptr (GFile) old_location = NULL;
1861 g_autoptr (GFile) new_location = NULL;
1862
1863 directory = op->file->details->directory;
1864
1865 new_name = g_file_info_get_name (new_info);
1866
1867 /* If there was another file by the same name in this
1868 * directory and it is not the same file that we are
1869 * renaming, mark it gone.
1870 */
1871 existing_file = nautilus_directory_find_file_by_name (directory, new_name);
1872 if (existing_file != NULL && existing_file != op->file)
1873 {
1874 nautilus_file_mark_gone (existing_file);
1875 nautilus_file_changed (existing_file);
1876 }
1877
1878 old_location = nautilus_file_get_location (op->file);
1879 old_uri = g_file_get_uri (old_location);
1880
1881 update_info_and_name (op->file, new_info);
1882
1883 new_location = nautilus_file_get_location (op->file);
1884 new_uri = g_file_get_uri (new_location);
1885
1886 nautilus_directory_moved (old_uri, new_uri);
1887 nautilus_tag_manager_update_moved_uris (tag_manager, old_location, new_location);
1888
1889 g_free (new_uri);
1890 g_free (old_uri);
1891
1892 g_object_unref (new_info);
1893 }
1894 nautilus_file_operation_complete (op, NULL, error);
1895 if (error)
1896 {
1897 g_error_free (error);
1898 }
1899 }
1900
1901 static void
rename_callback(GObject * source_object,GAsyncResult * res,gpointer callback_data)1902 rename_callback (GObject *source_object,
1903 GAsyncResult *res,
1904 gpointer callback_data)
1905 {
1906 NautilusFileOperation *op;
1907 GFile *new_file;
1908 GError *error;
1909
1910 op = callback_data;
1911
1912 error = NULL;
1913 new_file = g_file_set_display_name_finish (G_FILE (source_object),
1914 res, &error);
1915
1916 if (new_file != NULL)
1917 {
1918 if (op->undo_info != NULL)
1919 {
1920 nautilus_file_undo_info_rename_set_data_post (NAUTILUS_FILE_UNDO_INFO_RENAME (op->undo_info),
1921 new_file);
1922 }
1923 g_file_query_info_async (new_file,
1924 NAUTILUS_FILE_DEFAULT_ATTRIBUTES,
1925 0,
1926 G_PRIORITY_DEFAULT,
1927 op->cancellable,
1928 rename_get_info_callback, op);
1929 }
1930 else
1931 {
1932 nautilus_file_operation_complete (op, NULL, error);
1933 g_error_free (error);
1934 }
1935 }
1936
1937 static gboolean
name_is(NautilusFile * file,const char * new_name)1938 name_is (NautilusFile *file,
1939 const char *new_name)
1940 {
1941 const char *old_name;
1942 old_name = file->details->name;
1943 return strcmp (new_name, old_name) == 0;
1944 }
1945
1946 static gchar *
nautilus_file_can_rename_file(NautilusFile * file,const char * new_name,NautilusFileOperationCallback callback,gpointer callback_data)1947 nautilus_file_can_rename_file (NautilusFile *file,
1948 const char *new_name,
1949 NautilusFileOperationCallback callback,
1950 gpointer callback_data)
1951 {
1952 GError *error;
1953 gchar *new_file_name;
1954
1955 /* Return an error for incoming names containing path separators.
1956 * But not for .desktop files as '/' are allowed for them */
1957 if (strstr (new_name, "/") != NULL)
1958 {
1959 error = g_error_new (G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
1960 _("Slashes are not allowed in filenames"));
1961 if (callback != NULL)
1962 {
1963 (*callback)(file, NULL, error, callback_data);
1964 }
1965 g_error_free (error);
1966 return NULL;
1967 }
1968
1969 /* Can't rename a file that's already gone.
1970 * We need to check this here because there may be a new
1971 * file with the same name.
1972 */
1973 if (nautilus_file_rename_handle_file_gone (file, callback, callback_data))
1974 {
1975 return NULL;
1976 }
1977
1978 /* Test the name-hasn't-changed case explicitly, for two reasons.
1979 * (1) rename returns an error if new & old are same.
1980 * (2) We don't want to send file-changed signal if nothing changed.
1981 */
1982 if (name_is (file, new_name))
1983 {
1984 if (callback != NULL)
1985 {
1986 (*callback)(file, NULL, NULL, callback_data);
1987 }
1988 return NULL;
1989 }
1990
1991 /* Self-owned files can't be renamed. Test the name-not-actually-changing
1992 * case before this case.
1993 */
1994 if (nautilus_file_is_self_owned (file))
1995 {
1996 /* Claim that something changed even if the rename
1997 * failed. This makes it easier for some clients who
1998 * see the "reverting" to the old name as "changing
1999 * back".
2000 */
2001 nautilus_file_changed (file);
2002 error = g_error_new (G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
2003 _("Toplevel files cannot be renamed"));
2004
2005 if (callback != NULL)
2006 {
2007 (*callback)(file, NULL, error, callback_data);
2008 }
2009 g_error_free (error);
2010
2011 return NULL;
2012 }
2013
2014 new_file_name = g_strdup (new_name);
2015
2016 return new_file_name;
2017 }
2018
2019 void
nautilus_file_rename(NautilusFile * file,const char * new_name,NautilusFileOperationCallback callback,gpointer callback_data)2020 nautilus_file_rename (NautilusFile *file,
2021 const char *new_name,
2022 NautilusFileOperationCallback callback,
2023 gpointer callback_data)
2024 {
2025 NautilusFileOperation *op;
2026 char *old_name;
2027 char *new_file_name;
2028 GFile *location;
2029
2030 g_return_if_fail (NAUTILUS_IS_FILE (file));
2031 g_return_if_fail (new_name != NULL);
2032 g_return_if_fail (callback != NULL);
2033
2034 new_file_name = nautilus_file_can_rename_file (file,
2035 new_name,
2036 callback,
2037 callback_data);
2038
2039 if (new_file_name == NULL)
2040 {
2041 return;
2042 }
2043
2044 /* Set up a renaming operation. */
2045 op = nautilus_file_operation_new (file, callback, callback_data);
2046 op->is_rename = TRUE;
2047 location = nautilus_file_get_location (file);
2048
2049 /* Tell the undo manager a rename is taking place */
2050 if (!nautilus_file_undo_manager_is_operating ())
2051 {
2052 op->undo_info = nautilus_file_undo_info_rename_new ();
2053
2054 old_name = nautilus_file_get_display_name (file);
2055 nautilus_file_undo_info_rename_set_data_pre (NAUTILUS_FILE_UNDO_INFO_RENAME (op->undo_info),
2056 location, old_name, new_file_name);
2057 g_free (old_name);
2058 }
2059
2060 /* Do the renaming. */
2061 g_file_set_display_name_async (location,
2062 new_file_name,
2063 G_PRIORITY_DEFAULT,
2064 op->cancellable,
2065 rename_callback,
2066 op);
2067 g_free (new_file_name);
2068 g_object_unref (location);
2069 }
2070
2071 gboolean
nautilus_file_rename_handle_file_gone(NautilusFile * file,NautilusFileOperationCallback callback,gpointer callback_data)2072 nautilus_file_rename_handle_file_gone (NautilusFile *file,
2073 NautilusFileOperationCallback callback,
2074 gpointer callback_data)
2075 {
2076 GError *error;
2077
2078 if (nautilus_file_is_gone (file))
2079 {
2080 /* Claim that something changed even if the rename
2081 * failed. This makes it easier for some clients who
2082 * see the "reverting" to the old name as "changing
2083 * back".
2084 */
2085 nautilus_file_changed (file);
2086 error = g_error_new (G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
2087 _("File not found"));
2088 if (callback)
2089 {
2090 (*callback)(file, NULL, error, callback_data);
2091 }
2092 g_error_free (error);
2093 return TRUE;
2094 }
2095
2096 return FALSE;
2097 }
2098
2099 typedef struct
2100 {
2101 NautilusFileOperation *op;
2102 NautilusFile *file;
2103 } BatchRenameData;
2104
2105 static void
batch_rename_get_info_callback(GObject * source_object,GAsyncResult * res,gpointer callback_data)2106 batch_rename_get_info_callback (GObject *source_object,
2107 GAsyncResult *res,
2108 gpointer callback_data)
2109 {
2110 NautilusFileOperation *op;
2111 NautilusDirectory *directory;
2112 NautilusFile *existing_file;
2113 char *old_uri;
2114 char *new_uri;
2115 const char *new_name;
2116 GFileInfo *new_info;
2117 GError *error;
2118 BatchRenameData *data;
2119
2120 data = callback_data;
2121
2122 op = data->op;
2123 op->file = data->file;
2124
2125 error = NULL;
2126 new_info = g_file_query_info_finish (G_FILE (source_object), res, &error);
2127 if (new_info != NULL)
2128 {
2129 old_uri = nautilus_file_get_uri (op->file);
2130
2131 new_name = g_file_info_get_name (new_info);
2132
2133 directory = op->file->details->directory;
2134
2135 /* If there was another file by the same name in this
2136 * directory and it is not the same file that we are
2137 * renaming, mark it gone.
2138 */
2139 existing_file = nautilus_directory_find_file_by_name (directory, new_name);
2140 if (existing_file != NULL && existing_file != op->file)
2141 {
2142 nautilus_file_mark_gone (existing_file);
2143 nautilus_file_changed (existing_file);
2144 }
2145
2146 update_info_and_name (op->file, new_info);
2147
2148 new_uri = nautilus_file_get_uri (op->file);
2149 nautilus_directory_moved (old_uri, new_uri);
2150 g_free (new_uri);
2151 g_free (old_uri);
2152 g_object_unref (new_info);
2153 }
2154
2155 op->renamed_files++;
2156
2157 if (op->files == NULL ||
2158 op->renamed_files + op->skipped_files == g_list_length (op->files))
2159 {
2160 nautilus_file_operation_complete (op, NULL, error);
2161 }
2162
2163 g_free (data);
2164
2165 if (error)
2166 {
2167 g_error_free (error);
2168 }
2169 }
2170
2171 static void
real_batch_rename(GList * files,GList * new_names,NautilusFileOperationCallback callback,gpointer callback_data)2172 real_batch_rename (GList *files,
2173 GList *new_names,
2174 NautilusFileOperationCallback callback,
2175 gpointer callback_data)
2176 {
2177 GList *l1, *l2, *old_files, *new_files;
2178 NautilusFileOperation *op;
2179 GFile *location;
2180 GString *new_name;
2181 NautilusFile *file;
2182 GError *error;
2183 GFile *new_file;
2184 BatchRenameData *data;
2185
2186 error = NULL;
2187 old_files = NULL;
2188 new_files = NULL;
2189
2190 /* Set up a batch renaming operation. */
2191 op = nautilus_file_operation_new (files->data, callback, callback_data);
2192 op->files = nautilus_file_list_copy (files);
2193 op->renamed_files = 0;
2194 op->skipped_files = 0;
2195
2196 for (l1 = files->next; l1 != NULL; l1 = l1->next)
2197 {
2198 file = NAUTILUS_FILE (l1->data);
2199
2200 file->details->operations_in_progress = g_list_prepend (file->details->operations_in_progress,
2201 op);
2202 }
2203
2204 for (l1 = files, l2 = new_names; l1 != NULL && l2 != NULL; l1 = l1->next, l2 = l2->next)
2205 {
2206 g_autofree gchar *new_file_name = NULL;
2207 file = NAUTILUS_FILE (l1->data);
2208 new_name = l2->data;
2209
2210 location = nautilus_file_get_location (file);
2211
2212 new_file_name = nautilus_file_can_rename_file (file,
2213 new_name->str,
2214 callback,
2215 callback_data);
2216
2217 if (new_file_name == NULL)
2218 {
2219 op->skipped_files++;
2220
2221 continue;
2222 }
2223
2224 g_assert (G_IS_FILE (location));
2225
2226 /* Do the renaming. */
2227 new_file = g_file_set_display_name (location,
2228 new_file_name,
2229 op->cancellable,
2230 &error);
2231
2232 data = g_new0 (BatchRenameData, 1);
2233 data->op = op;
2234 data->file = file;
2235
2236 g_file_query_info_async (new_file,
2237 NAUTILUS_FILE_DEFAULT_ATTRIBUTES,
2238 0,
2239 G_PRIORITY_DEFAULT,
2240 op->cancellable,
2241 batch_rename_get_info_callback,
2242 data);
2243
2244 if (error != NULL)
2245 {
2246 g_warning ("Batch rename for file \"%s\" failed", nautilus_file_get_name (file));
2247 g_error_free (error);
2248 error = NULL;
2249
2250 op->skipped_files++;
2251 }
2252 else
2253 {
2254 old_files = g_list_append (old_files, location);
2255 new_files = g_list_append (new_files, new_file);
2256 }
2257 }
2258
2259 /* Tell the undo manager a batch rename is taking place if at least
2260 * a file has been renamed*/
2261 if (!nautilus_file_undo_manager_is_operating () && op->skipped_files != g_list_length (files))
2262 {
2263 op->undo_info = nautilus_file_undo_info_batch_rename_new (g_list_length (new_files));
2264
2265 nautilus_file_undo_info_batch_rename_set_data_pre (NAUTILUS_FILE_UNDO_INFO_BATCH_RENAME (op->undo_info),
2266 old_files);
2267
2268 nautilus_file_undo_info_batch_rename_set_data_post (NAUTILUS_FILE_UNDO_INFO_BATCH_RENAME (op->undo_info),
2269 new_files);
2270
2271 nautilus_file_undo_manager_set_action (op->undo_info);
2272 }
2273
2274 if (op->skipped_files == g_list_length (files))
2275 {
2276 nautilus_file_operation_complete (op, NULL, error);
2277 }
2278 }
2279
2280 void
nautilus_file_batch_rename(GList * files,GList * new_names,NautilusFileOperationCallback callback,gpointer callback_data)2281 nautilus_file_batch_rename (GList *files,
2282 GList *new_names,
2283 NautilusFileOperationCallback callback,
2284 gpointer callback_data)
2285 {
2286 real_batch_rename (files,
2287 new_names,
2288 callback,
2289 callback_data);
2290 }
2291
2292 gboolean
nautilus_file_rename_in_progress(NautilusFile * file)2293 nautilus_file_rename_in_progress (NautilusFile *file)
2294 {
2295 GList *node;
2296 NautilusFileOperation *op;
2297
2298 for (node = file->details->operations_in_progress; node != NULL; node = node->next)
2299 {
2300 op = node->data;
2301 if (op->is_rename)
2302 {
2303 return TRUE;
2304 }
2305 }
2306 return FALSE;
2307 }
2308
2309 void
nautilus_file_cancel(NautilusFile * file,NautilusFileOperationCallback callback,gpointer callback_data)2310 nautilus_file_cancel (NautilusFile *file,
2311 NautilusFileOperationCallback callback,
2312 gpointer callback_data)
2313 {
2314 GList *node, *next;
2315 NautilusFileOperation *op;
2316
2317 for (node = file->details->operations_in_progress; node != NULL; node = next)
2318 {
2319 next = node->next;
2320 op = node->data;
2321
2322 g_assert (op->file == file);
2323 if (op->callback == callback && op->callback_data == callback_data)
2324 {
2325 nautilus_file_operation_cancel (op);
2326 }
2327 }
2328 }
2329
2330 gboolean
nautilus_file_matches_uri(NautilusFile * file,const char * match_uri)2331 nautilus_file_matches_uri (NautilusFile *file,
2332 const char *match_uri)
2333 {
2334 GFile *match_file, *location;
2335 gboolean result;
2336
2337 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
2338 g_return_val_if_fail (match_uri != NULL, FALSE);
2339
2340 location = nautilus_file_get_location (file);
2341 match_file = g_file_new_for_uri (match_uri);
2342 result = g_file_equal (location, match_file);
2343 g_object_unref (location);
2344 g_object_unref (match_file);
2345
2346 return result;
2347 }
2348
2349 int
nautilus_file_compare_location(NautilusFile * file_1,NautilusFile * file_2)2350 nautilus_file_compare_location (NautilusFile *file_1,
2351 NautilusFile *file_2)
2352 {
2353 GFile *loc_a, *loc_b;
2354 gboolean res;
2355
2356 loc_a = nautilus_file_get_location (file_1);
2357 loc_b = nautilus_file_get_location (file_2);
2358
2359 res = !g_file_equal (loc_a, loc_b);
2360
2361 g_object_unref (loc_a);
2362 g_object_unref (loc_b);
2363
2364 return (gint) res;
2365 }
2366
2367 /**
2368 * nautilus_file_has_local_path:
2369 *
2370 * @file: a #NautilusFile
2371 *
2372 * Checks whether this file has an obtainable local paths. Usually, this means
2373 * the local path can be obtained by calling g_file_get_path(); this includes
2374 * native and FUSE files. As an exception, the local URI for files in recent://
2375 * can only be obtained from the G_FILE_ATTRIBUTE_STANDARD_TARGET_URI attribute.
2376 *
2377 * Returns: %TRUE if a local path is known to be obtainable for this file.
2378 */
2379 gboolean
nautilus_file_has_local_path(NautilusFile * file)2380 nautilus_file_has_local_path (NautilusFile *file)
2381 {
2382 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
2383
2384 return nautilus_directory_is_local_or_fuse (file->details->directory);
2385 }
2386
2387 static void
update_link(NautilusFile * link_file,NautilusFile * target_file)2388 update_link (NautilusFile *link_file,
2389 NautilusFile *target_file)
2390 {
2391 g_assert (NAUTILUS_IS_FILE (link_file));
2392 g_assert (NAUTILUS_IS_FILE (target_file));
2393
2394 /* FIXME bugzilla.gnome.org 42044: If we don't put any code
2395 * here then the hash table is a waste of time.
2396 */
2397 }
2398
2399 static GList *
get_link_files(NautilusFile * target_file)2400 get_link_files (NautilusFile *target_file)
2401 {
2402 char *uri;
2403 GList **link_files;
2404
2405 if (symbolic_links == NULL)
2406 {
2407 link_files = NULL;
2408 }
2409 else
2410 {
2411 uri = nautilus_file_get_uri (target_file);
2412 link_files = g_hash_table_lookup (symbolic_links, uri);
2413 g_free (uri);
2414 }
2415 if (link_files)
2416 {
2417 return nautilus_file_list_copy (*link_files);
2418 }
2419 return NULL;
2420 }
2421
2422 static void
update_links_if_target(NautilusFile * target_file)2423 update_links_if_target (NautilusFile *target_file)
2424 {
2425 GList *link_files, *p;
2426
2427 link_files = get_link_files (target_file);
2428 for (p = link_files; p != NULL; p = p->next)
2429 {
2430 update_link (NAUTILUS_FILE (p->data), target_file);
2431 }
2432 nautilus_file_list_free (link_files);
2433 }
2434
2435 static gboolean
update_info_internal(NautilusFile * file,GFileInfo * info,gboolean update_name)2436 update_info_internal (NautilusFile *file,
2437 GFileInfo *info,
2438 gboolean update_name)
2439 {
2440 GList *node;
2441 gboolean changed;
2442 gboolean is_symlink, is_hidden, is_mountpoint;
2443 gboolean has_permissions;
2444 guint32 permissions;
2445 gboolean can_read, can_write, can_execute, can_delete, can_trash, can_rename, can_mount, can_unmount, can_eject;
2446 gboolean can_start, can_start_degraded, can_stop, can_poll_for_media, is_media_check_automatic;
2447 GDriveStartStopType start_stop_type;
2448 gboolean thumbnailing_failed;
2449 int uid, gid;
2450 goffset size;
2451 int sort_order;
2452 time_t atime, mtime, btime;
2453 time_t trash_time;
2454 time_t recency;
2455 GTimeVal g_trash_time;
2456 const char *time_string;
2457 const char *symlink_name, *mime_type, *selinux_context, *name, *thumbnail_path;
2458 GFileType file_type;
2459 GIcon *icon;
2460 char *old_activation_uri;
2461 const char *activation_uri;
2462 const char *description;
2463 const char *filesystem_id;
2464 const char *trash_orig_path;
2465 const char *group, *owner, *owner_real;
2466 gboolean free_owner, free_group;
2467
2468 if (file->details->is_gone)
2469 {
2470 return FALSE;
2471 }
2472
2473 if (info == NULL)
2474 {
2475 nautilus_file_mark_gone (file);
2476 return TRUE;
2477 }
2478
2479 file->details->file_info_is_up_to_date = TRUE;
2480
2481 /* FIXME bugzilla.gnome.org 42044: Need to let links that
2482 * point to the old name know that the file has been renamed.
2483 */
2484
2485 remove_from_link_hash_table (file);
2486
2487 changed = FALSE;
2488
2489 if (!file->details->got_file_info)
2490 {
2491 changed = TRUE;
2492 }
2493 file->details->got_file_info = TRUE;
2494
2495 changed |= nautilus_file_set_display_name (file,
2496 g_file_info_get_display_name (info),
2497 g_file_info_get_edit_name (info),
2498 FALSE);
2499
2500 file_type = g_file_info_get_file_type (info);
2501 if (file->details->type != file_type)
2502 {
2503 changed = TRUE;
2504 }
2505 file->details->type = file_type;
2506
2507 if (!file->details->got_custom_activation_uri &&
2508 (g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_STANDARD_IS_VIRTUAL) ||
2509 file_type == G_FILE_TYPE_SHORTCUT ||
2510 nautilus_file_is_in_recent (file)))
2511 {
2512 activation_uri = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI);
2513 if (activation_uri == NULL)
2514 {
2515 if (file->details->activation_uri)
2516 {
2517 g_free (file->details->activation_uri);
2518 file->details->activation_uri = NULL;
2519 changed = TRUE;
2520 }
2521 }
2522 else
2523 {
2524 old_activation_uri = file->details->activation_uri;
2525 file->details->activation_uri = g_strdup (activation_uri);
2526
2527 if (old_activation_uri)
2528 {
2529 if (strcmp (old_activation_uri,
2530 file->details->activation_uri) != 0)
2531 {
2532 changed = TRUE;
2533 }
2534 g_free (old_activation_uri);
2535 }
2536 else
2537 {
2538 changed = TRUE;
2539 }
2540 }
2541 }
2542
2543 is_symlink = g_file_info_get_is_symlink (info);
2544 if (file->details->is_symlink != is_symlink)
2545 {
2546 changed = TRUE;
2547 }
2548 file->details->is_symlink = is_symlink;
2549
2550 is_hidden = g_file_info_get_is_hidden (info) || g_file_info_get_is_backup (info);
2551 if (file->details->is_hidden != is_hidden)
2552 {
2553 changed = TRUE;
2554 }
2555 file->details->is_hidden = is_hidden;
2556
2557 is_mountpoint = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT);
2558 if (file->details->is_mountpoint != is_mountpoint)
2559 {
2560 changed = TRUE;
2561 }
2562 file->details->is_mountpoint = is_mountpoint;
2563
2564 has_permissions = g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE);
2565 permissions = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE);
2566 if (file->details->has_permissions != has_permissions ||
2567 file->details->permissions != permissions)
2568 {
2569 changed = TRUE;
2570 }
2571 file->details->has_permissions = has_permissions;
2572 file->details->permissions = permissions;
2573
2574 /* We default to TRUE for this if we can't know */
2575 can_read = TRUE;
2576 can_write = TRUE;
2577 can_execute = TRUE;
2578 can_delete = TRUE;
2579 can_rename = TRUE;
2580 can_trash = FALSE;
2581 can_mount = FALSE;
2582 can_unmount = FALSE;
2583 can_eject = FALSE;
2584 can_start = FALSE;
2585 can_start_degraded = FALSE;
2586 can_stop = FALSE;
2587 can_poll_for_media = FALSE;
2588 is_media_check_automatic = FALSE;
2589 start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
2590 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ))
2591 {
2592 can_read = g_file_info_get_attribute_boolean (info,
2593 G_FILE_ATTRIBUTE_ACCESS_CAN_READ);
2594 }
2595 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE))
2596 {
2597 can_write = g_file_info_get_attribute_boolean (info,
2598 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
2599 }
2600 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE))
2601 {
2602 can_execute = g_file_info_get_attribute_boolean (info,
2603 G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE);
2604 }
2605 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE))
2606 {
2607 can_delete = g_file_info_get_attribute_boolean (info,
2608 G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE);
2609 }
2610 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH))
2611 {
2612 can_trash = g_file_info_get_attribute_boolean (info,
2613 G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH);
2614 }
2615 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME))
2616 {
2617 can_rename = g_file_info_get_attribute_boolean (info,
2618 G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME);
2619 }
2620 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT))
2621 {
2622 can_mount = g_file_info_get_attribute_boolean (info,
2623 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT);
2624 }
2625 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT))
2626 {
2627 can_unmount = g_file_info_get_attribute_boolean (info,
2628 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT);
2629 }
2630 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT))
2631 {
2632 can_eject = g_file_info_get_attribute_boolean (info,
2633 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT);
2634 }
2635 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START))
2636 {
2637 can_start = g_file_info_get_attribute_boolean (info,
2638 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START);
2639 }
2640 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START_DEGRADED))
2641 {
2642 can_start_degraded = g_file_info_get_attribute_boolean (info,
2643 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START_DEGRADED);
2644 }
2645 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_STOP))
2646 {
2647 can_stop = g_file_info_get_attribute_boolean (info,
2648 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_STOP);
2649 }
2650 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_START_STOP_TYPE))
2651 {
2652 start_stop_type = g_file_info_get_attribute_uint32 (info,
2653 G_FILE_ATTRIBUTE_MOUNTABLE_START_STOP_TYPE);
2654 }
2655 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_POLL))
2656 {
2657 can_poll_for_media = g_file_info_get_attribute_boolean (info,
2658 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_POLL);
2659 }
2660 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC))
2661 {
2662 is_media_check_automatic = g_file_info_get_attribute_boolean (info,
2663 G_FILE_ATTRIBUTE_MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC);
2664 }
2665 if (file->details->can_read != can_read ||
2666 file->details->can_write != can_write ||
2667 file->details->can_execute != can_execute ||
2668 file->details->can_delete != can_delete ||
2669 file->details->can_trash != can_trash ||
2670 file->details->can_rename != can_rename ||
2671 file->details->can_mount != can_mount ||
2672 file->details->can_unmount != can_unmount ||
2673 file->details->can_eject != can_eject ||
2674 file->details->can_start != can_start ||
2675 file->details->can_start_degraded != can_start_degraded ||
2676 file->details->can_stop != can_stop ||
2677 file->details->start_stop_type != start_stop_type ||
2678 file->details->can_poll_for_media != can_poll_for_media ||
2679 file->details->is_media_check_automatic != is_media_check_automatic)
2680 {
2681 changed = TRUE;
2682 }
2683
2684 file->details->can_read = can_read;
2685 file->details->can_write = can_write;
2686 file->details->can_execute = can_execute;
2687 file->details->can_delete = can_delete;
2688 file->details->can_trash = can_trash;
2689 file->details->can_rename = can_rename;
2690 file->details->can_mount = can_mount;
2691 file->details->can_unmount = can_unmount;
2692 file->details->can_eject = can_eject;
2693 file->details->can_start = can_start;
2694 file->details->can_start_degraded = can_start_degraded;
2695 file->details->can_stop = can_stop;
2696 file->details->start_stop_type = start_stop_type;
2697 file->details->can_poll_for_media = can_poll_for_media;
2698 file->details->is_media_check_automatic = is_media_check_automatic;
2699
2700 free_owner = FALSE;
2701 owner = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER);
2702 owner_real = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER_REAL);
2703 free_group = FALSE;
2704 group = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_GROUP);
2705
2706 uid = -1;
2707 gid = -1;
2708 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_UID))
2709 {
2710 uid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID);
2711 if (owner == NULL)
2712 {
2713 free_owner = TRUE;
2714 owner = g_strdup_printf ("%d", uid);
2715 }
2716 }
2717 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_GID))
2718 {
2719 gid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID);
2720 if (group == NULL)
2721 {
2722 free_group = TRUE;
2723 group = g_strdup_printf ("%d", gid);
2724 }
2725 }
2726 if (file->details->uid != uid ||
2727 file->details->gid != gid)
2728 {
2729 changed = TRUE;
2730 }
2731 file->details->uid = uid;
2732 file->details->gid = gid;
2733
2734 if (g_strcmp0 (file->details->owner, owner) != 0)
2735 {
2736 changed = TRUE;
2737 g_clear_pointer (&file->details->owner, g_ref_string_release);
2738 file->details->owner = g_ref_string_new_intern (owner);
2739 }
2740
2741 if (g_strcmp0 (file->details->owner_real, owner_real) != 0)
2742 {
2743 changed = TRUE;
2744 g_clear_pointer (&file->details->owner_real, g_ref_string_release);
2745 file->details->owner_real = g_ref_string_new_intern (owner_real);
2746 }
2747
2748 if (g_strcmp0 (file->details->group, group) != 0)
2749 {
2750 changed = TRUE;
2751 g_clear_pointer (&file->details->group, g_ref_string_release);
2752 file->details->group = g_ref_string_new_intern (group);
2753 }
2754
2755 if (free_owner)
2756 {
2757 g_free ((char *) owner);
2758 }
2759 if (free_group)
2760 {
2761 g_free ((char *) group);
2762 }
2763
2764 size = -1;
2765 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE))
2766 {
2767 size = g_file_info_get_size (info);
2768 }
2769 if (file->details->size != size)
2770 {
2771 changed = TRUE;
2772 }
2773 file->details->size = size;
2774
2775 sort_order = g_file_info_get_sort_order (info);
2776 if (file->details->sort_order != sort_order)
2777 {
2778 changed = TRUE;
2779 }
2780 file->details->sort_order = sort_order;
2781
2782 atime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_ACCESS);
2783 mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
2784 btime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CREATED);
2785 if (file->details->atime != atime ||
2786 file->details->mtime != mtime)
2787 {
2788 if (file->details->thumbnail == NULL)
2789 {
2790 file->details->thumbnail_is_up_to_date = FALSE;
2791 }
2792
2793 changed = TRUE;
2794 }
2795 file->details->atime = atime;
2796 file->details->mtime = mtime;
2797 file->details->btime = btime;
2798
2799 if (file->details->thumbnail != NULL &&
2800 file->details->thumbnail_mtime != 0 &&
2801 file->details->thumbnail_mtime != mtime)
2802 {
2803 file->details->thumbnail_is_up_to_date = FALSE;
2804 changed = TRUE;
2805 }
2806
2807 icon = g_file_info_get_icon (info);
2808 if (!g_icon_equal (icon, file->details->icon))
2809 {
2810 changed = TRUE;
2811
2812 if (file->details->icon)
2813 {
2814 g_object_unref (file->details->icon);
2815 }
2816 file->details->icon = g_object_ref (icon);
2817 }
2818
2819 thumbnail_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
2820 if (g_strcmp0 (file->details->thumbnail_path, thumbnail_path) != 0)
2821 {
2822 changed = TRUE;
2823 g_free (file->details->thumbnail_path);
2824 file->details->thumbnail_path = g_strdup (thumbnail_path);
2825 }
2826
2827 thumbnailing_failed = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED);
2828 if (file->details->thumbnailing_failed != thumbnailing_failed)
2829 {
2830 changed = TRUE;
2831 file->details->thumbnailing_failed = thumbnailing_failed;
2832 }
2833
2834 symlink_name = g_file_info_get_symlink_target (info);
2835 if (g_strcmp0 (file->details->symlink_name, symlink_name) != 0)
2836 {
2837 changed = TRUE;
2838 g_free (file->details->symlink_name);
2839 file->details->symlink_name = g_strdup (symlink_name);
2840 }
2841
2842 mime_type = g_file_info_get_content_type (info);
2843 if (mime_type == NULL)
2844 {
2845 mime_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE);
2846 }
2847 if (g_strcmp0 (file->details->mime_type, mime_type) != 0)
2848 {
2849 changed = TRUE;
2850 g_clear_pointer (&file->details->mime_type, g_ref_string_release);
2851 file->details->mime_type = g_ref_string_new_intern (mime_type);
2852 }
2853
2854 selinux_context = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_SELINUX_CONTEXT);
2855 if (g_strcmp0 (file->details->selinux_context, selinux_context) != 0)
2856 {
2857 changed = TRUE;
2858 g_free (file->details->selinux_context);
2859 file->details->selinux_context = g_strdup (selinux_context);
2860 }
2861
2862 description = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_DESCRIPTION);
2863 if (g_strcmp0 (file->details->description, description) != 0)
2864 {
2865 changed = TRUE;
2866 g_free (file->details->description);
2867 file->details->description = g_strdup (description);
2868 }
2869
2870 filesystem_id = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILESYSTEM);
2871 if (g_strcmp0 (file->details->filesystem_id, filesystem_id) != 0)
2872 {
2873 changed = TRUE;
2874 g_clear_pointer (&file->details->filesystem_id, g_ref_string_release);
2875 file->details->filesystem_id = g_ref_string_new_intern (filesystem_id);
2876 }
2877
2878 trash_time = 0;
2879 time_string = g_file_info_get_attribute_string (info, "trash::deletion-date");
2880 if (time_string != NULL)
2881 {
2882 g_time_val_from_iso8601 (time_string, &g_trash_time);
2883 trash_time = g_trash_time.tv_sec;
2884 }
2885 if (file->details->trash_time != trash_time)
2886 {
2887 changed = TRUE;
2888 file->details->trash_time = trash_time;
2889 }
2890
2891 recency = g_file_info_get_attribute_int64 (info, G_FILE_ATTRIBUTE_RECENT_MODIFIED);
2892 if (file->details->recency != recency)
2893 {
2894 changed = TRUE;
2895 file->details->recency = recency;
2896 }
2897
2898 trash_orig_path = g_file_info_get_attribute_byte_string (info, "trash::orig-path");
2899 if (g_strcmp0 (file->details->trash_orig_path, trash_orig_path) != 0)
2900 {
2901 changed = TRUE;
2902 g_free (file->details->trash_orig_path);
2903 file->details->trash_orig_path = g_strdup (trash_orig_path);
2904 }
2905
2906 changed |=
2907 nautilus_file_update_metadata_from_info (file, info);
2908
2909 if (update_name)
2910 {
2911 name = g_file_info_get_name (info);
2912 if (file->details->name == NULL ||
2913 strcmp (file->details->name, name) != 0)
2914 {
2915 changed = TRUE;
2916
2917 node = nautilus_directory_begin_file_name_change
2918 (file->details->directory, file);
2919
2920 g_clear_pointer (&file->details->name, g_ref_string_release);
2921 if (g_strcmp0 (file->details->display_name, name) == 0)
2922 {
2923 file->details->name = g_ref_string_acquire (file->details->display_name);
2924 }
2925 else
2926 {
2927 file->details->name = g_ref_string_new (name);
2928 }
2929
2930 if (!file->details->got_custom_display_name &&
2931 g_file_info_get_display_name (info) == NULL)
2932 {
2933 /* If the file info's display name is NULL,
2934 * nautilus_file_set_display_name() did
2935 * not unset the display name.
2936 */
2937 nautilus_file_clear_display_name (file);
2938 }
2939
2940 nautilus_directory_end_file_name_change
2941 (file->details->directory, file, node);
2942 }
2943 }
2944
2945 if (changed)
2946 {
2947 add_to_link_hash_table (file);
2948
2949 update_links_if_target (file);
2950 }
2951
2952 return changed;
2953 }
2954
2955 static gboolean
update_info_and_name(NautilusFile * file,GFileInfo * info)2956 update_info_and_name (NautilusFile *file,
2957 GFileInfo *info)
2958 {
2959 return update_info_internal (file, info, TRUE);
2960 }
2961
2962 gboolean
nautilus_file_update_info(NautilusFile * file,GFileInfo * info)2963 nautilus_file_update_info (NautilusFile *file,
2964 GFileInfo *info)
2965 {
2966 return update_info_internal (file, info, FALSE);
2967 }
2968
2969 static gboolean
update_name_internal(NautilusFile * file,const char * name,gboolean in_directory)2970 update_name_internal (NautilusFile *file,
2971 const char *name,
2972 gboolean in_directory)
2973 {
2974 GList *node;
2975
2976 g_assert (name != NULL);
2977
2978 if (file->details->is_gone)
2979 {
2980 return FALSE;
2981 }
2982
2983 if (name_is (file, name))
2984 {
2985 return FALSE;
2986 }
2987
2988 node = NULL;
2989 if (in_directory)
2990 {
2991 node = nautilus_directory_begin_file_name_change
2992 (file->details->directory, file);
2993 }
2994
2995 g_clear_pointer (&file->details->name, g_ref_string_release);
2996 file->details->name = g_ref_string_new (name);
2997
2998 if (!file->details->got_custom_display_name)
2999 {
3000 nautilus_file_clear_display_name (file);
3001 }
3002
3003 if (in_directory)
3004 {
3005 nautilus_directory_end_file_name_change
3006 (file->details->directory, file, node);
3007 }
3008
3009 return TRUE;
3010 }
3011
3012 gboolean
nautilus_file_update_name(NautilusFile * file,const char * name)3013 nautilus_file_update_name (NautilusFile *file,
3014 const char *name)
3015 {
3016 gboolean ret;
3017
3018 ret = update_name_internal (file, name, TRUE);
3019
3020 if (ret)
3021 {
3022 update_links_if_target (file);
3023 }
3024
3025 return ret;
3026 }
3027
3028 gboolean
nautilus_file_update_name_and_directory(NautilusFile * file,const char * name,NautilusDirectory * new_directory)3029 nautilus_file_update_name_and_directory (NautilusFile *file,
3030 const char *name,
3031 NautilusDirectory *new_directory)
3032 {
3033 NautilusDirectory *old_directory;
3034 FileMonitors *monitors;
3035
3036 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
3037 g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (file->details->directory), FALSE);
3038 g_return_val_if_fail (!file->details->is_gone, FALSE);
3039 g_return_val_if_fail (!nautilus_file_is_self_owned (file), FALSE);
3040 g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (new_directory), FALSE);
3041
3042 old_directory = file->details->directory;
3043 if (old_directory == new_directory)
3044 {
3045 if (name)
3046 {
3047 return update_name_internal (file, name, TRUE);
3048 }
3049 else
3050 {
3051 return FALSE;
3052 }
3053 }
3054
3055 nautilus_file_ref (file);
3056
3057 /* FIXME bugzilla.gnome.org 42044: Need to let links that
3058 * point to the old name know that the file has been moved.
3059 */
3060
3061 remove_from_link_hash_table (file);
3062
3063 monitors = nautilus_directory_remove_file_monitors (old_directory, file);
3064 nautilus_directory_remove_file (old_directory, file);
3065
3066 nautilus_file_set_directory (file, new_directory);
3067
3068 if (name)
3069 {
3070 update_name_internal (file, name, FALSE);
3071 }
3072
3073 nautilus_directory_add_file (new_directory, file);
3074 nautilus_directory_add_file_monitors (new_directory, file, monitors);
3075
3076 add_to_link_hash_table (file);
3077
3078 update_links_if_target (file);
3079
3080 nautilus_file_unref (file);
3081
3082 return TRUE;
3083 }
3084
3085 static Knowledge
get_item_count(NautilusFile * file,guint * count)3086 get_item_count (NautilusFile *file,
3087 guint *count)
3088 {
3089 gboolean known, unreadable;
3090
3091 known = nautilus_file_get_directory_item_count
3092 (file, count, &unreadable);
3093 if (!known)
3094 {
3095 return UNKNOWN;
3096 }
3097 if (unreadable)
3098 {
3099 return UNKNOWABLE;
3100 }
3101 return KNOWN;
3102 }
3103
3104 static Knowledge
get_size(NautilusFile * file,goffset * size)3105 get_size (NautilusFile *file,
3106 goffset *size)
3107 {
3108 /* If we tried and failed, then treat it like there is no size
3109 * to know.
3110 */
3111 if (file->details->get_info_failed)
3112 {
3113 return UNKNOWABLE;
3114 }
3115
3116 /* If the info is NULL that means we haven't even tried yet,
3117 * so it's just unknown, not unknowable.
3118 */
3119 if (!file->details->got_file_info)
3120 {
3121 return UNKNOWN;
3122 }
3123
3124 /* If we got info with no size in it, it means there is no
3125 * such thing as a size as far as gnome-vfs is concerned,
3126 * so "unknowable".
3127 */
3128 if (file->details->size == -1)
3129 {
3130 return UNKNOWABLE;
3131 }
3132
3133 /* We have a size! */
3134 *size = file->details->size;
3135 return KNOWN;
3136 }
3137
3138 static Knowledge
get_time(NautilusFile * file,time_t * time_out,NautilusDateType type)3139 get_time (NautilusFile *file,
3140 time_t *time_out,
3141 NautilusDateType type)
3142 {
3143 time_t time;
3144
3145 /* If we tried and failed, then treat it like there is no size
3146 * to know.
3147 */
3148 if (file->details->get_info_failed)
3149 {
3150 return UNKNOWABLE;
3151 }
3152
3153 /* If the info is NULL that means we haven't even tried yet,
3154 * so it's just unknown, not unknowable.
3155 */
3156 if (!file->details->got_file_info)
3157 {
3158 return UNKNOWN;
3159 }
3160
3161 switch (type)
3162 {
3163 case NAUTILUS_DATE_TYPE_MODIFIED:
3164 {
3165 time = file->details->mtime;
3166 }
3167 break;
3168
3169 case NAUTILUS_DATE_TYPE_ACCESSED:
3170 {
3171 time = file->details->atime;
3172 }
3173 break;
3174
3175 case NAUTILUS_DATE_TYPE_CREATED:
3176 {
3177 time = file->details->btime;
3178 }
3179 break;
3180
3181 case NAUTILUS_DATE_TYPE_TRASHED:
3182 {
3183 time = file->details->trash_time;
3184 }
3185 break;
3186
3187 case NAUTILUS_DATE_TYPE_RECENCY:
3188 {
3189 time = file->details->recency;
3190 }
3191 break;
3192
3193 default:
3194 {
3195 g_assert_not_reached ();
3196 }
3197 break;
3198 }
3199
3200 *time_out = time;
3201
3202 /* If we got info with no modification time in it, it means
3203 * there is no such thing as a modification time as far as
3204 * gnome-vfs is concerned, so "unknowable".
3205 */
3206 if (time == 0)
3207 {
3208 return UNKNOWABLE;
3209 }
3210 return KNOWN;
3211 }
3212
3213 static int
compare_directories_by_count(NautilusFile * file_1,NautilusFile * file_2)3214 compare_directories_by_count (NautilusFile *file_1,
3215 NautilusFile *file_2)
3216 {
3217 /* Sort order:
3218 * Directories with unknown # of items
3219 * Directories with "unknowable" # of items
3220 * Directories with 0 items
3221 * Directories with n items
3222 */
3223
3224 Knowledge count_known_1, count_known_2;
3225 guint count_1, count_2;
3226
3227 count_known_1 = get_item_count (file_1, &count_1);
3228 count_known_2 = get_item_count (file_2, &count_2);
3229
3230 if (count_known_1 > count_known_2)
3231 {
3232 return -1;
3233 }
3234 if (count_known_1 < count_known_2)
3235 {
3236 return +1;
3237 }
3238
3239 /* count_known_1 and count_known_2 are equal now. Check if count
3240 * details are UNKNOWABLE or UNKNOWN.
3241 */
3242 if (count_known_1 == UNKNOWABLE || count_known_1 == UNKNOWN)
3243 {
3244 return 0;
3245 }
3246
3247 if (count_1 < count_2)
3248 {
3249 return -1;
3250 }
3251 if (count_1 > count_2)
3252 {
3253 return +1;
3254 }
3255
3256 return 0;
3257 }
3258
3259 static int
compare_files_by_size(NautilusFile * file_1,NautilusFile * file_2)3260 compare_files_by_size (NautilusFile *file_1,
3261 NautilusFile *file_2)
3262 {
3263 /* Sort order:
3264 * Files with unknown size.
3265 * Files with "unknowable" size.
3266 * Files with smaller sizes.
3267 * Files with large sizes.
3268 */
3269
3270 Knowledge size_known_1, size_known_2;
3271 goffset size_1 = 0, size_2 = 0;
3272
3273 size_known_1 = get_size (file_1, &size_1);
3274 size_known_2 = get_size (file_2, &size_2);
3275
3276 if (size_known_1 > size_known_2)
3277 {
3278 return -1;
3279 }
3280 if (size_known_1 < size_known_2)
3281 {
3282 return +1;
3283 }
3284
3285 /* size_known_1 and size_known_2 are equal now. Check if size
3286 * details are UNKNOWABLE or UNKNOWN
3287 */
3288 if (size_known_1 == UNKNOWABLE || size_known_1 == UNKNOWN)
3289 {
3290 return 0;
3291 }
3292
3293 if (size_1 < size_2)
3294 {
3295 return -1;
3296 }
3297 if (size_1 > size_2)
3298 {
3299 return +1;
3300 }
3301
3302 return 0;
3303 }
3304
3305 static int
compare_by_size(NautilusFile * file_1,NautilusFile * file_2)3306 compare_by_size (NautilusFile *file_1,
3307 NautilusFile *file_2)
3308 {
3309 /* Sort order:
3310 * Directories with n items
3311 * Directories with 0 items
3312 * Directories with "unknowable" # of items
3313 * Directories with unknown # of items
3314 * Files with large sizes.
3315 * Files with smaller sizes.
3316 * Files with "unknowable" size.
3317 * Files with unknown size.
3318 */
3319
3320 gboolean is_directory_1, is_directory_2;
3321
3322 is_directory_1 = nautilus_file_is_directory (file_1);
3323 is_directory_2 = nautilus_file_is_directory (file_2);
3324
3325 if (is_directory_1 && !is_directory_2)
3326 {
3327 return -1;
3328 }
3329 if (is_directory_2 && !is_directory_1)
3330 {
3331 return +1;
3332 }
3333
3334 if (is_directory_1)
3335 {
3336 return compare_directories_by_count (file_1, file_2);
3337 }
3338 else
3339 {
3340 return compare_files_by_size (file_1, file_2);
3341 }
3342 }
3343
3344 static int
compare_by_display_name(NautilusFile * file_1,NautilusFile * file_2)3345 compare_by_display_name (NautilusFile *file_1,
3346 NautilusFile *file_2)
3347 {
3348 const char *name_1, *name_2;
3349 const char *key_1, *key_2;
3350 gboolean sort_last_1, sort_last_2;
3351 int compare;
3352
3353 name_1 = nautilus_file_peek_display_name (file_1);
3354 name_2 = nautilus_file_peek_display_name (file_2);
3355
3356 sort_last_1 = name_1[0] == SORT_LAST_CHAR1 || name_1[0] == SORT_LAST_CHAR2;
3357 sort_last_2 = name_2[0] == SORT_LAST_CHAR1 || name_2[0] == SORT_LAST_CHAR2;
3358
3359 if (sort_last_1 && !sort_last_2)
3360 {
3361 compare = +1;
3362 }
3363 else if (!sort_last_1 && sort_last_2)
3364 {
3365 compare = -1;
3366 }
3367 else
3368 {
3369 key_1 = nautilus_file_peek_display_name_collation_key (file_1);
3370 key_2 = nautilus_file_peek_display_name_collation_key (file_2);
3371 compare = strcmp (key_1, key_2);
3372 }
3373
3374 return compare;
3375 }
3376
3377 static int
compare_by_directory_name(NautilusFile * file_1,NautilusFile * file_2)3378 compare_by_directory_name (NautilusFile *file_1,
3379 NautilusFile *file_2)
3380 {
3381 return strcmp (file_1->details->directory_name_collation_key,
3382 file_2->details->directory_name_collation_key);
3383 }
3384
3385 static GList *
prepend_automatic_keywords(NautilusFile * file,GList * names)3386 prepend_automatic_keywords (NautilusFile *file,
3387 GList *names)
3388 {
3389 /* Prepend in reverse order. */
3390 NautilusFile *parent;
3391
3392 parent = nautilus_file_get_parent (file);
3393
3394 /* Trash files are assumed to be read-only,
3395 * so we want to ignore them here. */
3396 if (!nautilus_file_can_write (file) &&
3397 !nautilus_file_is_in_trash (file) &&
3398 (parent == NULL || nautilus_file_can_write (parent)))
3399 {
3400 names = g_list_prepend
3401 (names, g_strdup (NAUTILUS_FILE_EMBLEM_NAME_CANT_WRITE));
3402 }
3403 if (!nautilus_file_can_read (file))
3404 {
3405 names = g_list_prepend
3406 (names, g_strdup (NAUTILUS_FILE_EMBLEM_NAME_CANT_READ));
3407 }
3408 if (nautilus_file_is_symbolic_link (file))
3409 {
3410 names = g_list_prepend
3411 (names, g_strdup (NAUTILUS_FILE_EMBLEM_NAME_SYMBOLIC_LINK));
3412 }
3413
3414 if (parent)
3415 {
3416 nautilus_file_unref (parent);
3417 }
3418
3419
3420 return names;
3421 }
3422
3423 static int
compare_by_type(NautilusFile * file_1,NautilusFile * file_2)3424 compare_by_type (NautilusFile *file_1,
3425 NautilusFile *file_2)
3426 {
3427 gboolean is_directory_1;
3428 gboolean is_directory_2;
3429 char *type_string_1;
3430 char *type_string_2;
3431 int result;
3432
3433 /* Directories go first. Then, if mime types are identical,
3434 * don't bother getting strings (for speed). This assumes
3435 * that the string is dependent entirely on the mime type,
3436 * which is true now but might not be later.
3437 */
3438 is_directory_1 = nautilus_file_is_directory (file_1);
3439 is_directory_2 = nautilus_file_is_directory (file_2);
3440
3441 if (is_directory_1 && is_directory_2)
3442 {
3443 return 0;
3444 }
3445
3446 if (is_directory_1)
3447 {
3448 return -1;
3449 }
3450
3451 if (is_directory_2)
3452 {
3453 return +1;
3454 }
3455
3456 if (file_1->details->mime_type != NULL &&
3457 file_2->details->mime_type != NULL &&
3458 strcmp (file_1->details->mime_type,
3459 file_2->details->mime_type) == 0)
3460 {
3461 return 0;
3462 }
3463
3464 type_string_1 = nautilus_file_get_type_as_string_no_extra_text (file_1);
3465 type_string_2 = nautilus_file_get_type_as_string_no_extra_text (file_2);
3466
3467 if (type_string_1 == NULL || type_string_2 == NULL)
3468 {
3469 if (type_string_1 != NULL)
3470 {
3471 return -1;
3472 }
3473
3474 if (type_string_2 != NULL)
3475 {
3476 return 1;
3477 }
3478
3479 return 0;
3480 }
3481
3482 result = g_utf8_collate (type_string_1, type_string_2);
3483
3484 g_free (type_string_1);
3485 g_free (type_string_2);
3486
3487 return result;
3488 }
3489
3490 static int
compare_by_starred(NautilusFile * file_1,NautilusFile * file_2)3491 compare_by_starred (NautilusFile *file_1,
3492 NautilusFile *file_2)
3493 {
3494 g_autoptr (NautilusTagManager) tag_manager = nautilus_tag_manager_get ();
3495 g_autofree gchar *uri_1 = NULL;
3496 g_autofree gchar *uri_2 = NULL;
3497 gboolean file_1_is_starred;
3498 gboolean file_2_is_starred;
3499
3500 uri_1 = nautilus_file_get_uri (file_1);
3501 uri_2 = nautilus_file_get_uri (file_2);
3502
3503 file_1_is_starred = nautilus_tag_manager_file_is_starred (tag_manager,
3504 uri_1);
3505 file_2_is_starred = nautilus_tag_manager_file_is_starred (tag_manager,
3506 uri_2);
3507 if (!!file_1_is_starred == !!file_2_is_starred)
3508 {
3509 return 0;
3510 }
3511 else if (file_1_is_starred && !file_2_is_starred)
3512 {
3513 return -1;
3514 }
3515 else
3516 {
3517 return 1;
3518 }
3519 }
3520
3521 static Knowledge
get_search_relevance(NautilusFile * file,gdouble * relevance_out)3522 get_search_relevance (NautilusFile *file,
3523 gdouble *relevance_out)
3524 {
3525 /* we're only called in search directories, and in that
3526 * case, the relevance is always known (or zero).
3527 */
3528 *relevance_out = file->details->search_relevance;
3529 return KNOWN;
3530 }
3531
3532 static int
compare_by_search_relevance(NautilusFile * file_1,NautilusFile * file_2)3533 compare_by_search_relevance (NautilusFile *file_1,
3534 NautilusFile *file_2)
3535 {
3536 gdouble r_1, r_2;
3537
3538 get_search_relevance (file_1, &r_1);
3539 get_search_relevance (file_2, &r_2);
3540
3541 if (r_1 < r_2)
3542 {
3543 return -1;
3544 }
3545 if (r_1 > r_2)
3546 {
3547 return +1;
3548 }
3549
3550 return 0;
3551 }
3552
3553 static int
compare_by_time(NautilusFile * file_1,NautilusFile * file_2,NautilusDateType type)3554 compare_by_time (NautilusFile *file_1,
3555 NautilusFile *file_2,
3556 NautilusDateType type)
3557 {
3558 /* Sort order:
3559 * Files with unknown times.
3560 * Files with "unknowable" times.
3561 * Files with older times.
3562 * Files with newer times.
3563 */
3564
3565 Knowledge time_known_1, time_known_2;
3566 time_t time_1, time_2;
3567
3568 time_1 = 0;
3569 time_2 = 0;
3570
3571 time_known_1 = get_time (file_1, &time_1, type);
3572 time_known_2 = get_time (file_2, &time_2, type);
3573
3574 if (time_known_1 > time_known_2)
3575 {
3576 return -1;
3577 }
3578 if (time_known_1 < time_known_2)
3579 {
3580 return +1;
3581 }
3582
3583 /* Now time_known_1 is equal to time_known_2. Check whether
3584 * we failed to get modification times for files
3585 */
3586 if (time_known_1 == UNKNOWABLE || time_known_1 == UNKNOWN)
3587 {
3588 return 0;
3589 }
3590
3591 if (time_1 < time_2)
3592 {
3593 return -1;
3594 }
3595 if (time_1 > time_2)
3596 {
3597 return +1;
3598 }
3599
3600 return 0;
3601 }
3602
3603 static int
compare_by_full_path(NautilusFile * file_1,NautilusFile * file_2)3604 compare_by_full_path (NautilusFile *file_1,
3605 NautilusFile *file_2)
3606 {
3607 int compare;
3608
3609 compare = compare_by_directory_name (file_1, file_2);
3610 if (compare != 0)
3611 {
3612 return compare;
3613 }
3614 return compare_by_display_name (file_1, file_2);
3615 }
3616
3617 static int
nautilus_file_compare_for_sort_internal(NautilusFile * file_1,NautilusFile * file_2,gboolean directories_first,gboolean reversed)3618 nautilus_file_compare_for_sort_internal (NautilusFile *file_1,
3619 NautilusFile *file_2,
3620 gboolean directories_first,
3621 gboolean reversed)
3622 {
3623 gboolean is_directory_1, is_directory_2;
3624
3625 if (directories_first)
3626 {
3627 is_directory_1 = nautilus_file_is_directory (file_1);
3628 is_directory_2 = nautilus_file_is_directory (file_2);
3629
3630 if (is_directory_1 && !is_directory_2)
3631 {
3632 return -1;
3633 }
3634
3635 if (is_directory_2 && !is_directory_1)
3636 {
3637 return +1;
3638 }
3639 }
3640
3641 if (file_1->details->sort_order < file_2->details->sort_order)
3642 {
3643 return reversed ? 1 : -1;
3644 }
3645 else if (file_1->details->sort_order > file_2->details->sort_order)
3646 {
3647 return reversed ? -1 : 1;
3648 }
3649
3650 return 0;
3651 }
3652
3653 /**
3654 * nautilus_file_compare_for_sort:
3655 * @file_1: A file object
3656 * @file_2: Another file object
3657 * @sort_type: Sort criterion
3658 * @directories_first: Put all directories before any non-directories
3659 * @reversed: Reverse the order of the items, except that
3660 * the directories_first flag is still respected.
3661 *
3662 * Return value: int < 0 if @file_1 should come before file_2 in a
3663 * sorted list; int > 0 if @file_2 should come before file_1 in a
3664 * sorted list; 0 if @file_1 and @file_2 are equal for this sort criterion. Note
3665 * that each named sort type may actually break ties several ways, with the name
3666 * of the sort criterion being the primary but not only differentiator.
3667 **/
3668 int
nautilus_file_compare_for_sort(NautilusFile * file_1,NautilusFile * file_2,NautilusFileSortType sort_type,gboolean directories_first,gboolean reversed)3669 nautilus_file_compare_for_sort (NautilusFile *file_1,
3670 NautilusFile *file_2,
3671 NautilusFileSortType sort_type,
3672 gboolean directories_first,
3673 gboolean reversed)
3674 {
3675 int result;
3676
3677 if (file_1 == file_2)
3678 {
3679 return 0;
3680 }
3681
3682 result = nautilus_file_compare_for_sort_internal (file_1, file_2, directories_first, reversed);
3683
3684 if (result == 0)
3685 {
3686 switch (sort_type)
3687 {
3688 case NAUTILUS_FILE_SORT_BY_DISPLAY_NAME:
3689 {
3690 result = compare_by_display_name (file_1, file_2);
3691 if (result == 0)
3692 {
3693 result = compare_by_directory_name (file_1, file_2);
3694 }
3695 }
3696 break;
3697
3698 case NAUTILUS_FILE_SORT_BY_SIZE:
3699 {
3700 /* Compare directory sizes ourselves, then if necessary
3701 * use GnomeVFS to compare file sizes.
3702 */
3703 result = compare_by_size (file_1, file_2);
3704 if (result == 0)
3705 {
3706 result = compare_by_full_path (file_1, file_2);
3707 }
3708 }
3709 break;
3710
3711 case NAUTILUS_FILE_SORT_BY_TYPE:
3712 {
3713 /* GnomeVFS doesn't know about our special text for certain
3714 * mime types, so we handle the mime-type sorting ourselves.
3715 */
3716 result = compare_by_type (file_1, file_2);
3717 if (result == 0)
3718 {
3719 result = compare_by_full_path (file_1, file_2);
3720 }
3721 }
3722 break;
3723
3724 case NAUTILUS_FILE_SORT_BY_STARRED:
3725 {
3726 result = compare_by_starred (file_1, file_2);
3727 if (result == 0)
3728 {
3729 result = compare_by_full_path (file_1, file_2);
3730 }
3731 }
3732 break;
3733
3734 case NAUTILUS_FILE_SORT_BY_MTIME:
3735 {
3736 result = compare_by_time (file_1, file_2, NAUTILUS_DATE_TYPE_MODIFIED);
3737 if (result == 0)
3738 {
3739 result = compare_by_full_path (file_1, file_2);
3740 }
3741 }
3742 break;
3743
3744 case NAUTILUS_FILE_SORT_BY_ATIME:
3745 {
3746 result = compare_by_time (file_1, file_2, NAUTILUS_DATE_TYPE_ACCESSED);
3747 if (result == 0)
3748 {
3749 result = compare_by_full_path (file_1, file_2);
3750 }
3751 }
3752 break;
3753
3754 case NAUTILUS_FILE_SORT_BY_BTIME:
3755 {
3756 result = compare_by_time (file_1, file_2, NAUTILUS_DATE_TYPE_CREATED);
3757 if (result == 0)
3758 {
3759 result = compare_by_full_path (file_1, file_2);
3760 }
3761 }
3762 break;
3763
3764 case NAUTILUS_FILE_SORT_BY_TRASHED_TIME:
3765 {
3766 result = compare_by_time (file_1, file_2, NAUTILUS_DATE_TYPE_TRASHED);
3767 if (result == 0)
3768 {
3769 result = compare_by_full_path (file_1, file_2);
3770 }
3771 }
3772 break;
3773
3774 case NAUTILUS_FILE_SORT_BY_SEARCH_RELEVANCE:
3775 {
3776 result = compare_by_search_relevance (file_1, file_2);
3777 if (result == 0)
3778 {
3779 result = compare_by_full_path (file_1, file_2);
3780
3781 /* ensure alphabetical order for files of the same relevance */
3782 reversed = FALSE;
3783 }
3784 }
3785 break;
3786
3787 case NAUTILUS_FILE_SORT_BY_RECENCY:
3788 {
3789 result = compare_by_time (file_1, file_2, NAUTILUS_DATE_TYPE_RECENCY);
3790 if (result == 0)
3791 {
3792 result = compare_by_full_path (file_1, file_2);
3793 }
3794 }
3795 break;
3796
3797 default:
3798 {
3799 g_return_val_if_reached (0);
3800 }
3801 }
3802
3803 if (reversed)
3804 {
3805 result = -result;
3806 }
3807 }
3808
3809 return result;
3810 }
3811
3812 int
nautilus_file_compare_for_sort_by_attribute_q(NautilusFile * file_1,NautilusFile * file_2,GQuark attribute,gboolean directories_first,gboolean reversed)3813 nautilus_file_compare_for_sort_by_attribute_q (NautilusFile *file_1,
3814 NautilusFile *file_2,
3815 GQuark attribute,
3816 gboolean directories_first,
3817 gboolean reversed)
3818 {
3819 int result;
3820
3821 if (file_1 == file_2)
3822 {
3823 return 0;
3824 }
3825
3826 /* Convert certain attributes into NautilusFileSortTypes and use
3827 * nautilus_file_compare_for_sort()
3828 */
3829 if (attribute == 0 || attribute == attribute_name_q)
3830 {
3831 return nautilus_file_compare_for_sort (file_1, file_2,
3832 NAUTILUS_FILE_SORT_BY_DISPLAY_NAME,
3833 directories_first,
3834 reversed);
3835 }
3836 else if (attribute == attribute_size_q)
3837 {
3838 return nautilus_file_compare_for_sort (file_1, file_2,
3839 NAUTILUS_FILE_SORT_BY_SIZE,
3840 directories_first,
3841 reversed);
3842 }
3843 else if (attribute == attribute_type_q)
3844 {
3845 return nautilus_file_compare_for_sort (file_1, file_2,
3846 NAUTILUS_FILE_SORT_BY_TYPE,
3847 directories_first,
3848 reversed);
3849 }
3850 else if (attribute == attribute_starred_q)
3851 {
3852 return nautilus_file_compare_for_sort (file_1, file_2,
3853 NAUTILUS_FILE_SORT_BY_STARRED,
3854 directories_first,
3855 reversed);
3856 }
3857 else if (attribute == attribute_modification_date_q || attribute == attribute_date_modified_q || attribute == attribute_date_modified_with_time_q || attribute == attribute_date_modified_full_q)
3858 {
3859 return nautilus_file_compare_for_sort (file_1, file_2,
3860 NAUTILUS_FILE_SORT_BY_MTIME,
3861 directories_first,
3862 reversed);
3863 }
3864 else if (attribute == attribute_accessed_date_q || attribute == attribute_date_accessed_q || attribute == attribute_date_accessed_full_q)
3865 {
3866 return nautilus_file_compare_for_sort (file_1, file_2,
3867 NAUTILUS_FILE_SORT_BY_ATIME,
3868 directories_first,
3869 reversed);
3870 }
3871 else if (attribute == attribute_date_created_q || attribute == attribute_date_created_full_q)
3872 {
3873 return nautilus_file_compare_for_sort (file_1, file_2,
3874 NAUTILUS_FILE_SORT_BY_BTIME,
3875 directories_first,
3876 reversed);
3877 }
3878 else if (attribute == attribute_trashed_on_q || attribute == attribute_trashed_on_full_q)
3879 {
3880 return nautilus_file_compare_for_sort (file_1, file_2,
3881 NAUTILUS_FILE_SORT_BY_TRASHED_TIME,
3882 directories_first,
3883 reversed);
3884 }
3885 else if (attribute == attribute_search_relevance_q)
3886 {
3887 return nautilus_file_compare_for_sort (file_1, file_2,
3888 NAUTILUS_FILE_SORT_BY_SEARCH_RELEVANCE,
3889 directories_first,
3890 reversed);
3891 }
3892 else if (attribute == attribute_recency_q)
3893 {
3894 return nautilus_file_compare_for_sort (file_1, file_2,
3895 NAUTILUS_FILE_SORT_BY_RECENCY,
3896 directories_first,
3897 reversed);
3898 }
3899
3900 /* it is a normal attribute, compare by strings */
3901
3902 result = nautilus_file_compare_for_sort_internal (file_1, file_2, directories_first, reversed);
3903
3904 if (result == 0)
3905 {
3906 char *value_1;
3907 char *value_2;
3908
3909 value_1 = nautilus_file_get_string_attribute_q (file_1,
3910 attribute);
3911 value_2 = nautilus_file_get_string_attribute_q (file_2,
3912 attribute);
3913
3914 if (value_1 != NULL && value_2 != NULL)
3915 {
3916 result = strcmp (value_1, value_2);
3917 }
3918
3919 g_free (value_1);
3920 g_free (value_2);
3921
3922 if (reversed)
3923 {
3924 result = -result;
3925 }
3926 }
3927
3928 return result;
3929 }
3930
3931 int
nautilus_file_compare_for_sort_by_attribute(NautilusFile * file_1,NautilusFile * file_2,const char * attribute,gboolean directories_first,gboolean reversed)3932 nautilus_file_compare_for_sort_by_attribute (NautilusFile *file_1,
3933 NautilusFile *file_2,
3934 const char *attribute,
3935 gboolean directories_first,
3936 gboolean reversed)
3937 {
3938 return nautilus_file_compare_for_sort_by_attribute_q (file_1, file_2,
3939 g_quark_from_string (attribute),
3940 directories_first,
3941 reversed);
3942 }
3943
3944
3945 /**
3946 * nautilus_file_compare_name:
3947 * @file: A file object
3948 * @string: A string we are comparing it with
3949 *
3950 * Return value: result of a comparison of the file name and the given string.
3951 **/
3952 int
nautilus_file_compare_display_name(NautilusFile * file,const char * string)3953 nautilus_file_compare_display_name (NautilusFile *file,
3954 const char *string)
3955 {
3956 const char *name;
3957 int result;
3958
3959 g_return_val_if_fail (string != NULL, -1);
3960
3961 name = nautilus_file_peek_display_name (file);
3962 result = g_strcmp0 (name, string);
3963 return result;
3964 }
3965
3966
3967 gboolean
nautilus_file_is_hidden_file(NautilusFile * file)3968 nautilus_file_is_hidden_file (NautilusFile *file)
3969 {
3970 return file->details->is_hidden;
3971 }
3972
3973 /**
3974 * nautilus_file_should_show:
3975 * @file: the file to check
3976 * @show_hidden: whether we want to show hidden files or not
3977 *
3978 * Determines if a #NautilusFile should be shown. Note that when browsing
3979 * a trash directory, this function will always return %TRUE.
3980 *
3981 * Returns: %TRUE if the file should be shown, %FALSE if it shouldn't.
3982 */
3983 gboolean
nautilus_file_should_show(NautilusFile * file,gboolean show_hidden)3984 nautilus_file_should_show (NautilusFile *file,
3985 gboolean show_hidden)
3986 {
3987 /* Never hide any files in trash. */
3988 if (nautilus_file_is_in_trash (file))
3989 {
3990 return TRUE;
3991 }
3992
3993 if (!show_hidden && nautilus_file_is_hidden_file (file))
3994 {
3995 return FALSE;
3996 }
3997
3998 return TRUE;
3999 }
4000
4001 gboolean
nautilus_file_is_home(NautilusFile * file)4002 nautilus_file_is_home (NautilusFile *file)
4003 {
4004 g_autoptr (GFile) location = NULL;
4005
4006 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
4007
4008 location = nautilus_directory_get_location (file->details->directory);
4009 if (location == NULL)
4010 {
4011 return FALSE;
4012 }
4013
4014 return nautilus_is_home_directory_file (location, file->details->name);
4015 }
4016
4017 gboolean
nautilus_file_is_in_search(NautilusFile * file)4018 nautilus_file_is_in_search (NautilusFile *file)
4019 {
4020 char *uri;
4021 gboolean ret;
4022
4023 uri = nautilus_file_get_uri (file);
4024 ret = eel_uri_is_search (uri);
4025 g_free (uri);
4026
4027 return ret;
4028 }
4029
4030 static gboolean
filter_hidden_partition_callback(NautilusFile * file,gpointer callback_data)4031 filter_hidden_partition_callback (NautilusFile *file,
4032 gpointer callback_data)
4033 {
4034 FilterOptions options;
4035
4036 options = GPOINTER_TO_INT (callback_data);
4037
4038 return nautilus_file_should_show (file,
4039 options & SHOW_HIDDEN);
4040 }
4041
4042 GList *
nautilus_file_list_filter_hidden(GList * files,gboolean show_hidden)4043 nautilus_file_list_filter_hidden (GList *files,
4044 gboolean show_hidden)
4045 {
4046 GList *filtered_files;
4047 GList *removed_files;
4048
4049 /* FIXME bugzilla.gnome.org 40653:
4050 * Eventually this should become a generic filtering thingy.
4051 */
4052
4053 filtered_files = nautilus_file_list_filter (files,
4054 &removed_files,
4055 filter_hidden_partition_callback,
4056 GINT_TO_POINTER ((show_hidden ? SHOW_HIDDEN : 0)));
4057 nautilus_file_list_free (removed_files);
4058
4059 return filtered_files;
4060 }
4061
4062 /* This functions filters a file list when its items match a certain condition
4063 * in the filter function. This function preserves the ordering.
4064 */
4065 GList *
nautilus_file_list_filter(GList * files,GList ** failed,NautilusFileFilterFunc filter_function,gpointer user_data)4066 nautilus_file_list_filter (GList *files,
4067 GList **failed,
4068 NautilusFileFilterFunc filter_function,
4069 gpointer user_data)
4070 {
4071 GList *filtered = NULL;
4072 GList *l;
4073 GList *reversed;
4074
4075 *failed = NULL;
4076 /* Avoid using g_list_append since it's O(n) */
4077 reversed = g_list_copy (files);
4078 reversed = g_list_reverse (reversed);
4079 for (l = reversed; l != NULL; l = l->next)
4080 {
4081 if (filter_function (l->data, user_data))
4082 {
4083 filtered = g_list_prepend (filtered, nautilus_file_ref (l->data));
4084 }
4085 else
4086 {
4087 *failed = g_list_prepend (*failed, nautilus_file_ref (l->data));
4088 }
4089 }
4090
4091 g_list_free (reversed);
4092
4093 return filtered;
4094 }
4095
4096 gboolean
nautilus_file_list_are_all_folders(const GList * files)4097 nautilus_file_list_are_all_folders (const GList *files)
4098 {
4099 const GList *l;
4100
4101 for (l = files; l != NULL; l = l->next)
4102 {
4103 if (!nautilus_file_is_directory (NAUTILUS_FILE (l->data)))
4104 {
4105 return FALSE;
4106 }
4107 }
4108
4109 return TRUE;
4110 }
4111
4112 char *
nautilus_file_get_metadata(NautilusFile * file,const char * key,const char * default_metadata)4113 nautilus_file_get_metadata (NautilusFile *file,
4114 const char *key,
4115 const char *default_metadata)
4116 {
4117 guint id;
4118 char *value;
4119
4120 g_return_val_if_fail (key != NULL, g_strdup (default_metadata));
4121 g_return_val_if_fail (key[0] != '\0', g_strdup (default_metadata));
4122
4123 if (file == NULL ||
4124 file->details->metadata == NULL)
4125 {
4126 return g_strdup (default_metadata);
4127 }
4128
4129 g_return_val_if_fail (NAUTILUS_IS_FILE (file), g_strdup (default_metadata));
4130
4131 id = nautilus_metadata_get_id (key);
4132 value = g_hash_table_lookup (file->details->metadata, GUINT_TO_POINTER (id));
4133
4134 if (value)
4135 {
4136 return g_strdup (value);
4137 }
4138 return g_strdup (default_metadata);
4139 }
4140
4141 GList *
nautilus_file_get_metadata_list(NautilusFile * file,const char * key)4142 nautilus_file_get_metadata_list (NautilusFile *file,
4143 const char *key)
4144 {
4145 GList *res;
4146 guint id;
4147 char **value;
4148 int i;
4149
4150 g_return_val_if_fail (key != NULL, NULL);
4151 g_return_val_if_fail (key[0] != '\0', NULL);
4152
4153 if (file == NULL ||
4154 file->details->metadata == NULL)
4155 {
4156 return NULL;
4157 }
4158
4159 g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
4160
4161 id = nautilus_metadata_get_id (key);
4162 id |= METADATA_ID_IS_LIST_MASK;
4163
4164 value = g_hash_table_lookup (file->details->metadata, GUINT_TO_POINTER (id));
4165
4166 if (value)
4167 {
4168 res = NULL;
4169 for (i = 0; value[i] != NULL; i++)
4170 {
4171 res = g_list_prepend (res, g_strdup (value[i]));
4172 }
4173 return g_list_reverse (res);
4174 }
4175
4176 return NULL;
4177 }
4178
4179 void
nautilus_file_set_metadata(NautilusFile * file,const char * key,const char * default_metadata,const char * metadata)4180 nautilus_file_set_metadata (NautilusFile *file,
4181 const char *key,
4182 const char *default_metadata,
4183 const char *metadata)
4184 {
4185 const char *val;
4186
4187 g_return_if_fail (NAUTILUS_IS_FILE (file));
4188 g_return_if_fail (key != NULL);
4189 g_return_if_fail (key[0] != '\0');
4190
4191 val = metadata;
4192 if (val == NULL)
4193 {
4194 val = default_metadata;
4195 }
4196
4197 NAUTILUS_FILE_CLASS (G_OBJECT_GET_CLASS (file))->set_metadata (file, key, val);
4198 }
4199
4200 void
nautilus_file_set_metadata_list(NautilusFile * file,const char * key,GList * list)4201 nautilus_file_set_metadata_list (NautilusFile *file,
4202 const char *key,
4203 GList *list)
4204 {
4205 char **val;
4206 int len, i;
4207 GList *l;
4208
4209 g_return_if_fail (NAUTILUS_IS_FILE (file));
4210 g_return_if_fail (key != NULL);
4211 g_return_if_fail (key[0] != '\0');
4212
4213 len = g_list_length (list);
4214 val = g_new (char *, len + 1);
4215 for (l = list, i = 0; l != NULL; l = l->next, i++)
4216 {
4217 val[i] = l->data;
4218 }
4219 val[i] = NULL;
4220
4221 NAUTILUS_FILE_CLASS (G_OBJECT_GET_CLASS (file))->set_metadata_as_list (file, key, val);
4222
4223 g_free (val);
4224 }
4225
4226 gboolean
nautilus_file_get_boolean_metadata(NautilusFile * file,const char * key,gboolean default_metadata)4227 nautilus_file_get_boolean_metadata (NautilusFile *file,
4228 const char *key,
4229 gboolean default_metadata)
4230 {
4231 char *result_as_string;
4232 gboolean result;
4233
4234 g_return_val_if_fail (key != NULL, default_metadata);
4235 g_return_val_if_fail (key[0] != '\0', default_metadata);
4236
4237 if (file == NULL)
4238 {
4239 return default_metadata;
4240 }
4241
4242 g_return_val_if_fail (NAUTILUS_IS_FILE (file), default_metadata);
4243
4244 result_as_string = nautilus_file_get_metadata
4245 (file, key, default_metadata ? "true" : "false");
4246 g_assert (result_as_string != NULL);
4247
4248 if (g_ascii_strcasecmp (result_as_string, "true") == 0)
4249 {
4250 result = TRUE;
4251 }
4252 else if (g_ascii_strcasecmp (result_as_string, "false") == 0)
4253 {
4254 result = FALSE;
4255 }
4256 else
4257 {
4258 g_error ("boolean metadata with value other than true or false");
4259 result = default_metadata;
4260 }
4261
4262 g_free (result_as_string);
4263 return result;
4264 }
4265
4266 int
nautilus_file_get_integer_metadata(NautilusFile * file,const char * key,int default_metadata)4267 nautilus_file_get_integer_metadata (NautilusFile *file,
4268 const char *key,
4269 int default_metadata)
4270 {
4271 char *result_as_string;
4272 char default_as_string[32];
4273 int result;
4274 char c;
4275
4276 g_return_val_if_fail (key != NULL, default_metadata);
4277 g_return_val_if_fail (key[0] != '\0', default_metadata);
4278
4279 if (file == NULL)
4280 {
4281 return default_metadata;
4282 }
4283 g_return_val_if_fail (NAUTILUS_IS_FILE (file), default_metadata);
4284
4285 g_snprintf (default_as_string, sizeof (default_as_string), "%d", default_metadata);
4286 result_as_string = nautilus_file_get_metadata
4287 (file, key, default_as_string);
4288
4289 /* Normally we can't get a a NULL, but we check for it here to
4290 * handle the oddball case of a non-existent directory.
4291 */
4292 if (result_as_string == NULL)
4293 {
4294 result = default_metadata;
4295 }
4296 else
4297 {
4298 if (sscanf (result_as_string, " %d %c", &result, &c) != 1)
4299 {
4300 result = default_metadata;
4301 }
4302 g_free (result_as_string);
4303 }
4304
4305 return result;
4306 }
4307
4308 static gboolean
get_time_from_time_string(const char * time_string,time_t * time)4309 get_time_from_time_string (const char *time_string,
4310 time_t *time)
4311 {
4312 long scanned_time;
4313 char c;
4314
4315 g_assert (time != NULL);
4316
4317 /* Only accept string if it has one integer with nothing
4318 * afterwards.
4319 */
4320 if (time_string == NULL ||
4321 sscanf (time_string, "%ld%c", &scanned_time, &c) != 1)
4322 {
4323 return FALSE;
4324 }
4325 *time = (time_t) scanned_time;
4326 return TRUE;
4327 }
4328
4329 time_t
nautilus_file_get_time_metadata(NautilusFile * file,const char * key)4330 nautilus_file_get_time_metadata (NautilusFile *file,
4331 const char *key)
4332 {
4333 time_t time;
4334 char *time_string;
4335
4336 time_string = nautilus_file_get_metadata (file, key, NULL);
4337 if (!get_time_from_time_string (time_string, &time))
4338 {
4339 time = UNDEFINED_TIME;
4340 }
4341 g_free (time_string);
4342
4343 return time;
4344 }
4345
4346 void
nautilus_file_set_time_metadata(NautilusFile * file,const char * key,time_t time)4347 nautilus_file_set_time_metadata (NautilusFile *file,
4348 const char *key,
4349 time_t time)
4350 {
4351 char time_str[21];
4352 char *metadata;
4353
4354 if (time != UNDEFINED_TIME)
4355 {
4356 /* 2^64 turns out to be 20 characters */
4357 g_snprintf (time_str, 20, "%ld", (long int) time);
4358 time_str[20] = '\0';
4359 metadata = time_str;
4360 }
4361 else
4362 {
4363 metadata = NULL;
4364 }
4365
4366 nautilus_file_set_metadata (file, key, NULL, metadata);
4367 }
4368
4369
4370 void
nautilus_file_set_boolean_metadata(NautilusFile * file,const char * key,gboolean default_metadata,gboolean metadata)4371 nautilus_file_set_boolean_metadata (NautilusFile *file,
4372 const char *key,
4373 gboolean default_metadata,
4374 gboolean metadata)
4375 {
4376 g_return_if_fail (NAUTILUS_IS_FILE (file));
4377 g_return_if_fail (key != NULL);
4378 g_return_if_fail (key[0] != '\0');
4379
4380 nautilus_file_set_metadata (file, key,
4381 default_metadata ? "true" : "false",
4382 metadata ? "true" : "false");
4383 }
4384
4385 void
nautilus_file_set_integer_metadata(NautilusFile * file,const char * key,int default_metadata,int metadata)4386 nautilus_file_set_integer_metadata (NautilusFile *file,
4387 const char *key,
4388 int default_metadata,
4389 int metadata)
4390 {
4391 char value_as_string[32];
4392 char default_as_string[32];
4393
4394 g_return_if_fail (NAUTILUS_IS_FILE (file));
4395 g_return_if_fail (key != NULL);
4396 g_return_if_fail (key[0] != '\0');
4397
4398 g_snprintf (value_as_string, sizeof (value_as_string), "%d", metadata);
4399 g_snprintf (default_as_string, sizeof (default_as_string), "%d", default_metadata);
4400
4401 nautilus_file_set_metadata (file, key,
4402 default_as_string, value_as_string);
4403 }
4404
4405 static const char *
nautilus_file_peek_display_name_collation_key(NautilusFile * file)4406 nautilus_file_peek_display_name_collation_key (NautilusFile *file)
4407 {
4408 const char *res;
4409
4410 res = file->details->display_name_collation_key;
4411 if (res == NULL)
4412 {
4413 res = "";
4414 }
4415
4416 return res;
4417 }
4418
4419 static const char *
nautilus_file_peek_display_name(NautilusFile * file)4420 nautilus_file_peek_display_name (NautilusFile *file)
4421 {
4422 const char *name;
4423 char *escaped_name;
4424
4425 /* FIXME: for some reason we can get a NautilusFile instance which is
4426 * no longer valid or could be freed somewhere else in the same time.
4427 * There's race condition somewhere. See bug 602500.
4428 */
4429 if (file == NULL || nautilus_file_is_gone (file))
4430 {
4431 return "";
4432 }
4433
4434 /* Default to display name based on filename if its not set yet */
4435
4436 if (file->details->display_name == NULL)
4437 {
4438 name = file->details->name;
4439 if (g_utf8_validate (name, -1, NULL))
4440 {
4441 nautilus_file_set_display_name (file,
4442 name,
4443 NULL,
4444 FALSE);
4445 }
4446 else
4447 {
4448 escaped_name = g_uri_escape_string (name, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, TRUE);
4449 nautilus_file_set_display_name (file,
4450 escaped_name,
4451 NULL,
4452 FALSE);
4453 g_free (escaped_name);
4454 }
4455 }
4456
4457 return file->details->display_name ?
4458 file->details->display_name : "";
4459 }
4460
4461 char *
nautilus_file_get_display_name(NautilusFile * file)4462 nautilus_file_get_display_name (NautilusFile *file)
4463 {
4464 if (nautilus_file_is_other_locations (file))
4465 {
4466 return g_strdup (_("Other Locations"));
4467 }
4468 if (nautilus_file_is_starred_location (file))
4469 {
4470 return g_strdup (_("Starred"));
4471 }
4472
4473 return g_strdup (nautilus_file_peek_display_name (file));
4474 }
4475
4476 char *
nautilus_file_get_edit_name(NautilusFile * file)4477 nautilus_file_get_edit_name (NautilusFile *file)
4478 {
4479 const char *res;
4480
4481 res = file->details->edit_name;
4482 if (res == NULL)
4483 {
4484 res = "";
4485 }
4486
4487 return g_strdup (res);
4488 }
4489
4490 char *
nautilus_file_get_name(NautilusFile * file)4491 nautilus_file_get_name (NautilusFile *file)
4492 {
4493 g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
4494
4495 return nautilus_file_info_get_name (NAUTILUS_FILE_INFO (file));
4496 }
4497
4498 /**
4499 * nautilus_file_get_description:
4500 * @file: a #NautilusFile.
4501 *
4502 * Gets the standard::description key from @file, if
4503 * it has been cached.
4504 *
4505 * Returns: a string containing the value of the standard::description
4506 * key, or %NULL.
4507 */
4508 char *
nautilus_file_get_description(NautilusFile * file)4509 nautilus_file_get_description (NautilusFile *file)
4510 {
4511 return g_strdup (file->details->description);
4512 }
4513
4514 void
nautilus_file_monitor_add(NautilusFile * file,gconstpointer client,NautilusFileAttributes attributes)4515 nautilus_file_monitor_add (NautilusFile *file,
4516 gconstpointer client,
4517 NautilusFileAttributes attributes)
4518 {
4519 g_return_if_fail (NAUTILUS_IS_FILE (file));
4520 g_return_if_fail (client != NULL);
4521
4522 NAUTILUS_FILE_CLASS (G_OBJECT_GET_CLASS (file))->monitor_add (file, client, attributes);
4523 }
4524
4525 void
nautilus_file_monitor_remove(NautilusFile * file,gconstpointer client)4526 nautilus_file_monitor_remove (NautilusFile *file,
4527 gconstpointer client)
4528 {
4529 g_return_if_fail (NAUTILUS_IS_FILE (file));
4530 g_return_if_fail (client != NULL);
4531
4532 NAUTILUS_FILE_CLASS (G_OBJECT_GET_CLASS (file))->monitor_remove (file, client);
4533 }
4534
4535 gboolean
nautilus_file_has_activation_uri(NautilusFile * file)4536 nautilus_file_has_activation_uri (NautilusFile *file)
4537 {
4538 return file->details->activation_uri != NULL;
4539 }
4540
4541
4542 /* Return the uri associated with the passed-in file, which may not be
4543 * the actual uri if the file is an desktop file or a nautilus
4544 * xml link file.
4545 */
4546 char *
nautilus_file_get_activation_uri(NautilusFile * file)4547 nautilus_file_get_activation_uri (NautilusFile *file)
4548 {
4549 g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
4550
4551 return nautilus_file_info_get_activation_uri (NAUTILUS_FILE_INFO (file));
4552 }
4553
4554 GFile *
nautilus_file_get_activation_location(NautilusFile * file)4555 nautilus_file_get_activation_location (NautilusFile *file)
4556 {
4557 g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
4558
4559 if (file->details->activation_uri != NULL)
4560 {
4561 return g_file_new_for_uri (file->details->activation_uri);
4562 }
4563
4564 return nautilus_file_get_location (file);
4565 }
4566
4567 static gboolean
is_uri_relative(const char * uri)4568 is_uri_relative (const char *uri)
4569 {
4570 char *scheme;
4571 gboolean ret;
4572
4573 scheme = g_uri_parse_scheme (uri);
4574 ret = (scheme == NULL);
4575 g_free (scheme);
4576 return ret;
4577 }
4578
4579 static char *
get_custom_icon_metadata_uri(NautilusFile * file)4580 get_custom_icon_metadata_uri (NautilusFile *file)
4581 {
4582 char *custom_icon_uri;
4583 char *uri;
4584 char *dir_uri;
4585
4586 uri = nautilus_file_get_metadata (file, NAUTILUS_METADATA_KEY_CUSTOM_ICON, NULL);
4587 if (uri != NULL &&
4588 nautilus_file_is_directory (file) &&
4589 is_uri_relative (uri))
4590 {
4591 dir_uri = nautilus_file_get_uri (file);
4592 custom_icon_uri = g_build_filename (dir_uri, uri, NULL);
4593 g_free (dir_uri);
4594 g_free (uri);
4595 }
4596 else
4597 {
4598 custom_icon_uri = uri;
4599 }
4600 return custom_icon_uri;
4601 }
4602
4603 static char *
get_custom_icon_metadata_name(NautilusFile * file)4604 get_custom_icon_metadata_name (NautilusFile *file)
4605 {
4606 char *icon_name;
4607
4608 icon_name = nautilus_file_get_metadata (file,
4609 NAUTILUS_METADATA_KEY_CUSTOM_ICON_NAME, NULL);
4610
4611 return icon_name;
4612 }
4613
4614 static GIcon *
get_mount_icon(NautilusFile * file)4615 get_mount_icon (NautilusFile *file)
4616 {
4617 GMount *mount;
4618 GIcon *mount_icon;
4619
4620 mount = nautilus_file_get_mount (file);
4621 mount_icon = NULL;
4622
4623 if (mount != NULL)
4624 {
4625 mount_icon = g_mount_get_icon (mount);
4626 g_object_unref (mount);
4627 }
4628
4629 return mount_icon;
4630 }
4631
4632 static GIcon *
get_custom_icon(NautilusFile * file)4633 get_custom_icon (NautilusFile *file)
4634 {
4635 char *custom_icon_uri, *custom_icon_name;
4636 GFile *icon_file;
4637 GIcon *icon;
4638
4639 if (file == NULL)
4640 {
4641 return NULL;
4642 }
4643
4644 icon = NULL;
4645
4646 /* Metadata takes precedence; first we look at the custom
4647 * icon URI, then at the custom icon name.
4648 */
4649 custom_icon_uri = get_custom_icon_metadata_uri (file);
4650
4651 if (custom_icon_uri)
4652 {
4653 icon_file = g_file_new_for_uri (custom_icon_uri);
4654 icon = g_file_icon_new (icon_file);
4655 g_object_unref (icon_file);
4656 g_free (custom_icon_uri);
4657 }
4658
4659 if (icon == NULL)
4660 {
4661 custom_icon_name = get_custom_icon_metadata_name (file);
4662
4663 if (custom_icon_name != NULL)
4664 {
4665 icon = g_themed_icon_new_with_default_fallbacks (custom_icon_name);
4666 g_free (custom_icon_name);
4667 }
4668 }
4669
4670 return icon;
4671 }
4672
4673 static GIcon *
get_default_file_icon(void)4674 get_default_file_icon (void)
4675 {
4676 static GIcon *fallback_icon = NULL;
4677 if (fallback_icon == NULL)
4678 {
4679 fallback_icon = g_themed_icon_new ("text-x-generic");
4680 }
4681
4682 return fallback_icon;
4683 }
4684
4685 GFilesystemPreviewType
nautilus_file_get_filesystem_use_preview(NautilusFile * file)4686 nautilus_file_get_filesystem_use_preview (NautilusFile *file)
4687 {
4688 GFilesystemPreviewType use_preview;
4689 NautilusFile *parent;
4690
4691 parent = nautilus_file_get_parent (file);
4692 if (parent != NULL)
4693 {
4694 use_preview = parent->details->filesystem_use_preview;
4695 g_object_unref (parent);
4696 }
4697 else
4698 {
4699 use_preview = 0;
4700 }
4701
4702 return use_preview;
4703 }
4704
4705 char *
nautilus_file_get_filesystem_type(NautilusFile * file)4706 nautilus_file_get_filesystem_type (NautilusFile *file)
4707 {
4708 char *filesystem_type = NULL;
4709
4710 g_assert (NAUTILUS_IS_FILE (file));
4711
4712 if (nautilus_file_is_directory (file))
4713 {
4714 filesystem_type = g_strdup (file->details->filesystem_type);
4715 }
4716 else
4717 {
4718 g_autoptr (NautilusFile) parent = NULL;
4719
4720 parent = nautilus_file_get_parent (file);
4721 if (parent != NULL)
4722 {
4723 filesystem_type = g_strdup (parent->details->filesystem_type);
4724 }
4725 }
4726
4727 return filesystem_type;
4728 }
4729
4730 gboolean
nautilus_file_get_filesystem_remote(NautilusFile * file)4731 nautilus_file_get_filesystem_remote (NautilusFile *file)
4732 {
4733 g_assert (NAUTILUS_IS_FILE (file));
4734
4735 if (nautilus_file_is_directory (file))
4736 {
4737 return file->details->filesystem_remote;
4738 }
4739 else
4740 {
4741 g_autoptr (NautilusFile) parent = NULL;
4742
4743 parent = nautilus_file_get_parent (file);
4744 if (parent != NULL)
4745 {
4746 return parent->details->filesystem_remote;
4747 }
4748 }
4749
4750 return FALSE;
4751 }
4752
4753 static gboolean
get_speed_tradeoff_preference_for_file(NautilusFile * file,NautilusSpeedTradeoffValue value)4754 get_speed_tradeoff_preference_for_file (NautilusFile *file,
4755 NautilusSpeedTradeoffValue value)
4756 {
4757 GFilesystemPreviewType use_preview;
4758
4759 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
4760
4761 use_preview = nautilus_file_get_filesystem_use_preview (file);
4762
4763 if (value == NAUTILUS_SPEED_TRADEOFF_ALWAYS)
4764 {
4765 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER)
4766 {
4767 return FALSE;
4768 }
4769 else
4770 {
4771 return TRUE;
4772 }
4773 }
4774 else if (value == NAUTILUS_SPEED_TRADEOFF_NEVER)
4775 {
4776 return FALSE;
4777 }
4778 else if (value == NAUTILUS_SPEED_TRADEOFF_LOCAL_ONLY)
4779 {
4780 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER)
4781 {
4782 /* file system says to never preview anything */
4783 return FALSE;
4784 }
4785 else if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL)
4786 {
4787 /* file system says we should treat file as if it's local */
4788 return TRUE;
4789 }
4790 else
4791 {
4792 /* only local files */
4793 return !nautilus_file_is_remote (file);
4794 }
4795 }
4796
4797 return FALSE;
4798 }
4799
4800 gboolean
nautilus_file_should_show_thumbnail(NautilusFile * file)4801 nautilus_file_should_show_thumbnail (NautilusFile *file)
4802 {
4803 const char *mime_type;
4804
4805 mime_type = file->details->mime_type;
4806 if (mime_type == NULL)
4807 {
4808 mime_type = "application/octet-stream";
4809 }
4810
4811 /* If the thumbnail has already been created, don't care about the size
4812 * of the original file.
4813 */
4814 if (nautilus_thumbnail_is_mimetype_limited_by_size (mime_type) &&
4815 file->details->thumbnail_path == NULL &&
4816 nautilus_file_get_size (file) > cached_thumbnail_limit)
4817 {
4818 return FALSE;
4819 }
4820
4821 return get_speed_tradeoff_preference_for_file (file, show_file_thumbs);
4822 }
4823
4824 static gboolean
nautilus_is_video_file(NautilusFile * file)4825 nautilus_is_video_file (NautilusFile *file)
4826 {
4827 const char *mime_type;
4828 guint i;
4829
4830 mime_type = file->details->mime_type;
4831 if (mime_type == NULL)
4832 {
4833 return FALSE;
4834 }
4835
4836 for (i = 0; video_mime_types[i] != NULL; i++)
4837 {
4838 if (g_content_type_equals (video_mime_types[i], mime_type))
4839 {
4840 return TRUE;
4841 }
4842 }
4843
4844 return FALSE;
4845 }
4846
4847 static GList *
sort_keyword_list_and_remove_duplicates(GList * keywords)4848 sort_keyword_list_and_remove_duplicates (GList *keywords)
4849 {
4850 GList *p;
4851 GList *duplicate_link;
4852
4853 if (keywords != NULL)
4854 {
4855 keywords = g_list_sort (keywords, (GCompareFunc) g_utf8_collate);
4856
4857 p = keywords;
4858 while (p->next != NULL)
4859 {
4860 if (strcmp ((const char *) p->data, (const char *) p->next->data) == 0)
4861 {
4862 duplicate_link = p->next;
4863 keywords = g_list_remove_link (keywords, duplicate_link);
4864 g_list_free_full (duplicate_link, g_free);
4865 }
4866 else
4867 {
4868 p = p->next;
4869 }
4870 }
4871 }
4872
4873 return keywords;
4874 }
4875
4876 static void
clean_up_metadata_keywords(NautilusFile * file,GList ** metadata_keywords)4877 clean_up_metadata_keywords (NautilusFile *file,
4878 GList **metadata_keywords)
4879 {
4880 NautilusFile *parent_file;
4881 GList *l, *res = NULL;
4882 char *exclude[4];
4883 char *keyword;
4884 gboolean found;
4885 gint i;
4886
4887 i = 0;
4888 exclude[i++] = NAUTILUS_FILE_EMBLEM_NAME_TRASH;
4889 exclude[i++] = NAUTILUS_FILE_EMBLEM_NAME_NOTE;
4890
4891 parent_file = nautilus_file_get_parent (file);
4892 if (parent_file)
4893 {
4894 if (!nautilus_file_can_write (parent_file))
4895 {
4896 exclude[i++] = NAUTILUS_FILE_EMBLEM_NAME_CANT_WRITE;
4897 }
4898 nautilus_file_unref (parent_file);
4899 }
4900 exclude[i++] = NULL;
4901
4902 for (l = *metadata_keywords; l != NULL; l = l->next)
4903 {
4904 keyword = l->data;
4905 found = FALSE;
4906
4907 for (i = 0; exclude[i] != NULL; i++)
4908 {
4909 if (strcmp (exclude[i], keyword) == 0)
4910 {
4911 found = TRUE;
4912 break;
4913 }
4914 }
4915
4916 if (!found)
4917 {
4918 res = g_list_prepend (res, keyword);
4919 }
4920 }
4921
4922 g_list_free (*metadata_keywords);
4923 *metadata_keywords = res;
4924 }
4925
4926 /**
4927 * nautilus_file_get_keywords
4928 *
4929 * Return this file's keywords.
4930 * @file: NautilusFile representing the file in question.
4931 *
4932 * Returns: A list of keywords.
4933 *
4934 **/
4935 static GList *
nautilus_file_get_keywords(NautilusFile * file)4936 nautilus_file_get_keywords (NautilusFile *file)
4937 {
4938 GList *keywords, *metadata_keywords;
4939
4940 if (file == NULL)
4941 {
4942 return NULL;
4943 }
4944
4945 g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
4946
4947 keywords = g_list_copy_deep (file->details->extension_emblems, (GCopyFunc) g_strdup, NULL);
4948 keywords = g_list_concat (keywords, g_list_copy_deep (file->details->pending_extension_emblems, (GCopyFunc) g_strdup, NULL));
4949
4950 metadata_keywords = nautilus_file_get_metadata_list (file, NAUTILUS_METADATA_KEY_EMBLEMS);
4951 clean_up_metadata_keywords (file, &metadata_keywords);
4952 keywords = g_list_concat (keywords, metadata_keywords);
4953
4954 return sort_keyword_list_and_remove_duplicates (keywords);
4955 }
4956
4957 /**
4958 * nautilus_file_get_emblem_icons
4959 *
4960 * Return the list of names of emblems that this file should display,
4961 * in canonical order.
4962 * @file: NautilusFile representing the file in question.
4963 *
4964 * Returns: A list of emblem names.
4965 *
4966 **/
4967 static GList *
nautilus_file_get_emblem_icons(NautilusFile * file)4968 nautilus_file_get_emblem_icons (NautilusFile *file)
4969 {
4970 GList *keywords, *l;
4971 GList *icons;
4972 char *icon_names[2];
4973 char *keyword;
4974 GIcon *icon;
4975
4976 if (file == NULL)
4977 {
4978 return NULL;
4979 }
4980
4981 g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
4982
4983 keywords = nautilus_file_get_keywords (file);
4984 keywords = prepend_automatic_keywords (file, keywords);
4985
4986 icons = NULL;
4987 for (l = keywords; l != NULL; l = l->next)
4988 {
4989 keyword = l->data;
4990
4991 icon_names[0] = g_strconcat ("emblem-", keyword, NULL);
4992 icon_names[1] = keyword;
4993 icon = g_themed_icon_new_from_names (icon_names, 2);
4994 g_free (icon_names[0]);
4995
4996 icons = g_list_prepend (icons, icon);
4997 }
4998
4999 icon = get_mount_icon (file);
5000 if (icon != NULL)
5001 {
5002 icons = g_list_prepend (icons, icon);
5003 }
5004
5005 g_list_free_full (keywords, g_free);
5006
5007 return icons;
5008 }
5009
5010 static void
prepend_icon_name(const char * name,GThemedIcon * icon)5011 prepend_icon_name (const char *name,
5012 GThemedIcon *icon)
5013 {
5014 g_themed_icon_prepend_name (icon, name);
5015 }
5016
5017 static void
apply_emblems_to_icon(NautilusFile * file,GIcon ** icon,NautilusFileIconFlags flags)5018 apply_emblems_to_icon (NautilusFile *file,
5019 GIcon **icon,
5020 NautilusFileIconFlags flags)
5021 {
5022 GIcon *emblemed_icon = NULL;
5023 g_autolist (GIcon) emblems = NULL;
5024
5025 emblems = nautilus_file_get_emblem_icons (file);
5026
5027 for (GList *l = emblems; l != NULL; l = l->next)
5028 {
5029 g_autoptr (GEmblem) emblem = NULL;
5030
5031 if (g_icon_equal (l->data, *icon))
5032 {
5033 continue;
5034 }
5035
5036 emblem = g_emblem_new (l->data);
5037
5038 if (emblemed_icon == NULL)
5039 {
5040 emblemed_icon = g_emblemed_icon_new (*icon, emblem);
5041 }
5042 else
5043 {
5044 g_emblemed_icon_add_emblem (G_EMBLEMED_ICON (emblemed_icon), emblem);
5045 }
5046
5047 if (emblemed_icon != NULL &&
5048 (flags & NAUTILUS_FILE_ICON_FLAGS_USE_ONE_EMBLEM))
5049 {
5050 break;
5051 }
5052 }
5053
5054 if (emblemed_icon != NULL)
5055 {
5056 g_object_unref (*icon);
5057 *icon = emblemed_icon;
5058 }
5059 }
5060
5061 GIcon *
nautilus_file_get_gicon(NautilusFile * file,NautilusFileIconFlags flags)5062 nautilus_file_get_gicon (NautilusFile *file,
5063 NautilusFileIconFlags flags)
5064 {
5065 const char * const *names;
5066 const char *name;
5067 GPtrArray *prepend_array;
5068 GIcon *icon;
5069 int i;
5070 gboolean is_folder = FALSE, is_inode_directory = FALSE;
5071
5072 if (file == NULL)
5073 {
5074 return NULL;
5075 }
5076
5077 icon = get_custom_icon (file);
5078 if (icon != NULL)
5079 {
5080 return icon;
5081 }
5082
5083 if (flags & NAUTILUS_FILE_ICON_FLAGS_USE_MOUNT_ICON)
5084 {
5085 icon = get_mount_icon (file);
5086
5087 if (icon != NULL)
5088 {
5089 goto out;
5090 }
5091 }
5092
5093 if (file->details->icon)
5094 {
5095 icon = NULL;
5096
5097 if (((flags & NAUTILUS_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT) ||
5098 (flags & NAUTILUS_FILE_ICON_FLAGS_FOR_OPEN_FOLDER) ||
5099 (flags & NAUTILUS_FILE_ICON_FLAGS_USE_MOUNT_ICON) ||
5100 (flags & NAUTILUS_FILE_ICON_FLAGS_USE_EMBLEMS)) &&
5101 G_IS_THEMED_ICON (file->details->icon))
5102 {
5103 names = g_themed_icon_get_names (G_THEMED_ICON (file->details->icon));
5104 prepend_array = g_ptr_array_new ();
5105
5106 for (i = 0; names[i] != NULL; i++)
5107 {
5108 name = names[i];
5109
5110 if (strcmp (name, "folder") == 0)
5111 {
5112 is_folder = TRUE;
5113 }
5114 if (strcmp (name, "inode-directory") == 0)
5115 {
5116 is_inode_directory = TRUE;
5117 }
5118 }
5119
5120 /* Here, we add icons in reverse order of precedence,
5121 * because they are later prepended */
5122
5123 /* "folder" should override "inode-directory", not the other way around */
5124 if (is_inode_directory)
5125 {
5126 g_ptr_array_add (prepend_array, "folder");
5127 }
5128 if (is_folder && (flags & NAUTILUS_FILE_ICON_FLAGS_FOR_OPEN_FOLDER))
5129 {
5130 g_ptr_array_add (prepend_array, "folder-open");
5131 }
5132 if (is_folder &&
5133 (flags & NAUTILUS_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT))
5134 {
5135 g_ptr_array_add (prepend_array, "folder-drag-accept");
5136 }
5137
5138 if (prepend_array->len)
5139 {
5140 /* When constructing GThemed Icon, pointers from the array
5141 * are reused, but not the array itself, so the cast is safe */
5142 icon = g_themed_icon_new_from_names ((char **) names, -1);
5143 g_ptr_array_foreach (prepend_array, (GFunc) prepend_icon_name, icon);
5144 }
5145
5146 g_ptr_array_free (prepend_array, TRUE);
5147 }
5148
5149 if (icon == NULL)
5150 {
5151 icon = g_object_ref (file->details->icon);
5152 }
5153 }
5154
5155 out:
5156 if (icon == NULL)
5157 {
5158 icon = g_object_ref (get_default_file_icon ());
5159 }
5160
5161 if (flags & NAUTILUS_FILE_ICON_FLAGS_USE_EMBLEMS)
5162 {
5163 apply_emblems_to_icon (file, &icon, flags);
5164 }
5165
5166 return icon;
5167 }
5168
5169 char *
nautilus_file_get_thumbnail_path(NautilusFile * file)5170 nautilus_file_get_thumbnail_path (NautilusFile *file)
5171 {
5172 return g_strdup (file->details->thumbnail_path);
5173 }
5174
5175 static NautilusIconInfo *
nautilus_file_get_thumbnail_icon(NautilusFile * file,int size,int scale,NautilusFileIconFlags flags)5176 nautilus_file_get_thumbnail_icon (NautilusFile *file,
5177 int size,
5178 int scale,
5179 NautilusFileIconFlags flags)
5180 {
5181 int modified_size;
5182 GdkPixbuf *pixbuf;
5183 int w, h, s;
5184 double thumb_scale;
5185 GIcon *gicon;
5186 NautilusIconInfo *icon;
5187
5188 icon = NULL;
5189 gicon = NULL;
5190 pixbuf = NULL;
5191
5192 if (flags & NAUTILUS_FILE_ICON_FLAGS_FORCE_THUMBNAIL_SIZE)
5193 {
5194 modified_size = size * scale;
5195 }
5196 else
5197 {
5198 modified_size = size * scale * NAUTILUS_CANVAS_ICON_SIZE_STANDARD / NAUTILUS_CANVAS_ICON_SIZE_SMALL;
5199 }
5200
5201 if (file->details->thumbnail)
5202 {
5203 w = gdk_pixbuf_get_width (file->details->thumbnail);
5204 h = gdk_pixbuf_get_height (file->details->thumbnail);
5205
5206 s = MAX (w, h);
5207 /* Don't scale up small thumbnails in the standard view */
5208 if (s <= NAUTILUS_CANVAS_ICON_SIZE_STANDARD)
5209 {
5210 thumb_scale = (double) size / NAUTILUS_CANVAS_ICON_SIZE_SMALL;
5211 }
5212 else
5213 {
5214 thumb_scale = (double) modified_size / s;
5215 }
5216
5217 /* Make sure that icons don't get smaller than NAUTILUS_LIST_ICON_SIZE_SMALL */
5218 if (s * thumb_scale <= NAUTILUS_LIST_ICON_SIZE_SMALL)
5219 {
5220 thumb_scale = (double) NAUTILUS_LIST_ICON_SIZE_SMALL / s;
5221 }
5222
5223 if (file->details->thumbnail_scale == thumb_scale &&
5224 file->details->scaled_thumbnail != NULL)
5225 {
5226 pixbuf = file->details->scaled_thumbnail;
5227 }
5228 else
5229 {
5230 GdkPixbuf *bg_pixbuf;
5231 int bg_size;
5232
5233 pixbuf = gdk_pixbuf_scale_simple (file->details->thumbnail,
5234 MAX (w * thumb_scale, 1),
5235 MAX (h * thumb_scale, 1),
5236 GDK_INTERP_BILINEAR);
5237
5238 /* We don't want frames around small icons */
5239 if (!gdk_pixbuf_get_has_alpha (file->details->thumbnail) || s >= 128 * scale)
5240 {
5241 gboolean use_experimental_views;
5242
5243 use_experimental_views = g_settings_get_boolean (nautilus_preferences,
5244 NAUTILUS_PREFERENCES_USE_EXPERIMENTAL_VIEWS);
5245 if (!use_experimental_views)
5246 {
5247 if (nautilus_is_video_file (file))
5248 {
5249 nautilus_ui_frame_video (&pixbuf);
5250 }
5251 else
5252 {
5253 nautilus_ui_frame_image (&pixbuf);
5254 }
5255 }
5256 }
5257
5258 /* Copy to a transparent square pixbuf, aligned to the bottom edge */
5259 bg_size = MAX (gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf));
5260 bg_pixbuf = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (pixbuf),
5261 TRUE,
5262 gdk_pixbuf_get_bits_per_sample (pixbuf),
5263 bg_size,
5264 bg_size);
5265 gdk_pixbuf_fill (bg_pixbuf, 0);
5266 gdk_pixbuf_copy_area (pixbuf,
5267 0,
5268 0,
5269 gdk_pixbuf_get_width (pixbuf),
5270 gdk_pixbuf_get_height (pixbuf),
5271 bg_pixbuf,
5272 (bg_size - gdk_pixbuf_get_width (pixbuf)) / 2,
5273 (bg_size - gdk_pixbuf_get_height (pixbuf)));
5274 g_clear_object (&pixbuf);
5275 pixbuf = bg_pixbuf;
5276
5277 g_clear_object (&file->details->scaled_thumbnail);
5278 file->details->scaled_thumbnail = pixbuf;
5279 file->details->thumbnail_scale = thumb_scale;
5280 }
5281
5282 DEBUG ("Returning thumbnailed image, at size %d %d",
5283 gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf));
5284 }
5285 else if (file->details->thumbnail_path == NULL &&
5286 file->details->can_read &&
5287 !file->details->is_thumbnailing &&
5288 !file->details->thumbnailing_failed &&
5289 nautilus_can_thumbnail (file))
5290 {
5291 nautilus_create_thumbnail (file);
5292 }
5293
5294 if (pixbuf != NULL)
5295 {
5296 gicon = G_ICON (g_object_ref (pixbuf));
5297 }
5298 else if (file->details->is_thumbnailing)
5299 {
5300 gicon = g_themed_icon_new (ICON_NAME_THUMBNAIL_LOADING);
5301 }
5302
5303 if (gicon != NULL)
5304 {
5305 apply_emblems_to_icon (file, &gicon, flags);
5306
5307 if (g_icon_equal (gicon, G_ICON (pixbuf)))
5308 {
5309 icon = nautilus_icon_info_new_for_pixbuf (pixbuf, scale);
5310 }
5311 else
5312 {
5313 icon = nautilus_icon_info_lookup (gicon, size, scale);
5314 }
5315
5316 g_object_unref (gicon);
5317 }
5318
5319 return icon;
5320 }
5321
5322 static gboolean
nautilus_thumbnail_is_limited_by_zoom(int size,int scale)5323 nautilus_thumbnail_is_limited_by_zoom (int size,
5324 int scale)
5325 {
5326 int zoom_level;
5327
5328 zoom_level = size * scale;
5329
5330 if (zoom_level <= NAUTILUS_LIST_ICON_SIZE_STANDARD)
5331 {
5332 return TRUE;
5333 }
5334
5335 return FALSE;
5336 }
5337
5338 NautilusIconInfo *
nautilus_file_get_icon(NautilusFile * file,int size,int scale,NautilusFileIconFlags flags)5339 nautilus_file_get_icon (NautilusFile *file,
5340 int size,
5341 int scale,
5342 NautilusFileIconFlags flags)
5343 {
5344 NautilusIconInfo *icon;
5345 GIcon *gicon;
5346
5347 icon = NULL;
5348
5349 if (file == NULL)
5350 {
5351 goto out;
5352 }
5353
5354 gicon = get_custom_icon (file);
5355 if (gicon != NULL)
5356 {
5357 if (flags & NAUTILUS_FILE_ICON_FLAGS_USE_EMBLEMS)
5358 {
5359 apply_emblems_to_icon (file, &gicon, flags);
5360 }
5361
5362 icon = nautilus_icon_info_lookup (gicon, size, scale);
5363 g_object_unref (gicon);
5364
5365 goto out;
5366 }
5367
5368 DEBUG ("Called file_get_icon(), at size %d, force thumbnail %d", size,
5369 flags & NAUTILUS_FILE_ICON_FLAGS_FORCE_THUMBNAIL_SIZE);
5370
5371 if (flags & NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS &&
5372 nautilus_file_should_show_thumbnail (file) &&
5373 !nautilus_thumbnail_is_limited_by_zoom (size, scale))
5374 {
5375 icon = nautilus_file_get_thumbnail_icon (file, size, scale, flags);
5376 }
5377
5378 if (icon == NULL)
5379 {
5380 gicon = nautilus_file_get_gicon (file, flags);
5381 icon = nautilus_icon_info_lookup (gicon, size, scale);
5382 g_object_unref (gicon);
5383
5384 if (nautilus_icon_info_is_fallback (icon))
5385 {
5386 g_object_unref (icon);
5387 icon = nautilus_icon_info_lookup (get_default_file_icon (), size, scale);
5388 }
5389 }
5390
5391 out:
5392 return icon;
5393 }
5394
5395 GdkPixbuf *
nautilus_file_get_icon_pixbuf(NautilusFile * file,int size,gboolean force_size,int scale,NautilusFileIconFlags flags)5396 nautilus_file_get_icon_pixbuf (NautilusFile *file,
5397 int size,
5398 gboolean force_size,
5399 int scale,
5400 NautilusFileIconFlags flags)
5401 {
5402 NautilusIconInfo *info;
5403 GdkPixbuf *pixbuf;
5404
5405 info = nautilus_file_get_icon (file, size, scale, flags);
5406 if (force_size)
5407 {
5408 pixbuf = nautilus_icon_info_get_pixbuf_at_size (info, size);
5409 }
5410 else
5411 {
5412 pixbuf = nautilus_icon_info_get_pixbuf (info);
5413 }
5414 g_object_unref (info);
5415
5416 return pixbuf;
5417 }
5418
5419 gboolean
nautilus_file_get_date(NautilusFile * file,NautilusDateType date_type,time_t * date)5420 nautilus_file_get_date (NautilusFile *file,
5421 NautilusDateType date_type,
5422 time_t *date)
5423 {
5424 if (date != NULL)
5425 {
5426 *date = 0;
5427 }
5428
5429 g_return_val_if_fail (date_type == NAUTILUS_DATE_TYPE_ACCESSED
5430 || date_type == NAUTILUS_DATE_TYPE_MODIFIED
5431 || date_type == NAUTILUS_DATE_TYPE_CREATED
5432 || date_type == NAUTILUS_DATE_TYPE_TRASHED
5433 || date_type == NAUTILUS_DATE_TYPE_RECENCY,
5434 FALSE);
5435
5436 if (file == NULL)
5437 {
5438 return FALSE;
5439 }
5440
5441 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
5442
5443 return NAUTILUS_FILE_CLASS (G_OBJECT_GET_CLASS (file))->get_date (file, date_type, date);
5444 }
5445
5446 static char *
nautilus_file_get_where_string(NautilusFile * file)5447 nautilus_file_get_where_string (NautilusFile *file)
5448 {
5449 if (file == NULL)
5450 {
5451 return NULL;
5452 }
5453
5454 g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
5455
5456 return NAUTILUS_FILE_CLASS (G_OBJECT_GET_CLASS (file))->get_where_string (file);
5457 }
5458
5459 static char *
nautilus_file_get_trash_original_file_parent_as_string(NautilusFile * file)5460 nautilus_file_get_trash_original_file_parent_as_string (NautilusFile *file)
5461 {
5462 NautilusFile *orig_file;
5463 char *filename;
5464
5465 filename = NULL;
5466 orig_file = nautilus_file_get_trash_original_file (file);
5467 if (orig_file != NULL)
5468 {
5469 filename = nautilus_file_get_parent_uri_for_display (orig_file);
5470
5471 nautilus_file_unref (orig_file);
5472 }
5473
5474 return filename;
5475 }
5476
5477 /**
5478 * nautilus_file_get_date_as_string:
5479 *
5480 * Get a user-displayable string representing a file modification date.
5481 * The caller is responsible for g_free-ing this string.
5482 * @file: NautilusFile representing the file in question.
5483 *
5484 * Returns: Newly allocated string ready to display to the user.
5485 *
5486 **/
5487 static char *
nautilus_file_get_date_as_string(NautilusFile * file,NautilusDateType date_type,NautilusDateFormat date_format)5488 nautilus_file_get_date_as_string (NautilusFile *file,
5489 NautilusDateType date_type,
5490 NautilusDateFormat date_format)
5491 {
5492 time_t file_time_raw;
5493 GDateTime *file_date_time, *now;
5494 GDateTime *today_midnight;
5495 gint days_ago;
5496 gboolean use_24;
5497 const gchar *format;
5498 gchar *result;
5499 gchar *result_with_ratio;
5500
5501 if (!nautilus_file_get_date (file, date_type, &file_time_raw))
5502 {
5503 return NULL;
5504 }
5505
5506 file_date_time = g_date_time_new_from_unix_local (file_time_raw);
5507 if (date_format != NAUTILUS_DATE_FORMAT_FULL)
5508 {
5509 GDateTime *file_date;
5510
5511 now = g_date_time_new_now_local ();
5512 today_midnight = g_date_time_new_local (g_date_time_get_year (now),
5513 g_date_time_get_month (now),
5514 g_date_time_get_day_of_month (now),
5515 0, 0, 0);
5516
5517 file_date = g_date_time_new_local (g_date_time_get_year (file_date_time),
5518 g_date_time_get_month (file_date_time),
5519 g_date_time_get_day_of_month (file_date_time),
5520 0, 0, 0);
5521
5522 days_ago = g_date_time_difference (today_midnight, file_date) / G_TIME_SPAN_DAY;
5523
5524 use_24 = g_settings_get_enum (gnome_interface_preferences, "clock-format") ==
5525 G_DESKTOP_CLOCK_FORMAT_24H;
5526
5527 /* Show only the time if date is on today */
5528 if (days_ago == 0)
5529 {
5530 if (use_24)
5531 {
5532 /* Translators: Time in 24h format */
5533 format = _("%H:%M");
5534 }
5535 else
5536 {
5537 /* Translators: Time in 12h format */
5538 format = _("%l:%M %p");
5539 }
5540 }
5541 /* Show the word "Yesterday" and time if date is on yesterday */
5542 else if (days_ago == 1)
5543 {
5544 if (date_format == NAUTILUS_DATE_FORMAT_REGULAR)
5545 {
5546 /* xgettext:no-c-format */
5547 format = _("Yesterday");
5548 }
5549 else
5550 {
5551 if (use_24)
5552 {
5553 /* Translators: this is the word Yesterday followed by
5554 * a time in 24h format. i.e. "Yesterday 23:04" */
5555 /* xgettext:no-c-format */
5556 format = _("Yesterday %H:%M");
5557 }
5558 else
5559 {
5560 /* Translators: this is the word Yesterday followed by
5561 * a time in 12h format. i.e. "Yesterday 9:04 PM" */
5562 /* xgettext:no-c-format */
5563 format = _("Yesterday %l:%M %p");
5564 }
5565 }
5566 }
5567 /* Show a week day and time if date is in the last week */
5568 else if (days_ago > 1 && days_ago < 7)
5569 {
5570 if (date_format == NAUTILUS_DATE_FORMAT_REGULAR)
5571 {
5572 /* xgettext:no-c-format */
5573 format = _("%a");
5574 }
5575 else
5576 {
5577 if (use_24)
5578 {
5579 /* Translators: this is the name of the week day followed by
5580 * a time in 24h format. i.e. "Monday 23:04" */
5581 /* xgettext:no-c-format */
5582 format = _("%a %H:%M");
5583 }
5584 else
5585 {
5586 /* Translators: this is the week day name followed by
5587 * a time in 12h format. i.e. "Monday 9:04 PM" */
5588 /* xgettext:no-c-format */
5589 format = _("%a %l:%M %p");
5590 }
5591 }
5592 }
5593 else if (g_date_time_get_year (file_date) == g_date_time_get_year (now))
5594 {
5595 if (date_format == NAUTILUS_DATE_FORMAT_REGULAR)
5596 {
5597 /* Translators: this is the day of the month followed
5598 * by the abbreviated month name i.e. "3 Feb" */
5599 /* xgettext:no-c-format */
5600 format = _("%-e %b");
5601 }
5602 else
5603 {
5604 if (use_24)
5605 {
5606 /* Translators: this is the day of the month followed
5607 * by the abbreviated month name followed by a time in
5608 * 24h format i.e. "3 Feb 23:04" */
5609 /* xgettext:no-c-format */
5610 format = _("%-e %b %H:%M");
5611 }
5612 else
5613 {
5614 /* Translators: this is the day of the month followed
5615 * by the abbreviated month name followed by a time in
5616 * 12h format i.e. "3 Feb 9:04" */
5617 /* xgettext:no-c-format */
5618 format = _("%-e %b %l:%M %p");
5619 }
5620 }
5621 }
5622 else
5623 {
5624 if (date_format == NAUTILUS_DATE_FORMAT_REGULAR)
5625 {
5626 /* Translators: this is the day of the month followed by the abbreviated
5627 * month name followed by the year i.e. "3 Feb 2015" */
5628 /* xgettext:no-c-format */
5629 format = _("%-e %b %Y");
5630 }
5631 else
5632 {
5633 if (use_24)
5634 {
5635 /* Translators: this is the day number followed
5636 * by the abbreviated month name followed by the year followed
5637 * by a time in 24h format i.e. "3 Feb 2015 23:04" */
5638 /* xgettext:no-c-format */
5639 format = _("%-e %b %Y %H:%M");
5640 }
5641 else
5642 {
5643 /* Translators: this is the day number followed
5644 * by the abbreviated month name followed by the year followed
5645 * by a time in 12h format i.e. "3 Feb 2015 9:04 PM" */
5646 /* xgettext:no-c-format */
5647 format = _("%-e %b %Y %l:%M %p");
5648 }
5649 }
5650 }
5651
5652 g_date_time_unref (file_date);
5653 g_date_time_unref (now);
5654 g_date_time_unref (today_midnight);
5655 }
5656 else
5657 {
5658 /* xgettext:no-c-format */
5659 format = _("%c");
5660 }
5661
5662 result = g_date_time_format (file_date_time, format);
5663 g_date_time_unref (file_date_time);
5664
5665 /* Replace ":" with ratio. Replacement is done afterward because g_date_time_format
5666 * may fail with utf8 chars in some locales */
5667 result_with_ratio = eel_str_replace_substring (result, ":", "∶");
5668 g_free (result);
5669
5670 return result_with_ratio;
5671 }
5672
5673 static void
show_directory_item_count_changed_callback(gpointer callback_data)5674 show_directory_item_count_changed_callback (gpointer callback_data)
5675 {
5676 show_directory_item_count = g_settings_get_enum (nautilus_preferences, NAUTILUS_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS);
5677 }
5678
5679 gboolean
nautilus_file_should_show_directory_item_count(NautilusFile * file)5680 nautilus_file_should_show_directory_item_count (NautilusFile *file)
5681 {
5682 static gboolean show_directory_item_count_callback_added = FALSE;
5683
5684 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
5685
5686 if (file->details->mime_type &&
5687 strcmp (file->details->mime_type, "x-directory/smb-share") == 0)
5688 {
5689 return FALSE;
5690 }
5691
5692 /* Add the callback once for the life of our process */
5693 if (!show_directory_item_count_callback_added)
5694 {
5695 g_signal_connect_swapped (nautilus_preferences,
5696 "changed::" NAUTILUS_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS,
5697 G_CALLBACK (show_directory_item_count_changed_callback),
5698 NULL);
5699 show_directory_item_count_callback_added = TRUE;
5700
5701 /* Peek for the first time */
5702 show_directory_item_count_changed_callback (NULL);
5703 }
5704
5705 return get_speed_tradeoff_preference_for_file (file, show_directory_item_count);
5706 }
5707
5708 /**
5709 * nautilus_file_get_directory_item_count
5710 *
5711 * Get the number of items in a directory.
5712 * @file: NautilusFile representing a directory.
5713 * @count: Place to put count.
5714 * @count_unreadable: Set to TRUE (if non-NULL) if permissions prevent
5715 * the item count from being read on this directory. Otherwise set to FALSE.
5716 *
5717 * Returns: TRUE if count is available.
5718 *
5719 **/
5720 gboolean
nautilus_file_get_directory_item_count(NautilusFile * file,guint * count,gboolean * count_unreadable)5721 nautilus_file_get_directory_item_count (NautilusFile *file,
5722 guint *count,
5723 gboolean *count_unreadable)
5724 {
5725 if (count != NULL)
5726 {
5727 *count = 0;
5728 }
5729 if (count_unreadable != NULL)
5730 {
5731 *count_unreadable = FALSE;
5732 }
5733
5734 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
5735
5736 if (!nautilus_file_is_directory (file))
5737 {
5738 return FALSE;
5739 }
5740
5741 if (!nautilus_file_should_show_directory_item_count (file))
5742 {
5743 return FALSE;
5744 }
5745
5746 return NAUTILUS_FILE_CLASS (G_OBJECT_GET_CLASS (file))->get_item_count
5747 (file, count, count_unreadable);
5748 }
5749
5750 /**
5751 * nautilus_file_get_deep_counts
5752 *
5753 * Get the statistics about items inside a directory.
5754 * @file: NautilusFile representing a directory or file.
5755 * @directory_count: Place to put count of directories inside.
5756 * @files_count: Place to put count of files inside.
5757 * @unreadable_directory_count: Number of directories encountered
5758 * that were unreadable.
5759 * @total_size: Total size of all files and directories visited.
5760 * @force: Whether the deep counts should even be collected if
5761 * nautilus_file_should_show_directory_item_count returns FALSE
5762 * for this file.
5763 *
5764 * Returns: Status to indicate whether sizes are available.
5765 *
5766 **/
5767 NautilusRequestStatus
nautilus_file_get_deep_counts(NautilusFile * file,guint * directory_count,guint * file_count,guint * unreadable_directory_count,goffset * total_size,gboolean force)5768 nautilus_file_get_deep_counts (NautilusFile *file,
5769 guint *directory_count,
5770 guint *file_count,
5771 guint *unreadable_directory_count,
5772 goffset *total_size,
5773 gboolean force)
5774 {
5775 if (directory_count != NULL)
5776 {
5777 *directory_count = 0;
5778 }
5779 if (file_count != NULL)
5780 {
5781 *file_count = 0;
5782 }
5783 if (unreadable_directory_count != NULL)
5784 {
5785 *unreadable_directory_count = 0;
5786 }
5787 if (total_size != NULL)
5788 {
5789 *total_size = 0;
5790 }
5791
5792 g_return_val_if_fail (NAUTILUS_IS_FILE (file), NAUTILUS_REQUEST_DONE);
5793
5794 if (!force && !nautilus_file_should_show_directory_item_count (file))
5795 {
5796 /* Set field so an existing value isn't treated as up-to-date
5797 * when preference changes later.
5798 */
5799 file->details->deep_counts_status = NAUTILUS_REQUEST_NOT_STARTED;
5800 return file->details->deep_counts_status;
5801 }
5802
5803 return NAUTILUS_FILE_CLASS (G_OBJECT_GET_CLASS (file))->get_deep_counts
5804 (file, directory_count, file_count,
5805 unreadable_directory_count, total_size);
5806 }
5807
5808 void
nautilus_file_recompute_deep_counts(NautilusFile * file)5809 nautilus_file_recompute_deep_counts (NautilusFile *file)
5810 {
5811 if (file->details->deep_counts_status != NAUTILUS_REQUEST_IN_PROGRESS)
5812 {
5813 file->details->deep_counts_status = NAUTILUS_REQUEST_NOT_STARTED;
5814 if (file->details->directory != NULL)
5815 {
5816 nautilus_directory_add_file_to_work_queue (file->details->directory, file);
5817 nautilus_directory_async_state_changed (file->details->directory);
5818 }
5819 }
5820 }
5821
5822 gboolean
nautilus_file_can_get_size(NautilusFile * file)5823 nautilus_file_can_get_size (NautilusFile *file)
5824 {
5825 return file->details->size == -1;
5826 }
5827
5828
5829 /**
5830 * nautilus_file_get_size
5831 *
5832 * Get the file size.
5833 * @file: NautilusFile representing the file in question.
5834 *
5835 * Returns: Size in bytes.
5836 *
5837 **/
5838 goffset
nautilus_file_get_size(NautilusFile * file)5839 nautilus_file_get_size (NautilusFile *file)
5840 {
5841 /* Before we have info on the file, we don't know the size. */
5842 if (file->details->size == -1)
5843 {
5844 return 0;
5845 }
5846 return file->details->size;
5847 }
5848
5849 time_t
nautilus_file_get_mtime(NautilusFile * file)5850 nautilus_file_get_mtime (NautilusFile *file)
5851 {
5852 return file->details->mtime;
5853 }
5854
5855 time_t
nautilus_file_get_atime(NautilusFile * file)5856 nautilus_file_get_atime (NautilusFile *file)
5857 {
5858 return file->details->atime;
5859 }
5860
5861 time_t
nautilus_file_get_btime(NautilusFile * file)5862 nautilus_file_get_btime (NautilusFile *file)
5863 {
5864 return file->details->btime;
5865 }
5866
5867 time_t
nautilus_file_get_recency(NautilusFile * file)5868 nautilus_file_get_recency (NautilusFile *file)
5869 {
5870 g_return_val_if_fail (NAUTILUS_IS_FILE (file), 0);
5871
5872 return file->details->recency;
5873 }
5874
5875 time_t
nautilus_file_get_trash_time(NautilusFile * file)5876 nautilus_file_get_trash_time (NautilusFile *file)
5877 {
5878 g_return_val_if_fail (NAUTILUS_IS_FILE (file), 0);
5879
5880 return file->details->trash_time;
5881 }
5882
5883 static void
set_attributes_get_info_callback(GObject * source_object,GAsyncResult * res,gpointer callback_data)5884 set_attributes_get_info_callback (GObject *source_object,
5885 GAsyncResult *res,
5886 gpointer callback_data)
5887 {
5888 NautilusFileOperation *op;
5889 GFileInfo *new_info;
5890 GError *error;
5891
5892 op = callback_data;
5893
5894 error = NULL;
5895 new_info = g_file_query_info_finish (G_FILE (source_object), res, &error);
5896 if (new_info != NULL)
5897 {
5898 if (nautilus_file_update_info (op->file, new_info))
5899 {
5900 nautilus_file_changed (op->file);
5901 }
5902 g_object_unref (new_info);
5903 }
5904 nautilus_file_operation_complete (op, NULL, error);
5905 if (error)
5906 {
5907 g_error_free (error);
5908 }
5909 }
5910
5911
5912 static void
set_attributes_callback(GObject * source_object,GAsyncResult * result,gpointer callback_data)5913 set_attributes_callback (GObject *source_object,
5914 GAsyncResult *result,
5915 gpointer callback_data)
5916 {
5917 NautilusFileOperation *op;
5918 GError *error;
5919 gboolean res;
5920
5921 op = callback_data;
5922
5923 error = NULL;
5924 res = g_file_set_attributes_finish (G_FILE (source_object),
5925 result,
5926 NULL,
5927 &error);
5928
5929 if (res)
5930 {
5931 g_file_query_info_async (G_FILE (source_object),
5932 NAUTILUS_FILE_DEFAULT_ATTRIBUTES,
5933 0,
5934 G_PRIORITY_DEFAULT,
5935 op->cancellable,
5936 set_attributes_get_info_callback, op);
5937 }
5938 else
5939 {
5940 nautilus_file_operation_complete (op, NULL, error);
5941 g_error_free (error);
5942 }
5943 }
5944
5945 void
nautilus_file_set_attributes(NautilusFile * file,GFileInfo * attributes,NautilusFileOperationCallback callback,gpointer callback_data)5946 nautilus_file_set_attributes (NautilusFile *file,
5947 GFileInfo *attributes,
5948 NautilusFileOperationCallback callback,
5949 gpointer callback_data)
5950 {
5951 NautilusFileOperation *op;
5952 GFile *location;
5953
5954 op = nautilus_file_operation_new (file, callback, callback_data);
5955
5956 location = nautilus_file_get_location (file);
5957 g_file_set_attributes_async (location,
5958 attributes,
5959 0,
5960 G_PRIORITY_DEFAULT,
5961 op->cancellable,
5962 set_attributes_callback,
5963 op);
5964 g_object_unref (location);
5965 }
5966
5967 void
nautilus_file_set_search_relevance(NautilusFile * file,gdouble relevance)5968 nautilus_file_set_search_relevance (NautilusFile *file,
5969 gdouble relevance)
5970 {
5971 file->details->search_relevance = relevance;
5972 }
5973
5974 void
nautilus_file_set_search_fts_snippet(NautilusFile * file,const gchar * fts_snippet)5975 nautilus_file_set_search_fts_snippet (NautilusFile *file,
5976 const gchar *fts_snippet)
5977 {
5978 file->details->fts_snippet = g_strdup (fts_snippet);
5979 }
5980
5981 const gchar *
nautilus_file_get_search_fts_snippet(NautilusFile * file)5982 nautilus_file_get_search_fts_snippet (NautilusFile *file)
5983 {
5984 return file->details->fts_snippet;
5985 }
5986
5987 /**
5988 * nautilus_file_can_get_permissions:
5989 *
5990 * Check whether the permissions for a file are determinable.
5991 * This might not be the case for files on non-UNIX file systems.
5992 *
5993 * @file: The file in question.
5994 *
5995 * Return value: TRUE if the permissions are valid.
5996 */
5997 gboolean
nautilus_file_can_get_permissions(NautilusFile * file)5998 nautilus_file_can_get_permissions (NautilusFile *file)
5999 {
6000 return file->details->has_permissions;
6001 }
6002
6003 /**
6004 * nautilus_file_can_set_permissions:
6005 *
6006 * Check whether the current user is allowed to change
6007 * the permissions of a file.
6008 *
6009 * @file: The file in question.
6010 *
6011 * Return value: TRUE if the current user can change the
6012 * permissions of @file, FALSE otherwise. It's always possible
6013 * that when you actually try to do it, you will fail.
6014 */
6015 gboolean
nautilus_file_can_set_permissions(NautilusFile * file)6016 nautilus_file_can_set_permissions (NautilusFile *file)
6017 {
6018 g_autoptr (GFile) location = NULL;
6019 uid_t user_id;
6020
6021 location = nautilus_file_get_location (file);
6022
6023 if (file->details->uid != -1 &&
6024 g_file_is_native (location))
6025 {
6026 /* Check the user. */
6027 user_id = geteuid ();
6028
6029 /* Owner is allowed to set permissions. */
6030 if (user_id == (uid_t) file->details->uid)
6031 {
6032 return TRUE;
6033 }
6034
6035 /* Root is also allowed to set permissions. */
6036 if (user_id == 0)
6037 {
6038 return TRUE;
6039 }
6040
6041 /* Nobody else is allowed. */
6042 return FALSE;
6043 }
6044
6045 /* pretend to have full chmod rights when no info is available, relevant when
6046 * the FS can't provide ownership info, for instance for FTP */
6047 return TRUE;
6048 }
6049
6050 guint
nautilus_file_get_permissions(NautilusFile * file)6051 nautilus_file_get_permissions (NautilusFile *file)
6052 {
6053 g_return_val_if_fail (nautilus_file_can_get_permissions (file), 0);
6054
6055 return file->details->permissions;
6056 }
6057
6058 /**
6059 * nautilus_file_set_permissions:
6060 *
6061 * Change a file's permissions. This should only be called if
6062 * nautilus_file_can_set_permissions returned TRUE.
6063 *
6064 * @file: NautilusFile representing the file in question.
6065 * @new_permissions: New permissions value. This is the whole
6066 * set of permissions, not a delta.
6067 **/
6068 void
nautilus_file_set_permissions(NautilusFile * file,guint32 new_permissions,NautilusFileOperationCallback callback,gpointer callback_data)6069 nautilus_file_set_permissions (NautilusFile *file,
6070 guint32 new_permissions,
6071 NautilusFileOperationCallback callback,
6072 gpointer callback_data)
6073 {
6074 GFileInfo *info;
6075 GError *error;
6076
6077 if (!nautilus_file_can_set_permissions (file))
6078 {
6079 /* Claim that something changed even if the permission change failed.
6080 * This makes it easier for some clients who see the "reverting"
6081 * to the old permissions as "changing back".
6082 */
6083 nautilus_file_changed (file);
6084 error = g_error_new (G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
6085 _("Not allowed to set permissions"));
6086 (*callback)(file, NULL, error, callback_data);
6087 g_error_free (error);
6088 return;
6089 }
6090
6091 /* Test the permissions-haven't-changed case explicitly
6092 * because we don't want to send the file-changed signal if
6093 * nothing changed.
6094 */
6095 if (new_permissions == file->details->permissions)
6096 {
6097 (*callback)(file, NULL, NULL, callback_data);
6098 return;
6099 }
6100
6101 if (!nautilus_file_undo_manager_is_operating ())
6102 {
6103 NautilusFileUndoInfo *undo_info;
6104
6105 undo_info = nautilus_file_undo_info_permissions_new (nautilus_file_get_location (file),
6106 file->details->permissions,
6107 new_permissions);
6108 nautilus_file_undo_manager_set_action (undo_info);
6109 }
6110
6111 info = g_file_info_new ();
6112 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE, new_permissions);
6113 nautilus_file_set_attributes (file, info, callback, callback_data);
6114
6115 g_object_unref (info);
6116 }
6117
6118 /**
6119 * nautilus_file_can_get_selinux_context:
6120 *
6121 * Check whether the selinux context for a file are determinable.
6122 * This might not be the case for files on non-UNIX file systems,
6123 * files without a context or systems that don't support selinux.
6124 *
6125 * @file: The file in question.
6126 *
6127 * Return value: TRUE if the permissions are valid.
6128 */
6129 gboolean
nautilus_file_can_get_selinux_context(NautilusFile * file)6130 nautilus_file_can_get_selinux_context (NautilusFile *file)
6131 {
6132 return file->details->selinux_context != NULL;
6133 }
6134
6135
6136 /**
6137 * nautilus_file_get_selinux_context:
6138 *
6139 * Get a user-displayable string representing a file's selinux
6140 * context
6141 * @file: NautilusFile representing the file in question.
6142 *
6143 * Returns: Newly allocated string ready to display to the user.
6144 *
6145 **/
6146 char *
nautilus_file_get_selinux_context(NautilusFile * file)6147 nautilus_file_get_selinux_context (NautilusFile *file)
6148 {
6149 char *translated;
6150 char *raw;
6151
6152 g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
6153
6154 if (!nautilus_file_can_get_selinux_context (file))
6155 {
6156 return NULL;
6157 }
6158
6159 raw = file->details->selinux_context;
6160
6161 #ifdef HAVE_SELINUX
6162 if (selinux_raw_to_trans_context (raw, &translated) == 0)
6163 {
6164 char *tmp;
6165 tmp = g_strdup (translated);
6166 freecon (translated);
6167 translated = tmp;
6168 }
6169 else
6170 #endif
6171 {
6172 translated = g_strdup (raw);
6173 }
6174
6175 return translated;
6176 }
6177
6178 static char *
get_real_name(const char * name,const char * gecos)6179 get_real_name (const char *name,
6180 const char *gecos)
6181 {
6182 char *locale_string, *part_before_comma, *capitalized_login_name, *real_name;
6183
6184 if (gecos == NULL)
6185 {
6186 return NULL;
6187 }
6188
6189 locale_string = eel_str_strip_substring_and_after (gecos, ",");
6190 if (!g_utf8_validate (locale_string, -1, NULL))
6191 {
6192 part_before_comma = g_locale_to_utf8 (locale_string, -1, NULL, NULL, NULL);
6193 g_free (locale_string);
6194 }
6195 else
6196 {
6197 part_before_comma = locale_string;
6198 }
6199
6200 if (!g_utf8_validate (name, -1, NULL))
6201 {
6202 locale_string = g_locale_to_utf8 (name, -1, NULL, NULL, NULL);
6203 }
6204 else
6205 {
6206 locale_string = g_strdup (name);
6207 }
6208
6209 capitalized_login_name = eel_str_capitalize (locale_string);
6210 g_free (locale_string);
6211
6212 if (capitalized_login_name == NULL)
6213 {
6214 real_name = part_before_comma;
6215 }
6216 else
6217 {
6218 real_name = eel_str_replace_substring
6219 (part_before_comma, "&", capitalized_login_name);
6220 g_free (part_before_comma);
6221 }
6222
6223
6224 if (g_strcmp0 (real_name, NULL) == 0
6225 || g_strcmp0 (name, real_name) == 0
6226 || g_strcmp0 (capitalized_login_name, real_name) == 0)
6227 {
6228 g_free (real_name);
6229 real_name = NULL;
6230 }
6231
6232 g_free (capitalized_login_name);
6233
6234 return real_name;
6235 }
6236
6237 static gboolean
get_group_id_from_group_name(const char * group_name,uid_t * gid)6238 get_group_id_from_group_name (const char *group_name,
6239 uid_t *gid)
6240 {
6241 struct group *group;
6242
6243 g_assert (gid != NULL);
6244
6245 group = getgrnam (group_name);
6246
6247 if (group == NULL)
6248 {
6249 return FALSE;
6250 }
6251
6252 *gid = group->gr_gid;
6253
6254 return TRUE;
6255 }
6256
6257 static gboolean
get_ids_from_user_name(const char * user_name,uid_t * uid,uid_t * gid)6258 get_ids_from_user_name (const char *user_name,
6259 uid_t *uid,
6260 uid_t *gid)
6261 {
6262 struct passwd *password_info;
6263
6264 g_assert (uid != NULL || gid != NULL);
6265
6266 password_info = getpwnam (user_name);
6267
6268 if (password_info == NULL)
6269 {
6270 return FALSE;
6271 }
6272
6273 if (uid != NULL)
6274 {
6275 *uid = password_info->pw_uid;
6276 }
6277
6278 if (gid != NULL)
6279 {
6280 *gid = password_info->pw_gid;
6281 }
6282
6283 return TRUE;
6284 }
6285
6286 static gboolean
get_user_id_from_user_name(const char * user_name,uid_t * id)6287 get_user_id_from_user_name (const char *user_name,
6288 uid_t *id)
6289 {
6290 return get_ids_from_user_name (user_name, id, NULL);
6291 }
6292
6293 static gboolean
get_id_from_digit_string(const char * digit_string,uid_t * id)6294 get_id_from_digit_string (const char *digit_string,
6295 uid_t *id)
6296 {
6297 long scanned_id;
6298 char c;
6299
6300 g_assert (id != NULL);
6301
6302 /* Only accept string if it has one integer with nothing
6303 * afterwards.
6304 */
6305 if (sscanf (digit_string, "%ld%c", &scanned_id, &c) != 1)
6306 {
6307 return FALSE;
6308 }
6309 *id = scanned_id;
6310 return TRUE;
6311 }
6312
6313 /**
6314 * nautilus_file_can_get_owner:
6315 *
6316 * Check whether the owner a file is determinable.
6317 * This might not be the case for files on non-UNIX file systems.
6318 *
6319 * @file: The file in question.
6320 *
6321 * Return value: TRUE if the owner is valid.
6322 */
6323 gboolean
nautilus_file_can_get_owner(NautilusFile * file)6324 nautilus_file_can_get_owner (NautilusFile *file)
6325 {
6326 /* Before we have info on a file, the owner is unknown. */
6327 return file->details->uid != -1;
6328 }
6329
6330 /**
6331 * nautilus_file_get_owner_name:
6332 *
6333 * Get the user name of the file's owner. If the owner has no
6334 * name, returns the userid as a string. The caller is responsible
6335 * for g_free-ing this string.
6336 *
6337 * @file: The file in question.
6338 *
6339 * Return value: A newly-allocated string.
6340 */
6341 char *
nautilus_file_get_owner_name(NautilusFile * file)6342 nautilus_file_get_owner_name (NautilusFile *file)
6343 {
6344 return nautilus_file_get_owner_as_string (file, FALSE);
6345 }
6346
6347 /**
6348 * nautilus_file_can_set_owner:
6349 *
6350 * Check whether the current user is allowed to change
6351 * the owner of a file.
6352 *
6353 * @file: The file in question.
6354 *
6355 * Return value: TRUE if the current user can change the
6356 * owner of @file, FALSE otherwise. It's always possible
6357 * that when you actually try to do it, you will fail.
6358 */
6359 gboolean
nautilus_file_can_set_owner(NautilusFile * file)6360 nautilus_file_can_set_owner (NautilusFile *file)
6361 {
6362 /* Not allowed to set the owner if we can't
6363 * even read it. This can happen on non-UNIX file
6364 * systems.
6365 */
6366 if (!nautilus_file_can_get_owner (file))
6367 {
6368 return FALSE;
6369 }
6370
6371 /* Owner can be changed only in admin backend or by root */
6372 return nautilus_file_is_in_admin (file) || geteuid () == 0;
6373 }
6374
6375 /**
6376 * nautilus_file_set_owner:
6377 *
6378 * Set the owner of a file. This will only have any effect if
6379 * nautilus_file_can_set_owner returns TRUE.
6380 *
6381 * @file: The file in question.
6382 * @user_name_or_id: The user name to set the owner to.
6383 * If the string does not match any user name, and the
6384 * string is an integer, the owner will be set to the
6385 * userid represented by that integer.
6386 * @callback: Function called when asynch owner change succeeds or fails.
6387 * @callback_data: Parameter passed back with callback function.
6388 */
6389 void
nautilus_file_set_owner(NautilusFile * file,const char * user_name_or_id,NautilusFileOperationCallback callback,gpointer callback_data)6390 nautilus_file_set_owner (NautilusFile *file,
6391 const char *user_name_or_id,
6392 NautilusFileOperationCallback callback,
6393 gpointer callback_data)
6394 {
6395 GError *error;
6396 GFileInfo *info;
6397 uid_t new_id;
6398
6399 if (!nautilus_file_can_set_owner (file))
6400 {
6401 /* Claim that something changed even if the permission
6402 * change failed. This makes it easier for some
6403 * clients who see the "reverting" to the old owner as
6404 * "changing back".
6405 */
6406 nautilus_file_changed (file);
6407 error = g_error_new (G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
6408 _("Not allowed to set owner"));
6409 (*callback)(file, NULL, error, callback_data);
6410 g_error_free (error);
6411 return;
6412 }
6413
6414 /* If no match treating user_name_or_id as name, try treating
6415 * it as id.
6416 */
6417 if (!get_user_id_from_user_name (user_name_or_id, &new_id)
6418 && !get_id_from_digit_string (user_name_or_id, &new_id))
6419 {
6420 /* Claim that something changed even if the permission
6421 * change failed. This makes it easier for some
6422 * clients who see the "reverting" to the old owner as
6423 * "changing back".
6424 */
6425 nautilus_file_changed (file);
6426 error = g_error_new (G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
6427 _("Specified owner “%s” doesn’t exist"), user_name_or_id);
6428 (*callback)(file, NULL, error, callback_data);
6429 g_error_free (error);
6430 return;
6431 }
6432
6433 /* Test the owner-hasn't-changed case explicitly because we
6434 * don't want to send the file-changed signal if nothing
6435 * changed.
6436 */
6437 if (new_id == (uid_t) file->details->uid)
6438 {
6439 (*callback)(file, NULL, NULL, callback_data);
6440 return;
6441 }
6442
6443 if (!nautilus_file_undo_manager_is_operating ())
6444 {
6445 NautilusFileUndoInfo *undo_info;
6446 char *current_owner;
6447
6448 current_owner = nautilus_file_get_owner_as_string (file, FALSE);
6449
6450 undo_info = nautilus_file_undo_info_ownership_new (NAUTILUS_FILE_UNDO_OP_CHANGE_OWNER,
6451 nautilus_file_get_location (file),
6452 current_owner,
6453 user_name_or_id);
6454 nautilus_file_undo_manager_set_action (undo_info);
6455
6456 g_free (current_owner);
6457 }
6458
6459 info = g_file_info_new ();
6460 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID, new_id);
6461 nautilus_file_set_attributes (file, info, callback, callback_data);
6462 g_object_unref (info);
6463 }
6464
6465 /**
6466 * nautilus_get_user_names:
6467 *
6468 * Get a list of user names. For users with a different associated
6469 * "real name", the real name follows the standard user name, separated
6470 * by a carriage return. The caller is responsible for freeing this list
6471 * and its contents.
6472 */
6473 GList *
nautilus_get_user_names(void)6474 nautilus_get_user_names (void)
6475 {
6476 GList *list;
6477 char *real_name, *name;
6478 struct passwd *user;
6479
6480 list = NULL;
6481
6482 setpwent ();
6483
6484 while ((user = getpwent ()) != NULL)
6485 {
6486 real_name = get_real_name (user->pw_name, user->pw_gecos);
6487 if (real_name != NULL)
6488 {
6489 name = g_strconcat (user->pw_name, "\n", real_name, NULL);
6490 }
6491 else
6492 {
6493 name = g_strdup (user->pw_name);
6494 }
6495 g_free (real_name);
6496 list = g_list_prepend (list, name);
6497 }
6498
6499 endpwent ();
6500
6501 return g_list_sort (list, (GCompareFunc) g_utf8_collate);
6502 }
6503
6504 /**
6505 * nautilus_file_can_get_group:
6506 *
6507 * Check whether the group a file is determinable.
6508 * This might not be the case for files on non-UNIX file systems.
6509 *
6510 * @file: The file in question.
6511 *
6512 * Return value: TRUE if the group is valid.
6513 */
6514 gboolean
nautilus_file_can_get_group(NautilusFile * file)6515 nautilus_file_can_get_group (NautilusFile *file)
6516 {
6517 /* Before we have info on a file, the group is unknown. */
6518 return file->details->gid != -1;
6519 }
6520
6521 /**
6522 * nautilus_file_get_group_name:
6523 *
6524 * Get the name of the file's group. If the group has no
6525 * name, returns the groupid as a string. The caller is responsible
6526 * for g_free-ing this string.
6527 *
6528 * @file: The file in question.
6529 *
6530 * Return value: A newly-allocated string.
6531 **/
6532 char *
nautilus_file_get_group_name(NautilusFile * file)6533 nautilus_file_get_group_name (NautilusFile *file)
6534 {
6535 return g_strdup (file->details->group);
6536 }
6537
6538 /**
6539 * nautilus_file_can_set_group:
6540 *
6541 * Check whether the current user is allowed to change
6542 * the group of a file.
6543 *
6544 * @file: The file in question.
6545 *
6546 * Return value: TRUE if the current user can change the
6547 * group of @file, FALSE otherwise. It's always possible
6548 * that when you actually try to do it, you will fail.
6549 */
6550 gboolean
nautilus_file_can_set_group(NautilusFile * file)6551 nautilus_file_can_set_group (NautilusFile *file)
6552 {
6553 uid_t user_id;
6554
6555 /* Not allowed to set the permissions if we can't
6556 * even read them. This can happen on non-UNIX file
6557 * systems.
6558 */
6559 if (!nautilus_file_can_get_group (file))
6560 {
6561 return FALSE;
6562 }
6563
6564 /* Check the user. */
6565 user_id = geteuid ();
6566
6567 /* Owner is allowed to set group (with restrictions). */
6568 if (user_id == (uid_t) file->details->uid)
6569 {
6570 return TRUE;
6571 }
6572
6573 /* Root is also allowed to set group. */
6574 if (user_id == 0)
6575 {
6576 return TRUE;
6577 }
6578
6579 /* Nobody else is allowed. */
6580 return FALSE;
6581 }
6582
6583 /* Get a list of group names, filtered to only the ones
6584 * that contain the given username. If the username is
6585 * NULL, returns a list of all group names.
6586 */
6587 static GList *
nautilus_get_group_names_for_user(void)6588 nautilus_get_group_names_for_user (void)
6589 {
6590 GList *list;
6591 struct group *group;
6592 int count, i;
6593 gid_t gid_list[NGROUPS_MAX + 1];
6594
6595
6596 list = NULL;
6597
6598 count = getgroups (NGROUPS_MAX + 1, gid_list);
6599 for (i = 0; i < count; i++)
6600 {
6601 group = getgrgid (gid_list[i]);
6602 if (group == NULL)
6603 {
6604 break;
6605 }
6606
6607 list = g_list_prepend (list, g_strdup (group->gr_name));
6608 }
6609
6610 return g_list_sort (list, (GCompareFunc) g_utf8_collate);
6611 }
6612
6613 /**
6614 * nautilus_get_group_names:
6615 *
6616 * Get a list of all group names.
6617 */
6618 GList *
nautilus_get_all_group_names(void)6619 nautilus_get_all_group_names (void)
6620 {
6621 GList *list;
6622 struct group *group;
6623
6624 list = NULL;
6625
6626 setgrent ();
6627
6628 while ((group = getgrent ()) != NULL)
6629 {
6630 list = g_list_prepend (list, g_strdup (group->gr_name));
6631 }
6632
6633 endgrent ();
6634
6635 return g_list_sort (list, (GCompareFunc) g_utf8_collate);
6636 }
6637
6638 /**
6639 * nautilus_file_get_settable_group_names:
6640 *
6641 * Get a list of all group names that the current user
6642 * can set the group of a specific file to.
6643 *
6644 * @file: The NautilusFile in question.
6645 */
6646 GList *
nautilus_file_get_settable_group_names(NautilusFile * file)6647 nautilus_file_get_settable_group_names (NautilusFile *file)
6648 {
6649 uid_t user_id;
6650 GList *result;
6651
6652 if (!nautilus_file_can_set_group (file))
6653 {
6654 return NULL;
6655 }
6656
6657 /* Check the user. */
6658 user_id = geteuid ();
6659
6660 if (user_id == 0)
6661 {
6662 /* Root is allowed to set group to anything. */
6663 result = nautilus_get_all_group_names ();
6664 }
6665 else if (user_id == (uid_t) file->details->uid)
6666 {
6667 /* Owner is allowed to set group to any that owner is member of. */
6668 result = nautilus_get_group_names_for_user ();
6669 }
6670 else
6671 {
6672 g_warning ("unhandled case in nautilus_get_settable_group_names");
6673 result = NULL;
6674 }
6675
6676 return result;
6677 }
6678
6679 /**
6680 * nautilus_file_set_group:
6681 *
6682 * Set the group of a file. This will only have any effect if
6683 * nautilus_file_can_set_group returns TRUE.
6684 *
6685 * @file: The file in question.
6686 * @group_name_or_id: The group name to set the owner to.
6687 * If the string does not match any group name, and the
6688 * string is an integer, the group will be set to the
6689 * group id represented by that integer.
6690 * @callback: Function called when asynch group change succeeds or fails.
6691 * @callback_data: Parameter passed back with callback function.
6692 */
6693 void
nautilus_file_set_group(NautilusFile * file,const char * group_name_or_id,NautilusFileOperationCallback callback,gpointer callback_data)6694 nautilus_file_set_group (NautilusFile *file,
6695 const char *group_name_or_id,
6696 NautilusFileOperationCallback callback,
6697 gpointer callback_data)
6698 {
6699 GError *error;
6700 GFileInfo *info;
6701 uid_t new_id;
6702
6703 if (!nautilus_file_can_set_group (file))
6704 {
6705 /* Claim that something changed even if the group
6706 * change failed. This makes it easier for some
6707 * clients who see the "reverting" to the old group as
6708 * "changing back".
6709 */
6710 nautilus_file_changed (file);
6711 error = g_error_new (G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
6712 _("Not allowed to set group"));
6713 (*callback)(file, NULL, error, callback_data);
6714 g_error_free (error);
6715 return;
6716 }
6717
6718 /* If no match treating group_name_or_id as name, try treating
6719 * it as id.
6720 */
6721 if (!get_group_id_from_group_name (group_name_or_id, &new_id)
6722 && !get_id_from_digit_string (group_name_or_id, &new_id))
6723 {
6724 /* Claim that something changed even if the group
6725 * change failed. This makes it easier for some
6726 * clients who see the "reverting" to the old group as
6727 * "changing back".
6728 */
6729 nautilus_file_changed (file);
6730 error = g_error_new (G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
6731 _("Specified group “%s” doesn’t exist"), group_name_or_id);
6732 (*callback)(file, NULL, error, callback_data);
6733 g_error_free (error);
6734 return;
6735 }
6736
6737 if (new_id == (gid_t) file->details->gid)
6738 {
6739 (*callback)(file, NULL, NULL, callback_data);
6740 return;
6741 }
6742
6743 if (!nautilus_file_undo_manager_is_operating ())
6744 {
6745 NautilusFileUndoInfo *undo_info;
6746 char *current_group;
6747
6748 current_group = nautilus_file_get_group_name (file);
6749 undo_info = nautilus_file_undo_info_ownership_new (NAUTILUS_FILE_UNDO_OP_CHANGE_GROUP,
6750 nautilus_file_get_location (file),
6751 current_group,
6752 group_name_or_id);
6753 nautilus_file_undo_manager_set_action (undo_info);
6754
6755 g_free (current_group);
6756 }
6757
6758 info = g_file_info_new ();
6759 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID, new_id);
6760 nautilus_file_set_attributes (file, info, callback, callback_data);
6761 g_object_unref (info);
6762 }
6763
6764 /**
6765 * nautilus_file_get_octal_permissions_as_string:
6766 *
6767 * Get a user-displayable string representing a file's permissions
6768 * as an octal number. The caller
6769 * is responsible for g_free-ing this string.
6770 * @file: NautilusFile representing the file in question.
6771 *
6772 * Returns: Newly allocated string ready to display to the user.
6773 *
6774 **/
6775 static char *
nautilus_file_get_octal_permissions_as_string(NautilusFile * file)6776 nautilus_file_get_octal_permissions_as_string (NautilusFile *file)
6777 {
6778 guint32 permissions;
6779
6780 g_assert (NAUTILUS_IS_FILE (file));
6781
6782 if (!nautilus_file_can_get_permissions (file))
6783 {
6784 return NULL;
6785 }
6786
6787 permissions = file->details->permissions;
6788 return g_strdup_printf ("%03o", permissions);
6789 }
6790
6791 /**
6792 * nautilus_file_get_permissions_as_string:
6793 *
6794 * Get a user-displayable string representing a file's permissions. The caller
6795 * is responsible for g_free-ing this string.
6796 * @file: NautilusFile representing the file in question.
6797 *
6798 * Returns: Newly allocated string ready to display to the user.
6799 *
6800 **/
6801 static char *
nautilus_file_get_permissions_as_string(NautilusFile * file)6802 nautilus_file_get_permissions_as_string (NautilusFile *file)
6803 {
6804 guint32 permissions;
6805 gboolean is_directory;
6806 gboolean is_link;
6807 gboolean suid, sgid, sticky;
6808
6809 if (!nautilus_file_can_get_permissions (file))
6810 {
6811 return NULL;
6812 }
6813
6814 g_assert (NAUTILUS_IS_FILE (file));
6815
6816 permissions = file->details->permissions;
6817 is_directory = nautilus_file_is_directory (file);
6818 is_link = nautilus_file_is_symbolic_link (file);
6819
6820 /* We use ls conventions for displaying these three obscure flags */
6821 suid = permissions & S_ISUID;
6822 sgid = permissions & S_ISGID;
6823 sticky = permissions & S_ISVTX;
6824
6825 return g_strdup_printf ("%c%c%c%c%c%c%c%c%c%c",
6826 is_link ? 'l' : is_directory ? 'd' : '-',
6827 permissions & S_IRUSR ? 'r' : '-',
6828 permissions & S_IWUSR ? 'w' : '-',
6829 permissions & S_IXUSR
6830 ? (suid ? 's' : 'x')
6831 : (suid ? 'S' : '-'),
6832 permissions & S_IRGRP ? 'r' : '-',
6833 permissions & S_IWGRP ? 'w' : '-',
6834 permissions & S_IXGRP
6835 ? (sgid ? 's' : 'x')
6836 : (sgid ? 'S' : '-'),
6837 permissions & S_IROTH ? 'r' : '-',
6838 permissions & S_IWOTH ? 'w' : '-',
6839 permissions & S_IXOTH
6840 ? (sticky ? 't' : 'x')
6841 : (sticky ? 'T' : '-'));
6842 }
6843
6844 /**
6845 * nautilus_file_get_owner_as_string:
6846 *
6847 * Get a user-displayable string representing a file's owner. The caller
6848 * is responsible for g_free-ing this string.
6849 * @file: NautilusFile representing the file in question.
6850 * @include_real_name: Whether or not to append the real name (if any)
6851 * for this user after the user name.
6852 *
6853 * Returns: Newly allocated string ready to display to the user.
6854 *
6855 **/
6856 static char *
nautilus_file_get_owner_as_string(NautilusFile * file,gboolean include_real_name)6857 nautilus_file_get_owner_as_string (NautilusFile *file,
6858 gboolean include_real_name)
6859 {
6860 char *user_name;
6861
6862 /* Before we have info on a file, the owner is unknown. */
6863 if (file->details->owner == NULL &&
6864 file->details->owner_real == NULL)
6865 {
6866 return NULL;
6867 }
6868
6869 if (include_real_name &&
6870 file->details->uid == getuid ())
6871 {
6872 /* Translators: "Me" is used to indicate the file is owned by me (the current user) */
6873 user_name = g_strdup (_("Me"));
6874 }
6875 else if (file->details->owner_real == NULL)
6876 {
6877 user_name = g_strdup (file->details->owner);
6878 }
6879 else if (file->details->owner == NULL)
6880 {
6881 user_name = g_strdup (file->details->owner_real);
6882 }
6883 else if (include_real_name &&
6884 strcmp (file->details->owner, file->details->owner_real) != 0)
6885 {
6886 user_name = g_strdup (file->details->owner_real);
6887 }
6888 else
6889 {
6890 user_name = g_strdup (file->details->owner);
6891 }
6892
6893 return user_name;
6894 }
6895
6896 static char *
format_item_count_for_display(guint item_count,gboolean includes_directories,gboolean includes_files)6897 format_item_count_for_display (guint item_count,
6898 gboolean includes_directories,
6899 gboolean includes_files)
6900 {
6901 g_assert (includes_directories || includes_files);
6902
6903 return g_strdup_printf (includes_directories
6904 ? (includes_files
6905 ? ngettext ("%'u item", "%'u items", item_count)
6906 : ngettext ("%'u folder", "%'u folders", item_count))
6907 : ngettext ("%'u file", "%'u files", item_count), item_count);
6908 }
6909
6910 /**
6911 * nautilus_file_get_size_as_string:
6912 *
6913 * Get a user-displayable string representing a file size. The caller
6914 * is responsible for g_free-ing this string. The string is an item
6915 * count for directories.
6916 * @file: NautilusFile representing the file in question.
6917 *
6918 * Returns: Newly allocated string ready to display to the user.
6919 *
6920 **/
6921 static char *
nautilus_file_get_size_as_string(NautilusFile * file)6922 nautilus_file_get_size_as_string (NautilusFile *file)
6923 {
6924 guint item_count;
6925 gboolean count_unreadable;
6926
6927 if (file == NULL)
6928 {
6929 return NULL;
6930 }
6931
6932 g_assert (NAUTILUS_IS_FILE (file));
6933
6934 if (nautilus_file_is_directory (file))
6935 {
6936 if (!nautilus_file_get_directory_item_count (file, &item_count, &count_unreadable))
6937 {
6938 return NULL;
6939 }
6940 return format_item_count_for_display (item_count, TRUE, TRUE);
6941 }
6942
6943 if (file->details->size == -1)
6944 {
6945 return NULL;
6946 }
6947 return g_format_size (file->details->size);
6948 }
6949
6950 /**
6951 * nautilus_file_get_size_as_string_with_real_size:
6952 *
6953 * Get a user-displayable string representing a file size. The caller
6954 * is responsible for g_free-ing this string. The string is an item
6955 * count for directories.
6956 * This function adds the real size in the string.
6957 * @file: NautilusFile representing the file in question.
6958 *
6959 * Returns: Newly allocated string ready to display to the user.
6960 *
6961 **/
6962 static char *
nautilus_file_get_size_as_string_with_real_size(NautilusFile * file)6963 nautilus_file_get_size_as_string_with_real_size (NautilusFile *file)
6964 {
6965 guint item_count;
6966 gboolean count_unreadable;
6967
6968 if (file == NULL)
6969 {
6970 return NULL;
6971 }
6972
6973 g_assert (NAUTILUS_IS_FILE (file));
6974
6975 if (nautilus_file_is_directory (file))
6976 {
6977 if (!nautilus_file_get_directory_item_count (file, &item_count, &count_unreadable))
6978 {
6979 return NULL;
6980 }
6981 return format_item_count_for_display (item_count, TRUE, TRUE);
6982 }
6983
6984 if (file->details->size == -1)
6985 {
6986 return NULL;
6987 }
6988
6989 return g_format_size_full (file->details->size, G_FORMAT_SIZE_LONG_FORMAT);
6990 }
6991
6992
6993 static char *
nautilus_file_get_deep_count_as_string_internal(NautilusFile * file,gboolean report_size,gboolean report_directory_count,gboolean report_file_count)6994 nautilus_file_get_deep_count_as_string_internal (NautilusFile *file,
6995 gboolean report_size,
6996 gboolean report_directory_count,
6997 gboolean report_file_count)
6998 {
6999 NautilusRequestStatus status;
7000 guint directory_count;
7001 guint file_count;
7002 guint unreadable_count;
7003 guint total_count;
7004 goffset total_size;
7005
7006 /* Must ask for size or some kind of count, but not both. */
7007 g_assert (!report_size || (!report_directory_count && !report_file_count));
7008 g_assert (report_size || report_directory_count || report_file_count);
7009
7010 if (file == NULL)
7011 {
7012 return NULL;
7013 }
7014
7015 g_assert (NAUTILUS_IS_FILE (file));
7016 g_assert (nautilus_file_is_directory (file));
7017
7018 status = nautilus_file_get_deep_counts
7019 (file, &directory_count, &file_count, &unreadable_count, &total_size, FALSE);
7020
7021 /* Check whether any info is available. */
7022 if (status == NAUTILUS_REQUEST_NOT_STARTED)
7023 {
7024 return NULL;
7025 }
7026
7027 total_count = file_count + directory_count;
7028
7029 if (total_count == 0)
7030 {
7031 switch (status)
7032 {
7033 case NAUTILUS_REQUEST_IN_PROGRESS:
7034 {
7035 /* Don't return confident "zero" until we're finished looking,
7036 * because of next case.
7037 */
7038 return NULL;
7039 }
7040
7041 case NAUTILUS_REQUEST_DONE:
7042 {
7043 /* Don't return "zero" if we there were contents but we couldn't read them. */
7044 if (unreadable_count != 0)
7045 {
7046 return NULL;
7047 }
7048 }
7049
7050 default:
7051 {}
7052 break;
7053 }
7054 }
7055
7056 /* Note that we don't distinguish the "everything was readable" case
7057 * from the "some things but not everything was readable" case here.
7058 * Callers can distinguish them using nautilus_file_get_deep_counts
7059 * directly if desired.
7060 */
7061 if (report_size)
7062 {
7063 return g_format_size (total_size);
7064 }
7065
7066 return format_item_count_for_display (report_directory_count
7067 ? (report_file_count ? total_count : directory_count)
7068 : file_count,
7069 report_directory_count, report_file_count);
7070 }
7071
7072 /**
7073 * nautilus_file_get_deep_size_as_string:
7074 *
7075 * Get a user-displayable string representing the size of all contained
7076 * items (only makes sense for directories). The caller
7077 * is responsible for g_free-ing this string.
7078 * @file: NautilusFile representing the file in question.
7079 *
7080 * Returns: Newly allocated string ready to display to the user.
7081 *
7082 **/
7083 static char *
nautilus_file_get_deep_size_as_string(NautilusFile * file)7084 nautilus_file_get_deep_size_as_string (NautilusFile *file)
7085 {
7086 return nautilus_file_get_deep_count_as_string_internal (file, TRUE, FALSE, FALSE);
7087 }
7088
7089 /**
7090 * nautilus_file_get_deep_total_count_as_string:
7091 *
7092 * Get a user-displayable string representing the count of all contained
7093 * items (only makes sense for directories). The caller
7094 * is responsible for g_free-ing this string.
7095 * @file: NautilusFile representing the file in question.
7096 *
7097 * Returns: Newly allocated string ready to display to the user.
7098 *
7099 **/
7100 static char *
nautilus_file_get_deep_total_count_as_string(NautilusFile * file)7101 nautilus_file_get_deep_total_count_as_string (NautilusFile *file)
7102 {
7103 return nautilus_file_get_deep_count_as_string_internal (file, FALSE, TRUE, TRUE);
7104 }
7105
7106 /**
7107 * nautilus_file_get_deep_file_count_as_string:
7108 *
7109 * Get a user-displayable string representing the count of all contained
7110 * items, not including directories. It only makes sense to call this
7111 * function on a directory. The caller
7112 * is responsible for g_free-ing this string.
7113 * @file: NautilusFile representing the file in question.
7114 *
7115 * Returns: Newly allocated string ready to display to the user.
7116 *
7117 **/
7118 static char *
nautilus_file_get_deep_file_count_as_string(NautilusFile * file)7119 nautilus_file_get_deep_file_count_as_string (NautilusFile *file)
7120 {
7121 return nautilus_file_get_deep_count_as_string_internal (file, FALSE, FALSE, TRUE);
7122 }
7123
7124 /**
7125 * nautilus_file_get_deep_directory_count_as_string:
7126 *
7127 * Get a user-displayable string representing the count of all contained
7128 * directories. It only makes sense to call this
7129 * function on a directory. The caller
7130 * is responsible for g_free-ing this string.
7131 * @file: NautilusFile representing the file in question.
7132 *
7133 * Returns: Newly allocated string ready to display to the user.
7134 *
7135 **/
7136 static char *
nautilus_file_get_deep_directory_count_as_string(NautilusFile * file)7137 nautilus_file_get_deep_directory_count_as_string (NautilusFile *file)
7138 {
7139 return nautilus_file_get_deep_count_as_string_internal (file, FALSE, TRUE, FALSE);
7140 }
7141
7142 /**
7143 * nautilus_file_get_string_attribute:
7144 *
7145 * Get a user-displayable string from a named attribute. Use g_free to
7146 * free this string. If the value is unknown, returns NULL. You can call
7147 * nautilus_file_get_string_attribute_with_default if you want a non-NULL
7148 * default.
7149 *
7150 * @file: NautilusFile representing the file in question.
7151 * @attribute_name: The name of the desired attribute. The currently supported
7152 * set includes "name", "type", "detailed_type", "mime_type", "size", "deep_size", "deep_directory_count",
7153 * "deep_file_count", "deep_total_count", "date_modified", "date_accessed", "date_created",
7154 * "date_modified_full", "date_accessed_full", "date_created_full",
7155 * "owner", "group", "permissions", "octal_permissions", "uri", "where",
7156 * "link_target", "volume", "free_space", "selinux_context", "trashed_on", "trashed_on_full", "trashed_orig_path",
7157 * "recency"
7158 *
7159 * Returns: Newly allocated string ready to display to the user, or NULL
7160 * if the value is unknown or @attribute_name is not supported.
7161 *
7162 **/
7163 char *
nautilus_file_get_string_attribute_q(NautilusFile * file,GQuark attribute_q)7164 nautilus_file_get_string_attribute_q (NautilusFile *file,
7165 GQuark attribute_q)
7166 {
7167 char *extension_attribute;
7168
7169 if (attribute_q == attribute_name_q)
7170 {
7171 return nautilus_file_get_display_name (file);
7172 }
7173 if (attribute_q == attribute_type_q)
7174 {
7175 return nautilus_file_get_type_as_string (file);
7176 }
7177 if (attribute_q == attribute_detailed_type_q)
7178 {
7179 return nautilus_file_get_detailed_type_as_string (file);
7180 }
7181 if (attribute_q == attribute_mime_type_q)
7182 {
7183 return nautilus_file_get_mime_type (file);
7184 }
7185 if (attribute_q == attribute_size_q)
7186 {
7187 return nautilus_file_get_size_as_string (file);
7188 }
7189 if (attribute_q == attribute_size_detail_q)
7190 {
7191 return nautilus_file_get_size_as_string_with_real_size (file);
7192 }
7193 if (attribute_q == attribute_deep_size_q)
7194 {
7195 return nautilus_file_get_deep_size_as_string (file);
7196 }
7197 if (attribute_q == attribute_deep_file_count_q)
7198 {
7199 return nautilus_file_get_deep_file_count_as_string (file);
7200 }
7201 if (attribute_q == attribute_deep_directory_count_q)
7202 {
7203 return nautilus_file_get_deep_directory_count_as_string (file);
7204 }
7205 if (attribute_q == attribute_deep_total_count_q)
7206 {
7207 return nautilus_file_get_deep_total_count_as_string (file);
7208 }
7209 if (attribute_q == attribute_trash_orig_path_q)
7210 {
7211 return nautilus_file_get_trash_original_file_parent_as_string (file);
7212 }
7213 if (attribute_q == attribute_date_modified_q)
7214 {
7215 return nautilus_file_get_date_as_string (file,
7216 NAUTILUS_DATE_TYPE_MODIFIED,
7217 NAUTILUS_DATE_FORMAT_REGULAR);
7218 }
7219 if (attribute_q == attribute_date_modified_full_q)
7220 {
7221 return nautilus_file_get_date_as_string (file,
7222 NAUTILUS_DATE_TYPE_MODIFIED,
7223 NAUTILUS_DATE_FORMAT_FULL);
7224 }
7225 if (attribute_q == attribute_date_modified_with_time_q)
7226 {
7227 return nautilus_file_get_date_as_string (file,
7228 NAUTILUS_DATE_TYPE_MODIFIED,
7229 NAUTILUS_DATE_FORMAT_REGULAR_WITH_TIME);
7230 }
7231 if (attribute_q == attribute_date_accessed_q)
7232 {
7233 return nautilus_file_get_date_as_string (file,
7234 NAUTILUS_DATE_TYPE_ACCESSED,
7235 NAUTILUS_DATE_FORMAT_REGULAR);
7236 }
7237 if (attribute_q == attribute_date_accessed_full_q)
7238 {
7239 return nautilus_file_get_date_as_string (file,
7240 NAUTILUS_DATE_TYPE_ACCESSED,
7241 NAUTILUS_DATE_FORMAT_FULL);
7242 }
7243 if (attribute_q == attribute_date_created_q)
7244 {
7245 return nautilus_file_get_date_as_string (file,
7246 NAUTILUS_DATE_TYPE_CREATED,
7247 NAUTILUS_DATE_FORMAT_REGULAR);
7248 }
7249 if (attribute_q == attribute_date_created_full_q)
7250 {
7251 return nautilus_file_get_date_as_string (file,
7252 NAUTILUS_DATE_TYPE_CREATED,
7253 NAUTILUS_DATE_FORMAT_FULL);
7254 }
7255 if (attribute_q == attribute_trashed_on_q)
7256 {
7257 return nautilus_file_get_date_as_string (file,
7258 NAUTILUS_DATE_TYPE_TRASHED,
7259 NAUTILUS_DATE_FORMAT_REGULAR);
7260 }
7261 if (attribute_q == attribute_trashed_on_full_q)
7262 {
7263 return nautilus_file_get_date_as_string (file,
7264 NAUTILUS_DATE_TYPE_TRASHED,
7265 NAUTILUS_DATE_FORMAT_FULL);
7266 }
7267 if (attribute_q == attribute_recency_q)
7268 {
7269 return nautilus_file_get_date_as_string (file,
7270 NAUTILUS_DATE_TYPE_RECENCY,
7271 NAUTILUS_DATE_FORMAT_REGULAR);
7272 }
7273 if (attribute_q == attribute_permissions_q)
7274 {
7275 return nautilus_file_get_permissions_as_string (file);
7276 }
7277 if (attribute_q == attribute_selinux_context_q)
7278 {
7279 return nautilus_file_get_selinux_context (file);
7280 }
7281 if (attribute_q == attribute_octal_permissions_q)
7282 {
7283 return nautilus_file_get_octal_permissions_as_string (file);
7284 }
7285 if (attribute_q == attribute_owner_q)
7286 {
7287 return nautilus_file_get_owner_as_string (file, TRUE);
7288 }
7289 if (attribute_q == attribute_group_q)
7290 {
7291 return nautilus_file_get_group_name (file);
7292 }
7293 if (attribute_q == attribute_uri_q)
7294 {
7295 return nautilus_file_get_uri (file);
7296 }
7297 if (attribute_q == attribute_where_q)
7298 {
7299 return nautilus_file_get_where_string (file);
7300 }
7301 if (attribute_q == attribute_link_target_q)
7302 {
7303 return nautilus_file_get_symbolic_link_target_path (file);
7304 }
7305 if (attribute_q == attribute_volume_q)
7306 {
7307 return nautilus_file_get_volume_name (file);
7308 }
7309 if (attribute_q == attribute_free_space_q)
7310 {
7311 return nautilus_file_get_volume_free_space (file);
7312 }
7313
7314 extension_attribute = NULL;
7315
7316 if (file->details->pending_extension_attributes)
7317 {
7318 extension_attribute = g_hash_table_lookup (file->details->pending_extension_attributes,
7319 GINT_TO_POINTER (attribute_q));
7320 }
7321
7322 if (extension_attribute == NULL && file->details->extension_attributes)
7323 {
7324 extension_attribute = g_hash_table_lookup (file->details->extension_attributes,
7325 GINT_TO_POINTER (attribute_q));
7326 }
7327
7328 return g_strdup (extension_attribute);
7329 }
7330
7331 char *
nautilus_file_get_string_attribute(NautilusFile * file,const char * attribute_name)7332 nautilus_file_get_string_attribute (NautilusFile *file,
7333 const char *attribute_name)
7334 {
7335 g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
7336
7337 return nautilus_file_info_get_string_attribute (NAUTILUS_FILE_INFO (file), attribute_name);
7338 }
7339
7340
7341 /**
7342 * nautilus_file_get_string_attribute_with_default:
7343 *
7344 * Get a user-displayable string from a named attribute. Use g_free to
7345 * free this string. If the value is unknown, returns a string representing
7346 * the unknown value, which varies with attribute. You can call
7347 * nautilus_file_get_string_attribute if you want NULL instead of a default
7348 * result.
7349 *
7350 * @file: NautilusFile representing the file in question.
7351 * @attribute_name: The name of the desired attribute. See the description of
7352 * nautilus_file_get_string for the set of available attributes.
7353 *
7354 * Returns: Newly allocated string ready to display to the user, or a string
7355 * such as "unknown" if the value is unknown or @attribute_name is not supported.
7356 *
7357 **/
7358 char *
nautilus_file_get_string_attribute_with_default_q(NautilusFile * file,GQuark attribute_q)7359 nautilus_file_get_string_attribute_with_default_q (NautilusFile *file,
7360 GQuark attribute_q)
7361 {
7362 char *result;
7363 guint item_count;
7364 gboolean count_unreadable;
7365 NautilusRequestStatus status;
7366
7367 result = nautilus_file_get_string_attribute_q (file, attribute_q);
7368 if (result != NULL)
7369 {
7370 return result;
7371 }
7372
7373 /* Supply default values for the ones we know about. */
7374 /* FIXME bugzilla.gnome.org 40646:
7375 * Use hash table and switch statement or function pointers for speed?
7376 */
7377 if (attribute_q == attribute_size_q)
7378 {
7379 if (!nautilus_file_should_show_directory_item_count (file))
7380 {
7381 return g_strdup ("—");
7382 }
7383 count_unreadable = FALSE;
7384 if (nautilus_file_is_directory (file))
7385 {
7386 nautilus_file_get_directory_item_count (file, &item_count, &count_unreadable);
7387 }
7388 return g_strdup (count_unreadable ? "—" : "…");
7389 }
7390 if (attribute_q == attribute_deep_size_q)
7391 {
7392 status = nautilus_file_get_deep_counts (file, NULL, NULL, NULL, NULL, FALSE);
7393 if (status == NAUTILUS_REQUEST_DONE)
7394 {
7395 /* This means no contents at all were readable */
7396 return g_strdup (_("? bytes"));
7397 }
7398 return g_strdup ("…");
7399 }
7400 if (attribute_q == attribute_deep_file_count_q
7401 || attribute_q == attribute_deep_directory_count_q
7402 || attribute_q == attribute_deep_total_count_q)
7403 {
7404 status = nautilus_file_get_deep_counts (file, NULL, NULL, NULL, NULL, FALSE);
7405 if (status == NAUTILUS_REQUEST_DONE)
7406 {
7407 /* This means no contents at all were readable */
7408 return g_strdup (_("? items"));
7409 }
7410 return g_strdup ("…");
7411 }
7412 if (attribute_q == attribute_type_q
7413 || attribute_q == attribute_detailed_type_q
7414 || attribute_q == attribute_mime_type_q)
7415 {
7416 return g_strdup (_("Unknown"));
7417 }
7418 if (attribute_q == attribute_trashed_on_q)
7419 {
7420 /* If n/a */
7421 return g_strdup ("");
7422 }
7423 if (attribute_q == attribute_trash_orig_path_q)
7424 {
7425 /* If n/a */
7426 return g_strdup ("");
7427 }
7428 if (attribute_q == attribute_recency_q)
7429 {
7430 /* If n/a */
7431 return g_strdup ("");
7432 }
7433 if (attribute_q == attribute_starred_q)
7434 {
7435 /* If n/a */
7436 return g_strdup ("");
7437 }
7438 if (attribute_q == attribute_date_created_full_q)
7439 {
7440 /* If n/a */
7441 return g_strdup ("—");
7442 }
7443
7444 /* Fallback, use for both unknown attributes and attributes
7445 * for which we have no more appropriate default.
7446 */
7447 return g_strdup (_("unknown"));
7448 }
7449
7450 char *
nautilus_file_get_string_attribute_with_default(NautilusFile * file,const char * attribute_name)7451 nautilus_file_get_string_attribute_with_default (NautilusFile *file,
7452 const char *attribute_name)
7453 {
7454 return nautilus_file_get_string_attribute_with_default_q (file, g_quark_from_string (attribute_name));
7455 }
7456
7457 gboolean
nautilus_file_is_date_sort_attribute_q(GQuark attribute_q)7458 nautilus_file_is_date_sort_attribute_q (GQuark attribute_q)
7459 {
7460 if (attribute_q == attribute_modification_date_q ||
7461 attribute_q == attribute_date_modified_q ||
7462 attribute_q == attribute_date_modified_full_q ||
7463 attribute_q == attribute_date_modified_with_time_q ||
7464 attribute_q == attribute_accessed_date_q ||
7465 attribute_q == attribute_date_accessed_q ||
7466 attribute_q == attribute_date_accessed_full_q ||
7467 attribute_q == attribute_date_created_q ||
7468 attribute_q == attribute_date_created_full_q ||
7469 attribute_q == attribute_trashed_on_q ||
7470 attribute_q == attribute_trashed_on_full_q ||
7471 attribute_q == attribute_recency_q)
7472 {
7473 return TRUE;
7474 }
7475
7476 return FALSE;
7477 }
7478
7479 struct
7480 {
7481 const char *icon_name;
7482 const char *display_name;
7483 } mime_type_map[] =
7484 {
7485 { "application-x-executable", N_("Program") },
7486 { "audio-x-generic", N_("Audio") },
7487 { "font-x-generic", N_("Font") },
7488 { "image-x-generic", N_("Image") },
7489 { "package-x-generic", N_("Archive") },
7490 { "text-html", N_("Markup") },
7491 { "text-x-generic", N_("Text") },
7492 { "text-x-generic-template", N_("Text") },
7493 { "text-x-script", N_("Program") },
7494 { "video-x-generic", N_("Video") },
7495 { "x-office-address-book", N_("Contacts") },
7496 { "x-office-calendar", N_("Calendar") },
7497 { "x-office-document", N_("Document") },
7498 { "x-office-presentation", N_("Presentation") },
7499 { "x-office-spreadsheet", N_("Spreadsheet") },
7500 };
7501
7502 static char *
get_basic_type_for_mime_type(const char * mime_type)7503 get_basic_type_for_mime_type (const char *mime_type)
7504 {
7505 char *icon_name;
7506 char *basic_type = NULL;
7507
7508 icon_name = g_content_type_get_generic_icon_name (mime_type);
7509 if (icon_name != NULL)
7510 {
7511 int i;
7512
7513 for (i = 0; i < G_N_ELEMENTS (mime_type_map); i++)
7514 {
7515 if (strcmp (mime_type_map[i].icon_name, icon_name) == 0)
7516 {
7517 basic_type = g_strdup (gettext (mime_type_map[i].display_name));
7518 break;
7519 }
7520 }
7521 }
7522
7523 if (basic_type == NULL)
7524 {
7525 /* Refers to a file type which is known but not one of the basic types */
7526 basic_type = g_strdup (_("Other"));
7527 }
7528
7529 g_free (icon_name);
7530
7531 return basic_type;
7532 }
7533
7534 static char *
get_description(NautilusFile * file,gboolean detailed)7535 get_description (NautilusFile *file,
7536 gboolean detailed)
7537 {
7538 const char *mime_type;
7539
7540 g_assert (NAUTILUS_IS_FILE (file));
7541
7542 mime_type = file->details->mime_type;
7543 if (mime_type == NULL)
7544 {
7545 return NULL;
7546 }
7547
7548 if (g_content_type_is_unknown (mime_type))
7549 {
7550 if (nautilus_file_is_executable (file))
7551 {
7552 return g_strdup (_("Program"));
7553 }
7554 return g_strdup (_("Binary"));
7555 }
7556
7557 if (strcmp (mime_type, "inode/directory") == 0)
7558 {
7559 return g_strdup (_("Folder"));
7560 }
7561
7562 if (detailed)
7563 {
7564 char *description;
7565
7566 description = g_content_type_get_description (mime_type);
7567 if (description != NULL)
7568 {
7569 return description;
7570 }
7571 }
7572 else
7573 {
7574 char *category;
7575
7576 category = get_basic_type_for_mime_type (mime_type);
7577 if (category != NULL)
7578 {
7579 return category;
7580 }
7581 }
7582
7583 return g_strdup (mime_type);
7584 }
7585
7586 /* Takes ownership of string */
7587 static char *
update_description_for_link(NautilusFile * file,char * string)7588 update_description_for_link (NautilusFile *file,
7589 char *string)
7590 {
7591 char *res;
7592
7593 if (nautilus_file_is_symbolic_link (file))
7594 {
7595 g_assert (!nautilus_file_is_broken_symbolic_link (file));
7596 if (string == NULL)
7597 {
7598 return g_strdup (_("Link"));
7599 }
7600 /* Note to localizers: convert file type string for file
7601 * (e.g. "folder", "plain text") to file type for symbolic link
7602 * to that kind of file (e.g. "link to folder").
7603 */
7604 res = g_strdup_printf (_("Link to %s"), string);
7605 g_free (string);
7606 return res;
7607 }
7608
7609 return string;
7610 }
7611
7612 static char *
nautilus_file_get_type_as_string(NautilusFile * file)7613 nautilus_file_get_type_as_string (NautilusFile *file)
7614 {
7615 if (file == NULL)
7616 {
7617 return NULL;
7618 }
7619
7620 if (nautilus_file_is_broken_symbolic_link (file))
7621 {
7622 return g_strdup (_("Link (broken)"));
7623 }
7624
7625 return update_description_for_link (file, get_description (file, FALSE));
7626 }
7627
7628 static char *
nautilus_file_get_type_as_string_no_extra_text(NautilusFile * file)7629 nautilus_file_get_type_as_string_no_extra_text (NautilusFile *file)
7630 {
7631 if (file == NULL)
7632 {
7633 return NULL;
7634 }
7635
7636 if (nautilus_file_is_broken_symbolic_link (file))
7637 {
7638 return g_strdup (_("Link (broken)"));
7639 }
7640
7641 return get_description (file, FALSE);
7642 }
7643
7644 static char *
nautilus_file_get_detailed_type_as_string(NautilusFile * file)7645 nautilus_file_get_detailed_type_as_string (NautilusFile *file)
7646 {
7647 if (file == NULL)
7648 {
7649 return NULL;
7650 }
7651
7652 if (nautilus_file_is_broken_symbolic_link (file))
7653 {
7654 return g_strdup (_("Link (broken)"));
7655 }
7656
7657 return update_description_for_link (file, get_description (file, TRUE));
7658 }
7659
7660 /**
7661 * nautilus_file_get_file_type
7662 *
7663 * Return this file's type.
7664 * @file: NautilusFile representing the file in question.
7665 *
7666 * Returns: The type.
7667 *
7668 **/
7669 GFileType
nautilus_file_get_file_type(NautilusFile * file)7670 nautilus_file_get_file_type (NautilusFile *file)
7671 {
7672 g_return_val_if_fail (NAUTILUS_IS_FILE (file), G_FILE_TYPE_UNKNOWN);
7673
7674 return nautilus_file_info_get_file_type (NAUTILUS_FILE_INFO (file));
7675 }
7676
7677 /**
7678 * nautilus_file_get_mime_type
7679 *
7680 * Return this file's default mime type.
7681 * @file: NautilusFile representing the file in question.
7682 *
7683 * Returns: The mime type.
7684 *
7685 **/
7686 char *
nautilus_file_get_mime_type(NautilusFile * file)7687 nautilus_file_get_mime_type (NautilusFile *file)
7688 {
7689 g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
7690
7691 return nautilus_file_info_get_mime_type (NAUTILUS_FILE_INFO (file));
7692 }
7693
7694 /**
7695 * nautilus_file_is_mime_type
7696 *
7697 * Check whether a file is of a particular MIME type, or inherited
7698 * from it.
7699 * @file: NautilusFile representing the file in question.
7700 * @mime_type: The MIME-type string to test (e.g. "text/plain")
7701 *
7702 * Return value: TRUE if @mime_type exactly matches the
7703 * file's MIME type.
7704 *
7705 **/
7706 gboolean
nautilus_file_is_mime_type(NautilusFile * file,const char * mime_type)7707 nautilus_file_is_mime_type (NautilusFile *file,
7708 const char *mime_type)
7709 {
7710 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
7711 g_return_val_if_fail (mime_type != NULL, FALSE);
7712
7713 return nautilus_file_info_is_mime_type (NAUTILUS_FILE_INFO (file), mime_type);
7714 }
7715
7716 char *
nautilus_file_get_extension(NautilusFile * file)7717 nautilus_file_get_extension (NautilusFile *file)
7718 {
7719 char *name;
7720 char *extension = NULL;
7721
7722 name = nautilus_file_get_name (file);
7723 if (name != NULL)
7724 {
7725 extension = g_strdup (eel_filename_get_extension_offset (name));
7726 g_free (name);
7727 }
7728
7729 return extension;
7730 }
7731
7732 gboolean
nautilus_file_is_launchable(NautilusFile * file)7733 nautilus_file_is_launchable (NautilusFile *file)
7734 {
7735 gboolean type_can_be_executable;
7736
7737 type_can_be_executable = FALSE;
7738 if (file->details->mime_type != NULL)
7739 {
7740 type_can_be_executable =
7741 g_content_type_can_be_executable (file->details->mime_type);
7742 }
7743
7744 return type_can_be_executable &&
7745 nautilus_file_can_get_permissions (file) &&
7746 nautilus_file_can_execute (file) &&
7747 nautilus_file_is_executable (file) &&
7748 nautilus_file_is_regular_file (file);
7749 }
7750
7751 /**
7752 * nautilus_file_is_symbolic_link
7753 *
7754 * Check if this file is a symbolic link.
7755 * @file: NautilusFile representing the file in question.
7756 *
7757 * Returns: True if the file is a symbolic link.
7758 *
7759 **/
7760 gboolean
nautilus_file_is_symbolic_link(NautilusFile * file)7761 nautilus_file_is_symbolic_link (NautilusFile *file)
7762 {
7763 return file->details->is_symlink;
7764 }
7765
7766 GMount *
nautilus_file_get_mount(NautilusFile * file)7767 nautilus_file_get_mount (NautilusFile *file)
7768 {
7769 g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
7770
7771 return nautilus_file_info_get_mount (NAUTILUS_FILE_INFO (file));
7772 }
7773
7774 static void
file_mount_unmounted(GMount * mount,gpointer data)7775 file_mount_unmounted (GMount *mount,
7776 gpointer data)
7777 {
7778 NautilusFile *file;
7779
7780 file = NAUTILUS_FILE (data);
7781
7782 nautilus_file_invalidate_attributes (file, NAUTILUS_FILE_ATTRIBUTE_MOUNT);
7783 }
7784
7785 void
nautilus_file_set_mount(NautilusFile * file,GMount * mount)7786 nautilus_file_set_mount (NautilusFile *file,
7787 GMount *mount)
7788 {
7789 if (file->details->mount)
7790 {
7791 g_signal_handlers_disconnect_by_func (file->details->mount, file_mount_unmounted, file);
7792 g_object_unref (file->details->mount);
7793 file->details->mount = NULL;
7794 }
7795
7796 if (mount)
7797 {
7798 file->details->mount = g_object_ref (mount);
7799 g_signal_connect (mount, "unmounted",
7800 G_CALLBACK (file_mount_unmounted), file);
7801 }
7802 }
7803
7804 /**
7805 * nautilus_file_is_broken_symbolic_link
7806 *
7807 * Check if this file is a symbolic link with a missing target.
7808 * @file: NautilusFile representing the file in question.
7809 *
7810 * Returns: True if the file is a symbolic link with a missing target.
7811 *
7812 **/
7813 gboolean
nautilus_file_is_broken_symbolic_link(NautilusFile * file)7814 nautilus_file_is_broken_symbolic_link (NautilusFile *file)
7815 {
7816 if (file == NULL)
7817 {
7818 return FALSE;
7819 }
7820
7821 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
7822
7823 /* Non-broken symbolic links return the target's type for get_file_type. */
7824 return nautilus_file_get_file_type (file) == G_FILE_TYPE_SYMBOLIC_LINK;
7825 }
7826
7827 static void
get_fs_free_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)7828 get_fs_free_cb (GObject *source_object,
7829 GAsyncResult *res,
7830 gpointer user_data)
7831 {
7832 NautilusFile *file;
7833 guint64 free_space;
7834 GFileInfo *info;
7835
7836 file = NAUTILUS_FILE (user_data);
7837
7838 free_space = (guint64) - 1;
7839 info = g_file_query_filesystem_info_finish (G_FILE (source_object),
7840 res, NULL);
7841 if (info)
7842 {
7843 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE))
7844 {
7845 free_space = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE);
7846 }
7847 g_object_unref (info);
7848 }
7849
7850 if (file->details->free_space != free_space)
7851 {
7852 file->details->free_space = free_space;
7853 nautilus_file_emit_changed (file);
7854 }
7855
7856 nautilus_file_unref (file);
7857 }
7858
7859 /**
7860 * nautilus_file_get_volume_free_space
7861 * Get a nicely formatted char with free space on the file's volume
7862 * @file: NautilusFile representing the file in question.
7863 *
7864 * Returns: newly-allocated copy of file size in a formatted string
7865 */
7866 char *
nautilus_file_get_volume_free_space(NautilusFile * file)7867 nautilus_file_get_volume_free_space (NautilusFile *file)
7868 {
7869 GFile *location;
7870 char *res;
7871 time_t now;
7872
7873 now = time (NULL);
7874 /* Update first time and then every 2 seconds */
7875 if (file->details->free_space_read == 0 ||
7876 (now - file->details->free_space_read) > 2)
7877 {
7878 file->details->free_space_read = now;
7879 location = nautilus_file_get_location (file);
7880 g_file_query_filesystem_info_async (location,
7881 G_FILE_ATTRIBUTE_FILESYSTEM_FREE,
7882 0, NULL,
7883 get_fs_free_cb,
7884 nautilus_file_ref (file));
7885 g_object_unref (location);
7886 }
7887
7888 res = NULL;
7889 if (file->details->free_space != (guint64) - 1)
7890 {
7891 res = g_format_size (file->details->free_space);
7892 }
7893
7894 return res;
7895 }
7896
7897 /**
7898 * nautilus_file_get_volume_name
7899 * Get the path of the volume the file resides on
7900 * @file: NautilusFile representing the file in question.
7901 *
7902 * Returns: newly-allocated copy of the volume name of the target file,
7903 * if the volume name isn't set, it returns the mount path of the volume
7904 */
7905 char *
nautilus_file_get_volume_name(NautilusFile * file)7906 nautilus_file_get_volume_name (NautilusFile *file)
7907 {
7908 GFile *location;
7909 char *res;
7910 GMount *mount;
7911
7912 res = NULL;
7913
7914 location = nautilus_file_get_location (file);
7915 mount = g_file_find_enclosing_mount (location, NULL, NULL);
7916 if (mount)
7917 {
7918 res = g_strdup (g_mount_get_name (mount));
7919 g_object_unref (mount);
7920 }
7921 g_object_unref (location);
7922
7923 return res;
7924 }
7925
7926 /**
7927 * nautilus_file_get_symbolic_link_target_path
7928 *
7929 * Get the file path of the target of a symbolic link. It is an error
7930 * to call this function on a file that isn't a symbolic link.
7931 * @file: NautilusFile representing the symbolic link in question.
7932 *
7933 * Returns: newly-allocated copy of the file path of the target of the symbolic link.
7934 */
7935 char *
nautilus_file_get_symbolic_link_target_path(NautilusFile * file)7936 nautilus_file_get_symbolic_link_target_path (NautilusFile *file)
7937 {
7938 if (!nautilus_file_is_symbolic_link (file))
7939 {
7940 g_warning ("File has symlink target, but is not marked as symlink");
7941 }
7942
7943 return g_strdup (file->details->symlink_name);
7944 }
7945
7946 /**
7947 * nautilus_file_get_symbolic_link_target_uri
7948 *
7949 * Get the uri of the target of a symbolic link. It is an error
7950 * to call this function on a file that isn't a symbolic link.
7951 * @file: NautilusFile representing the symbolic link in question.
7952 *
7953 * Returns: newly-allocated copy of the uri of the target of the symbolic link.
7954 */
7955 char *
nautilus_file_get_symbolic_link_target_uri(NautilusFile * file)7956 nautilus_file_get_symbolic_link_target_uri (NautilusFile *file)
7957 {
7958 GFile *location, *parent, *target;
7959 char *target_uri;
7960
7961 if (!nautilus_file_is_symbolic_link (file))
7962 {
7963 g_warning ("File has symlink target, but is not marked as symlink");
7964 }
7965
7966 if (file->details->symlink_name == NULL)
7967 {
7968 return NULL;
7969 }
7970 else
7971 {
7972 target = NULL;
7973
7974 location = nautilus_file_get_location (file);
7975 parent = g_file_get_parent (location);
7976 g_object_unref (location);
7977 if (parent)
7978 {
7979 target = g_file_resolve_relative_path (parent, file->details->symlink_name);
7980 g_object_unref (parent);
7981 }
7982
7983 target_uri = NULL;
7984 if (target)
7985 {
7986 target_uri = g_file_get_uri (target);
7987 g_object_unref (target);
7988 }
7989 return target_uri;
7990 }
7991 }
7992
7993 /**
7994 * nautilus_file_is_regular_file
7995 *
7996 * Check if this file is a regular file.
7997 * @file: NautilusFile representing the file in question.
7998 *
7999 * Returns: TRUE if @file is a regular file.
8000 *
8001 **/
8002 gboolean
nautilus_file_is_regular_file(NautilusFile * file)8003 nautilus_file_is_regular_file (NautilusFile *file)
8004 {
8005 return nautilus_file_get_file_type (file) == G_FILE_TYPE_REGULAR;
8006 }
8007
8008 /**
8009 * nautilus_file_is_directory
8010 *
8011 * Check if this file is a directory.
8012 * @file: NautilusFile representing the file in question.
8013 *
8014 * Returns: TRUE if @file is a directory.
8015 *
8016 **/
8017 gboolean
nautilus_file_is_directory(NautilusFile * file)8018 nautilus_file_is_directory (NautilusFile *file)
8019 {
8020 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
8021
8022 return nautilus_file_info_is_directory (NAUTILUS_FILE_INFO (file));
8023 }
8024
8025 /**
8026 * nautilus_file_is_user_special_directory
8027 *
8028 * Check if this file is a special platform directory.
8029 * @file: NautilusFile representing the file in question.
8030 * @special_directory: GUserDirectory representing the type to test for
8031 *
8032 * Returns: TRUE if @file is a special directory of the given kind.
8033 */
8034 gboolean
nautilus_file_is_user_special_directory(NautilusFile * file,GUserDirectory special_directory)8035 nautilus_file_is_user_special_directory (NautilusFile *file,
8036 GUserDirectory special_directory)
8037 {
8038 gboolean is_special_dir;
8039 const gchar *special_dir;
8040
8041 special_dir = g_get_user_special_dir (special_directory);
8042 is_special_dir = FALSE;
8043
8044 if (special_dir)
8045 {
8046 GFile *loc;
8047 GFile *special_gfile;
8048
8049 loc = nautilus_file_get_location (file);
8050 special_gfile = g_file_new_for_path (special_dir);
8051 is_special_dir = g_file_equal (loc, special_gfile);
8052 g_object_unref (special_gfile);
8053 g_object_unref (loc);
8054 }
8055
8056 return is_special_dir;
8057 }
8058
8059 gboolean
nautilus_file_is_archive(NautilusFile * file)8060 nautilus_file_is_archive (NautilusFile *file)
8061 {
8062 g_autofree char *mime_type = NULL;
8063
8064 mime_type = nautilus_file_get_mime_type (file);
8065
8066 return autoar_check_mime_type_supported (mime_type);
8067 }
8068
8069
8070 /**
8071 * nautilus_file_is_in_trash
8072 *
8073 * Check if this file is a file in trash.
8074 * @file: NautilusFile representing the file in question.
8075 *
8076 * Returns: TRUE if @file is in a trash.
8077 *
8078 **/
8079 gboolean
nautilus_file_is_in_trash(NautilusFile * file)8080 nautilus_file_is_in_trash (NautilusFile *file)
8081 {
8082 g_assert (NAUTILUS_IS_FILE (file));
8083
8084 return nautilus_directory_is_in_trash (file->details->directory);
8085 }
8086
8087 /**
8088 * nautilus_file_is_in_recent
8089 *
8090 * Check if this file is a file in Recent.
8091 * @file: NautilusFile representing the file in question.
8092 *
8093 * Returns: TRUE if @file is in Recent.
8094 *
8095 **/
8096 gboolean
nautilus_file_is_in_recent(NautilusFile * file)8097 nautilus_file_is_in_recent (NautilusFile *file)
8098 {
8099 g_assert (NAUTILUS_IS_FILE (file));
8100
8101 return nautilus_directory_is_in_recent (file->details->directory);
8102 }
8103
8104 /**
8105 * nautilus_file_is_in_starred
8106 *
8107 * Check if this file is a file in Starred.
8108 * @file: NautilusFile representing the file in question.
8109 *
8110 * Returns: TRUE if @file is in Starred.
8111 *
8112 **/
8113 gboolean
nautilus_file_is_in_starred(NautilusFile * file)8114 nautilus_file_is_in_starred (NautilusFile *file)
8115 {
8116 g_assert (NAUTILUS_IS_FILE (file));
8117
8118 return nautilus_directory_is_in_starred (file->details->directory);
8119 }
8120
8121 /**
8122 * nautilus_file_is_remote
8123 *
8124 * Check if this file is a file in a remote filesystem.
8125 * @file: NautilusFile representing the file in question.
8126 *
8127 * Returns: TRUE if @file is in a remote filesystem.
8128 *
8129 **/
8130 gboolean
nautilus_file_is_remote(NautilusFile * file)8131 nautilus_file_is_remote (NautilusFile *file)
8132 {
8133 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
8134
8135 return nautilus_file_get_filesystem_remote (file);
8136 }
8137
8138 /**
8139 * nautilus_file_is_other_locations
8140 *
8141 * Check if this file is Other Locations.
8142 * @file: NautilusFile representing the file in question.
8143 *
8144 * Returns: TRUE if @file is Other Locations.
8145 *
8146 **/
8147 gboolean
nautilus_file_is_other_locations(NautilusFile * file)8148 nautilus_file_is_other_locations (NautilusFile *file)
8149 {
8150 gboolean is_other_locations;
8151 gchar *uri;
8152
8153 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
8154
8155 uri = nautilus_file_get_uri (file);
8156 is_other_locations = g_strcmp0 (uri, "other-locations:///") == 0;
8157
8158 g_free (uri);
8159
8160 return is_other_locations;
8161 }
8162
8163 /**
8164 * nautilus_file_is_starred_location
8165 *
8166 * Check if this file is the Favorite location.
8167 * @file: NautilusFile representing the file in question.
8168 *
8169 * Returns: TRUE if @file is the Favorite location.
8170 *
8171 **/
8172 gboolean
nautilus_file_is_starred_location(NautilusFile * file)8173 nautilus_file_is_starred_location (NautilusFile *file)
8174 {
8175 g_autofree gchar *uri = NULL;
8176
8177 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
8178
8179 uri = nautilus_file_get_uri (file);
8180
8181 return eel_uri_is_starred (uri);
8182 }
8183
8184 /**
8185 * nautilus_file_is_in_admin
8186 *
8187 * Check if this file is using admin backend.
8188 * @file: NautilusFile representing the file in question.
8189 *
8190 * Returns: TRUE if @file is using admin backend.
8191 *
8192 **/
8193 gboolean
nautilus_file_is_in_admin(NautilusFile * file)8194 nautilus_file_is_in_admin (NautilusFile *file)
8195 {
8196 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
8197
8198 return nautilus_directory_is_in_admin (file->details->directory);
8199 }
8200
8201 GError *
nautilus_file_get_file_info_error(NautilusFile * file)8202 nautilus_file_get_file_info_error (NautilusFile *file)
8203 {
8204 if (!file->details->get_info_failed)
8205 {
8206 return NULL;
8207 }
8208
8209 return file->details->get_info_error;
8210 }
8211
8212 /**
8213 * nautilus_file_contains_text
8214 *
8215 * Check if this file contains text.
8216 * This is private and is used to decide whether or not to read the top left text.
8217 * @file: NautilusFile representing the file in question.
8218 *
8219 * Returns: TRUE if @file has a text MIME type.
8220 *
8221 **/
8222 gboolean
nautilus_file_contains_text(NautilusFile * file)8223 nautilus_file_contains_text (NautilusFile *file)
8224 {
8225 if (file == NULL)
8226 {
8227 return FALSE;
8228 }
8229
8230 /* All text files inherit from text/plain */
8231 return nautilus_file_is_mime_type (file, "text/plain");
8232 }
8233
8234 /**
8235 * nautilus_file_is_executable
8236 *
8237 * Check if this file is executable at all.
8238 * @file: NautilusFile representing the file in question.
8239 *
8240 * Returns: TRUE if any of the execute bits are set. FALSE if
8241 * not, or if the permissions are unknown.
8242 *
8243 **/
8244 gboolean
nautilus_file_is_executable(NautilusFile * file)8245 nautilus_file_is_executable (NautilusFile *file)
8246 {
8247 if (!file->details->has_permissions)
8248 {
8249 /* File's permissions field is not valid.
8250 * Can't access specific permissions, so return FALSE.
8251 */
8252 return FALSE;
8253 }
8254
8255 return file->details->can_execute;
8256 }
8257
8258 char *
nautilus_file_get_filesystem_id(NautilusFile * file)8259 nautilus_file_get_filesystem_id (NautilusFile *file)
8260 {
8261 return g_strdup (file->details->filesystem_id);
8262 }
8263
8264 NautilusFile *
nautilus_file_get_trash_original_file(NautilusFile * file)8265 nautilus_file_get_trash_original_file (NautilusFile *file)
8266 {
8267 GFile *location;
8268 NautilusFile *original_file;
8269
8270 original_file = NULL;
8271
8272 if (file->details->trash_orig_path != NULL)
8273 {
8274 location = g_file_new_for_path (file->details->trash_orig_path);
8275 original_file = nautilus_file_get (location);
8276 g_object_unref (location);
8277 }
8278
8279 return original_file;
8280 }
8281
8282 void
nautilus_file_mark_gone(NautilusFile * file)8283 nautilus_file_mark_gone (NautilusFile *file)
8284 {
8285 NautilusDirectory *directory;
8286
8287 if (file->details->is_gone)
8288 {
8289 return;
8290 }
8291
8292 file->details->is_gone = TRUE;
8293
8294 update_links_if_target (file);
8295
8296 /* Drop it from the symlink hash ! */
8297 remove_from_link_hash_table (file);
8298
8299 /* Removing the file from the directory can result in dropping the last
8300 * reference, and so clearing the info then will result in a crash.
8301 */
8302 nautilus_file_clear_info (file);
8303
8304 /* Let the directory know it's gone. */
8305 directory = file->details->directory;
8306 if (!nautilus_file_is_self_owned (file))
8307 {
8308 nautilus_directory_remove_file (directory, file);
8309 }
8310
8311 /* FIXME bugzilla.gnome.org 42429:
8312 * Maybe we can get rid of the name too eventually, but
8313 * for now that would probably require too many if statements
8314 * everywhere anyone deals with the name. Maybe we can give it
8315 * a hard-coded "<deleted>" name or something.
8316 */
8317 }
8318
8319 /**
8320 * nautilus_file_changed
8321 *
8322 * Notify the user that this file has changed.
8323 * @file: NautilusFile representing the file in question.
8324 **/
8325 void
nautilus_file_changed(NautilusFile * file)8326 nautilus_file_changed (NautilusFile *file)
8327 {
8328 GList fake_list;
8329
8330 g_return_if_fail (NAUTILUS_IS_FILE (file));
8331
8332 if (nautilus_file_is_self_owned (file))
8333 {
8334 nautilus_file_emit_changed (file);
8335 }
8336 else
8337 {
8338 fake_list.data = file;
8339 fake_list.next = NULL;
8340 fake_list.prev = NULL;
8341 nautilus_directory_emit_change_signals
8342 (file->details->directory, &fake_list);
8343 }
8344 }
8345
8346 /**
8347 * nautilus_file_updated_deep_count_in_progress
8348 *
8349 * Notify clients that a newer deep count is available for
8350 * the directory in question.
8351 */
8352 void
nautilus_file_updated_deep_count_in_progress(NautilusFile * file)8353 nautilus_file_updated_deep_count_in_progress (NautilusFile *file)
8354 {
8355 GList *link_files, *node;
8356
8357 g_assert (NAUTILUS_IS_FILE (file));
8358 g_assert (nautilus_file_is_directory (file));
8359
8360 /* Send out a signal. */
8361 g_signal_emit (file, signals[UPDATED_DEEP_COUNT_IN_PROGRESS], 0, file);
8362
8363 /* Tell link files pointing to this object about the change. */
8364 link_files = get_link_files (file);
8365 for (node = link_files; node != NULL; node = node->next)
8366 {
8367 nautilus_file_updated_deep_count_in_progress (NAUTILUS_FILE (node->data));
8368 }
8369 nautilus_file_list_free (link_files);
8370 }
8371
8372 /**
8373 * nautilus_file_emit_changed
8374 *
8375 * Emit a file changed signal.
8376 * This can only be called by the directory, since the directory
8377 * also has to emit a files_changed signal.
8378 *
8379 * @file: NautilusFile representing the file in question.
8380 **/
8381 void
nautilus_file_emit_changed(NautilusFile * file)8382 nautilus_file_emit_changed (NautilusFile *file)
8383 {
8384 GList *link_files, *p;
8385
8386 g_assert (NAUTILUS_IS_FILE (file));
8387
8388 /* Send out a signal. */
8389 g_signal_emit (file, signals[CHANGED], 0, file);
8390
8391 /* Tell link files pointing to this object about the change. */
8392 link_files = get_link_files (file);
8393 for (p = link_files; p != NULL; p = p->next)
8394 {
8395 /* Looking for directly recursive links. */
8396 g_autolist (NautilusFile) link_targets = NULL;
8397 NautilusDirectory *directory;
8398
8399 /* Files can be links to themselves. */
8400 if (p->data == file)
8401 {
8402 continue;
8403 }
8404
8405 link_targets = get_link_files (p->data);
8406 directory = nautilus_file_get_directory (p->data);
8407
8408 /* Reiterating (heh) that this will break with more complex cycles.
8409 * Users, stop trying to break things on purpose.
8410 */
8411 if (g_list_find (link_targets, file) != NULL &&
8412 directory == nautilus_file_get_directory (file))
8413 {
8414 g_signal_emit (p->data, signals[CHANGED], 0, p->data);
8415 continue;
8416 }
8417
8418 nautilus_file_changed (NAUTILUS_FILE (p->data));
8419 }
8420 nautilus_file_list_free (link_files);
8421 }
8422
8423 /**
8424 * nautilus_file_is_gone
8425 *
8426 * Check if a file has already been deleted.
8427 * @file: NautilusFile representing the file in question.
8428 *
8429 * Returns: TRUE if the file is already gone.
8430 **/
8431 gboolean
nautilus_file_is_gone(NautilusFile * file)8432 nautilus_file_is_gone (NautilusFile *file)
8433 {
8434 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
8435
8436 return nautilus_file_info_is_gone (NAUTILUS_FILE_INFO (file));
8437 }
8438
8439 /**
8440 * nautilus_file_is_not_yet_confirmed
8441 *
8442 * Check if we're in a state where we don't know if a file really
8443 * exists or not, before the initial I/O is complete.
8444 * @file: NautilusFile representing the file in question.
8445 *
8446 * Returns: TRUE if the file is already gone.
8447 **/
8448 gboolean
nautilus_file_is_not_yet_confirmed(NautilusFile * file)8449 nautilus_file_is_not_yet_confirmed (NautilusFile *file)
8450 {
8451 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
8452
8453 return !file->details->got_file_info;
8454 }
8455
8456 /**
8457 * nautilus_file_check_if_ready
8458 *
8459 * Check whether the values for a set of file attributes are
8460 * currently available, without doing any additional work. This
8461 * is useful for callers that want to reflect updated information
8462 * when it is ready but don't want to force the work required to
8463 * obtain the information, which might be slow network calls, e.g.
8464 *
8465 * @file: The file being queried.
8466 * @file_attributes: A bit-mask with the desired information.
8467 *
8468 * Return value: TRUE if all of the specified attributes are currently readable.
8469 */
8470 gboolean
nautilus_file_check_if_ready(NautilusFile * file,NautilusFileAttributes file_attributes)8471 nautilus_file_check_if_ready (NautilusFile *file,
8472 NautilusFileAttributes file_attributes)
8473 {
8474 /* To be parallel with call_when_ready, return
8475 * TRUE for NULL file.
8476 */
8477 if (file == NULL)
8478 {
8479 return TRUE;
8480 }
8481
8482 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
8483
8484 return NAUTILUS_FILE_CLASS (G_OBJECT_GET_CLASS (file))->check_if_ready (file, file_attributes);
8485 }
8486
8487 void
nautilus_file_call_when_ready(NautilusFile * file,NautilusFileAttributes file_attributes,NautilusFileCallback callback,gpointer callback_data)8488 nautilus_file_call_when_ready (NautilusFile *file,
8489 NautilusFileAttributes file_attributes,
8490 NautilusFileCallback callback,
8491 gpointer callback_data)
8492 {
8493 if (file == NULL)
8494 {
8495 (*callback)(file, callback_data);
8496 return;
8497 }
8498
8499 g_return_if_fail (NAUTILUS_IS_FILE (file));
8500
8501 NAUTILUS_FILE_CLASS (G_OBJECT_GET_CLASS (file))->call_when_ready
8502 (file, file_attributes, callback, callback_data);
8503 }
8504
8505 void
nautilus_file_cancel_call_when_ready(NautilusFile * file,NautilusFileCallback callback,gpointer callback_data)8506 nautilus_file_cancel_call_when_ready (NautilusFile *file,
8507 NautilusFileCallback callback,
8508 gpointer callback_data)
8509 {
8510 g_return_if_fail (callback != NULL);
8511
8512 if (file == NULL)
8513 {
8514 return;
8515 }
8516
8517 g_return_if_fail (NAUTILUS_IS_FILE (file));
8518
8519 NAUTILUS_FILE_CLASS (G_OBJECT_GET_CLASS (file))->cancel_call_when_ready
8520 (file, callback, callback_data);
8521 }
8522
8523 static void
invalidate_directory_count(NautilusFile * file)8524 invalidate_directory_count (NautilusFile *file)
8525 {
8526 file->details->directory_count_is_up_to_date = FALSE;
8527 }
8528
8529 static void
invalidate_deep_counts(NautilusFile * file)8530 invalidate_deep_counts (NautilusFile *file)
8531 {
8532 file->details->deep_counts_status = NAUTILUS_REQUEST_NOT_STARTED;
8533 }
8534
8535 static void
invalidate_mime_list(NautilusFile * file)8536 invalidate_mime_list (NautilusFile *file)
8537 {
8538 file->details->mime_list_is_up_to_date = FALSE;
8539 }
8540
8541 static void
invalidate_file_info(NautilusFile * file)8542 invalidate_file_info (NautilusFile *file)
8543 {
8544 file->details->file_info_is_up_to_date = FALSE;
8545 }
8546
8547 static void
invalidate_thumbnail(NautilusFile * file)8548 invalidate_thumbnail (NautilusFile *file)
8549 {
8550 file->details->thumbnail_is_up_to_date = FALSE;
8551 }
8552
8553 static void
invalidate_mount(NautilusFile * file)8554 invalidate_mount (NautilusFile *file)
8555 {
8556 file->details->mount_is_up_to_date = FALSE;
8557 }
8558
8559 void
nautilus_file_invalidate_extension_info_internal(NautilusFile * file)8560 nautilus_file_invalidate_extension_info_internal (NautilusFile *file)
8561 {
8562 if (file->details->pending_info_providers)
8563 {
8564 g_list_free_full (file->details->pending_info_providers, g_object_unref);
8565 }
8566
8567 file->details->pending_info_providers =
8568 nautilus_module_get_extensions_for_type (NAUTILUS_TYPE_INFO_PROVIDER);
8569 }
8570
8571 void
nautilus_file_invalidate_attributes_internal(NautilusFile * file,NautilusFileAttributes file_attributes)8572 nautilus_file_invalidate_attributes_internal (NautilusFile *file,
8573 NautilusFileAttributes file_attributes)
8574 {
8575 Request request;
8576
8577 if (file == NULL)
8578 {
8579 return;
8580 }
8581
8582 request = nautilus_directory_set_up_request (file_attributes);
8583
8584 if (REQUEST_WANTS_TYPE (request, REQUEST_DIRECTORY_COUNT))
8585 {
8586 invalidate_directory_count (file);
8587 }
8588 if (REQUEST_WANTS_TYPE (request, REQUEST_DEEP_COUNT))
8589 {
8590 invalidate_deep_counts (file);
8591 }
8592 if (REQUEST_WANTS_TYPE (request, REQUEST_MIME_LIST))
8593 {
8594 invalidate_mime_list (file);
8595 }
8596 if (REQUEST_WANTS_TYPE (request, REQUEST_FILE_INFO))
8597 {
8598 invalidate_file_info (file);
8599 }
8600 if (REQUEST_WANTS_TYPE (request, REQUEST_EXTENSION_INFO))
8601 {
8602 nautilus_file_invalidate_extension_info_internal (file);
8603 }
8604 if (REQUEST_WANTS_TYPE (request, REQUEST_THUMBNAIL))
8605 {
8606 invalidate_thumbnail (file);
8607 }
8608 if (REQUEST_WANTS_TYPE (request, REQUEST_MOUNT))
8609 {
8610 invalidate_mount (file);
8611 }
8612
8613 /* FIXME bugzilla.gnome.org 45075: implement invalidating metadata */
8614 }
8615
8616 gboolean
nautilus_file_is_thumbnailing(NautilusFile * file)8617 nautilus_file_is_thumbnailing (NautilusFile *file)
8618 {
8619 g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
8620
8621 return file->details->is_thumbnailing;
8622 }
8623
8624 void
nautilus_file_set_is_thumbnailing(NautilusFile * file,gboolean is_thumbnailing)8625 nautilus_file_set_is_thumbnailing (NautilusFile *file,
8626 gboolean is_thumbnailing)
8627 {
8628 g_return_if_fail (NAUTILUS_IS_FILE (file));
8629
8630 file->details->is_thumbnailing = is_thumbnailing;
8631 }
8632
8633
8634 /**
8635 * nautilus_file_invalidate_attributes
8636 *
8637 * Invalidate the specified attributes and force a reload.
8638 * @file: NautilusFile representing the file in question.
8639 * @file_attributes: attributes to froget.
8640 **/
8641
8642 void
nautilus_file_invalidate_attributes(NautilusFile * file,NautilusFileAttributes file_attributes)8643 nautilus_file_invalidate_attributes (NautilusFile *file,
8644 NautilusFileAttributes file_attributes)
8645 {
8646 /* Cancel possible in-progress loads of any of these attributes */
8647 nautilus_directory_cancel_loading_file_attributes (file->details->directory,
8648 file,
8649 file_attributes);
8650
8651 /* Actually invalidate the values */
8652 nautilus_file_invalidate_attributes_internal (file, file_attributes);
8653
8654 nautilus_directory_add_file_to_work_queue (file->details->directory, file);
8655
8656 /* Kick off I/O if necessary */
8657 nautilus_directory_async_state_changed (file->details->directory);
8658 }
8659
8660 NautilusFileAttributes
nautilus_file_get_all_attributes(void)8661 nautilus_file_get_all_attributes (void)
8662 {
8663 return NAUTILUS_FILE_ATTRIBUTE_INFO |
8664 NAUTILUS_FILE_ATTRIBUTE_DEEP_COUNTS |
8665 NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT |
8666 NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES |
8667 NAUTILUS_FILE_ATTRIBUTE_EXTENSION_INFO |
8668 NAUTILUS_FILE_ATTRIBUTE_THUMBNAIL |
8669 NAUTILUS_FILE_ATTRIBUTE_MOUNT;
8670 }
8671
8672 void
nautilus_file_invalidate_all_attributes(NautilusFile * file)8673 nautilus_file_invalidate_all_attributes (NautilusFile *file)
8674 {
8675 NautilusFileAttributes all_attributes;
8676
8677 all_attributes = nautilus_file_get_all_attributes ();
8678 nautilus_file_invalidate_attributes (file, all_attributes);
8679 }
8680
8681
8682 /**
8683 * nautilus_file_dump
8684 *
8685 * Debugging call, prints out the contents of the file
8686 * fields.
8687 *
8688 * @file: file to dump.
8689 **/
8690 void
nautilus_file_dump(NautilusFile * file)8691 nautilus_file_dump (NautilusFile *file)
8692 {
8693 long size = file->details->deep_size;
8694 char *uri;
8695 const char *file_kind;
8696
8697 uri = nautilus_file_get_uri (file);
8698 g_print ("uri: %s \n", uri);
8699 if (!file->details->got_file_info)
8700 {
8701 g_print ("no file info \n");
8702 }
8703 else if (file->details->get_info_failed)
8704 {
8705 g_print ("failed to get file info \n");
8706 }
8707 else
8708 {
8709 g_print ("size: %ld \n", size);
8710 switch (file->details->type)
8711 {
8712 case G_FILE_TYPE_REGULAR:
8713 {
8714 file_kind = "regular file";
8715 }
8716 break;
8717
8718 case G_FILE_TYPE_DIRECTORY:
8719 {
8720 file_kind = "folder";
8721 }
8722 break;
8723
8724 case G_FILE_TYPE_SPECIAL:
8725 {
8726 file_kind = "special";
8727 }
8728 break;
8729
8730 case G_FILE_TYPE_SYMBOLIC_LINK:
8731 {
8732 file_kind = "symbolic link";
8733 }
8734 break;
8735
8736 case G_FILE_TYPE_UNKNOWN:
8737 default:
8738 {
8739 file_kind = "unknown";
8740 }
8741 break;
8742 }
8743 g_print ("kind: %s \n", file_kind);
8744 if (file->details->type == G_FILE_TYPE_SYMBOLIC_LINK)
8745 {
8746 g_print ("link to %s \n", file->details->symlink_name);
8747 /* FIXME bugzilla.gnome.org 42430: add following of symlinks here */
8748 }
8749 /* FIXME bugzilla.gnome.org 42431: add permissions and other useful stuff here */
8750 }
8751 g_free (uri);
8752 }
8753
8754 /**
8755 * nautilus_file_list_ref
8756 *
8757 * Ref all the files in a list.
8758 * @list: GList of files.
8759 **/
8760 GList *
nautilus_file_list_ref(GList * list)8761 nautilus_file_list_ref (GList *list)
8762 {
8763 g_list_foreach (list, (GFunc) nautilus_file_ref, NULL);
8764 return list;
8765 }
8766
8767 /**
8768 * nautilus_file_list_unref
8769 *
8770 * Unref all the files in a list.
8771 * @list: GList of files.
8772 **/
8773 void
nautilus_file_list_unref(GList * list)8774 nautilus_file_list_unref (GList *list)
8775 {
8776 g_list_foreach (list, (GFunc) nautilus_file_unref, NULL);
8777 }
8778
8779 /**
8780 * nautilus_file_list_free
8781 *
8782 * Free a list of files after unrefing them.
8783 * @list: GList of files.
8784 **/
8785 void
nautilus_file_list_free(GList * list)8786 nautilus_file_list_free (GList *list)
8787 {
8788 nautilus_file_list_unref (list);
8789 g_list_free (list);
8790 }
8791
8792 /**
8793 * nautilus_file_list_copy
8794 *
8795 * Copy the list of files, making a new ref of each,
8796 * @list: GList of files.
8797 **/
8798 GList *
nautilus_file_list_copy(GList * list)8799 nautilus_file_list_copy (GList *list)
8800 {
8801 return g_list_copy (nautilus_file_list_ref (list));
8802 }
8803
8804 static gboolean
get_attributes_for_default_sort_type(NautilusFile * file,gboolean * is_recent,gboolean * is_download,gboolean * is_trash,gboolean * is_search)8805 get_attributes_for_default_sort_type (NautilusFile *file,
8806 gboolean *is_recent,
8807 gboolean *is_download,
8808 gboolean *is_trash,
8809 gboolean *is_search)
8810 {
8811 gboolean is_recent_dir, is_download_dir, is_trash_dir, is_search_dir, retval;
8812
8813 *is_recent = FALSE;
8814 *is_download = FALSE;
8815 *is_trash = FALSE;
8816 *is_search = FALSE;
8817 retval = FALSE;
8818
8819 /* special handling for certain directories */
8820 if (file && nautilus_file_is_directory (file))
8821 {
8822 is_recent_dir =
8823 nautilus_file_is_in_recent (file);
8824 is_download_dir =
8825 nautilus_file_is_user_special_directory (file, G_USER_DIRECTORY_DOWNLOAD);
8826 is_trash_dir =
8827 nautilus_file_is_in_trash (file);
8828 is_search_dir =
8829 nautilus_file_is_in_search (file);
8830
8831 if (is_download_dir)
8832 {
8833 *is_download = TRUE;
8834 retval = TRUE;
8835 }
8836 else if (is_trash_dir)
8837 {
8838 *is_trash = TRUE;
8839 retval = TRUE;
8840 }
8841 else if (is_recent_dir)
8842 {
8843 *is_recent = TRUE;
8844 retval = TRUE;
8845 }
8846 else if (is_search_dir)
8847 {
8848 *is_search = TRUE;
8849 retval = TRUE;
8850 }
8851 }
8852
8853 return retval;
8854 }
8855 /**
8856 * nautilus_file_get_default_sort_type:
8857 * @file: A #NautilusFile representing a location
8858 * @reversed: (out): Location to store whether the order is reversed by default.
8859 *
8860 * Gets which sort order applies by default for the provided locations.
8861 *
8862 * If @file is a location with special needs (e.g. Trash or Recent), the return
8863 * value and @reversed flag are dictated by design. Otherwise, they stem from
8864 * the "default-sort-order" and "default-sort-in-reverse-order" preference keys.
8865 *
8866 * Returns: The default #NautilusFileSortType for this @file.
8867 */
8868 NautilusFileSortType
nautilus_file_get_default_sort_type(NautilusFile * file,gboolean * reversed)8869 nautilus_file_get_default_sort_type (NautilusFile *file,
8870 gboolean *reversed)
8871 {
8872 NautilusFileSortType retval;
8873 gboolean is_recent;
8874 gboolean is_download;
8875 gboolean is_trash;
8876 gboolean is_search;
8877 gboolean res;
8878
8879 retval = g_settings_get_enum (nautilus_preferences,
8880 NAUTILUS_PREFERENCES_DEFAULT_SORT_ORDER);
8881 is_recent = FALSE;
8882 is_download = FALSE;
8883 is_trash = FALSE;
8884 is_search = FALSE;
8885 res = get_attributes_for_default_sort_type (file, &is_recent, &is_download, &is_trash, &is_search);
8886
8887 if (res)
8888 {
8889 if (is_recent)
8890 {
8891 retval = NAUTILUS_FILE_SORT_BY_RECENCY;
8892 }
8893 else if (is_download)
8894 {
8895 retval = NAUTILUS_FILE_SORT_BY_MTIME;
8896 }
8897 else if (is_trash)
8898 {
8899 retval = NAUTILUS_FILE_SORT_BY_TRASHED_TIME;
8900 }
8901 else if (is_search)
8902 {
8903 retval = NAUTILUS_FILE_SORT_BY_SEARCH_RELEVANCE;
8904 }
8905 else
8906 {
8907 g_assert_not_reached ();
8908 }
8909
8910 if (reversed != NULL)
8911 {
8912 *reversed = res;
8913 }
8914 }
8915 else
8916 {
8917 if (reversed != NULL)
8918 {
8919 *reversed = g_settings_get_boolean (nautilus_preferences,
8920 NAUTILUS_PREFERENCES_DEFAULT_SORT_IN_REVERSE_ORDER);
8921 }
8922 }
8923
8924 return retval;
8925 }
8926
8927 static int
compare_by_display_name_cover(gconstpointer a,gconstpointer b)8928 compare_by_display_name_cover (gconstpointer a,
8929 gconstpointer b)
8930 {
8931 return compare_by_display_name (NAUTILUS_FILE (a), NAUTILUS_FILE (b));
8932 }
8933
8934 /**
8935 * nautilus_file_list_sort_by_display_name
8936 *
8937 * Sort the list of files by file name.
8938 * @list: GList of files.
8939 **/
8940 GList *
nautilus_file_list_sort_by_display_name(GList * list)8941 nautilus_file_list_sort_by_display_name (GList *list)
8942 {
8943 return g_list_sort (list, compare_by_display_name_cover);
8944 }
8945
8946 static GList *ready_data_list = NULL;
8947
8948 typedef struct
8949 {
8950 GList *file_list;
8951 GList *remaining_files;
8952 NautilusFileListCallback callback;
8953 gpointer callback_data;
8954 } FileListReadyData;
8955
8956 static void
file_list_ready_data_free(FileListReadyData * data)8957 file_list_ready_data_free (FileListReadyData *data)
8958 {
8959 GList *l;
8960
8961 l = g_list_find (ready_data_list, data);
8962 if (l != NULL)
8963 {
8964 ready_data_list = g_list_delete_link (ready_data_list, l);
8965
8966 nautilus_file_list_free (data->file_list);
8967 g_list_free (data->remaining_files);
8968 g_free (data);
8969 }
8970 }
8971
8972 static FileListReadyData *
file_list_ready_data_new(GList * file_list,NautilusFileListCallback callback,gpointer callback_data)8973 file_list_ready_data_new (GList *file_list,
8974 NautilusFileListCallback callback,
8975 gpointer callback_data)
8976 {
8977 FileListReadyData *data;
8978
8979 data = g_new0 (FileListReadyData, 1);
8980 data->file_list = nautilus_file_list_copy (file_list);
8981 data->remaining_files = g_list_copy (file_list);
8982 data->callback = callback;
8983 data->callback_data = callback_data;
8984
8985 ready_data_list = g_list_prepend (ready_data_list, data);
8986
8987 return data;
8988 }
8989
8990 static void
file_list_file_ready_callback(NautilusFile * file,gpointer user_data)8991 file_list_file_ready_callback (NautilusFile *file,
8992 gpointer user_data)
8993 {
8994 FileListReadyData *data;
8995
8996 data = user_data;
8997 data->remaining_files = g_list_remove (data->remaining_files, file);
8998
8999 if (data->remaining_files == NULL)
9000 {
9001 if (data->callback)
9002 {
9003 (*data->callback)(data->file_list, data->callback_data);
9004 }
9005
9006 file_list_ready_data_free (data);
9007 }
9008 }
9009
9010 void
nautilus_file_list_call_when_ready(GList * file_list,NautilusFileAttributes attributes,NautilusFileListHandle ** handle,NautilusFileListCallback callback,gpointer callback_data)9011 nautilus_file_list_call_when_ready (GList *file_list,
9012 NautilusFileAttributes attributes,
9013 NautilusFileListHandle **handle,
9014 NautilusFileListCallback callback,
9015 gpointer callback_data)
9016 {
9017 GList *l;
9018 FileListReadyData *data;
9019 NautilusFile *file;
9020
9021 g_return_if_fail (file_list != NULL);
9022
9023 data = file_list_ready_data_new
9024 (file_list, callback, callback_data);
9025
9026 if (handle)
9027 {
9028 *handle = (NautilusFileListHandle *) data;
9029 }
9030
9031
9032 l = file_list;
9033 while (l != NULL)
9034 {
9035 file = NAUTILUS_FILE (l->data);
9036 /* Need to do this here, as the list can be modified by this call */
9037 l = l->next;
9038 nautilus_file_call_when_ready (file,
9039 attributes,
9040 file_list_file_ready_callback,
9041 data);
9042 }
9043 }
9044
9045 void
nautilus_file_list_cancel_call_when_ready(NautilusFileListHandle * handle)9046 nautilus_file_list_cancel_call_when_ready (NautilusFileListHandle *handle)
9047 {
9048 GList *l;
9049 NautilusFile *file;
9050 FileListReadyData *data;
9051
9052 g_return_if_fail (handle != NULL);
9053
9054 data = (FileListReadyData *) handle;
9055
9056 l = g_list_find (ready_data_list, data);
9057 if (l != NULL)
9058 {
9059 for (l = data->remaining_files; l != NULL; l = l->next)
9060 {
9061 file = NAUTILUS_FILE (l->data);
9062
9063 NAUTILUS_FILE_CLASS (G_OBJECT_GET_CLASS (file))->cancel_call_when_ready
9064 (file, file_list_file_ready_callback, data);
9065 }
9066
9067 file_list_ready_data_free (data);
9068 }
9069 }
9070
9071 static void
thumbnail_limit_changed_callback(gpointer user_data)9072 thumbnail_limit_changed_callback (gpointer user_data)
9073 {
9074 cached_thumbnail_limit = g_settings_get_uint64 (nautilus_preferences,
9075 NAUTILUS_PREFERENCES_FILE_THUMBNAIL_LIMIT);
9076
9077 /*Converts the obtained limit in MB to bytes */
9078 cached_thumbnail_limit *= MEGA_TO_BASE_RATE;
9079
9080 /* Tell the world that icons might have changed. We could invent a narrower-scope
9081 * signal to mean only "thumbnails might have changed" if this ends up being slow
9082 * for some reason.
9083 */
9084 emit_change_signals_for_all_files_in_all_directories ();
9085 }
9086
9087 static void
show_thumbnails_changed_callback(gpointer user_data)9088 show_thumbnails_changed_callback (gpointer user_data)
9089 {
9090 show_file_thumbs = g_settings_get_enum (nautilus_preferences, NAUTILUS_PREFERENCES_SHOW_FILE_THUMBNAILS);
9091
9092 /* Tell the world that icons might have changed. We could invent a narrower-scope
9093 * signal to mean only "thumbnails might have changed" if this ends up being slow
9094 * for some reason.
9095 */
9096 emit_change_signals_for_all_files_in_all_directories ();
9097 }
9098
9099 static void
mime_type_data_changed_callback(GObject * signaller,gpointer user_data)9100 mime_type_data_changed_callback (GObject *signaller,
9101 gpointer user_data)
9102 {
9103 /* Tell the world that icons might have changed. We could invent a narrower-scope
9104 * signal to mean only "thumbnails might have changed" if this ends up being slow
9105 * for some reason.
9106 */
9107 emit_change_signals_for_all_files_in_all_directories ();
9108 }
9109
9110 static gboolean
real_get_item_count(NautilusFile * file,guint * count,gboolean * count_unreadable)9111 real_get_item_count (NautilusFile *file,
9112 guint *count,
9113 gboolean *count_unreadable)
9114 {
9115 if (count_unreadable != NULL)
9116 {
9117 *count_unreadable = file->details->directory_count_failed;
9118 }
9119
9120 if (!file->details->got_directory_count)
9121 {
9122 if (count != NULL)
9123 {
9124 *count = 0;
9125 }
9126 return FALSE;
9127 }
9128
9129 if (count != NULL)
9130 {
9131 *count = file->details->directory_count;
9132 }
9133
9134 return TRUE;
9135 }
9136
9137 static NautilusRequestStatus
real_get_deep_counts(NautilusFile * file,guint * directory_count,guint * file_count,guint * unreadable_directory_count,goffset * total_size)9138 real_get_deep_counts (NautilusFile *file,
9139 guint *directory_count,
9140 guint *file_count,
9141 guint *unreadable_directory_count,
9142 goffset *total_size)
9143 {
9144 GFileType type;
9145
9146 type = nautilus_file_get_file_type (file);
9147
9148 if (directory_count != NULL)
9149 {
9150 *directory_count = 0;
9151 }
9152 if (file_count != NULL)
9153 {
9154 *file_count = 0;
9155 }
9156 if (unreadable_directory_count != NULL)
9157 {
9158 *unreadable_directory_count = 0;
9159 }
9160 if (total_size != NULL)
9161 {
9162 *total_size = 0;
9163 }
9164
9165 if (type != G_FILE_TYPE_DIRECTORY)
9166 {
9167 return NAUTILUS_REQUEST_DONE;
9168 }
9169
9170 if (file->details->deep_counts_status != NAUTILUS_REQUEST_NOT_STARTED)
9171 {
9172 if (directory_count != NULL)
9173 {
9174 *directory_count = file->details->deep_directory_count;
9175 }
9176 if (file_count != NULL)
9177 {
9178 *file_count = file->details->deep_file_count;
9179 }
9180 if (unreadable_directory_count != NULL)
9181 {
9182 *unreadable_directory_count = file->details->deep_unreadable_count;
9183 }
9184 if (total_size != NULL)
9185 {
9186 *total_size = file->details->deep_size;
9187 }
9188 return file->details->deep_counts_status;
9189 }
9190
9191 /* For directories, or before we know the type, we haven't started. */
9192 if (type == G_FILE_TYPE_UNKNOWN || type == G_FILE_TYPE_DIRECTORY)
9193 {
9194 return NAUTILUS_REQUEST_NOT_STARTED;
9195 }
9196
9197 /* For other types, we are done, and the zeros are permanent. */
9198 return NAUTILUS_REQUEST_DONE;
9199 }
9200
9201 static void
real_set_metadata(NautilusFile * file,const char * key,const char * value)9202 real_set_metadata (NautilusFile *file,
9203 const char *key,
9204 const char *value)
9205 {
9206 /* Dummy default impl */
9207 }
9208
9209 static void
real_set_metadata_as_list(NautilusFile * file,const char * key,char ** value)9210 real_set_metadata_as_list (NautilusFile *file,
9211 const char *key,
9212 char **value)
9213 {
9214 /* Dummy default impl */
9215 }
9216
9217 static void
nautilus_file_class_init(NautilusFileClass * class)9218 nautilus_file_class_init (NautilusFileClass *class)
9219 {
9220 nautilus_file_info_getter = nautilus_file_get_internal;
9221
9222 attribute_name_q = g_quark_from_static_string ("name");
9223 attribute_size_q = g_quark_from_static_string ("size");
9224 attribute_type_q = g_quark_from_static_string ("type");
9225 attribute_detailed_type_q = g_quark_from_static_string ("detailed_type");
9226 attribute_modification_date_q = g_quark_from_static_string ("modification_date");
9227 attribute_date_modified_q = g_quark_from_static_string ("date_modified");
9228 attribute_date_modified_full_q = g_quark_from_static_string ("date_modified_full");
9229 attribute_date_modified_with_time_q = g_quark_from_static_string ("date_modified_with_time");
9230 attribute_recency_q = g_quark_from_static_string ("recency");
9231 attribute_accessed_date_q = g_quark_from_static_string ("accessed_date");
9232 attribute_date_accessed_q = g_quark_from_static_string ("date_accessed");
9233 attribute_date_accessed_full_q = g_quark_from_static_string ("date_accessed_full");
9234 attribute_date_created_q = g_quark_from_static_string ("date_created");
9235 attribute_date_created_full_q = g_quark_from_static_string ("date_created_full");
9236 attribute_mime_type_q = g_quark_from_static_string ("mime_type");
9237 attribute_size_detail_q = g_quark_from_static_string ("size_detail");
9238 attribute_deep_size_q = g_quark_from_static_string ("deep_size");
9239 attribute_deep_file_count_q = g_quark_from_static_string ("deep_file_count");
9240 attribute_deep_directory_count_q = g_quark_from_static_string ("deep_directory_count");
9241 attribute_deep_total_count_q = g_quark_from_static_string ("deep_total_count");
9242 attribute_search_relevance_q = g_quark_from_static_string ("search_relevance");
9243 attribute_trashed_on_q = g_quark_from_static_string ("trashed_on");
9244 attribute_trashed_on_full_q = g_quark_from_static_string ("trashed_on_full");
9245 attribute_trash_orig_path_q = g_quark_from_static_string ("trash_orig_path");
9246 attribute_permissions_q = g_quark_from_static_string ("permissions");
9247 attribute_selinux_context_q = g_quark_from_static_string ("selinux_context");
9248 attribute_octal_permissions_q = g_quark_from_static_string ("octal_permissions");
9249 attribute_owner_q = g_quark_from_static_string ("owner");
9250 attribute_group_q = g_quark_from_static_string ("group");
9251 attribute_uri_q = g_quark_from_static_string ("uri");
9252 attribute_where_q = g_quark_from_static_string ("where");
9253 attribute_link_target_q = g_quark_from_static_string ("link_target");
9254 attribute_volume_q = g_quark_from_static_string ("volume");
9255 attribute_free_space_q = g_quark_from_static_string ("free_space");
9256 attribute_starred_q = g_quark_from_static_string ("starred");
9257
9258 G_OBJECT_CLASS (class)->finalize = finalize;
9259 G_OBJECT_CLASS (class)->constructor = nautilus_file_constructor;
9260
9261 class->get_item_count = real_get_item_count;
9262 class->get_deep_counts = real_get_deep_counts;
9263 class->set_metadata = real_set_metadata;
9264 class->set_metadata_as_list = real_set_metadata_as_list;
9265
9266 signals[CHANGED] =
9267 g_signal_new ("changed",
9268 G_TYPE_FROM_CLASS (class),
9269 G_SIGNAL_RUN_LAST,
9270 G_STRUCT_OFFSET (NautilusFileClass, changed),
9271 NULL, NULL,
9272 g_cclosure_marshal_VOID__VOID,
9273 G_TYPE_NONE, 0);
9274
9275 signals[UPDATED_DEEP_COUNT_IN_PROGRESS] =
9276 g_signal_new ("updated-deep-count-in-progress",
9277 G_TYPE_FROM_CLASS (class),
9278 G_SIGNAL_RUN_LAST,
9279 G_STRUCT_OFFSET (NautilusFileClass, updated_deep_count_in_progress),
9280 NULL, NULL,
9281 g_cclosure_marshal_VOID__VOID,
9282 G_TYPE_NONE, 0);
9283
9284 g_type_class_add_private (class, sizeof (NautilusFileDetails));
9285
9286 thumbnail_limit_changed_callback (NULL);
9287 g_signal_connect_swapped (nautilus_preferences,
9288 "changed::" NAUTILUS_PREFERENCES_FILE_THUMBNAIL_LIMIT,
9289 G_CALLBACK (thumbnail_limit_changed_callback),
9290 NULL);
9291 show_thumbnails_changed_callback (NULL);
9292 g_signal_connect_swapped (nautilus_preferences,
9293 "changed::" NAUTILUS_PREFERENCES_SHOW_FILE_THUMBNAILS,
9294 G_CALLBACK (show_thumbnails_changed_callback),
9295 NULL);
9296
9297 g_signal_connect (nautilus_signaller_get_current (),
9298 "mime-data-changed",
9299 G_CALLBACK (mime_type_data_changed_callback),
9300 NULL);
9301 }
9302
9303 void
nautilus_file_info_providers_done(NautilusFile * file)9304 nautilus_file_info_providers_done (NautilusFile *file)
9305 {
9306 g_list_free_full (file->details->extension_emblems, g_free);
9307 file->details->extension_emblems = file->details->pending_extension_emblems;
9308 file->details->pending_extension_emblems = NULL;
9309
9310 if (file->details->extension_attributes)
9311 {
9312 g_hash_table_destroy (file->details->extension_attributes);
9313 }
9314
9315 file->details->extension_attributes = file->details->pending_extension_attributes;
9316 file->details->pending_extension_attributes = NULL;
9317
9318 nautilus_file_changed (file);
9319 }
9320
9321 /* DND */
9322
9323 static gboolean
nautilus_drag_can_accept_files(NautilusFile * drop_target_item)9324 nautilus_drag_can_accept_files (NautilusFile *drop_target_item)
9325 {
9326 if (nautilus_file_is_directory (drop_target_item))
9327 {
9328 NautilusDirectory *directory;
9329 gboolean res;
9330
9331 /* target is a directory, accept if editable */
9332 directory = nautilus_directory_get_for_file (drop_target_item);
9333 res = nautilus_directory_is_editable (directory) &&
9334 nautilus_file_can_write (drop_target_item);
9335 nautilus_directory_unref (directory);
9336 return res;
9337 }
9338
9339 if (nautilus_is_file_roller_installed () &&
9340 nautilus_file_is_archive (drop_target_item))
9341 {
9342 return TRUE;
9343 }
9344
9345 return FALSE;
9346 }
9347
9348 gboolean
nautilus_drag_can_accept_item(NautilusFile * drop_target_item,const char * item_uri)9349 nautilus_drag_can_accept_item (NautilusFile *drop_target_item,
9350 const char *item_uri)
9351 {
9352 if (nautilus_file_matches_uri (drop_target_item, item_uri))
9353 {
9354 /* can't accept itself */
9355 return FALSE;
9356 }
9357
9358 return nautilus_drag_can_accept_files (drop_target_item);
9359 }
9360
9361 gboolean
nautilus_drag_can_accept_items(NautilusFile * drop_target_item,const GList * items)9362 nautilus_drag_can_accept_items (NautilusFile *drop_target_item,
9363 const GList *items)
9364 {
9365 int max;
9366
9367 if (drop_target_item == NULL)
9368 {
9369 return FALSE;
9370 }
9371
9372 g_assert (NAUTILUS_IS_FILE (drop_target_item));
9373
9374 /* Iterate through selection checking if item will get accepted by the
9375 * drop target. If more than 100 items selected, return an over-optimisic
9376 * result
9377 */
9378 for (max = 100; items != NULL && max >= 0; items = items->next, max--)
9379 {
9380 if (!nautilus_drag_can_accept_item (drop_target_item,
9381 ((NautilusDragSelectionItem *) items->data)->uri))
9382 {
9383 return FALSE;
9384 }
9385 }
9386
9387 return TRUE;
9388 }
9389
9390 gboolean
nautilus_drag_can_accept_info(NautilusFile * drop_target_item,NautilusIconDndTargetType drag_type,const GList * items)9391 nautilus_drag_can_accept_info (NautilusFile *drop_target_item,
9392 NautilusIconDndTargetType drag_type,
9393 const GList *items)
9394 {
9395 switch (drag_type)
9396 {
9397 case NAUTILUS_ICON_DND_GNOME_ICON_LIST:
9398 {
9399 return nautilus_drag_can_accept_items (drop_target_item, items);
9400 }
9401
9402 case NAUTILUS_ICON_DND_URI_LIST:
9403 case NAUTILUS_ICON_DND_NETSCAPE_URL:
9404 case NAUTILUS_ICON_DND_TEXT:
9405 {
9406 return nautilus_drag_can_accept_files (drop_target_item);
9407 }
9408
9409 case NAUTILUS_ICON_DND_XDNDDIRECTSAVE:
9410 case NAUTILUS_ICON_DND_RAW:
9411 {
9412 return nautilus_drag_can_accept_files (drop_target_item); /* Check if we can accept files at this location */
9413 }
9414
9415 case NAUTILUS_ICON_DND_ROOTWINDOW_DROP:
9416 {
9417 return FALSE;
9418 }
9419
9420 default:
9421 {
9422 g_assert_not_reached ();
9423 return FALSE;
9424 }
9425 }
9426 }
9427
9428 static gboolean
is_gone(NautilusFileInfo * file_info)9429 is_gone (NautilusFileInfo *file_info)
9430 {
9431 NautilusFile *file;
9432
9433 file = NAUTILUS_FILE (file_info);
9434
9435 return file->details->is_gone;
9436 }
9437
9438 static char *
get_name(NautilusFileInfo * file_info)9439 get_name (NautilusFileInfo *file_info)
9440 {
9441 NautilusFile *file;
9442
9443 file = NAUTILUS_FILE (file_info);
9444
9445 return g_strdup (file->details->name);
9446 }
9447
9448 static char *
get_uri(NautilusFileInfo * file_info)9449 get_uri (NautilusFileInfo *file_info)
9450 {
9451 NautilusFile *file;
9452 g_autoptr (GFile) location = NULL;
9453
9454 file = NAUTILUS_FILE (file_info);
9455 location = nautilus_file_get_location (file);
9456
9457 return g_file_get_uri (location);
9458 }
9459
9460 static char *
get_parent_uri(NautilusFileInfo * file_info)9461 get_parent_uri (NautilusFileInfo *file_info)
9462 {
9463 NautilusFile *file;
9464
9465 file = NAUTILUS_FILE (file_info);
9466
9467 if (nautilus_file_is_self_owned (file))
9468 {
9469 /* Callers expect an empty string, not a NULL. */
9470 return g_strdup ("");
9471 }
9472
9473 return nautilus_directory_get_uri (file->details->directory);
9474 }
9475
9476 static char *
get_uri_scheme(NautilusFileInfo * file_info)9477 get_uri_scheme (NautilusFileInfo *file_info)
9478 {
9479 NautilusFile *file;
9480 g_autoptr (GFile) location = NULL;
9481
9482 file = NAUTILUS_FILE (file_info);
9483
9484 if (file->details->directory == NULL)
9485 {
9486 return NULL;
9487 }
9488
9489 location = nautilus_directory_get_location (file->details->directory);
9490 if (location == NULL)
9491 {
9492 return NULL;
9493 }
9494
9495 return g_file_get_uri_scheme (location);
9496 }
9497
9498 static char *
get_mime_type(NautilusFileInfo * file_info)9499 get_mime_type (NautilusFileInfo *file_info)
9500 {
9501 NautilusFile *file;
9502
9503 file = NAUTILUS_FILE (file_info);
9504
9505 if (file->details->mime_type != NULL)
9506 {
9507 return g_strdup (file->details->mime_type);
9508 }
9509
9510 return g_strdup ("application/octet-stream");
9511 }
9512
9513 static gboolean
is_mime_type(NautilusFileInfo * file_info,const char * mime_type)9514 is_mime_type (NautilusFileInfo *file_info,
9515 const char *mime_type)
9516 {
9517 NautilusFile *file;
9518
9519 file = NAUTILUS_FILE (file_info);
9520
9521 if (file->details->mime_type == NULL)
9522 {
9523 return FALSE;
9524 }
9525
9526 return g_content_type_is_a (file->details->mime_type, mime_type);
9527 }
9528
9529 static gboolean
is_directory(NautilusFileInfo * file_info)9530 is_directory (NautilusFileInfo *file_info)
9531 {
9532 NautilusFile *file;
9533
9534 file = NAUTILUS_FILE (file_info);
9535
9536 return nautilus_file_get_file_type (file) == G_FILE_TYPE_DIRECTORY;
9537 }
9538
9539 static void
add_emblem(NautilusFileInfo * file_info,const char * emblem_name)9540 add_emblem (NautilusFileInfo *file_info,
9541 const char *emblem_name)
9542 {
9543 NautilusFile *file;
9544
9545 file = NAUTILUS_FILE (file_info);
9546
9547 if (file->details->pending_info_providers)
9548 {
9549 file->details->pending_extension_emblems = g_list_prepend (file->details->pending_extension_emblems,
9550 g_strdup (emblem_name));
9551 }
9552 else
9553 {
9554 file->details->extension_emblems = g_list_prepend (file->details->extension_emblems,
9555 g_strdup (emblem_name));
9556 }
9557
9558 nautilus_file_changed (file);
9559 }
9560
9561 static char *
get_string_attribute(NautilusFileInfo * file_info,const char * attribute_name)9562 get_string_attribute (NautilusFileInfo *file_info,
9563 const char *attribute_name)
9564 {
9565 NautilusFile *file;
9566
9567 file = NAUTILUS_FILE (file_info);
9568
9569 return nautilus_file_get_string_attribute_q (file, g_quark_from_string (attribute_name));
9570 }
9571
9572 static void
add_string_attribute(NautilusFileInfo * file_info,const char * attribute_name,const char * value)9573 add_string_attribute (NautilusFileInfo *file_info,
9574 const char *attribute_name,
9575 const char *value)
9576 {
9577 NautilusFile *file;
9578
9579 file = NAUTILUS_FILE (file_info);
9580
9581 if (file->details->pending_info_providers != NULL)
9582 {
9583 /* Lazily create hashtable */
9584 if (file->details->pending_extension_attributes == NULL)
9585 {
9586 file->details->pending_extension_attributes =
9587 g_hash_table_new_full (g_direct_hash, g_direct_equal,
9588 NULL,
9589 (GDestroyNotify) g_free);
9590 }
9591 g_hash_table_insert (file->details->pending_extension_attributes,
9592 GINT_TO_POINTER (g_quark_from_string (attribute_name)),
9593 g_strdup (value));
9594 }
9595 else
9596 {
9597 if (file->details->extension_attributes == NULL)
9598 {
9599 file->details->extension_attributes =
9600 g_hash_table_new_full (g_direct_hash, g_direct_equal,
9601 NULL,
9602 (GDestroyNotify) g_free);
9603 }
9604 g_hash_table_insert (file->details->extension_attributes,
9605 GINT_TO_POINTER (g_quark_from_string (attribute_name)),
9606 g_strdup (value));
9607 }
9608
9609 nautilus_file_changed (file);
9610 }
9611
9612 static void
invalidate_extension_info(NautilusFileInfo * file_info)9613 invalidate_extension_info (NautilusFileInfo *file_info)
9614 {
9615 NautilusFile *file;
9616
9617 file = NAUTILUS_FILE (file_info);
9618
9619 nautilus_file_invalidate_attributes (file, NAUTILUS_FILE_ATTRIBUTE_EXTENSION_INFO);
9620 }
9621
9622 static char *
get_activation_uri(NautilusFileInfo * file_info)9623 get_activation_uri (NautilusFileInfo *file_info)
9624 {
9625 NautilusFile *file;
9626
9627 file = NAUTILUS_FILE (file_info);
9628
9629 if (file->details->activation_uri != NULL)
9630 {
9631 return g_strdup (file->details->activation_uri);
9632 }
9633
9634 return nautilus_file_get_uri (file);
9635 }
9636
9637 static GFileType
get_file_type(NautilusFileInfo * file_info)9638 get_file_type (NautilusFileInfo *file_info)
9639 {
9640 NautilusFile *file;
9641
9642 file = NAUTILUS_FILE (file_info);
9643
9644 return file->details->type;
9645 }
9646
9647 static GFile *
get_location(NautilusFileInfo * file_info)9648 get_location (NautilusFileInfo *file_info)
9649 {
9650 NautilusFile *file;
9651 g_autoptr (GFile) location = NULL;
9652
9653 file = NAUTILUS_FILE (file_info);
9654 location = nautilus_directory_get_location (file->details->directory);
9655
9656 if (nautilus_file_is_self_owned (file))
9657 {
9658 return g_object_ref (location);
9659 }
9660
9661 return g_file_get_child (location, file->details->name);
9662 }
9663
9664 static GFile *
get_parent_location(NautilusFileInfo * file_info)9665 get_parent_location (NautilusFileInfo *file_info)
9666 {
9667 NautilusFile *file;
9668
9669 file = NAUTILUS_FILE (file_info);
9670
9671 if (nautilus_file_is_self_owned (file))
9672 {
9673 return NULL;
9674 }
9675
9676 return nautilus_directory_get_location (file->details->directory);
9677 }
9678
9679 static NautilusFileInfo *
get_parent_info(NautilusFileInfo * file_info)9680 get_parent_info (NautilusFileInfo *file_info)
9681 {
9682 NautilusFile *file;
9683 NautilusFile *parent_file;
9684
9685 file = NAUTILUS_FILE (file_info);
9686
9687 if (nautilus_file_is_self_owned (file))
9688 {
9689 return NULL;
9690 }
9691
9692 parent_file = nautilus_directory_get_corresponding_file (file->details->directory);
9693
9694 return NAUTILUS_FILE_INFO (parent_file);
9695 }
9696
9697 static GMount *
get_mount(NautilusFileInfo * file_info)9698 get_mount (NautilusFileInfo *file_info)
9699 {
9700 NautilusFile *file;
9701
9702 file = NAUTILUS_FILE (file_info);
9703
9704 if (file->details->mount)
9705 {
9706 return g_object_ref (file->details->mount);
9707 }
9708
9709 return NULL;
9710 }
9711
9712 static gboolean
can_write(NautilusFileInfo * file_info)9713 can_write (NautilusFileInfo *file_info)
9714 {
9715 NautilusFile *file;
9716
9717 file = NAUTILUS_FILE (file_info);
9718
9719 return file->details->can_write;
9720 }
9721
9722 static void
nautilus_file_info_iface_init(NautilusFileInfoInterface * iface)9723 nautilus_file_info_iface_init (NautilusFileInfoInterface *iface)
9724 {
9725 iface->is_gone = is_gone;
9726
9727 iface->get_name = get_name;
9728 iface->get_uri = get_uri;
9729 iface->get_parent_uri = get_parent_uri;
9730 iface->get_uri_scheme = get_uri_scheme;
9731
9732 iface->get_mime_type = get_mime_type;
9733 iface->is_mime_type = is_mime_type;
9734 iface->is_directory = is_directory;
9735
9736 iface->add_emblem = add_emblem;
9737 iface->get_string_attribute = get_string_attribute;
9738 iface->add_string_attribute = add_string_attribute;
9739 iface->invalidate_extension_info = invalidate_extension_info;
9740
9741 iface->get_activation_uri = get_activation_uri;
9742
9743 iface->get_file_type = get_file_type;
9744 iface->get_location = get_location;
9745 iface->get_parent_location = get_parent_location;
9746 iface->get_parent_info = get_parent_info;
9747 iface->get_mount = get_mount;
9748 iface->can_write = can_write;
9749 }
9750
9751 #if !defined (NAUTILUS_OMIT_SELF_CHECK)
9752
9753 void
nautilus_self_check_file(void)9754 nautilus_self_check_file (void)
9755 {
9756 NautilusFile *file_1;
9757 NautilusFile *file_2;
9758 GList *list;
9759
9760 /* refcount checks */
9761
9762 EEL_CHECK_INTEGER_RESULT (nautilus_directory_number_outstanding (), 0);
9763
9764 file_1 = nautilus_file_get_by_uri ("file:///home/");
9765
9766 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1);
9767 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1->details->directory)->ref_count, 1);
9768 EEL_CHECK_INTEGER_RESULT (nautilus_directory_number_outstanding (), 1);
9769
9770 nautilus_file_unref (file_1);
9771
9772 EEL_CHECK_INTEGER_RESULT (nautilus_directory_number_outstanding (), 0);
9773
9774 file_1 = nautilus_file_get_by_uri ("file:///etc");
9775 file_2 = nautilus_file_get_by_uri ("file:///usr");
9776
9777 list = NULL;
9778 list = g_list_prepend (list, file_1);
9779 list = g_list_prepend (list, file_2);
9780
9781 nautilus_file_list_ref (list);
9782
9783 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 2);
9784 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 2);
9785
9786 nautilus_file_list_unref (list);
9787
9788 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1);
9789 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 1);
9790
9791 nautilus_file_list_free (list);
9792
9793 EEL_CHECK_INTEGER_RESULT (nautilus_directory_number_outstanding (), 0);
9794
9795
9796 /* name checks */
9797 file_1 = nautilus_file_get_by_uri ("file:///home/");
9798
9799 EEL_CHECK_STRING_RESULT (nautilus_file_get_name (file_1), "home");
9800
9801 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_get_by_uri ("file:///home/") == file_1, TRUE);
9802 nautilus_file_unref (file_1);
9803
9804 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_get_by_uri ("file:///home") == file_1, TRUE);
9805 nautilus_file_unref (file_1);
9806
9807 nautilus_file_unref (file_1);
9808
9809 file_1 = nautilus_file_get_by_uri ("file:///home");
9810 EEL_CHECK_STRING_RESULT (nautilus_file_get_name (file_1), "home");
9811 nautilus_file_unref (file_1);
9812
9813 /* sorting */
9814 file_1 = nautilus_file_get_by_uri ("file:///etc");
9815 file_2 = nautilus_file_get_by_uri ("file:///usr");
9816
9817 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1);
9818 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 1);
9819
9820 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1, file_2, NAUTILUS_FILE_SORT_BY_DISPLAY_NAME, FALSE, FALSE) < 0, TRUE);
9821 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1, file_2, NAUTILUS_FILE_SORT_BY_DISPLAY_NAME, FALSE, TRUE) > 0, TRUE);
9822 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1, file_1, NAUTILUS_FILE_SORT_BY_DISPLAY_NAME, FALSE, FALSE) == 0, TRUE);
9823 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1, file_1, NAUTILUS_FILE_SORT_BY_DISPLAY_NAME, TRUE, FALSE) == 0, TRUE);
9824 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1, file_1, NAUTILUS_FILE_SORT_BY_DISPLAY_NAME, FALSE, TRUE) == 0, TRUE);
9825 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1, file_1, NAUTILUS_FILE_SORT_BY_DISPLAY_NAME, TRUE, TRUE) == 0, TRUE);
9826
9827 nautilus_file_unref (file_1);
9828 nautilus_file_unref (file_2);
9829 }
9830
9831 #endif /* !NAUTILUS_OMIT_SELF_CHECK */
9832