Commit message: gfile: Limit access to files when copying

file_copy_fallback creates new files with default permissions and
set the correct permissions after the operation is finished. This
might cause that the files can be accessible by more users during
the operation than expected. Use G_FILE_CREATE_PRIVATE for the new
files to limit access to those files.
CVE: CVE-2019-12450
CWE: CWE-362
Vulnerability description: file_copy_fallback in gio/gfile.c in GNOME GLib 2.15.0 through 2.61.1 does not properly restrict file permissions while a copy operation is in progress. Instead, default permissions are used.

Project: glib
File: gfile.c

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);
}

Project: glib
File: gfile.c

create_async_thread (GTask         *task,
                     gpointer       source_object,
                     gpointer       task_data,
                     GCancellable  *cancellable)
{
  GFileCreateFlags *data = task_data;
  GFileOutputStream *stream;
  GError *error = NULL;

  stream = g_file_create (G_FILE (source_object), *data, cancellable, &error);
  if (stream)
    g_task_return_pointer (task, stream, g_object_unref);
  else
    g_task_return_error (task, error);
}

Project: glib
File: gfile.c

enumerate_children_async_thread (GTask         *task,
                                 gpointer       object,
                                 gpointer       task_data,
                                 GCancellable  *cancellable)
{
  QueryInfoAsyncData *data = task_data;
  GFileEnumerator *enumerator;
  GError *error = NULL;

  enumerator = g_file_enumerate_children (G_FILE (object), data->attributes, data->flags, cancellable, &error);
  if (error)
    g_task_return_error (task, error);
  else
    g_task_return_pointer (task, enumerator, g_object_unref);
}

Project: glib
File: gfile.c

g_file_monitor_file (GFile              *file,
                     GFileMonitorFlags   flags,
                     GCancellable       *cancellable,
                     GError            **error)
{
  GFileIface *iface;
  GFileMonitor *monitor;

  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);

  monitor = NULL;

  if (iface->monitor_file)
    monitor = (* iface->monitor_file) (file, flags, cancellable, NULL);

  /* Fallback to polling */
  if (monitor == NULL)
    monitor = _g_poll_file_monitor_new (file);

  return monitor;
}

Project: glib
File: gfile.c

g_file_get_relative_path (GFile *parent,
                          GFile *descendant)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (parent), NULL);
  g_return_val_if_fail (G_IS_FILE (descendant), NULL);

  if (G_TYPE_FROM_INSTANCE (parent) != G_TYPE_FROM_INSTANCE (descendant))
    return NULL;

  iface = G_FILE_GET_IFACE (parent);

  return (* iface->get_relative_path) (parent, descendant);
}

Project: glib
File: gfile.c

g_file_replace_contents_bytes_async  (GFile               *file,
                                      GBytes              *contents,
                                      const char          *etag,
                                      gboolean             make_backup,
                                      GFileCreateFlags     flags,
                                      GCancellable        *cancellable,
                                      GAsyncReadyCallback  callback,
                                      gpointer             user_data)
{
  ReplaceContentsData *data;

  g_return_if_fail (G_IS_FILE (file));
  g_return_if_fail (contents != NULL);

  data = g_new0 (ReplaceContentsData, 1);

  data->content = g_bytes_ref (contents);

  data->task = g_task_new (file, cancellable, callback, user_data);
  g_task_set_source_tag (data->task, g_file_replace_contents_bytes_async);
  g_task_set_task_data (data->task, data, (GDestroyNotify)replace_contents_data_free);

  g_file_replace_async (file,
                        etag,
                        make_backup,
                        flags,
                        0,
                        g_task_get_cancellable (data->task),
                        replace_contents_open_callback,
                        data);
}

Project: glib
File: gfile.c

g_file_query_default_handler_finish (GFile        *file,
                                     GAsyncResult *result,
                                     GError      **error)
{
  g_return_val_if_fail (G_IS_FILE (file), NULL);
  g_return_val_if_fail (g_task_is_valid (result, file), NULL);

  return g_task_propagate_pointer (G_TASK (result), error);
}

Project: glib
File: gfile.c

g_file_load_bytes_cb (GObject      *object,
                      GAsyncResult *result,
                      gpointer      user_data)
{
  GFile *file = G_FILE (object);
  GTask *task = user_data;
  GError *error = NULL;
  gchar *etag = NULL;
  gchar *contents = NULL;
  gsize len = 0;

  g_file_load_contents_finish (file, result, &contents, &len, &etag, &error);
  g_task_set_task_data (task, g_steal_pointer (&etag), g_free);

  if (error != NULL)
    g_task_return_error (task, g_steal_pointer (&error));
  else
    g_task_return_pointer (task,
                           g_bytes_new_take (g_steal_pointer (&contents), len),
                           (GDestroyNotify)g_bytes_unref);

  g_object_unref (task);
}

Project: glib
File: gfile.c

set_info_async_thread (GTask        *task,
                       gpointer      object,
                       gpointer      task_data,
                       GCancellable *cancellable)
{
  SetInfoAsyncData *data = task_data;

  data->error = NULL;
  data->res = g_file_set_attributes_from_info (G_FILE (object),
                                               data->info,
                                               data->flags,
                                               cancellable,
                                               &data->error);
}

Project: glib
File: gfile.c

g_file_set_display_name_async (GFile               *file,
                               const gchar         *display_name,
                               gint                 io_priority,
                               GCancellable        *cancellable,
                               GAsyncReadyCallback  callback,
                               gpointer             user_data)
{
  GFileIface *iface;

  g_return_if_fail (G_IS_FILE (file));
  g_return_if_fail (display_name != NULL);

  iface = G_FILE_GET_IFACE (file);
  (* iface->set_display_name_async) (file,
                                     display_name,
                                     io_priority,
                                     cancellable,
                                     callback,
                                     user_data);
}

Project: glib
File: gfile.c

query_default_handler_query_info_cb (GObject      *object,
                                     GAsyncResult *result,
                                     gpointer      user_data)
{
  GFile *file = G_FILE (object);
  GTask *task = G_TASK (user_data);
  GError *error = NULL;
  GFileInfo *info;
  const char *content_type;
  GAppInfo *appinfo = NULL;

  info = g_file_query_info_finish (file, result, &error);
  if (info == NULL)
    {
      g_task_return_error (task, g_steal_pointer (&error));
      g_object_unref (task);
      return;
    }

  content_type = g_file_info_get_content_type (info);
  if (content_type)
    {
      char *path;

      /* Don't use is_native(), as we want to support fuse paths if available */
      path = g_file_get_path (file);

      /* FIXME: The following still uses blocking calls. */
      appinfo = g_app_info_get_default_for_type (content_type,
                                                 path == NULL);
      g_free (path);
    }

  g_object_unref (info);

  if (appinfo != NULL)
    g_task_return_pointer (task, g_steal_pointer (&appinfo), g_object_unref);
  else
    g_task_return_new_error (task,
                             G_IO_ERROR,
                             G_IO_ERROR_NOT_SUPPORTED,
                             _("No application is registered as handling this file"));
  g_object_unref (task);
}

Project: glib
File: gfile.c

g_file_replace_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_async_result_legacy_propagate_error (res, error))
    return NULL;

  iface = G_FILE_GET_IFACE (file);
  return (* iface->replace_finish) (file, res, error);
}

Project: glib
File: gfile.c

g_file_mount_mountable (GFile               *file,
                        GMountMountFlags     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->mount_mountable == NULL)
    {
      g_task_report_new_error (file, callback, user_data,
                               g_file_mount_mountable,
                               G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
                               _("Operation not supported"));
      return;
    }

  (* iface->mount_mountable) (file,
                              flags,
                              mount_operation,
                              cancellable,
                              callback,
                              user_data);
}

Project: glib
File: gfile.c

g_file_mount_enclosing_volume (GFile               *location,
                               GMountMountFlags     flags,
                               GMountOperation     *mount_operation,
                               GCancellable        *cancellable,
                               GAsyncReadyCallback  callback,
                               gpointer             user_data)
{
  GFileIface *iface;

  g_return_if_fail (G_IS_FILE (location));

  iface = G_FILE_GET_IFACE (location);

  if (iface->mount_enclosing_volume == NULL)
    {
      g_task_report_new_error (location, callback, user_data,
                               g_file_mount_enclosing_volume,
                               G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
                               _("volume doesn’t implement mount"));
      return;
    }

  (* iface->mount_enclosing_volume) (location, flags, mount_operation, cancellable, callback, user_data);

}

Project: glib
File: gfile.c

g_file_set_attribute_uint32 (GFile                *file,
                             const gchar          *attribute,
                             guint32               value,
                             GFileQueryInfoFlags   flags,
                             GCancellable         *cancellable,
                             GError              **error)
{
  return g_file_set_attribute (file, attribute,
                               G_FILE_ATTRIBUTE_TYPE_UINT32, &value,
                               flags, cancellable, error);
}

Project: glib
File: gfile.c

g_file_default_init (GFileIface *iface)
{
  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;
  iface->read_finish = g_file_real_read_finish;
  iface->append_to_async = g_file_real_append_to_async;
  iface->append_to_finish = g_file_real_append_to_finish;
  iface->create_async = g_file_real_create_async;
  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->delete_file_async = g_file_real_delete_async;
  iface->delete_file_finish = g_file_real_delete_finish;
  iface->trash_async = g_file_real_trash_async;
  iface->trash_finish = g_file_real_trash_finish;
  iface->make_directory_async = g_file_real_make_directory_async;
  iface->make_directory_finish = g_file_real_make_directory_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;
  iface->copy_async = g_file_real_copy_async;
  iface->copy_finish = g_file_real_copy_finish;
  iface->measure_disk_usage = g_file_real_measure_disk_usage;
  iface->measure_disk_usage_async = g_file_real_measure_disk_usage_async;
  iface->measure_disk_usage_finish = g_file_real_measure_disk_usage_finish;
}

Project: glib
File: gfile.c

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);
}

Project: glib
File: gfile.c

g_file_delete (GFile         *file,
               GCancellable  *cancellable,
               GError       **error)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (file), FALSE);

  if (g_cancellable_set_error_if_cancelled (cancellable, error))
    return FALSE;

  iface = G_FILE_GET_IFACE (file);

  if (iface->delete_file == NULL)
    {
      g_set_error_literal (error, G_IO_ERROR,
                           G_IO_ERROR_NOT_SUPPORTED,
                           _("Operation not supported"));
      return FALSE;
    }

  return (* iface->delete_file) (file, cancellable, error);
}

Project: glib
File: gfile.c

g_file_new_for_path (const char *path)
{
  g_return_val_if_fail (path != NULL, NULL);

  return g_vfs_get_file_for_path (g_vfs_get_default (), path);
}

Project: glib
File: gfile.c

load_contents_read_callback (GObject      *obj,
                             GAsyncResult *read_res,
                             gpointer      user_data)
{
  GInputStream *stream = G_INPUT_STREAM (obj);
  LoadContentsData *data = user_data;
  GError *error = NULL;
  gssize read_size;

  read_size = g_input_stream_read_finish (stream, read_res, &error);

  if (read_size < 0)
    {
      g_task_return_error (data->task, error);
      g_object_unref (data->task);

      /* Close the file ignoring any error */
      g_input_stream_close_async (stream, 0, NULL, NULL, NULL);
      g_object_unref (stream);
    }
  else if (read_size == 0)
    {
      g_file_input_stream_query_info_async (G_FILE_INPUT_STREAM (stream),
                                            G_FILE_ATTRIBUTE_ETAG_VALUE,
                                            0,
                                            g_task_get_cancellable (data->task),
                                            load_contents_fstat_callback,
                                            data);
    }
  else if (read_size > 0)
    {
      data->pos += read_size;

      g_byte_array_set_size (data->content,
                             data->pos + GET_CONTENT_BLOCK_SIZE);


      if (data->read_more_callback &&
          !data->read_more_callback ((char *)data->content->data, data->pos,
                                     g_async_result_get_user_data (G_ASYNC_RESULT (data->task))))
        g_file_input_stream_query_info_async (G_FILE_INPUT_STREAM (stream),
                                              G_FILE_ATTRIBUTE_ETAG_VALUE,
                                              0,
                                              g_task_get_cancellable (data->task),
                                              load_contents_fstat_callback,
                                              data);
      else
        g_input_stream_read_async (stream,
                                   data->content->data + data->pos,
                                   GET_CONTENT_BLOCK_SIZE,
                                   0,
                                   g_task_get_cancellable (data->task),
                                   load_contents_read_callback,
                                   data);
    }
}

Project: glib
File: gfile.c

g_file_real_measure_disk_usage_async (GFile                        *file,
                                      GFileMeasureFlags             flags,
                                      gint                          io_priority,
                                      GCancellable                 *cancellable,
                                      GFileMeasureProgressCallback  progress_callback,
                                      gpointer                      progress_data,
                                      GAsyncReadyCallback           callback,
                                      gpointer                      user_data)
{
  MeasureTaskData data;
  GTask *task;

  data.flags = flags;
  data.progress_callback = progress_callback;
  data.progress_data = progress_data;

  task = g_task_new (file, cancellable, callback, user_data);
  g_task_set_source_tag (task, g_file_real_measure_disk_usage_async);
  g_task_set_task_data (task, g_memdup (&data, sizeof data), g_free);
  g_task_set_priority (task, io_priority);

  g_task_run_in_thread (task, measure_disk_usage_thread);
  g_object_unref (task);
}

Project: glib
File: gfile.c

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_async_result_legacy_propagate_error (res, error))
    return NULL;

  iface = G_FILE_GET_IFACE (file);
  return (* iface->read_finish) (file, res, error);
}

Project: glib
File: gfile.c

g_file_trash (GFile         *file,
              GCancellable  *cancellable,
              GError       **error)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (file), FALSE);

  if (g_cancellable_set_error_if_cancelled (cancellable, error))
    return FALSE;

  iface = G_FILE_GET_IFACE (file);

  if (iface->trash == NULL)
    {
      g_set_error_literal (error,
                           G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
                           _("Trash not supported"));
      return FALSE;
    }

  return (* iface->trash) (file, cancellable, error);
}

Project: glib
File: gfile.c

