Improve the g_file_make_symbolic_link docs
[platform/upstream/glib.git] / gio / gfile.c
index 0d0a5e1..d104ab4 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.
  * Author: Alexander Larsson <alexl@redhat.com>
  */
 
-#include <config.h>
+#include "config.h"
+#ifdef HAVE_SPLICE
+#define _GNU_SOURCE
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#endif
 #include <string.h>
 #include <sys/types.h>
 #ifdef HAVE_PWD_H
 #include "gfile.h"
 #include "gvfs.h"
 #include "gioscheduler.h"
-#include <glocalfile.h>
 #include "gsimpleasyncresult.h"
 #include "gfileattribute-priv.h"
+#include "gfiledescriptorbased.h"
 #include "gpollfilemonitor.h"
+#include "gappinfo.h"
+#include "gfileinputstream.h"
+#include "gfileoutputstream.h"
+#include "gcancellable.h"
+#include "gasyncresult.h"
+#include "gioerror.h"
 #include "glibintl.h"
 
 #include "gioalias.h"
 /**
  * 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 filesystem 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 (duplicated 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 
  * simply have _async() appended to their function names. The asynchronous 
  * I/O functions call a #GAsyncReadyCallback which is then used to finalize 
  * the operation, producing a GAsyncResult which is then passed to the 
- * function's matching _finish() 
- * operation. 
+ * function's matching _finish() operation. 
  *
  * Some #GFile operations do not have synchronous analogs, as they may
  * take a very long time to finish, and blocking may leave an application
  * unusable. Notable cases include:
  * g_file_mount_mountable() to mount a mountable file.
- * g_file_unmount_mountable() to unmount a mountable file.
- * g_file_eject_mountable() to eject a mountable file.
+ * g_file_unmount_mountable_with_operation() to unmount a mountable file.
+ * g_file_eject_mountable_with_operation() to eject a mountable file.
  * 
  * <para id="gfile-etag"><indexterm><primary>entity tag</primary></indexterm>
  * One notable feature of #GFile<!-- -->s are entity tags, or "etags" for 
  * </para>
  **/
 
-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);
-
-GType
-g_file_get_type (void)
-{
-  static GType file_type = 0;
-
-  if (! file_type)
-    {
-      static const GTypeInfo file_info =
-      {
-        sizeof (GFileIface), /* class_size */
-       g_file_base_init,   /* base_init */
-       NULL,           /* base_finalize */
-       g_file_class_init,
-       NULL,           /* class_finalize */
-       NULL,           /* class_data */
-       0,
-       0,              /* n_preallocs */
-       NULL
-      };
-
-      file_type =
-       g_type_register_static (G_TYPE_INTERFACE, I_("GFile"),
-                               &file_info, 0);
-
-      g_type_interface_add_prerequisite (file_type, G_TYPE_OBJECT);
-    }
-
-  return file_type;
-}
+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 void               g_file_real_open_readwrite_async        (GFile                  *file,
+                                                                   int                  io_priority,
+                                                                   GCancellable           *cancellable,
+                                                                   GAsyncReadyCallback     callback,
+                                                                   gpointer                user_data);
+static GFileIOStream *    g_file_real_open_readwrite_finish       (GFile                  *file,
+                                                                   GAsyncResult           *res,
+                                                                   GError                **error);
+static void               g_file_real_create_readwrite_async      (GFile                  *file,
+                                                                   GFileCreateFlags        flags,
+                                                                   int                     io_priority,
+                                                                   GCancellable           *cancellable,
+                                                                   GAsyncReadyCallback     callback,
+                                                                   gpointer                user_data);
+static GFileIOStream *    g_file_real_create_readwrite_finish     (GFile                  *file,
+                                                                   GAsyncResult           *res,
+                                                                   GError                **error);
+static void               g_file_real_replace_readwrite_async     (GFile                  *file,
+                                                                   const char             *etag,
+                                                                   gboolean                make_backup,
+                                                                   GFileCreateFlags        flags,
+                                                                   int                     io_priority,
+                                                                   GCancellable           *cancellable,
+                                                                   GAsyncReadyCallback     callback,
+                                                                   gpointer                user_data);
+static GFileIOStream *    g_file_real_replace_readwrite_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);
+
+typedef GFileIface GFileInterface;
+G_DEFINE_INTERFACE (GFile, g_file, G_TYPE_OBJECT)
 
 static void
-g_file_class_init (gpointer g_class,
-                  gpointer class_data)
+g_file_default_init (GFileIface *iface)
 {
-  GFileIface *iface = g_class;
-
   iface->enumerate_children_async = g_file_real_enumerate_children_async;
   iface->enumerate_children_finish = g_file_real_enumerate_children_finish;
   iface->set_display_name_async = g_file_real_set_display_name_async;
   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,12 +293,17 @@ 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->open_readwrite_async = g_file_real_open_readwrite_async;
+  iface->open_readwrite_finish = g_file_real_open_readwrite_finish;
+  iface->create_readwrite_async = g_file_real_create_readwrite_async;
+  iface->create_readwrite_finish = g_file_real_create_readwrite_finish;
+  iface->replace_readwrite_async = g_file_real_replace_readwrite_async;
+  iface->replace_readwrite_finish = g_file_real_replace_readwrite_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;
-}
-
-static void
-g_file_base_init (gpointer g_class)
-{
+  iface->copy_async = g_file_real_copy_async;
+  iface->copy_finish = g_file_real_copy_finish;
 }
 
 
@@ -331,9 +404,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 +488,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
@@ -442,7 +522,7 @@ g_file_get_parse_name (GFile *file)
  *
  * This call does no blocking i/o.
  * 
- * Returns: #GFile that is a duplicate of the given #GFile. 
+ * Returns: a new #GFile that is a duplicate of the given #GFile. 
  **/
 GFile *
 g_file_dup (GFile *file)
@@ -486,7 +566,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.
  * 
