Fix up last commit.
[platform/upstream/glib.git] / gio / gfile.c
index 12b148c..9e65a4b 100644 (file)
@@ -1,3 +1,5 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
 /* GIO - GLib Input, Output and Streaming Library
  * 
  * Copyright (C) 2006-2007 Red Hat, Inc.
 /**
  * SECTION:gfile
  * @short_description: File and Directory Handling
- * @include: gio.h
+ * @include: gio/gio.h
  * @see_also: #GFileInfo, #GFileEnumerator
  * 
  * #GFile is a high level abstraction for manipulating files on a 
  * virtual file system. #GFile<!-- -->s are lightweight, immutable 
  * objects that do no I/O upon creation. It is necessary to understand that
- * #GFile objects do not represent files, merely a handle to a file. All
- * file I/O is implemented as streaming operations (see #GInputStream and 
+ * #GFile objects do not represent files, merely an identifier for a file. All
+ * file content I/O is implemented as streaming operations (see #GInputStream and 
  * #GOutputStream).
- * 
+ *
  * To construct a #GFile, you can use: 
  * g_file_new_for_path() if you have a path.
  * g_file_new_for_uri() if you have a URI.
  * g_file_new_for_commandline_arg() for a command line argument.
- * 
- * You can move through the file system with #GFile handles with
- * g_file_get_parent() to get a handle to the parent directory.
- * g_file_get_child() to get a handle to a child within a directory.
- * g_file_resolve_relative_path() to resolve a relative path between
- * two #GFile<!-- -->s.
+ * g_file_parse_name() from a utf8 string gotten from g_file_get_parse_name().
+ * 
+ * One way to think of a #GFile is as an abstraction of a pathname. For normal
+ * files the system pathname is what is stored internally, but as #GFile<!-- -->s
+ * are extensible it could also be something else that corresponds to a pathname
+ * in a userspace implementation of a filesystem.
+ *
+ * #GFile<!-- -->s make up hierarchies of directories and files that correspond to the
+ * files on a filesystem. You can move through the file system with #GFile using
+ * g_file_get_parent() to get an identifier for the parent directory, g_file_get_child()
+ * to get a child within a directory, g_file_resolve_relative_path() to resolve a relative
+ * path between two #GFile<!-- -->s. There can be multiple hierarchies, so you may not
+ * end up at the same root if you repeatedly call g_file_get_parent() on two different
+ * files.
+ *
+ * All #GFile<!-- -->s have a basename (get with g_file_get_basename()). These names
+ * are byte strings that are used to identify the file on the filesystem (relative to
+ * its parent directory) and there is no guarantees that they have any particular charset
+ * encoding or even make any sense at all. If you want to use filenames in a user
+ * interface you should use the display name that you can get by requesting the
+ * %G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME attribute with g_file_query_info().
+ * This is guaranteed to be in utf8 and can be used in a user interface. But always
+ * store the real basename or the #GFile to use to actually access the file, because
+ * there is no way to go from a display name to the actual name.
+ *
+ * Using #GFile as an identifier has the same weaknesses as using a path in that
+ * there may be multiple aliases for the same file. For instance, hard or
+ * soft links may cause two different #GFile<!-- -->s to refer to the same file.
+ * Other possible causes for aliases are: case insensitive filesystems, short
+ * and long names on Fat/NTFS, or bind mounts in linux. If you want to check if
+ * two #GFile<!-- -->s point to the same file you can query for the
+ * %G_FILE_ATTRIBUTE_ID_FILE attribute. Note that #GFile does some trivial
+ * canonicalization of pathnames passed in, so that trivial differences in the
+ * path string used at creation (dupplicated slashes, slash at end of path, "."
+ * or ".." path segments, etc) does not create different #GFile<!-- -->s.
  * 
  * Many #GFile operations have both synchronous and asynchronous versions 
  * to suit your application. Asynchronous versions of synchronous functions 
@@ -90,88 +121,117 @@ static void g_file_base_init (gpointer g_class);
 static void g_file_class_init (gpointer g_class,
                               gpointer class_data);
 
-static void               g_file_real_query_info_async          (GFile                *file,
-                                                                const char           *attributes,
-                                                                GFileQueryInfoFlags   flags,
-                                                                int                   io_priority,
-                                                                GCancellable         *cancellable,
-                                                                GAsyncReadyCallback   callback,
-                                                                gpointer              user_data);
-static GFileInfo *        g_file_real_query_info_finish         (GFile                *file,
-                                                                GAsyncResult         *res,
-                                                                GError              **error);
-static void               g_file_real_enumerate_children_async  (GFile                *file,
-                                                                const char           *attributes,
-                                                                GFileQueryInfoFlags   flags,
-                                                                int                   io_priority,
-                                                                GCancellable         *cancellable,
-                                                                GAsyncReadyCallback   callback,
-                                                                gpointer              user_data);
-static GFileEnumerator *  g_file_real_enumerate_children_finish (GFile                *file,
-                                                                GAsyncResult         *res,
-                                                                GError              **error);
-static void               g_file_real_read_async                (GFile                *file,
-                                                                int                   io_priority,
-                                                                GCancellable         *cancellable,
-                                                                GAsyncReadyCallback   callback,
-                                                                gpointer              user_data);
-static GFileInputStream * g_file_real_read_finish               (GFile                *file,
-                                                                GAsyncResult         *res,
-                                                                GError              **error);
-static void               g_file_real_append_to_async           (GFile                *file,
-                                                                GFileCreateFlags      flags,
-                                                                int                   io_priority,
-                                                                GCancellable         *cancellable,
-                                                                GAsyncReadyCallback   callback,
-                                                                gpointer              user_data);
-static GFileOutputStream *g_file_real_append_to_finish          (GFile                *file,
-                                                                GAsyncResult         *res,
-                                                                GError              **error);
-static void               g_file_real_create_async              (GFile                *file,
-                                                                GFileCreateFlags      flags,
-                                                                int                   io_priority,
-                                                                GCancellable         *cancellable,
-                                                                GAsyncReadyCallback   callback,
-                                                                gpointer              user_data);
-static GFileOutputStream *g_file_real_create_finish             (GFile                *file,
-                                                                GAsyncResult         *res,
-                                                                GError              **error);
-static void               g_file_real_replace_async             (GFile                *file,
-                                                                const char           *etag,
-                                                                gboolean              make_backup,
-                                                                GFileCreateFlags      flags,
-                                                                int                   io_priority,
-                                                                GCancellable         *cancellable,
-                                                                GAsyncReadyCallback   callback,
-                                                                gpointer              user_data);
-static GFileOutputStream *g_file_real_replace_finish            (GFile                *file,
-                                                                GAsyncResult         *res,
-                                                                GError              **error);
-static gboolean           g_file_real_set_attributes_from_info  (GFile                *file,
-                                                                GFileInfo            *info,
-                                                                GFileQueryInfoFlags   flags,
-                                                                GCancellable         *cancellable,
-                                                                GError              **error);
-static void               g_file_real_set_display_name_async    (GFile                *file,
-                                                                const char           *display_name,
-                                                                int                   io_priority,
-                                                                GCancellable         *cancellable,
-                                                                GAsyncReadyCallback   callback,
-                                                                gpointer              user_data);
-static GFile *            g_file_real_set_display_name_finish   (GFile                *file,
-                                                                GAsyncResult         *res,
-                                                                GError              **error);
-static void               g_file_real_set_attributes_async      (GFile                *file,
-                                                                GFileInfo            *info,
-                                                                GFileQueryInfoFlags   flags,
-                                                                int                   io_priority,
-                                                                GCancellable         *cancellable,
-                                                                GAsyncReadyCallback   callback,
-                                                                gpointer              user_data);
-static gboolean           g_file_real_set_attributes_finish     (GFile                *file,
-                                                                GAsyncResult         *res,
-                                                                GFileInfo           **info,
-                                                                GError              **error);
+static void               g_file_real_query_info_async            (GFile                  *file,
+                                                                  const char             *attributes,
+                                                                  GFileQueryInfoFlags     flags,
+                                                                  int                     io_priority,
+                                                                  GCancellable           *cancellable,
+                                                                  GAsyncReadyCallback     callback,
+                                                                  gpointer                user_data);
+static GFileInfo *        g_file_real_query_info_finish           (GFile                  *file,
+                                                                  GAsyncResult           *res,
+                                                                  GError                **error);
+static void               g_file_real_query_filesystem_info_async (GFile                  *file,
+                                                                  const char             *attributes,
+                                                                  int                     io_priority,
+                                                                  GCancellable           *cancellable,
+                                                                  GAsyncReadyCallback     callback,
+                                                                  gpointer                user_data);
+static GFileInfo *        g_file_real_query_filesystem_info_finish (GFile                  *file,
+                                                                  GAsyncResult           *res,
+                                                                  GError                **error);
+static void               g_file_real_enumerate_children_async    (GFile                  *file,
+                                                                  const char             *attributes,
+                                                                  GFileQueryInfoFlags     flags,
+                                                                  int                     io_priority,
+                                                                  GCancellable           *cancellable,
+                                                                  GAsyncReadyCallback     callback,
+                                                                  gpointer                user_data);
+static GFileEnumerator *  g_file_real_enumerate_children_finish   (GFile                  *file,
+                                                                  GAsyncResult           *res,
+                                                                  GError                **error);
+static void               g_file_real_read_async                  (GFile                  *file,
+                                                                  int                     io_priority,
+                                                                  GCancellable           *cancellable,
+                                                                  GAsyncReadyCallback     callback,
+                                                                  gpointer                user_data);
+static GFileInputStream * g_file_real_read_finish                 (GFile                  *file,
+                                                                  GAsyncResult           *res,
+                                                                  GError                **error);
+static void               g_file_real_append_to_async             (GFile                  *file,
+                                                                  GFileCreateFlags        flags,
+                                                                  int                     io_priority,
+                                                                  GCancellable           *cancellable,
+                                                                  GAsyncReadyCallback     callback,
+                                                                  gpointer                user_data);
+static GFileOutputStream *g_file_real_append_to_finish            (GFile                  *file,
+                                                                  GAsyncResult           *res,
+                                                                  GError                **error);
+static void               g_file_real_create_async                (GFile                  *file,
+                                                                  GFileCreateFlags        flags,
+                                                                  int                     io_priority,
+                                                                  GCancellable           *cancellable,
+                                                                  GAsyncReadyCallback     callback,
+                                                                  gpointer                user_data);
+static GFileOutputStream *g_file_real_create_finish               (GFile                  *file,
+                                                                  GAsyncResult           *res,
+                                                                  GError                **error);
+static void               g_file_real_replace_async               (GFile                  *file,
+                                                                  const char             *etag,
+                                                                  gboolean                make_backup,
+                                                                  GFileCreateFlags        flags,
+                                                                  int                     io_priority,
+                                                                  GCancellable           *cancellable,
+                                                                  GAsyncReadyCallback     callback,
+                                                                  gpointer                user_data);
+static GFileOutputStream *g_file_real_replace_finish              (GFile                  *file,
+                                                                  GAsyncResult           *res,
+                                                                  GError                **error);
+static gboolean           g_file_real_set_attributes_from_info    (GFile                  *file,
+                                                                  GFileInfo              *info,
+                                                                  GFileQueryInfoFlags     flags,
+                                                                  GCancellable           *cancellable,
+                                                                  GError                **error);
+static void               g_file_real_set_display_name_async      (GFile                  *file,
+                                                                  const char             *display_name,
+                                                                  int                     io_priority,
+                                                                  GCancellable           *cancellable,
+                                                                  GAsyncReadyCallback     callback,
+                                                                  gpointer                user_data);
+static GFile *            g_file_real_set_display_name_finish     (GFile                  *file,
+                                                                  GAsyncResult           *res,
+                                                                  GError                **error);
+static void               g_file_real_set_attributes_async        (GFile                  *file,
+                                                                  GFileInfo              *info,
+                                                                  GFileQueryInfoFlags     flags,
+                                                                  int                     io_priority,
+                                                                  GCancellable           *cancellable,
+                                                                  GAsyncReadyCallback     callback,
+                                                                  gpointer                user_data);
+static gboolean           g_file_real_set_attributes_finish       (GFile                  *file,
+                                                                  GAsyncResult           *res,
+                                                                  GFileInfo             **info,
+                                                                  GError                **error);
+static void               g_file_real_find_enclosing_mount_async  (GFile                  *file,
+                                                                  int                     io_priority,
+                                                                  GCancellable           *cancellable,
+                                                                  GAsyncReadyCallback     callback,
+                                                                  gpointer                user_data);
+static GMount *           g_file_real_find_enclosing_mount_finish (GFile                  *file,
+                                                                  GAsyncResult           *res,
+                                                                  GError                **error);
+static void               g_file_real_copy_async                  (GFile                  *source,
+                                                                  GFile                  *destination,
+                                                                  GFileCopyFlags          flags,
+                                                                  int                     io_priority,
+                                                                  GCancellable           *cancellable,
+                                                                  GFileProgressCallback   progress_callback,
+                                                                  gpointer                progress_callback_data,
+                                                                  GAsyncReadyCallback     callback,
+                                                                  gpointer                user_data);
+static gboolean           g_file_real_copy_finish                 (GFile                  *file,
+                                                                  GAsyncResult           *res,
+                                                                  GError                **error);
 
 GType
 g_file_get_type (void)
@@ -215,6 +275,8 @@ g_file_class_init (gpointer g_class,
   iface->set_display_name_finish = g_file_real_set_display_name_finish;
   iface->query_info_async = g_file_real_query_info_async;
   iface->query_info_finish = g_file_real_query_info_finish;
+  iface->query_filesystem_info_async = g_file_real_query_filesystem_info_async;
+  iface->query_filesystem_info_finish = g_file_real_query_filesystem_info_finish;
   iface->set_attributes_async = g_file_real_set_attributes_async;
   iface->set_attributes_finish = g_file_real_set_attributes_finish;
   iface->read_async = g_file_real_read_async;
@@ -225,7 +287,11 @@ g_file_class_init (gpointer g_class,
   iface->create_finish = g_file_real_create_finish;
   iface->replace_async = g_file_real_replace_async;
   iface->replace_finish = g_file_real_replace_finish;
+  iface->find_enclosing_mount_async = g_file_real_find_enclosing_mount_async;
+  iface->find_enclosing_mount_finish = g_file_real_find_enclosing_mount_finish;
   iface->set_attributes_from_info = g_file_real_set_attributes_from_info;
+  iface->copy_async = g_file_real_copy_async;
+  iface->copy_finish = g_file_real_copy_finish;
 }
 
 static void
@@ -331,9 +397,15 @@ g_file_get_uri_scheme (GFile *file)
  * Gets the base name (the last component of the path) for a given #GFile.
  *
  * If called for the top level of a system (such as the filesystem root
- * or a uri like sftp://host/ it will return a single directory separator
+ * or a uri like sftp://host/) it will return a single directory separator
  * (and on Windows, possibly a drive letter).
  *
+ * The base name is a byte string (*not* UTF-8). It has no defined encoding
+ * or rules other than it may not contain zero bytes.  If you want to use
+ * filenames in a user interface you should use the display name that you
+ * can get by requesting the %G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME
+ * attribute with g_file_query_info().
+ * 
  * This call does no blocking i/o.
  * 
  * Returns: string containing the #GFile's base name, or %NULL 
@@ -409,7 +481,8 @@ g_file_get_uri (GFile *file)
  * g_file_parse_name().
  *
  * This is generally used to show the #GFile as a nice
- * string in a user interface, like in a location entry.
+ * full-pathname kind of string in a user interface,
+ * like in a location entry.
  *
  * For local files with names that can safely be converted
  * to UTF8 the pathname is used, otherwise the IRI is used
@@ -486,7 +559,10 @@ g_file_hash (gconstpointer file)
  * @file1: the first #GFile.
  * @file2: the second #GFile.
  *
- * Checks equality of two given #GFile<!-- -->s
+ * Checks equality of two given #GFile<!-- -->s. Note that two
+ * #GFile<!-- -->s that differ can still refer to the same
+ * file on the filesystem due to various forms of filename
+ * aliasing.
  *
  * This call does no blocking i/o.
  * 
@@ -539,9 +615,9 @@ g_file_get_parent (GFile *file)
 /**
  * g_file_get_child:
  * @file: input #GFile.
- * @name: string containing the child's name.
+ * @name: string containing the child's basename.
  *
- * Gets a specific child of @file with name equal to @name.
+ * Gets a child of @file with basename equal to @name.
  *
  * Note that the file with that specific name might not exist, but
  * you can still have a #GFile that points to it. You can use this
@@ -594,31 +670,36 @@ g_file_get_child_for_display_name (GFile      *file,
 }
 
 /**
- * g_file_contains_file:
- * @parent: input #GFile.
- * @descendant: input #GFile.
- * 
- * Checks whether @parent (recursively) contains the specified @descendant.
+ * g_file_has_prefix:
+ * @file: input #GFile.
+ * @prefix: input #GFile.
  * 
- * This call does no blocking i/o.
+ * Checks whether @file has the prefix specified by @prefix. In other word, if the
+ * names of inital elements of @file<!-- -->s pathname match @prefix.
  * 
- * Returns:  %TRUE if the @descendant's parent, grandparent, etc is @parent. %FALSE otherwise.
+ * This call does no i/o, as it works purely on names. As such it can sometimes
+ * return %FALSE even if @file is inside a @prefix (from a filesystem point of view),
+ * because the prefix of @file is an alias of @prefix.
+ *
+ * Returns:  %TRUE if the @files's parent, grandparent, etc is @prefix. %FALSE otherwise.
  **/
 gboolean