replace_readwrite_async_thread (GTask        *task,
                                gpointer      object,
                                gpointer      task_data,
                                GCancellable *cancellable)
{
  GFileIOStream *stream;
  GError *error = NULL;
  ReplaceRWAsyncData *data = task_data;

  stream = g_file_replace_readwrite (G_FILE (object),
                                     data->etag,
                                     data->make_backup,
                                     data->flags,
                                     cancellable,
                                     &error);

  if (stream == NULL)
    g_task_return_error (task, error);
  else
    g_task_return_pointer (task, stream, g_object_unref);
}

Project: glib
File: gfile.c

g_file_query_filesystem_info (GFile         *file,
                              const char    *attributes,
                              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->query_filesystem_info == NULL)
    {
      g_set_error_literal (error, G_IO_ERROR,
                           G_IO_ERROR_NOT_SUPPORTED,
                           _("Operation not supported"));
      return NULL;
    }

  return (* iface->query_filesystem_info) (file, attributes, cancellable, error);
}

Project: glib
File: gfile.c

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_async_result_legacy_propagate_error (result, error))
    return FALSE;
  else if (g_async_result_is_tagged (result, g_file_eject_mountable_with_operation))
    return g_task_propagate_boolean (G_TASK (result), error);

  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);
}

Project: glib
File: gfile.c

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_task_report_new_error (file, callback, user_data,
                               g_file_start_mountable,
                               G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
                               _("Operation not supported"));
      return;
    }

  (* iface->start_mountable) (file,
                              flags,
                              start_operation,
                              cancellable,
                              callback,
                              user_data);
}

Project: glib
File: gfile.c

g_file_set_attribute (GFile                *file,
                      const gchar          *attribute,
                      GFileAttributeType    type,
                      gpointer              value_p,
                      GFileQueryInfoFlags   flags,
                      GCancellable         *cancellable,
                      GError              **error)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (file), FALSE);
  g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);

  if (g_cancellable_set_error_if_cancelled (cancellable, error))
    return FALSE;

  iface = G_FILE_GET_IFACE (file);

  if (iface->set_attribute == NULL)
    {
      g_set_error_literal (error, G_IO_ERROR,
                           G_IO_ERROR_NOT_SUPPORTED,
                           _("Operation not supported"));
      return FALSE;
    }

  return (* iface->set_attribute) (file, attribute, type, value_p, flags, cancellable, error);
}

Project: glib
File: gfile.c

g_file_set_display_name_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_async_result_legacy_propagate_error (res, error))
    return NULL;

  iface = G_FILE_GET_IFACE (file);
  return (* iface->set_display_name_finish) (file, res, error);
}

Project: glib
File: gfile.c

should_copy (GFileAttributeInfo *info,
             gboolean            copy_all_attributes,
             gboolean            skip_perms)
{
  if (skip_perms && strcmp(info->name, "unix::mode") == 0)
        return FALSE;

  if (copy_all_attributes)
    return info->flags & G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED;
  return info->flags & G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE;
}

Project: glib
File: gfile.c

g_file_real_copy_finish (GFile        *file,
                         GAsyncResult *res,
                         GError      **error)
{
  g_return_val_if_fail (g_task_is_valid (res, file), FALSE);

  return g_task_propagate_boolean (G_TASK (res), error);
}

Project: glib
File: gfile.c

g_file_set_attribute_string (GFile                *file,
                             const char           *attribute,
                             const char           *value,
                             GFileQueryInfoFlags   flags,
                             GCancellable         *cancellable,
                             GError              **error)
{
  return g_file_set_attribute (file, attribute,
                               G_FILE_ATTRIBUTE_TYPE_STRING, (gpointer)value,
                               flags, cancellable, error);
}

Project: glib
File: gfile.c

g_file_dup (GFile *file)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (file), NULL);

  iface = G_FILE_GET_IFACE (file);

  return (* iface->dup) (file);
}

Project: glib
File: gfile.c

g_file_unmount_mountable (GFile               *file,
                          GMountUnmountFlags   flags,
                          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)
    {
      g_task_report_new_error (file, callback, user_data,
                               g_file_unmount_mountable_with_operation,
                               G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
                               _("Operation not supported"));
      return;
    }

  (* iface->unmount_mountable) (file,
                                flags,
                                cancellable,
                                callback,
                                user_data);
}

Project: glib
File: gfile.c

g_file_real_replace_readwrite_finish (GFile         *file,
                                      GAsyncResult  *res,
                                      GError       **error)
{
  g_return_val_if_fail (g_task_is_valid (res, file), NULL);

  return g_task_propagate_pointer (G_TASK (res), error);
}

Project: glib
File: gfile.c

g_file_replace_contents_async  (GFile               *file,
                                const char          *contents,
                                gsize                length,
                                const char          *etag,
                                gboolean             make_backup,
                                GFileCreateFlags     flags,
                                GCancellable        *cancellable,
                                GAsyncReadyCallback  callback,
                                gpointer             user_data)
{
  GBytes *bytes;

  bytes = g_bytes_new_static (contents, length);
  g_file_replace_contents_bytes_async (file, bytes, etag, make_backup, flags,
      cancellable, callback, user_data);
  g_bytes_unref (bytes);
}

Project: glib
File: gfile.c

g_file_real_append_to_finish (GFile         *file,
                              GAsyncResult  *res,
                              GError       **error)
{
  g_return_val_if_fail (g_task_is_valid (res, file), NULL);

  return g_task_propagate_pointer (G_TASK (res), error);
}

Project: glib
File: gfile.c

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);
}

Project: glib
File: gfile.c

load_contents_fstat_callback (GObject      *obj,
                              GAsyncResult *stat_res,
                              gpointer      user_data)
{
  GInputStream *stream = G_INPUT_STREAM (obj);
  LoadContentsData *data = user_data;
  GFileInfo *info;

  info = g_file_input_stream_query_info_finish (G_FILE_INPUT_STREAM (stream),
                                                stat_res, NULL);
  if (info)
    {
      data->etag = g_strdup (g_file_info_get_etag (info));
      g_object_unref (info);
    }

  g_input_stream_close_async (stream, 0,
                              g_task_get_cancellable (data->task),
                              load_contents_close_callback, data);
}

Project: glib
File: gfile.c

g_file_real_set_display_name_finish (GFile         *file,
                                     GAsyncResult  *res,
                                     GError       **error)
{
  g_return_val_if_fail (g_task_is_valid (res, file), NULL);

  return g_task_propagate_pointer (G_TASK (res), error);
}

Project: glib
File: gfile.c

g_file_mount_enclosing_volume_finish (GFile         *location,
                                      GAsyncResult  *result,
                                      GError       **error)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (location), FALSE);
  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);

  if (g_async_result_legacy_propagate_error (result, error))
    return FALSE;
  else if (g_async_result_is_tagged (result, g_file_mount_enclosing_volume))
    return g_task_propagate_boolean (G_TASK (result), error);

  iface = G_FILE_GET_IFACE (location);

  return (* iface->mount_enclosing_volume_finish) (location, result, error);
}

Project: glib
File: gfile.c

g_file_enumerate_children (GFile                *file,
                           const char           *attributes,
                           GFileQueryInfoFlags   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->enumerate_children == NULL)
    {
      g_set_error_literal (error, G_IO_ERROR,
                           G_IO_ERROR_NOT_SUPPORTED,
                           _("Operation not supported"));
      return NULL;
    }

  return (* iface->enumerate_children) (file, attributes, flags,
                                        cancellable, error);
}

Project: glib
File: gfile.c

g_file_real_append_to_async (GFile               *file,
                             GFileCreateFlags     flags,
                             int                  io_priority,
                             GCancellable        *cancellable,
                             GAsyncReadyCallback  callback,
                             gpointer             user_data)
{
  GFileCreateFlags *data;
  GTask *task;

  data = g_new0 (GFileCreateFlags, 1);
  *data = flags;

  task = g_task_new (file, cancellable, callback, user_data);
  g_task_set_source_tag (task, g_file_real_append_to_async);
  g_task_set_task_data (task, data, g_free);
  g_task_set_priority (task, io_priority);

  g_task_run_in_thread (task, append_to_async_thread);
  g_object_unref (task);
}

Project: glib
File: gfile.c

replace_contents_write_callback (GObject      *obj,
                                 GAsyncResult *read_res,
                                 gpointer      user_data)
{
  GOutputStream *stream = G_OUTPUT_STREAM (obj);
  ReplaceContentsData *data = user_data;
  GError *error = NULL;
  gssize write_size;

  write_size = g_output_stream_write_finish (stream, read_res, &error);

  if (write_size <= 0)
    {
      /* Error or EOF, close the file */
      if (write_size < 0)
        {
          data->failed = TRUE;
          g_task_return_error (data->task, error);
        }
      g_output_stream_close_async (stream, 0,
                                   g_task_get_cancellable (data->task),
                                   replace_contents_close_callback, data);
    }
  else if (write_size > 0)
    {
      const gchar *content;
      gsize length;

      content = g_bytes_get_data (data->content, &length);
      data->pos += write_size;

      if (data->pos >= length)
        g_output_stream_close_async (stream, 0,
                                     g_task_get_cancellable (data->task),
                                     replace_contents_close_callback, data);
      else
        g_output_stream_write_async (stream,
                                     content + data->pos,
                                     length - data->pos,
                                     0,
                                     g_task_get_cancellable (data->task),
                                     replace_contents_write_callback,
                                     data);
    }
}

Project: glib
File: gfile.c

g_file_real_find_enclosing_mount_finish (GFile         *file,
                                         GAsyncResult  *res,
                                         GError       **error)
{
  g_return_val_if_fail (g_task_is_valid (res, file), NULL);

  return g_task_propagate_pointer (G_TASK (res), error);
}

Project: glib
File: gfile.c

g_file_resolve_relative_path (GFile      *file,
                              const char *relative_path)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (file), NULL);
  g_return_val_if_fail (relative_path != NULL, NULL);

  iface = G_FILE_GET_IFACE (file);

  return (* iface->resolve_relative_path) (file, relative_path);
}

Project: glib
File: gfile.c

g_file_query_info (GFile                *file,
                   const char           *attributes,
                   GFileQueryInfoFlags   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->query_info == NULL)
    {
      g_set_error_literal (error, G_IO_ERROR,
                           G_IO_ERROR_NOT_SUPPORTED,
                           _("Operation not supported"));
      return NULL;
    }

  return (* iface->query_info) (file, attributes, flags, cancellable, error);
}

Project: glib
File: gfile.c

g_file_real_create_readwrite_finish (GFile         *file,
                                     GAsyncResult  *res,
                                     GError       **error)
{
  g_return_val_if_fail (g_task_is_valid (res, file), NULL);

  return g_task_propagate_pointer (G_TASK (res), error);
}

Project: glib
File: gfile.c

g_file_real_replace_finish (GFile         *file,
                            GAsyncResult  *res,
                            GError       **error)
{
  g_return_val_if_fail (g_task_is_valid (res, file), NULL);

  return g_task_propagate_pointer (G_TASK (res), error);
}

Project: glib
File: gfile.c

g_file_has_uri_scheme (GFile      *file,
                       const char *uri_scheme)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (file), FALSE);
  g_return_val_if_fail (uri_scheme != NULL, FALSE);

  iface = G_FILE_GET_IFACE (file);

  return (* iface->has_uri_scheme) (file, uri_scheme);
}

Project: glib
File: gfile.c

g_file_trash_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);

  iface = G_FILE_GET_IFACE (file);
  return (* iface->trash_finish) (file, result, error);
}

Project: glib
File: gfile.c

g_file_append_to_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_async_result_legacy_propagate_error (res, error))
    return NULL;

  iface = G_FILE_GET_IFACE (file);
  return (* iface->append_to_finish) (file, res, error);
}

Project: glib
File: gfile.c

append_to_async_thread (GTask         *task,
                        gpointer       source_object,
                        gpointer       task_data,
                        GCancellable  *cancellable)
{
  GFileCreateFlags *data = task_data;
  GFileOutputStream *stream;
  GError *error = NULL;

  stream = g_file_append_to (G_FILE (source_object), *data, cancellable, &error);
  if (stream)
    g_task_return_pointer (task, stream, g_object_unref);
  else
    g_task_return_error (task, error);
}

Project: glib
File: gfile.c

g_file_copy (GFile                  *source,
             GFile                  *destination,
             GFileCopyFlags          flags,
             GCancellable           *cancellable,
             GFileProgressCallback   progress_callback,
             gpointer                progress_callback_data,
             GError                **error)
{
  GFileIface *iface;
  GError *my_error;
  gboolean res;

  g_return_val_if_fail (G_IS_FILE (source), FALSE);
  g_return_val_if_fail (G_IS_FILE (destination), FALSE);

  if (g_cancellable_set_error_if_cancelled (cancellable, error))
    return FALSE;

  iface = G_FILE_GET_IFACE (destination);
  if (iface->copy)
    {
      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);

          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);
        }
    }

  return file_copy_fallback (source, destination, flags, cancellable,
                             progress_callback, progress_callback_data,
                             error);
}

Project: glib
File: gfile.c

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_async_result_legacy_propagate_error (res, error))
    return NULL;

  iface = G_FILE_GET_IFACE (file);
  return (* iface->open_readwrite_finish) (file, res, error);
}

Project: glib
File: gfile.c

g_file_append_to_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->append_to_async) (file,
                              flags,
                              io_priority,
                              cancellable,
                              callback,
                              user_data);
}

Project: glib
File: gfile.c

g_file_mount_mountable_finish (GFile         *file,
                               GAsyncResult  *result,
                               GError       **error)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (file), NULL);
  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);

  if (g_async_result_legacy_propagate_error (result, error))
    return NULL;
  else if (g_async_result_is_tagged (result, g_file_mount_mountable))
    return g_task_propagate_pointer (G_TASK (result), error);

  iface = G_FILE_GET_IFACE (file);
  return (* iface->mount_mountable_finish) (file, result, error);
}

Project: glib
File: gfile.c

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;
}

Project: glib
File: gfile.c

g_file_set_attributes_async (GFile               *file,
                             GFileInfo           *info,
                             GFileQueryInfoFlags  flags,
                             int                  io_priority,
                             GCancellable        *cancellable,
                             GAsyncReadyCallback  callback,
                             gpointer             user_data)
{
  GFileIface *iface;

  g_return_if_fail (G_IS_FILE (file));
  g_return_if_fail (G_IS_FILE_INFO (info));

  iface = G_FILE_GET_IFACE (file);
  (* iface->set_attributes_async) (file,
                                   info,
                                   flags,
                                   io_priority,
                                   cancellable,
                                   callback,
                                   user_data);
}