@@ -523,6 +606,7 @@ g_file_equal (GFile *file1,
  * 
  * Returns: a #GFile structure to the parent of the given
  *     #GFile or %NULL if there is no parent. 
+ *     Free the returned object with g_object_unref().
  **/
 GFile *
 g_file_get_parent (GFile *file)
@@ -537,11 +621,54 @@ g_file_get_parent (GFile *file)
 }
 
 /**
+ * g_file_has_parent:
+ * @file: input #GFile
+ * @parent: the parent to check for, or %NULL
+ *
+ * Checks if @file has a parent, and optionally, if it is @parent.
+ *
+ * If @parent is %NULL then this function returns %TRUE if @file has any
+ * parent at all.  If @parent is non-%NULL then %TRUE is only returned
+ * if @file is a child of @parent.
+ *
+ * Returns: %TRUE if @file is a child of @parent (or any parent in the
+ *          case that @parent is %NULL).
+ *
+ * Since: 2.24
+ **/
+gboolean
+g_file_has_parent (GFile *file,
+                   GFile *parent)
+{
+  GFile *actual_parent;
+  gboolean result;
+
+  g_return_val_if_fail (G_IS_FILE (file), FALSE);
+  g_return_val_if_fail (parent == NULL || G_IS_FILE (parent), FALSE);
+
+  actual_parent = g_file_get_parent (file);
+
+  if (actual_parent != NULL)
+    {
+      if (parent != NULL)
+        result = g_file_equal (parent, actual_parent);
+      else
+        result = TRUE;
+
+      g_object_unref (actual_parent);
+    }
+  else
+    result = FALSE;
+
+  return result;
+}
+
+/**
  * 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
@@ -550,6 +677,7 @@ g_file_get_parent (GFile *file)
  * This call does no blocking i/o.
  * 
  * Returns: a #GFile to a child specified by @name.
+ *     Free the returned object with g_object_unref().
  **/
 GFile *
 g_file_get_child (GFile      *file,
@@ -577,6 +705,7 @@ g_file_get_child (GFile      *file,
  * 
  * Returns: a #GFile to the specified child, or 
  *     %NULL if the display name couldn't be converted.  
+ *     Free the returned object with g_object_unref().
  **/
 GFile *
 g_file_get_child_for_display_name (GFile      *file,
@@ -594,31 +723,40 @@ 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.
+ * Only full pathname elements are matched, so a path like /foo is not
+ * considered a prefix of /foobar, only of /foo/bar.
  * 
- * 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,8 +769,8 @@ 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 
- *     g_free() when no longer needed.
+ *     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 *
 g_file_get_relative_path (GFile *parent,
@@ -662,6 +800,7 @@ g_file_get_relative_path (GFile *parent,
  * 
  * Returns: #GFile to the resolved path. %NULL if @relative_path 
  *     is %NULL or if @file is invalid.
+ *     Free the returned object with g_object_unref().
  **/
 GFile *
 g_file_resolve_relative_path (GFile      *file,
@@ -690,8 +829,8 @@ g_file_resolve_relative_path (GFile      *file,
  * all the files in the directory.
  *
  * The @attribute value is a string that specifies the file attributes that
- * should be gathered. It is not an error if its not possible to read a particular
- * requested attribute from a file, it just won't be set. @attribute should
+ * should be gathered. It is not an error if it's not possible to read a particular
+ * requested attribute from a file - it just won't be set. @attribute should
  * be a comma-separated list of attribute or attribute wildcards. The wildcard "*"
  * means all attributes, and a wildcard like "standard::*" means all attributes in the standard
  * namespace. An example attribute query be "standard::*,owner::user".
@@ -706,6 +845,7 @@ g_file_resolve_relative_path (GFile      *file,
  * Other errors are possible too.
  *
  * Returns: A #GFileEnumerator if successful, %NULL on error. 
+ *     Free the returned object with g_object_unref().
  **/
 GFileEnumerator *
 g_file_enumerate_children (GFile                *file,
@@ -726,9 +866,9 @@ g_file_enumerate_children (GFile                *file,
 
   if (iface->enumerate_children == NULL)
     {
-      g_set_error (error, G_IO_ERROR,
-                  G_IO_ERROR_NOT_SUPPORTED,
-                  _("Operation not supported"));
+      g_set_error_literal (error, G_IO_ERROR,
+                           G_IO_ERROR_NOT_SUPPORTED,
+                           _("Operation not supported"));
       return NULL;
     }
 
@@ -790,6 +930,7 @@ g_file_enumerate_children_async (GFile               *file,
  * See g_file_enumerate_children_async().
  *
  * Returns: a #GFileEnumerator or %NULL if an error occurred.
+ *     Free the returned object with g_object_unref().
  **/
 GFileEnumerator *
 g_file_enumerate_children_finish (GFile         *file,
@@ -812,6 +953,93 @@ g_file_enumerate_children_finish (GFile         *file,
   return (* iface->enumerate_children_finish) (file, res, error);
 }
 
+/**
+ * g_file_query_exists:
+ * @file: input #GFile.
+ * @cancellable: optional #GCancellable object, %NULL to ignore.
+ *
+ * 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 existence
+ * and then execute something based on the outcome of that, because 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, 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 a G_IO_ERROR_EXISTS error.
+ *
+ * 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
+ * errors that can happen due to races when you execute the operation.
+ * 
+ * Returns: %TRUE if the file exists (and can be detected without error), %FALSE otherwise (or if cancelled).
+ */
+gboolean
+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);
+  if (info != NULL)
+    {
+      g_object_unref (info);
+      return TRUE;
+    }
+  
+  return FALSE;
+}
+
+/**
+ * g_file_query_file_type:
+ * @file: input #GFile.
+ * @flags: a set of #GFileQueryInfoFlags passed to g_file_query_info().
+ * @cancellable: optional #GCancellable object, %NULL to ignore.
+ *
+ * Utility function to inspect the #GFileType of a file. This is
+ * implemented using g_file_query_info() and as such does blocking I/O.
+ *
+ * The primary use case of this method is to check if a file is a regular file,
+ * directory, or symlink.
+ * 
+ * Returns: The #GFileType of the file and #G_FILE_TYPE_UNKNOWN if the file
+ *          does not exist
+ *
+ * Since: 2.18
+ */
+GFileType
+g_file_query_file_type (GFile *file,
+                        GFileQueryInfoFlags   flags,
+                       GCancellable *cancellable)
+{
+  GFileInfo *info;
+  GFileType file_type;
+  
+  g_return_val_if_fail (G_IS_FILE(file), G_FILE_TYPE_UNKNOWN);
+  info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE, flags,
+                           cancellable, NULL);
+  if (info != NULL)
+    {
+      file_type = g_file_info_get_file_type (info);
+      g_object_unref (info);
+    }
+  else
+    file_type = G_FILE_TYPE_UNKNOWN;
+  
+  return file_type;
+}
 
 /**
  * g_file_query_info:
@@ -822,12 +1050,12 @@ g_file_enumerate_children_finish (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 its not possible to read a particular
- * requested attribute from a file, it just won't be set. @attribute should
+ * should be gathered. It is not an error if it's not possible to read a particular
+ * requested attribute from a file - it just won't be set. @attribute should
  * be a comma-separated list of attribute or attribute wildcards. The wildcard "*"
  * means all attributes, and a wildcard like "standard::*" means all attributes in the standard
  * namespace. An example attribute query be "standard::*,owner::user".
@@ -841,13 +1069,14 @@ g_file_enumerate_children_finish (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.
  * Other errors are possible too, and depend on what kind of filesystem the file is on.
  *
  * Returns: a #GFileInfo for the given @file, or %NULL on error.
+ *     Free the returned object with g_object_unref().
  **/
 GFileInfo *
 g_file_query_info (GFile                *file,
@@ -867,9 +1096,9 @@ g_file_query_info (GFile                *file,
 
   if (iface->query_info == NULL)
     {
-      g_set_error (error, G_IO_ERROR,
-                  G_IO_ERROR_NOT_SUPPORTED,
-                  _("Operation not supported"));
+      g_set_error_literal (error, G_IO_ERROR,
+                           G_IO_ERROR_NOT_SUPPORTED,
+                           _("Operation not supported"));
       return NULL;
     }
   
@@ -888,7 +1117,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
@@ -930,6 +1159,7 @@ g_file_query_info_async (GFile               *file,
  * See g_file_query_info_async().
  * 
  * Returns: #GFileInfo for given @file or %NULL on error.
+ *     Free the returned object with g_object_unref().
  **/
 GFileInfo *
 g_file_query_info_finish (GFile         *file,
@@ -965,8 +1195,8 @@ g_file_query_info_finish (GFile         *file,
  * the filesystem.
  *
  * The @attribute value is a string that specifies the file attributes that
- * should be gathered. It is not an error if its not possible to read a particular
- * requested attribute from a file, it just won't be set. @attribute should
+ * should be gathered. It is not an error if it's not possible to read a particular
+ * requested attribute from a file - it just won't be set. @attribute should
  * be a comma-separated list of attribute or attribute wildcards. The wildcard "*"
  * means all attributes, and a wildcard like "fs:*" means all attributes in the fs
  * namespace. The standard namespace for filesystem attributes is "fs".
@@ -982,6 +1212,7 @@ g_file_query_info_finish (GFile         *file,
  * Other errors are possible too, and depend on what kind of filesystem the file is on.
  *
  * Returns: a #GFileInfo or %NULL if there was an error.
+ *     Free the returned object with g_object_unref().
  **/
 GFileInfo *
 g_file_query_filesystem_info (GFile         *file,
@@ -1000,9 +1231,9 @@ g_file_query_filesystem_info (GFile         *file,
 
   if (iface->query_filesystem_info == NULL)
     {
-      g_set_error (error, G_IO_ERROR,
-                  G_IO_ERROR_NOT_SUPPORTED,
-                  _("Operation not supported"));
+      g_set_error_literal (error, G_IO_ERROR,
+                           G_IO_ERROR_NOT_SUPPORTED,
+                           _("Operation not supported"));
       return NULL;
     }
   
@@ -1010,6 +1241,82 @@ 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.
+ *     Free the returned object with g_object_unref().
+ **/
+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. 
@@ -1026,6 +1333,7 @@ g_file_query_filesystem_info (GFile         *file,
  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. 
  * 
  * Returns: a #GMount where the @file is located or %NULL on error.
+ *     Free the returned object with g_object_unref().
  **/
 GMount *
 g_file_find_enclosing_mount (GFile         *file,
@@ -1035,23 +1343,95 @@ 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_literal (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.
+ *     Free the returned object with g_object_unref().
+ **/
+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:
  * @file: #GFile to read.
  * @cancellable: a #GCancellable
@@ -1069,6 +1449,7 @@ g_file_find_enclosing_mount (GFile         *file,
  * Other errors are possible too, and depend on what kind of filesystem the file is on.
  *
  * Returns: #GFileInputStream or %NULL on error.
+ *     Free the returned object with g_object_unref().
  **/
 GFileInputStream *
 g_file_read (GFile         *file,
@@ -1086,9 +1467,9 @@ g_file_read (GFile         *file,
 
   if (iface->read_fn == NULL)
     {
-      g_set_error (error, G_IO_ERROR,
-                  G_IO_ERROR_NOT_SUPPORTED,
-                  _("Operation not supported"));
+      g_set_error_literal (error, G_IO_ERROR,
+                           G_IO_ERROR_NOT_SUPPORTED,
+                           _("Operation not supported"));
       return NULL;
     }
   
@@ -1115,12 +1496,13 @@ g_file_read (GFile         *file,
  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. 
  *
  * Some file systems don't allow all file names, and may
- * return an G_IO_ERROR_INVALID_FILENAME error.
- * If the file is a directory the G_IO_ERROR_IS_DIRECTORY error will be
+ * return an %G_IO_ERROR_INVALID_FILENAME error.
+ * If the file is a directory the %G_IO_ERROR_IS_DIRECTORY error will be
  * returned. Other errors are possible too, and depend on what kind of
  * filesystem the file is on.
  * 
- * Returns: a #GFileOutputStream.
+ * Returns: a #GFileOutputStream, or %NULL on error.
+ *     Free the returned object with g_object_unref().
  **/
 GFileOutputStream *
 g_file_append_to (GFile             *file,
@@ -1139,9 +1521,9 @@ g_file_append_to (GFile             *file,
 
   if (iface->append_to == NULL)
     {
-      g_set_error (error, G_IO_ERROR,
-                  G_IO_ERROR_NOT_SUPPORTED,
-                  _("Operation not supported"));
+      g_set_error_literal (error, G_IO_ERROR,
+                           G_IO_ERROR_NOT_SUPPORTED,
+                           _("Operation not supported"));
       return NULL;
     }
   
@@ -1156,7 +1538,7 @@ g_file_append_to (GFile             *file,
  * @error: a #GError, or %NULL
  *
  * Creates a new file and returns an output stream for writing to it.
- * The file must not already exists.
+ * The file must not already exist.
  *
  * By default files created are generally readable by everyone,
  * but if you pass #G_FILE_CREATE_PRIVATE in @flags the file
@@ -1167,8 +1549,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
@@ -1177,7 +1558,8 @@ g_file_append_to (GFile             *file,
  * filesystem the file is on.
  * 
  * Returns: a #GFileOutputStream for the newly created file, or 
- * %NULL on error.
+ *     %NULL on error.
+ *     Free the returned object with g_object_unref().
  **/
 GFileOutputStream *
 g_file_create (GFile             *file,
@@ -1196,9 +1578,9 @@ g_file_create (GFile             *file,
 
   if (iface->create == NULL)
     {
-      g_set_error (error, G_IO_ERROR,
-                  G_IO_ERROR_NOT_SUPPORTED,
-                  _("Operation not supported"));
+      g_set_error_literal (error, G_IO_ERROR,
+                           G_IO_ERROR_NOT_SUPPORTED,
+                           _("Operation not supported"));
       return NULL;
     }
   
@@ -1216,7 +1598,8 @@ g_file_create (GFile             *file,
  * @error: a #GError, or %NULL
  *
  * Returns an output stream for overwriting the file, possibly
- * creating a backup copy of the file first.
+ * creating a backup copy of the file first. If the file doesn't exist,
+ * it will be created.
  *
  * This will try to replace the file in the safest way possible so
  * that any errors during the writing will not affect an already
@@ -1257,6 +1640,7 @@ g_file_create (GFile             *file,
  * filesystem the file is on.
  *
  * Returns: a #GFileOutputStream or %NULL on error. 
+ *     Free the returned object with g_object_unref().
  **/
 GFileOutputStream *
 g_file_replace (GFile             *file,
@@ -1277,9 +1661,9 @@ g_file_replace (GFile             *file,
 
   if (iface->replace == NULL)
     {
-      g_set_error (error, G_IO_ERROR,
-                  G_IO_ERROR_NOT_SUPPORTED,
-                  _("Operation not supported"));
+      g_set_error_literal (error, G_IO_ERROR,
+                           G_IO_ERROR_NOT_SUPPORTED,
+                           _("Operation not supported"));
       return NULL;
     }
   
@@ -1292,63 +1676,228 @@ g_file_replace (GFile             *file,
 }
 
 /**
- * g_file_read_async:
- * @file: input #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
+ * g_file_open_readwrite:
+ * @file: #GFile to open
+ * @cancellable: a #GCancellable
+ * @error: a #GError, or %NULL
  *
- * Asynchronously opens @file for reading.
+ * Opens an existing file for reading and writing. The result is
+ * a #GFileIOStream that can be used to read and write the contents of the file.
  *
- * For more details, see g_file_read() which is
- * the synchronous version of this call.
+ * 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.
  *
- * When the operation is finished, @callback will be called. You can then call
- * g_file_read_finish() to get the result of the operation.
+ * If the file does not exist, the G_IO_ERROR_NOT_FOUND error will be returned.
+ * If the file is a directory, the G_IO_ERROR_IS_DIRECTORY error will be returned.
+ * Other errors are possible too, and depend on what kind of filesystem the file is on.
+ * Note that in many non-local file cases read and write streams are not supported,
+ * so make sure you really need to do read and write streaming, rather than
+ * just opening for reading or writing.
+ *
+ * Returns: #GFileIOStream or %NULL on error.
+ *     Free the returned object with g_object_unref().
+ *
+ * Since: 2.22
  **/
-void
-g_file_read_async (GFile               *file,
-                  int                  io_priority,
-                  GCancellable        *cancellable,
-                  GAsyncReadyCallback  callback,
-                  gpointer             user_data)
+GFileIOStream *
+g_file_open_readwrite (GFile                      *file,
+                       GCancellable               *cancellable,
+                       GError                    **error)
 {
   GFileIface *iface;
-  
-  g_return_if_fail (G_IS_FILE (file));
+
+  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);
-  (* iface->read_async) (file,
-                        io_priority,
-                        cancellable,
-                        callback,
-                        user_data);
+
+  if (iface->open_readwrite == NULL)
+    {
+      g_set_error_literal (error, G_IO_ERROR,
+                           G_IO_ERROR_NOT_SUPPORTED,
+                           _("Operation not supported"));
+      return NULL;
+    }
+
+  return (* iface->open_readwrite) (file, cancellable, error);
 }
 
 /**
- * g_file_read_finish:
- * @file: input #GFile.
- * @res: a #GAsyncResult. 
- * @error: a #GError, or %NULL
+ * g_file_create_readwrite:
+ * @file: a #GFile
+ * @flags: a set of #GFileCreateFlags
+ * @cancellable: optional #GCancellable object, %NULL to ignore
+ * @error: return location for a #GError, or %NULL
  *
- * Finishes an asynchronous file read operation started with 
- * g_file_read_async(). 
- *  
- * Returns: a #GFileInputStream or %NULL on error.
- **/
-GFileInputStream *
-g_file_read_finish (GFile         *file,
-                   GAsyncResult  *res,
-                   GError       **error)
+ * Creates a new file and returns a stream for reading and writing to it.
+ * The file must not already exist.
+ *
+ * By default files created are generally readable by everyone,
+ * but if you pass #G_FILE_CREATE_PRIVATE in @flags the file
+ * will be made readable only to the current user, to the level that
+ * is supported on the target filesystem.
+ *
+ * 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.
+ *
+ * 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
+ * is too long, %G_IO_ERROR_FILENAME_TOO_LONG will be returned. Other errors
+ * are possible too, and depend on what kind of filesystem the file is on.
+ *
+ * Note that in many non-local file cases read and write streams are not
+ * supported, so make sure you really need to do read and write streaming,
+ * rather than just opening for reading or writing.
+ *
+ * Returns: a #GFileIOStream for the newly created file, or %NULL on error.
+ *     Free the returned object with g_object_unref().
+ *
+ * Since: 2.22
+ */
+GFileIOStream *
+g_file_create_readwrite (GFile             *file,
+                         GFileCreateFlags   flags,
+                         GCancellable      *cancellable,
+                         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))
+  if (g_cancellable_set_error_if_cancelled (cancellable, error))
+    return NULL;
+
+  iface = G_FILE_GET_IFACE (file);
+
+  if (iface->create_readwrite == NULL)
+    {
+      g_set_error_literal (error, G_IO_ERROR,
+                           G_IO_ERROR_NOT_SUPPORTED,
+                           _("Operation not supported"));
+      return NULL;
+    }
+
+  return (* iface->create_readwrite) (file, flags, cancellable, error);
+}
+
+/**
+ * g_file_replace_readwrite:
+ * @file: a #GFile
+ * @etag: an optional <link linkend="gfile-etag">entity tag</link> for the
+ *     current #GFile, or #NULL to ignore
+ * @make_backup: %TRUE if a backup should be created
+ * @flags: a set of #GFileCreateFlags
+ * @cancellable: optional #GCancellable object, %NULL to ignore
+ * @error: return location for a #GError, or %NULL
+ *
+ * Returns an output stream for overwriting the file in readwrite mode,
+ * possibly creating a backup copy of the file first. If the file doesn't
+ * exist, it will be created.
+ *
+ * For details about the behaviour, see g_file_replace() which does the same
+ * thing but returns an output stream only.
+ *
+ * Note that in many non-local file cases read and write streams are not
+ * supported, so make sure you really need to do read and write streaming,
+ * rather than just opening for reading or writing.
+ *
+ * Returns: a #GFileIOStream or %NULL on error.
+ *     Free the returned object with g_object_unref().
+ *
+ * Since: 2.22
+ */
+GFileIOStream *
+g_file_replace_readwrite (GFile             *file,
+                          const char        *etag,
+                          gboolean           make_backup,
+                          GFileCreateFlags   flags,
+                          GCancellable      *cancellable,
+                          GError           **error)
+{
+  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->replace_readwrite == NULL)
+    {
+      g_set_error_literal (error, G_IO_ERROR,
+                           G_IO_ERROR_NOT_SUPPORTED,
+                           _("Operation not supported"));
+      return NULL;
+    }
+
+  return (* iface->replace_readwrite) (file, etag, make_backup, flags, cancellable, error);
+}
+
+/**
+ * g_file_read_async:
+ * @file: input #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 opens @file for reading.
+ *
+ * For more details, see g_file_read() which is
+ * the synchronous version of this call.
+ *
+ * When the operation is finished, @callback will be called. You can then call
+ * g_file_read_finish() to get the result of the operation.
+ **/
+void
+g_file_read_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->read_async) (file,
+                        io_priority,
+                        cancellable,
+                        callback,
+                        user_data);
+}
+
+/**
+ * g_file_read_finish:
+ * @file: input #GFile.
+ * @res: a #GAsyncResult. 
+ * @error: a #GError, or %NULL
+ *
+ * Finishes an asynchronous file read operation started with 
+ * g_file_read_async(). 
+ *  
+ * Returns: a #GFileInputStream or %NULL on error.
+ *     Free the returned object with g_object_unref().
+ **/
+GFileInputStream *
+g_file_read_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))
@@ -1408,6 +1957,7 @@ g_file_append_to_async (GFile               *file,
  * g_file_append_to_async(). 
  * 
  * Returns: a valid #GFileOutputStream or %NULL on error.
+ *     Free the returned object with g_object_unref().
  **/
 GFileOutputStream *
 g_file_append_to_finish (GFile         *file,
@@ -1441,7 +1991,7 @@ g_file_append_to_finish (GFile         *file,
  * @user_data: the data to pass to callback function
  * 
  * Asynchronously creates a new file and returns an output stream for writing to it.
- * The file must not already exists.
+ * The file must not already exist.
  *
  * For more details, see g_file_create() which is
  * the synchronous version of this call.
@@ -1480,6 +2030,7 @@ g_file_create_async (GFile               *file,
  * g_file_create_async(). 
  * 
  * Returns: a #GFileOutputStream or %NULL on error.
+ *     Free the returned object with g_object_unref().
  **/
 GFileOutputStream *
 g_file_create_finish (GFile         *file,
@@ -1559,6 +2110,7 @@ g_file_replace_async (GFile               *file,
  * g_file_replace_async(). 
  * 
  * Returns: a #GFileOutputStream, or %NULL on error.
+ *     Free the returned object with g_object_unref().
  **/
 GFileOutputStream *
 g_file_replace_finish (GFile         *file,
@@ -1576,11 +2128,247 @@ g_file_replace_finish (GFile         *file,
       if (g_simple_async_result_propagate_error (simple, error))
        return NULL;
     }
-  
+
   iface = G_FILE_GET_IFACE (file);
   return (* iface->replace_finish) (file, res, error);
 }
 
+
+/**
+ * g_file_open_readwrite_async:
+ * @file: input #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 opens @file for reading and writing.
+ *
+ * For more details, see g_file_open_readwrite() which is
+ * the synchronous version of this call.
+ *
+ * When the operation is finished, @callback will be called. You can then call
+ * g_file_open_readwrite_finish() to get the result of the operation.
+ *
+ * Since: 2.22
+ **/
+void
+g_file_open_readwrite_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->open_readwrite_async) (file,
+                                   io_priority,
+                                   cancellable,
+                                   callback,
+                                   user_data);
+}
+
+/**
+ * g_file_open_readwrite_finish:
+ * @file: input #GFile.
+ * @res: a #GAsyncResult.
+ * @error: a #GError, or %NULL
+ *
+ * Finishes an asynchronous file read operation started with
+ * g_file_open_readwrite_async().
+ *
+ * Returns: a #GFileIOStream or %NULL on error.
+ *     Free the returned object with g_object_unref().
+ *
+ * Since: 2.22
+ **/
+GFileIOStream *
+g_file_open_readwrite_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->open_readwrite_finish) (file, res, error);
+}
+
+
+/**
+ * g_file_create_readwrite_async:
+ * @file: input #GFile
+ * @flags: a set of #GFileCreateFlags
+ * @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 creates a new file and returns a stream for reading and
+ * writing to it. The file must not already exist.
+ *
+ * For more details, see g_file_create_readwrite() which is
+ * the synchronous version of this call.
+ *
+ * When the operation is finished, @callback will be called. You can then
+ * call g_file_create_readwrite_finish() to get the result of the operation.
+ *
+ * Since: 2.22
+ */
+void
+g_file_create_readwrite_async (GFile               *file,
+                               GFileCreateFlags     flags,
+                               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->create_readwrite_async) (file,
+                                     flags,
+                                     io_priority,
+                                     cancellable,
+                                     callback,
+                                     user_data);
+}
+
+/**
+ * g_file_create_readwrite_finish:
+ * @file: input #GFile
+ * @res: a #GAsyncResult
+ * @error: a #GError, or %NULL
+ *
+ * Finishes an asynchronous file create operation started with
+ * g_file_create_readwrite_async().
+ *
+ * Returns: a #GFileIOStream or %NULL on error.
+ *     Free the returned object with g_object_unref().
+ *
+ * Since: 2.22
+ **/
+GFileIOStream *
+g_file_create_readwrite_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->create_readwrite_finish) (file, res, error);
+}
+
+/**
+ * g_file_replace_readwrite_async:
+ * @file: input #GFile.
+ * @etag: an <link linkend="gfile-etag">entity tag</link> for the
+ *     current #GFile, or NULL to ignore.
+ * @make_backup: %TRUE if a backup should be created.
+ * @flags: a set of #GFileCreateFlags.
+ * @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 overwrites the file in read-write mode, replacing the
+ * contents, possibly creating a backup copy of the file first.
+ *
+ * For more details, see g_file_replace_readwrite() which is
+ * the synchronous version of this call.
+ *
+ * When the operation is finished, @callback will be called. You can then
+ * call g_file_replace_readwrite_finish() to get the result of the operation.
+ *
+ * Since: 2.22
+ */
+void
+g_file_replace_readwrite_async (GFile               *file,
+                                const char          *etag,
+                                gboolean             make_backup,
+                                GFileCreateFlags     flags,
+                                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->replace_readwrite_async) (file,
+                                      etag,
+                                      make_backup,
+                                      flags,
+                                      io_priority,
+                                      cancellable,
+                                      callback,
+                                      user_data);
+}
+
+/**
+ * g_file_replace_readwrite_finish:
+ * @file: input #GFile.
+ * @res: a #GAsyncResult.
+ * @error: a #GError, or %NULL
+ *
+ * Finishes an asynchronous file replace operation started with
+ * g_file_replace_readwrite_async().
+ *
+ * Returns: a #GFileIOStream, or %NULL on error.
+ *     Free the returned object with g_object_unref().
+ *
+ * Since: 2.22
+ */
+GFileIOStream *
+g_file_replace_readwrite_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->replace_readwrite_finish) (file, res, error);
+}
+
 static gboolean
 copy_symlink (GFile           *destination,
              GFileCopyFlags   flags,
@@ -1617,8 +2405,8 @@ copy_symlink (GFile           *destination,
              
              if (file_type == G_FILE_TYPE_DIRECTORY)
                {
-                 g_set_error (error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY,
-                              _("Can't copy over directory"));
+                 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY,
+                                       _("Can't copy over directory"));
                  return FALSE;
                }
            }
@@ -1677,16 +2465,16 @@ open_source_for_copy (GFile           *source,
            {
              if (file_type == G_FILE_TYPE_DIRECTORY)
                {
-                 g_set_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_MERGE,
-                              _("Can't copy directory over directory"));
+                 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_MERGE,
+                                       _("Can't copy directory over directory"));
                  return NULL;
                }
              /* continue to would_recurse error */
            }
          else
            {
-             g_set_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS,
-                          _("Target file exists"));
+             g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_EXISTS,
+                                   _("Target file exists"));
              return NULL;
            }
        }
@@ -1703,8 +2491,8 @@ open_source_for_copy (GFile           *source,
          g_error_free (my_error);
        }
       
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_RECURSE,
-                  _("Can't recursively copy directory"));
+      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_RECURSE,
+                           _("Can't recursively copy directory"));
       return NULL;
     }
 
@@ -1714,8 +2502,12 @@ open_source_for_copy (GFile           *source,
 
 static gboolean
 should_copy (GFileAttributeInfo *info, 
-             gboolean            as_move)
+             gboolean            as_move,
+             gboolean            skip_perms)
 {
+  if (skip_perms && strcmp(info->name, "unix::mode") == 0)
+        return FALSE;
+
   if (as_move)
     return info->flags & G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED;
   return info->flags & G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE;
@@ -1724,7 +2516,8 @@ should_copy (GFileAttributeInfo *info,
 static char *
 build_attribute_list_for_copy (GFileAttributeInfoList *attributes,
                               GFileAttributeInfoList *namespaces,
-                              gboolean                as_move)
+                              gboolean                as_move,
+                              gboolean                skip_perms)
 {
   GString *s;
   gboolean first;
@@ -1737,7 +2530,7 @@ build_attribute_list_for_copy (GFileAttributeInfoList *attributes,
     {
       for (i = 0; i < attributes->n_infos; i++)
        {
-         if (should_copy (&attributes->infos[i], as_move))
+         if (should_copy (&attributes->infos[i], as_move, skip_perms))
            {
              if (first)
                first = FALSE;
@@ -1753,7 +2546,7 @@ build_attribute_list_for_copy (GFileAttributeInfoList *attributes,
     {
       for (i = 0; i < namespaces->n_infos; i++)
        {
-         if (should_copy (&namespaces->infos[i], as_move))
+         if (should_copy (&namespaces->infos[i], as_move, FALSE))
            {
              if (first)
                first = FALSE;
@@ -1761,7 +2554,7 @@ build_attribute_list_for_copy (GFileAttributeInfoList *attributes,
                g_string_append_c (s, ',');
                
              g_string_append (s, namespaces->infos[i].name);
-             g_string_append (s, ":*");
+             g_string_append (s, "::*");
            }
        }
     }
@@ -1781,9 +2574,10 @@ build_attribute_list_for_copy (GFileAttributeInfoList *attributes,
  *
  * Normally only a subset of the file attributes are copied,
  * those that are copies in a normal file copy operation
- * (which for instance does not include e.g. mtime). However
+ * (which for instance does not include e.g. owner). However
  * if #G_FILE_COPY_ALL_METADATA is specified in @flags, then
- * all the metadata that is possible to copy is copied.
+ * all the metadata that is possible to copy is copied. This
+ * is useful when implementing move by copy + delete source.
  *
  * Returns: %TRUE if the attributes were copied successfully, %FALSE otherwise.
  **/
@@ -1800,9 +2594,11 @@ g_file_copy_attributes (GFile           *source,
   GFileInfo *info;
   gboolean as_move;
   gboolean source_nofollow_symlinks;
+  gboolean skip_perms;
 
   as_move = flags & G_FILE_COPY_ALL_METADATA;
   source_nofollow_symlinks = flags & G_FILE_COPY_NOFOLLOW_SYMLINKS;
+  skip_perms = (flags & G_FILE_COPY_TARGET_DEFAULT_PERMS) != 0;
 
   /* Ignore errors here, if the target supports no attributes there is nothing to copy */
   attributes = g_file_query_settable_attributes (destination, cancellable, NULL);
@@ -1811,7 +2607,7 @@ g_file_copy_attributes (GFile           *source,
   if (attributes == NULL && namespaces == NULL)
     return TRUE;
 
-  attrs_to_read = build_attribute_list_for_copy (attributes, namespaces, as_move);
+  attrs_to_read = build_attribute_list_for_copy (attributes, namespaces, as_move, skip_perms);
 
   /* Ignore errors here, if we can't read some info (e.g. if it doesn't exist)
    * we just don't copy it. 
@@ -1827,7 +2623,8 @@ g_file_copy_attributes (GFile           *source,
   if  (info)
     {
       res = g_file_set_attributes_from_info (destination,
-                                            info, 0,
+                                            info,
+                         G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                             cancellable,
                                             error);
       g_object_unref (info);
@@ -1839,10 +2636,10 @@ g_file_copy_attributes (GFile           *source,
   return res;
 }
 
-/* Closes the streams */
 static gboolean
 copy_stream_with_progress (GInputStream           *in,
                           GOutputStream          *out,
+                           GFile                  *source,
                           GCancellable           *cancellable,
                           GFileProgressCallback   progress_callback,
                           gpointer                progress_callback_data,
@@ -1850,20 +2647,42 @@ 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;
-  info = g_file_input_stream_query_info (G_FILE_INPUT_STREAM (in),
-                                        G_FILE_ATTRIBUTE_STANDARD_SIZE,
-                                        cancellable, NULL);
-  if (info)
+  total_size = -1;
+  /* avoid performance impact of querying total size when it's not needed */
+  if (progress_callback)
     {
-      total_size = g_file_info_get_size (info);
-      g_object_unref (info);
+      info = g_file_input_stream_query_info (G_FILE_INPUT_STREAM (in),
+                                             G_FILE_ATTRIBUTE_STANDARD_SIZE,
+                                             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)
+        {
+          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;
@@ -1897,59 +2716,174 @@ copy_stream_with_progress (GInputStream           *in,
 
       if (!res)
         break;
-      
+
       if (progress_callback)
        progress_callback (current_size, total_size, progress_callback_data);
     }
 
-  if (!res)
-    error = NULL; /* Ignore further errors */
-
   /* 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);
-
-  /* But write errors on close are bad! */
-  if (!g_output_stream_close (out, cancellable, error))
-    res = FALSE;
-
-  g_object_unref (in);
-  g_object_unref (out);
-      
   return res;
 }
 
+#ifdef HAVE_SPLICE
+
 static gboolean
-file_copy_fallback (GFile                  *source,
-                   GFile                  *destination,
-                   GFileCopyFlags          flags,
-                   GCancellable           *cancellable,
-                   GFileProgressCallback   progress_callback,
-                   gpointer                progress_callback_data,
-                   GError                **error)
+do_splice (int     fd_in,
+          loff_t *off_in,
+           int     fd_out,
+          loff_t *off_out,
+           size_t  len,
+           long   *bytes_transferd,
+           GError **error)
 {
-  GInputStream *in;
-  GOutputStream *out;
-  GFileInfo *info;
-  const char *target;
+  long result;
 
-  /* Maybe copy the symlink? */
-  if (flags & G_FILE_COPY_NOFOLLOW_SYMLINKS)
+retry:
+  result = splice (fd_in, off_in, fd_out, off_out, len, SPLICE_F_MORE);
+
+  if (result == -1)
     {
-      info = g_file_query_info (source,
-                               G_FILE_ATTRIBUTE_STANDARD_TYPE "," G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
-                               G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
-                               cancellable,
-                               error);
-      if (info == NULL)
-       return FALSE;
+      int errsv = errno;
 
-      if (g_file_info_get_file_type (info) == G_FILE_TYPE_SYMBOLIC_LINK &&
-         (target = g_file_info_get_symlink_target (info)) != NULL)
+      if (errsv == EINTR)
+        goto retry;
+      else if (errsv == ENOSYS || errsv == EINVAL)
+        g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                             _("Splice not supported"));
+      else
+        g_set_error (error, G_IO_ERROR,
+                     g_io_error_from_errno (errsv),
+                     _("Error splicing file: %s"),
+                     g_strerror (errsv));
+
+      return FALSE;
+    }
+
+  *bytes_transferd = result;
+  return TRUE;
+}
+
+static gboolean
+splice_stream_with_progress (GInputStream           *in,
+                             GOutputStream          *out,
+                             GCancellable           *cancellable,
+                             GFileProgressCallback   progress_callback,
+                             gpointer                progress_callback_data,
+                             GError                **error)
+{
+  int buffer[2];
+  gboolean res;
+  goffset total_size;
+  loff_t offset_in;
+  loff_t offset_out;
+  int fd_in, fd_out;
+
+  fd_in = g_file_descriptor_based_get_fd (G_FILE_DESCRIPTOR_BASED (in));
+  fd_out = g_file_descriptor_based_get_fd (G_FILE_DESCRIPTOR_BASED (out));
+
+  if (pipe (buffer) != 0)
+    {
+      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                           "Pipe creation failed");
+      return FALSE;
+    }
+
+  total_size = -1;
+  /* avoid performance impact of querying total size when it's not needed */
+  if (progress_callback)
+    {
+      struct stat sbuf;
+
+      if (fstat (fd_in, &sbuf) == 0)
+        total_size = sbuf.st_size;
+    }
+
+  if (total_size == -1)
+    total_size = 0;
+
+  offset_in = offset_out = 0;
+  res = FALSE;
+  while (TRUE)
+    {
+      long n_read;
+      long n_written;
+
+      if (g_cancellable_set_error_if_cancelled (cancellable, error))
+        break;
+
+      if (!do_splice (fd_in, &offset_in, buffer[1], NULL, 1024*64, &n_read, error))
+        break;
+
+      if (n_read == 0)
+        {
+          res = TRUE;
+          break;
+        }
+
+      while (n_read > 0)
+        {
+          if (g_cancellable_set_error_if_cancelled (cancellable, error))
+            goto out;
+
+          if (!do_splice (buffer[0], NULL, fd_out, &offset_out, n_read, &n_written, error))
+            goto out;
+
+          n_read -= n_written;
+        }
+
+      if (progress_callback)
+        progress_callback (offset_in, total_size, progress_callback_data);
+    }
+
+  /* Make sure we send full copied size */
+  if (progress_callback)
+    progress_callback (offset_in, total_size, progress_callback_data);
+
+ out:
+  close (buffer[0]);
+  close (buffer[1]);
+
+  return res;
+}
+#endif
+
+static gboolean
+file_copy_fallback (GFile                  *source,
+                   GFile                  *destination,
+                   GFileCopyFlags          flags,
+                   GCancellable           *cancellable,
+                   GFileProgressCallback   progress_callback,
+                   gpointer                progress_callback_data,
+                   GError                **error)
+{
+  GInputStream *in;
+  GOutputStream *out;
+  GFileInfo *info;
+  const char *target;
+  gboolean result;
+#ifdef HAVE_SPLICE
+  gboolean fallback = TRUE;
+#endif
+
+  /* need to know the file type */
+  info = g_file_query_info (source,
+                           G_FILE_ATTRIBUTE_STANDARD_TYPE "," G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
+                           G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+                           cancellable,
+                           error);
+
+  if (info == NULL)
+         return FALSE;
+
+  /* Maybe copy the symlink? */
+  if ((flags & G_FILE_COPY_NOFOLLOW_SYMLINKS) &&
+      g_file_info_get_file_type (info) == G_FILE_TYPE_SYMBOLIC_LINK)
+    {
+      target = g_file_info_get_symlink_target (info);
+      if (target)
        {
          if (!copy_symlink (destination, flags, cancellable, target, error))
            {
@@ -1960,10 +2894,23 @@ file_copy_fallback (GFile                  *source,
          g_object_unref (info);
          goto copied_file;
        }
-      
+        /* ... else fall back on a regular file copy */
+       g_object_unref (info);
+    }
+  /* Handle "special" files (pipes, device nodes, ...)? */
+  else if (g_file_info_get_file_type (info) == G_FILE_TYPE_SPECIAL)
+    {
+      /* FIXME: could try to recreate device nodes and others? */
+
+      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                           _("Can't copy special file"));
       g_object_unref (info);
+      return FALSE;
     }
-  
+  /* Everything else should just fall back on a regular copy. */
+  else
+    g_object_unref (info);
+
   in = open_source_for_copy (source, destination, flags, cancellable, error);
   if (in == NULL)
     return FALSE;
@@ -1971,8 +2918,9 @@ file_copy_fallback (GFile                  *source,
   if (flags & G_FILE_COPY_OVERWRITE)
     {
       out = (GOutputStream *)g_file_replace (destination,
-                                            NULL, 0,
+                                            NULL,
                                             flags & G_FILE_COPY_BACKUP,
+                                             G_FILE_CREATE_REPLACE_DESTINATION,
                                             cancellable, error);
     }
   else
@@ -1986,13 +2934,45 @@ file_copy_fallback (GFile                  *source,
       return FALSE;
     }
 
-  if (!copy_stream_with_progress (in, out, cancellable,
-                                 progress_callback, progress_callback_data,
-                                 error))
+#ifdef HAVE_SPLICE
+  if (G_IS_FILE_DESCRIPTOR_BASED (in) && G_IS_FILE_DESCRIPTOR_BASED (out))
+    {
+      GError *splice_err = NULL;
+
+      result = splice_stream_with_progress (in, out, cancellable,
+                                            progress_callback, progress_callback_data,
+                                            &splice_err);
+
+      if (result || !g_error_matches (splice_err, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
+        {
+          fallback = FALSE;
+          if (!result)
+            g_propagate_error (error, splice_err);
+        }
+      else
+        g_clear_error (&splice_err);
+    }
+
+  if (fallback)
+#endif
+    result = copy_stream_with_progress (in, out, source, cancellable,
+                                       progress_callback, progress_callback_data,
+                                       error);
+
+  /* Don't care about errors in source here */
+  g_input_stream_close (in, cancellable, NULL);
+
+  /* But write errors on close are bad! */
+  if (!g_output_stream_close (out, cancellable, result ? error : NULL))
+    result = FALSE;
+
+  g_object_unref (in);
+  g_object_unref (out);
+
+  if (result == FALSE)
     return FALSE;
 
  copied_file:
-
   /* Ignore errors here. Failure to copy metadata is not a hard error */
   g_file_copy_attributes (source, destination,
                          flags, cancellable, NULL);
@@ -2068,14 +3048,40 @@ g_file_copy (GFile                  *source,
   if (g_cancellable_set_error_if_cancelled (cancellable, error))
     return FALSE;
   
-  if (G_OBJECT_TYPE (source) == G_OBJECT_TYPE (destination))
+  iface = G_FILE_GET_IFACE (destination);
+  if (iface->copy)
     {
-      iface = G_FILE_GET_IFACE (source);
+      my_error = NULL;
+      res = (* iface->copy) (source, destination,
+                            flags, cancellable,
+                            progress_callback, progress_callback_data,
+                            &my_error);
+      
+      if (res)
+       return TRUE;
+      
+      if (my_error->domain != G_IO_ERROR || my_error->code != G_IO_ERROR_NOT_SUPPORTED)
+       {
+         g_propagate_error (error, my_error);
+             return FALSE;
+       }
+      else
+       g_clear_error (&my_error);
+    }
 
+  /* If the types are different, and the destination method failed
+     also try the source method */
+  if (G_OBJECT_TYPE (source) != G_OBJECT_TYPE (destination))
+    {
+      iface = G_FILE_GET_IFACE (source);
+      
       if (iface->copy)
        {
          my_error = NULL;
-         res = (* iface->copy) (source, destination, flags, cancellable, progress_callback, progress_callback_data, &my_error);
+         res = (* iface->copy) (source, destination,
+                                flags, cancellable,
+                                progress_callback, progress_callback_data,
+                                &my_error);
          
          if (res)
            return TRUE;
@@ -2085,14 +3091,99 @@ g_file_copy (GFile                  *source,
              g_propagate_error (error, my_error);
              return FALSE;
            }
+         else
+           g_clear_error (&my_error);
        }
     }
-
+  
   return file_copy_fallback (source, destination, flags, cancellable,
                             progress_callback, progress_callback_data,
                             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:
@@ -2106,7 +3197,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.
  * 
@@ -2162,14 +3253,38 @@ g_file_move (GFile                  *source,
   if (g_cancellable_set_error_if_cancelled (cancellable, error))
     return FALSE;
   
-  if (G_OBJECT_TYPE (source) == G_OBJECT_TYPE (destination))
+  iface = G_FILE_GET_IFACE (destination);
+  if (iface->move)
     {
-      iface = G_FILE_GET_IFACE (source);
+      my_error = NULL;
+      res = (* iface->move) (source, destination,
+                            flags, cancellable,
+                            progress_callback, progress_callback_data,
+                            &my_error);
+      
+      if (res)
+       return TRUE;
+      
+      if (my_error->domain != G_IO_ERROR || my_error->code != G_IO_ERROR_NOT_SUPPORTED)
+       {
+         g_propagate_error (error, my_error);
+         return FALSE;
+       }
+    }
 
+  /* If the types are different, and the destination method failed
+     also try the source method */
+  if (G_OBJECT_TYPE (source) != G_OBJECT_TYPE (destination))
+    {
+      iface = G_FILE_GET_IFACE (source);
+      
       if (iface->move)
        {
          my_error = NULL;
-         res = (* iface->move) (source, destination, flags, cancellable, progress_callback, progress_callback_data, &my_error);
+         res = (* iface->move) (source, destination,
+                                flags, cancellable,
+                                progress_callback, progress_callback_data,
+                                &my_error);
          
          if (res)
            return TRUE;
@@ -2181,12 +3296,12 @@ g_file_move (GFile                  *source,
            }
        }
     }
-
+  
   if (flags & G_FILE_COPY_NO_FALLBACK_FOR_MOVE)
     {  
-      g_set_error (error, G_IO_ERROR,
-                  G_IO_ERROR_NOT_SUPPORTED,
-                  _("Operation not supported"));
+      g_set_error_literal (error, G_IO_ERROR,
+                           G_IO_ERROR_NOT_SUPPORTED,
+                           _("Operation not supported"));
       return FALSE;
     }
   
@@ -2205,7 +3320,16 @@ g_file_move (GFile                  *source,
  * @cancellable: optional #GCancellable object, %NULL to ignore.
  * @error: a #GError, or %NULL 
  *
- * Creates a directory.
+ * Creates a directory. Note that this will only create a child directory of
+ * the immediate parent directory of the path or URI given by the #GFile. To 
+ * recursively create directories, see g_file_make_directory_with_parents().
+ * This function will fail if the parent directory does not exist, setting 
+ * @error to %G_IO_ERROR_NOT_FOUND. If the file system doesn't support creating
+ * directories, this function will fail, setting @error to 
+ * %G_IO_ERROR_NOT_SUPPORTED.
+ *
+ * For a local #GFile the newly created directory will have the default
+ * (current) ownership and permissions of the current process.
  * 
  * If @cancellable is not %NULL, then the operation can be cancelled by
  * triggering the cancellable object from another thread. If the operation
@@ -2229,9 +3353,9 @@ g_file_make_directory (GFile         *file,
 
   if (iface->make_directory == NULL)
     {
-      g_set_error (error, G_IO_ERROR,
-                  G_IO_ERROR_NOT_SUPPORTED,
-                  _("Operation not supported"));
+      g_set_error_literal (error, G_IO_ERROR,
+                           G_IO_ERROR_NOT_SUPPORTED,
+                           _("Operation not supported"));
       return FALSE;
     }
   
@@ -2239,21 +3363,103 @@ g_file_make_directory (GFile         *file,
 }
 
 /**
- * g_file_make_symbolic_link:
+ * g_file_make_directory_with_parents:
  * @file: input #GFile.
- * @symlink_value: a string with the value of the new symlink.
  * @cancellable: optional #GCancellable object, %NULL to ignore.
- * @error: a #GError. 
- * 
- * Creates a symbolic link.
+ * @error: a #GError, or %NULL 
  *
+ * Creates a directory and any parent directories that may not exist similar to
+ * 'mkdir -p'. If the file system does not support creating directories, this
+ * function will fail, setting @error to %G_IO_ERROR_NOT_SUPPORTED.
+ * 
+ * For a local #GFile the newly created directories will have the default
+ * (current) ownership and permissions of the current process.
+ * 
  * 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: %TRUE on the creation of a new symlink, %FALSE otherwise.
+ * Returns: %TRUE if all directories have been successfully created, %FALSE
+ * otherwise.
+ *
+ * Since: 2.18
  **/
 gboolean
+g_file_make_directory_with_parents (GFile         *file,
+                                   GCancellable  *cancellable,
+                                   GError       **error)
+{
+  gboolean result;
+  GFile *parent_file, *work_file;
+  GList *list = NULL, *l;
+  GError *my_error = NULL;
+
+  if (g_cancellable_set_error_if_cancelled (cancellable, error))
+    return FALSE;
+  
+  result = g_file_make_directory (file, cancellable, &my_error);
+  if (result || my_error->code != G_IO_ERROR_NOT_FOUND) 
+    {
+      if (my_error)
+        g_propagate_error (error, my_error);
+      return result;
+    }
+  
+  work_file = file;
+  
+  while (!result && my_error->code == G_IO_ERROR_NOT_FOUND) 
+    {
+      g_clear_error (&my_error);
+    
+      parent_file = g_file_get_parent (work_file);
+      if (parent_file == NULL)
+        break;
+      result = g_file_make_directory (parent_file, cancellable, &my_error);
+    
+      if (!result && my_error->code == G_IO_ERROR_NOT_FOUND)
+        list = g_list_prepend (list, parent_file);
+
+      work_file = parent_file;
+    }
+
+  for (l = list; result && l; l = l->next)
+    {
+      result = g_file_make_directory ((GFile *) l->data, cancellable, &my_error);
+    }
+  
+  /* Clean up */
+  while (list != NULL) 
+    {
+      g_object_unref ((GFile *) list->data);
+      list = g_list_remove (list, list->data);
+    }
+
+  if (!result) 
+    {
+      g_propagate_error (error, my_error);
+      return result;
+    }
+  
+  return g_file_make_directory (file, cancellable, error);
+}
+
+/**
+ * g_file_make_symbolic_link:
+ * @file: a #GFile with the name of the symlink to create
+ * @symlink_value: a string with the path for the target of the new symlink
+ * @cancellable: optional #GCancellable object, %NULL to ignore.
+ * @error: a #GError.
+ *
+ * Creates a symbolic link named @file which contains the string
+ * @symlink_value.
+ *
+ * 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: %TRUE on the creation of a new symlink, %FALSE otherwise.
+ */
+gboolean
 g_file_make_symbolic_link (GFile         *file,
                           const char    *symlink_value,
                           GCancellable  *cancellable,
@@ -2269,9 +3475,9 @@ g_file_make_symbolic_link (GFile         *file,
 
   if (*symlink_value == '\0')
     {
-      g_set_error (error, G_IO_ERROR,
-                   G_IO_ERROR_INVALID_ARGUMENT,
-                   _("Invalid symlink value given"));
+      g_set_error_literal (error, G_IO_ERROR,
+                           G_IO_ERROR_INVALID_ARGUMENT,
+                           _("Invalid symlink value given"));
       return FALSE;
     }
   
@@ -2279,9 +3485,9 @@ g_file_make_symbolic_link (GFile         *file,
 
   if (iface->make_symbolic_link == NULL)
     {
-      g_set_error (error, G_IO_ERROR,
-                  G_IO_ERROR_NOT_SUPPORTED,
-                  _("Operation not supported"));
+      g_set_error_literal (error, G_IO_ERROR,
+                           G_IO_ERROR_NOT_SUPPORTED,
+                           _("Operation not supported"));
       return FALSE;
     }
   
@@ -2294,7 +3500,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
@@ -2318,9 +3525,9 @@ g_file_delete (GFile         *file,
 
   if (iface->delete_file == NULL)
     {
-      g_set_error (error, G_IO_ERROR,
-                  G_IO_ERROR_NOT_SUPPORTED,
-                  _("Operation not supported"));
+      g_set_error_literal (error, G_IO_ERROR,
+                           G_IO_ERROR_NOT_SUPPORTED,
+                           _("Operation not supported"));
       return FALSE;
     }
   
@@ -2361,9 +3568,9 @@ g_file_trash (GFile         *file,
 
   if (iface->trash == NULL)
     {
-      g_set_error (error,
-                  G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
-                  _("Trash not supported"));
+      g_set_error_literal (error,
+                           G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                           _("Trash not supported"));
       return FALSE;
     }
   
@@ -2392,7 +3599,9 @@ g_file_trash (GFile         *file,
  * triggering the cancellable object from another thread. If the operation
  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. 
  * 
- * Returns: a #GFile specifying what @file was renamed to, or %NULL if there was an error.
+ * Returns: a #GFile specifying what @file was renamed to, or %NULL 
+ *     if there was an error.
+ *     Free the returned object with g_object_unref().
  **/
 GFile *
 g_file_set_display_name (GFile         *file,
@@ -2434,7 +3643,7 @@ g_file_set_display_name (GFile         *file,
  * 
  * Asynchronously sets the display name for a given #GFile.
  * 
- * For more details, see g_set_display_name() which is
+ * For more details, see g_file_set_display_name() which is
  * the synchronous version of this call.
  *
  * When the operation is finished, @callback will be called. You can then call
@@ -2472,6 +3681,7 @@ g_file_set_display_name_async (GFile               *file,
  * g_file_set_display_name_async().
  * 
  * Returns: a #GFile or %NULL on error.
+ *     Free the returned object with g_object_unref().
  **/
 GFile *
 g_file_set_display_name_finish (GFile         *file,
@@ -2642,9 +3852,9 @@ g_file_set_attribute (GFile                      *file,
 
   if (iface->set_attribute == NULL)
     {
-      g_set_error (error, G_IO_ERROR,
-                  G_IO_ERROR_NOT_SUPPORTED,
-                  _("Operation not supported"));
+      g_set_error_literal (error, G_IO_ERROR,
+                           G_IO_ERROR_NOT_SUPPORTED,
+                           _("Operation not supported"));
       return FALSE;
     }
 
@@ -3008,9 +4218,10 @@ 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
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied, or %NULL.
  * @user_data: the data to pass to callback function
  * 
  * Mounts a file of type G_FILE_TYPE_MOUNTABLE.
@@ -3026,6 +4237,7 @@ g_file_set_attribute_int64 (GFile                *file,
  **/
 void
 g_file_mount_mountable (GFile               *file,
+                       GMountMountFlags     flags,
                        GMountOperation     *mount_operation,
                        GCancellable        *cancellable,
                        GAsyncReadyCallback  callback,
@@ -3037,15 +4249,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,
@@ -3064,6 +4280,7 @@ g_file_mount_mountable (GFile               *file,
  * with g_file_mount_mountable().
  *
  * Returns: a #GFile or %NULL on error.
+ *     Free the returned object with g_object_unref().
  **/
 GFile *
 g_file_mount_mountable_finish (GFile         *file,
@@ -3091,7 +4308,7 @@ g_file_mount_mountable_finish (GFile         *file,
  * @file: input #GFile.
  * @flags: flags affecting the operation
  * @cancellable: optional #GCancellable object, %NULL to ignore.
- * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied, or %NULL.
  * @user_data: the data to pass to callback function
  *
  * Unmounts a file of type G_FILE_TYPE_MOUNTABLE.
@@ -3102,6 +4319,8 @@ g_file_mount_mountable_finish (GFile         *file,
  *
  * When the operation is finished, @callback will be called. You can then call
  * g_file_unmount_mountable_finish() to get the result of the operation.
+ *
+ * Deprecated: 2.22: Use g_file_unmount_mountable_with_operation() instead.
  **/
 void
 g_file_unmount_mountable (GFile               *file,
@@ -3117,12 +4336,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,
@@ -3144,6 +4366,8 @@ g_file_unmount_mountable (GFile               *file,
  *
  * Returns: %TRUE if the operation finished successfully. %FALSE
  * otherwise.
+ *
+ * Deprecated: 2.22: Use g_file_unmount_mountable_with_operation_finish() instead.
  **/
 gboolean
 g_file_unmount_mountable_finish (GFile         *file,
@@ -3167,26 +4391,128 @@ g_file_unmount_mountable_finish (GFile         *file,
 }
 
 /**
- * g_file_eject_mountable:
+ * g_file_unmount_mountable_with_operation:
  * @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
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied, or %NULL.
  * @user_data: the data to pass to callback function
- * 
- * Starts an asynchronous eject on a mountable.  
- * When this operation has completed, @callback will be called with
- * @user_user data, and the operation can be finalized with 
- * g_file_eject_mountable_finish().
- * 
+ *
+ * Unmounts a file of type G_FILE_TYPE_MOUNTABLE.
+ *
  * 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. 
+ * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
+ *
+ * When the operation is finished, @callback will be called. You can then call
+ * g_file_unmount_mountable_finish() to get the result of the operation.
+ *
+ * Since: 2.22
  **/
 void
-g_file_eject_mountable (GFile               *file,
-                       GMountUnmountFlags   flags,
-                       GCancellable        *cancellable,
+g_file_unmount_mountable_with_operation (GFile               *file,
+                                         GMountUnmountFlags   flags,
+                                         GMountOperation     *mount_operation,
+                                         GCancellable        *cancellable,
+                                         GAsyncReadyCallback  callback,
+                                         gpointer             user_data)
+{
+  GFileIface *iface;
+
+  g_return_if_fail (G_IS_FILE (file));
+
+  iface = G_FILE_GET_IFACE (file);
+
+  if (iface->unmount_mountable == NULL && iface->unmount_mountable_with_operation == 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;
+    }
+
+  if (iface->unmount_mountable_with_operation != NULL)
+    (* iface->unmount_mountable_with_operation) (file,
+                                                 flags,
+                                                 mount_operation,
+                                                 cancellable,
+                                                 callback,
+                                                 user_data);
+  else
+    (* iface->unmount_mountable) (file,
+                                  flags,
+                                  cancellable,
+                                  callback,
+                                  user_data);
+}
+
+/**
+ * g_file_unmount_mountable_with_operation_finish:
+ * @file: input #GFile.
+ * @result: a #GAsyncResult.
+ * @error: a #GError, or %NULL
+ *
+ * Finishes an unmount operation, see g_file_unmount_mountable_with_operation() for details.
+ *
+ * Finish an asynchronous unmount operation that was started
+ * with g_file_unmount_mountable_with_operation().
+ *
+ * Returns: %TRUE if the operation finished successfully. %FALSE
+ * otherwise.
+ *
+ * Since: 2.22
+ **/
+gboolean
+g_file_unmount_mountable_with_operation_finish (GFile         *file,
+                                                GAsyncResult  *result,
+                                                GError       **error)
+{
+  GFileIface *iface;
+
+  g_return_val_if_fail (G_IS_FILE (file), FALSE);
+  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+  if (G_IS_SIMPLE_ASYNC_RESULT (result))
+    {
+      GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
+      if (g_simple_async_result_propagate_error (simple, error))
+       return FALSE;
+    }
+
+  iface = G_FILE_GET_IFACE (file);
+  if (iface->unmount_mountable_with_operation_finish != NULL)
+    return (* iface->unmount_mountable_with_operation_finish) (file, result, error);
+  else
+    return (* iface->unmount_mountable_finish) (file, result, error);
+}
+
+/**
+ * g_file_eject_mountable:
+ * @file: input #GFile.
+ * @flags: flags affecting the operation
+ * @cancellable: optional #GCancellable object, %NULL to ignore.
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied, or %NULL.
+ * @user_data: the data to pass to callback function
+ * 
+ * Starts an asynchronous eject on a mountable.  
+ * When this operation has completed, @callback will be called with
+ * @user_user data, and the operation can be finalized with 
+ * g_file_eject_mountable_finish().
+ * 
+ * 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. 
+ *
+ * Deprecated: 2.22: Use g_file_eject_mountable_with_operation() instead.
+ **/
+void
+g_file_eject_mountable (GFile               *file,
+                       GMountUnmountFlags   flags,
+                       GCancellable        *cancellable,
                        GAsyncReadyCallback  callback,
                        gpointer             user_data)
 {
@@ -3196,13 +4522,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,
@@ -3222,6 +4551,8 @@ g_file_eject_mountable (GFile               *file,
  * 
  * Returns: %TRUE if the @file was ejected successfully. %FALSE 
  * otherwise.
+ *
+ * Deprecated: 2.22: Use g_file_eject_mountable_with_operation_finish() instead.
  **/
 gboolean
 g_file_eject_mountable_finish (GFile         *file,
@@ -3245,6 +4576,104 @@ g_file_eject_mountable_finish (GFile         *file,
 }
 
 /**
+ * g_file_eject_mountable_with_operation:
+ * @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.
+ * @user_data: the data to pass to callback function
+ *
+ * Starts an asynchronous eject on a mountable.
+ * When this operation has completed, @callback will be called with
+ * @user_user data, and the operation can be finalized with
+ * g_file_eject_mountable_with_operation_finish().
+ *
+ * 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.
+ *
+ * Since: 2.22
+ **/
+void
+g_file_eject_mountable_with_operation (GFile               *file,
+                                       GMountUnmountFlags   flags,
+                                       GMountOperation     *mount_operation,
+                                       GCancellable        *cancellable,
+                                       GAsyncReadyCallback  callback,
+                                       gpointer             user_data)
+{
+  GFileIface *iface;
+
+  g_return_if_fail (G_IS_FILE (file));
+
+  iface = G_FILE_GET_IFACE (file);
+
+  if (iface->eject_mountable == NULL && iface->eject_mountable_with_operation == 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;
+    }
+
+  if (iface->eject_mountable_with_operation != NULL)
+    (* iface->eject_mountable_with_operation) (file,
+                                               flags,
+                                               mount_operation,
+                                               cancellable,
+                                               callback,
+                                               user_data);
+  else
+    (* iface->eject_mountable) (file,
+                                flags,
+                                cancellable,
+                                callback,
+                                user_data);
+}
+
+/**
+ * g_file_eject_mountable_with_operation_finish:
+ * @file: input #GFile.
+ * @result: a #GAsyncResult.
+ * @error: a #GError, or %NULL
+ *
+ * Finishes an asynchronous eject operation started by
+ * g_file_eject_mountable_with_operation().
+ *
+ * Returns: %TRUE if the @file was ejected successfully. %FALSE
+ * otherwise.
+ *
+ * Since: 2.22
+ **/
+gboolean
+g_file_eject_mountable_with_operation_finish (GFile         *file,
+                                              GAsyncResult  *result,
+                                              GError       **error)
+{
+  GFileIface *iface;
+
+  g_return_val_if_fail (G_IS_FILE (file), FALSE);
+  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+  if (G_IS_SIMPLE_ASYNC_RESULT (result))
+    {
+      GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
+      if (g_simple_async_result_propagate_error (simple, error))
+       return FALSE;
+    }
+
+  iface = G_FILE_GET_IFACE (file);
+  if (iface->eject_mountable_with_operation_finish != NULL)
+    return (* iface->eject_mountable_with_operation_finish) (file, result, error);
+  else
+    return (* iface->eject_mountable_finish) (file, result, error);
+}
+
+/**
  * g_file_monitor_directory:
  * @file: input #GFile.
  * @flags: a set of #GFileMonitorFlags.
@@ -3258,8 +4687,8 @@ g_file_eject_mountable_finish (GFile         *file,
  * triggering the cancellable object from another thread. If the operation
  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. 
  * 
- * Returns: a #GFileMonitor for the given @file, 
- * or %NULL on error.
+ * Returns: a #GFileMonitor for the given @file, or %NULL on error.
+ *     Free the returned object with g_object_unref().
  **/
 GFileMonitor*
 g_file_monitor_directory (GFile             *file,
@@ -3278,9 +4707,9 @@ g_file_monitor_directory (GFile             *file,
 
   if (iface->monitor_dir == NULL)
     {
-      g_set_error (error, G_IO_ERROR,
-                  G_IO_ERROR_NOT_SUPPORTED,
-                  _("Operation not supported"));
+      g_set_error_literal (error, G_IO_ERROR,
+                           G_IO_ERROR_NOT_SUPPORTED,
+                           _("Operation not supported"));
       return NULL;
     }
 
@@ -3301,7 +4730,8 @@ g_file_monitor_directory (GFile             *file,
  * triggering the cancellable object from another thread. If the operation
  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. 
  * 
- * Returns: a #GFileMonitor for the given @file.
+ * Returns: a #GFileMonitor for the given @file, or %NULL on error.
+ *     Free the returned object with g_object_unref().
  **/
 GFileMonitor*
 g_file_monitor_file (GFile             *file,
@@ -3322,7 +4752,7 @@ g_file_monitor_file (GFile             *file,
   monitor = NULL;
   
   if (iface->monitor_file)
-    monitor = (* iface->monitor_file) (file, flags, cancellable, error);
+    monitor = (* iface->monitor_file) (file, flags, cancellable, NULL);
 
 /* Fallback to polling */
   if (monitor == NULL)
@@ -3331,6 +4761,37 @@ g_file_monitor_file (GFile             *file,
   return monitor;
 }
 
+/**
+ * g_file_monitor:
+ * @file: input #GFile
+ * @flags: a set of #GFileMonitorFlags
+ * @cancellable: optional #GCancellable object, %NULL to ignore
+ * @error: a #GError, or %NULL
+ * 
+ * Obtains a file or directory monitor for the given file, depending
+ * on the type of the 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 #GFileMonitor for the given @file, or %NULL on error.
+ *     Free the returned object with g_object_unref().
+ *
+ * Since: 2.18
+ */
+GFileMonitor*
+g_file_monitor (GFile             *file,
+               GFileMonitorFlags  flags,
+               GCancellable      *cancellable,
+               GError           **error)
+{
+  if (g_file_query_file_type (file, 0, cancellable) == G_FILE_TYPE_DIRECTORY)
+    return g_file_monitor_directory (file, flags, cancellable, error);
+  else
+    return g_file_monitor_file (file, flags, cancellable, error);
+}
+
 /********************************************
  *   Default implementation of async ops    *
  ********************************************/
@@ -3414,6 +4875,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;
@@ -3500,6 +5035,18 @@ open_read_async_thread (GSimpleAsyncResult *res,
 
   iface = G_FILE_GET_IFACE (object);
 
+  if (iface->read_fn == NULL)
+    {
+      g_set_error_literal (&error, G_IO_ERROR,
+                           G_IO_ERROR_NOT_SUPPORTED,
+                           _("Operation not supported"));
+
+      g_simple_async_result_set_from_error (res, error);
+      g_error_free (error);
+
+      return;
+    }
+  
   stream = iface->read_fn (G_FILE (object), cancellable, &error);
 
   if (stream == NULL)
@@ -3757,6 +5304,235 @@ g_file_real_replace_finish (GFile         *file,
   return NULL;
 }
 
+static void
+open_readwrite_async_thread (GSimpleAsyncResult *res,
+                            GObject            *object,
+                            GCancellable       *cancellable)
+{
+  GFileIface *iface;
+  GFileIOStream *stream;
+  GError *error = NULL;
+
+  iface = G_FILE_GET_IFACE (object);
+
+  if (iface->open_readwrite == NULL)
+    {
+      g_set_error_literal (&error, G_IO_ERROR,
+                           G_IO_ERROR_NOT_SUPPORTED,
+                           _("Operation not supported"));
+
+      g_simple_async_result_set_from_error (res, error);
+      g_error_free (error);
+
+      return;
+    }
+
+  stream = iface->open_readwrite (G_FILE (object), cancellable, &error);
+
+  if (stream == NULL)
+    {
+      g_simple_async_result_set_from_error (res, error);
+      g_error_free (error);
+    }
+  else
+    g_simple_async_result_set_op_res_gpointer (res, stream, g_object_unref);
+}
+
+static void
+g_file_real_open_readwrite_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_open_readwrite_async);
+
+  g_simple_async_result_run_in_thread (res, open_readwrite_async_thread, io_priority, cancellable);
+  g_object_unref (res);
+}
+
+static GFileIOStream *
+g_file_real_open_readwrite_finish (GFile         *file,
+                                  GAsyncResult  *res,
+                                  GError       **error)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+  gpointer op;
+
+  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_real_open_readwrite_async);
+
+  op = g_simple_async_result_get_op_res_gpointer (simple);
+  if (op)
+    return g_object_ref (op);
+
+  return NULL;
+}
+
+static void
+create_readwrite_async_thread (GSimpleAsyncResult *res,
+                              GObject            *object,
+                              GCancellable       *cancellable)
+{
+  GFileIface *iface;
+  GFileCreateFlags *data;
+  GFileIOStream *stream;
+  GError *error = NULL;
+
+  iface = G_FILE_GET_IFACE (object);
+
+  data = g_simple_async_result_get_op_res_gpointer (res);
+
+  if (iface->create_readwrite == NULL)
+    {
+      g_set_error_literal (&error, G_IO_ERROR,
+                           G_IO_ERROR_NOT_SUPPORTED,
+                           _("Operation not supported"));
+
+      g_simple_async_result_set_from_error (res, error);
+      g_error_free (error);
+
+      return;
+    }
+
+  stream = iface->create_readwrite (G_FILE (object), *data, cancellable, &error);
+
+  if (stream == NULL)
+    {
+      g_simple_async_result_set_from_error (res, error);
+      g_error_free (error);
+    }
+  else
+    g_simple_async_result_set_op_res_gpointer (res, stream, g_object_unref);
+}
+
+static void
+g_file_real_create_readwrite_async (GFile               *file,
+                                   GFileCreateFlags     flags,
+                                   int                  io_priority,
+                                   GCancellable        *cancellable,
+                                   GAsyncReadyCallback  callback,
+                                   gpointer             user_data)
+{
+  GFileCreateFlags *data;
+  GSimpleAsyncResult *res;
+
+  data = g_new0 (GFileCreateFlags, 1);
+  *data = flags;
+
+  res = g_simple_async_result_new (G_OBJECT (file), callback, user_data, g_file_real_create_readwrite_async);
+  g_simple_async_result_set_op_res_gpointer (res, data, (GDestroyNotify)g_free);
+
+  g_simple_async_result_run_in_thread (res, create_readwrite_async_thread, io_priority, cancellable);
+  g_object_unref (res);
+}
+
+static GFileIOStream *
+g_file_real_create_readwrite_finish (GFile         *file,
+                                     GAsyncResult  *res,
+                                     GError       **error)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+  gpointer op;
+
+  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_real_create_readwrite_async);
+
+  op = g_simple_async_result_get_op_res_gpointer (simple);
+  if (op)
+    return g_object_ref (op);
+
+  return NULL;
+}
+
+typedef struct {
+  GFileIOStream *stream;
+  char *etag;
+  gboolean make_backup;
+  GFileCreateFlags flags;
+} ReplaceRWAsyncData;
+
+static void
+replace_rw_async_data_free (ReplaceRWAsyncData *data)
+{
+  if (data->stream)
+    g_object_unref (data->stream);
+  g_free (data->etag);
+  g_free (data);
+}
+
+static void
+replace_readwrite_async_thread (GSimpleAsyncResult *res,
+                               GObject            *object,
+                               GCancellable       *cancellable)
+{
+  GFileIface *iface;
+  GFileIOStream *stream;
+  GError *error = NULL;
+  ReplaceRWAsyncData *data;
+
+  iface = G_FILE_GET_IFACE (object);
+
+  data = g_simple_async_result_get_op_res_gpointer (res);
+
+  stream = iface->replace_readwrite (G_FILE (object),
+                                    data->etag,
+                                    data->make_backup,
+                                    data->flags,
+                                    cancellable,
+                                    &error);
+
+  if (stream == NULL)
+    {
+      g_simple_async_result_set_from_error (res, error);
+      g_error_free (error);
+    }
+  else
+    data->stream = stream;
+}
+
+static void
+g_file_real_replace_readwrite_async (GFile               *file,
+                                    const char          *etag,
+                                    gboolean             make_backup,
+                                    GFileCreateFlags     flags,
+                                    int                  io_priority,
+                                    GCancellable        *cancellable,
+                                    GAsyncReadyCallback  callback,
+                                    gpointer             user_data)
+{
+  GSimpleAsyncResult *res;
+  ReplaceRWAsyncData *data;
+
+  data = g_new0 (ReplaceRWAsyncData, 1);
+  data->etag = g_strdup (etag);
+  data->make_backup = make_backup;
+  data->flags = flags;
+
+  res = g_simple_async_result_new (G_OBJECT (file), callback, user_data, g_file_real_replace_readwrite_async);
+  g_simple_async_result_set_op_res_gpointer (res, data, (GDestroyNotify)replace_rw_async_data_free);
+
+  g_simple_async_result_run_in_thread (res, replace_readwrite_async_thread, io_priority, cancellable);
+  g_object_unref (res);
+}
+
+static GFileIOStream *
+g_file_real_replace_readwrite_finish (GFile         *file,
+                                      GAsyncResult  *res,
+                                      GError       **error)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+  ReplaceRWAsyncData *data;
+
+  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_real_replace_readwrite_async);
+
+  data = g_simple_async_result_get_op_res_gpointer (simple);
+  if (data->stream)
+    return g_object_ref (data->stream);
+
+  return NULL;
+}
+
 typedef struct {
   char *name;
   GFile *file;
@@ -3888,28 +5664,218 @@ g_file_real_set_attributes_async (GFile               *file,
   g_object_unref (res);
 }
 
-static gboolean
-g_file_real_set_attributes_finish (GFile         *file,
-                                  GAsyncResult  *res,
-                                  GFileInfo    **info,
-                                  GError       **error)
+static gboolean
+g_file_real_set_attributes_finish (GFile         *file,
+                                  GAsyncResult  *res,
+                                  GFileInfo    **info,
+                                  GError       **error)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+  SetInfoAsyncData *data;
+  
+  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_real_set_attributes_async);
+
+  data = g_simple_async_result_get_op_res_gpointer (simple);
+
+  if (info) 
+    *info = g_object_ref (data->info);
+
+  if (error != NULL && data->error) 
+    *error = g_error_copy (data->error);
+  
+  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 *simple = G_SIMPLE_ASYNC_RESULT (res);
-  SetInfoAsyncData *data;
-  
-  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_real_set_attributes_async);
+  GSimpleAsyncResult *res;
+  CopyAsyncData *data;
 
-  data = g_simple_async_result_get_op_res_gpointer (simple);
+  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;
 
-  if (info) 
-    *info = g_object_ref (data->info);
+  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);
 
-  if (error != NULL && data->error) 
-    *error = g_error_copy (data->error);
-  
-  return data->res;
+  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                 *
  ********************************************/
@@ -3975,6 +5941,9 @@ is_valid_scheme_character (char c)
   return g_ascii_isalnum (c) || c == '+' || c == '-' || c == '.';
 }
 
+/* Following RFC 2396, valid schemes are built like:
+ *       scheme        = alpha *( alpha | digit | "+" | "-" | "." )
+ */
 static gboolean
 has_valid_scheme (const char *uri)
 {
@@ -3982,7 +5951,7 @@ has_valid_scheme (const char *uri)
   
   p = uri;
   
-  if (!is_valid_scheme_character (*p))
+  if (!g_ascii_isalpha (*p))
     return FALSE;
 
   do {
@@ -4032,9 +6001,10 @@ 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
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied, or %NULL.
  * @user_data: the data to pass to callback function
  * 
  * Starts a @mount_operation, mounting the volume that contains the file @location. 
@@ -4049,6 +6019,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,
@@ -4070,7 +6041,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);
 
 }
 
@@ -4112,6 +6083,76 @@ 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);
+  if (uri_scheme && uri_scheme[0] != '\0')
+    {
+      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_literal (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
 
 /**
@@ -4119,20 +6160,23 @@ g_file_mount_enclosing_volume_finish (GFile         *location,
  * @file: input #GFile.
  * @cancellable: optional #GCancellable object, %NULL to ignore.
  * @contents: a location to place the contents of the file.
- * @length: a location to place the length of the contents of the file.
- * @etag_out: a location to place the current entity tag for the file.
+ * @length: a location to place the length of the contents of the file,
+ *    or %NULL if the length is not needed
+ * @etag_out: a location to place the current entity tag for the file,
+ *    or %NULL if the entity tag is not needed
  * @error: a #GError, or %NULL
  *
- * Loads the content of the file into memory, returning the size of
- * the data. The data is always zero terminated, but this is not
- * included in the resultant @length.
+ * Loads the content of the file into memory. The data is always 
+ * zero-terminated, but this is not included in the resultant @length.
+ * The returned @content should be freed with g_free() when no longer
+ * needed.
  * 
  * 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: %TRUE if the @file's contents were successfully loaded.
- * %FALSE if there were errors..
+ * %FALSE if there were errors.
  **/
 gboolean
 g_file_load_contents (GFile         *file,
@@ -4424,12 +6468,17 @@ g_file_load_partial_contents_async (GFile                 *file,
  * @file: input #GFile.
  * @res: a #GAsyncResult. 
  * @contents: a location to place the contents of the file.
- * @length: a location to place the length of the contents of the file.
- * @etag_out: a location to place the current entity tag for the file.
+ * @length: a location to place the length of the contents of the file,
+ *     or %NULL if the length is not needed
+ * @etag_out: a location to place the current entity tag for the file,
+ *     or %NULL if the entity tag is not needed
  * @error: a #GError, or %NULL
  * 
  * Finishes an asynchronous partial load operation that was started
- * with g_file_load_partial_contents_async().
+ * with g_file_load_partial_contents_async(). The data is always 
+ * zero-terminated, but this is not included in the resultant @length.
+ * The returned @content should be freed with g_free() when no longer
+ * needed.
  *
  * Returns: %TRUE if the load was successful. If %FALSE and @error is 
  * present, it will be set appropriately. 
@@ -4525,13 +6574,16 @@ g_file_load_contents_async (GFile               *file,
  * @file: input #GFile.
  * @res: a #GAsyncResult. 
  * @contents: a location to place the contents of the file.
- * @length: a location to place the length of the contents of the file.
- * @etag_out: a location to place the current entity tag for the file.
+ * @length: a location to place the length of the contents of the file,
+ *     or %NULL if the length is not needed
+ * @etag_out: a location to place the current entity tag for the file,
+ *     or %NULL if the entity tag is not needed
  * @error: a #GError, or %NULL
  * 
  * Finishes an asynchronous load of the @file's contents. 
  * The contents are placed in @contents, and @length is set to the 
- * size of the @contents string. If @etag_out is present, it will be 
+ * size of the @contents string. The @content should be freed with
+ * g_free() when no longer needed. If @etag_out is present, it will be 
  * set to the new entity tag for the @file.
  * 
  * Returns: %TRUE if the load was successful. If %FALSE and @error is 
@@ -4559,11 +6611,12 @@ g_file_load_contents_finish (GFile         *file,
  * @contents: a string containing the new contents for @file.
  * @length: the length of @contents in bytes.
  * @etag: the old <link linkend="gfile-etag">entity tag</link> 
- *     for the document.
+ *     for the document, or %NULL
  * @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, or %NULL
  * @cancellable: optional #GCancellable object, %NULL to ignore.
  * @error: a #GError, or %NULL
  *
@@ -4599,6 +6652,7 @@ g_file_replace_contents (GFile             *file,
   GFileOutputStream *out;
   gsize pos, remainder;
   gssize res;
+  gboolean ret;
 
   g_return_val_if_fail (G_IS_FILE (file), FALSE);
   g_return_val_if_fail (contents != NULL, FALSE);
@@ -4624,18 +6678,20 @@ g_file_replace_contents (GFile             *file,
     {
       /* Ignore errors on close */
       g_output_stream_close (G_OUTPUT_STREAM (out), cancellable, NULL);
-      
+      g_object_unref (out);
+
       /* error is set already */
       return FALSE;
     }
   
-  if (!g_output_stream_close (G_OUTPUT_STREAM (out), cancellable, error))
-    return FALSE;
+  ret = g_output_stream_close (G_OUTPUT_STREAM (out), cancellable, error);
 
   if (new_etag)
     *new_etag = g_file_output_stream_get_etag (out);
-  
-  return TRUE;
+
+  g_object_unref (out);
+
+  return ret;
 }
 
 typedef struct {
@@ -4768,7 +6824,7 @@ replace_contents_open_callback (GObject      *obj,
  * @file: input #GFile.
  * @contents: string of contents to replace the file with.
  * @length: the length of @contents in bytes.
- * @etag: a new <link linkend="gfile-etag">entity tag</link> for the @file.
+ * @etag: a new <link linkend="gfile-etag">entity tag</link> for the @file, or %NULL
  * @make_backup: %TRUE if a backup should be created.
  * @flags: a set of #GFileCreateFlags.
  * @cancellable: optional #GCancellable object, %NULL to ignore.
@@ -4832,7 +6888,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, or %NULL
  * @error: a #GError, or %NULL 
  * 
  * Finishes an asynchronous replace of the given @file. See
@@ -4879,5 +6936,296 @@ g_file_replace_contents_finish (GFile         *file,
   return TRUE;
 }
 
+/**
+ * g_file_start_mountable:
+ * @file: input #GFile.
+ * @flags: flags affecting the operation
+ * @start_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.
+ * @user_data: the data to pass to callback function
+ *
+ * Starts a file of type G_FILE_TYPE_MOUNTABLE.
+ * Using @start_operation, you can request callbacks when, for instance,
+ * passwords are needed during authentication.
+ *
+ * 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.
+ *
+ * When the operation is finished, @callback will be called. You can then call
+ * g_file_mount_mountable_finish() to get the result of the operation.
+ *
+ * Since: 2.22
+ */
+void
+g_file_start_mountable (GFile                      *file,
+                        GDriveStartFlags            flags,
+                        GMountOperation            *start_operation,
+                        GCancellable               *cancellable,
+                        GAsyncReadyCallback         callback,
+                        gpointer                    user_data)
+{
+  GFileIface *iface;
+
+  g_return_if_fail (G_IS_FILE (file));
+
+  iface = G_FILE_GET_IFACE (file);
+
+  if (iface->start_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->start_mountable) (file,
+                             flags,
+                             start_operation,
+                             cancellable,
+                             callback,
+                             user_data);
+}
+
+/**
+ * g_file_start_mountable_finish:
+ * @file: input #GFile.
+ * @result: a #GAsyncResult.
+ * @error: a #GError, or %NULL
+ *
+ * Finishes a start operation. See g_file_start_mountable() for details.
+ *
+ * Finish an asynchronous start operation that was started
+ * with g_file_start_mountable().
+ *
+ * Returns: %TRUE if the operation finished successfully. %FALSE
+ * otherwise.
+ *
+ * Since: 2.22
+ */
+gboolean
+g_file_start_mountable_finish (GFile                      *file,
+                               GAsyncResult               *result,
+                               GError                    **error)
+{
+  GFileIface *iface;
+
+  g_return_val_if_fail (G_IS_FILE (file), FALSE);
+  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+  if (G_IS_SIMPLE_ASYNC_RESULT (result))
+    {
+      GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
+      if (g_simple_async_result_propagate_error (simple, error))
+       return FALSE;
+    }
+
+  iface = G_FILE_GET_IFACE (file);
+  return (* iface->start_mountable_finish) (file, result, error);
+}
+
+/**
+ * g_file_stop_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.
+ * @user_data: the data to pass to callback function
+ *
+ * Stops a file of type G_FILE_TYPE_MOUNTABLE.
+ *
+ * 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.
+ *
+ * When the operation is finished, @callback will be called. You can then call
+ * g_file_stop_mountable_finish() to get the result of the operation.
+ *
+ * Since: 2.22
+ */
+void
+g_file_stop_mountable (GFile                      *file,
+                       GMountUnmountFlags          flags,
+                       GMountOperation            *mount_operation,
+                       GCancellable               *cancellable,
+                       GAsyncReadyCallback         callback,
+                       gpointer                    user_data)
+{
+  GFileIface *iface;
+
+  g_return_if_fail (G_IS_FILE (file));
+
+  iface = G_FILE_GET_IFACE (file);
+
+  if (iface->stop_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->stop_mountable) (file,
+                             flags,
+                             mount_operation,
+                             cancellable,
+                             callback,
+                             user_data);
+}
+
+/**
+ * g_file_stop_mountable_finish:
+ * @file: input #GFile.
+ * @result: a #GAsyncResult.
+ * @error: a #GError, or %NULL
+ *
+ * Finishes an stop operation, see g_file_stop_mountable() for details.
+ *
+ * Finish an asynchronous stop operation that was started
+ * with g_file_stop_mountable().
+ *
+ * Returns: %TRUE if the operation finished successfully. %FALSE
+ * otherwise.
+ *
+ * Since: 2.22
+ */
+gboolean
+g_file_stop_mountable_finish (GFile                      *file,
+                              GAsyncResult               *result,
+                              GError                    **error)
+{
+  GFileIface *iface;
+
+  g_return_val_if_fail (G_IS_FILE (file), FALSE);
+  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+  if (G_IS_SIMPLE_ASYNC_RESULT (result))
+    {
+      GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
+      if (g_simple_async_result_propagate_error (simple, error))
+       return FALSE;
+    }
+
+  iface = G_FILE_GET_IFACE (file);
+  return (* iface->stop_mountable_finish) (file, result, error);
+}
+
+/**
+ * g_file_poll_mountable:
+ * @file: input #GFile.
+ * @cancellable: optional #GCancellable object, %NULL to ignore.
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied, or %NULL.
+ * @user_data: the data to pass to callback function
+ *
+ * Polls a file of type G_FILE_TYPE_MOUNTABLE.
+ *
+ * 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.
+ *
+ * When the operation is finished, @callback will be called. You can then call
+ * g_file_mount_mountable_finish() to get the result of the operation.
+ *
+ * Since: 2.22
+ */
+void
+g_file_poll_mountable (GFile                      *file,
+                       GCancellable               *cancellable,
+                       GAsyncReadyCallback         callback,
+                       gpointer                    user_data)
+{
+  GFileIface *iface;
+
+  g_return_if_fail (G_IS_FILE (file));
+
+  iface = G_FILE_GET_IFACE (file);
+
+  if (iface->poll_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->poll_mountable) (file,
+                             cancellable,
+                             callback,
+                             user_data);
+}
+
+/**
+ * g_file_poll_mountable_finish:
+ * @file: input #GFile.
+ * @result: a #GAsyncResult.
+ * @error: a #GError, or %NULL
+ *
+ * Finishes a poll operation. See g_file_poll_mountable() for details.
+ *
+ * Finish an asynchronous poll operation that was polled
+ * with g_file_poll_mountable().
+ *
+ * Returns: %TRUE if the operation finished successfully. %FALSE
+ * otherwise.
+ *
+ * Since: 2.22
+ */
+gboolean
+g_file_poll_mountable_finish (GFile                      *file,
+                              GAsyncResult               *result,
+                              GError                    **error)
+{
+  GFileIface *iface;
+
+  g_return_val_if_fail (G_IS_FILE (file), FALSE);
+  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+  if (G_IS_SIMPLE_ASYNC_RESULT (result))
+    {
+      GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
+      if (g_simple_async_result_propagate_error (simple, error))
+       return FALSE;
+    }
+
+  iface = G_FILE_GET_IFACE (file);
+  return (* iface->poll_mountable_finish) (file, result, error);
+}
+
+/**
+ * g_file_supports_thread_contexts:
+ * @file: a #GFile.
+ *
+ * Checks if @file supports <link
+ * linkend="g-main-context-push-thread-default-context">thread-default
+ * contexts</link>. If this returns %FALSE, you cannot perform
+ * asynchronous operations on @file in a thread that has a
+ * thread-default context.
+ *
+ * Returns: Whether or not @file supports thread-default contexts.
+ *
+ * Since: 2.22
+ */
+gboolean
+g_file_supports_thread_contexts (GFile *file)
+{
+ GFileIface *iface;
+
+ g_return_val_if_fail (G_IS_FILE (file), FALSE);
+
+ iface = G_FILE_GET_IFACE (file);
+ return iface->supports_thread_contexts;
+}
+
 #define __G_FILE_C__
 #include "gioaliasdef.c"