-g_file_contains_file (GFile *parent,
-                     GFile *descendant)
+g_file_has_prefix (GFile *file,
+                  GFile *prefix)
 {
   GFileIface *iface;
   
-  g_return_val_if_fail (G_IS_FILE (parent), FALSE);
-  g_return_val_if_fail (G_IS_FILE (descendant), FALSE);
+  g_return_val_if_fail (G_IS_FILE (file), FALSE);
+  g_return_val_if_fail (G_IS_FILE (prefix), FALSE);
 
-  if (G_TYPE_FROM_INSTANCE (parent) != G_TYPE_FROM_INSTANCE (descendant))
+  if (G_TYPE_FROM_INSTANCE (file) != G_TYPE_FROM_INSTANCE (prefix))
     return FALSE;
   
-  iface = G_FILE_GET_IFACE (parent);
+  iface = G_FILE_GET_IFACE (file);
 
-  return (* iface->contains_file) (parent, descendant);
+  /* The vtable function differs in arg order since we're
+     using the old contains_file call */
+  return (* iface->prefix_matches) (prefix, file);
 }
 
 /**
@@ -631,7 +712,7 @@ g_file_contains_file (GFile *parent,
  * This call does no blocking i/o.
  * 
  * Returns: string with the relative path from @descendant 
- *     to @parent, or %NULL if @descendant is not a descendant of @parent. The returned string should be freed with 
+ *     to @parent, or %NULL if @descendant doesn't have @parent as prefix. The returned string should be freed with 
  *     g_free() when no longer needed.
  **/
 char *