Project: glib
File: gfile.c

g_file_unmount_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_async_result_legacy_propagate_error (result, error))
    return FALSE;
  else if (g_async_result_is_tagged (result, g_file_unmount_mountable_with_operation))
    return g_task_propagate_boolean (G_TASK (result), error);

  iface = G_FILE_GET_IFACE (file);
  return (* iface->unmount_mountable_finish) (file, result, error);
}

Project: glib
File: gfile.c

g_file_real_query_info_async (GFile               *file,
                              const char          *attributes,
                              GFileQueryInfoFlags  flags,
                              int                  io_priority,
                              GCancellable        *cancellable,
                              GAsyncReadyCallback  callback,
                              gpointer             user_data)
{
  GTask *task;
  QueryInfoAsyncData *data;

  data = g_new0 (QueryInfoAsyncData, 1);
  data->attributes = g_strdup (attributes);
  data->flags = flags;

  task = g_task_new (file, cancellable, callback, user_data);
  g_task_set_source_tag (task, g_file_real_query_info_async);
  g_task_set_task_data (task, data, (GDestroyNotify)query_info_data_free);
  g_task_set_priority (task, io_priority);
  g_task_run_in_thread (task, query_info_async_thread);
  g_object_unref (task);
}

Project: glib
File: gfile.c

g_file_new_for_uri (const char *uri)
{
  g_return_val_if_fail (uri != NULL, NULL);

  return g_vfs_get_file_for_uri (g_vfs_get_default (), uri);
}

Project: glib
File: gfile.c

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);
}

Project: glib
File: gfile.c

g_file_measure_disk_usage_finish (GFile         *file,
                                  GAsyncResult  *result,
                                  guint64       *disk_usage,
                                  guint64       *num_dirs,
                                  guint64       *num_files,
                                  GError       **error)
{
  g_return_val_if_fail (G_IS_FILE (file), FALSE);
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

  return G_FILE_GET_IFACE (file)->measure_disk_usage_finish (file, result, disk_usage, num_dirs, num_files, error);
}

Project: glib
File: gfile.c

g_file_load_bytes_async (GFile               *file,
                         GCancellable        *cancellable,
                         GAsyncReadyCallback  callback,
                         gpointer             user_data)
{
  GError *error = NULL;
  GBytes *bytes;
  GTask *task;

  g_return_if_fail (G_IS_FILE (file));
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));

  task = g_task_new (file, cancellable, callback, user_data);
  g_task_set_source_tag (task, g_file_load_bytes_async);

  if (!g_file_has_uri_scheme (file, "resource"))
    {
      g_file_load_contents_async (file,
                                  cancellable,
                                  g_file_load_bytes_cb,
                                  g_steal_pointer (&task));
      return;
    }

  bytes = g_file_load_bytes (file, cancellable, NULL, &error);

  if (bytes == NULL)
    g_task_return_error (task, g_steal_pointer (&error));
  else
    g_task_return_pointer (task,
                           g_steal_pointer (&bytes),
                           (GDestroyNotify)g_bytes_unref);

  g_object_unref (task);
}

Project: glib
File: gfile.c

g_file_query_settable_attributes (GFile         *file,
                                  GCancellable  *cancellable,
                                  GError       **error)
{
  GFileIface *iface;
  GError *my_error;
  GFileAttributeInfoList *list;

  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->query_settable_attributes == NULL)
    return g_file_attribute_info_list_new ();

  my_error = NULL;
  list = (* iface->query_settable_attributes) (file, cancellable, &my_error);

  if (list == NULL)
    {
      if (my_error->domain == G_IO_ERROR && my_error->code == G_IO_ERROR_NOT_SUPPORTED)
        {
          list = g_file_attribute_info_list_new ();
          g_error_free (my_error);
        }
      else
        g_propagate_error (error, my_error);
    }

  return list;
}

Project: glib
File: gfile.c

g_file_real_set_attributes_async (GFile               *file,
                                  GFileInfo           *info,
                                  GFileQueryInfoFlags  flags,
                                  int                  io_priority,
                                  GCancellable        *cancellable,
                                  GAsyncReadyCallback  callback,
                                  gpointer             user_data)
{
  GTask *task;
  SetInfoAsyncData *data;

  data = g_new0 (SetInfoAsyncData, 1);
  data->info = g_file_info_dup (info);
  data->flags = flags;

  task = g_task_new (file, cancellable, callback, user_data);
  g_task_set_source_tag (task, g_file_real_set_attributes_async);
  g_task_set_task_data (task, data, (GDestroyNotify)set_info_data_free);
  g_task_set_priority (task, io_priority);

  g_task_run_in_thread (task, set_info_async_thread);
  g_object_unref (task);
}

Project: glib
File: gfile.c

measure_disk_usage_invoke_progress (gpointer user_data)
{
  MeasureProgress *progress = user_data;

  (* progress->callback) (progress->reporting,
                          progress->current_size, progress->num_dirs, progress->num_files,
                          progress->user_data);

  return FALSE;
}

Project: glib
File: gfile.c

copy_async_thread (GTask        *task,
                   gpointer      source,
                   gpointer      task_data,
                   GCancellable *cancellable)
{
  CopyAsyncData *data = task_data;
  gboolean result;
  GError *error = NULL;

  result = g_file_copy (data->source,
                        data->destination,
                        data->flags,
                        cancellable,
                        (data->progress_cb != NULL) ? copy_async_progress_callback : NULL,
                        task,
                        &error);
  if (result)
    g_task_return_boolean (task, TRUE);
  else
    g_task_return_error (task, error);
}

Project: glib
File: gfile.c

g_file_query_default_handler_async (GFile              *file,
                                    int                 io_priority,
                                    GCancellable       *cancellable,
                                    GAsyncReadyCallback callback,
                                    gpointer            user_data)
{
  GTask *task;
  char *uri_scheme;

  task = g_task_new (file, cancellable, callback, user_data);
  g_task_set_source_tag (task, g_file_query_default_handler_async);

  uri_scheme = g_file_get_uri_scheme (file);
  if (uri_scheme && uri_scheme[0] != '\0')
    {
      GAppInfo *appinfo;

      /* FIXME: The following still uses blocking calls. */
      appinfo = g_app_info_get_default_for_uri_scheme (uri_scheme);
      g_free (uri_scheme);

      if (appinfo != NULL)
        {
          g_task_return_pointer (task, g_steal_pointer (&appinfo), g_object_unref);
          g_object_unref (task);
          return;
        }
    }
  else
    g_free (uri_scheme);

  g_file_query_info_async (file,
                           G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
                           0,
                           io_priority,
                           cancellable,
                           query_default_handler_query_info_cb,
                           g_steal_pointer (&task));
}

Project: glib
File: gfile.c

g_file_delete_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_async_result_legacy_propagate_error (result, error))
    return FALSE;

  iface = G_FILE_GET_IFACE (file);
  return (* iface->delete_file_finish) (file, result, error);
}

Project: glib
File: gfile.c

g_file_copy_attributes (GFile           *source,
                        GFile           *destination,
                        GFileCopyFlags   flags,
                        GCancellable    *cancellable,
                        GError         **error)
{
  char *attrs_to_read;
  gboolean res;
  GFileInfo *info;
  gboolean source_nofollow_symlinks;

  if (!build_attribute_list_for_copy (destination, flags, &attrs_to_read,
                                      cancellable, error))
    return FALSE;

  source_nofollow_symlinks = flags & G_FILE_COPY_NOFOLLOW_SYMLINKS;

  /* Ignore errors here, if we can't read some info (e.g. if it doesn't exist)
   * we just don't copy it.
   */
  info = g_file_query_info (source, attrs_to_read,
                            source_nofollow_symlinks ? G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS:0,
                            cancellable,
                            NULL);

  g_free (attrs_to_read);

  res = TRUE;
  if  (info)
    {
      res = g_file_set_attributes_from_info (destination,
                                             info,
                                             G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                             cancellable,
                                             error);
      g_object_unref (info);
    }

  return res;
}

Project: glib
File: gfile.c

query_filesystem_info_async_thread (GTask         *task,
                                    gpointer       object,
                                    gpointer       task_data,
                                    GCancellable  *cancellable)
{
  const char *attributes = task_data;
  GFileInfo *info;
  GError *error = NULL;

  info = g_file_query_filesystem_info (G_FILE (object), attributes, cancellable, &error);
  if (info)
    g_task_return_pointer (task, info, g_object_unref);
  else
    g_task_return_error (task, error);
}

Project: glib
File: gfile.c

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;
    }
  else
    g_free (uri_scheme);

  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 available */
      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;
}

Project: glib
File: gfile.c

copy_symlink (GFile           *destination,
              GFileCopyFlags   flags,
              GCancellable    *cancellable,
              const char      *target,
              GError         **error)
{
  GError *my_error;
  gboolean tried_delete;
  GFileInfo *info;
  GFileType file_type;

  tried_delete = FALSE;

 retry:
  my_error = NULL;
  if (!g_file_make_symbolic_link (destination, target, cancellable, &my_error))
    {
      /* Maybe it already existed, and we want to overwrite? */
      if (!tried_delete && (flags & G_FILE_COPY_OVERWRITE) &&
          my_error->domain == G_IO_ERROR && my_error->code == G_IO_ERROR_EXISTS)
        {
          g_clear_error (&my_error);

          /* Don't overwrite if the destination is a directory */
          info = g_file_query_info (destination, G_FILE_ATTRIBUTE_STANDARD_TYPE,
                                    G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                    cancellable, &my_error);
          if (info != NULL)
            {
              file_type = g_file_info_get_file_type (info);
              g_object_unref (info);

              if (file_type == G_FILE_TYPE_DIRECTORY)
                {
                  g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY,
                                       _("Can’t copy over directory"));
                  return FALSE;
                }
            }

          if (!g_file_delete (destination, cancellable, error))
            return FALSE;

          tried_delete = TRUE;
          goto retry;
        }
            /* Nah, fail */
      g_propagate_error (error, my_error);
      return FALSE;
    }

  return TRUE;
}

Project: glib
File: gfile.c

replace_contents_open_callback (GObject      *obj,
                                GAsyncResult *open_res,
                                gpointer      user_data)
{
  GFile *file = G_FILE (obj);
  GFileOutputStream *stream;
  ReplaceContentsData *data = user_data;
  GError *error = NULL;

  stream = g_file_replace_finish (file, open_res, &error);

  if (stream)
    {
      const gchar *content;
      gsize length;

      content = g_bytes_get_data (data->content, &length);
      g_output_stream_write_async (G_OUTPUT_STREAM (stream),
                                   content + data->pos,
                                   length - data->pos,
                                   0,
                                   g_task_get_cancellable (data->task),
                                   replace_contents_write_callback,
                                   data);
    }
  else
    {
      g_task_return_error (data->task, error);
      g_object_unref (data->task);
    }
}

Project: glib
File: gfile.c

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_async_result_legacy_propagate_error (result, error))
    return FALSE;
  else if (g_async_result_is_tagged (result, g_file_unmount_mountable_with_operation))
    return g_task_propagate_boolean (G_TASK (result), error);

  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);
}

Project: glib
File: gfile.c

g_file_replace_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_async) (file,
                            etag,
                            make_backup,
                            flags,
                            io_priority,
                            cancellable,
                            callback,
                            user_data);
}

Project: glib
File: gfile.c

g_file_real_set_attributes_finish (GFile         *file,
                                   GAsyncResult  *res,
                                   GFileInfo    **info,
                                   GError       **error)
{
  SetInfoAsyncData *data;

  g_return_val_if_fail (g_task_is_valid (res, file), FALSE);

  data = g_task_get_task_data (G_TASK (res));

  if (info)
    *info = g_object_ref (data->info);

  if (error != NULL && data->error)
    *error = g_error_copy (data->error);

  return data->res;
}

Project: glib
File: gfile.c

replace_async_data_free (ReplaceAsyncData *data)
{
  if (data->stream)
    g_object_unref (data->stream);
  g_free (data->etag);
  g_free (data);
}

Project: glib
File: gfile.c

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)
{
  GTask *task;
  CopyAsyncData *data;

  data = g_slice_new (CopyAsyncData);
  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;

  task = g_task_new (source, cancellable, callback, user_data);
  g_task_set_source_tag (task, g_file_real_copy_async);
  g_task_set_task_data (task, data, (GDestroyNotify)copy_async_data_free);
  g_task_set_priority (task, io_priority);
  g_task_run_in_thread (task, copy_async_thread);
  g_object_unref (task);
}

Project: glib
File: gfile.c

copy_async_data_free (CopyAsyncData *data)
{
  g_object_unref (data->source);
  g_object_unref (data->destination);
  g_slice_free (CopyAsyncData, data);
}

Project: glib
File: gfile.c

g_file_load_bytes_finish (GFile         *file,
                          GAsyncResult  *result,
                          gchar        **etag_out,
                          GError       **error)
{
  GBytes *bytes;

  g_return_val_if_fail (G_IS_FILE (file), NULL);
  g_return_val_if_fail (G_IS_TASK (result), NULL);
  g_return_val_if_fail (g_task_is_valid (G_TASK (result), file), NULL);
  g_return_val_if_fail (error == NULL || *error == NULL, NULL);

  bytes = g_task_propagate_pointer (G_TASK (result), error);

  if (etag_out != NULL)
    *etag_out = g_strdup (g_task_get_task_data (G_TASK (result)));

  return bytes;
}

Project: glib
File: gfile.c

g_file_query_writable_namespaces (GFile         *file,
                                  GCancellable  *cancellable,
                                  GError       **error)
{
  GFileIface *iface;
  GError *my_error;
  GFileAttributeInfoList *list;

  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->query_writable_namespaces == NULL)
    return g_file_attribute_info_list_new ();

  my_error = NULL;
  list = (* iface->query_writable_namespaces) (file, cancellable, &my_error);

  if (list == NULL)
    {
      g_warn_if_reached();
      list = g_file_attribute_info_list_new ();
    }

  if (my_error != NULL)
    {
      if (my_error->domain == G_IO_ERROR && my_error->code == G_IO_ERROR_NOT_SUPPORTED)
        {
          g_error_free (my_error);
        }
      else
        g_propagate_error (error, my_error);
    }

  return list;
}

Project: glib
File: gfile.c

