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

No issues found

   1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
   2 
   3    nautilus-file.c: Nautilus file model.
   4  
   5    Copyright (C) 1999, 2000, 2001 Eazel, Inc.
   6   
   7    This program is free software; you can redistribute it and/or
   8    modify it under the terms of the GNU General Public License as
   9    published by the Free Software Foundation; either version 2 of the
  10    License, or (at your option) any later version.
  11   
  12    This program is distributed in the hope that it will be useful,
  13    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15    General Public License for more details.
  16   
  17    You should have received a copy of the GNU General Public
  18    License along with this program; if not, write to the
  19    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  20    Boston, MA 02111-1307, USA.
  21   
  22    Author: Darin Adler <darin@bentspoon.com>
  23 */
  24 
  25 #include <config.h>
  26 #include "nautilus-file.h"
  27 
  28 #include "nautilus-directory-notify.h"
  29 #include "nautilus-directory-private.h"
  30 #include "nautilus-signaller.h"
  31 #include "nautilus-desktop-directory.h"
  32 #include "nautilus-desktop-directory-file.h"
  33 #include "nautilus-desktop-icon-file.h"
  34 #include "nautilus-file-attributes.h"
  35 #include "nautilus-file-private.h"
  36 #include "nautilus-file-operations.h"
  37 #include "nautilus-file-utilities.h"
  38 #include "nautilus-global-preferences.h"
  39 #include "nautilus-lib-self-check-functions.h"
  40 #include "nautilus-link.h"
  41 #include "nautilus-metadata.h"
  42 #include "nautilus-module.h"
  43 #include "nautilus-search-directory.h"
  44 #include "nautilus-search-directory-file.h"
  45 #include "nautilus-thumbnails.h"
  46 #include "nautilus-ui-utilities.h"
  47 #include "nautilus-vfs-file.h"
  48 #include "nautilus-file-undo-operations.h"
  49 #include "nautilus-file-undo-manager.h"
  50 #include <eel/eel-debug.h>
  51 #include <eel/eel-glib-extensions.h>
  52 #include <eel/eel-gtk-extensions.h>
  53 #include <eel/eel-vfs-extensions.h>
  54 #include <eel/eel-string.h>
  55 #include <grp.h>
  56 #include <gtk/gtk.h>
  57 #include <glib/gi18n.h>
  58 #include <glib/gstdio.h>
  59 #include <gio/gio.h>
  60 #include <glib.h>
  61 #include <gdesktop-enums.h>
  62 #include <libnautilus-extension/nautilus-file-info.h>
  63 #include <libnautilus-extension/nautilus-extension-private.h>
  64 #include <libxml/parser.h>
  65 #include <pwd.h>
  66 #include <stdlib.h>
  67 #include <sys/time.h>
  68 #include <time.h>
  69 #include <unistd.h>
  70 #include <sys/stat.h>
  71 
  72 #ifdef HAVE_SELINUX
  73 #include <selinux/selinux.h>
  74 #endif
  75 
  76 #define DEBUG_FLAG NAUTILUS_DEBUG_FILE
  77 #include <libnautilus-private/nautilus-debug.h>
  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 /* Files that start with these characters sort after files that don't. */
  95 #define SORT_LAST_CHAR1 '.'
  96 #define SORT_LAST_CHAR2 '#'
  97 
  98 /* Name of Nautilus trash directories */
  99 #define TRASH_DIRECTORY_NAME ".Trash"
 100 
 101 #define METADATA_ID_IS_LIST_MASK (1<<31)
 102 
 103 typedef enum {
 104 	SHOW_HIDDEN = 1 << 0,
 105 } FilterOptions;
 106 
 107 typedef void (* ModifyListFunction) (GList **list, NautilusFile *file);
 108 
 109 enum {
 110 	CHANGED,
 111 	UPDATED_DEEP_COUNT_IN_PROGRESS,
 112 	LAST_SIGNAL
 113 };
 114 
 115 static guint signals[LAST_SIGNAL];
 116 
 117 static GHashTable *symbolic_links;
 118 
 119 static guint64 cached_thumbnail_limit;
 120 int cached_thumbnail_size;
 121 static NautilusSpeedTradeoffValue show_file_thumbs;
 122 
 123 static NautilusSpeedTradeoffValue show_directory_item_count;
 124 
 125 static GQuark attribute_name_q,
 126 	attribute_size_q,
 127 	attribute_type_q,
 128 	attribute_detailed_type_q,
 129 	attribute_modification_date_q,
 130 	attribute_date_modified_q,
 131 	attribute_date_modified_full_q,
 132 	attribute_accessed_date_q,
 133 	attribute_date_accessed_q,
 134 	attribute_date_accessed_full_q,
 135 	attribute_mime_type_q,
 136 	attribute_size_detail_q,
 137 	attribute_deep_size_q,
 138 	attribute_deep_file_count_q,
 139 	attribute_deep_directory_count_q,
 140 	attribute_deep_total_count_q,
 141 	attribute_search_relevance_q,
 142 	attribute_trashed_on_q,
 143 	attribute_trashed_on_full_q,
 144 	attribute_trash_orig_path_q,
 145 	attribute_permissions_q,
 146 	attribute_selinux_context_q,
 147 	attribute_octal_permissions_q,
 148 	attribute_owner_q,
 149 	attribute_group_q,
 150 	attribute_uri_q,
 151 	attribute_where_q,
 152 	attribute_link_target_q,
 153 	attribute_volume_q,
 154 	attribute_free_space_q;
 155 
 156 static void     nautilus_file_info_iface_init                (NautilusFileInfoIface *iface);
 157 static char *   nautilus_file_get_owner_as_string            (NautilusFile          *file,
 158 							      gboolean               include_real_name);
 159 static char *   nautilus_file_get_type_as_string             (NautilusFile          *file);
 160 static char *   nautilus_file_get_detailed_type_as_string    (NautilusFile          *file);
 161 static gboolean update_info_and_name                         (NautilusFile          *file,
 162 							      GFileInfo             *info);
 163 static const char * nautilus_file_peek_display_name (NautilusFile *file);
 164 static const char * nautilus_file_peek_display_name_collation_key (NautilusFile *file);
 165 static void file_mount_unmounted (GMount *mount,  gpointer data);
 166 static void metadata_hash_free (GHashTable *hash);
 167 
 168 G_DEFINE_TYPE_WITH_CODE (NautilusFile, nautilus_file, G_TYPE_OBJECT,
 169 			 G_IMPLEMENT_INTERFACE (NAUTILUS_TYPE_FILE_INFO,
 170 						nautilus_file_info_iface_init));
 171 
 172 static void
 173 nautilus_file_init (NautilusFile *file)
 174 {
 175 	file->details = G_TYPE_INSTANCE_GET_PRIVATE ((file), NAUTILUS_TYPE_FILE, NautilusFileDetails);
 176 
 177 	nautilus_file_clear_info (file);
 178 	nautilus_file_invalidate_extension_info_internal (file);
 179 
 180 	file->details->free_space = -1;
 181 }
 182 
 183 static GObject*
 184 nautilus_file_constructor (GType                  type,
 185 			   guint                  n_construct_properties,
 186 			   GObjectConstructParam *construct_params)
 187 {
 188   GObject *object;
 189   NautilusFile *file;
 190 
 191   object = (* G_OBJECT_CLASS (nautilus_file_parent_class)->constructor) (type,
 192 									 n_construct_properties,
 193 									 construct_params);
 194 
 195   file = NAUTILUS_FILE (object);
 196 
 197   /* Set to default type after full construction */
 198   if (NAUTILUS_FILE_GET_CLASS (file)->default_file_type != G_FILE_TYPE_UNKNOWN) {
 199 	  file->details->type = NAUTILUS_FILE_GET_CLASS (file)->default_file_type;
 200   }
 201   
 202   return object;
 203 }
 204 
 205 gboolean
 206 nautilus_file_set_display_name (NautilusFile *file,
 207 				const char *display_name,
 208 				const char *edit_name,
 209 				gboolean custom)
 210 {
 211 	gboolean changed;
 212 
 213 	if (custom && display_name == NULL) {
 214 		/* We're re-setting a custom display name, invalidate it if
 215 		   we already set it so that the old one is re-read */
 216 		if (file->details->got_custom_display_name) {
 217 			file->details->got_custom_display_name = FALSE;
 218 			nautilus_file_invalidate_attributes (file,
 219 							     NAUTILUS_FILE_ATTRIBUTE_INFO);
 220 		}
 221 		return FALSE;
 222 	}
 223 	
 224 	if (display_name == NULL || *display_name == 0) {
 225 		return FALSE;
 226 	}
 227 	
 228 	if (!custom && file->details->got_custom_display_name) {
 229 		return FALSE;
 230 	}
 231 
 232 	if (edit_name == NULL) {
 233 		edit_name = display_name;
 234 	}
 235 	    
 236 	changed = FALSE;
 237 	
 238 	if (g_strcmp0 (eel_ref_str_peek (file->details->display_name), display_name) != 0) {
 239 		changed = TRUE;
 240 		
 241 		eel_ref_str_unref (file->details->display_name);
 242 		
 243 		if (g_strcmp0 (eel_ref_str_peek (file->details->name), display_name) == 0) {
 244 			file->details->display_name = eel_ref_str_ref (file->details->name);
 245 		} else {
 246 			file->details->display_name = eel_ref_str_new (display_name);
 247 		}
 248 		
 249 		g_free (file->details->display_name_collation_key);
 250 		file->details->display_name_collation_key = g_utf8_collate_key_for_filename (display_name, -1);
 251 	}
 252 
 253 	if (g_strcmp0 (eel_ref_str_peek (file->details->edit_name), edit_name) != 0) {
 254 		changed = TRUE;
 255 		
 256 		eel_ref_str_unref (file->details->edit_name);
 257 		if (g_strcmp0 (eel_ref_str_peek (file->details->display_name), edit_name) == 0) {
 258 			file->details->edit_name = eel_ref_str_ref (file->details->display_name);
 259 		} else {
 260 			file->details->edit_name = eel_ref_str_new (edit_name);
 261 		}
 262 	}
 263 	
 264 	file->details->got_custom_display_name = custom;
 265 	return changed;
 266 }
 267 
 268 static void
 269 nautilus_file_clear_display_name (NautilusFile *file)
 270 {
 271 	eel_ref_str_unref (file->details->display_name);
 272 	file->details->display_name = NULL;
 273 	g_free (file->details->display_name_collation_key);
 274 	file->details->display_name_collation_key = NULL;
 275 	eel_ref_str_unref (file->details->edit_name);
 276 	file->details->edit_name = NULL;
 277 }
 278 
 279 static gboolean
 280 foreach_metadata_free (gpointer  key,
 281 		       gpointer  value,
 282 		       gpointer  user_data)
 283 {
 284 	guint id;
 285 
 286 	id = GPOINTER_TO_UINT (key);
 287 
 288 	if (id & METADATA_ID_IS_LIST_MASK) {
 289 		g_strfreev ((char **)value);
 290 	} else {
 291 		g_free ((char *)value);
 292 	}
 293 	return TRUE;
 294 }
 295 
 296 
 297 static void
 298 metadata_hash_free (GHashTable *hash)
 299 {
 300 	g_hash_table_foreach_remove (hash,
 301 				     foreach_metadata_free,
 302 				     NULL);
 303 	g_hash_table_destroy (hash);
 304 }
 305 
 306 static gboolean
 307 metadata_hash_equal (GHashTable *hash1,
 308 		     GHashTable *hash2)
 309 {
 310 	GHashTableIter iter;
 311 	gpointer key1, value1, value2;
 312 	guint id;
 313 
 314 	if (hash1 == NULL && hash2 == NULL) {
 315 		return TRUE;
 316 	}
 317 
 318 	if (hash1 == NULL || hash2 == NULL) {
 319 		return FALSE;
 320 	}
 321 
 322 	if (g_hash_table_size (hash1) !=
 323 	    g_hash_table_size (hash2)) {
 324 		return FALSE;
 325 	}
 326 
 327 	g_hash_table_iter_init (&iter, hash1);
 328 	while (g_hash_table_iter_next (&iter, &key1, &value1)) {
 329 		value2 = g_hash_table_lookup (hash2, key1);
 330 		if (value2 == NULL) {
 331 			return FALSE;
 332 		}
 333 		id = GPOINTER_TO_UINT (key1);
 334 		if (id & METADATA_ID_IS_LIST_MASK) {
 335 			if (!eel_g_strv_equal ((char **)value1, (char **)value2)) {
 336 				return FALSE;
 337 			}
 338 		} else {
 339 			if (strcmp ((char *)value1, (char *)value2) != 0) {
 340 				return FALSE;
 341 			}
 342 		}
 343 	}
 344 
 345 	return TRUE;
 346 }
 347 
 348 static void
 349 clear_metadata (NautilusFile *file)
 350 {
 351 	if (file->details->metadata) {
 352 		metadata_hash_free (file->details->metadata);
 353 		file->details->metadata = NULL;
 354 	}
 355 }
 356 
 357 static GHashTable *
 358 get_metadata_from_info (GFileInfo *info)
 359 {
 360 	GHashTable *metadata;
 361 	char **attrs;
 362 	guint id;
 363 	int i;
 364 	GFileAttributeType type;
 365 	gpointer value;
 366 
 367 	attrs = g_file_info_list_attributes (info, "metadata");
 368 
 369 	metadata = g_hash_table_new (NULL, NULL);
 370 
 371 	for (i = 0; attrs[i] != NULL; i++) {
 372 		id = nautilus_metadata_get_id (attrs[i] + strlen ("metadata::"));
 373 		if (id == 0) {
 374 			continue;
 375 		}
 376 
 377 		if (!g_file_info_get_attribute_data (info, attrs[i],
 378 						     &type, &value, NULL)) {
 379 			continue;
 380 		}
 381 
 382 		if (type == G_FILE_ATTRIBUTE_TYPE_STRING) {
 383 			g_hash_table_insert (metadata, GUINT_TO_POINTER (id),
 384 					     g_strdup ((char *)value));
 385 		} else if (type == G_FILE_ATTRIBUTE_TYPE_STRINGV) {
 386 			id |= METADATA_ID_IS_LIST_MASK;
 387 			g_hash_table_insert (metadata, GUINT_TO_POINTER (id),
 388 					     g_strdupv ((char **)value));
 389 		}
 390 	}
 391 
 392 	g_strfreev (attrs);
 393 
 394 	return metadata;
 395 }
 396 
 397 gboolean
 398 nautilus_file_update_metadata_from_info (NautilusFile *file,
 399 					 GFileInfo *info)
 400 {
 401 	gboolean changed = FALSE;
 402 
 403 	if (g_file_info_has_namespace (info, "metadata")) {
 404 		GHashTable *metadata;
 405 
 406 		metadata = get_metadata_from_info (info);
 407 		if (!metadata_hash_equal (metadata,
 408 					  file->details->metadata)) {
 409 			changed = TRUE;
 410 			clear_metadata (file);
 411 			file->details->metadata = metadata;
 412 		} else {
 413 			metadata_hash_free (metadata);
 414 		}
 415 	} else if (file->details->metadata) {
 416 		changed = TRUE;
 417 		clear_metadata (file);
 418 	}
 419 	return changed;
 420 }
 421 
 422 void
 423 nautilus_file_clear_info (NautilusFile *file)
 424 {
 425 	file->details->got_file_info = FALSE;
 426 	if (file->details->get_info_error) {
 427 		g_error_free (file->details->get_info_error);
 428 		file->details->get_info_error = NULL;
 429 	}
 430 	/* Reset to default type, which might be other than unknown for
 431 	   special kinds of files like the desktop or a search directory */
 432 	file->details->type = NAUTILUS_FILE_GET_CLASS (file)->default_file_type;
 433 
 434 	if (!file->details->got_custom_display_name) {
 435 		nautilus_file_clear_display_name (file);
 436 	}
 437 
 438 	if (!file->details->got_custom_activation_uri &&
 439 	    file->details->activation_uri != NULL) {
 440 		g_free (file->details->activation_uri);
 441 		file->details->activation_uri = NULL;
 442 	}
 443 	
 444 	if (file->details->icon != NULL) {
 445 		g_object_unref (file->details->icon);
 446 		file->details->icon = NULL;
 447 	}
 448 
 449 	g_free (file->details->thumbnail_path);
 450 	file->details->thumbnail_path = NULL;
 451 	file->details->thumbnailing_failed = FALSE;
 452 	
 453 	file->details->is_launcher = FALSE;
 454 	file->details->is_foreign_link = FALSE;
 455 	file->details->is_trusted_link = FALSE;
 456 	file->details->is_symlink = FALSE;
 457 	file->details->is_hidden = FALSE;
 458 	file->details->is_mountpoint = FALSE;
 459 	file->details->uid = -1;
 460 	file->details->gid = -1;
 461 	file->details->can_read = TRUE;
 462 	file->details->can_write = TRUE;
 463 	file->details->can_execute = TRUE;
 464 	file->details->can_delete = TRUE;
 465 	file->details->can_trash = TRUE;
 466 	file->details->can_rename = TRUE;
 467 	file->details->can_mount = FALSE;
 468 	file->details->can_unmount = FALSE;
 469 	file->details->can_eject = FALSE;
 470 	file->details->can_start = FALSE;
 471 	file->details->can_start_degraded = FALSE;
 472 	file->details->can_stop = FALSE;
 473 	file->details->start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
 474 	file->details->can_poll_for_media = FALSE;
 475 	file->details->is_media_check_automatic = FALSE;
 476 	file->details->has_permissions = FALSE;
 477 	file->details->permissions = 0;
 478 	file->details->size = -1;
 479 	file->details->sort_order = 0;
 480 	file->details->mtime = 0;
 481 	file->details->atime = 0;
 482 	file->details->trash_time = 0;
 483 	g_free (file->details->symlink_name);
 484 	file->details->symlink_name = NULL;
 485 	eel_ref_str_unref (file->details->mime_type);
 486 	file->details->mime_type = NULL;
 487 	g_free (file->details->selinux_context);
 488 	file->details->selinux_context = NULL;
 489 	g_free (file->details->description);
 490 	file->details->description = NULL;
 491 	eel_ref_str_unref (file->details->owner);
 492 	file->details->owner = NULL;
 493 	eel_ref_str_unref (file->details->owner_real);
 494 	file->details->owner_real = NULL;
 495 	eel_ref_str_unref (file->details->group);
 496 	file->details->group = NULL;
 497 
 498 	eel_ref_str_unref (file->details->filesystem_id);
 499 	file->details->filesystem_id = NULL;
 500 
 501 	clear_metadata (file);
 502 }
 503 
 504 static NautilusFile *
 505 nautilus_file_new_from_filename (NautilusDirectory *directory,
 506 				 const char *filename,
 507 				 gboolean self_owned)
 508 {
 509 	NautilusFile *file;
 510 
 511 	g_assert (NAUTILUS_IS_DIRECTORY (directory));
 512 	g_assert (filename != NULL);
 513 	g_assert (filename[0] != '\0');
 514 
 515 	if (NAUTILUS_IS_DESKTOP_DIRECTORY (directory)) {
 516 		if (self_owned) {
 517 			file = NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_DESKTOP_DIRECTORY_FILE, NULL));
 518 		} else {
 519 			/* This doesn't normally happen, unless the user somehow types in a uri
 520 			 * that references a file like this. (See #349840) */
 521 			file = NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_VFS_FILE, NULL));
 522 		}
 523 	} else if (NAUTILUS_IS_SEARCH_DIRECTORY (directory)) {
 524 		if (self_owned) {
 525 			file = NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_SEARCH_DIRECTORY_FILE, NULL));
 526 		} else {
 527 			/* This doesn't normally happen, unless the user somehow types in a uri
 528 			 * that references a file like this. (See #349840) */
 529 			file = NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_VFS_FILE, NULL));
 530 		}
 531 	} else {
 532 		file = NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_VFS_FILE, NULL));
 533 	}
 534 
 535 	file->details->directory = nautilus_directory_ref (directory);
 536 
 537 	file->details->name = eel_ref_str_new (filename);
 538 
 539 #ifdef NAUTILUS_FILE_DEBUG_REF
 540 	DEBUG_REF_PRINTF("%10p ref'd", file);
 541 #endif
 542 
 543 	return file;
 544 }
 545 
 546 static void
 547 modify_link_hash_table (NautilusFile *file,
 548 			ModifyListFunction modify_function)
 549 {
 550 	char *target_uri;
 551 	gboolean found;
 552 	gpointer original_key;
 553 	GList **list_ptr;
 554 
 555 	/* Check if there is a symlink name. If none, we are OK. */
 556 	if (file->details->symlink_name == NULL) {
 557 		return;
 558 	}
 559 
 560 	/* Create the hash table first time through. */
 561 	if (symbolic_links == NULL) {
 562 		symbolic_links = g_hash_table_new (g_str_hash, g_str_equal);
 563 	}
 564 
 565 	target_uri = nautilus_file_get_symbolic_link_target_uri (file);
 566 	
 567 	/* Find the old contents of the hash table. */
 568 	found = g_hash_table_lookup_extended
 569 		(symbolic_links, target_uri,
 570 		 &original_key, (gpointer *)&list_ptr);
 571 	if (!found) {
 572 		list_ptr = g_new0 (GList *, 1);
 573 		original_key = g_strdup (target_uri);
 574 		g_hash_table_insert (symbolic_links, original_key, list_ptr);
 575 	}
 576 	(* modify_function) (list_ptr, file);
 577 	if (*list_ptr == NULL) {
 578 		g_hash_table_remove (symbolic_links, target_uri);
 579 		g_free (list_ptr);
 580 		g_free (original_key);
 581 	}
 582 	g_free (target_uri);
 583 }
 584 
 585 static void
 586 symbolic_link_weak_notify (gpointer      data,
 587 			   GObject      *where_the_object_was)
 588 {
 589 	GList **list = data;
 590 	/* This really shouldn't happen, but we're seeing some strange things in
 591 	   bug #358172 where the symlink hashtable isn't correctly updated. */
 592 	*list = g_list_remove (*list, where_the_object_was);
 593 }
 594 
 595 static void
 596 add_to_link_hash_table_list (GList **list, NautilusFile *file)
 597 {
 598 	if (g_list_find (*list, file) != NULL) {
 599 		g_warning ("Adding file to symlink_table multiple times. "
 600 			   "Please add feedback of what you were doing at http://bugzilla.gnome.org/show_bug.cgi?id=358172\n");
 601 		return;
 602 	}
 603 	g_object_weak_ref (G_OBJECT (file), symbolic_link_weak_notify, list);
 604 	*list = g_list_prepend (*list, file); 
 605 }
 606 
 607 static void
 608 add_to_link_hash_table (NautilusFile *file)
 609 {
 610 	modify_link_hash_table (file, add_to_link_hash_table_list);
 611 }
 612 
 613 static void
 614 remove_from_link_hash_table_list (GList **list, NautilusFile *file)
 615 {
 616 	if (g_list_find (*list, file) != NULL) {
 617 		g_object_weak_unref (G_OBJECT (file), symbolic_link_weak_notify, list);
 618 		*list = g_list_remove (*list, file);
 619 	}
 620 }
 621 
 622 static void
 623 remove_from_link_hash_table (NautilusFile *file)
 624 {
 625 	modify_link_hash_table (file, remove_from_link_hash_table_list);
 626 }
 627 
 628 NautilusFile *
 629 nautilus_file_new_from_info (NautilusDirectory *directory,
 630 			     GFileInfo *info)
 631 {
 632 	NautilusFile *file;
 633 
 634 	g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL);
 635 	g_return_val_if_fail (info != NULL, NULL);
 636 
 637 	file = NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_VFS_FILE, NULL));
 638 	file->details->directory = nautilus_directory_ref (directory);
 639 
 640 	update_info_and_name (file, info);
 641 
 642 #ifdef NAUTILUS_FILE_DEBUG_REF
 643 	DEBUG_REF_PRINTF("%10p ref'd", file);
 644 #endif
 645 
 646 	return file;
 647 }
 648 
 649 static NautilusFile *
 650 nautilus_file_get_internal (GFile *location, gboolean create)
 651 {
 652 	gboolean self_owned;
 653 	NautilusDirectory *directory;
 654 	NautilusFile *file;
 655 	GFile *parent;
 656 	char *basename;
 657 
 658 	g_assert (location != NULL);
 659 
 660 	parent = g_file_get_parent (location);
 661 	
 662 	self_owned = FALSE;
 663 	if (parent == NULL) {
 664 		self_owned = TRUE;
 665 		parent = g_object_ref (location);
 666 	} 
 667 
 668 	/* Get object that represents the directory. */
 669 	directory = nautilus_directory_get_internal (parent, create);
 670 
 671 	g_object_unref (parent);
 672 
 673 	/* Get the name for the file. */
 674 	if (self_owned && directory != NULL) {
 675 		basename = nautilus_directory_get_name_for_self_as_new_file (directory);
 676 	} else {
 677 		basename = g_file_get_basename (location);
 678 	}
 679 	/* Check to see if it's a file that's already known. */
 680 	if (directory == NULL) {
 681 		file = NULL;
 682 	} else if (self_owned) {
 683 		file = directory->details->as_file;
 684 	} else {
 685 		file = nautilus_directory_find_file_by_name (directory, basename);
 686 	}
 687 
 688 	/* Ref or create the file. */
 689 	if (file != NULL) {
 690 		nautilus_file_ref (file);
 691 	} else if (create) {
 692 		file = nautilus_file_new_from_filename (directory, basename, self_owned);
 693 		if (self_owned) {
 694 			g_assert (directory->details->as_file == NULL);
 695 			directory->details->as_file = file;
 696 		} else {
 697 			nautilus_directory_add_file (directory, file);
 698 		}
 699 	}
 700 
 701 	g_free (basename);
 702 	nautilus_directory_unref (directory);
 703 
 704 	return file;
 705 }
 706 
 707 NautilusFile *
 708 nautilus_file_get (GFile *location)
 709 {
 710 	return nautilus_file_get_internal (location, TRUE);
 711 }
 712 
 713 NautilusFile *
 714 nautilus_file_get_existing (GFile *location)
 715 {
 716 	return nautilus_file_get_internal (location, FALSE);
 717 }
 718 
 719 NautilusFile *
 720 nautilus_file_get_existing_by_uri (const char *uri)
 721 {
 722 	GFile *location;
 723 	NautilusFile *file;
 724 	
 725 	location = g_file_new_for_uri (uri);
 726 	file = nautilus_file_get_internal (location, FALSE);
 727 	g_object_unref (location);
 728 	
 729 	return file;
 730 }
 731 
 732 NautilusFile *
 733 nautilus_file_get_by_uri (const char *uri)
 734 {
 735 	GFile *location;
 736 	NautilusFile *file;
 737 	
 738 	location = g_file_new_for_uri (uri);
 739 	file = nautilus_file_get_internal (location, TRUE);
 740 	g_object_unref (location);
 741 	
 742 	return file;
 743 }
 744 
 745 gboolean
 746 nautilus_file_is_self_owned (NautilusFile *file)
 747 {
 748 	return file->details->directory->details->as_file == file;
 749 }
 750 
 751 static void
 752 finalize (GObject *object)
 753 {
 754 	NautilusDirectory *directory;
 755 	NautilusFile *file;
 756 	char *uri;
 757 
 758 	file = NAUTILUS_FILE (object);
 759 
 760 	g_assert (file->details->operations_in_progress == NULL);
 761 
 762 	if (file->details->is_thumbnailing) {
 763 		uri = nautilus_file_get_uri (file);
 764 		nautilus_thumbnail_remove_from_queue (uri);
 765 		g_free (uri);
 766 	}
 767 	
 768 	nautilus_async_destroying_file (file);
 769 
 770 	remove_from_link_hash_table (file);
 771 
 772 	directory = file->details->directory;
 773 	
 774 	if (nautilus_file_is_self_owned (file)) {
 775 		directory->details->as_file = NULL;
 776 	} else {
 777 		if (!file->details->is_gone) {
 778 			nautilus_directory_remove_file (directory, file);
 779 		}
 780 	}
 781 
 782 	if (file->details->get_info_error) {
 783 		g_error_free (file->details->get_info_error);
 784 	}
 785 
 786 	nautilus_directory_unref (directory);
 787 	eel_ref_str_unref (file->details->name);
 788 	eel_ref_str_unref (file->details->display_name);
 789 	g_free (file->details->display_name_collation_key);
 790 	eel_ref_str_unref (file->details->edit_name);
 791 	if (file->details->icon) {
 792 		g_object_unref (file->details->icon);
 793 	}
 794 	g_free (file->details->thumbnail_path);
 795 	g_free (file->details->symlink_name);
 796 	eel_ref_str_unref (file->details->mime_type);
 797 	eel_ref_str_unref (file->details->owner);
 798 	eel_ref_str_unref (file->details->owner_real);
 799 	eel_ref_str_unref (file->details->group);
 800 	g_free (file->details->selinux_context);
 801 	g_free (file->details->description);
 802 	g_free (file->details->top_left_text);
 803 	g_free (file->details->activation_uri);
 804 	g_clear_object (&file->details->custom_icon);
 805 
 806 	if (file->details->thumbnail) {
 807 		g_object_unref (file->details->thumbnail);
 808 	}
 809 	if (file->details->mount) {
 810 		g_signal_handlers_disconnect_by_func (file->details->mount, file_mount_unmounted, file);
 811 		g_object_unref (file->details->mount);
 812 	}
 813 
 814 	eel_ref_str_unref (file->details->filesystem_id);
 815 	g_free (file->details->trash_orig_path);
 816 
 817 	g_list_free_full (file->details->mime_list, g_free);
 818 	g_list_free_full (file->details->pending_extension_emblems, g_free);
 819 	g_list_free_full (file->details->extension_emblems, g_free);
 820 	g_list_free_full (file->details->pending_info_providers, g_object_unref);
 821 
 822 	if (file->details->pending_extension_attributes) {
 823 		g_hash_table_destroy (file->details->pending_extension_attributes);
 824 	}
 825 	
 826 	if (file->details->extension_attributes) {
 827 		g_hash_table_destroy (file->details->extension_attributes);
 828 	}
 829 
 830 	if (file->details->metadata) {
 831 		metadata_hash_free (file->details->metadata);
 832 	}
 833 
 834 	G_OBJECT_CLASS (nautilus_file_parent_class)->finalize (object);
 835 }
 836 
 837 NautilusFile *
 838 nautilus_file_ref (NautilusFile *file)
 839 {
 840 	if (file == NULL) {
 841 		return NULL;
 842 	}
 843 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
 844 
 845 #ifdef NAUTILUS_FILE_DEBUG_REF
 846 	DEBUG_REF_PRINTF("%10p ref'd", file);
 847 #endif
 848 	
 849 	return g_object_ref (file);
 850 }
 851 
 852 void
 853 nautilus_file_unref (NautilusFile *file)
 854 {
 855 	if (file == NULL) {
 856 		return;
 857 	}
 858 
 859 	g_return_if_fail (NAUTILUS_IS_FILE (file));
 860 
 861 #ifdef NAUTILUS_FILE_DEBUG_REF
 862 	DEBUG_REF_PRINTF("%10p unref'd", file);
 863 #endif
 864 	
 865 	g_object_unref (file);
 866 }
 867 
 868 /**
 869  * nautilus_file_get_parent_uri_for_display:
 870  * 
 871  * Get the uri for the parent directory.
 872  * 
 873  * @file: The file in question.
 874  * 
 875  * Return value: A string representing the parent's location,
 876  * formatted for user display (including stripping "file://").
 877  * If the parent is NULL, returns the empty string.
 878  */ 
 879 char *
 880 nautilus_file_get_parent_uri_for_display (NautilusFile *file) 
 881 {
 882 	GFile *parent;
 883 	char *result;
 884 
 885 	g_assert (NAUTILUS_IS_FILE (file));
 886 	
 887 	parent = nautilus_file_get_parent_location (file);
 888 	if (parent) {
 889 		result = g_file_get_parse_name (parent);
 890 		g_object_unref (parent);
 891 	} else {
 892 		result = g_strdup ("");
 893 	}
 894 
 895 	return result;
 896 }
 897 
 898 /**
 899  * nautilus_file_get_parent_uri:
 900  * 
 901  * Get the uri for the parent directory.
 902  * 
 903  * @file: The file in question.
 904  * 
 905  * Return value: A string for the parent's location, in "raw URI" form.
 906  * Use nautilus_file_get_parent_uri_for_display instead if the
 907  * result is to be displayed on-screen.
 908  * If the parent is NULL, returns the empty string.
 909  */ 
 910 char *
 911 nautilus_file_get_parent_uri (NautilusFile *file) 
 912 {
 913 	g_assert (NAUTILUS_IS_FILE (file));
 914 	
 915 	if (nautilus_file_is_self_owned (file)) {
 916 		/* Callers expect an empty string, not a NULL. */
 917 		return g_strdup ("");
 918 	}
 919 
 920 	return nautilus_directory_get_uri (file->details->directory);
 921 }
 922 
 923 GFile *
 924 nautilus_file_get_parent_location (NautilusFile *file) 
 925 {
 926 	g_assert (NAUTILUS_IS_FILE (file));
 927 	
 928 	if (nautilus_file_is_self_owned (file)) {
 929 		/* Callers expect an empty string, not a NULL. */
 930 		return NULL;
 931 	}
 932 
 933 	return nautilus_directory_get_location (file->details->directory);
 934 }
 935 
 936 NautilusFile *
 937 nautilus_file_get_parent (NautilusFile *file)
 938 {
 939 	g_assert (NAUTILUS_IS_FILE (file));
 940 	
 941 	if (nautilus_file_is_self_owned (file)) {
 942 		return NULL;
 943 	}
 944 
 945 	return nautilus_directory_get_corresponding_file (file->details->directory);
 946 }
 947 
 948 /**
 949  * nautilus_file_can_read:
 950  * 
 951  * Check whether the user is allowed to read the contents of this file.
 952  * 
 953  * @file: The file to check.
 954  * 
 955  * Return value: FALSE if the user is definitely not allowed to read
 956  * the contents of the file. If the user has read permission, or
 957  * the code can't tell whether the user has read permission,
 958  * returns TRUE (so failures must always be handled).
 959  */
 960 gboolean
 961 nautilus_file_can_read (NautilusFile *file)
 962 {
 963 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
 964 	
 965 	return file->details->can_read;
 966 }
 967 
 968 /**
 969  * nautilus_file_can_write:
 970  * 
 971  * Check whether the user is allowed to write to this file.
 972  * 
 973  * @file: The file to check.
 974  * 
 975  * Return value: FALSE if the user is definitely not allowed to write
 976  * to the file. If the user has write permission, or
 977  * the code can't tell whether the user has write permission,
 978  * returns TRUE (so failures must always be handled).
 979  */
 980 gboolean
 981 nautilus_file_can_write (NautilusFile *file)
 982 {
 983 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
 984 
 985 	return file->details->can_write;
 986 }
 987 
 988 /**
 989  * nautilus_file_can_execute:
 990  * 
 991  * Check whether the user is allowed to execute this file.
 992  * 
 993  * @file: The file to check.
 994  * 
 995  * Return value: FALSE if the user is definitely not allowed to execute
 996  * the file. If the user has execute permission, or
 997  * the code can't tell whether the user has execute permission,
 998  * returns TRUE (so failures must always be handled).
 999  */