@@ -820,21 +901,21 @@ g_file_enumerate_children_finish (GFile         *file,
  * Utility function to check if a particular file exists. This is
  * implemented using g_file_query_info() and as such does blocking I/O.
  *
- * Note that in many cases it is racy to first check for file existance
+ * Note that in many cases it is racy to first check for file existence
  * and then execute something based on the outcome of that, because the
- * file might have been created or removed inbetween the operations. The
+ * file might have been created or removed in between the operations. The
  * general approach to handling that is to not check, but just do the
  * operation and handle the errors as they come.
  *
- * As an example of race-free checking. Take the case of reading a file, and
- * if it doesn't exist, create it. There are two racy versions: read it, and
+ * As an example of race-free checking, take the case of reading a file, and
+ * if it doesn't exist, creating it. There are two racy versions: read it, and
  * on error create it; and: check if it exists, if not create it. These
  * can both result in two processes creating the file (with perhaps a partially
  * written file as the result). The correct approach is to always try to create
  * the file with g_file_create() which will either atomically create the file
- * or fail with an G_IO_ERROR_EXISTS error.
+ * or fail with a G_IO_ERROR_EXISTS error.
  *
- * However, in many cases an existance check is useful in a user
+ * However, in many cases an existence check is useful in a user
  * interface, for instance to make a menu item sensitive/insensitive, so that
  * you don't have to fool users that something is possible and then just show
  * and error dialog. If you do this, you should make sure to also handle the
@@ -847,7 +928,9 @@ g_file_query_exists (GFile *file,
                     GCancellable *cancellable)
 {
   GFileInfo *info;
-
+  
+  g_return_val_if_fail (G_IS_FILE(file), FALSE);
+  
   info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE,
                            G_FILE_QUERY_INFO_NONE,
                            cancellable, NULL);
@@ -869,8 +952,8 @@ g_file_query_exists (GFile *file,
  * @error: a #GError.
  *
  * Gets the requested information about specified @file. The result
- * is a #GFileInfo objects that contains key-value attributes (like type or size
- * for the file.
+ * is a #GFileInfo object that contains key-value attributes (such as 
+ * the type or size of the file).
  *
  * The @attribute value is a string that specifies the file attributes that
  * should be gathered. It is not an error if it's not possible to read a particular
@@ -888,7 +971,7 @@ g_file_query_exists (GFile *file,
  * symlink is returned, rather than information about the symlink itself.
  * However if you pass #G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS in @flags the
  * information about the symlink itself will be returned. Also, for symlinks
- * that points to non-existing files the information about the symlink itself
+ * that point to non-existing files the information about the symlink itself
  * will be returned.
  *
  * If the file does not exist, the G_IO_ERROR_NOT_FOUND error will be returned.
@@ -935,7 +1018,7 @@ g_file_query_info (GFile                *file,
  * @user_data: the data to pass to callback function
  * 
  * Asynchronously gets the requested information about specified @file. The result
- * is a #GFileInfo objects that contains key-value attributes (such as type or size
+ * is a #GFileInfo object that contains key-value attributes (such as type or size
  * for the file).
  * 
  * For more details, see g_file_query_info() which is
@@ -1057,6 +1140,81 @@ g_file_query_filesystem_info (GFile         *file,
 }
 
 /**
+ * g_file_query_filesystem_info_async:
+ * @file: input #GFile.
+ * @attributes: an attribute query string.
+ * @io_priority: the <link linkend="io-priority">I/O priority</link> 
+ *     of the request.
+ * @cancellable: optional #GCancellable object, %NULL to ignore. 
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: the data to pass to callback function
+ * 
+ * Asynchronously gets the requested information about the filesystem
+ * that the specified @file is on. The result is a #GFileInfo object
+ * that contains key-value attributes (such as type or size for the
+ * file).
+ * 
+ * For more details, see g_file_query_filesystem_info() which is the
+ * synchronous version of this call.
+ *
+ * When the operation is finished, @callback will be called. You can
+ * then call g_file_query_info_finish() to get the result of the
+ * operation.
+ **/
+void
+g_file_query_filesystem_info_async (GFile               *file,
+                                    const char          *attributes,
+                                    int                  io_priority,
+                                    GCancellable        *cancellable,
+                                    GAsyncReadyCallback  callback,
+                                    gpointer             user_data)
+{
+  GFileIface *iface;
+  
+  g_return_if_fail (G_IS_FILE (file));
+
+  iface = G_FILE_GET_IFACE (file);
+  (* iface->query_filesystem_info_async) (file,
+                                          attributes,
+                                          io_priority,
+                                          cancellable,
+                                          callback,
+                                          user_data);
+}
+
+/**
+ * g_file_query_filesystem_info_finish:
+ * @file: input #GFile.
+ * @res: a #GAsyncResult. 
+ * @error: a #GError. 
+ * 
+ * Finishes an asynchronous filesystem info query.  See
+ * g_file_query_filesystem_info_async().
+ * 
+ * Returns: #GFileInfo for given @file or %NULL on error.
+ **/
+GFileInfo *
+g_file_query_filesystem_info_finish (GFile         *file,
+                                     GAsyncResult  *res,
+                                     GError       **error)
+{
+  GFileIface *iface;
+
+  g_return_val_if_fail (G_IS_FILE (file), NULL);
+  g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
+
+  if (G_IS_SIMPLE_ASYNC_RESULT (res))
+    {
+      GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+      if (g_simple_async_result_propagate_error (simple, error))
+       return NULL;
+    }
+  
+  iface = G_FILE_GET_IFACE (file);
+  return (* iface->query_filesystem_info_finish) (file, res, error);
+}
+
+/**
  * g_file_find_enclosing_mount:
  * @file: input #GFile.
  * @cancellable: optional #GCancellable object, %NULL to ignore. 
@@ -1082,21 +1240,91 @@ g_file_find_enclosing_mount (GFile         *file,
   GFileIface *iface;
 
   g_return_val_if_fail (G_IS_FILE (file), NULL);
-  
+
   if (g_cancellable_set_error_if_cancelled (cancellable, error))
     return NULL;
 
   iface = G_FILE_GET_IFACE (file);
   if (iface->find_enclosing_mount == NULL)
     {
-      g_set_error (error, G_IO_ERROR,
-                  G_IO_ERROR_NOT_FOUND,
+
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+                       /* Translators: This is an error message when trying to find the
+                        * enclosing (user visible) mount of a file, but none exists. */
                   _("Containing mount does not exist"));
       return NULL;
     }