g_file_load_partial_contents_async (GFile                 *file,
                                    GCancellable          *cancellable,
                                    GFileReadMoreCallback  read_more_callback,
                                    GAsyncReadyCallback    callback,
                                    gpointer               user_data)
{
  LoadContentsData *data;

  g_return_if_fail (G_IS_FILE (file));

  data = g_new0 (LoadContentsData, 1);
  data->read_more_callback = read_more_callback;
  data->content = g_byte_array_new ();

  data->task = g_task_new (file, cancellable, callback, user_data);
  g_task_set_source_tag (data->task, g_file_load_partial_contents_async);
  g_task_set_task_data (data->task, data, (GDestroyNotify)load_contents_data_free);

  g_file_read_async (file,
                     0,
                     g_task_get_cancellable (data->task),
                     load_contents_open_callback,
                     data);
}

Project: glib
File: gfile.c

g_file_make_symbolic_link (GFile         *file,
                           const char    *symlink_value,
                           GCancellable  *cancellable,
                           GError       **error)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (file), FALSE);
  g_return_val_if_fail (symlink_value != NULL, FALSE);

  if (g_cancellable_set_error_if_cancelled (cancellable, error))
    return FALSE;

  if (*symlink_value == '\0')
    {
      g_set_error_literal (error, G_IO_ERROR,
                           G_IO_ERROR_INVALID_ARGUMENT,
                           _("Invalid symlink value given"));
      return FALSE;
    }

  iface = G_FILE_GET_IFACE (file);

  if (iface->make_symbolic_link == NULL)
    {
      g_set_error_literal (error, G_IO_ERROR,
                           G_IO_ERROR_NOT_SUPPORTED,
                           _("Operation not supported"));
      return FALSE;
    }

  return (* iface->make_symbolic_link) (file, symlink_value, cancellable, error);
}

Project: glib
File: gfile.c

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);
}

Project: glib
File: gfile.c

g_file_real_read_finish (GFile         *file,
                         GAsyncResult  *res,
                         GError       **error)
{
  g_return_val_if_fail (g_task_is_valid (res, file), NULL);

  return g_task_propagate_pointer (G_TASK (res), error);
}

Project: glib
File: gfile.c

g_file_query_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_async_result_legacy_propagate_error (res, error))
    return NULL;

  iface = G_FILE_GET_IFACE (file);
  return (* iface->query_info_finish) (file, res, error);
}

Project: glib
File: gfile.c

file_peek_path_generic (GFile *file)
{
  const char *path;
  static GQuark _file_path_quark = 0;

  if (G_UNLIKELY (_file_path_quark) == 0)
    _file_path_quark = g_quark_from_static_string ("gio-file-path");

  /* We need to be careful about threading, as two threads calling
   * g_file_peek_path() on the same file could race: both would see
   * (g_object_get_qdata(…) == NULL) to begin with, both would generate and add
   * the path, but the second thread to add it would end up freeing the path
   * set by the first thread. The first thread would still return the pointer
   * to that freed path, though, resulting an a read-after-free. Handle that
   * with a compare-and-swap loop. The g_object_*_qdata() functions are atomic. */

  while (TRUE)
    {
      gchar *new_path = NULL;

      path = g_object_get_qdata ((GObject*)file, _file_path_quark);

      if (path != NULL)
        break;

      if (g_file_has_uri_scheme (file, "trash") ||
          g_file_has_uri_scheme (file, "recent"))
        new_path = file_get_target_path (file);
      else
        new_path = g_file_get_path (file);
      if (new_path == NULL)
        return NULL;

      /* By passing NULL here, we ensure we never replace existing data: */
      if (g_object_replace_qdata ((GObject *) file, _file_path_quark,
                                  NULL, (gpointer) new_path,
                                  (GDestroyNotify) g_free, NULL))
        break;
      else
        g_free (new_path);
    }

  return path;
}

Project: glib
File: gfile.c

g_file_read (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->read_fn == NULL)
    {
      g_set_error_literal (error, G_IO_ERROR,
                           G_IO_ERROR_NOT_SUPPORTED,
                           _("Operation not supported"));
      return NULL;
    }

  return (* iface->read_fn) (file, cancellable, error);
}

Project: glib
File: gfile.c

g_file_get_child (GFile      *file,
                  const char *name)
{
  g_return_val_if_fail (G_IS_FILE (file), NULL);
  g_return_val_if_fail (name != NULL, NULL);

  return g_file_resolve_relative_path (file, name);
}

Project: glib
File: gfile.c

g_file_set_attributes_from_info (GFile                *file,
                                 GFileInfo            *info,
                                 GFileQueryInfoFlags   flags,
                                 GCancellable         *cancellable,
                                 GError              **error)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (file), FALSE);
  g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);

  if (g_cancellable_set_error_if_cancelled (cancellable, error))
    return FALSE;

  g_file_info_clear_status (info);

  iface = G_FILE_GET_IFACE (file);

  return (* iface->set_attributes_from_info) (file,
                                              info,
                                              flags,
                                              cancellable,
                                              error);
}

Project: glib
File: gfile.c

g_file_real_delete_finish (GFile         *file,
                           GAsyncResult  *res,
                           GError       **error)
{
  g_return_val_if_fail (g_task_is_valid (res, file), FALSE);

  return g_task_propagate_boolean (G_TASK (res), error);
}

Project: glib
File: gfile.c

g_file_set_attribute_byte_string  (GFile                *file,
                                   const gchar          *attribute,
                                   const gchar          *value,
                                   GFileQueryInfoFlags   flags,
                                   GCancellable         *cancellable,
                                   GError              **error)
{
  return g_file_set_attribute (file, attribute,
                               G_FILE_ATTRIBUTE_TYPE_BYTE_STRING, (gpointer)value,
                               flags, cancellable, error);
}

Project: glib
File: gfile.c

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_async_result_legacy_propagate_error (result, error))
    return FALSE;
  else if (g_async_result_is_tagged (result, g_file_poll_mountable))
    return g_task_propagate_boolean (G_TASK (result), error);

  iface = G_FILE_GET_IFACE (file);
  return (* iface->poll_mountable_finish) (file, result, error);
}

Project: glib
File: gfile.c

copy_stream_with_progress (GInputStream           *in,
                           GOutputStream          *out,
                           GFile                  *source,
                           GCancellable           *cancellable,
                           GFileProgressCallback   progress_callback,
                           gpointer                progress_callback_data,
                           GError                **error)
{
  gssize n_read;
  gsize n_written;
  goffset current_size;
  char *buffer;
  gboolean res;
  goffset total_size;
  GFileInfo *info;

  total_size = -1;
  /* avoid performance impact of querying total size when it's not needed */
  if (progress_callback)
    {
      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;

  buffer = g_malloc0 (STREAM_BUFFER_SIZE);
  current_size = 0;
  res = TRUE;
  while (TRUE)
    {
      n_read = g_input_stream_read (in, buffer, STREAM_BUFFER_SIZE, cancellable, error);
      if (n_read == -1)
        {
          res = FALSE;
          break;
        }

      if (n_read == 0)
        break;

      current_size += n_read;

      res = g_output_stream_write_all (out, buffer, n_read, &n_written, cancellable, error);
      if (!res)
        break;

      if (progress_callback)
        progress_callback (current_size, total_size, progress_callback_data);
    }
  g_free (buffer);

  /* Make sure we send full copied size */
  if (progress_callback)
    progress_callback (current_size, total_size, progress_callback_data);

  return res;
}

Project: glib
File: gfile.c

g_file_real_enumerate_children_async (GFile               *file,
                                      const char          *attributes,
                                      GFileQueryInfoFlags  flags,
                                      int                  io_priority,
                                      GCancellable        *cancellable,
                                      GAsyncReadyCallback  callback,
                                      gpointer             user_data)
{
  GTask *task;
  QueryInfoAsyncData *data;

  data = g_new0 (QueryInfoAsyncData, 1);
  data->attributes = g_strdup (attributes);
  data->flags = flags;

  task = g_task_new (file, cancellable, callback, user_data);
  g_task_set_source_tag (task, g_file_real_enumerate_children_async);
  g_task_set_task_data (task, data, (GDestroyNotify)query_info_data_free);
  g_task_set_priority (task, io_priority);
  g_task_run_in_thread (task, enumerate_children_async_thread);
  g_object_unref (task);
}

Project: glib
File: gfile.c

g_file_real_delete_async (GFile               *file,
                          int                  io_priority,
                          GCancellable        *cancellable,
                          GAsyncReadyCallback  callback,
                          gpointer             user_data)
{
  GTask *task;

  task = g_task_new (file, cancellable, callback, user_data);
  g_task_set_source_tag (task, g_file_real_delete_async);
  g_task_set_priority (task, io_priority);
  g_task_run_in_thread (task, delete_async_thread);
  g_object_unref (task);
}

Project: glib
File: gfile.c

g_file_delete_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->delete_file_async) (file,
                                io_priority,
                                cancellable,
                                callback,
                                user_data);
}

Project: glib
File: gfile.c

g_file_make_directory (GFile         *file,
                       GCancellable  *cancellable,
                       GError       **error)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (file), FALSE);

  if (g_cancellable_set_error_if_cancelled (cancellable, error))
    return FALSE;

  iface = G_FILE_GET_IFACE (file);

  if (iface->make_directory == NULL)
    {
      g_set_error_literal (error, G_IO_ERROR,
                           G_IO_ERROR_NOT_SUPPORTED,
                           _("Operation not supported"));
      return FALSE;
    }

  return (* iface->make_directory) (file, cancellable, error);
}

Project: glib
File: gfile.c

g_file_real_trash_finish (GFile         *file,
                          GAsyncResult  *res,
                          GError       **error)
{
  g_return_val_if_fail (g_task_is_valid (res, file), FALSE);

  return g_task_propagate_boolean (G_TASK (res), error);
}

Project: glib
File: gfile.c

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_task_report_new_error (file, callback, user_data,
                               g_file_unmount_mountable_with_operation,
                               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);
}

Project: glib
File: gfile.c

g_file_get_child_for_display_name (GFile      *file,
                                   const char *display_name,
                                   GError **error)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (file), NULL);
  g_return_val_if_fail (display_name != NULL, NULL);

  iface = G_FILE_GET_IFACE (file);

  return (* iface->get_child_for_display_name) (file, display_name, error);
}

Project: glib
File: gfile.c

set_display_name_async_thread (GTask        *task,
                               gpointer      object,
                               gpointer      task_data,
                               GCancellable *cancellable)
{
  GError *error = NULL;
  char *name = task_data;
  GFile *file;

  file = g_file_set_display_name (G_FILE (object), name, cancellable, &error);

  if (file == NULL)
    g_task_return_error (task, error);
  else
    g_task_return_pointer (task, file, g_object_unref);
}

Project: glib
File: gfile.c

g_file_get_uri_scheme (GFile *file)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (file), NULL);

  iface = G_FILE_GET_IFACE (file);

  return (* iface->get_uri_scheme) (file);
}

Project: glib
File: gfile.c

g_file_real_create_finish (GFile         *file,
                           GAsyncResult  *res,
                           GError       **error)
{
  g_return_val_if_fail (g_task_is_valid (res, file), NULL);

  return g_task_propagate_pointer (G_TASK (res), error);
}

Project: glib
File: gfile.c

set_info_data_free (SetInfoAsyncData *data)
{
  if (data->info)
    g_object_unref (data->info);
  if (data->error)
    g_error_free (data->error);
  g_free (data);
}

Project: glib
File: gfile.c

g_file_move (GFile                  *source,
             GFile                  *destination,
             GFileCopyFlags          flags,
             GCancellable           *cancellable,
             GFileProgressCallback   progress_callback,
             gpointer                progress_callback_data,
             GError                **error)
{
  GFileIface *iface;
  GError *my_error;
  gboolean res;

  g_return_val_if_fail (G_IS_FILE (source), FALSE);
  g_return_val_if_fail (G_IS_FILE (destination), FALSE);

  if (g_cancellable_set_error_if_cancelled (cancellable, error))
    return FALSE;

  iface = G_FILE_GET_IFACE (destination);
  if (iface->move)
    {
      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;
        }
      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->move)
        {
          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;
            }
          else
            g_clear_error (&my_error);
        }
    }

  if (flags & G_FILE_COPY_NO_FALLBACK_FOR_MOVE)
    {
      g_set_error_literal (error, G_IO_ERROR,
                           G_IO_ERROR_NOT_SUPPORTED,
                           _("Operation not supported"));
      return FALSE;
    }

  flags |= G_FILE_COPY_ALL_METADATA;
  if (!g_file_copy (source, destination, flags, cancellable,
                    progress_callback, progress_callback_data,
                    error))
    return FALSE;

  return g_file_delete (source, cancellable, error);
}

Project: glib
File: gfile.c

open_readwrite_async_thread (GTask        *task,
                             gpointer      object,
                             gpointer      task_data,
                             GCancellable *cancellable)
{
  GFileIOStream *stream;
  GError *error = NULL;

  stream = g_file_open_readwrite (G_FILE (object), cancellable, &error);

  if (stream == NULL)
    g_task_return_error (task, error);
  else
    g_task_return_pointer (task, stream, g_object_unref);
}

Project: glib
File: gfile.c

g_file_set_display_name (GFile         *file,
                         const gchar   *display_name,
                         GCancellable  *cancellable,
                         GError       **error)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (file), NULL);
  g_return_val_if_fail (display_name != NULL, NULL);

  if (strchr (display_name, G_DIR_SEPARATOR) != NULL)
    {
      g_set_error (error,
                   G_IO_ERROR,
                   G_IO_ERROR_INVALID_ARGUMENT,
                   _("File names cannot contain “%c”"), G_DIR_SEPARATOR);
      return NULL;
    }

  if (g_cancellable_set_error_if_cancelled (cancellable, error))
    return NULL;

  iface = G_FILE_GET_IFACE (file);

  return (* iface->set_display_name) (file, display_name, cancellable, error);
}

Project: glib
File: gfile.c

g_file_is_native (GFile *file)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (file), FALSE);

  iface = G_FILE_GET_IFACE (file);

  return (* iface->is_native) (file);
}

Project: glib
File: gfile.c

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)
{
  GTask *task;
  ReplaceAsyncData *data;

  data = g_new0 (ReplaceAsyncData, 1);
  data->etag = g_strdup (etag);
  data->make_backup = make_backup;
  data->flags = flags;

  task = g_task_new (file, cancellable, callback, user_data);
  g_task_set_source_tag (task, g_file_real_replace_async);
  g_task_set_task_data (task, data, (GDestroyNotify)replace_async_data_free);
  g_task_set_priority (task, io_priority);

  g_task_run_in_thread (task, replace_async_thread);
  g_object_unref (task);
}

