Add support for abstract unix socket addresses
[platform/upstream/glib.git] / gio / gfile.c
index 4194f6c..493ae6b 100644 (file)
 #include "gsimpleasyncresult.h"
 #include "gfileattribute-priv.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"
@@ -186,6 +192,34 @@ static void               g_file_real_replace_async               (GFile
 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,
@@ -235,11 +269,11 @@ static gboolean           g_file_real_copy_finish                 (GFile
 GType
 g_file_get_type (void)
 {
-  static GType file_type = 0;
+  static volatile gsize g_define_type_id__volatile = 0;
 
-  if (! file_type)
+  if (g_once_init_enter (&g_define_type_id__volatile))
     {
-      static const GTypeInfo file_info =
+      const GTypeInfo file_info =
       {
         sizeof (GFileIface), /* class_size */
        g_file_base_init,   /* base_init */
@@ -251,15 +285,16 @@ g_file_get_type (void)
        0,              /* n_preallocs */
        NULL
       };
-
-      file_type =
+      GType g_define_type_id =
        g_type_register_static (G_TYPE_INTERFACE, I_("GFile"),
                                &file_info, 0);
 
-      g_type_interface_add_prerequisite (file_type, G_TYPE_OBJECT);
+      g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_OBJECT);
+
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
     }
 
-  return file_type;
+  return g_define_type_id__volatile;
 }
 
 static void
@@ -286,6 +321,12 @@ 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;
@@ -514,7 +555,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)
@@ -598,6 +639,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)
@@ -625,6 +667,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,
@@ -652,6 +695,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,
@@ -673,14 +717,18 @@ g_file_get_child_for_display_name (GFile      *file,
  * @file: input #GFile.
  * @prefix: input #GFile.
  * 
- * Checks whether @file has the prefix specified by @prefix. In other word, if the
- * names of inital elements of @file<!-- -->s pathname match @prefix.
+ * 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.
  * 
- * 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.
+ * 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.
+ * Returns:  %TRUE if the @files's parent, grandparent, etc is @prefix. 
+ *     %FALSE otherwise.
  **/
 gboolean
 g_file_has_prefix (GFile *file,
@@ -711,8 +759,8 @@ g_file_has_prefix (GFile *file,
  * This call does no blocking i/o.
  * 
  * Returns: string with the relative path from @descendant 
- *     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.
+ *     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,
@@ -742,6 +790,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,
@@ -786,6 +835,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,
@@ -870,6 +920,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,
@@ -1015,6 +1066,7 @@ g_file_query_file_type (GFile *file,
  * 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,
@@ -1097,6 +1149,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,
@@ -1149,6 +1202,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,
@@ -1229,6 +1283,7 @@ g_file_query_filesystem_info_async (GFile               *file,
  * 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,
@@ -1268,6 +1323,7 @@ g_file_query_filesystem_info_finish (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,
@@ -1294,6 +1350,7 @@ g_file_find_enclosing_mount (GFile         *file,
 
   return (* iface->find_enclosing_mount) (file, cancellable, error);
 }
+
 /**
  * g_file_find_enclosing_mount_async:
  * @file: a #GFile
@@ -1340,6 +1397,7 @@ g_file_find_enclosing_mount_async (GFile              *file,
  * 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,
@@ -1381,6 +1439,7 @@ g_file_find_enclosing_mount_finish (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,
@@ -1432,7 +1491,8 @@ g_file_read (GFile         *file,
  * returned. Other errors are possible too, and depend on what kind of
  * filesystem the file is on.
  * 
- * Returns: a #GFileOutputStream, or %NULL on error
+ * Returns: a #GFileOutputStream, or %NULL on error.
+ *     Free the returned object with g_object_unref().
  **/
 GFileOutputStream *
 g_file_append_to (GFile             *file,
@@ -1488,7 +1548,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,
@@ -1569,6 +1630,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,
@@ -1604,6 +1666,173 @@ g_file_replace (GFile             *file,
 }
 
 /**
+ * g_file_open_readwrite:
+ * @file: #GFile to open
+ * @cancellable: a #GCancellable
+ * @error: a #GError, or %NULL
+ *
+ * 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.
+ *
+ * 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 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
+ **/
+GFileIOStream *
+g_file_open_readwrite (GFile                      *file,
+                       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->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_create_readwrite:
+ * @file: input #GFile.
+ * @flags: a set of #GFileCreateFlags.
+ * @cancellable: optional #GCancellable object, %NULL to ignore.
+ * @error: a #GError, or %NULL
+ *
+ * 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 to 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);
+
+  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: input #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: 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> 
@@ -1649,6 +1878,7 @@ g_file_read_async (GFile               *file,
  * 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,
@@ -1720,6 +1950,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,
@@ -1792,6 +2023,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,
@@ -1871,6 +2103,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,
@@ -1893,6 +2126,242 @@ g_file_replace_finish (GFile         *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,
@@ -2026,8 +2495,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;
@@ -2036,7 +2509,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;
@@ -2049,7 +2523,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;
@@ -2065,7 +2539,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;
@@ -2093,9 +2567,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.
  **/
@@ -2112,9 +2587,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);
@@ -2123,7 +2600,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. 
@@ -2139,7 +2616,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);
@@ -2267,19 +2745,22 @@ file_copy_fallback (GFile                  *source,
   GFileInfo *info;
   const char *target;
 
+  /* 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)
+  if ((flags & G_FILE_COPY_NOFOLLOW_SYMLINKS) &&
+      g_file_info_get_file_type (info) == G_FILE_TYPE_SYMBOLIC_LINK)
     {
-      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;
-
-      if (g_file_info_get_file_type (info) == G_FILE_TYPE_SYMBOLIC_LINK &&
-         (target = g_file_info_get_symlink_target (info)) != NULL)
+      target = g_file_info_get_symlink_target (info);
+      if (target)
        {
          if (!copy_symlink (destination, flags, cancellable, target, error))
            {
@@ -2290,10 +2771,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;
@@ -2303,7 +2797,7 @@ file_copy_fallback (GFile                  *source,
       out = (GOutputStream *)g_file_replace (destination,
                                             NULL,
                                             flags & G_FILE_COPY_BACKUP,
-                                             0,
+                                             G_FILE_CREATE_REPLACE_DESTINATION,
                                             cancellable, error);
     }
   else
@@ -2416,6 +2910,8 @@ g_file_copy (GFile                  *source,
          g_propagate_error (error, my_error);
              return FALSE;
        }
+      else
+       g_clear_error (&my_error);
     }
 
   /* If the types are different, and the destination method failed
@@ -2440,6 +2936,8 @@ g_file_copy (GFile                  *source,
              g_propagate_error (error, my_error);
              return FALSE;
            }
+         else
+           g_clear_error (&my_error);
        }
     }
   
@@ -2674,6 +3172,9 @@ g_file_move (GFile                  *source,
  * @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
@@ -2716,6 +3217,9 @@ g_file_make_directory (GFile         *file,
  * '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. 
@@ -2939,7 +3443,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,
@@ -2981,7 +3487,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
@@ -3019,6 +3525,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,
@@ -3617,6 +4124,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,
@@ -3817,8 +4325,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,
@@ -3860,7 +4368,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,
@@ -3890,6 +4399,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    *
  ********************************************/
@@ -4133,6 +4673,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)
@@ -4390,6 +4942,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;
@@ -5014,20 +5795,23 @@ g_file_query_default_handler (GFile                  *file,
  * @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,
@@ -5319,12 +6103,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. 
@@ -5420,13 +6209,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 
@@ -5454,12 +6246,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. This should be freed with g_free() when no longer 
- *      needed.
+ *      needed, or %NULL
  * @cancellable: optional #GCancellable object, %NULL to ignore.
  * @error: a #GError, or %NULL
  *
@@ -5667,7 +6459,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.
@@ -5732,7 +6524,7 @@ g_file_replace_contents_async  (GFile               *file,
  * @res: a #GAsyncResult. 
  * @new_etag: a location of a new <link linkend="gfile-etag">entity tag</link> 
  *     for the document. This should be freed with g_free() when it is no 
- *     longer needed.
+ *     longer needed, or %NULL
  * @error: a #GError, or %NULL 
  * 
  * Finishes an asynchronous replace of the given @file. See