-  
+
   return (* iface->find_enclosing_mount) (file, cancellable, error);
 }
+/**
+ * g_file_find_enclosing_mount_async:
+ * @file: a #GFile
+ * @io_priority: the <link linkend="io-priority">I/O priority</link> 
+ *     of the request.
+ * @cancellable: optional #GCancellable object, %NULL to ignore.
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: the data to pass to callback function
+ *
+ * Asynchronously gets the mount for the file.
+ *
+ * For more details, see g_file_find_enclosing_mount() which is
+ * the synchronous version of this call.
+ *
+ * When the operation is finished, @callback will be called. You can then call
+ * g_file_find_enclosing_mount_finish() to get the result of the operation.
+ */
+void
+g_file_find_enclosing_mount_async (GFile              *file,
+                                  int                   io_priority,
+                                  GCancellable         *cancellable,
+                                  GAsyncReadyCallback   callback,
+                                  gpointer              user_data)
+{
+  GFileIface *iface;
+
+  g_return_if_fail (G_IS_FILE (file));
+
+  iface = G_FILE_GET_IFACE (file);
+  (* iface->find_enclosing_mount_async) (file,
+                                        io_priority,
+                                        cancellable,
+                                        callback,
+                                        user_data);
+}
+
+/**
+ * g_file_find_enclosing_mount_finish:
+ * @file: a #GFile
+ * @res: a #GAsyncResult
+ * @error: a #GError
+ * 
+ * Finishes an asynchronous find mount request. 
+ * See g_file_find_enclosing_mount_async().
+ * 
+ * Returns: #GMount for given @file or %NULL on error.
+ **/
+GMount *
+g_file_find_enclosing_mount_finish (GFile         *file,
+                                   GAsyncResult  *res,
+                                   GError       **error)
+{
+  GFileIface *iface;
+  
+  g_return_val_if_fail (G_IS_FILE (file), NULL);
+  g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
+
+  if (G_IS_SIMPLE_ASYNC_RESULT (res))
+    {
+      GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+      if (g_simple_async_result_propagate_error (simple, error))
+       return NULL;
+    }
+  
+  iface = G_FILE_GET_IFACE (file);
+  return (* iface->find_enclosing_mount_finish) (file, res, error);
+}
+
 
 /**
  * g_file_read:
@@ -1214,8 +1442,7 @@ g_file_append_to (GFile             *file,
  * triggering the cancellable object from another thread. If the operation
  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. 
  *
- * If a file with this name already exists the G_IO_ERROR_EXISTS error
- * will be returned. If the file is a directory the G_IO_ERROR_IS_DIRECTORY
+ * If a file or directory with this name already exists the G_IO_ERROR_EXISTS
  * error will be returned.
  * Some file systems don't allow all file names, and may
  * return an G_IO_ERROR_INVALID_FILENAME error, and if the name
@@ -1890,6 +2117,7 @@ g_file_copy_attributes (GFile           *source,
 static gboolean
 copy_stream_with_progress (GInputStream           *in,
                           GOutputStream          *out,
+                           GFile                  *source,
                           GCancellable           *cancellable,
                           GFileProgressCallback   progress_callback,
                           gpointer                progress_callback_data,
@@ -1897,20 +2125,38 @@ copy_stream_with_progress (GInputStream           *in,
 {
   gssize n_read, n_written;
   goffset current_size;
-  char buffer[8192], *p;
+  char buffer[1024*64], *p;
   gboolean res;
   goffset total_size;
   GFileInfo *info;
 
-  total_size = 0;
+  total_size = -1;
   info = g_file_input_stream_query_info (G_FILE_INPUT_STREAM (in),
                                         G_FILE_ATTRIBUTE_STANDARD_SIZE,
                                         cancellable, NULL);
   if (info)
     {
-      total_size = g_file_info_get_size (info);
+      if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE))
+        total_size = g_file_info_get_size (info);
       g_object_unref (info);
     }
+
+  if (total_size == -1)
+    {
+      info = g_file_query_info (source, 
+                                G_FILE_ATTRIBUTE_STANDARD_SIZE,
+                                G_FILE_QUERY_INFO_NONE,
+                                cancellable, NULL);
+      if (info)
+        {
+          if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE))
+            total_size = g_file_info_get_size (info);
+          g_object_unref (info);
+        }
+    }
+
+  if (total_size == -1)
+    total_size = 0;
   
   current_size = 0;
   res = TRUE;
@@ -1944,7 +2190,7 @@ copy_stream_with_progress (GInputStream           *in,
 
       if (!res)
         break;
-      
+
       if (progress_callback)
        progress_callback (current_size, total_size, progress_callback_data);
     }
@@ -1955,7 +2201,6 @@ copy_stream_with_progress (GInputStream           *in,
   /* Make sure we send full copied size */
   if (progress_callback)
     progress_callback (current_size, total_size, progress_callback_data);