Project: glib
File: gfile.c

g_file_load_contents (GFile         *file,
                      GCancellable  *cancellable,
                      char         **contents,
                      gsize         *length,
                      char         **etag_out,
                      GError       **error)
{
  GFileInputStream *in;
  GByteArray *content;
  gsize pos;
  gssize res;
  GFileInfo *info;

  g_return_val_if_fail (G_IS_FILE (file), FALSE);
  g_return_val_if_fail (contents != NULL, FALSE);

  in = g_file_read (file, cancellable, error);
  if (in == NULL)
    return FALSE;

  content = g_byte_array_new ();
  pos = 0;

  g_byte_array_set_size (content, pos + GET_CONTENT_BLOCK_SIZE + 1);
  while ((res = g_input_stream_read (G_INPUT_STREAM (in),
                                     content->data + pos,
                                     GET_CONTENT_BLOCK_SIZE,
                                     cancellable, error)) > 0)
    {
      pos += res;
      g_byte_array_set_size (content, pos + GET_CONTENT_BLOCK_SIZE + 1);
    }

  if (etag_out)
    {
      *etag_out = NULL;

      info = g_file_input_stream_query_info (in,
                                             G_FILE_ATTRIBUTE_ETAG_VALUE,
                                             cancellable,
                                             NULL);
      if (info)
        {
          *etag_out = g_strdup (g_file_info_get_etag (info));
          g_object_unref (info);
        }
    }

  /* Ignore errors on close */
  g_input_stream_close (G_INPUT_STREAM (in), cancellable, NULL);
  g_object_unref (in);

  if (res < 0)
    {
      /* error is set already */
      g_byte_array_free (content, TRUE);
      return FALSE;
    }

  if (length)
    *length = pos;

  /* Zero terminate (we got an extra byte allocated for this */
  content->data[pos] = 0;

  *contents = (char *)g_byte_array_free (content, FALSE);

  return TRUE;
}

Project: glib
File: gfile.c

replace_contents_data_free (ReplaceContentsData *data)
{
  g_bytes_unref (data->content);
  g_free (data->etag);
  g_free (data);
}

Project: glib
File: gfile.c

g_file_equal (GFile *file1,
              GFile *file2)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (file1), FALSE);
  g_return_val_if_fail (G_IS_FILE (file2), FALSE);

  if (file1 == file2)
    return TRUE;

  if (G_TYPE_FROM_INSTANCE (file1) != G_TYPE_FROM_INSTANCE (file2))
    return FALSE;

  iface = G_FILE_GET_IFACE (file1);

  return (* iface->equal) (file1, file2);
}

Project: glib
File: gfile.c

g_file_real_measure_disk_usage_finish (GFile         *file,
                                       GAsyncResult  *result,
                                       guint64       *disk_usage,
                                       guint64       *num_dirs,
                                       guint64       *num_files,
                                       GError       **error)
{
  MeasureResult *measure_result;

  g_return_val_if_fail (g_task_is_valid (result, file), FALSE);

  measure_result = g_task_propagate_pointer (G_TASK (result), error);

  if (measure_result == NULL)
    return FALSE;

  if (disk_usage)
    *disk_usage = measure_result->disk_usage;

  if (num_dirs)
    *num_dirs = measure_result->num_dirs;

  if (num_files)
    *num_files = measure_result->num_files;

  g_free (measure_result);

  return TRUE;
}

Project: glib
File: gfile.c

g_file_eject_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_async_result_legacy_propagate_error (result, error))
    return FALSE;
  else if (g_async_result_is_tagged (result, g_file_eject_mountable_with_operation))
    return g_task_propagate_boolean (G_TASK (result), error);

  iface = G_FILE_GET_IFACE (file);
  return (* iface->eject_mountable_finish) (file, result, error);
}

Project: glib
File: gfile.c

trash_async_thread (GTask        *task,
                    gpointer      object,
                    gpointer      task_data,
                    GCancellable *cancellable)
{
  GError *error = NULL;

  if (g_file_trash (G_FILE (object), cancellable, &error))
    g_task_return_boolean (task, TRUE);
  else
    g_task_return_error (task, error);
}

Project: glib
File: gfile.c

g_file_append_to (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->append_to == NULL)
    {
      g_set_error_literal (error, G_IO_ERROR,
                           G_IO_ERROR_NOT_SUPPORTED,
                           _("Operation not supported"));
      return NULL;
    }

  return (* iface->append_to) (file, flags, cancellable, error);
}

Project: glib
File: gfile.c

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);
}

Project: glib
File: gfile.c

g_file_real_trash_async (GFile               *file,
                         int                  io_priority,
                         GCancellable        *cancellable,
                         GAsyncReadyCallback  callback,
                         gpointer             user_data)
{
  GTask *task;

  task = g_task_new (file, cancellable, callback, user_data);
  g_task_set_source_tag (task, g_file_real_trash_async);
  g_task_set_priority (task, io_priority);
  g_task_run_in_thread (task, trash_async_thread);
  g_object_unref (task);
}

Project: glib
File: gfile.c

g_file_monitor_directory (GFile              *file,
                          GFileMonitorFlags   flags,
                          GCancellable       *cancellable,
                          GError            **error)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (file), NULL);
  g_return_val_if_fail (~flags & G_FILE_MONITOR_WATCH_HARD_LINKS, NULL);

  if (g_cancellable_set_error_if_cancelled (cancellable, error))
    return NULL;

  iface = G_FILE_GET_IFACE (file);

  if (iface->monitor_dir == NULL)
    {
      g_set_error_literal (error, G_IO_ERROR,
                           G_IO_ERROR_NOT_SUPPORTED,
                           _("Operation not supported"));
      return NULL;
    }

  return (* iface->monitor_dir) (file, flags, cancellable, error);
}

Project: glib
File: gfile.c

g_file_create (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 == NULL)
    {
      g_set_error_literal (error, G_IO_ERROR,
                           G_IO_ERROR_NOT_SUPPORTED,
                           _("Operation not supported"));
      return NULL;
    }

  return (* iface->create) (file, flags, cancellable, error);
}

Project: glib
File: gfile.c

g_file_real_open_readwrite_finish (GFile         *file,
                                   GAsyncResult  *res,
                                   GError       **error)
{
  g_return_val_if_fail (g_task_is_valid (res, file), NULL);

  return g_task_propagate_pointer (G_TASK (res), error);
}

Project: glib
File: gfile.c

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_async_result_legacy_propagate_error (res, error))
    return FALSE;

  iface = G_FILE_GET_IFACE (file);
  return (* iface->copy_finish) (file, res, error);
}

Project: glib
File: gfile.c

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_task_report_new_error (file, callback, user_data,
                               g_file_stop_mountable,
                               G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
                               _("Operation not supported"));
      return;
    }

  (* iface->stop_mountable) (file,
                             flags,
                             mount_operation,
                             cancellable,
                             callback,
                             user_data);
}

Project: glib
File: gfile.c

g_file_get_parent (GFile *file)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (file), NULL);

  iface = G_FILE_GET_IFACE (file);

  return (* iface->get_parent) (file);
}

Project: glib
File: gfile.c

g_file_get_uri (GFile *file)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (file), NULL);

  iface = G_FILE_GET_IFACE (file);

  return (* iface->get_uri) (file);
}

Project: glib
File: gfile.c

g_file_real_query_info_finish (GFile         *file,
                               GAsyncResult  *res,
                               GError       **error)
{
  g_return_val_if_fail (g_task_is_valid (res, file), NULL);

  return g_task_propagate_pointer (G_TASK (res), error);
}

Project: glib
File: gfile.c

g_file_real_query_filesystem_info_finish (GFile         *file,
                                          GAsyncResult  *res,
                                          GError       **error)
{
  g_return_val_if_fail (g_task_is_valid (res, file), NULL);

  return g_task_propagate_pointer (G_TASK (res), error);
}

Project: glib
File: gfile.c

is_valid_scheme_character (char c)
{
  return g_ascii_isalnum (c) || c == '+' || c == '-' || c == '.';
}

Project: glib
File: gfile.c

g_file_new_tmp (const char     *tmpl,
                GFileIOStream **iostream,
                GError        **error)
{
  gint fd;
  gchar *path;
  GFile *file;
  GFileOutputStream *output;

  g_return_val_if_fail (iostream != NULL, NULL);

  fd = g_file_open_tmp (tmpl, &path, error);
  if (fd == -1)
    return NULL;

  file = g_file_new_for_path (path);

  output = _g_local_file_output_stream_new (fd);
  *iostream = _g_local_file_io_stream_new (G_LOCAL_FILE_OUTPUT_STREAM (output));

  g_object_unref (output);
  g_free (path);

  return file;
}

Project: glib
File: gfile.c

g_file_real_make_directory_finish (GFile         *file,
                                   GAsyncResult  *res,
                                   GError       **error)
{
  g_return_val_if_fail (g_task_is_valid (res, file), FALSE);

  return g_task_propagate_boolean (G_TASK (res), error);
}

Project: glib
File: gfile.c

load_contents_close_callback (GObject      *obj,
                              GAsyncResult *close_res,
                              gpointer      user_data)
{
  GInputStream *stream = G_INPUT_STREAM (obj);
  LoadContentsData *data = user_data;

  /* Ignore errors here, we're only reading anyway */
  g_input_stream_close_finish (stream, close_res, NULL);
  g_object_unref (stream);

  g_task_return_boolean (data->task, TRUE);
  g_object_unref (data->task);
}

Project: glib
File: gfile.c

g_file_create_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_async) (file,
                           flags,
                           io_priority,
                           cancellable,
                           callback,
                           user_data);
}

Project: glib
File: gfile.c

query_info_data_free (QueryInfoAsyncData *data)
{
  g_free (data->attributes);
  g_free (data);
}

Project: glib
File: gfile.c

g_file_parse_name (const char *parse_name)
{
  g_return_val_if_fail (parse_name != NULL, NULL);

  return g_vfs_parse_name (g_vfs_get_default (), parse_name);
}

Project: glib
File: gfile.c

g_file_real_set_attributes_from_info (GFile                *file,
                                      GFileInfo            *info,
                                      GFileQueryInfoFlags   flags,
                                      GCancellable         *cancellable,
                                      GError              **error)
{
  char **attributes;
  int i;
  gboolean res;
  GFileAttributeValue *value;

  res = TRUE;

  attributes = g_file_info_list_attributes (info, NULL);

  for (i = 0; attributes[i] != NULL; i++)
    {
      value = _g_file_info_get_attribute_value (info, attributes[i]);

      if (value->status != G_FILE_ATTRIBUTE_STATUS_UNSET)
        continue;

      if (!g_file_set_attribute (file, attributes[i],
                                 value->type, _g_file_attribute_value_peek_as_pointer (value),
                                 flags, cancellable, error))
        {
          value->status = G_FILE_ATTRIBUTE_STATUS_ERROR_SETTING;
          res = FALSE;
          /* Don't set error multiple times */
          error = NULL;
        }
      else
        value->status = G_FILE_ATTRIBUTE_STATUS_SET;
    }

  g_strfreev (attributes);

  return res;
}

Project: glib
File: gfile.c

g_file_load_bytes (GFile         *file,
                   GCancellable  *cancellable,
                   gchar        **etag_out,
                   GError       **error)
{
  gchar *contents;
  gsize len;

  g_return_val_if_fail (G_IS_FILE (file), NULL);
  g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
  g_return_val_if_fail (error == NULL || *error == NULL, NULL);

  if (etag_out != NULL)
    *etag_out = NULL;

  if (g_file_has_uri_scheme (file, "resource"))
    {
      GBytes *bytes;
      gchar *uri, *unescaped;

      uri = g_file_get_uri (file);
      unescaped = g_uri_unescape_string (uri + strlen ("resource://"), NULL);
      g_free (uri);

      bytes = g_resources_lookup_data (unescaped, G_RESOURCE_LOOKUP_FLAGS_NONE, error);
      g_free (unescaped);

      return bytes;
    }

  /* contents is guaranteed to be \0 terminated */
  if (g_file_load_contents (file, cancellable, &contents, &len, etag_out, error))
    return g_bytes_new_take (g_steal_pointer (&contents), len);

  return NULL;
}

Project: glib
File: gfile.c

g_file_enumerate_children_async (GFile               *file,
                                 const char          *attributes,
                                 GFileQueryInfoFlags  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->enumerate_children_async) (file,
                                       attributes,
                                       flags,
                                       io_priority,
                                       cancellable,
                                       callback,
                                       user_data);
}

Project: glib
File: gfile.c

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_async_result_legacy_propagate_error (result, error))
    return FALSE;
  else if (g_async_result_is_tagged (result, g_file_start_mountable))
    return g_task_propagate_boolean (G_TASK (result), error);

  iface = G_FILE_GET_IFACE (file);
  return (* iface->start_mountable_finish) (file, result, error);
}

Project: glib
File: gfile.c

g_file_get_basename (GFile *file)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (file), NULL);

  iface = G_FILE_GET_IFACE (file);

  return (* iface->get_basename) (file);
}

Project: glib
File: gfile.c

g_file_measure_disk_usage_async (GFile                        *file,
                                 GFileMeasureFlags             flags,
                                 gint                          io_priority,
                                 GCancellable                 *cancellable,
                                 GFileMeasureProgressCallback  progress_callback,
                                 gpointer                      progress_data,
                                 GAsyncReadyCallback           callback,
                                 gpointer                      user_data)
{
  g_return_if_fail (G_IS_FILE (file));
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));

  G_FILE_GET_IFACE (file)->measure_disk_usage_async (file, flags, io_priority, cancellable,
                                                     progress_callback, progress_data,
                                                     callback, user_data);
}

Project: glib
File: gfile.c

find_enclosing_mount_async_thread (GTask        *task,
                                   gpointer      object,
                                   gpointer      task_data,
                                   GCancellable *cancellable)
{
  GError *error = NULL;
  GMount *mount;

  mount = g_file_find_enclosing_mount (G_FILE (object), cancellable, &error);

  if (mount == NULL)
    g_task_return_error (task, error);
  else
    g_task_return_pointer (task, mount, g_object_unref);
}

Project: glib
File: gfile.c

