Subject: limit deep search ( folder contents count and size ) to one filesystem
Author: Phillip Susi <psusi@ubuntu.com>
Description: When getting the size of the root directory, nautilus was descending
  into other filesystems including /proc, causing it to report nonsensical sizes.
  Store the fsid of the starting directory, and do not recurse into other mount
  points.
Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/nautilus/+bug/585472
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=629394


Index: b/libnautilus-private/nautilus-directory-async.c
===================================================================
--- a/libnautilus-private/nautilus-directory-async.c
+++ b/libnautilus-private/nautilus-directory-async.c
@@ -135,6 +135,7 @@
 	GFile *deep_count_location;
 	GList *deep_count_subdirectories;
 	GArray *seen_deep_count_inodes;
+	char *fs_id;
 };
 
 
@@ -2684,6 +2685,7 @@
 	NautilusFile *file;
 	GFile *subdir;
 	gboolean is_seen_inode;
+	const char *id;
 
 	if (should_skip_file (NULL, info)) {
 		return;
@@ -2701,10 +2703,13 @@
 		file->details->deep_directory_count += 1;
 
 		/* Record the fact that we have to descend into this directory. */
-
-		subdir = g_file_get_child (state->deep_count_location, g_file_info_get_name (info));
-		state->deep_count_subdirectories = g_list_prepend
-			(state->deep_count_subdirectories, subdir);
+		id = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILESYSTEM);
+		if (g_strcmp0 (id, state->fs_id) == 0) {
+			/* only if it is on the same filesystem */
+			subdir = g_file_get_child (state->deep_count_location, g_file_info_get_name (info));
+			state->deep_count_subdirectories = g_list_prepend
+				(state->deep_count_subdirectories, subdir);
+		}
 	} else {
 		/* Even non-regular files count as files. */
 		file->details->deep_file_count += 1;
@@ -2732,6 +2737,7 @@
 	}
 	g_list_free_full (state->deep_count_subdirectories, g_object_unref);
 	g_array_free (state->seen_deep_count_inodes, TRUE);
+	g_free (state->fs_id);
 	g_free (state);
 }
 
@@ -2878,6 +2884,7 @@
 					 G_FILE_ATTRIBUTE_STANDARD_SIZE ","
 					 G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN ","
 					 G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP ","
+					 G_FILE_ATTRIBUTE_ID_FILESYSTEM ","
 					 G_FILE_ATTRIBUTE_UNIX_INODE,
 					 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, /* flags */
 					 G_PRIORITY_LOW, /* prio */
@@ -2909,13 +2916,34 @@
 }
 
 static void
+deep_count_got_info (GObject *source_object,
+		     GAsyncResult *res,
+		     gpointer user_data)
+{
+	GFileInfo *info;
+	const char *id;
+	GFile *file = (GFile *)source_object;
+	DeepCountState *state = (DeepCountState *)user_data;
+
+	info = g_file_query_info_finish (file,
+					 res,
+					 NULL);
+	if (info) {
+		id = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILESYSTEM);
+		state->fs_id = g_strdup (id);
+		g_object_unref (info);
+	}
+	deep_count_load (state, file);
+}
+
+static void
 deep_count_start (NautilusDirectory *directory,
 		  NautilusFile *file,
 		  gboolean *doing_io)
 {
 	GFile *location;
 	DeepCountState *state;
-	
+
 	if (directory->details->deep_count_in_progress != NULL) {
 		*doing_io = TRUE;
 		return;
@@ -2955,7 +2983,14 @@
 	directory->details->deep_count_in_progress = state;
 	
 	location = nautilus_file_get_location (file);
-	deep_count_load (state, location);
+	state->fs_id = NULL;
+	g_file_query_info_async (location,
+				 G_FILE_ATTRIBUTE_ID_FILESYSTEM,
+				 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+				 G_PRIORITY_DEFAULT,
+				 NULL,
+				 deep_count_got_info,
+				 state);
 	g_object_unref (location);
 }
 