-
   
   /* Don't care about errors in source here */
   g_input_stream_close (in, cancellable, NULL);
@@ -2033,7 +2278,7 @@ file_copy_fallback (GFile                  *source,
       return FALSE;
     }
 
-  if (!copy_stream_with_progress (in, out, cancellable,
+  if (!copy_stream_with_progress (in, out, source, cancellable,
                                  progress_callback, progress_callback_data,
                                  error))
     return FALSE;
@@ -2164,6 +2409,89 @@ g_file_copy (GFile                  *source,
                             error);
 }
 
+/**
+ * g_file_copy_async:
+ * @source: input #GFile.
+ * @destination: destination #GFile
+ * @flags: set of #GFileCopyFlags
+ * @io_priority: the <link linkend="io-priority">I/O priority</link> 
+ *     of the request. 
+ * @cancellable: optional #GCancellable object, %NULL to ignore.
+ * @progress_callback: function to callback with progress information
+ * @progress_callback_data: user data to pass to @progress_callback
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: the data to pass to callback function
+ *
+ * Copies the file @source to the location specified by @destination 
+ * asynchronously. For details of the behaviour, see g_file_copy().
+ *
+ * If @progress_callback is not %NULL, then that function that will be called
+ * just like in g_file_copy(), however the callback will run in the main loop,
+ * not in the thread that is doing the I/O operation.
+ *
+ * When the operation is finished, @callback will be called. You can then call
+ * g_file_copy_finish() to get the result of the operation.
+ **/
+void
+g_file_copy_async (GFile                  *source,
+                  GFile                  *destination,
+                  GFileCopyFlags          flags,
+                  int                     io_priority,
+                  GCancellable           *cancellable,
+                  GFileProgressCallback   progress_callback,
+                  gpointer                progress_callback_data,
+                  GAsyncReadyCallback     callback,
+                  gpointer                user_data)
+{
+  GFileIface *iface;
+
+  g_return_if_fail (G_IS_FILE (source));
+  g_return_if_fail (G_IS_FILE (destination));
+
+  iface = G_FILE_GET_IFACE (source);
+  (* iface->copy_async) (source,
+                        destination,
+                        flags,
+                        io_priority,
+                        cancellable,
+                        progress_callback,
+                        progress_callback_data,
+                        callback,
+                        user_data);
+}
+
+/**
+ * g_file_copy_finish:
+ * @file: input #GFile.
+ * @res: a #GAsyncResult. 
+ * @error: a #GError, or %NULL
+ * 
+ * Finishes copying the file started with 
+ * g_file_copy_async().
+ * 
+ * Returns: a %TRUE on success, %FALSE on error.
+ **/
+gboolean
+g_file_copy_finish (GFile        *file,
+                   GAsyncResult *res,
+                   GError      **error)
+{
+  GFileIface *iface;
+  
+  g_return_val_if_fail (G_IS_FILE (file), FALSE);
+  g_return_val_if_fail (G_IS_ASYNC_RESULT (res), FALSE);
+
+  if (G_IS_SIMPLE_ASYNC_RESULT (res))
+    {
+      GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+      
+      if (g_simple_async_result_propagate_error (simple, error))
+       return FALSE;
+    }
+  
+  iface = G_FILE_GET_IFACE (file);
+  return (* iface->copy_finish) (file, res, error);
+}
 
 /**
  * g_file_move:
@@ -2177,7 +2505,7 @@ g_file_copy (GFile                  *source,
  *
  *
  * Tries to move the file or directory @source to the location specified by @destination.
- * If native move operations is supported then this is used, otherwise a copy + delete
+ * If native move operations are supported then this is used, otherwise a copy + delete
  * fallback is used. The native implementation may support moving directories (for instance
  * on moves inside the same filesystem), but the fallback code does not.
  * 
@@ -2389,7 +2717,8 @@ g_file_make_symbolic_link (GFile         *file,
  * @cancellable: optional #GCancellable object, %NULL to ignore.
  * @error: a #GError, or %NULL 
  * 
- * Deletes a file.
+ * Deletes a file. If the @file is a directory, it will only be deleted if it 
+ * is empty.
  * 
  * If @cancellable is not %NULL, then the operation can be cancelled by
  * triggering the cancellable object from another thread. If the operation
@@ -3103,6 +3432,7 @@ g_file_set_attribute_int64 (GFile                *file,
 /**
  * g_file_mount_mountable:
  * @file: input #GFile.
+ * @flags: flags affecting the operation
  * @mount_operation: a #GMountOperation, or %NULL to avoid user interaction.
  * @cancellable: optional #GCancellable object, %NULL to ignore.
  * @callback: a #GAsyncReadyCallback to call when the request is satisfied, or %NULL.
@@ -3121,6 +3451,7 @@ g_file_set_attribute_int64 (GFile                *file,
  **/
 void
 g_file_mount_mountable (GFile               *file,
+                       GMountMountFlags     flags,
                        GMountOperation     *mount_operation,
                        GCancellable        *cancellable,
                        GAsyncReadyCallback  callback,
@@ -3132,15 +3463,19 @@ g_file_mount_mountable (GFile               *file,
 
   iface = G_FILE_GET_IFACE (file);
 
-  if (iface->mount_mountable == NULL)
-    g_simple_async_report_error_in_idle (G_OBJECT (file),
-                                        callback,
-                                        user_data,
-                                        G_IO_ERROR,
-                                        G_IO_ERROR_NOT_SUPPORTED,
-                                        _("Operation not supported"));
+  if (iface->mount_mountable == NULL) 
+    {
+      g_simple_async_report_error_in_idle (G_OBJECT (file),
+                                          callback,
+                                          user_data,
+                                          G_IO_ERROR,
+                                          G_IO_ERROR_NOT_SUPPORTED,
+                                          _("Operation not supported"));
+      return;
+    }
   
   (* iface->mount_mountable) (file,
+                             flags,
                              mount_operation,
                              cancellable,
                              callback,
@@ -3212,12 +3547,15 @@ g_file_unmount_mountable (GFile               *file,
   iface = G_FILE_GET_IFACE (file);
   
   if (iface->unmount_mountable == NULL)
-    g_simple_async_report_error_in_idle (G_OBJECT (file),
-                                        callback,
-                                        user_data,
-                                        G_IO_ERROR,
-                                        G_IO_ERROR_NOT_SUPPORTED,
-                                        _("Operation not supported"));
+    {
+      g_simple_async_report_error_in_idle (G_OBJECT (file),
+                                          callback,
+                                          user_data,
+                                          G_IO_ERROR,
+                                          G_IO_ERROR_NOT_SUPPORTED,
+                                          _("Operation not supported"));
+      return;
+    }
   
   (* iface->unmount_mountable) (file,
                                flags,
@@ -3291,13 +3629,16 @@ g_file_eject_mountable (GFile               *file,
 
   iface = G_FILE_GET_IFACE (file);
   
-  if (iface->eject_mountable == NULL)
-    g_simple_async_report_error_in_idle (G_OBJECT (file),
-                                        callback,
-                                        user_data,
-                                        G_IO_ERROR,
-                                        G_IO_ERROR_NOT_SUPPORTED,
-                                        _("Operation not supported"));
+  if (iface->eject_mountable == NULL) 
+    {
+      g_simple_async_report_error_in_idle (G_OBJECT (file),
+                                          callback,
+                                          user_data,
+                                          G_IO_ERROR,
+                                          G_IO_ERROR_NOT_SUPPORTED,
+                                          _("Operation not supported"));
+      return;
+    }
   
   (* iface->eject_mountable) (file,
                              flags,
@@ -3509,6 +3850,80 @@ g_file_real_query_info_finish (GFile         *file,
 
 typedef struct {
   char *attributes;
+  GFileInfo *info;
+} QueryFilesystemInfoAsyncData;
+
+static void
+query_filesystem_info_data_free (QueryFilesystemInfoAsyncData *data)
+{
+  if (data->info)
+    g_object_unref (data->info);
+  g_free (data->attributes);
+  g_free (data);
+}
+
+static void
+query_filesystem_info_async_thread (GSimpleAsyncResult *res,
+                                    GObject            *object,
+                                    GCancellable       *cancellable)
+{
+  GError *error = NULL;
+  QueryFilesystemInfoAsyncData *data;
+  GFileInfo *info;
+  
+  data = g_simple_async_result_get_op_res_gpointer (res);
+  
+  info = g_file_query_filesystem_info (G_FILE (object), data->attributes, cancellable, &error);
+
+  if (info == NULL)
+    {
+      g_simple_async_result_set_from_error (res, error);
+      g_error_free (error);
+    }
+  else
+    data->info = info;
+}
+
+static void
+g_file_real_query_filesystem_info_async (GFile               *file,
+                                         const char          *attributes,
+                                         int                  io_priority,
+                                         GCancellable        *cancellable,
+                                         GAsyncReadyCallback  callback,
+                                         gpointer             user_data)
+{
+  GSimpleAsyncResult *res;
+  QueryFilesystemInfoAsyncData *data;
+
+  data = g_new0 (QueryFilesystemInfoAsyncData, 1);
+  data->attributes = g_strdup (attributes);
+  
+  res = g_simple_async_result_new (G_OBJECT (file), callback, user_data, g_file_real_query_filesystem_info_async);
+  g_simple_async_result_set_op_res_gpointer (res, data, (GDestroyNotify)query_filesystem_info_data_free);
+  
+  g_simple_async_result_run_in_thread (res, query_filesystem_info_async_thread, io_priority, cancellable);
+  g_object_unref (res);
+}
+
+static GFileInfo *
+g_file_real_query_filesystem_info_finish (GFile         *file,
+                                          GAsyncResult  *res,
+                                          GError       **error)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+  QueryFilesystemInfoAsyncData *data;
+
+  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_real_query_filesystem_info_async);
+
+  data = g_simple_async_result_get_op_res_gpointer (simple);
+  if (data->info)
+    return g_object_ref (data->info);
+  
+  return NULL;
+}
+
+typedef struct {
+  char *attributes;
   GFileQueryInfoFlags flags;
   GFileEnumerator *enumerator;
 } EnumerateChildrenAsyncData;
@@ -4005,6 +4420,196 @@ g_file_real_set_attributes_finish (GFile         *file,
   return data->res;
 }
 
+static void
+find_enclosing_mount_async_thread (GSimpleAsyncResult *res,
+                                   GObject            *object,
+                                   GCancellable       *cancellable)
+{
+  GError *error = NULL;
+  GMount *mount;
+  
+  mount = g_file_find_enclosing_mount (G_FILE (object), cancellable, &error);
+
+  if (mount == NULL)
+    {
+      g_simple_async_result_set_from_error (res, error);
+      g_error_free (error);
+    }
+  else
+    g_simple_async_result_set_op_res_gpointer (res, mount, (GDestroyNotify)g_object_unref);
+}
+
+static void
+g_file_real_find_enclosing_mount_async (GFile               *file,
+                                       int                  io_priority,
+                                       GCancellable        *cancellable,
+                                       GAsyncReadyCallback  callback,
+                                       gpointer             user_data)
+{
+  GSimpleAsyncResult *res;
+  
+  res = g_simple_async_result_new (G_OBJECT (file), callback, user_data, g_file_real_find_enclosing_mount_async);
+  
+  g_simple_async_result_run_in_thread (res, find_enclosing_mount_async_thread, io_priority, cancellable);
+  g_object_unref (res);
+}
+
+static GMount *
+g_file_real_find_enclosing_mount_finish (GFile         *file,
+                                         GAsyncResult  *res,
+                                         GError       **error)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+  GMount *mount;
+
+  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_real_find_enclosing_mount_async);
+
+  mount = g_simple_async_result_get_op_res_gpointer (simple);
+  return g_object_ref (mount);
+}
+
+
+typedef struct {
+  GFile *source;
+  GFile *destination;
+  GFileCopyFlags flags;
+  GFileProgressCallback progress_cb;
+  gpointer progress_cb_data;
+  GIOSchedulerJob *job;
+} CopyAsyncData;
+
+static void
+copy_async_data_free (CopyAsyncData *data)
+{
+  g_object_unref (data->source);
+  g_object_unref (data->destination);
+  g_free (data);
+}
+
+typedef struct {
+  CopyAsyncData *data;
+  goffset current_num_bytes;
+  goffset total_num_bytes;
+} ProgressData;
+
+static gboolean
+copy_async_progress_in_main (gpointer user_data)
+{
+  ProgressData *progress = user_data;
+  CopyAsyncData *data = progress->data;
+
+  data->progress_cb (progress->current_num_bytes,
+                    progress->total_num_bytes,
+                    data->progress_cb_data);
+
+  return FALSE;
+}
+
+static gboolean
+mainloop_barrier (gpointer user_data)
+{
+  /* Does nothing, but ensures all queued idles before
+     this are run */
+  return FALSE;
+}
+
+
+static void
+copy_async_progress_callback (goffset  current_num_bytes,
+                             goffset  total_num_bytes,
+                             gpointer user_data)
+{
+  CopyAsyncData *data = user_data;
+  ProgressData *progress;
+
+  progress = g_new (ProgressData, 1);
+  progress->data = data;
+  progress->current_num_bytes = current_num_bytes;
+  progress->total_num_bytes = total_num_bytes;
+  
+  g_io_scheduler_job_send_to_mainloop_async (data->job,
+                                            copy_async_progress_in_main,
+                                            progress,
+                                            g_free);
+}
+
+static gboolean
+copy_async_thread (GIOSchedulerJob *job,
+                  GCancellable    *cancellable,
+                  gpointer         user_data)
+{
+  GSimpleAsyncResult *res;
+  CopyAsyncData *data;
+  gboolean result;
+  GError *error;
+
+  res = user_data;
+  data = g_simple_async_result_get_op_res_gpointer (res);
+
+  error = NULL;
+  data->job = job;
+  result = g_file_copy (data->source,
+                       data->destination,
+                       data->flags,
+                       cancellable,
+                       (data->progress_cb != NULL) ? copy_async_progress_callback : NULL,
+                       data,
+                       &error);
+
+  /* Ensure all progress callbacks are done running in main thread */
+  if (data->progress_cb != NULL)
+    g_io_scheduler_job_send_to_mainloop (job,
+                                        mainloop_barrier,
+                                        NULL, NULL);
+  
+  if (!result)
+    {
+      g_simple_async_result_set_from_error (res, error);
+      g_error_free (error);
+    }
+
+  g_simple_async_result_complete_in_idle (res);
+
+  return FALSE;
+}
+
+static void
+g_file_real_copy_async (GFile                  *source,
+                       GFile                  *destination,
+                       GFileCopyFlags          flags,
+                       int                     io_priority,
+                       GCancellable           *cancellable,
+                       GFileProgressCallback   progress_callback,
+                       gpointer                progress_callback_data,
+                       GAsyncReadyCallback     callback,
+                       gpointer                user_data)
+{
+  GSimpleAsyncResult *res;
+  CopyAsyncData *data;
+
+  data = g_new0 (CopyAsyncData, 1);
+  data->source = g_object_ref (source);
+  data->destination = g_object_ref (destination);
+  data->flags = flags;
+  data->progress_cb = progress_callback;
+  data->progress_cb_data = progress_callback_data;
+
+  res = g_simple_async_result_new (G_OBJECT (source), callback, user_data, g_file_real_copy_async);
+  g_simple_async_result_set_op_res_gpointer (res, data, (GDestroyNotify)copy_async_data_free);
+
+  g_io_scheduler_push_job (copy_async_thread, res, g_object_unref, io_priority, cancellable);
+}
+
+static gboolean
+g_file_real_copy_finish (GFile        *file,
+                        GAsyncResult *res,
+                        GError      **error)
+{
+  /* Error handled in g_file_copy_finish() */
+  return TRUE;
+}
+
+
 /********************************************
  *   Default VFS operations                 *
  ********************************************/
@@ -4127,6 +4732,7 @@ g_file_new_for_commandline_arg (const char *arg)
 /**
  * g_file_mount_enclosing_volume:
  * @location: input #GFile.
+ * @flags: flags affecting the operation
  * @mount_operation: a #GMountOperation or %NULL to avoid user interaction.
  * @cancellable: optional #GCancellable object, %NULL to ignore.
  * @callback: a #GAsyncReadyCallback to call when the request is satisfied, or %NULL.
@@ -4144,6 +4750,7 @@ g_file_new_for_commandline_arg (const char *arg)
  **/
 void
 g_file_mount_enclosing_volume (GFile               *location,
+                              GMountMountFlags     flags,
                               GMountOperation     *mount_operation,
                               GCancellable        *cancellable,
                               GAsyncReadyCallback  callback,
@@ -4165,7 +4772,7 @@ g_file_mount_enclosing_volume (GFile               *location,
       return;
     }
   
-  (* iface->mount_enclosing_volume) (location, mount_operation, cancellable, callback, user_data);
+  (* iface->mount_enclosing_volume) (location, flags, mount_operation, cancellable, callback, user_data);
 
 }
 
@@ -4207,6 +4814,73 @@ g_file_mount_enclosing_volume_finish (GFile         *location,
  *   Utility functions                      *
  ********************************************/
 
+/**
+ * g_file_query_default_handler:
+ * @file: a #GFile to open.
+ * @cancellable: optional #GCancellable object, %NULL to ignore.
+ * @error: a #GError, or %NULL
+ *
+ * Returns the #GAppInfo that is registered as the default
+ * application to handle the file specified by @file.
+ *
+ * If @cancellable is not %NULL, then the operation can be cancelled by
+ * triggering the cancellable object from another thread. If the operation
+ * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. 
+ *
+ * Returns: a #GAppInfo if the handle was found, %NULL if there were errors.
+ * When you are done with it, release it with g_object_unref()
+ **/
+GAppInfo *
+g_file_query_default_handler (GFile                  *file,
+                             GCancellable           *cancellable,
+                             GError                **error)
+{
+  char *uri_scheme;
+  const char *content_type;
+  GAppInfo *appinfo;
+  GFileInfo *info;
+  char *path;
+  
+  uri_scheme = g_file_get_uri_scheme (file);
+  appinfo = g_app_info_get_default_for_uri_scheme (uri_scheme);
+  g_free (uri_scheme);
+
+  if (appinfo != NULL)
+    return appinfo;
+
+  info = g_file_query_info (file,
+                           G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+                           0,
+                           cancellable,
+                           error);
+  if (info == NULL)
+    return NULL;
+
+  appinfo = NULL;
+
+  content_type = g_file_info_get_content_type (info);
+  if (content_type)
+    {
+      /* Don't use is_native(), as we want to support fuse paths if availible */
+      path = g_file_get_path (file);
+      appinfo = g_app_info_get_default_for_type (content_type,
+                                                path == NULL);
+      g_free (path);
+    }
+  
+  g_object_unref (info);
+
+  if (appinfo != NULL)
+    return appinfo;
+
+  g_set_error (error, G_IO_ERROR,
+              G_IO_ERROR_NOT_SUPPORTED,
+              _("No application is registered as handling this file"));
+  return NULL;
+  
+}
+
+
 #define GET_CONTENT_BLOCK_SIZE 8192
 
 /**
@@ -4658,7 +5332,8 @@ g_file_load_contents_finish (GFile         *file,
  * @make_backup: %TRUE if a backup should be created.
  * @flags: a set of #GFileCreateFlags.
  * @new_etag: a location to a new <link linkend="gfile-etag">entity tag</link>
- *      for the document.
+ *      for the document. This should be freed with g_free() when no longer 
+ *      needed.
  * @cancellable: optional #GCancellable object, %NULL to ignore.
  * @error: a #GError, or %NULL
  *
@@ -4927,7 +5602,8 @@ g_file_replace_contents_async  (GFile               *file,
  * @file: input #GFile.
  * @res: a #GAsyncResult. 
  * @new_etag: a location of a new <link linkend="gfile-etag">entity tag</link> 
- *     for the document.
+ *     for the document. This should be freed with g_free() when it is no 
+ *     longer needed.
  * @error: a #GError, or %NULL 
  * 
  * Finishes an asynchronous replace of the given @file. See