1000 gboolean
1001 nautilus_file_can_execute (NautilusFile *file)
1002 {
1003 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1004 
1005 	return file->details->can_execute;
1006 }
1007 
1008 gboolean
1009 nautilus_file_can_mount (NautilusFile *file)
1010 {
1011 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1012 	
1013 	return file->details->can_mount;
1014 }
1015 	
1016 gboolean
1017 nautilus_file_can_unmount (NautilusFile *file)
1018 {
1019 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1020 
1021 	return file->details->can_unmount ||
1022 		(file->details->mount != NULL &&
1023 		 g_mount_can_unmount (file->details->mount));
1024 }
1025 	
1026 gboolean
1027 nautilus_file_can_eject (NautilusFile *file)
1028 {
1029 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1030 
1031 	return file->details->can_eject ||
1032 		(file->details->mount != NULL &&
1033 		 g_mount_can_eject (file->details->mount));
1034 }
1035 
1036 gboolean
1037 nautilus_file_can_start (NautilusFile *file)
1038 {
1039 	gboolean ret;
1040 	GDrive *drive;
1041 
1042 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1043 
1044 	ret = FALSE;
1045 
1046 	if (file->details->can_start) {
1047 		ret = TRUE;
1048 		goto out;
1049 	}
1050 
1051 	if (file->details->mount != NULL) {
1052 		drive = g_mount_get_drive (file->details->mount);
1053 		if (drive != NULL) {
1054 			ret = g_drive_can_start (drive);
1055 			g_object_unref (drive);
1056 		}
1057 	}
1058 
1059  out:
1060 	return ret;
1061 }
1062 
1063 gboolean
1064 nautilus_file_can_start_degraded (NautilusFile *file)
1065 {
1066 	gboolean ret;
1067 	GDrive *drive;
1068 
1069 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1070 
1071 	ret = FALSE;
1072 
1073 	if (file->details->can_start_degraded) {
1074 		ret = TRUE;
1075 		goto out;
1076 	}
1077 
1078 	if (file->details->mount != NULL) {
1079 		drive = g_mount_get_drive (file->details->mount);
1080 		if (drive != NULL) {
1081 			ret = g_drive_can_start_degraded (drive);
1082 			g_object_unref (drive);
1083 		}
1084 	}
1085 
1086  out:
1087 	return ret;
1088 }
1089 
1090 gboolean
1091 nautilus_file_can_poll_for_media (NautilusFile *file)
1092 {
1093 	gboolean ret;
1094 	GDrive *drive;
1095 
1096 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1097 
1098 	ret = FALSE;
1099 
1100 	if (file->details->can_poll_for_media) {
1101 		ret = TRUE;
1102 		goto out;
1103 	}
1104 
1105 	if (file->details->mount != NULL) {
1106 		drive = g_mount_get_drive (file->details->mount);
1107 		if (drive != NULL) {
1108 			ret = g_drive_can_poll_for_media (drive);
1109 			g_object_unref (drive);
1110 		}
1111 	}
1112 
1113  out:
1114 	return ret;
1115 }
1116 
1117 gboolean
1118 nautilus_file_is_media_check_automatic (NautilusFile *file)
1119 {
1120 	gboolean ret;
1121 	GDrive *drive;
1122 
1123 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1124 
1125 	ret = FALSE;
1126 
1127 	if (file->details->is_media_check_automatic) {
1128 		ret = TRUE;
1129 		goto out;
1130 	}
1131 
1132 	if (file->details->mount != NULL) {
1133 		drive = g_mount_get_drive (file->details->mount);
1134 		if (drive != NULL) {
1135 			ret = g_drive_is_media_check_automatic (drive);
1136 			g_object_unref (drive);
1137 		}
1138 	}
1139 
1140  out:
1141 	return ret;
1142 }
1143 
1144 
1145 gboolean
1146 nautilus_file_can_stop (NautilusFile *file)
1147 {
1148 	gboolean ret;
1149 	GDrive *drive;
1150 
1151 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1152 
1153 	ret = FALSE;
1154 
1155 	if (file->details->can_stop) {
1156 		ret = TRUE;
1157 		goto out;
1158 	}
1159 
1160 	if (file->details->mount != NULL) {
1161 		drive = g_mount_get_drive (file->details->mount);
1162 		if (drive != NULL) {
1163 			ret = g_drive_can_stop (drive);
1164 			g_object_unref (drive);
1165 		}
1166 	}
1167 
1168  out:
1169 	return ret;
1170 }
1171 
1172 GDriveStartStopType
1173 nautilus_file_get_start_stop_type (NautilusFile *file)
1174 {
1175 	GDriveStartStopType ret;
1176 	GDrive *drive;
1177 
1178 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1179 
1180 	ret = file->details->start_stop_type;
1181 	if (ret != G_DRIVE_START_STOP_TYPE_UNKNOWN)
1182 		goto out;
1183 
1184 	if (file->details->mount != NULL) {
1185 		drive = g_mount_get_drive (file->details->mount);
1186 		if (drive != NULL) {
1187 			ret = g_drive_get_start_stop_type (drive);
1188 			g_object_unref (drive);
1189 		}
1190 	}
1191 
1192  out:
1193 	return ret;
1194 }
1195 
1196 void
1197 nautilus_file_mount (NautilusFile                   *file,
1198 		     GMountOperation                *mount_op,
1199 		     GCancellable                   *cancellable,
1200 		     NautilusFileOperationCallback   callback,
1201 		     gpointer                        callback_data)
1202 {
1203 	GError *error;
1204 	
1205 	if (NAUTILUS_FILE_GET_CLASS (file)->mount == NULL) {
1206 		if (callback) {
1207 			error = NULL;
1208 			g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
1209                                              _("This file cannot be mounted"));
1210 			callback (file, NULL, error, callback_data);
1211 			g_error_free (error);
1212 		}
1213 	} else {
1214 		NAUTILUS_FILE_GET_CLASS (file)->mount (file, mount_op, cancellable, callback, callback_data);
1215 	}
1216 }
1217 
1218 typedef struct {
1219 	NautilusFile *file;
1220 	NautilusFileOperationCallback callback;
1221 	gpointer callback_data;
1222 } UnmountData;
1223 
1224 static void
1225 unmount_done (void *callback_data)
1226 {
1227 	UnmountData *data;
1228 
1229 	data = (UnmountData *)callback_data;
1230 	if (data->callback) {
1231 		data->callback (data->file, NULL, NULL, data->callback_data);
1232 	}
1233 	nautilus_file_unref (data->file);
1234 	g_free (data);
1235 }
1236 
1237 void
1238 nautilus_file_unmount (NautilusFile                   *file,
1239 		       GMountOperation                *mount_op,
1240 		       GCancellable                   *cancellable,
1241 		       NautilusFileOperationCallback   callback,
1242 		       gpointer                        callback_data)
1243 {
1244 	GError *error;
1245 	UnmountData *data;
1246 
1247 	if (file->details->can_unmount) {
1248 		if (NAUTILUS_FILE_GET_CLASS (file)->unmount != NULL) {
1249 			NAUTILUS_FILE_GET_CLASS (file)->unmount (file, mount_op, cancellable, callback, callback_data);
1250 		} else {
1251 			if (callback) {
1252 				error = NULL;
1253 				g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
1254 						     _("This file cannot be unmounted"));
1255 				callback (file, NULL, error, callback_data);
1256 				g_error_free (error);
1257 			}
1258 		}
1259 	} else if (file->details->mount != NULL &&
1260 		   g_mount_can_unmount (file->details->mount)) {
1261 		data = g_new0 (UnmountData, 1);
1262 		data->file = nautilus_file_ref (file);
1263 		data->callback = callback;
1264 		data->callback_data = callback_data;
1265 		nautilus_file_operations_unmount_mount_full (NULL, file->details->mount, NULL, FALSE, TRUE, unmount_done, data);
1266 	} else if (callback) {
1267 		callback (file, NULL, NULL, callback_data);
1268 	}
1269 }
1270 
1271 void
1272 nautilus_file_eject (NautilusFile                   *file,
1273 		     GMountOperation                *mount_op,
1274 		     GCancellable                   *cancellable,
1275 		     NautilusFileOperationCallback   callback,
1276 		     gpointer                        callback_data)
1277 {
1278 	GError *error;
1279 	UnmountData *data;
1280 
1281 	if (file->details->can_eject) {
1282 		if (NAUTILUS_FILE_GET_CLASS (file)->eject != NULL) {
1283 			NAUTILUS_FILE_GET_CLASS (file)->eject (file, mount_op, cancellable, callback, callback_data);
1284 		} else {
1285 			if (callback) {
1286 				error = NULL;
1287 				g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
1288 						     _("This file cannot be ejected"));
1289 				callback (file, NULL, error, callback_data);
1290 				g_error_free (error);
1291 			}
1292 		}
1293 	} else if (file->details->mount != NULL &&
1294 		   g_mount_can_eject (file->details->mount)) {
1295 		data = g_new0 (UnmountData, 1);
1296 		data->file = nautilus_file_ref (file);
1297 		data->callback = callback;
1298 		data->callback_data = callback_data;
1299 		nautilus_file_operations_unmount_mount_full (NULL, file->details->mount, NULL, TRUE, TRUE, unmount_done, data);
1300 	} else if (callback) {
1301 		callback (file, NULL, NULL, callback_data);
1302 	}
1303 }
1304 
1305 void
1306 nautilus_file_start (NautilusFile                   *file,
1307 		     GMountOperation                *start_op,
1308 		     GCancellable                   *cancellable,
1309 		     NautilusFileOperationCallback   callback,
1310 		     gpointer                        callback_data)
1311 {
1312 	GError *error;
1313 
1314 	if ((file->details->can_start || file->details->can_start_degraded) &&
1315 	    NAUTILUS_FILE_GET_CLASS (file)->start != NULL) {
1316 		NAUTILUS_FILE_GET_CLASS (file)->start (file, start_op, cancellable, callback, callback_data);
1317 	} else {
1318 		if (callback) {
1319 			error = NULL;
1320 			g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
1321                                              _("This file cannot be started"));
1322 			callback (file, NULL, error, callback_data);
1323 			g_error_free (error);
1324 		}
1325 	}
1326 }
1327 
1328 static void
1329 file_stop_callback (GObject *source_object,
1330 		    GAsyncResult *res,
1331 		    gpointer callback_data)
1332 {
1333 	NautilusFileOperation *op;
1334 	gboolean stopped;
1335 	GError *error;
1336 
1337 	op = callback_data;
1338 
1339 	error = NULL;
1340 	stopped = g_drive_stop_finish (G_DRIVE (source_object),
1341 				       res, &error);
1342 
1343 	if (!stopped &&
1344 	    error->domain == G_IO_ERROR &&
1345 	    (error->code == G_IO_ERROR_FAILED_HANDLED ||
1346 	     error->code == G_IO_ERROR_CANCELLED)) {
1347 		g_error_free (error);
1348 		error = NULL;
1349 	}
1350 
1351 	nautilus_file_operation_complete (op, NULL, error);
1352 	if (error) {
1353 		g_error_free (error);
1354 	}
1355 }
1356 
1357 void
1358 nautilus_file_stop (NautilusFile                   *file,
1359 		    GMountOperation                *mount_op,
1360 		    GCancellable                   *cancellable,
1361 		    NautilusFileOperationCallback   callback,
1362 		    gpointer                        callback_data)
1363 {
1364 	GError *error;
1365 
1366 	if (NAUTILUS_FILE_GET_CLASS (file)->stop != NULL) {
1367 		if (file->details->can_stop) {
1368 			NAUTILUS_FILE_GET_CLASS (file)->stop (file, mount_op, cancellable, callback, callback_data);
1369 		} else {
1370 			if (callback) {
1371 				error = NULL;
1372 				g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
1373 						     _("This file cannot be stopped"));
1374 				callback (file, NULL, error, callback_data);
1375 				g_error_free (error);
1376 			}
1377 		}
1378 	} else {
1379 		GDrive *drive;
1380 
1381 		drive = NULL;
1382 		if (file->details->mount != NULL)
1383 			drive = g_mount_get_drive (file->details->mount);
1384 
1385 		if (drive != NULL && g_drive_can_stop (drive)) {
1386 			NautilusFileOperation *op;
1387 
1388 			op = nautilus_file_operation_new (file, callback, callback_data);
1389 			if (cancellable) {
1390 				g_object_unref (op->cancellable);
1391 				op->cancellable = g_object_ref (cancellable);
1392 			}
1393 
1394 			g_drive_stop (drive,
1395 				      G_MOUNT_UNMOUNT_NONE,
1396 				      mount_op,
1397 				      op->cancellable,
1398 				      file_stop_callback,
1399 				      op);
1400 		} else {
1401 			if (callback) {
1402 				error = NULL;
1403 				g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
1404 						     _("This file cannot be stopped"));
1405 				callback (file, NULL, error, callback_data);
1406 				g_error_free (error);
1407 			}
1408 		}
1409 
1410 		if (drive != NULL) {
1411 			g_object_unref (drive);
1412 		}
1413 	}
1414 }
1415 
1416 void
1417 nautilus_file_poll_for_media (NautilusFile *file)
1418 {
1419 	if (file->details->can_poll_for_media) {
1420 		if (NAUTILUS_FILE_GET_CLASS (file)->stop != NULL) {
1421 			NAUTILUS_FILE_GET_CLASS (file)->poll_for_media (file);
1422 		}
1423 	} else if (file->details->mount != NULL) {
1424 		GDrive *drive;
1425 		drive = g_mount_get_drive (file->details->mount);
1426 		if (drive != NULL) {
1427 			g_drive_poll_for_media (drive,
1428 						NULL,  /* cancellable */
1429 						NULL,  /* GAsyncReadyCallback */
1430 						NULL); /* user_data */
1431 			g_object_unref (drive);
1432 		}
1433 	}
1434 }
1435 
1436 /**
1437  * nautilus_file_is_desktop_directory:
1438  * 
1439  * Check whether this file is the desktop directory.
1440  * 
1441  * @file: The file to check.
1442  * 
1443  * Return value: TRUE if this is the physical desktop directory.
1444  */
1445 gboolean
1446 nautilus_file_is_desktop_directory (NautilusFile *file)
1447 {
1448 	GFile *dir;
1449 
1450 	dir = file->details->directory->details->location;
1451 
1452 	if (dir == NULL) {
1453 		return FALSE;
1454 	}
1455 
1456 	return nautilus_is_desktop_directory_file (dir, eel_ref_str_peek (file->details->name));
1457 }
1458 
1459 static gboolean
1460 is_desktop_file (NautilusFile *file)
1461 {
1462 	return nautilus_file_is_mime_type (file, "application/x-desktop");
1463 }
1464 
1465 static gboolean
1466 can_rename_desktop_file (NautilusFile *file)
1467 {
1468 	GFile *location;
1469 	gboolean res;
1470 
1471 	location = nautilus_file_get_location (file);
1472 	res = g_file_is_native (location);
1473 	g_object_unref (location);
1474 	return res;
1475 }
1476 
1477 /**
1478  * nautilus_file_can_rename:
1479  * 
1480  * Check whether the user is allowed to change the name of the file.
1481  * 
1482  * @file: The file to check.
1483  * 
1484  * Return value: FALSE if the user is definitely not allowed to change
1485  * the name of the file. If the user is allowed to change the name, or
1486  * the code can't tell whether the user is allowed to change the name,
1487  * returns TRUE (so rename failures must always be handled).
1488  */
1489 gboolean
1490 nautilus_file_can_rename (NautilusFile *file)
1491 {
1492 	gboolean can_rename;
1493 	
1494 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1495 
1496 	/* Nonexistent files can't be renamed. */
1497 	if (nautilus_file_is_gone (file)) {
1498 		return FALSE;
1499 	}
1500 
1501 	/* Self-owned files can't be renamed */
1502 	if (nautilus_file_is_self_owned (file)) {
1503 		return FALSE;
1504 	}
1505 
1506 	if ((is_desktop_file (file) && !can_rename_desktop_file (file)) ||
1507 	     nautilus_file_is_home (file)) {
1508 		return FALSE;
1509 	}
1510 	
1511 	can_rename = TRUE;
1512 
1513 	/* Certain types of links can't be renamed */
1514 	if (NAUTILUS_IS_DESKTOP_ICON_FILE (file)) {
1515 		NautilusDesktopLink *link;
1516 
1517 		link = nautilus_desktop_icon_file_get_link (NAUTILUS_DESKTOP_ICON_FILE (file));
1518 
1519 		if (link != NULL) {
1520 			can_rename = nautilus_desktop_link_can_rename (link);
1521 			g_object_unref (link);
1522 		}
1523 	}
1524 
1525 	if (!can_rename) {
1526 		return FALSE;
1527 	}
1528 
1529 	return file->details->can_rename;
1530 }
1531 
1532 gboolean
1533 nautilus_file_can_delete (NautilusFile *file)
1534 {
1535 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1536 
1537 	/* Nonexistent files can't be deleted. */
1538 	if (nautilus_file_is_gone (file)) {
1539 		return FALSE;
1540 	}
1541 
1542 	/* Self-owned files can't be deleted */
1543 	if (nautilus_file_is_self_owned (file)) {
1544 		return FALSE;
1545 	}
1546 
1547 	return file->details->can_delete;
1548 }
1549 
1550 gboolean
1551 nautilus_file_can_trash (NautilusFile *file)
1552 {
1553 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
1554 
1555 	/* Nonexistent files can't be deleted. */
1556 	if (nautilus_file_is_gone (file)) {
1557 		return FALSE;
1558 	}
1559 
1560 	/* Self-owned files can't be deleted */
1561 	if (nautilus_file_is_self_owned (file)) {
1562 		return FALSE;
1563 	}
1564 
1565 	return file->details->can_trash;
1566 }
1567 
1568 GFile *
1569 nautilus_file_get_location (NautilusFile *file)
1570 {
1571 	GFile *dir;
1572 	
1573 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
1574 
1575 	dir = file->details->directory->details->location;
1576 	
1577 	if (nautilus_file_is_self_owned (file)) {
1578 		return g_object_ref (dir);
1579 	}
1580 	
1581 	return g_file_get_child (dir, eel_ref_str_peek (file->details->name));
1582 }
1583 
1584 /* Return the actual uri associated with the passed-in file. */
1585 char *
1586 nautilus_file_get_uri (NautilusFile *file)
1587 {
1588 	char *uri;
1589 	GFile *loc;
1590 	
1591 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
1592 
1593 	loc = nautilus_file_get_location (file);
1594 	uri = g_file_get_uri (loc);
1595 	g_object_unref (loc);
1596 	
1597 	return uri;
1598 }
1599 
1600 char *
1601 nautilus_file_get_uri_scheme (NautilusFile *file)
1602 {
1603 	GFile *loc;
1604 	char *scheme;
1605 	
1606 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
1607 
1608 	if (file->details->directory == NULL || 
1609 	    file->details->directory->details->location == NULL) {
1610 		return NULL;
1611 	}
1612 
1613 	loc = nautilus_directory_get_location (file->details->directory);
1614 	scheme = g_file_get_uri_scheme (loc);
1615 	g_object_unref (loc);
1616 	
1617 	return scheme;
1618 }
1619 
1620 NautilusFileOperation *
1621 nautilus_file_operation_new (NautilusFile *file,
1622 			     NautilusFileOperationCallback callback,
1623 			     gpointer callback_data)
1624 {
1625 	NautilusFileOperation *op;
1626 
1627 	op = g_new0 (NautilusFileOperation, 1);
1628 	op->file = nautilus_file_ref (file);
1629 	op->callback = callback;
1630 	op->callback_data = callback_data;
1631 	op->cancellable = g_cancellable_new ();
1632 
1633 	op->file->details->operations_in_progress = g_list_prepend
1634 		(op->file->details->operations_in_progress, op);
1635 
1636 	return op;
1637 }
1638 
1639 static void
1640 nautilus_file_operation_remove (NautilusFileOperation *op)
1641 {
1642 	op->file->details->operations_in_progress = g_list_remove
1643 		(op->file->details->operations_in_progress, op);
1644 }
1645 
1646 void
1647 nautilus_file_operation_free (NautilusFileOperation *op)
1648 {
1649 	nautilus_file_operation_remove (op);
1650 	nautilus_file_unref (op->file);
1651 	g_object_unref (op->cancellable);
1652 	if (op->free_data) {
1653 		op->free_data (op->data);
1654 	}
1655 
1656 	if (op->undo_info != NULL) {
1657 		nautilus_file_undo_manager_set_action (op->undo_info);
1658 		g_object_unref (op->undo_info);
1659 	}
1660 
1661 	g_free (op);
1662 }
1663 
1664 void
1665 nautilus_file_operation_complete (NautilusFileOperation *op,
1666 				  GFile *result_file,
1667 				  GError *error)
1668 {
1669 	/* Claim that something changed even if the operation failed.
1670 	 * This makes it easier for some clients who see the "reverting"
1671 	 * as "changing back".
1672 	 */
1673 	nautilus_file_operation_remove (op);
1674 	nautilus_file_changed (op->file);
1675 	if (op->callback) {
1676 		(* op->callback) (op->file, result_file, error, op->callback_data);
1677 	}
1678 
1679 	if (error != NULL) {
1680 		g_clear_object (&op->undo_info);
1681 	}
1682 
1683 	nautilus_file_operation_free (op);
1684 }
1685 
1686 void
1687 nautilus_file_operation_cancel (NautilusFileOperation *op)
1688 {
1689 	/* Cancel the operation if it's still in progress. */
1690 	g_cancellable_cancel (op->cancellable);
1691 }
1692 
1693 static void
1694 rename_get_info_callback (GObject *source_object,
1695 			  GAsyncResult *res,
1696 			  gpointer callback_data)
1697 {
1698 	NautilusFileOperation *op;
1699 	NautilusDirectory *directory;
1700 	NautilusFile *existing_file;
1701 	char *old_name;
1702 	char *old_uri;
1703 	char *new_uri;
1704 	const char *new_name;
1705 	GFileInfo *new_info;
1706 	GError *error;
1707 	
1708 	op = callback_data;
1709 
1710 	error = NULL;
1711 	new_info = g_file_query_info_finish (G_FILE (source_object), res, &error);
1712 	if (new_info != NULL) {
1713 		directory = op->file->details->directory;
1714 
1715 		new_name = g_file_info_get_name (new_info);
1716 		
1717 		/* If there was another file by the same name in this
1718 		 * directory, mark it gone.
1719 		 */
1720 		existing_file = nautilus_directory_find_file_by_name (directory, new_name);
1721 		if (existing_file != NULL) {
1722 			nautilus_file_mark_gone (existing_file);
1723 			nautilus_file_changed (existing_file);
1724 		}
1725 		
1726 		old_uri = nautilus_file_get_uri (op->file);
1727 		old_name = g_strdup (eel_ref_str_peek (op->file->details->name));
1728 		
1729 		update_info_and_name (op->file, new_info);
1730 		
1731 		g_free (old_name);
1732 		
1733 		new_uri = nautilus_file_get_uri (op->file);
1734 		nautilus_directory_moved (old_uri, new_uri);
1735 		g_free (new_uri);
1736 		g_free (old_uri);
1737 		
1738 		/* the rename could have affected the display name if e.g.
1739 		 * we're in a vfolder where the name comes from a desktop file
1740 		 * and a rename affects the contents of the desktop file.
1741 		 */
1742 		if (op->file->details->got_custom_display_name) {
1743 			nautilus_file_invalidate_attributes (op->file,
1744 							     NAUTILUS_FILE_ATTRIBUTE_INFO |
1745 							     NAUTILUS_FILE_ATTRIBUTE_LINK_INFO);
1746 		}
1747 		
1748 		g_object_unref (new_info);
1749 	}
1750 	nautilus_file_operation_complete (op, NULL, error);
1751 	if (error) {
1752 		g_error_free (error);
1753 	}
1754 }
1755 
1756 static void
1757 rename_callback (GObject *source_object,
1758 		 GAsyncResult *res,
1759 		 gpointer callback_data)
1760 {
1761 	NautilusFileOperation *op;
1762 	GFile *new_file;
1763 	GError *error;
1764 
1765 	op = callback_data;
1766 
1767 	error = NULL;
1768 	new_file = g_file_set_display_name_finish (G_FILE (source_object),
1769 						   res, &error);
1770 
1771 	if (new_file != NULL) {
1772 		if (op->undo_info != NULL) {
1773 			nautilus_file_undo_info_rename_set_data (NAUTILUS_FILE_UNDO_INFO_RENAME (op->undo_info),
1774 								 G_FILE (source_object), new_file);
1775 		}
1776 
1777 		g_file_query_info_async (new_file,
1778 					 NAUTILUS_FILE_DEFAULT_ATTRIBUTES,
1779 					 0,
1780 					 G_PRIORITY_DEFAULT,
1781 					 op->cancellable,
1782 					 rename_get_info_callback, op);
1783 	} else {
1784 		nautilus_file_operation_complete (op, NULL, error);
1785 		g_error_free (error);
1786 	}
1787 }
1788 
1789 static gboolean
1790 name_is (NautilusFile *file, const char *new_name)
1791 {
1792 	const char *old_name;
1793 	old_name = eel_ref_str_peek (file->details->name);
1794 	return strcmp (new_name, old_name) == 0;
1795 }
1796 
1797 void
1798 nautilus_file_rename (NautilusFile *file,
1799 		      const char *new_name,
1800 		      NautilusFileOperationCallback callback,
1801 		      gpointer callback_data)
1802 {
1803 	NautilusFileOperation *op;
1804 	char *uri;
1805 	char *old_name;
1806 	char *new_file_name;
1807 	gboolean success, name_changed;
1808 	gboolean is_renameable_desktop_file;
1809 	GFile *location;
1810 	GError *error;
1811 	
1812 	g_return_if_fail (NAUTILUS_IS_FILE (file));
1813 	g_return_if_fail (new_name != NULL);
1814 	g_return_if_fail (callback != NULL);
1815 
1816 	is_renameable_desktop_file =
1817 		is_desktop_file (file) && can_rename_desktop_file (file);
1818 	
1819 	/* Return an error for incoming names containing path separators.
1820 	 * But not for .desktop files as '/' are allowed for them */
1821 	if (strstr (new_name, "/") != NULL && !is_renameable_desktop_file) {
1822 		error = g_error_new (G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
1823 				     _("Slashes are not allowed in filenames"));
1824 		(* callback) (file, NULL, error, callback_data);
1825 		g_error_free (error);
1826 		return;
1827 	}
1828 	
1829 	/* Can't rename a file that's already gone.
1830 	 * We need to check this here because there may be a new
1831 	 * file with the same name.
1832 	 */
1833 	if (nautilus_file_is_gone (file)) {
1834 	       	/* Claim that something changed even if the rename
1835 		 * failed. This makes it easier for some clients who
1836 		 * see the "reverting" to the old name as "changing
1837 		 * back".
1838 		 */
1839 		nautilus_file_changed (file);
1840 		error = g_error_new (G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
1841 				     _("File not found"));
1842 		(* callback) (file, NULL, error, callback_data);
1843 		g_error_free (error);
1844 		return;
1845 	}
1846 
1847 	/* Test the name-hasn't-changed case explicitly, for two reasons.
1848 	 * (1) rename returns an error if new & old are same.
1849 	 * (2) We don't want to send file-changed signal if nothing changed.
1850 	 */
1851 	if (!NAUTILUS_IS_DESKTOP_ICON_FILE (file) &&
1852 	    !is_renameable_desktop_file &&
1853 	    name_is (file, new_name)) {
1854 		(* callback) (file, NULL, NULL, callback_data);
1855 		return;
1856 	}
1857 
1858 	/* Self-owned files can't be renamed. Test the name-not-actually-changing
1859 	 * case before this case.
1860 	 */
1861 	if (nautilus_file_is_self_owned (file)) {
1862 	       	/* Claim that something changed even if the rename
1863 		 * failed. This makes it easier for some clients who
1864 		 * see the "reverting" to the old name as "changing
1865 		 * back".
1866 		 */
1867 		nautilus_file_changed (file);
1868 		error = g_error_new (G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
1869 				     _("Toplevel files cannot be renamed"));
1870 		
1871 		(* callback) (file, NULL, error, callback_data);
1872 		g_error_free (error);
1873 		return;
1874 	}
1875 
1876 	if (NAUTILUS_IS_DESKTOP_ICON_FILE (file)) {
1877 		NautilusDesktopLink *link;
1878 
1879 		link = nautilus_desktop_icon_file_get_link (NAUTILUS_DESKTOP_ICON_FILE (file));
1880 		old_name = nautilus_file_get_display_name (file);
1881 
1882 		if ((old_name != NULL && strcmp (new_name, old_name) == 0)) {
1883 			success = TRUE;
1884 		} else {
1885 			success = (link != NULL && nautilus_desktop_link_rename (link, new_name));
1886 		}
1887 
1888 		if (success) {
1889 			(* callback) (file, NULL, NULL, callback_data);
1890 		} else {
1891 			error = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED,
1892 					     _("Unable to rename desktop icon"));
1893 			(* callback) (file, NULL, error, callback_data);
1894 			g_error_free (error);
1895 		}
1896 
1897 		g_free (old_name);
1898 		g_object_unref (link);
1899 		return;
1900 	}
1901 	
1902 	if (is_renameable_desktop_file) {
1903 		/* Don't actually change the name if the new name is the same.
1904 		 * This helps for the vfolder method where this can happen and
1905 		 * we want to minimize actual changes
1906 		 */
1907 		uri = nautilus_file_get_uri (file);
1908 		old_name = nautilus_link_local_get_text (uri);
1909 		if (old_name != NULL && strcmp (new_name, old_name) == 0) {
1910 			success = TRUE;
1911 			name_changed = FALSE;
1912 		} else {
1913 			success = nautilus_link_local_set_text (uri, new_name);
1914 			name_changed = TRUE;
1915 		}
1916 		g_free (old_name);
1917 		g_free (uri);
1918 
1919 		if (!success) {
1920 			error = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED,
1921 					     _("Unable to rename desktop file"));
1922 			(* callback) (file, NULL, error, callback_data);
1923 			g_error_free (error);
1924 			return;
1925 		}
1926 		new_file_name = g_strdup_printf ("%s.desktop", new_name);
1927 		new_file_name = g_strdelimit (new_file_name, "/", '-');
1928 
1929 		if (name_is (file, new_file_name)) {
1930 			if (name_changed) {
1931 				nautilus_file_invalidate_attributes (file,
1932 								     NAUTILUS_FILE_ATTRIBUTE_INFO |
1933 								     NAUTILUS_FILE_ATTRIBUTE_LINK_INFO);
1934 			}
1935 
1936 			(* callback) (file, NULL, NULL, callback_data);
1937 			g_free (new_file_name);
1938 			return;
1939 		}
1940 	} else {
1941 		new_file_name = g_strdup (new_name);
1942 	}
1943 
1944 	/* Set up a renaming operation. */
1945 	op = nautilus_file_operation_new (file, callback, callback_data);
1946 	op->is_rename = TRUE;
1947 	location = nautilus_file_get_location (file);
1948 
1949 	/* Tell the undo manager a rename is taking place */
1950 	if (!nautilus_file_undo_manager_pop_flag ()) {
1951 		op->undo_info = nautilus_file_undo_info_rename_new ();
1952 	}
1953 
1954 	/* Do the renaming. */
1955 	g_file_set_display_name_async (location,
1956 				       new_file_name,
1957 				       G_PRIORITY_DEFAULT,
1958 				       op->cancellable,
1959 				       rename_callback,
1960 				       op);
1961 	g_free (new_file_name);
1962 	g_object_unref (location);
1963 }
1964 
1965 gboolean
1966 nautilus_file_rename_in_progress (NautilusFile *file)
1967 {
1968 	GList *node;
1969 	NautilusFileOperation *op;
1970 
1971 	for (node = file->details->operations_in_progress; node != NULL; node = node->next) {
1972 		op = node->data;
1973 		if (op->is_rename) {
1974 			return TRUE;
1975 		}
1976 	}
1977 	return FALSE;
1978 }
1979 
1980 void
1981 nautilus_file_cancel (NautilusFile *file,
1982 		      NautilusFileOperationCallback callback,
1983 		      gpointer callback_data)
1984 {
1985 	GList *node, *next;
1986 	NautilusFileOperation *op;
1987 
1988 	for (node = file->details->operations_in_progress; node != NULL; node = next) {
1989 		next = node->next;
1990 		op = node->data;
1991 
1992 		g_assert (op->file == file);
1993 		if (op->callback == callback && op->callback_data == callback_data) {
1994 			nautilus_file_operation_cancel (op);
1995 		}
1996 	}
1997 }
1998 
1999 gboolean         
2000 nautilus_file_matches_uri (NautilusFile *file, const char *match_uri)
2001 {
2002 	GFile *match_file, *location;
2003 	gboolean result;
2004 
2005 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
2006 	g_return_val_if_fail (match_uri != NULL, FALSE);
2007 	
2008 	location = nautilus_file_get_location (file);
2009 	match_file = g_file_new_for_uri (match_uri);
2010 	result = g_file_equal (location, match_file);
2011 	g_object_unref (location);
2012 	g_object_unref (match_file);
2013 
2014 	return result;
2015 }
2016 
2017 int
2018 nautilus_file_compare_location (NautilusFile *file_1,
2019                                 NautilusFile *file_2)
2020 {
2021 	GFile *loc_a, *loc_b;
2022 	gboolean res;
2023 
2024 	loc_a = nautilus_file_get_location (file_1);
2025 	loc_b = nautilus_file_get_location (file_2);
2026 
2027 	res = !g_file_equal (loc_a, loc_b);
2028 
2029 	g_object_unref (loc_a);
2030 	g_object_unref (loc_b);
2031 
2032 	return (gint) res;
2033 }
2034 
2035 gboolean
2036 nautilus_file_is_local (NautilusFile *file)
2037 {
2038 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
2039 	
2040 	return nautilus_directory_is_local (file->details->directory);
2041 }
2042 
2043 static void
2044 update_link (NautilusFile *link_file, NautilusFile *target_file)
2045 {
2046 	g_assert (NAUTILUS_IS_FILE (link_file));
2047 	g_assert (NAUTILUS_IS_FILE (target_file));
2048 
2049 	/* FIXME bugzilla.gnome.org 42044: If we don't put any code
2050 	 * here then the hash table is a waste of time.
2051 	 */
2052 }
2053 
2054 static GList *
2055 get_link_files (NautilusFile *target_file)
2056 {
2057 	char *uri;
2058 	GList **link_files;
2059 	
2060 	if (symbolic_links == NULL) {
2061 		link_files = NULL;
2062 	} else {
2063 		uri = nautilus_file_get_uri (target_file);
2064 		link_files = g_hash_table_lookup (symbolic_links, uri);
2065 		g_free (uri);
2066 	}
2067 	if (link_files) {
2068 		return nautilus_file_list_copy (*link_files);
2069 	}
2070 	return NULL;
2071 }
2072 
2073 static void
2074 update_links_if_target (NautilusFile *target_file)
2075 {
2076 	GList *link_files, *p;
2077 
2078 	link_files = get_link_files (target_file);
2079 	for (p = link_files; p != NULL; p = p->next) {
2080 		update_link (NAUTILUS_FILE (p->data), target_file);
2081 	}
2082 	nautilus_file_list_free (link_files);
2083 }
2084 
2085 static gboolean
2086 update_info_internal (NautilusFile *file,
2087 		      GFileInfo *info,
2088 		      gboolean update_name)
2089 {
2090 	GList *node;
2091 	gboolean changed;
2092 	gboolean is_symlink, is_hidden, is_mountpoint;
2093 	gboolean has_permissions;
2094 	guint32 permissions;
2095 	gboolean can_read, can_write, can_execute, can_delete, can_trash, can_rename, can_mount, can_unmount, can_eject;
2096 	gboolean can_start, can_start_degraded, can_stop, can_poll_for_media, is_media_check_automatic;
2097 	GDriveStartStopType start_stop_type;
2098 	gboolean thumbnailing_failed;
2099 	int uid, gid;
2100 	goffset size;
2101 	int sort_order;
2102 	time_t atime, mtime;
2103 	time_t trash_time;
2104 	GTimeVal g_trash_time;
2105 	const char * time_string;
2106 	const char *symlink_name, *mime_type, *selinux_context, *name, *thumbnail_path;
2107 	GFileType file_type;
2108 	GIcon *icon;
2109 	char *old_activation_uri;
2110 	const char *activation_uri;
2111 	const char *description;
2112 	const char *filesystem_id;
2113 	const char *trash_orig_path;
2114 	const char *group, *owner, *owner_real;
2115 	gboolean free_owner, free_group;
2116 	
2117 	if (file->details->is_gone) {
2118 		return FALSE;
2119 	}
2120 
2121 	if (info == NULL) {
2122 		nautilus_file_mark_gone (file);
2123 		return TRUE;
2124 	}
2125 
2126 	file->details->file_info_is_up_to_date = TRUE;
2127 
2128 	/* FIXME bugzilla.gnome.org 42044: Need to let links that
2129 	 * point to the old name know that the file has been renamed.
2130 	 */
2131 
2132 	remove_from_link_hash_table (file);
2133 
2134 	changed = FALSE;
2135 
2136 	if (!file->details->got_file_info) {
2137 		changed = TRUE;
2138 	}
2139 	file->details->got_file_info = TRUE;
2140 
2141 	changed |= nautilus_file_set_display_name (file,
2142 						  g_file_info_get_display_name (info),
2143 						  g_file_info_get_edit_name (info),
2144 						  FALSE);
2145 
2146 	mime_type = g_file_info_get_content_type (info);
2147 	if (g_strcmp0 (mime_type, NAUTILUS_SAVED_SEARCH_MIMETYPE) == 0) {
2148 		g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
2149 	}
2150 
2151 	file_type = g_file_info_get_file_type (info);
2152 	if (file->details->type != file_type) {
2153 		changed = TRUE;
2154 	}
2155 	file->details->type = file_type;
2156 
2157 	if (!file->details->got_custom_activation_uri) {
2158 		activation_uri = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI);
2159 		if (activation_uri == NULL) {
2160 			if (file->details->activation_uri) {
2161 				g_free (file->details->activation_uri);
2162 				file->details->activation_uri = NULL;
2163 				changed = TRUE;
2164 			}
2165 		} else {
2166 			old_activation_uri = file->details->activation_uri;
2167 			file->details->activation_uri = g_strdup (activation_uri);
2168 			
2169 			if (old_activation_uri) {
2170 				if (strcmp (old_activation_uri,
2171 					    file->details->activation_uri) != 0) {
2172 					changed = TRUE;
2173 				}
2174 				g_free (old_activation_uri);
2175 			} else {
2176 				changed = TRUE;
2177 			}
2178 		}
2179 	}
2180 	
2181 	is_symlink = g_file_info_get_is_symlink (info);
2182 	if (file->details->is_symlink != is_symlink) {
2183 		changed = TRUE;
2184 	}
2185 	file->details->is_symlink = is_symlink;
2186 
2187 	is_hidden = g_file_info_get_is_hidden (info) || g_file_info_get_is_backup (info);
2188 	if (file->details->is_hidden != is_hidden) {
2189 		changed = TRUE;
2190 	}
2191 	file->details->is_hidden = is_hidden;
2192 
2193 	is_mountpoint = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT);
2194 	if (file->details->is_mountpoint != is_mountpoint) {
2195 		changed = TRUE;
2196 	}
2197 	file->details->is_mountpoint = is_mountpoint;
2198 
2199 	has_permissions = g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE);
2200 	permissions = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE);;
2201 	if (file->details->has_permissions != has_permissions ||
2202 	    file->details->permissions != permissions) {
2203 		changed = TRUE;
2204 	}
2205 	file->details->has_permissions = has_permissions;
2206 	file->details->permissions = permissions;
2207 
2208 	/* We default to TRUE for this if we can't know */
2209 	can_read = TRUE;
2210 	can_write = TRUE;
2211 	can_execute = TRUE;
2212 	can_delete = TRUE;
2213 	can_trash = TRUE;
2214 	can_rename = TRUE;
2215 	can_mount = FALSE;
2216 	can_unmount = FALSE;
2217 	can_eject = FALSE;
2218 	can_start = FALSE;
2219 	can_start_degraded = FALSE;
2220 	can_stop = FALSE;
2221 	can_poll_for_media = FALSE;
2222 	is_media_check_automatic = FALSE;
2223 	start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
2224 	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ)) {
2225 		can_read = g_file_info_get_attribute_boolean (info,
2226 							      G_FILE_ATTRIBUTE_ACCESS_CAN_READ);
2227 	}
2228 	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE)) {
2229 		can_write = g_file_info_get_attribute_boolean (info,
2230 							       G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
2231 	}
2232 	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE)) {
2233 		can_execute = g_file_info_get_attribute_boolean (info,
2234 								G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE);
2235 	}
2236 	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE)) {
2237 		can_delete = g_file_info_get_attribute_boolean (info,
2238 								G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE);
2239 	}
2240 	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH)) {
2241 		can_trash = g_file_info_get_attribute_boolean (info,
2242 							       G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH);
2243 	}
2244 	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME)) {
2245 		can_rename = g_file_info_get_attribute_boolean (info,
2246 								G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME);
2247 	}
2248 	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT)) {
2249 		can_mount = g_file_info_get_attribute_boolean (info,
2250 							       G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT);
2251 	}
2252 	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT)) {
2253 		can_unmount = g_file_info_get_attribute_boolean (info,
2254 								 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT);
2255 	}
2256 	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT)) {
2257 		can_eject = g_file_info_get_attribute_boolean (info,
2258 							       G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT);
2259 	}
2260 	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START)) {
2261 		can_start = g_file_info_get_attribute_boolean (info,
2262 							       G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START);
2263 	}
2264 	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START_DEGRADED)) {
2265 		can_start_degraded = g_file_info_get_attribute_boolean (info,
2266 							       G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START_DEGRADED);
2267 	}
2268 	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_STOP)) {
2269 		can_stop = g_file_info_get_attribute_boolean (info,
2270 							      G_FILE_ATTRIBUTE_MOUNTABLE_CAN_STOP);
2271 	}
2272 	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_START_STOP_TYPE)) {
2273 		start_stop_type = g_file_info_get_attribute_uint32 (info,
2274 								    G_FILE_ATTRIBUTE_MOUNTABLE_START_STOP_TYPE);
2275 	}
2276 	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_POLL)) {
2277 		can_poll_for_media = g_file_info_get_attribute_boolean (info,
2278 									G_FILE_ATTRIBUTE_MOUNTABLE_CAN_POLL);
2279 	}
2280 	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC)) {
2281 		is_media_check_automatic = g_file_info_get_attribute_boolean (info,
2282 									      G_FILE_ATTRIBUTE_MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC);
2283 	}
2284 	if (file->details->can_read != can_read ||
2285 	    file->details->can_write != can_write ||
2286 	    file->details->can_execute != can_execute ||
2287 	    file->details->can_delete != can_delete ||
2288 	    file->details->can_trash != can_trash ||
2289 	    file->details->can_rename != can_rename ||
2290 	    file->details->can_mount != can_mount ||
2291 	    file->details->can_unmount != can_unmount ||
2292 	    file->details->can_eject != can_eject ||
2293 	    file->details->can_start != can_start ||
2294 	    file->details->can_start_degraded != can_start_degraded ||
2295 	    file->details->can_stop != can_stop ||
2296 	    file->details->start_stop_type != start_stop_type ||
2297 	    file->details->can_poll_for_media != can_poll_for_media ||
2298 	    file->details->is_media_check_automatic != is_media_check_automatic) {
2299 		changed = TRUE;
2300 	}
2301 	
2302 	file->details->can_read = can_read;
2303 	file->details->can_write = can_write;
2304 	file->details->can_execute = can_execute;
2305 	file->details->can_delete = can_delete;
2306 	file->details->can_trash = can_trash;
2307 	file->details->can_rename = can_rename;
2308 	file->details->can_mount = can_mount;
2309 	file->details->can_unmount = can_unmount;
2310 	file->details->can_eject = can_eject;
2311 	file->details->can_start = can_start;
2312 	file->details->can_start_degraded = can_start_degraded;
2313 	file->details->can_stop = can_stop;
2314 	file->details->start_stop_type = start_stop_type;
2315 	file->details->can_poll_for_media = can_poll_for_media;
2316 	file->details->is_media_check_automatic = is_media_check_automatic;
2317 
2318 	free_owner = FALSE;
2319 	owner = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER);
2320 	owner_real = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER_REAL);
2321 	free_group = FALSE;
2322 	group = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_GROUP);
2323 	
2324 	uid = -1;
2325 	gid = -1;
2326 	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_UID)) {
2327 		uid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID);
2328 		if (owner == NULL) {
2329 			free_owner = TRUE;
2330 			owner = g_strdup_printf ("%d", uid);
2331 		}
2332 	}
2333 	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_GID)) {
2334 		gid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID);
2335 		if (group == NULL) {
2336 			free_group = TRUE;
2337 			group = g_strdup_printf ("%d", gid);
2338 		}
2339 	}
2340 	if (file->details->uid != uid ||
2341 	    file->details->gid != gid) {
2342 		changed = TRUE;
2343 	}
2344 	file->details->uid = uid;
2345 	file->details->gid = gid;
2346 
2347 	if (g_strcmp0 (eel_ref_str_peek (file->details->owner), owner) != 0) {
2348 		changed = TRUE;
2349 		eel_ref_str_unref (file->details->owner);
2350 		file->details->owner = eel_ref_str_get_unique (owner);
2351 	}
2352 	
2353 	if (g_strcmp0 (eel_ref_str_peek (file->details->owner_real), owner_real) != 0) {
2354 		changed = TRUE;
2355 		eel_ref_str_unref (file->details->owner_real);
2356 		file->details->owner_real = eel_ref_str_get_unique (owner_real);
2357 	}
2358 	
2359 	if (g_strcmp0 (eel_ref_str_peek (file->details->group), group) != 0) {
2360 		changed = TRUE;
2361 		eel_ref_str_unref (file->details->group);
2362 		file->details->group = eel_ref_str_get_unique (group);
2363 	}
2364 
2365 	if (free_owner) {
2366 		g_free ((char *)owner);
2367 	}
2368 	if (free_group) {
2369 		g_free ((char *)group);
2370 	}
2371 	
2372 	size = -1;
2373 	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE)) {
2374 		size = g_file_info_get_size (info);
2375 	}
2376 	if (file->details->size != size) {
2377 		changed = TRUE;
2378 	}
2379 	file->details->size = size;
2380 
2381 	sort_order = g_file_info_get_sort_order (info);
2382 	if (file->details->sort_order != sort_order) {
2383 		changed = TRUE;
2384 	}
2385 	file->details->sort_order = sort_order;
2386 	
2387 	atime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_ACCESS);
2388 	mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
2389 	if (file->details->atime != atime ||
2390 	    file->details->mtime != mtime) {
2391 		if (file->details->thumbnail == NULL) {
2392 			file->details->thumbnail_is_up_to_date = FALSE;
2393 		}
2394 
2395 		changed = TRUE;
2396 	}
2397 	file->details->atime = atime;
2398 	file->details->mtime = mtime;
2399 
2400 	if (file->details->thumbnail != NULL &&
2401 	    file->details->thumbnail_mtime != 0 &&
2402 	    file->details->thumbnail_mtime != mtime) {
2403 		file->details->thumbnail_is_up_to_date = FALSE;
2404 		changed = TRUE;
2405 	}
2406 
2407 	icon = g_file_info_get_icon (info);
2408 	if (!g_icon_equal (icon, file->details->icon)) {
2409 		changed = TRUE;
2410 
2411 		if (file->details->icon) {
2412 			g_object_unref (file->details->icon);
2413 		}
2414 		file->details->icon = g_object_ref (icon);
2415 	}
2416 
2417 	thumbnail_path =  g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
2418 	if (g_strcmp0 (file->details->thumbnail_path, thumbnail_path) != 0) {
2419 		changed = TRUE;
2420 		g_free (file->details->thumbnail_path);
2421 		file->details->thumbnail_path = g_strdup (thumbnail_path);
2422 	}
2423 
2424 	thumbnailing_failed =  g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED);
2425 	if (file->details->thumbnailing_failed != thumbnailing_failed) {
2426 		changed = TRUE;
2427 		file->details->thumbnailing_failed = thumbnailing_failed;
2428 	}
2429 	
2430 	symlink_name = g_file_info_get_symlink_target (info);
2431 	if (g_strcmp0 (file->details->symlink_name, symlink_name) != 0) {
2432 		changed = TRUE;
2433 		g_free (file->details->symlink_name);
2434 		file->details->symlink_name = g_strdup (symlink_name);
2435 	}
2436 
2437 	mime_type = g_file_info_get_content_type (info);
2438 	if (g_strcmp0 (eel_ref_str_peek (file->details->mime_type), mime_type) != 0) {
2439 		changed = TRUE;
2440 		eel_ref_str_unref (file->details->mime_type);
2441 		file->details->mime_type = eel_ref_str_get_unique (mime_type);
2442 	}
2443 	
2444 	selinux_context = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_SELINUX_CONTEXT);
2445 	if (g_strcmp0 (file->details->selinux_context, selinux_context) != 0) {
2446 		changed = TRUE;
2447 		g_free (file->details->selinux_context);
2448 		file->details->selinux_context = g_strdup (selinux_context);
2449 	}
2450 	
2451 	description = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_DESCRIPTION);
2452 	if (g_strcmp0 (file->details->description, description) != 0) {
2453 		changed = TRUE;
2454 		g_free (file->details->description);
2455 		file->details->description = g_strdup (description);
2456 	}
2457 
2458 	filesystem_id = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILESYSTEM);
2459 	if (g_strcmp0 (eel_ref_str_peek (file->details->filesystem_id), filesystem_id) != 0) {
2460 		changed = TRUE;
2461 		eel_ref_str_unref (file->details->filesystem_id);
2462 		file->details->filesystem_id = eel_ref_str_get_unique (filesystem_id);
2463 	}
2464 
2465 	trash_time = 0;
2466 	time_string = g_file_info_get_attribute_string (info, "trash::deletion-date");
2467 	if (time_string != NULL) {
2468 		g_time_val_from_iso8601 (time_string, &g_trash_time);
2469 		trash_time = g_trash_time.tv_sec;
2470 	}
2471 	if (file->details->trash_time != trash_time) {
2472 		changed = TRUE;
2473 		file->details->trash_time = trash_time;
2474 	}
2475 
2476 	trash_orig_path = g_file_info_get_attribute_byte_string (info, "trash::orig-path");
2477 	if (g_strcmp0 (file->details->trash_orig_path, trash_orig_path) != 0) {
2478 		changed = TRUE;
2479 		g_free (file->details->trash_orig_path);
2480 		file->details->trash_orig_path = g_strdup (trash_orig_path);
2481 	}
2482 
2483 	changed |=
2484 		nautilus_file_update_metadata_from_info (file, info);
2485 
2486 	if (update_name) {
2487 		name = g_file_info_get_name (info);
2488 		if (file->details->name == NULL ||
2489 		    strcmp (eel_ref_str_peek (file->details->name), name) != 0) {
2490 			changed = TRUE;
2491 
2492 			node = nautilus_directory_begin_file_name_change
2493 				(file->details->directory, file);
2494 			
2495 			eel_ref_str_unref (file->details->name);
2496 			if (g_strcmp0 (eel_ref_str_peek (file->details->display_name),
2497 				       name) == 0) {
2498 				file->details->name = eel_ref_str_ref (file->details->display_name);
2499 			} else {
2500 				file->details->name = eel_ref_str_new (name);
2501 			}
2502 
2503 			if (!file->details->got_custom_display_name &&
2504 			    g_file_info_get_display_name (info) == NULL) {
2505 				/* If the file info's display name is NULL,
2506 				 * nautilus_file_set_display_name() did
2507 				 * not unset the display name.
2508 				 */
2509 				nautilus_file_clear_display_name (file);
2510 			}
2511 
2512 			nautilus_directory_end_file_name_change
2513 				(file->details->directory, file, node);
2514 		}
2515 	}
2516 
2517 	if (changed) {
2518 		add_to_link_hash_table (file);
2519 		
2520 		update_links_if_target (file);
2521 	}
2522 
2523 	return changed;
2524 }
2525 
2526 static gboolean
2527 update_info_and_name (NautilusFile *file,
2528 		      GFileInfo *info)
2529 {
2530 	return update_info_internal (file, info, TRUE);
2531 }
2532 
2533 gboolean
2534 nautilus_file_update_info (NautilusFile *file,
2535 			   GFileInfo *info)
2536 {
2537 	return update_info_internal (file, info, FALSE);
2538 }
2539 
2540 static gboolean
2541 update_name_internal (NautilusFile *file,
2542 		      const char *name,
2543 		      gboolean in_directory)
2544 {
2545 	GList *node;
2546 
2547 	g_assert (name != NULL);
2548 
2549 	if (file->details->is_gone) {
2550 		return FALSE;
2551 	}
2552 
2553 	if (name_is (file, name)) {
2554 		return FALSE;
2555 	}
2556 	
2557 	node = NULL;
2558 	if (in_directory) {
2559 		node = nautilus_directory_begin_file_name_change
2560 			(file->details->directory, file);
2561 	}
2562 	
2563 	eel_ref_str_unref (file->details->name);
2564 	file->details->name = eel_ref_str_new (name);
2565 
2566 	if (!file->details->got_custom_display_name) {
2567 		nautilus_file_clear_display_name (file);
2568 	}
2569 
2570 	if (in_directory) {
2571 		nautilus_directory_end_file_name_change
2572 			(file->details->directory, file, node);
2573 	}
2574 
2575 	return TRUE;
2576 }
2577 
2578 gboolean
2579 nautilus_file_update_name (NautilusFile *file, const char *name)
2580 {
2581 	gboolean ret;
2582 	
2583 	ret = update_name_internal (file, name, TRUE);
2584 
2585 	if (ret) {
2586 		update_links_if_target (file);
2587 	}
2588 
2589 	return ret;
2590 }
2591 
2592 gboolean
2593 nautilus_file_update_name_and_directory (NautilusFile *file, 
2594 					 const char *name,
2595 					 NautilusDirectory *new_directory)
2596 {
2597 	NautilusDirectory *old_directory;
2598 	FileMonitors *monitors;
2599 
2600 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
2601 	g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (file->details->directory), FALSE);
2602 	g_return_val_if_fail (!file->details->is_gone, FALSE);
2603 	g_return_val_if_fail (!nautilus_file_is_self_owned (file), FALSE);
2604 	g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (new_directory), FALSE);
2605 
2606 	old_directory = file->details->directory;
2607 	if (old_directory == new_directory) {
2608 		if (name) {
2609 			return update_name_internal (file, name, TRUE);
2610 		} else {
2611 			return FALSE;
2612 		}
2613 	}
2614 
2615 	nautilus_file_ref (file);
2616 
2617 	/* FIXME bugzilla.gnome.org 42044: Need to let links that
2618 	 * point to the old name know that the file has been moved.
2619 	 */
2620 
2621 	remove_from_link_hash_table (file);
2622 
2623 	monitors = nautilus_directory_remove_file_monitors (old_directory, file);
2624 	nautilus_directory_remove_file (old_directory, file);
2625 
2626 	file->details->directory = nautilus_directory_ref (new_directory);
2627 	nautilus_directory_unref (old_directory);
2628 
2629 	if (name) {
2630 		update_name_internal (file, name, FALSE);
2631 	}
2632 
2633 	nautilus_directory_add_file (new_directory, file);
2634 	nautilus_directory_add_file_monitors (new_directory, file, monitors);
2635 
2636 	add_to_link_hash_table (file);
2637 
2638 	update_links_if_target (file);
2639 
2640 	nautilus_file_unref (file);
2641 
2642 	return TRUE;
2643 }
2644 
2645 void
2646 nautilus_file_set_directory (NautilusFile *file,
2647 			     NautilusDirectory *new_directory)
2648 {
2649 	nautilus_file_update_name_and_directory (file, NULL, new_directory);
2650 }
2651 
2652 static Knowledge
2653 get_item_count (NautilusFile *file,
2654 		guint *count)
2655 {
2656 	gboolean known, unreadable;
2657 
2658 	known = nautilus_file_get_directory_item_count
2659 		(file, count, &unreadable);
2660 	if (!known) {
2661 		return UNKNOWN;
2662 	}
2663 	if (unreadable) {
2664 		return UNKNOWABLE;
2665 	}
2666 	return KNOWN;
2667 }
2668 
2669 static Knowledge
2670 get_size (NautilusFile *file,
2671 	  goffset *size)
2672 {
2673 	/* If we tried and failed, then treat it like there is no size
2674 	 * to know.
2675 	 */
2676 	if (file->details->get_info_failed) {
2677 		return UNKNOWABLE;
2678 	}
2679 
2680 	/* If the info is NULL that means we haven't even tried yet,
2681 	 * so it's just unknown, not unknowable.
2682 	 */
2683 	if (!file->details->got_file_info) {
2684 		return UNKNOWN;
2685 	}
2686 
2687 	/* If we got info with no size in it, it means there is no
2688 	 * such thing as a size as far as gnome-vfs is concerned,
2689 	 * so "unknowable".
2690 	 */
2691 	if (file->details->size == -1) {
2692 		return UNKNOWABLE;
2693 	}
2694 
2695 	/* We have a size! */
2696 	*size = file->details->size;
2697 	return KNOWN;
2698 }
2699 
2700 static Knowledge
2701 get_time (NautilusFile *file,
2702 	  time_t *time_out,
2703 	  NautilusDateType type)
2704 {
2705 	time_t time;
2706 
2707 	/* If we tried and failed, then treat it like there is no size
2708 	 * to know.
2709 	 */
2710 	if (file->details->get_info_failed) {
2711 		return UNKNOWABLE;
2712 	}
2713 
2714 	/* If the info is NULL that means we haven't even tried yet,
2715 	 * so it's just unknown, not unknowable.
2716 	 */
2717 	if (!file->details->got_file_info) {
2718 		return UNKNOWN;
2719 	}
2720 
2721 	switch (type) {
2722 	case NAUTILUS_DATE_TYPE_MODIFIED:
2723 		time = file->details->mtime;
2724 		break;
2725 	case NAUTILUS_DATE_TYPE_ACCESSED:
2726 		time = file->details->atime;
2727 		break;
2728 	case NAUTILUS_DATE_TYPE_TRASHED:
2729 		time = file->details->trash_time;
2730 		break;
2731 	default:
2732 		g_assert_not_reached ();
2733 		break;
2734 	}
2735 
2736 	*time_out = time;
2737 	
2738 	/* If we got info with no modification time in it, it means
2739 	 * there is no such thing as a modification time as far as
2740 	 * gnome-vfs is concerned, so "unknowable".
2741 	 */
2742 	if (time == 0) {
2743 		return UNKNOWABLE;
2744 	}
2745 	return KNOWN;
2746 }
2747 
2748 static int
2749 compare_directories_by_count (NautilusFile *file_1, NautilusFile *file_2)
2750 {
2751 	/* Sort order:
2752 	 *   Directories with unknown # of items
2753 	 *   Directories with "unknowable" # of items
2754 	 *   Directories with 0 items
2755 	 *   Directories with n items
2756 	 */
2757 
2758 	Knowledge count_known_1, count_known_2;
2759 	guint count_1, count_2;
2760 
2761 	count_known_1 = get_item_count (file_1, &count_1);
2762 	count_known_2 = get_item_count (file_2, &count_2);
2763 
2764 	if (count_known_1 > count_known_2) {
2765 		return -1;
2766 	}
2767 	if (count_known_1 < count_known_2) {
2768 		return +1;
2769 	}
2770 
2771 	/* count_known_1 and count_known_2 are equal now. Check if count
2772 	 * details are UNKNOWABLE or UNKNOWN.
2773 	 */ 
2774 	if (count_known_1 == UNKNOWABLE || count_known_1 == UNKNOWN) {
2775 		return 0;
2776 	}
2777 
2778 	if (count_1 < count_2) {
2779 		return -1;
2780 	}
2781 	if (count_1 > count_2) {
2782 		return +1;
2783 	}
2784 
2785 	return 0;
2786 }
2787 
2788 static int
2789 compare_files_by_size (NautilusFile *file_1, NautilusFile *file_2)
2790 {
2791 	/* Sort order:
2792 	 *   Files with unknown size.
2793 	 *   Files with "unknowable" size.
2794 	 *   Files with smaller sizes.
2795 	 *   Files with large sizes.
2796 	 */
2797 
2798 	Knowledge size_known_1, size_known_2;
2799 	goffset size_1 = 0, size_2 = 0;
2800 
2801 	size_known_1 = get_size (file_1, &size_1);
2802 	size_known_2 = get_size (file_2, &size_2);
2803 
2804 	if (size_known_1 > size_known_2) {
2805 		return -1;
2806 	}
2807 	if (size_known_1 < size_known_2) {
2808 		return +1;
2809 	}
2810 
2811 	/* size_known_1 and size_known_2 are equal now. Check if size 
2812 	 * details are UNKNOWABLE or UNKNOWN 
2813 	 */ 
2814 	if (size_known_1 == UNKNOWABLE || size_known_1 == UNKNOWN) {
2815 		return 0;
2816 	}
2817 
2818 	if (size_1 < size_2) {
2819 		return -1;
2820 	}
2821 	if (size_1 > size_2) {
2822 		return +1;
2823 	}
2824 
2825 	return 0;
2826 }
2827 
2828 static int
2829 compare_by_size (NautilusFile *file_1, NautilusFile *file_2)
2830 {
2831 	/* Sort order:
2832 	 *   Directories with n items
2833 	 *   Directories with 0 items
2834 	 *   Directories with "unknowable" # of items
2835 	 *   Directories with unknown # of items
2836 	 *   Files with large sizes.
2837 	 *   Files with smaller sizes.
2838 	 *   Files with "unknowable" size.
2839 	 *   Files with unknown size.
2840 	 */
2841 
2842 	gboolean is_directory_1, is_directory_2;
2843 
2844 	is_directory_1 = nautilus_file_is_directory (file_1);
2845 	is_directory_2 = nautilus_file_is_directory (file_2);
2846 
2847 	if (is_directory_1 && !is_directory_2) {
2848 		return -1;
2849 	}
2850 	if (is_directory_2 && !is_directory_1) {
2851 		return +1;
2852 	}
2853 
2854 	if (is_directory_1) {
2855 		return compare_directories_by_count (file_1, file_2);
2856 	} else {
2857 		return compare_files_by_size (file_1, file_2);
2858 	}
2859 }
2860 
2861 static int
2862 compare_by_display_name (NautilusFile *file_1, NautilusFile *file_2)
2863 {
2864 	const char *name_1, *name_2;
2865 	const char *key_1, *key_2;
2866 	gboolean sort_last_1, sort_last_2;
2867 	int compare;
2868 
2869 	name_1 = nautilus_file_peek_display_name (file_1);
2870 	name_2 = nautilus_file_peek_display_name (file_2);
2871 
2872 	sort_last_1 = name_1[0] == SORT_LAST_CHAR1 || name_1[0] == SORT_LAST_CHAR2;
2873 	sort_last_2 = name_2[0] == SORT_LAST_CHAR1 || name_2[0] == SORT_LAST_CHAR2;
2874 
2875 	if (sort_last_1 && !sort_last_2) {
2876 		compare = +1;
2877 	} else if (!sort_last_1 && sort_last_2) {
2878 		compare = -1;
2879 	} else {
2880 		key_1 = nautilus_file_peek_display_name_collation_key (file_1);
2881 		key_2 = nautilus_file_peek_display_name_collation_key (file_2);
2882 		compare = strcmp (key_1, key_2);
2883 	}
2884 
2885 	return compare;
2886 }
2887 
2888 static int
2889 compare_by_directory_name (NautilusFile *file_1, NautilusFile *file_2)
2890 {
2891 	char *directory_1, *directory_2;
2892 	int compare;
2893 
2894 	if (file_1->details->directory == file_2->details->directory) {
2895 		return 0;
2896 	}
2897 
2898 	directory_1 = nautilus_file_get_parent_uri_for_display (file_1);
2899 	directory_2 = nautilus_file_get_parent_uri_for_display (file_2);
2900 
2901 	compare = g_utf8_collate (directory_1, directory_2);
2902 
2903 	g_free (directory_1);
2904 	g_free (directory_2);
2905 
2906 	return compare;
2907 }
2908 
2909 static GList *
2910 prepend_automatic_keywords (NautilusFile *file,
2911 			    GList *names)
2912 {
2913 	/* Prepend in reverse order. */
2914 	NautilusFile *parent;
2915 
2916 	parent = nautilus_file_get_parent (file);
2917 
2918 	/* Trash files are assumed to be read-only, 
2919 	 * so we want to ignore them here. */
2920 	if (!nautilus_file_can_write (file) &&
2921 	    !nautilus_file_is_in_trash (file) &&
2922 	    (parent == NULL || nautilus_file_can_write (parent))) {
2923 		names = g_list_prepend
2924 			(names, g_strdup (NAUTILUS_FILE_EMBLEM_NAME_CANT_WRITE));
2925 	}
2926 	if (!nautilus_file_can_read (file)) {
2927 		names = g_list_prepend
2928 			(names, g_strdup (NAUTILUS_FILE_EMBLEM_NAME_CANT_READ));
2929 	}
2930 	if (nautilus_file_is_symbolic_link (file)) {
2931 		names = g_list_prepend
2932 			(names, g_strdup (NAUTILUS_FILE_EMBLEM_NAME_SYMBOLIC_LINK));
2933 	}
2934 
2935 	if (parent) {
2936 		nautilus_file_unref (parent);
2937 	}
2938 		
2939 	
2940 	return names;
2941 }
2942 
2943 static int
2944 compare_by_type (NautilusFile *file_1, NautilusFile *file_2)
2945 {
2946 	gboolean is_directory_1;
2947 	gboolean is_directory_2;
2948 	char *type_string_1;
2949 	char *type_string_2;
2950 	int result;
2951 
2952 	/* Directories go first. Then, if mime types are identical,
2953 	 * don't bother getting strings (for speed). This assumes
2954 	 * that the string is dependent entirely on the mime type,
2955 	 * which is true now but might not be later.
2956 	 */
2957 	is_directory_1 = nautilus_file_is_directory (file_1);
2958 	is_directory_2 = nautilus_file_is_directory (file_2);
2959 	
2960 	if (is_directory_1 && is_directory_2) {
2961 		return 0;
2962 	}
2963 
2964 	if (is_directory_1) {
2965 		return -1;
2966 	}
2967 
2968 	if (is_directory_2) {
2969 		return +1;
2970 	}
2971 
2972 	if (file_1->details->mime_type != NULL &&
2973 	    file_2->details->mime_type != NULL &&
2974 	    strcmp (eel_ref_str_peek (file_1->details->mime_type),
2975 		    eel_ref_str_peek (file_2->details->mime_type)) == 0) {
2976 		return 0;
2977 	}
2978 
2979 	type_string_1 = nautilus_file_get_type_as_string (file_1);
2980 	type_string_2 = nautilus_file_get_type_as_string (file_2);
2981 
2982 	if (type_string_1 == NULL || type_string_2 == NULL) {
2983 		if (type_string_1 != NULL) {
2984 			return -1;
2985 		}
2986 
2987 		if (type_string_2 != NULL) {
2988 			return 1;
2989 		}
2990 
2991 		return 0;
2992 	}
2993 
2994 	result = g_utf8_collate (type_string_1, type_string_2);
2995 
2996 	g_free (type_string_1);
2997 	g_free (type_string_2);
2998 
2999 	return result;
3000 }
3001 
3002 static Knowledge
3003 get_search_relevance (NautilusFile *file,
3004 		      gdouble      *relevance_out)
3005 {
3006 	/* we're only called in search directories, and in that
3007 	 * case, the relevance is always known (or zero).
3008 	 */
3009 	*relevance_out = file->details->search_relevance;
3010 	return KNOWN;
3011 }
3012 
3013 static int
3014 compare_by_search_relevance (NautilusFile *file_1, NautilusFile *file_2)
3015 {
3016 	gdouble r_1, r_2;
3017 
3018 	get_search_relevance (file_1, &r_1);
3019 	get_search_relevance (file_2, &r_2);
3020 
3021 	if (r_1 < r_2) {
3022 		return -1;
3023 	}
3024 	if (r_1 > r_2) {
3025 		return +1;
3026 	}
3027 
3028 	return 0;
3029 }
3030 
3031 static int
3032 compare_by_time (NautilusFile *file_1, NautilusFile *file_2, NautilusDateType type)
3033 {
3034 	/* Sort order:
3035 	 *   Files with unknown times.
3036 	 *   Files with "unknowable" times.
3037 	 *   Files with older times.
3038 	 *   Files with newer times.
3039 	 */
3040 
3041 	Knowledge time_known_1, time_known_2;
3042 	time_t time_1, time_2;
3043 
3044 	time_1 = 0;
3045 	time_2 = 0;
3046 
3047 	time_known_1 = get_time (file_1, &time_1, type);
3048 	time_known_2 = get_time (file_2, &time_2, type);
3049 
3050 	if (time_known_1 > time_known_2) {
3051 		return -1;
3052 	}
3053 	if (time_known_1 < time_known_2) {
3054 		return +1;
3055 	}
3056 	
3057 	/* Now time_known_1 is equal to time_known_2. Check whether 
3058 	 * we failed to get modification times for files
3059 	 */
3060 	if(time_known_1 == UNKNOWABLE || time_known_1 == UNKNOWN) {
3061 		return 0;
3062 	}
3063 		
3064 	if (time_1 < time_2) {
3065 		return -1;
3066 	}
3067 	if (time_1 > time_2) {
3068 		return +1;
3069 	}
3070 
3071 	return 0;
3072 }
3073 
3074 static int
3075 compare_by_full_path (NautilusFile *file_1, NautilusFile *file_2)
3076 {
3077 	int compare;
3078 
3079 	compare = compare_by_directory_name (file_1, file_2);
3080 	if (compare != 0) {
3081 		return compare;
3082 	}
3083 	return compare_by_display_name (file_1, file_2);
3084 }
3085 
3086 static int
3087 nautilus_file_compare_for_sort_internal (NautilusFile *file_1,
3088 					 NautilusFile *file_2,
3089 					 gboolean directories_first,
3090 					 gboolean reversed)
3091 {
3092 	gboolean is_directory_1, is_directory_2;
3093 
3094 	if (directories_first) {
3095 		is_directory_1 = nautilus_file_is_directory (file_1);
3096 		is_directory_2 = nautilus_file_is_directory (file_2);
3097 
3098 		if (is_directory_1 && !is_directory_2) {
3099 			return -1;
3100 		}
3101 
3102 		if (is_directory_2 && !is_directory_1) {
3103 			return +1;
3104 		}
3105 	}
3106 
3107 	if (file_1->details->sort_order < file_2->details->sort_order) {
3108 		return reversed ? 1 : -1;
3109 	} else if (file_1->details->sort_order > file_2->details->sort_order) {
3110 		return reversed ? -1 : 1;
3111 	}
3112 
3113 	return 0;
3114 }
3115 
3116 /**
3117  * nautilus_file_compare_for_sort:
3118  * @file_1: A file object
3119  * @file_2: Another file object
3120  * @sort_type: Sort criterion
3121  * @directories_first: Put all directories before any non-directories
3122  * @reversed: Reverse the order of the items, except that
3123  * the directories_first flag is still respected.
3124  * 
3125  * Return value: int < 0 if @file_1 should come before file_2 in a
3126  * sorted list; int > 0 if @file_2 should come before file_1 in a
3127  * sorted list; 0 if @file_1 and @file_2 are equal for this sort criterion. Note
3128  * that each named sort type may actually break ties several ways, with the name
3129  * of the sort criterion being the primary but not only differentiator.
3130  **/
3131 int
3132 nautilus_file_compare_for_sort (NautilusFile *file_1,
3133 				NautilusFile *file_2,
3134 				NautilusFileSortType sort_type,
3135 				gboolean directories_first,
3136 				gboolean reversed)
3137 {
3138 	int result;
3139 
3140 	if (file_1 == file_2) {
3141 		return 0;
3142 	}
3143 	
3144 	result = nautilus_file_compare_for_sort_internal (file_1, file_2, directories_first, reversed);
3145 	
3146 	if (result == 0) {
3147 		switch (sort_type) {
3148 		case NAUTILUS_FILE_SORT_BY_DISPLAY_NAME:
3149 			result = compare_by_display_name (file_1, file_2);
3150 			if (result == 0) {
3151 				result = compare_by_directory_name (file_1, file_2);
3152 			}
3153 			break;
3154 		case NAUTILUS_FILE_SORT_BY_SIZE:
3155 			/* Compare directory sizes ourselves, then if necessary
3156 			 * use GnomeVFS to compare file sizes.
3157 			 */
3158 			result = compare_by_size (file_1, file_2);
3159 			if (result == 0) {
3160 				result = compare_by_full_path (file_1, file_2);
3161 			}
3162 			break;
3163 		case NAUTILUS_FILE_SORT_BY_TYPE:
3164 			/* GnomeVFS doesn't know about our special text for certain
3165 			 * mime types, so we handle the mime-type sorting ourselves.
3166 			 */
3167 			result = compare_by_type (file_1, file_2);
3168 			if (result == 0) {
3169 				result = compare_by_full_path (file_1, file_2);
3170 			}
3171 			break;
3172 		case NAUTILUS_FILE_SORT_BY_MTIME:
3173 			result = compare_by_time (file_1, file_2, NAUTILUS_DATE_TYPE_MODIFIED);
3174 			if (result == 0) {
3175 				result = compare_by_full_path (file_1, file_2);
3176 			}
3177 			break;
3178 		case NAUTILUS_FILE_SORT_BY_ATIME:
3179 			result = compare_by_time (file_1, file_2, NAUTILUS_DATE_TYPE_ACCESSED);
3180 			if (result == 0) {
3181 				result = compare_by_full_path (file_1, file_2);
3182 			}
3183 			break;
3184 		case NAUTILUS_FILE_SORT_BY_TRASHED_TIME:
3185 			result = compare_by_time (file_1, file_2, NAUTILUS_DATE_TYPE_TRASHED);
3186 			if (result == 0) {
3187 				result = compare_by_full_path (file_1, file_2);
3188 			}
3189 			break;
3190 		case NAUTILUS_FILE_SORT_BY_SEARCH_RELEVANCE:
3191 			result = compare_by_search_relevance (file_1, file_2);
3192 			if (result == 0) {
3193 				result = compare_by_full_path (file_1, file_2);
3194 			}
3195 			break;
3196 		default:
3197 			g_return_val_if_reached (0);
3198 		}
3199 
3200 		if (reversed) {
3201 			result = -result;
3202 		}
3203 	}
3204 
3205 	return result;
3206 }
3207 
3208 int
3209 nautilus_file_compare_for_sort_by_attribute_q   (NautilusFile                   *file_1,
3210 						 NautilusFile                   *file_2,
3211 						 GQuark                          attribute,
3212 						 gboolean                        directories_first,
3213 						 gboolean                        reversed)
3214 {
3215 	int result;
3216 
3217 	if (file_1 == file_2) {
3218 		return 0;
3219 	}
3220 
3221 	/* Convert certain attributes into NautilusFileSortTypes and use
3222 	 * nautilus_file_compare_for_sort()
3223 	 */
3224 	if (attribute == 0 || attribute == attribute_name_q) {
3225 		return nautilus_file_compare_for_sort (file_1, file_2,
3226 						       NAUTILUS_FILE_SORT_BY_DISPLAY_NAME,
3227 						       directories_first,
3228 						       reversed);
3229 	} else if (attribute == attribute_size_q) {
3230 		return nautilus_file_compare_for_sort (file_1, file_2,
3231 						       NAUTILUS_FILE_SORT_BY_SIZE,
3232 						       directories_first,
3233 						       reversed);
3234 	} else if (attribute == attribute_type_q) {
3235 		return nautilus_file_compare_for_sort (file_1, file_2,
3236 						       NAUTILUS_FILE_SORT_BY_TYPE,
3237 						       directories_first,
3238 						       reversed);
3239 	} else if (attribute == attribute_modification_date_q || attribute == attribute_date_modified_q || attribute == attribute_date_modified_full_q) {
3240 		return nautilus_file_compare_for_sort (file_1, file_2,
3241 						       NAUTILUS_FILE_SORT_BY_MTIME,
3242 						       directories_first,
3243 						       reversed);
3244         } else if (attribute == attribute_accessed_date_q || attribute == attribute_date_accessed_q || attribute == attribute_date_accessed_full_q) {
3245 		return nautilus_file_compare_for_sort (file_1, file_2,
3246 						       NAUTILUS_FILE_SORT_BY_ATIME,
3247 						       directories_first,
3248 						       reversed);
3249         } else if (attribute == attribute_trashed_on_q || attribute == attribute_trashed_on_full_q) {
3250 		return nautilus_file_compare_for_sort (file_1, file_2,
3251 						       NAUTILUS_FILE_SORT_BY_TRASHED_TIME,
3252 						       directories_first,
3253 						       reversed);
3254         } else if (attribute == attribute_search_relevance_q) {
3255 		return nautilus_file_compare_for_sort (file_1, file_2,
3256 						       NAUTILUS_FILE_SORT_BY_SEARCH_RELEVANCE,
3257 						       directories_first,
3258 						       reversed);
3259 	}
3260 
3261 	/* it is a normal attribute, compare by strings */
3262 
3263 	result = nautilus_file_compare_for_sort_internal (file_1, file_2, directories_first, reversed);
3264 	
3265 	if (result == 0) {
3266 		char *value_1;
3267 		char *value_2;
3268 		
3269 		value_1 = nautilus_file_get_string_attribute_q (file_1, 
3270 								attribute);
3271 		value_2 = nautilus_file_get_string_attribute_q (file_2, 
3272 								attribute);
3273 
3274 		if (value_1 != NULL && value_2 != NULL) {
3275 			result = strcmp (value_1, value_2);
3276 		}
3277 
3278 		g_free (value_1);
3279 		g_free (value_2);
3280 
3281 		if (reversed) {
3282 			result = -result;
3283 		}
3284 	}
3285 	
3286 	return result;
3287 }
3288 
3289 int
3290 nautilus_file_compare_for_sort_by_attribute     (NautilusFile                   *file_1,
3291 						 NautilusFile                   *file_2,
3292 						 const char                     *attribute,
3293 						 gboolean                        directories_first,
3294 						 gboolean                        reversed)
3295 {
3296 	return nautilus_file_compare_for_sort_by_attribute_q (file_1, file_2,
3297 							      g_quark_from_string (attribute),
3298 							      directories_first,
3299 							      reversed);
3300 }
3301 
3302 
3303 /**
3304  * nautilus_file_compare_name:
3305  * @file: A file object
3306  * @pattern: A string we are comparing it with
3307  * 
3308  * Return value: result of a comparison of the file name and the given pattern,
3309  * using the same sorting order as sort by name.
3310  **/
3311 int
3312 nautilus_file_compare_display_name (NautilusFile *file,
3313 				    const char *pattern)
3314 {
3315 	const char *name;
3316 	int result;
3317 
3318 	g_return_val_if_fail (pattern != NULL, -1);
3319 
3320 	name = nautilus_file_peek_display_name (file);
3321 	result = g_utf8_collate (name, pattern);
3322 	return result;
3323 }
3324 
3325 
3326 gboolean
3327 nautilus_file_is_hidden_file (NautilusFile *file)
3328 {
3329 	return file->details->is_hidden;
3330 }
3331 
3332 static gboolean
3333 is_file_hidden (NautilusFile *file)
3334 {
3335 	return file->details->directory->details->hidden_file_hash != NULL &&
3336 		g_hash_table_lookup (file->details->directory->details->hidden_file_hash,
3337 				     eel_ref_str_peek (file->details->name)) != NULL;
3338 	
3339 }
3340 
3341 /**
3342  * nautilus_file_should_show:
3343  * @file: the file to check.
3344  * @show_hidden: whether we want to show hidden files or not.
3345  * 
3346  * Determines if a #NautilusFile should be shown. Note that when browsing
3347  * a trash directory, this function will always return %TRUE. 
3348  *
3349  * Returns: %TRUE if the file should be shown, %FALSE if it shouldn't.
3350  */
3351 gboolean 
3352 nautilus_file_should_show (NautilusFile *file, 
3353 			   gboolean show_hidden,
3354 			   gboolean show_foreign)
3355 {
3356 	/* Never hide any files in trash. */
3357 	if (nautilus_file_is_in_trash (file)) {
3358 		return TRUE;
3359 	} else {
3360 		return (show_hidden || (!nautilus_file_is_hidden_file (file) && !is_file_hidden (file))) &&
3361 			(show_foreign || !(nautilus_file_is_in_desktop (file) && nautilus_file_is_foreign_link (file)));
3362 	}
3363 }
3364 
3365 gboolean
3366 nautilus_file_is_home (NautilusFile *file)
3367 {
3368 	GFile *dir;
3369 
3370 	dir = file->details->directory->details->location;
3371 	if (dir == NULL) {
3372 		return FALSE;
3373 	}
3374 
3375 	return nautilus_is_home_directory_file (dir,
3376 						eel_ref_str_peek (file->details->name));
3377 }
3378 
3379 gboolean
3380 nautilus_file_is_in_desktop (NautilusFile *file)
3381 {
3382 	if (file->details->directory->details->location) {
3383 		return nautilus_is_desktop_directory (file->details->directory->details->location);
3384 	}
3385 	return FALSE;
3386 }
3387 
3388 gboolean
3389 nautilus_file_is_in_search (NautilusFile *file)
3390 {
3391 	char *uri;
3392 	gboolean ret;
3393 
3394 	uri = nautilus_file_get_uri (file);
3395 	ret = eel_uri_is_search (uri);
3396 	g_free (uri);
3397 
3398 	return ret;
3399 }
3400 
3401 static gboolean
3402 filter_hidden_partition_callback (gpointer data,
3403 				  gpointer callback_data)
3404 {
3405 	NautilusFile *file;
3406 	FilterOptions options;
3407 
3408 	file = NAUTILUS_FILE (data);
3409 	options = GPOINTER_TO_INT (callback_data);
3410 
3411 	return nautilus_file_should_show (file,
3412 					  options & SHOW_HIDDEN,
3413 					  TRUE);
3414 }
3415 
3416 GList *
3417 nautilus_file_list_filter_hidden (GList    *files,
3418 				  gboolean  show_hidden)
3419 {
3420 	GList *filtered_files;
3421 	GList *removed_files;
3422 
3423 	/* FIXME bugzilla.gnome.org 40653:
3424 	 * Eventually this should become a generic filtering thingy.
3425 	 */
3426 
3427 	filtered_files = nautilus_file_list_copy (files);
3428 	filtered_files = eel_g_list_partition (filtered_files,
3429 					       filter_hidden_partition_callback,
3430 					       GINT_TO_POINTER ((show_hidden ? SHOW_HIDDEN : 0)),
3431 					       &removed_files);
3432 	nautilus_file_list_free (removed_files);
3433 
3434 	return filtered_files;
3435 }
3436 
3437 char *
3438 nautilus_file_get_metadata (NautilusFile *file,
3439 			    const char *key,
3440 			    const char *default_metadata)
3441 {
3442 	guint id;
3443 	char *value;
3444 
3445 	g_return_val_if_fail (key != NULL, g_strdup (default_metadata));
3446 	g_return_val_if_fail (key[0] != '\0', g_strdup (default_metadata));
3447 
3448 	if (file == NULL ||
3449 	    file->details->metadata == NULL) {
3450 		return g_strdup (default_metadata);
3451 	}
3452 
3453 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), g_strdup (default_metadata));
3454 
3455 	id = nautilus_metadata_get_id (key);
3456 	value = g_hash_table_lookup (file->details->metadata, GUINT_TO_POINTER (id));
3457 
3458 	if (value) {
3459 		return g_strdup (value);
3460 	}
3461 	return g_strdup (default_metadata);
3462 }
3463 
3464 GList *
3465 nautilus_file_get_metadata_list (NautilusFile *file,
3466 				 const char *key)
3467 {
3468 	GList *res;
3469 	guint id;
3470 	char **value;
3471 	int i;
3472 
3473 	g_return_val_if_fail (key != NULL, NULL);
3474 	g_return_val_if_fail (key[0] != '\0', NULL);
3475 
3476 	if (file == NULL ||
3477 	    file->details->metadata == NULL) {
3478 		return NULL;
3479 	}
3480 
3481 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
3482 
3483 	id = nautilus_metadata_get_id (key);
3484 	id |= METADATA_ID_IS_LIST_MASK;
3485 
3486 	value = g_hash_table_lookup (file->details->metadata, GUINT_TO_POINTER (id));
3487 
3488 	if (value) {
3489 		res = NULL;
3490 		for (i = 0; value[i] != NULL; i++) {
3491 			res = g_list_prepend (res, g_strdup (value[i]));
3492 		}
3493 		return g_list_reverse (res);
3494 	}
3495 
3496 	return NULL;
3497 }
3498 
3499 void
3500 nautilus_file_set_metadata (NautilusFile *file,
3501 			    const char *key,
3502 			    const char *default_metadata,
3503 			    const char *metadata)
3504 {
3505 	const char *val;
3506 
3507 	g_return_if_fail (NAUTILUS_IS_FILE (file));
3508 	g_return_if_fail (key != NULL);
3509 	g_return_if_fail (key[0] != '\0');
3510 
3511 	val = metadata;
3512 	if (val == NULL) {
3513 		val = default_metadata;
3514 	}
3515 
3516 	NAUTILUS_FILE_CLASS (G_OBJECT_GET_CLASS (file))->set_metadata (file, key, val);
3517 }
3518 
3519 void
3520 nautilus_file_set_metadata_list (NautilusFile *file,
3521 				 const char *key,
3522 				 GList *list)
3523 {
3524 	char **val;
3525 	int len, i;
3526 	GList *l;
3527 
3528 	g_return_if_fail (NAUTILUS_IS_FILE (file));
3529 	g_return_if_fail (key != NULL);
3530 	g_return_if_fail (key[0] != '\0');
3531 
3532 	len = g_list_length (list);
3533 	val = g_new (char *, len + 1);
3534 	for (l = list, i = 0; l != NULL; l = l->next, i++) {
3535 		val[i] = l->data;
3536 	}
3537 	val[i] = NULL;
3538 
3539 	NAUTILUS_FILE_CLASS (G_OBJECT_GET_CLASS (file))->set_metadata_as_list (file, key, val);
3540 
3541 	g_free (val);
3542 }
3543 
3544 gboolean
3545 nautilus_file_get_boolean_metadata (NautilusFile *file,
3546 				    const char   *key,
3547 				    gboolean      default_metadata)
3548 {
3549 	char *result_as_string;
3550 	gboolean result;
3551 
3552 	g_return_val_if_fail (key != NULL, default_metadata);
3553 	g_return_val_if_fail (key[0] != '\0', default_metadata);
3554 
3555 	if (file == NULL) {
3556 		return default_metadata;
3557 	}
3558 
3559 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), default_metadata);
3560 
3561 	result_as_string = nautilus_file_get_metadata
3562 		(file, key, default_metadata ? "true" : "false");
3563 	g_assert (result_as_string != NULL);
3564 
3565 	if (g_ascii_strcasecmp (result_as_string, "true") == 0) {
3566 		result = TRUE;
3567 	} else if (g_ascii_strcasecmp (result_as_string, "false") == 0) {
3568 		result = FALSE;
3569 	} else {
3570 		g_error ("boolean metadata with value other than true or false");
3571 		result = default_metadata;
3572 	}
3573 
3574 	g_free (result_as_string);
3575 	return result;
3576 }
3577 
3578 int
3579 nautilus_file_get_integer_metadata (NautilusFile *file,
3580 				    const char   *key,
3581 				    int           default_metadata)
3582 {
3583 	char *result_as_string;
3584 	char default_as_string[32];
3585 	int result;
3586 	char c;
3587 
3588 	g_return_val_if_fail (key != NULL, default_metadata);
3589 	g_return_val_if_fail (key[0] != '\0', default_metadata);
3590 
3591 	if (file == NULL) {
3592 		return default_metadata;
3593 	}
3594 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), default_metadata);
3595 
3596 	g_snprintf (default_as_string, sizeof (default_as_string), "%d", default_metadata);
3597 	result_as_string = nautilus_file_get_metadata
3598 		(file, key, default_as_string);
3599 
3600 	/* Normally we can't get a a NULL, but we check for it here to
3601 	 * handle the oddball case of a non-existent directory.
3602 	 */
3603 	if (result_as_string == NULL) {
3604 		result = default_metadata;
3605 	} else {
3606 		if (sscanf (result_as_string, " %d %c", &result, &c) != 1) {
3607 			result = default_metadata;
3608 		}
3609 		g_free (result_as_string);
3610 	}
3611 
3612 	return result;
3613 }
3614 
3615 static gboolean
3616 get_time_from_time_string (const char *time_string,
3617 			   time_t *time)
3618 {
3619 	long scanned_time;
3620 	char c;
3621 
3622 	g_assert (time != NULL);
3623 
3624 	/* Only accept string if it has one integer with nothing
3625 	 * afterwards.
3626 	 */
3627 	if (time_string == NULL ||
3628 	    sscanf (time_string, "%ld%c", &scanned_time, &c) != 1) {
3629 		return FALSE;
3630 	}
3631 	*time = (time_t) scanned_time;
3632 	return TRUE;
3633 }
3634 
3635 time_t
3636 nautilus_file_get_time_metadata (NautilusFile *file,
3637 				 const char   *key)
3638 {
3639 	time_t time;
3640 	char *time_string;
3641 
3642 	time_string = nautilus_file_get_metadata (file, key, NULL);
3643 	if (!get_time_from_time_string (time_string, &time)) {
3644 		time = UNDEFINED_TIME;
3645 	}
3646 	g_free (time_string);
3647 
3648 	return time;
3649 }
3650 
3651 void
3652 nautilus_file_set_time_metadata (NautilusFile *file,
3653 				 const char   *key,
3654 				 time_t        time)
3655 {
3656 	char time_str[21];
3657 	char *metadata;
3658 
3659 	if (time != UNDEFINED_TIME) {
3660 		/* 2^64 turns out to be 20 characters */
3661 		g_snprintf (time_str, 20, "%ld", (long int)time);
3662 		time_str[20] = '\0';
3663 		metadata = time_str;
3664 	} else {
3665 		metadata = NULL;
3666 	}
3667 
3668 	nautilus_file_set_metadata (file, key, NULL, metadata);
3669 }
3670 
3671 
3672 void
3673 nautilus_file_set_boolean_metadata (NautilusFile *file,
3674 				    const char   *key,
3675 				    gboolean      default_metadata,
3676 				    gboolean      metadata)
3677 {
3678 	g_return_if_fail (NAUTILUS_IS_FILE (file));
3679 	g_return_if_fail (key != NULL);
3680 	g_return_if_fail (key[0] != '\0');
3681 
3682 	nautilus_file_set_metadata (file, key,
3683 				    default_metadata ? "true" : "false",
3684 				    metadata ? "true" : "false");
3685 }
3686 
3687 void
3688 nautilus_file_set_integer_metadata (NautilusFile *file,
3689 				    const char   *key,
3690 				    int           default_metadata,
3691 				    int           metadata)
3692 {
3693 	char value_as_string[32];
3694 	char default_as_string[32];
3695 
3696 	g_return_if_fail (NAUTILUS_IS_FILE (file));
3697 	g_return_if_fail (key != NULL);
3698 	g_return_if_fail (key[0] != '\0');
3699 
3700 	g_snprintf (value_as_string, sizeof (value_as_string), "%d", metadata);
3701 	g_snprintf (default_as_string, sizeof (default_as_string), "%d", default_metadata);
3702 
3703 	nautilus_file_set_metadata (file, key,
3704 				    default_as_string, value_as_string);
3705 }
3706 
3707 static const char *
3708 nautilus_file_peek_display_name_collation_key (NautilusFile *file)
3709 {
3710 	const char *res;
3711 
3712 	res = file->details->display_name_collation_key;
3713 	if (res == NULL)
3714 		res = "";
3715 
3716 	return res;
3717 }
3718 
3719 static const char *
3720 nautilus_file_peek_display_name (NautilusFile *file)
3721 {
3722 	const char *name;
3723 	char *escaped_name;
3724 
3725 	/* FIXME: for some reason we can get a NautilusFile instance which is
3726 	 *        no longer valid or could be freed somewhere else in the same time.
3727 	 *        There's race condition somewhere. See bug 602500.
3728 	 */
3729 	if (file == NULL || nautilus_file_is_gone (file))
3730 		return "";
3731 
3732 	/* Default to display name based on filename if its not set yet */
3733 	
3734 	if (file->details->display_name == NULL) {
3735 		name = eel_ref_str_peek (file->details->name);
3736 		if (g_utf8_validate (name, -1, NULL)) {
3737 			nautilus_file_set_display_name (file,
3738 							name,
3739 							NULL,
3740 							FALSE);
3741 		} else {
3742 			escaped_name = g_uri_escape_string (name, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, TRUE);
3743 			nautilus_file_set_display_name (file,
3744 							escaped_name,
3745 							NULL,
3746 							FALSE);
3747 			g_free (escaped_name);
3748 		}
3749 	}
3750 	
3751 	return eel_ref_str_peek (file->details->display_name);
3752 }
3753 
3754 char *
3755 nautilus_file_get_display_name (NautilusFile *file)
3756 {
3757 	return g_strdup (nautilus_file_peek_display_name (file));
3758 }
3759 
3760 char *
3761 nautilus_file_get_edit_name (NautilusFile *file)
3762 {
3763 	const char *res;
3764 	
3765 	res = eel_ref_str_peek (file->details->edit_name);
3766 	if (res == NULL)
3767 		res = "";
3768 	
3769 	return g_strdup (res);
3770 }
3771 
3772 char *
3773 nautilus_file_get_name (NautilusFile *file)
3774 {
3775 	return g_strdup (eel_ref_str_peek (file->details->name));
3776 }
3777 
3778 /**
3779  * nautilus_file_get_description:
3780  * @file: a #NautilusFile.
3781  * 
3782  * Gets the standard::description key from @file, if 
3783  * it has been cached.
3784  * 
3785  * Returns: a string containing the value of the standard::description 
3786  * 	key, or %NULL.
3787  */
3788 char *
3789 nautilus_file_get_description (NautilusFile *file)
3790 {
3791 	return g_strdup (file->details->description);
3792 }
3793    
3794 void             
3795 nautilus_file_monitor_add (NautilusFile *file,
3796 			   gconstpointer client,
3797 			   NautilusFileAttributes attributes)
3798 {
3799 	g_return_if_fail (NAUTILUS_IS_FILE (file));
3800 	g_return_if_fail (client != NULL);
3801 
3802 	NAUTILUS_FILE_CLASS (G_OBJECT_GET_CLASS (file))->monitor_add (file, client, attributes);
3803 }   
3804 			   
3805 void
3806 nautilus_file_monitor_remove (NautilusFile *file,
3807 			      gconstpointer client)
3808 {
3809 	g_return_if_fail (NAUTILUS_IS_FILE (file));
3810 	g_return_if_fail (client != NULL);
3811 
3812 	NAUTILUS_FILE_CLASS (G_OBJECT_GET_CLASS (file))->monitor_remove (file, client);
3813 }			      
3814 
3815 gboolean
3816 nautilus_file_is_launcher (NautilusFile *file)
3817 {
3818 	return file->details->is_launcher;
3819 }
3820 
3821 gboolean
3822 nautilus_file_is_foreign_link (NautilusFile *file)
3823 {
3824 	return file->details->is_foreign_link;
3825 }
3826 
3827 gboolean
3828 nautilus_file_is_trusted_link (NautilusFile *file)
3829 {
3830 	return file->details->is_trusted_link;
3831 }
3832 
3833 gboolean
3834 nautilus_file_has_activation_uri (NautilusFile *file)
3835 {
3836 	return file->details->activation_uri != NULL;
3837 }
3838 
3839 
3840 /* Return the uri associated with the passed-in file, which may not be
3841  * the actual uri if the file is an desktop file or a nautilus
3842  * xml link file.
3843  */
3844 char *
3845 nautilus_file_get_activation_uri (NautilusFile *file)
3846 {
3847 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
3848 
3849 	if (file->details->activation_uri != NULL) {
3850 		return g_strdup (file->details->activation_uri);
3851 	}
3852 	
3853 	return nautilus_file_get_uri (file);
3854 }
3855 
3856 GFile *
3857 nautilus_file_get_activation_location (NautilusFile *file)
3858 {
3859 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
3860 
3861 	if (file->details->activation_uri != NULL) {
3862 		return g_file_new_for_uri (file->details->activation_uri);
3863 	}
3864 	
3865 	return nautilus_file_get_location (file);
3866 }
3867 
3868 
3869 char *
3870 nautilus_file_get_drop_target_uri (NautilusFile *file)
3871 {
3872 	char *uri, *target_uri;
3873 	GFile *location;
3874 	NautilusDesktopLink *link;
3875 	
3876 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
3877 
3878 	if (NAUTILUS_IS_DESKTOP_ICON_FILE (file)) {
3879 		link = nautilus_desktop_icon_file_get_link (NAUTILUS_DESKTOP_ICON_FILE (file));
3880 
3881 		if (link != NULL) {
3882 			location = nautilus_desktop_link_get_activation_location (link);
3883 			g_object_unref (link);
3884 			if (location != NULL) {
3885 				uri = g_file_get_uri (location);
3886 				g_object_unref (location);
3887 				return uri;
3888 			}
3889 		}
3890 	}
3891 	
3892 	uri = nautilus_file_get_uri (file);
3893 			
3894 	/* Check for Nautilus link */
3895 	if (nautilus_file_is_nautilus_link (file)) {
3896 		location = nautilus_file_get_location (file);
3897 		/* FIXME bugzilla.gnome.org 43020: This does sync. I/O and works only locally. */
3898 		if (g_file_is_native (location)) {
3899 			target_uri = nautilus_link_local_get_link_uri (uri);
3900 			if (target_uri != NULL) {
3901 				g_free (uri);
3902 				uri = target_uri;
3903 			}
3904 		}
3905 		g_object_unref (location);
3906 	}
3907 
3908 	return uri;
3909 }
3910 
3911 static gboolean
3912 is_uri_relative (const char *uri)
3913 {
3914 	char *scheme;
3915 	gboolean ret;
3916 
3917 	scheme = g_uri_parse_scheme (uri);
3918 	ret = (scheme == NULL);
3919 	g_free (scheme);
3920 	return ret;
3921 }
3922 
3923 static char *
3924 get_custom_icon_metadata_uri (NautilusFile *file)
3925 {
3926 	char *custom_icon_uri;
3927 	char *uri;
3928 	char *dir_uri;
3929 	
3930 	uri = nautilus_file_get_metadata (file, NAUTILUS_METADATA_KEY_CUSTOM_ICON, NULL);
3931 	if (uri != NULL &&
3932 	    nautilus_file_is_directory (file) &&
3933 	    is_uri_relative (uri)) {
3934 		dir_uri = nautilus_file_get_uri (file);
3935 		custom_icon_uri = g_build_filename (dir_uri, uri, NULL);
3936 		g_free (dir_uri);
3937 		g_free (uri);
3938 	} else {
3939 		custom_icon_uri = uri;
3940 	}
3941 	return custom_icon_uri;
3942 }
3943 
3944 static char *
3945 get_custom_icon_metadata_name (NautilusFile *file)
3946 {
3947 	char *icon_name;
3948 
3949 	icon_name = nautilus_file_get_metadata (file,
3950 						NAUTILUS_METADATA_KEY_CUSTOM_ICON_NAME, NULL);
3951 
3952 	return icon_name;
3953 }
3954 
3955 static GIcon *
3956 get_link_icon (NautilusFile *file)
3957 {
3958 	GIcon *icon = NULL;
3959 
3960 	if (file->details->got_link_info && file->details->custom_icon != NULL) {
3961 		icon = g_object_ref (file->details->custom_icon);
3962 	}
3963 
3964 	return icon;
3965 }
3966 
3967 static GIcon *
3968 get_custom_icon (NautilusFile *file)
3969 {
3970 	char *custom_icon_uri, *custom_icon_name;
3971 	GFile *icon_file;
3972 	GIcon *icon;
3973 
3974 	if (file == NULL) {
3975 		return NULL;
3976 	}
3977 
3978 	icon = NULL;
3979 	
3980 	/* Metadata takes precedence; first we look at the custom
3981 	 * icon URI, then at the custom icon name.
3982 	 */
3983 	custom_icon_uri = get_custom_icon_metadata_uri (file);
3984 
3985 	if (custom_icon_uri) {
3986 		icon_file = g_file_new_for_uri (custom_icon_uri);
3987 		icon = g_file_icon_new (icon_file);
3988 		g_object_unref (icon_file);
3989 		g_free (custom_icon_uri);
3990 	}
3991 
3992 	if (icon == NULL) {
3993 		custom_icon_name = get_custom_icon_metadata_name (file);
3994 
3995 		if (custom_icon_name != NULL) {
3996 			icon = g_themed_icon_new_with_default_fallbacks (custom_icon_name);
3997 			g_free (custom_icon_name);
3998 		}
3999 	}
4000 
4001 	return icon;
4002 }
4003 
4004 GFilesystemPreviewType
4005 nautilus_file_get_filesystem_use_preview (NautilusFile *file)
4006 {
4007 	GFilesystemPreviewType use_preview;
4008 	NautilusFile *parent;
4009 
4010 	parent = nautilus_file_get_parent (file);
4011 	if (parent != NULL) {
4012 		use_preview = parent->details->filesystem_use_preview;
4013 		g_object_unref (parent);
4014 	} else {
4015 		use_preview = 0;
4016 	}
4017 
4018 	return use_preview;
4019 }
4020 
4021 gboolean
4022 nautilus_file_should_show_thumbnail (NautilusFile *file)
4023 {
4024 	const char *mime_type;
4025 	GFilesystemPreviewType use_preview;
4026 
4027 	use_preview = nautilus_file_get_filesystem_use_preview (file);
4028 
4029 	mime_type = eel_ref_str_peek (file->details->mime_type);
4030 	if (mime_type == NULL) {
4031 		mime_type = "application/octet-stream";
4032 	}
4033 
4034 	/* If the thumbnail has already been created, don't care about the size
4035 	 * of the original file.
4036 	 */
4037 	if (nautilus_thumbnail_is_mimetype_limited_by_size (mime_type) &&
4038 	    file->details->thumbnail_path == NULL &&
4039 	    nautilus_file_get_size (file) > cached_thumbnail_limit) {
4040 		return FALSE;
4041 	}
4042 
4043 	if (show_file_thumbs == NAUTILUS_SPEED_TRADEOFF_ALWAYS) {
4044 		if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
4045 			return FALSE;
4046 		} else {
4047 			return TRUE;
4048 		}
4049 	} else if (show_file_thumbs == NAUTILUS_SPEED_TRADEOFF_NEVER) {
4050 		return FALSE;
4051 	} else {
4052 		if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
4053 			/* file system says to never thumbnail anything */
4054 			return FALSE;
4055 		} else if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL) {
4056 			/* file system says we should treat file as if it's local */
4057 			return TRUE;
4058 		} else {
4059 			/* only local files */
4060 			return nautilus_file_is_local (file);
4061 		}
4062 	}
4063 
4064 	return FALSE;
4065 }
4066 
4067 static void
4068 prepend_icon_name (const char *name,
4069 		   GThemedIcon *icon)
4070 {
4071 	g_themed_icon_prepend_name(icon, name);
4072 }
4073 
4074 GIcon *
4075 nautilus_file_get_gicon (NautilusFile *file,
4076 			 NautilusFileIconFlags flags)
4077 {
4078 	const char * const * names;
4079 	const char *name;
4080 	GPtrArray *prepend_array;
4081 	GMount *mount;
4082 	GIcon *icon, *mount_icon = NULL, *emblemed_icon;
4083 	GEmblem *emblem;
4084 	int i;
4085 	gboolean is_folder = FALSE, is_preview = FALSE, is_inode_directory = FALSE;
4086 
4087 	if (file == NULL) {
4088 		return NULL;
4089 	}
4090 
4091 	icon = get_custom_icon (file);
4092 
4093 	if (icon != NULL) {
4094 		return icon;
4095 	}
4096 
4097 	icon = get_link_icon (file);
4098 
4099 	if (icon != NULL) {
4100 		return icon;
4101 	}
4102 
4103 	if (file->details->icon) {
4104 		icon = NULL;
4105 
4106 		/* fetch the mount icon here, we'll use it later */
4107 		if (flags & NAUTILUS_FILE_ICON_FLAGS_USE_MOUNT_ICON ||
4108 		    flags & NAUTILUS_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) {
4109 			mount = nautilus_file_get_mount (file);
4110 
4111 			if (mount != NULL) {
4112 				mount_icon = g_mount_get_icon (mount);
4113 				g_object_unref (mount);
4114 			}
4115 		}
4116 
4117 		if (((flags & NAUTILUS_FILE_ICON_FLAGS_EMBEDDING_TEXT) ||
4118 		     (flags & NAUTILUS_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT) ||
4119 		     (flags & NAUTILUS_FILE_ICON_FLAGS_FOR_OPEN_FOLDER) ||
4120 		     (flags & NAUTILUS_FILE_ICON_FLAGS_USE_MOUNT_ICON) ||
4121 		     (flags & NAUTILUS_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) ||
4122 		     ((flags & NAUTILUS_FILE_ICON_FLAGS_IGNORE_VISITING) == 0 &&
4123 		      nautilus_file_has_open_window (file))) &&
4124 		    G_IS_THEMED_ICON (file->details->icon)) {
4125 			names = g_themed_icon_get_names (G_THEMED_ICON (file->details->icon));
4126 			prepend_array = g_ptr_array_new ();
4127 
4128 			for (i = 0; names[i] != NULL; i++) {
4129 				name = names[i];
4130 
4131 				if (strcmp (name, "folder") == 0) {
4132 					is_folder = TRUE;
4133 				}
4134 				if (strcmp (name, "inode-directory") == 0) {
4135 					is_inode_directory = TRUE;
4136 				}
4137 				if (strcmp (name, "text-x-generic") == 0 &&
4138 				    (flags & NAUTILUS_FILE_ICON_FLAGS_EMBEDDING_TEXT)) {
4139 					is_preview = TRUE;
4140 				}
4141 			}
4142 
4143 			/* Here, we add icons in reverse order of precedence,
4144 			 * because they are later prepended */
4145 			if (is_preview) {
4146 				g_ptr_array_add (prepend_array, "text-x-preview");
4147 			}
4148 			
4149 			/* "folder" should override "inode-directory", not the other way around */
4150 			if (is_inode_directory) {
4151 				g_ptr_array_add (prepend_array, "folder");
4152 			}
4153 			if (is_folder && (flags & NAUTILUS_FILE_ICON_FLAGS_FOR_OPEN_FOLDER)) {
4154 				g_ptr_array_add (prepend_array, "folder-open");
4155 			}
4156 			if (is_folder &&
4157 			    (flags & NAUTILUS_FILE_ICON_FLAGS_IGNORE_VISITING) == 0 &&
4158 			    nautilus_file_has_open_window (file)) {
4159 				g_ptr_array_add (prepend_array, "folder-visiting");
4160 			}
4161 			if (is_folder &&
4162 			    (flags & NAUTILUS_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT)) {
4163 				g_ptr_array_add (prepend_array, "folder-drag-accept");
4164 			}
4165 
4166 			if (prepend_array->len) {
4167 				/* When constructing GThemed Icon, pointers from the array
4168 				 * are reused, but not the array itself, so the cast is safe */
4169 				icon = g_themed_icon_new_from_names ((char**) names, -1);
4170 				g_ptr_array_foreach (prepend_array, (GFunc) prepend_icon_name, icon);
4171 			}
4172 
4173 			g_ptr_array_free (prepend_array, TRUE);
4174 		}
4175 
4176 		if (icon == NULL) {
4177 			icon = g_object_ref (file->details->icon);
4178 		}
4179 
4180 		if ((flags & NAUTILUS_FILE_ICON_FLAGS_USE_MOUNT_ICON) &&
4181 		    mount_icon != NULL) {
4182 			g_object_unref (icon);
4183 			icon = mount_icon;
4184 		} else if ((flags & NAUTILUS_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) &&
4185 			     mount_icon != NULL && !g_icon_equal (mount_icon, icon)) {
4186 
4187 			emblem = g_emblem_new (mount_icon);
4188 			emblemed_icon = g_emblemed_icon_new (icon, emblem);
4189 
4190 			g_object_unref (emblem);
4191 			g_object_unref (icon);
4192 			g_object_unref (mount_icon);
4193 
4194 			icon = emblemed_icon;
4195 		} else if (mount_icon != NULL) {
4196 			g_object_unref (mount_icon);
4197 		}
4198 
4199 		return icon;
4200 	}
4201 	
4202 	return g_themed_icon_new ("text-x-generic");
4203 }
4204 
4205 static GIcon *
4206 get_default_file_icon (NautilusFileIconFlags flags)
4207 {
4208 	static GIcon *fallback_icon = NULL;
4209 	static GIcon *fallback_icon_preview = NULL;
4210 	if (fallback_icon == NULL) {
4211 		fallback_icon = g_themed_icon_new ("text-x-generic");
4212 		fallback_icon_preview = g_themed_icon_new ("text-x-preview");
4213 		g_themed_icon_append_name (G_THEMED_ICON (fallback_icon_preview), "text-x-generic");
4214 	}
4215 	if (flags & NAUTILUS_FILE_ICON_FLAGS_EMBEDDING_TEXT) {
4216 		return fallback_icon_preview;
4217 	} else {
4218 		return fallback_icon;
4219 	}
4220 }
4221 
4222 char *
4223 nautilus_file_get_thumbnail_path (NautilusFile *file)
4224 {
4225 	return g_strdup (file->details->thumbnail_path);
4226 }
4227 
4228 NautilusIconInfo *
4229 nautilus_file_get_icon (NautilusFile *file,
4230 			int size,
4231 			NautilusFileIconFlags flags)
4232 {
4233 	NautilusIconInfo *icon;
4234 	GIcon *gicon;
4235 	GdkPixbuf *raw_pixbuf, *scaled_pixbuf;
4236 	int modified_size;
4237 
4238 	if (file == NULL) {
4239 		return NULL;
4240 	}
4241 
4242 	gicon = get_custom_icon (file);
4243 	if (gicon == NULL) {
4244 		gicon = get_link_icon (file);
4245 	}
4246 
4247 	if (gicon != NULL) {
4248 		icon = nautilus_icon_info_lookup (gicon, size);
4249 		g_object_unref (gicon);
4250 
4251 		return icon;
4252 	}
4253 
4254 	DEBUG ("Called file_get_icon(), at size %d, force thumbnail %d", size,
4255 	       flags & NAUTILUS_FILE_ICON_FLAGS_FORCE_THUMBNAIL_SIZE);
4256 	
4257 	if (flags & NAUTILUS_FILE_ICON_FLAGS_FORCE_THUMBNAIL_SIZE) {
4258 		modified_size = size;
4259 	} else {
4260 		modified_size = size * cached_thumbnail_size / NAUTILUS_ICON_SIZE_STANDARD;
4261 		DEBUG ("Modifying icon size to %d, as our cached thumbnail size is %d",
4262 		       modified_size, cached_thumbnail_size);
4263 	}
4264 
4265 	if (flags & NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS &&
4266 	    nautilus_file_should_show_thumbnail (file)) {
4267 		if (file->details->thumbnail) {
4268 			int w, h, s;
4269 			double scale;
4270 
4271 			raw_pixbuf = g_object_ref (file->details->thumbnail);
4272 
4273 			w = gdk_pixbuf_get_width (raw_pixbuf);
4274 			h = gdk_pixbuf_get_height (raw_pixbuf);
4275 			
4276 			s = MAX (w, h);			
4277 			/* Don't scale up small thumbnails in the standard view */
4278 			if (s <= cached_thumbnail_size) {
4279 				scale = (double)size / NAUTILUS_ICON_SIZE_STANDARD;
4280 			}
4281 			else {
4282 				scale = (double)modified_size / s;
4283 			}
4284 			/* Make sure that icons don't get smaller than NAUTILUS_ICON_SIZE_SMALLEST */
4285 			if (s*scale <= NAUTILUS_ICON_SIZE_SMALLEST) {
4286 				scale = (double) NAUTILUS_ICON_SIZE_SMALLEST / s;
4287 			}
4288 
4289 			scaled_pixbuf = gdk_pixbuf_scale_simple (raw_pixbuf,
4290 								 MAX (w * scale, 1),
4291 								 MAX (h * scale, 1),
4292 								 GDK_INTERP_BILINEAR);
4293 
4294 			/* We don't want frames around small icons */
4295 			if (!gdk_pixbuf_get_has_alpha (raw_pixbuf) || s >= 128) {
4296 				nautilus_ui_frame_image (&scaled_pixbuf);
4297 			}
4298 
4299 			g_object_unref (raw_pixbuf);
4300 
4301 			/* Don't scale up if more than 25%, then read the original
4302 			   image instead. We don't want to compare to exactly 100%,
4303 			   since the zoom level 150% gives thumbnails at 144, which is
4304 			   ok to scale up from 128. */
4305 			if (modified_size > 128*1.25 &&
4306 			    !file->details->thumbnail_wants_original &&
4307 			    nautilus_can_thumbnail_internally (file)) {
4308 				/* Invalidate if we resize upward */
4309 				file->details->thumbnail_wants_original = TRUE;
4310 				nautilus_file_invalidate_attributes (file, NAUTILUS_FILE_ATTRIBUTE_THUMBNAIL);
4311 			}
4312 
4313 			DEBUG ("Returning thumbnailed image, at size %d %d",
4314 			       (int) (w * scale), (int) (h * scale));
4315 			
4316 			icon = nautilus_icon_info_new_for_pixbuf (scaled_pixbuf);
4317 			g_object_unref (scaled_pixbuf);
4318 			return icon;
4319 		} else if (file->details->thumbnail_path == NULL &&
4320 			   file->details->can_read &&				
4321 			   !file->details->is_thumbnailing &&
4322 			   !file->details->thumbnailing_failed) {
4323 			if (nautilus_can_thumbnail (file)) {
4324 				nautilus_create_thumbnail (file);
4325 			}
4326 		}
4327 	}
4328 
4329 	if (file->details->is_thumbnailing &&
4330 	    flags & NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS)
4331 		gicon = g_themed_icon_new (ICON_NAME_THUMBNAIL_LOADING);
4332 	else
4333 		gicon = nautilus_file_get_gicon (file, flags);
4334 	
4335 	if (gicon) {
4336 		icon = nautilus_icon_info_lookup (gicon, size);
4337 		if (nautilus_icon_info_is_fallback (icon)) {
4338 			g_object_unref (icon);
4339 			icon = nautilus_icon_info_lookup (get_default_file_icon (flags), size);
4340 		}
4341 		g_object_unref (gicon);
4342 		return icon;
4343 	} else {
4344 		return nautilus_icon_info_lookup (get_default_file_icon (flags), size);
4345 	}
4346 }
4347 
4348 GdkPixbuf *
4349 nautilus_file_get_icon_pixbuf (NautilusFile *file,
4350 			       int size,
4351 			       gboolean force_size,
4352 			       NautilusFileIconFlags flags)
4353 {
4354 	NautilusIconInfo *info;
4355 	GdkPixbuf *pixbuf;
4356 
4357 	info = nautilus_file_get_icon (file, size, flags);
4358 	if (force_size) {
4359 		pixbuf =  nautilus_icon_info_get_pixbuf_at_size (info, size);
4360 	} else {
4361 		pixbuf = nautilus_icon_info_get_pixbuf (info);
4362 	}
4363 	g_object_unref (info);
4364 	
4365 	return pixbuf;
4366 }
4367 
4368 gboolean
4369 nautilus_file_get_date (NautilusFile *file,
4370 			NautilusDateType date_type,
4371 			time_t *date)
4372 {
4373 	if (date != NULL) {
4374 		*date = 0;
4375 	}
4376 
4377 	g_return_val_if_fail (date_type == NAUTILUS_DATE_TYPE_ACCESSED
4378 			      || date_type == NAUTILUS_DATE_TYPE_MODIFIED
4379 			      || date_type == NAUTILUS_DATE_TYPE_TRASHED,
4380 			      FALSE);
4381 
4382 	if (file == NULL) {
4383 		return FALSE;
4384 	}
4385 
4386 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
4387 
4388 	return NAUTILUS_FILE_CLASS (G_OBJECT_GET_CLASS (file))->get_date (file, date_type, date);
4389 }
4390 
4391 static char *
4392 nautilus_file_get_where_string (NautilusFile *file)
4393 {
4394 	if (file == NULL) {
4395 		return NULL;
4396 	}
4397 
4398 	g_return_val_if_fail (NAUTILUS_IS_FILE