new_for_cmdline_arg (const gchar *arg,
                     const gchar *cwd)
{
  GFile *file;
  char *filename;

  if (g_path_is_absolute (arg))
    return g_file_new_for_path (arg);

  if (has_valid_scheme (arg))
    return g_file_new_for_uri (arg);

  if (cwd == NULL)
    {
      char *current_dir;

      current_dir = g_get_current_dir ();
      filename = g_build_filename (current_dir, arg, NULL);
      g_free (current_dir);
    }
  else
    filename = g_build_filename (cwd, arg, NULL);

  file = g_file_new_for_path (filename);
  g_free (filename);

  return file;
}

Project: glib
File: gfile.c

btrfs_reflink_with_progress (GInputStream           *in,
                             GOutputStream          *out,
                             GFileInfo              *info,
                             GCancellable           *cancellable,
                             GFileProgressCallback   progress_callback,
                             gpointer                progress_callback_data,
                             GError                **error)
{
  goffset source_size;
  int fd_in, fd_out;
  int ret, errsv;

  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 (progress_callback)
    source_size = g_file_info_get_size (info);

  /* Btrfs clone ioctl properties:
   *  - Works at the inode level
   *  - Doesn't work with directories
   *  - Always follows symlinks (source and destination)
   *
   * By the time we get here, *in and *out are both regular files */
  ret = ioctl (fd_out, BTRFS_IOC_CLONE, fd_in);
  errsv = errno;

  if (ret < 0)
    {
      if (errsv == EXDEV)
	g_set_error_literal (error, G_IO_ERROR,
			     G_IO_ERROR_NOT_SUPPORTED,
			     _("Copy (reflink/clone) between mounts is not supported"));
      else if (errsv == EINVAL)
	g_set_error_literal (error, G_IO_ERROR,
			     G_IO_ERROR_NOT_SUPPORTED,
			     _("Copy (reflink/clone) is not supported or invalid"));
      else
	/* Most probably something odd happened; retry with fallback */
	g_set_error_literal (error, G_IO_ERROR,
			     G_IO_ERROR_NOT_SUPPORTED,
			     _("Copy (reflink/clone) is not supported or didn’t work"));
      /* We retry with fallback for all error cases because Btrfs is currently
       * unstable, and so we can't trust it to do clone properly.
       * In addition, any hard errors here would cause the same failure in the
       * fallback manual copy as well. */
      return FALSE;
    }

  /* Make sure we send full copied size */
  if (progress_callback)
    progress_callback (source_size, source_size, progress_callback_data);

  return TRUE;
}

Project: glib
File: gfile.c

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_async_result_legacy_propagate_error (res, error))
    return NULL;

  iface = G_FILE_GET_IFACE (file);
  return (* iface->replace_readwrite_finish) (file, res, error);
}

Project: glib
File: gfile.c

g_file_new_for_commandline_arg (const char *arg)
{
  g_return_val_if_fail (arg != NULL, NULL);

  return new_for_cmdline_arg (arg, NULL);
}

Project: glib
File: gfile.c

g_file_hash (gconstpointer file)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (file), 0);

  iface = G_FILE_GET_IFACE (file);

  return (* iface->hash) ((GFile *)file);
}

Project: glib
File: gfile.c

g_file_get_parse_name (GFile *file)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (file), NULL);

  iface = G_FILE_GET_IFACE (file);

  return (* iface->get_parse_name) (file);
}

Project: glib
File: gfile.c

replace_rw_async_data_free (ReplaceRWAsyncData *data)
{
  g_free (data->etag);
  g_free (data);
}

Project: glib
File: gfile.c

g_file_load_partial_contents_finish (GFile         *file,
                                     GAsyncResult  *res,
                                     char         **contents,
                                     gsize         *length,
                                     char         **etag_out,
                                     GError       **error)
{
  GTask *task;
  LoadContentsData *data;

  g_return_val_if_fail (G_IS_FILE (file), FALSE);
  g_return_val_if_fail (g_task_is_valid (res, file), FALSE);
  g_return_val_if_fail (contents != NULL, FALSE);

  task = G_TASK (res);

  if (!g_task_propagate_boolean (task, error))
    {
      if (length)
        *length = 0;
      return FALSE;
    }

  data = g_task_get_task_data (task);

  if (length)
    *length = data->pos;

  if (etag_out)
    {
      *etag_out = data->etag;
      data->etag = NULL;
    }

  /* Zero terminate */
  g_byte_array_set_size (data->content, data->pos + 1);
  data->content->data[data->pos] = 0;

  *contents = (char *)g_byte_array_free (data->content, FALSE);
  data->content = NULL;

  return TRUE;
}

Project: glib
File: gfile.c

g_file_create_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_async_result_legacy_propagate_error (res, error))
    return NULL;

  iface = G_FILE_GET_IFACE (file);
  return (* iface->create_finish) (file, res, error);
}

Project: glib
File: gfile.c

do_splice (int     fd_in,
           loff_t *off_in,
           int     fd_out,
           loff_t *off_out,
           size_t  len,
           long   *bytes_transferd,
           GError **error)
{
  long result;

retry:
  result = splice (fd_in, off_in, fd_out, off_out, len, SPLICE_F_MORE);

  if (result == -1)
    {
      int errsv = errno;

      if (errsv == EINTR)
        goto retry;
      else if (errsv == ENOSYS || errsv == EINVAL || errsv == EOPNOTSUPP)
        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;
}

Project: glib
File: gfile.c

g_file_find_enclosing_mount (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->find_enclosing_mount == NULL)
    {

      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);
}

Project: glib
File: gfile.c

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);
}

Project: glib
File: gfile.c

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 & ~G_FILE_MONITOR_WATCH_HARD_LINKS,
                                     cancellable, error);
  else
    return g_file_monitor_file (file, flags, cancellable, error);
}

Project: glib
File: gfile.c

g_file_set_attribute_int64 (GFile                *file,
                            const gchar          *attribute,
                            gint64                value,
                            GFileQueryInfoFlags   flags,
                            GCancellable         *cancellable,
                            GError              **error)
{
  return g_file_set_attribute (file, attribute,
                               G_FILE_ATTRIBUTE_TYPE_INT64, &value,
                               flags, cancellable, error);
}

Project: glib
File: gfile.c

g_file_set_attribute_uint64 (GFile                *file,
                             const gchar          *attribute,
                             guint64               value,
                             GFileQueryInfoFlags   flags,
                             GCancellable         *cancellable,
                             GError              **error)
 {
  return g_file_set_attribute (file, attribute,
                               G_FILE_ATTRIBUTE_TYPE_UINT64, &value,
                               flags, cancellable, error);
}

Project: glib
File: gfile.c

g_file_real_create_async (GFile               *file,
                          GFileCreateFlags     flags,
                          int                  io_priority,
                          GCancellable        *cancellable,
                          GAsyncReadyCallback  callback,
                          gpointer             user_data)
{
  GFileCreateFlags *data;
  GTask *task;

  data = g_new0 (GFileCreateFlags, 1);
  *data = flags;

  task = g_task_new (file, cancellable, callback, user_data);
  g_task_set_source_tag (task, g_file_real_create_async);
  g_task_set_task_data (task, data, g_free);
  g_task_set_priority (task, io_priority);

  g_task_run_in_thread (task, create_async_thread);
  g_object_unref (task);
}

Project: glib
File: gfile.c

create_readwrite_async_thread (GTask        *task,
                               gpointer      object,
                               gpointer      task_data,
                               GCancellable *cancellable)
{
  GFileCreateFlags *data = task_data;
  GFileIOStream *stream;
  GError *error = NULL;

  stream = g_file_create_readwrite (G_FILE (object), *data, cancellable, &error);

  if (stream == NULL)
    g_task_return_error (task, error);
  else
    g_task_return_pointer (task, stream, g_object_unref);
}

Project: glib
File: gfile.c

open_read_async_thread (GTask         *task,
                        gpointer       object,
                        gpointer       task_data,
                        GCancellable  *cancellable)
{
  GFileInputStream *stream;
  GError *error = NULL;

  stream = g_file_read (G_FILE (object), cancellable, &error);
  if (stream)
    g_task_return_pointer (task, stream, g_object_unref);
  else
    g_task_return_error (task, error);
}

Project: glib
File: gfile.c

delete_async_thread (GTask        *task,
                     gpointer      object,
                     gpointer      task_data,
                     GCancellable *cancellable)
{
  GError *error = NULL;

  if (g_file_delete (G_FILE (object), cancellable, &error))
    g_task_return_boolean (task, TRUE);
  else
    g_task_return_error (task, error);
}

Project: glib
File: gfile.c

replace_contents_close_callback (GObject      *obj,
                                 GAsyncResult *close_res,
                                 gpointer      user_data)
{
  GOutputStream *stream = G_OUTPUT_STREAM (obj);
  ReplaceContentsData *data = user_data;

  /* Ignore errors here, we're only reading anyway */
  g_output_stream_close_finish (stream, close_res, NULL);
  g_object_unref (stream);

  if (!data->failed)
    {
      data->etag = g_file_output_stream_get_etag (G_FILE_OUTPUT_STREAM (stream));
      g_task_return_boolean (data->task, TRUE);
    }
  g_object_unref (data->task);
}

Project: glib
File: gfile.c

query_info_async_thread (GTask         *task,
                         gpointer       object,
                         gpointer       task_data,
                         GCancellable  *cancellable)
{
  QueryInfoAsyncData *data = task_data;
  GFileInfo *info;
  GError *error = NULL;

  info = g_file_query_info (G_FILE (object), data->attributes, data->flags, cancellable, &error);
  if (info)
    g_task_return_pointer (task, info, g_object_unref);
  else
    g_task_return_error (task, error);
}

Project: glib
File: gfile.c

splice_stream_with_progress (GInputStream           *in,
                             GOutputStream          *out,
                             GCancellable           *cancellable,
                             GFileProgressCallback   progress_callback,
                             gpointer                progress_callback_data,
                             GError                **error)
{
  int buffer[2] = { -1, -1 };
  int buffer_size;
  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 (!g_unix_open_pipe (buffer, FD_CLOEXEC, error))
    return FALSE;

#if defined(F_SETPIPE_SZ) && defined(F_GETPIPE_SZ)
  /* Try a 1MiB buffer for improved throughput. If that fails, use the default
   * pipe size. See: https://bugzilla.gnome.org/791457 */
  buffer_size = fcntl (buffer[1], F_SETPIPE_SZ, 1024 * 1024);
  if (buffer_size <= 0)
    {
      int errsv;
      buffer_size = fcntl (buffer[1], F_GETPIPE_SZ);
      errsv = errno;

      if (buffer_size <= 0)
        {
          g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
                       _("Error splicing file: %s"), g_strerror (errsv));
          res = FALSE;
          goto out;
        }
    }
#else
  /* If #F_GETPIPE_SZ isn’t available, assume we’re on Linux < 2.6.35,
   * but ≥ 2.6.11, meaning the pipe capacity is 64KiB. Ignore the possibility of
   * running on Linux < 2.6.11 (where the capacity was the system page size,
   * typically 4KiB) because it’s ancient. See pipe(7). */
  buffer_size = 1024 * 64;
#endif

  g_assert (buffer_size > 0);

  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, buffer_size, &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);

  if (!g_close (buffer[0], error))
    goto out;
  buffer[0] = -1;
  if (!g_close (buffer[1], error))
    goto out;
  buffer[1] = -1;
 out:
  if (buffer[0] != -1)
    (void) g_close (buffer[0], NULL);
  if (buffer[1] != -1)
    (void) g_close (buffer[1], NULL);

  return res;
}

Project: glib
File: gfile.c

g_file_load_contents_finish (GFile         *file,
                             GAsyncResult  *res,
                             char         **contents,
                             gsize         *length,
                             char         **etag_out,
                             GError       **error)
{
  return g_file_load_partial_contents_finish (file,
                                              res,
                                              contents,
                                              length,
                                              etag_out,
                                              error);
}

Project: glib
File: gfile.c

g_file_new_for_commandline_arg_and_cwd (const gchar *arg,
                                        const gchar *cwd)
{
  g_return_val_if_fail (arg != NULL, NULL);
  g_return_val_if_fail (cwd != NULL, NULL);

  return new_for_cmdline_arg (arg, cwd);
}

Project: glib
File: gfile.c

g_file_replace_contents (GFile             *file,
                         const char        *contents,
                         gsize              length,
                         const char        *etag,
                         gboolean           make_backup,
                         GFileCreateFlags   flags,
                         char             **new_etag,
                         GCancellable      *cancellable,
                         GError           **error)
{
  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);

  out = g_file_replace (file, etag, make_backup, flags, cancellable, error);
  if (out == NULL)
    return FALSE;

  pos = 0;
  remainder = length;
  while (remainder > 0 &&
         (res = g_output_stream_write (G_OUTPUT_STREAM (out),
                                       contents + pos,
                                       MIN (remainder, GET_CONTENT_BLOCK_SIZE),
                                       cancellable,
                                       error)) > 0)
    {
      pos += res;
      remainder -= res;
    }

  if (remainder > 0 && res < 0)
    {
      /* Ignore errors on close */
      g_output_stream_close (G_OUTPUT_STREAM (out), cancellable, NULL);
      g_object_unref (out);

      /* error is set already */
      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);

  g_object_unref (out);

  return ret;
}

Project: glib
File: gfile.c

g_file_load_contents_async (GFile               *file,
                           GCancellable        *cancellable,
                           GAsyncReadyCallback  callback,
                           gpointer             user_data)
{
  g_file_load_partial_contents_async (file,
                                      cancellable,
                                      NULL,
                                      callback, user_data);
}

Project: glib
File: gfile.c

g_file_new_build_filename (const gchar *first_element,
                           ...)
{
  gchar *str;
  GFile *file;
  va_list args;

  g_return_val_if_fail (first_element != NULL, NULL);

  va_start (args, first_element);
  str = g_build_filename_valist (first_element, &args);
  va_end (args);

  file = g_file_new_for_path (str);
  g_free (str);

  return file;
}

Project: glib
File: gfile.c

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);
}

Project: glib
File: gfile.c

g_file_has_prefix (GFile *file,
                   GFile *prefix)
{
  GFileIface *iface;

  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 (file) != G_TYPE_FROM_INSTANCE (prefix))
    return FALSE;

  iface = G_FILE_GET_IFACE (file);

  /* The vtable function differs in arg order since
   * we're using the old contains_file call
   */
  return (* iface->prefix_matches) (prefix, file);
}

