+gboolean
+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;
+}
+
+typedef struct
+{
+ GFileMeasureFlags flags;
+ GFileMeasureProgressCallback progress_callback;
+ gpointer progress_data;
+} MeasureTaskData;
+
+typedef struct
+{
+ guint64 disk_usage;
+ guint64 num_dirs;
+ guint64 num_files;
+} MeasureResult;
+
+typedef struct
+{
+ GFileMeasureProgressCallback callback;
+ gpointer user_data;
+ gboolean reporting;
+ guint64 current_size;
+ guint64 num_dirs;
+ guint64 num_files;
+} MeasureProgress;
+
+static gboolean
+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;
+}
+
+static void
+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);
+}
+
+static void
+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);
+}
+
+static void
+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_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);
+}
+
+static gboolean
+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;
+}
+
+/**
+ * g_file_measure_disk_usage:
+ * @file: a #GFile
+ * @flags: #GFileMeasureFlags
+ * @cancellable: (allow-none): optional #GCancellable
+ * @progress_callback: (allow-none): a #GFileMeasureProgressCallback
+ * @progress_data: user_data for @progress_callback
+ * @disk_usage: (allow-none) (out): the number of bytes of disk space used
+ * @num_dirs: (allow-none) (out): the number of directories encountered
+ * @num_files: (allow-none) (out): the number of non-directories encountered
+ * @error: (allow-none): %NULL, or a pointer to a %NULL #GError pointer
+ *
+ * Recursively measures the disk usage of @file.
+ *
+ * This is essentially an analog of the 'du' command, but it also
+ * reports the number of directories and non-directory files encountered
+ * (including things like symbolic links).
+ *
+ * By default, errors are only reported against the toplevel file
+ * itself. Errors found while recursing are silently ignored, unless
+ * %G_FILE_DISK_USAGE_REPORT_ALL_ERRORS is given in @flags.
+ *
+ * The returned size, @disk_usage, is in bytes and should be formatted
+ * with g_format_size() in order to get something reasonable for showing
+ * in a user interface.
+ *
+ * @progress_callback and @progress_data can be given to request
+ * periodic progress updates while scanning. See the documentation for
+ * #GFileMeasureProgressCallback for information about when and how the
+ * callback will be invoked.
+ *
+ * Returns: %TRUE if successful, with the out parameters set.
+ * %FALSE otherwise, with @error set.
+ *
+ * Since: 2.38
+ **/
+gboolean
+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);
+}
+
+/**
+ * g_file_measure_disk_usage_async:
+ * @file: a #GFile
+ * @flags: #GFileMeasureFlags
+ * @io_priority: the [I/O priority][io-priority] of the request
+ * @cancellable: (allow-none): optional #GCancellable
+ * @progress_callback: (allow-none): a #GFileMeasureProgressCallback
+ * @progress_data: user_data for @progress_callback
+ * @callback: (allow-none): a #GAsyncReadyCallback to call when complete
+ * @user_data: the data to pass to callback function
+ *
+ * Recursively measures the disk usage of @file.
+ *
+ * This is the asynchronous version of g_file_measure_disk_usage(). See
+ * there for more information.
+ *
+ * Since: 2.38
+ **/
+void
+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);
+}
+
+/**
+ * g_file_measure_disk_usage_finish:
+ * @file: a #GFile
+ * @result: the #GAsyncResult passed to your #GAsyncReadyCallback
+ * @disk_usage: (allow-none) (out): the number of bytes of disk space used
+ * @num_dirs: (allow-none) (out): the number of directories encountered
+ * @num_files: (allow-none) (out): the number of non-directories encountered
+ * @error: (allow-none): %NULL, or a pointer to a %NULL #GError pointer
+ *
+ * Collects the results from an earlier call to
+ * g_file_measure_disk_usage_async(). See g_file_measure_disk_usage() for
+ * more information.
+ *
+ * Returns: %TRUE if successful, with the out parameters set.
+ * %FALSE otherwise, with @error set.
+ *
+ * Since: 2.38
+ **/
+gboolean
+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);
+}
+
+/**
+ * g_file_start_mountable:
+ * @file: input #GFile
+ * @flags: flags affecting the operation
+ * @start_operation: (allow-none): a #GMountOperation, or %NULL to avoid user interaction
+ * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore
+ * @callback: (allow-none): a #GAsyncReadyCallback to call when the request is satisfied, or %NULL
+ * @user_data: the data to pass to callback function
+ *
+ * Starts a file of type #G_FILE_TYPE_MOUNTABLE.
+ * Using @start_operation, you can request callbacks when, for instance,
+ * passwords are needed during authentication.
+ *
+ * If @cancellable is not %NULL, then the operation can be cancelled by
+ * triggering the cancellable object from another thread. If the operation
+ * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
+ *
+ * When the operation is finished, @callback will be called.
+ * You can then call g_file_mount_mountable_finish() to get
+ * the result of the operation.
+ *
+ * Since: 2.22
+ */
+void
+g_file_start_mountable (GFile *file,
+ GDriveStartFlags flags,
+ GMountOperation *start_operation,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GFileIface *iface;
+
+ g_return_if_fail (G_IS_FILE (file));
+
+ iface = G_FILE_GET_IFACE (file);
+
+ if (iface->start_mountable == NULL)
+ {
+ g_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);
+}
+
+/**
+ * g_file_start_mountable_finish:
+ * @file: input #GFile
+ * @result: a #GAsyncResult
+ * @error: a #GError, or %NULL
+ *
+ * Finishes a start operation. See g_file_start_mountable() for details.
+ *
+ * Finish an asynchronous start operation that was started
+ * with g_file_start_mountable().
+ *
+ * Returns: %TRUE if the operation finished successfully. %FALSE
+ * otherwise.
+ *
+ * Since: 2.22
+ */
+gboolean
+g_file_start_mountable_finish (GFile *file,
+ GAsyncResult *result,
+ GError **error)
+{
+ GFileIface *iface;
+
+ g_return_val_if_fail (G_IS_FILE (file), FALSE);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+ if (g_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);
+}
+
+/**
+ * g_file_stop_mountable:
+ * @file: input #GFile
+ * @flags: flags affecting the operation
+ * @mount_operation: (allow-none): a #GMountOperation,
+ * or %NULL to avoid user interaction.
+ * @cancellable: (allow-none): optional #GCancellable object,
+ * %NULL to ignore
+ * @callback: (allow-none): a #GAsyncReadyCallback to call
+ * when the request is satisfied, or %NULL
+ * @user_data: the data to pass to callback function
+ *
+ * Stops a file of type #G_FILE_TYPE_MOUNTABLE.
+ *
+ * If @cancellable is not %NULL, then the operation can be cancelled by
+ * triggering the cancellable object from another thread. If the operation
+ * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
+ *
+ * When the operation is finished, @callback will be called.
+ * You can then call g_file_stop_mountable_finish() to get
+ * the result of the operation.
+ *
+ * Since: 2.22
+ */
+void
+g_file_stop_mountable (GFile *file,
+ GMountUnmountFlags flags,
+ GMountOperation *mount_operation,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GFileIface *iface;
+
+ g_return_if_fail (G_IS_FILE (file));
+
+ iface = G_FILE_GET_IFACE (file);
+
+ if (iface->stop_mountable == NULL)
+ {
+ g_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);
+}
+
+/**
+ * g_file_stop_mountable_finish:
+ * @file: input #GFile
+ * @result: a #GAsyncResult
+ * @error: a #GError, or %NULL
+ *
+ * Finishes an stop operation, see g_file_stop_mountable() for details.
+ *
+ * Finish an asynchronous stop operation that was started
+ * with g_file_stop_mountable().
+ *
+ * Returns: %TRUE if the operation finished successfully.
+ * %FALSE otherwise.
+ *
+ * Since: 2.22
+ */
+gboolean
+g_file_stop_mountable_finish (GFile *file,
+ GAsyncResult *result,
+ GError **error)
+{
+ GFileIface *iface;
+
+ g_return_val_if_fail (G_IS_FILE (file), FALSE);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+ if (g_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);
+}
+
+/**
+ * g_file_poll_mountable:
+ * @file: input #GFile
+ * @cancellable: optional #GCancellable object, %NULL to ignore
+ * @callback: (allow-none): a #GAsyncReadyCallback to call
+ * when the request is satisfied, or %NULL
+ * @user_data: the data to pass to callback function
+ *
+ * Polls a file of type #G_FILE_TYPE_MOUNTABLE.
+ *
+ * If @cancellable is not %NULL, then the operation can be cancelled by
+ * triggering the cancellable object from another thread. If the operation
+ * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
+ *
+ * When the operation is finished, @callback will be called.
+ * You can then call g_file_mount_mountable_finish() to get
+ * the result of the operation.
+ *
+ * Since: 2.22
+ */
+void
+g_file_poll_mountable (GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GFileIface *iface;
+
+ g_return_if_fail (G_IS_FILE (file));
+
+ iface = G_FILE_GET_IFACE (file);
+
+ if (iface->poll_mountable == NULL)
+ {
+ g_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);
+}
+
+/**
+ * g_file_poll_mountable_finish:
+ * @file: input #GFile
+ * @result: a #GAsyncResult
+ * @error: a #GError, or %NULL
+ *
+ * Finishes a poll operation. See g_file_poll_mountable() for details.
+ *
+ * Finish an asynchronous poll operation that was polled
+ * with g_file_poll_mountable().
+ *
+ * Returns: %TRUE if the operation finished successfully. %FALSE
+ * otherwise.
+ *
+ * Since: 2.22
+ */
+gboolean
+g_file_poll_mountable_finish (GFile *file,
+ GAsyncResult *result,
+ GError **error)
+{
+ GFileIface *iface;
+
+ g_return_val_if_fail (G_IS_FILE (file), FALSE);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+ if (g_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);
+}
+
+/**
+ * g_file_supports_thread_contexts:
+ * @file: a #GFile
+ *
+ * Checks if @file supports
+ * [thread-default contexts][g-main-context-push-thread-default-context].
+ * If this returns %FALSE, you cannot perform asynchronous operations on
+ * @file in a thread that has a thread-default context.
+ *
+ * Returns: Whether or not @file supports thread-default contexts.
+ *
+ * Since: 2.22
+ */
+gboolean
+g_file_supports_thread_contexts (GFile *file)
+{
+ GFileIface *iface;
+
+ g_return_val_if_fail (G_IS_FILE (file), FALSE);
+
+ iface = G_FILE_GET_IFACE (file);
+ return iface->supports_thread_contexts;
+}