Project: glib
File: gfile.c

g_file_real_read_async (GFile               *file,
                        int                  io_priority,
                        GCancellable        *cancellable,
                        GAsyncReadyCallback  callback,
                        gpointer             user_data)
{
  GTask *task;

  task = g_task_new (file, cancellable, callback, user_data);
  g_task_set_source_tag (task, g_file_real_read_async);
  g_task_set_priority (task, io_priority);
  g_task_run_in_thread (task, open_read_async_thread);
  g_object_unref (task);
}

Project: glib
File: gfile.c

g_file_real_make_directory_async (GFile               *file,
                                  int                  io_priority,
                                  GCancellable        *cancellable,
                                  GAsyncReadyCallback  callback,
                                  gpointer             user_data)
{
  GTask *task;

  task = g_task_new (file, cancellable, callback, user_data);
  g_task_set_source_tag (task, g_file_real_make_directory_async);
  g_task_set_priority (task, io_priority);
  g_task_run_in_thread (task, make_directory_async_thread);
  g_object_unref (task);
}

Project: glib
File: gfile.c

load_contents_data_free (LoadContentsData *data)
{
  if (data->content)
    g_byte_array_free (data->content, TRUE);
  g_free (data->etag);
  g_free (data);
}

Project: glib
File: gfile.c

load_contents_open_callback (GObject      *obj,
                             GAsyncResult *open_res,
                             gpointer      user_data)
{
  GFile *file = G_FILE (obj);
  GFileInputStream *stream;
  LoadContentsData *data = user_data;
  GError *error = NULL;

  stream = g_file_read_finish (file, open_res, &error);

  if (stream)
    {
      g_byte_array_set_size (data->content,
                             data->pos + GET_CONTENT_BLOCK_SIZE);
      g_input_stream_read_async (G_INPUT_STREAM (stream),
                                 data->content->data + data->pos,
                                 GET_CONTENT_BLOCK_SIZE,
                                 0,
                                 g_task_get_cancellable (data->task),
                                 load_contents_read_callback,
                                 data);
    }
  else
    {
      g_task_return_error (data->task, error);
      g_object_unref (data->task);
    }
}

Project: glib
File: gfile.c

g_file_get_path (GFile *file)
{
  GFileIface *iface;

  g_return_val_if_fail (G_IS_FILE (file), NULL);

  iface = G_FILE_GET_IFACE (file);

  return (* iface->get_path) (file);
}

Project: glib
File: gfile.c

g_file_set_attribute_int32 (GFile                *file,
                            const gchar          *attribute,
                            gint32                value,
                            GFileQueryInfoFlags   flags,
                            GCancellable         *cancellable,
                            GError              **error)
{
  return g_file_set_attribute (file, attribute,
                               G_FILE_ATTRIBUTE_TYPE_INT32, &value,
                               flags, cancellable, error);
}

Project: glib
File: gfile.c

g_file_real_find_enclosing_mount_async (GFile               *file,
                                        int                  io_priority,
                                        GCancellable        *cancellable,
                                        GAsyncReadyCallback  callback,
                                        gpointer             user_data)
{
  GTask *task;

  task = g_task_new (file, cancellable, callback, user_data);
  g_task_set_source_tag (task, g_file_real_find_enclosing_mount_async);
  g_task_set_priority (task, io_priority);

  g_task_run_in_thread (task, find_enclosing_mount_async_thread);
  g_object_unref (task);
}

Project: glib
File: gfile.c

g_file_real_open_readwrite_async (GFile               *file,
                                  int                  io_priority,
                                  GCancellable        *cancellable,
                                  GAsyncReadyCallback  callback,
                                  gpointer             user_data)
{
  GTask *task;

  task = g_task_new (file, cancellable, callback, user_data);
  g_task_set_source_tag (task, g_file_real_open_readwrite_async);
  g_task_set_priority (task, io_priority);

  g_task_run_in_thread (task, open_readwrite_async_thread);
  g_object_unref (task);
}

Project: glib
File: gfile.c

g_file_query_info_async (GFile               *file,
                         const char          *attributes,
                         GFileQueryInfoFlags  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->query_info_async) (file,
                               attributes,
                               flags,
                               io_priority,
                               cancellable,
                               callback,
                               user_data);
}

Project: glib
File: gfile.c

has_valid_scheme (const char *uri)
{
  const char *p;

  p = uri;

  if (!g_ascii_isalpha (*p))
    return FALSE;

  do {
    p++;
  } while (is_valid_scheme_character (*p));

  return *p == ':';
}

Project: glib
File: gfile.c

measure_disk_usage_thread (GTask        *task,
                           gpointer      source_object,
                           gpointer      task_data,
                           GCancellable *cancellable)
{
  MeasureTaskData *data = task_data;
  GError *error = NULL;
  MeasureResult result = { 0, };

  if (g_file_measure_disk_usage (source_object, data->flags, cancellable,
                                 data->progress_callback ? measure_disk_usage_progress : NULL, task,
                                 &result.disk_usage, &result.num_dirs, &result.num_files,
                                 &error))
    g_task_return_pointer (task, g_memdup (&result, sizeof result), g_free);
  else
    g_task_return_error (task, error);
}

Project: glib
File: gfile.c

g_file_real_create_readwrite_async (GFile               *file,
                                    GFileCreateFlags     flags,
                                    int                  io_priority,
                                    GCancellable        *cancellable,
                                    GAsyncReadyCallback  callback,
                                    gpointer             user_data)
{
  GFileCreateFlags *data;
  GTask *task;

  data = g_new0 (GFileCreateFlags, 1);
  *data = flags;

  task = g_task_new (file, cancellable, callback, user_data);
  g_task_set_source_tag (task, g_file_real_create_readwrite_async);
  g_task_set_task_data (task, data, g_free);
  g_task_set_priority (task, io_priority);

  g_task_run_in_thread (task, create_readwrite_async_thread);
  g_object_unref (task);
}

Project: glib
File: gfile.c

g_file_make_directory_with_parents (GFile         *file,
                                    GCancellable  *cancellable,
                                    GError       **error)
{
  GFile *work_file = NULL;
  GList *list = NULL, *l;
  GError *my_error = NULL;

  g_return_val_if_fail (G_IS_FILE (file), FALSE);

  if (g_cancellable_set_error_if_cancelled (cancellable, error))
    return FALSE;

  /* Try for the simple case of not having to create any parent
   * directories.  If any parent directory needs to be created, this
   * call will fail with NOT_FOUND. If that happens, then that value of
   * my_error persists into the while loop below.
   */
  g_file_make_directory (file, cancellable, &my_error);
  if (!g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
    {
      if (my_error)
        g_propagate_error (error, my_error);
      return my_error == NULL;
    }

  work_file = g_object_ref (file);

  /* Creates the parent directories as needed. In case any particular
   * creation operation fails for lack of other parent directories
   * (NOT_FOUND), the directory is added to a list of directories to
   * create later, and the value of my_error is retained until the next
   * iteration of the loop.  After the loop my_error should either be
   * empty or contain a real failure condition.
   */
  while (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
    {
      GFile *parent_file;

      parent_file = g_file_get_parent (work_file);
      if (parent_file == NULL)
        break;

      g_clear_error (&my_error);
      g_file_make_directory (parent_file, cancellable, &my_error);
      /* Another process may have created the directory in between the
       * G_IO_ERROR_NOT_FOUND and now
       */
      if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_EXISTS))
        g_clear_error (&my_error);

      g_object_unref (work_file);
      work_file = g_object_ref (parent_file);

      if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
        list = g_list_prepend (list, parent_file);  /* Transfer ownership of ref */
      else
        g_object_unref (parent_file);
    }

  /* All directories should be able to be created now, so an error at
   * this point means the whole operation must fail -- except an EXISTS
   * error, which means that another process already created the
   * directory in between the previous failure and now.
   */
  for (l = list; my_error == NULL && l; l = l->next)
    {
      g_file_make_directory ((GFile *) l->data, cancellable, &my_error);
      if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_EXISTS))
        g_clear_error (&my_error);
    }

  if (work_file)
    g_object_unref (work_file);

  /* Clean up */
  while (list != NULL)
    {
      g_object_unref ((GFile *) list->data);
      list = g_list_remove (list, list->data);
    }

  /* At this point an error in my_error means a that something
   * unexpected failed in either of the loops above, so the whole
   * operation must fail.
   */
  if (my_error != NULL)
    {
      g_propagate_error (error, my_error);
      return FALSE;
    }

  return g_file_make_directory (file, cancellable, error);
}

Project: glib
File: gfile.c

replace_async_thread (GTask         *task,
                      gpointer       source_object,
                      gpointer       task_data,
                      GCancellable  *cancellable)
{
  GFileOutputStream *stream;
  ReplaceAsyncData *data = task_data;
  GError *error = NULL;

  stream = g_file_replace (G_FILE (source_object),
                           data->etag,
                           data->make_backup,
                           data->flags,
                           cancellable,
                           &error);

  if (stream)
    g_task_return_pointer (task, stream, g_object_unref);
  else
    g_task_return_error (task, error);
}

Project: glib
File: gfile.c

g_file_real_set_display_name_async (GFile               *file,
                                    const char          *display_name,
                                    int                  io_priority,
                                    GCancellable        *cancellable,
                                    GAsyncReadyCallback  callback,
                                    gpointer             user_data)
{
  GTask *task;

  task = g_task_new (file, cancellable, callback, user_data);
  g_task_set_source_tag (task, g_file_real_set_display_name_async);
  g_task_set_task_data (task, g_strdup (display_name), g_free);
  g_task_set_priority (task, io_priority);

  g_task_run_in_thread (task, set_display_name_async_thread);
  g_object_unref (task);
}

Project: glib
File: gfile.c

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;
}

Project: glib
File: gfile.c

g_file_real_measure_disk_usage (GFile                         *file,
                                GFileMeasureFlags              flags,
                                GCancellable                  *cancellable,
                                GFileMeasureProgressCallback   progress_callback,
                                gpointer                       progress_data,
                                guint64                       *disk_usage,
                                guint64                       *num_dirs,
                                guint64                       *num_files,
                                GError                       **error)
{
  g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
                       "Operation not supported for the current backend.");
  return FALSE;
}

Project: glib
File: gfile.c

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_async_result_legacy_propagate_error (res, error))
    return NULL;

  iface = G_FILE_GET_IFACE (file);
  return (* iface->create_readwrite_finish) (file, res, error);
}

Project: glib
File: gfile.c

g_file_real_enumerate_children_finish (GFile         *file,
                                       GAsyncResult  *res,
                                       GError       **error)
{
  g_return_val_if_fail (g_task_is_valid (res, file), NULL);

  return g_task_propagate_pointer (G_TASK (res), error);
}

Project: glib
File: gfile.c

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_async_result_legacy_propagate_error (result, error))
    return FALSE;
  else if (g_async_result_is_tagged (result, g_file_stop_mountable))
    return g_task_propagate_boolean (G_TASK (result), error);

  iface = G_FILE_GET_IFACE (file);
  return (* iface->stop_mountable_finish) (file, result, error);
}

Project: glib
File: gfile.c

g_file_set_attributes_finish (GFile         *file,
                              GAsyncResult  *result,
                              GFileInfo    **info,
                              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);

  /* No standard handling of errors here, as we must set info even
   * on errors
   */
  iface = G_FILE_GET_IFACE (file);
  return (* iface->set_attributes_finish) (file, result, info, error);
}

Project: glib
File: gfile.c

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_task_report_new_error (file, callback, user_data,
                               g_file_eject_mountable_with_operation,
                               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);
}

Project: glib
File: gfile.c

copy_async_progress_callback (goffset  current_num_bytes,
                              goffset  total_num_bytes,
                              gpointer user_data)
{
  GTask *task = user_data;
  CopyAsyncData *data = g_task_get_task_data (task);
  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_main_context_invoke_full (g_task_get_context (task),
                              g_task_get_priority (task),
                              copy_async_progress_in_main,
                              progress,
                              g_free);
}

Project: glib
File: gfile.c

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);
}

Project: glib
File: gfile.c

g_file_make_directory_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);

  iface = G_FILE_GET_IFACE (file);
  return (* iface->make_directory_finish) (file, result, error);
}

Project: glib
File: gfile.c

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_async_result_legacy_propagate_error (res, error))
    return NULL;

  iface = G_FILE_GET_IFACE (file);
  return (* iface->find_enclosing_mount_finish) (file, res, error);
}

Project: glib
File: gfile.c

file_copy_fallback (GFile                  *source,
                    GFile                  *destination,
                    GFileCopyFlags          flags,
                    GCancellable           *cancellable,
                    GFileProgressCallback   progress_callback,
                    gpointer                progress_callback_data,
                    GError                **error)
{
  gboolean ret = FALSE;
  GFileInputStream *file_in = NULL;
  GInputStream *in = NULL;
  GOutputStream *out = NULL;
  GFileInfo *info = NULL;
  const char *target;
  char *attrs_to_read;
  gboolean do_set_attributes = FALSE;

  /* 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)
    goto out;

  /* 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))
            goto out;

          ret = TRUE;
          goto out;
        }
        /* ... else fall back on a regular file copy */
    }
  /* 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"));
      goto out;
    }

  /* Everything else should just fall back on a regular copy. */

  file_in = open_source_for_copy (source, destination, flags, cancellable, error);
  if (!file_in)
    goto out;
  in = G_INPUT_STREAM (file_in);

  if (!build_attribute_list_for_copy (destination, flags, &attrs_to_read,
                                      cancellable, error))
    goto out;

  if (attrs_to_read != NULL)
    {
      GError *tmp_error = NULL;

      /* Ok, ditch the previous lightweight info (on Unix we just
       * called lstat()); at this point we gather all the information
       * we need about the source from the opened file descriptor.
       */
      g_object_unref (info);

      info = g_file_input_stream_query_info (file_in, attrs_to_read,
                                             cancellable, &tmp_error);
      if (!info)
        {
          /* Not all gvfs backends implement query_info_on_read(), we
           * can just fall back to the pathname again.
           * https://bugzilla.gnome.org/706254
           */
          if (g_error_matches (tmp_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
            {
              g_clear_error (&tmp_error);
              info = g_file_query_info (source, attrs_to_read, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                        cancellable, error);
            }
          else
            {
              g_free (attrs_to_read);
              g_propagate_error (error, tmp_error);
              goto out;
            }
        }
      g_free (attrs_to_read);
      if (!info)
        goto out;

      do_set_attributes = TRUE;
    }

  /* In the local file path, we pass down the source info which
   * includes things like unix::mode, to ensure that the target file
   * is not created with different permissions from the source file.
   *
   * If a future API like g_file_replace_with_info() is added, switch
   * this code to use that.
   */
  if (G_IS_LOCAL_FILE (destination))
    {
      if (flags & G_FILE_COPY_OVERWRITE)
        out = (GOutputStream*)_g_local_file_output_stream_replace (_g_local_file_get_filename (G_LOCAL_FILE (destination)),
                                                                   FALSE, NULL,
                                                                   flags & G_FILE_COPY_BACKUP,
                                                                   G_FILE_CREATE_REPLACE_DESTINATION |
                                                                   G_FILE_CREATE_PRIVATE, info,
                                                                   cancellable, error);
      else
        out = (GOutputStream*)_g_local_file_output_stream_create (_g_local_file_get_filename (G_LOCAL_FILE (destination)),
                                                                  FALSE, G_FILE_CREATE_PRIVATE, info,
                                                                  cancellable, error);
    }
  else if (flags & G_FILE_COPY_OVERWRITE)
    {
      out = (GOutputStream *)g_file_replace (destination,
                                             NULL,
                                             flags & G_FILE_COPY_BACKUP,
                                             G_FILE_CREATE_REPLACE_DESTINATION |
                                             G_FILE_CREATE_PRIVATE,
                                             cancellable, error);
    }
  else
    {
      out = (GOutputStream *)g_file_create (destination, G_FILE_CREATE_PRIVATE, cancellable, error);
    }

  if (!out)
    goto out;

#ifdef __linux__
  if (G_IS_FILE_DESCRIPTOR_BASED (in) && G_IS_FILE_DESCRIPTOR_BASED (out))
    {
      GError *reflink_err = NULL;

      if (!btrfs_reflink_with_progress (in, out, info, cancellable,
                                        progress_callback, progress_callback_data,
                                        &reflink_err))
        {
          if (g_error_matches (reflink_err, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
            {
              g_clear_error (&reflink_err);
            }
          else
            {
              g_propagate_error (error, reflink_err);
              goto out;
            }
        }
      else
        {
          ret = TRUE;
          goto out;
        }
    }
#endif

#ifdef HAVE_SPLICE
  if (G_IS_FILE_DESCRIPTOR_BASED (in) && G_IS_FILE_DESCRIPTOR_BASED (out))
    {
      GError *splice_err = NULL;

      if (!splice_stream_with_progress (in, out, cancellable,
                                        progress_callback, progress_callback_data,
                                        &splice_err))
        {
          if (g_error_matches (splice_err, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
            {
              g_clear_error (&splice_err);
            }
          else
            {
              g_propagate_error (error, splice_err);
              goto out;
            }
        }
      else
        {
          ret = TRUE;
          goto out;
        }
    }

#endif

  /* A plain read/write loop */
  if (!copy_stream_with_progress (in, out, source, cancellable,
                                  progress_callback, progress_callback_data,
                                  error))
    goto out;

  ret = TRUE;
 out:
  if (in)
    {
      /* Don't care about errors in source here */
      (void) g_input_stream_close (in, cancellable, NULL);
      g_object_unref (in);
    }

  if (out)
    {
      /* But write errors on close are bad! */
      if (!g_output_stream_close (out, cancellable, ret ? error : NULL))
        ret = FALSE;
      g_object_unref (out);
    }

  /* Ignore errors here. Failure to copy metadata is not a hard error */
  /* TODO: set these attributes /before/ we do the rename() on Unix */
  if (ret && do_set_attributes)
    {
      g_file_set_attributes_from_info (destination,
                                       info,
                                       G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                       cancellable,
                                       NULL);
    }

  g_clear_object (&info);

  return ret;
}

Project: glib
File: gfile.c

make_directory_async_thread (GTask        *task,
                             gpointer      object,
                             gpointer      task_data,
                             GCancellable *cancellable)
{
  GError *error = NULL;

  if (g_file_make_directory (G_FILE (object), cancellable, &error))
    g_task_return_boolean (task, TRUE);
  else
    g_task_return_error (task, error);
}

Project: glib
File: gfile.c

file_get_target_path (GFile *file)
{
  GFileInfo *info;
  const char *target;
  char *path;

  info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI, G_FILE_QUERY_INFO_NONE, NULL, NULL);
  if (info == NULL)
    return NULL;
  target = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI);
  path = g_filename_from_uri (target, NULL, NULL);
  g_object_unref (info);

  return path;
}

Project: glib
File: gfile.c

g_file_measure_disk_usage (GFile                         *file,
                           GFileMeasureFlags              flags,
                           GCancellable                  *cancellable,
                           GFileMeasureProgressCallback   progress_callback,
                           gpointer                       progress_data,
                           guint64                       *disk_usage,
                           guint64                       *num_dirs,
                           guint64                       *num_files,
                           GError                       **error)
{
  g_return_val_if_fail (G_IS_FILE (file), FALSE);
  g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

  return G_FILE_GET_IFACE (file)->measure_disk_usage (file, flags, cancellable,
                                                      progress_callback, progress_data,
                                                      disk_usage, num_dirs, num_files,
                                                      error);
}

Project: glib
File: gfile.c

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_async_result_legacy_propagate_error (res, error))
    return NULL;

  iface = G_FILE_GET_IFACE (file);
  return (* iface->query_filesystem_info_finish) (file, res, error);
}

Project: glib
File: gfile.c

open_source_for_copy (GFile           *source,
                      GFile           *destination,
                      GFileCopyFlags   flags,
                      GCancellable    *cancellable,
                      GError         **error)
{
  GError *my_error;
  GFileInputStream *ret;
  GFileInfo *info;
  GFileType file_type;

  my_error = NULL;
  ret = g_file_read (source, cancellable, &my_error);
  if (ret != NULL)
    return ret;

  /* There was an error opening the source, try to set a good error for it: */
  if (my_error->domain == G_IO_ERROR && my_error->code == G_IO_ERROR_IS_DIRECTORY)
    {
      /* The source is a directory, don't fail with WOULD_RECURSE immediately,
       * as that is less useful to the app. Better check for errors on the
       * target instead.
       */
      g_error_free (my_error);
      my_error = NULL;

      info = g_file_query_info (destination, G_FILE_ATTRIBUTE_STANDARD_TYPE,
                                G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                cancellable, &my_error);
      if (info != NULL &&
          g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_TYPE))
        {
          file_type = g_file_info_get_file_type (info);
          g_object_unref (info);

          if (flags & G_FILE_COPY_OVERWRITE)
            {
              if (file_type == G_FILE_TYPE_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_literal (error, G_IO_ERROR, G_IO_ERROR_EXISTS,
                                   _("Target file exists"));
              return NULL;
            }
        }
      else
        {
          /* Error getting info from target, return that error
           * (except for NOT_FOUND, which is no error here)
           */
          g_clear_object (&info);
          if (my_error != NULL && !g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
            {
              g_propagate_error (error, my_error);
              return NULL;
            }
          g_clear_error (&my_error);
        }

      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_RECURSE,
                           _("Can’t recursively copy directory"));
      return NULL;
    }

  g_propagate_error (error, my_error);
  return NULL;
}

Project: glib
File: gfile.c

g_file_peek_path (GFile *file)
{
  if (G_IS_LOCAL_FILE (file))
    return _g_local_file_get_filename ((GLocalFile *) file);
  return file_peek_path_generic (file);
}

Project: glib
File: gfile.c

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;
}

Project: glib
File: gfile.c

g_file_replace_contents_finish (GFile         *file,
                                GAsyncResult  *res,
                                char         **new_etag,
                                GError       **error)
{
  GTask *task;
  ReplaceContentsData *data;

  g_return_val_if_fail (G_IS_FILE (file), FALSE);
  g_return_val_if_fail (g_task_is_valid (res, file), FALSE);

  task = G_TASK (res);

  if (!g_task_propagate_boolean (task, error))
    return FALSE;

  data = g_task_get_task_data (task);

  if (new_etag)
    {
      *new_etag = data->etag;
      data->etag = NULL; /* Take ownership */
    }

  return TRUE;
}

Project: glib
File: gfile.c

measure_disk_usage_progress (gboolean reporting,
                             guint64  current_size,
                             guint64  num_dirs,
                             guint64  num_files,
                             gpointer user_data)
{
  MeasureProgress progress;
  GTask *task = user_data;
  MeasureTaskData *data;

  data = g_task_get_task_data (task);

  progress.callback = data->progress_callback;
  progress.user_data = data->progress_data;
  progress.reporting = reporting;
  progress.current_size = current_size;
  progress.num_dirs = num_dirs;
  progress.num_files = num_files;

  g_main_context_invoke_full (g_task_get_context (task),
                              g_task_get_priority (task),
                              measure_disk_usage_invoke_progress,
                              g_memdup (&progress, sizeof progress),
                              g_free);
}

Project: glib
File: gfile.c

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;
}

Project: glib
File: gfile.c

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_task_report_new_error (file, callback, user_data,
                               g_file_poll_mountable,
                               G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
                               _("Operation not supported"));
      return;
    }

  (* iface->poll_mountable) (file,
                             cancellable,
                             callback,
                             user_data);
}

Project: glib
File: gfile.c

g_file_replace (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 == NULL)
    {
      g_set_error_literal (error, G_IO_ERROR,
                           G_IO_ERROR_NOT_SUPPORTED,
                           _("Operation not supported"));
      return NULL;
    }

  /* Handle empty tag string as NULL in consistent way. */
  if (etag && *etag == 0)
    etag = NULL;

  return (* iface->replace) (file, etag, make_backup, flags, cancellable, error);
}

Project: glib
File: gfile.c

g_file_enumerate_children_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_async_result_legacy_propagate_error (res, error))
    return NULL;

  iface = G_FILE_GET_IFACE (file);
  return (* iface->enumerate_children_finish) (file, res, error);
}

Project: glib
File: gfile.c

g_file_make_directory_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->make_directory_async) (file,
                                   io_priority,
                                   cancellable,
                                   callback,
                                   user_data);
}

Project: glib
File: gfile.c

g_file_trash_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->trash_async) (file,
                          io_priority,
                          cancellable,
                          callback,
                          user_data);
}

Project: glib
File: gfile.c

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);
}

Project: glib
File: gfile.c

build_attribute_list_for_copy (GFile                  *file,
                               GFileCopyFlags          flags,
                               char                  **out_attributes,
                               GCancellable           *cancellable,
                               GError                **error)
{
  gboolean ret = FALSE;
  GFileAttributeInfoList *attributes = NULL, *namespaces = NULL;
  GString *s = NULL;
  gboolean first;
  int i;
  gboolean copy_all_attributes;
  gboolean skip_perms;

  copy_all_attributes = flags & G_FILE_COPY_ALL_METADATA;
  skip_perms = (flags & G_FILE_COPY_TARGET_DEFAULT_PERMS) != 0;

  /* Ignore errors here, if the target supports no attributes there is
   * nothing to copy.  We still honor the cancellable though.
   */
  attributes = g_file_query_settable_attributes (file, cancellable, NULL);
  if (g_cancellable_set_error_if_cancelled (cancellable, error))
    goto out;

  namespaces = g_file_query_writable_namespaces (file, cancellable, NULL);
  if (g_cancellable_set_error_if_cancelled (cancellable, error))
    goto out;

  if (attributes == NULL && namespaces == NULL)
    goto out;

  first = TRUE;
  s = g_string_new ("");

  if (attributes)
    {
      for (i = 0; i < attributes->n_infos; i++)
        {
          if (should_copy (&attributes->infos[i], copy_all_attributes, skip_perms))
            {
              if (first)
                first = FALSE;
              else
                g_string_append_c (s, ',');

              g_string_append (s, attributes->infos[i].name);
            }
        }
    }

  if (namespaces)
    {
      for (i = 0; i < namespaces->n_infos; i++)
        {
          if (should_copy (&namespaces->infos[i], copy_all_attributes, FALSE))
            {
              if (first)
                first = FALSE;
              else
                g_string_append_c (s, ',');

              g_string_append (s, namespaces->infos[i].name);
              g_string_append (s, "::*");
            }
        }
    }

  ret = TRUE;
  *out_attributes = g_string_free (s, FALSE);
  s = NULL;
 out:
  if (s)
    g_string_free (s, TRUE);
  if (attributes)
    g_file_attribute_info_list_unref (attributes);
  if (namespaces)
    g_file_attribute_info_list_unref (namespaces);
  
  return ret;
}

Project: glib
File: gfile.c

g_file_eject_mountable (GFile               *file,
                        GMountUnmountFlags   flags,
                        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)
    {
      g_task_report_new_error (file, callback, user_data,
                               g_file_eject_mountable_with_operation,
                               G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
                               _("Operation not supported"));
      return;
    }

  (* iface->eject_mountable) (file,
                              flags,
                              cancellable,
                              callback,
                              user_data);
}

Project: glib
File: gfile.c

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;
}

Project: glib
File: gfile.c

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)
{
  GTask *task;
  ReplaceRWAsyncData *data;

  data = g_new0 (ReplaceRWAsyncData, 1);
  data->etag = g_strdup (etag);
  data->make_backup = make_backup;
  data->flags = flags;

  task = g_task_new (file, cancellable, callback, user_data);
  g_task_set_source_tag (task, g_file_real_replace_readwrite_async);
  g_task_set_task_data (task, data, (GDestroyNotify)replace_rw_async_data_free);
  g_task_set_priority (task, io_priority);

  g_task_run_in_thread (task, replace_readwrite_async_thread);
  g_object_unref (task);
}

Project: glib
File: gfile.c

g_file_real_query_filesystem_info_async (GFile               *file,
                                         const char          *attributes,
                                         int                  io_priority,
                                         GCancellable        *cancellable,
                                         GAsyncReadyCallback  callback,
                                         gpointer             user_data)
{
  GTask *task;

  task = g_task_new (file, cancellable, callback, user_data);
  g_task_set_source_tag (task, g_file_real_query_filesystem_info_async);
  g_task_set_task_data (task, g_strdup (attributes), g_free);
  g_task_set_priority (task, io_priority);
  g_task_run_in_thread (task, query_filesystem_info_async_thread);
  g_object_unref (task);
}