hook gvariant vectors up to kdbus
[platform/upstream/glib.git] / gio / gfileenumerator.c
1 /* GIO - GLib Input, Output and Streaming Library
2  * 
3  * Copyright (C) 2006-2007 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17  *
18  * Author: Alexander Larsson <alexl@redhat.com>
19  */
20
21 #include "config.h"
22 #include "gfileenumerator.h"
23 #include "gfile.h"
24 #include "gioscheduler.h"
25 #include "gasyncresult.h"
26 #include "gasynchelper.h"
27 #include "gioerror.h"
28 #include "glibintl.h"
29
30 struct _GFileEnumeratorPrivate {
31   /* TODO: Should be public for subclasses? */
32   GFile *container;
33   guint closed : 1;
34   guint pending : 1;
35   GAsyncReadyCallback outstanding_callback;
36   GError *outstanding_error;
37 };
38
39 /**
40  * SECTION:gfileenumerator
41  * @short_description: Enumerated Files Routines
42  * @include: gio/gio.h
43  * 
44  * #GFileEnumerator allows you to operate on a set of #GFiles, 
45  * returning a #GFileInfo structure for each file enumerated (e.g. 
46  * g_file_enumerate_children() will return a #GFileEnumerator for each 
47  * of the children within a directory).
48  *
49  * To get the next file's information from a #GFileEnumerator, use 
50  * g_file_enumerator_next_file() or its asynchronous version, 
51  * g_file_enumerator_next_files_async(). Note that the asynchronous 
52  * version will return a list of #GFileInfos, whereas the 
53  * synchronous will only return the next file in the enumerator.
54  *
55  * The ordering of returned files is unspecified for non-Unix
56  * platforms; for more information, see g_dir_read_name().  On Unix,
57  * when operating on local files, returned files will be sorted by
58  * inode number.  Effectively you can assume that the ordering of
59  * returned files will be stable between successive calls (and
60  * applications) assuming the directory is unchanged.
61  *
62  * If your application needs a specific ordering, such as by name or
63  * modification time, you will have to implement that in your
64  * application code.
65  *
66  * To close a #GFileEnumerator, use g_file_enumerator_close(), or 
67  * its asynchronous version, g_file_enumerator_close_async(). Once 
68  * a #GFileEnumerator is closed, no further actions may be performed 
69  * on it, and it should be freed with g_object_unref().
70  * 
71  **/ 
72
73 G_DEFINE_TYPE_WITH_PRIVATE (GFileEnumerator, g_file_enumerator, G_TYPE_OBJECT)
74
75 enum {
76   PROP_0,
77   PROP_CONTAINER
78 };
79
80 static void     g_file_enumerator_real_next_files_async  (GFileEnumerator      *enumerator,
81                                                           int                   num_files,
82                                                           int                   io_priority,
83                                                           GCancellable         *cancellable,
84                                                           GAsyncReadyCallback   callback,
85                                                           gpointer              user_data);
86 static GList *  g_file_enumerator_real_next_files_finish (GFileEnumerator      *enumerator,
87                                                           GAsyncResult         *res,
88                                                           GError              **error);
89 static void     g_file_enumerator_real_close_async       (GFileEnumerator      *enumerator,
90                                                           int                   io_priority,
91                                                           GCancellable         *cancellable,
92                                                           GAsyncReadyCallback   callback,
93                                                           gpointer              user_data);
94 static gboolean g_file_enumerator_real_close_finish      (GFileEnumerator      *enumerator,
95                                                           GAsyncResult         *res,
96                                                           GError              **error);
97
98 static void
99 g_file_enumerator_set_property (GObject      *object,
100                                 guint         property_id,
101                                 const GValue *value,
102                                 GParamSpec   *pspec)
103 {
104   GFileEnumerator *enumerator;
105   
106   enumerator = G_FILE_ENUMERATOR (object);
107   
108   switch (property_id) {
109   case PROP_CONTAINER:
110     enumerator->priv->container = g_value_dup_object (value);
111     break;
112   default:
113     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
114     break;
115   }
116 }
117
118 static void
119 g_file_enumerator_dispose (GObject *object)
120 {
121   GFileEnumerator *enumerator;
122
123   enumerator = G_FILE_ENUMERATOR (object);
124   
125   if (enumerator->priv->container) {
126     g_object_unref (enumerator->priv->container);
127     enumerator->priv->container = NULL;
128   }
129
130   G_OBJECT_CLASS (g_file_enumerator_parent_class)->dispose (object);
131 }
132
133 static void
134 g_file_enumerator_finalize (GObject *object)
135 {
136   GFileEnumerator *enumerator;
137
138   enumerator = G_FILE_ENUMERATOR (object);
139   
140   if (!enumerator->priv->closed)
141     g_file_enumerator_close (enumerator, NULL, NULL);
142
143   G_OBJECT_CLASS (g_file_enumerator_parent_class)->finalize (object);
144 }
145
146 static void
147 g_file_enumerator_class_init (GFileEnumeratorClass *klass)
148 {
149   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
150
151   gobject_class->set_property = g_file_enumerator_set_property;
152   gobject_class->dispose = g_file_enumerator_dispose;
153   gobject_class->finalize = g_file_enumerator_finalize;
154
155   klass->next_files_async = g_file_enumerator_real_next_files_async;
156   klass->next_files_finish = g_file_enumerator_real_next_files_finish;
157   klass->close_async = g_file_enumerator_real_close_async;
158   klass->close_finish = g_file_enumerator_real_close_finish;
159
160   g_object_class_install_property
161     (gobject_class, PROP_CONTAINER,
162      g_param_spec_object ("container", P_("Container"),
163                           P_("The container that is being enumerated"),
164                           G_TYPE_FILE,
165                           G_PARAM_WRITABLE |
166                           G_PARAM_CONSTRUCT_ONLY |
167                           G_PARAM_STATIC_STRINGS));
168 }
169
170 static void
171 g_file_enumerator_init (GFileEnumerator *enumerator)
172 {
173   enumerator->priv = g_file_enumerator_get_instance_private (enumerator);
174 }
175
176 /**
177  * g_file_enumerator_next_file:
178  * @enumerator: a #GFileEnumerator.
179  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
180  * @error: location to store the error occurring, or %NULL to ignore
181  *
182  * Returns information for the next file in the enumerated object.
183  * Will block until the information is available. The #GFileInfo 
184  * returned from this function will contain attributes that match the 
185  * attribute string that was passed when the #GFileEnumerator was created.
186  *
187  * See the documentation of #GFileEnumerator for information about the
188  * order of returned files.
189  *
190  * On error, returns %NULL and sets @error to the error. If the
191  * enumerator is at the end, %NULL will be returned and @error will
192  * be unset.
193  *
194  * Returns: (nullable) (transfer full): A #GFileInfo or %NULL on error
195  *    or end of enumerator.  Free the returned object with
196  *    g_object_unref() when no longer needed.
197  **/
198 GFileInfo *
199 g_file_enumerator_next_file (GFileEnumerator *enumerator,
200                              GCancellable *cancellable,
201                              GError **error)
202 {
203   GFileEnumeratorClass *class;
204   GFileInfo *info;
205   
206   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
207   g_return_val_if_fail (enumerator != NULL, NULL);
208   
209   if (enumerator->priv->closed)
210     {
211       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
212                            _("Enumerator is closed"));
213       return NULL;
214     }
215
216   if (enumerator->priv->pending)
217     {
218       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING,
219                            _("File enumerator has outstanding operation"));
220       return NULL;
221     }
222
223   if (enumerator->priv->outstanding_error)
224     {
225       g_propagate_error (error, enumerator->priv->outstanding_error);
226       enumerator->priv->outstanding_error = NULL;
227       return NULL;
228     }
229   
230   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
231
232   if (cancellable)
233     g_cancellable_push_current (cancellable);
234   
235   enumerator->priv->pending = TRUE;
236   info = (* class->next_file) (enumerator, cancellable, error);
237   enumerator->priv->pending = FALSE;
238
239   if (cancellable)
240     g_cancellable_pop_current (cancellable);
241   
242   return info;
243 }
244   
245 /**
246  * g_file_enumerator_close:
247  * @enumerator: a #GFileEnumerator.
248  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore. 
249  * @error: location to store the error occurring, or %NULL to ignore
250  *
251  * Releases all resources used by this enumerator, making the
252  * enumerator return %G_IO_ERROR_CLOSED on all calls.
253  *
254  * This will be automatically called when the last reference
255  * is dropped, but you might want to call this function to make 
256  * sure resources are released as early as possible.
257  *
258  * Returns: #TRUE on success or #FALSE on error.
259  **/
260 gboolean
261 g_file_enumerator_close (GFileEnumerator  *enumerator,
262                          GCancellable     *cancellable,
263                          GError          **error)
264 {
265   GFileEnumeratorClass *class;
266
267   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), FALSE);
268   g_return_val_if_fail (enumerator != NULL, FALSE);
269   
270   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
271
272   if (enumerator->priv->closed)
273     return TRUE;
274   
275   if (enumerator->priv->pending)
276     {
277       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING,
278                            _("File enumerator has outstanding operation"));
279       return FALSE;
280     }
281
282   if (cancellable)
283     g_cancellable_push_current (cancellable);
284   
285   enumerator->priv->pending = TRUE;
286   (* class->close_fn) (enumerator, cancellable, error);
287   enumerator->priv->pending = FALSE;
288   enumerator->priv->closed = TRUE;
289
290   if (cancellable)
291     g_cancellable_pop_current (cancellable);
292   
293   return TRUE;
294 }
295
296 static void
297 next_async_callback_wrapper (GObject      *source_object,
298                              GAsyncResult *res,
299                              gpointer      user_data)
300 {
301   GFileEnumerator *enumerator = G_FILE_ENUMERATOR (source_object);
302
303   enumerator->priv->pending = FALSE;
304   if (enumerator->priv->outstanding_callback)
305     (*enumerator->priv->outstanding_callback) (source_object, res, user_data);
306   g_object_unref (enumerator);
307 }
308
309 /**
310  * g_file_enumerator_next_files_async:
311  * @enumerator: a #GFileEnumerator.
312  * @num_files: the number of file info objects to request
313  * @io_priority: the [I/O priority][io-priority] of the request 
314  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
315  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
316  * @user_data: (closure): the data to pass to callback function
317  *
318  * Request information for a number of files from the enumerator asynchronously.
319  * When all i/o for the operation is finished the @callback will be called with
320  * the requested information. 
321
322  * See the documentation of #GFileEnumerator for information about the
323  * order of returned files.
324  *
325  * The callback can be called with less than @num_files files in case of error
326  * or at the end of the enumerator. In case of a partial error the callback will
327  * be called with any succeeding items and no error, and on the next request the
328  * error will be reported. If a request is cancelled the callback will be called
329  * with %G_IO_ERROR_CANCELLED.
330  *
331  * During an async request no other sync and async calls are allowed, and will
332  * result in %G_IO_ERROR_PENDING errors. 
333  *
334  * Any outstanding i/o request with higher priority (lower numerical value) will
335  * be executed before an outstanding request with lower priority. Default
336  * priority is %G_PRIORITY_DEFAULT.
337  **/
338 void
339 g_file_enumerator_next_files_async (GFileEnumerator     *enumerator,
340                                     int                  num_files,
341                                     int                  io_priority,
342                                     GCancellable        *cancellable,
343                                     GAsyncReadyCallback  callback,
344                                     gpointer             user_data)
345 {
346   GFileEnumeratorClass *class;
347
348   g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
349   g_return_if_fail (enumerator != NULL);
350   g_return_if_fail (num_files >= 0);
351
352   if (num_files == 0)
353     {
354       GTask *task;
355
356       task = g_task_new (enumerator, cancellable, callback, user_data);
357       g_task_set_source_tag (task, g_file_enumerator_next_files_async);
358       g_task_return_pointer (task, NULL, NULL);
359       g_object_unref (task);
360       return;
361     }
362   
363   if (enumerator->priv->closed)
364     {
365       g_task_report_new_error (enumerator, callback, user_data,
366                                g_file_enumerator_next_files_async,
367                                G_IO_ERROR, G_IO_ERROR_CLOSED,
368                                _("File enumerator is already closed"));
369       return;
370     }
371   
372   if (enumerator->priv->pending)
373     {
374       g_task_report_new_error (enumerator, callback, user_data,
375                                g_file_enumerator_next_files_async,
376                                G_IO_ERROR, G_IO_ERROR_PENDING,
377                                _("File enumerator has outstanding operation"));
378       return;
379     }
380
381   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
382   
383   enumerator->priv->pending = TRUE;
384   enumerator->priv->outstanding_callback = callback;
385   g_object_ref (enumerator);
386   (* class->next_files_async) (enumerator, num_files, io_priority, cancellable, 
387                                next_async_callback_wrapper, user_data);
388 }
389
390 /**
391  * g_file_enumerator_next_files_finish:
392  * @enumerator: a #GFileEnumerator.
393  * @result: a #GAsyncResult.
394  * @error: a #GError location to store the error occurring, or %NULL to 
395  * ignore.
396  * 
397  * Finishes the asynchronous operation started with g_file_enumerator_next_files_async().
398  * 
399  * Returns: (transfer full) (element-type Gio.FileInfo): a #GList of #GFileInfos. You must free the list with 
400  *     g_list_free() and unref the infos with g_object_unref() when you're 
401  *     done with them.
402  **/
403 GList *
404 g_file_enumerator_next_files_finish (GFileEnumerator  *enumerator,
405                                      GAsyncResult     *result,
406                                      GError          **error)
407 {
408   GFileEnumeratorClass *class;
409   
410   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
411   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
412   
413   if (g_async_result_legacy_propagate_error (result, error))
414     return NULL;
415   else if (g_async_result_is_tagged (result, g_file_enumerator_next_files_async))
416     return g_task_propagate_pointer (G_TASK (result), error);
417   
418   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
419   return class->next_files_finish (enumerator, result, error);
420 }
421
422 static void
423 close_async_callback_wrapper (GObject      *source_object,
424                               GAsyncResult *res,
425                               gpointer      user_data)
426 {
427   GFileEnumerator *enumerator = G_FILE_ENUMERATOR (source_object);
428   
429   enumerator->priv->pending = FALSE;
430   enumerator->priv->closed = TRUE;
431   if (enumerator->priv->outstanding_callback)
432     (*enumerator->priv->outstanding_callback) (source_object, res, user_data);
433   g_object_unref (enumerator);
434 }
435
436 /**
437  * g_file_enumerator_close_async:
438  * @enumerator: a #GFileEnumerator.
439  * @io_priority: the [I/O priority][io-priority] of the request
440  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore. 
441  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
442  * @user_data: (closure): the data to pass to callback function
443  *
444  * Asynchronously closes the file enumerator. 
445  *
446  * If @cancellable is not %NULL, then the operation can be cancelled by
447  * triggering the cancellable object from another thread. If the operation
448  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned in 
449  * g_file_enumerator_close_finish(). 
450  **/
451 void
452 g_file_enumerator_close_async (GFileEnumerator     *enumerator,
453                                int                  io_priority,
454                                GCancellable        *cancellable,
455                                GAsyncReadyCallback  callback,
456                                gpointer             user_data)
457 {
458   GFileEnumeratorClass *class;
459
460   g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
461
462   if (enumerator->priv->closed)
463     {
464       g_task_report_new_error (enumerator, callback, user_data,
465                                g_file_enumerator_close_async,
466                                G_IO_ERROR, G_IO_ERROR_CLOSED,
467                                _("File enumerator is already closed"));
468       return;
469     }
470   
471   if (enumerator->priv->pending)
472     {
473       g_task_report_new_error (enumerator, callback, user_data,
474                                g_file_enumerator_close_async,
475                                G_IO_ERROR, G_IO_ERROR_PENDING,
476                                _("File enumerator has outstanding operation"));
477       return;
478     }
479
480   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
481   
482   enumerator->priv->pending = TRUE;
483   enumerator->priv->outstanding_callback = callback;
484   g_object_ref (enumerator);
485   (* class->close_async) (enumerator, io_priority, cancellable,
486                           close_async_callback_wrapper, user_data);
487 }
488
489 /**
490  * g_file_enumerator_close_finish:
491  * @enumerator: a #GFileEnumerator.
492  * @result: a #GAsyncResult.
493  * @error: a #GError location to store the error occurring, or %NULL to 
494  * ignore.
495  * 
496  * Finishes closing a file enumerator, started from g_file_enumerator_close_async().
497  * 
498  * If the file enumerator was already closed when g_file_enumerator_close_async() 
499  * was called, then this function will report %G_IO_ERROR_CLOSED in @error, and 
500  * return %FALSE. If the file enumerator had pending operation when the close 
501  * operation was started, then this function will report %G_IO_ERROR_PENDING, and
502  * return %FALSE.  If @cancellable was not %NULL, then the operation may have been 
503  * cancelled by triggering the cancellable object from another thread. If the operation
504  * was cancelled, the error %G_IO_ERROR_CANCELLED will be set, and %FALSE will be 
505  * returned. 
506  * 
507  * Returns: %TRUE if the close operation has finished successfully.
508  **/
509 gboolean
510 g_file_enumerator_close_finish (GFileEnumerator  *enumerator,
511                                 GAsyncResult     *result,
512                                 GError          **error)
513 {
514   GFileEnumeratorClass *class;
515
516   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), FALSE);
517   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
518   
519   if (g_async_result_legacy_propagate_error (result, error))
520     return FALSE;
521   else if (g_async_result_is_tagged (result, g_file_enumerator_close_async))
522     return g_task_propagate_boolean (G_TASK (result), error);
523
524   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
525   return class->close_finish (enumerator, result, error);
526 }
527
528 /**
529  * g_file_enumerator_is_closed:
530  * @enumerator: a #GFileEnumerator.
531  *
532  * Checks if the file enumerator has been closed.
533  * 
534  * Returns: %TRUE if the @enumerator is closed.
535  **/
536 gboolean
537 g_file_enumerator_is_closed (GFileEnumerator *enumerator)
538 {
539   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), TRUE);
540   
541   return enumerator->priv->closed;
542 }
543
544 /**
545  * g_file_enumerator_has_pending:
546  * @enumerator: a #GFileEnumerator.
547  * 
548  * Checks if the file enumerator has pending operations.
549  *
550  * Returns: %TRUE if the @enumerator has pending operations.
551  **/
552 gboolean
553 g_file_enumerator_has_pending (GFileEnumerator *enumerator)
554 {
555   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), TRUE);
556   
557   return enumerator->priv->pending;
558 }
559
560 /**
561  * g_file_enumerator_set_pending:
562  * @enumerator: a #GFileEnumerator.
563  * @pending: a boolean value.
564  * 
565  * Sets the file enumerator as having pending operations.
566  **/
567 void
568 g_file_enumerator_set_pending (GFileEnumerator *enumerator,
569                                gboolean         pending)
570 {
571   g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
572   
573   enumerator->priv->pending = pending;
574 }
575
576 /**
577  * g_file_enumerator_get_container:
578  * @enumerator: a #GFileEnumerator
579  *
580  * Get the #GFile container which is being enumerated.
581  *
582  * Returns: (transfer none): the #GFile which is being enumerated.
583  *
584  * Since: 2.18
585  */
586 GFile *
587 g_file_enumerator_get_container (GFileEnumerator *enumerator)
588 {
589   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
590
591   return enumerator->priv->container;
592 }
593
594 /**
595  * g_file_enumerator_get_child:
596  * @enumerator: a #GFileEnumerator
597  * @info: a #GFileInfo gotten from g_file_enumerator_next_file()
598  *   or the async equivalents.
599  *
600  * Return a new #GFile which refers to the file named by @info in the source
601  * directory of @enumerator.  This function is primarily intended to be used
602  * inside loops with g_file_enumerator_next_file().
603  *
604  * This is a convenience method that's equivalent to:
605  * |[<!-- language="C" -->
606  *   gchar *name = g_file_info_get_name (info);
607  *   GFile *child = g_file_get_child (g_file_enumerator_get_container (enumr),
608  *                                    name);
609  * ]|
610  *
611  * Returns: (transfer full): a #GFile for the #GFileInfo passed it.
612  *
613  * Since: 2.36
614  */
615 GFile *
616 g_file_enumerator_get_child (GFileEnumerator *enumerator,
617                              GFileInfo       *info)
618 {
619   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
620
621   return g_file_get_child (enumerator->priv->container,
622                            g_file_info_get_name (info));
623 }
624
625 static void
626 next_async_op_free (GList *files)
627 {
628   g_list_free_full (files, g_object_unref);
629 }
630
631 static void
632 next_files_thread (GTask        *task,
633                    gpointer      source_object,
634                    gpointer      task_data,
635                    GCancellable *cancellable)
636 {
637   GFileEnumerator *enumerator = source_object;
638   int num_files = GPOINTER_TO_INT (task_data);
639   GFileEnumeratorClass *class;
640   GList *files = NULL;
641   GError *error = NULL;
642   GFileInfo *info;
643   int i;
644
645   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
646
647   for (i = 0; i < num_files; i++)
648     {
649       if (g_cancellable_set_error_if_cancelled (cancellable, &error))
650         info = NULL;
651       else
652         info = class->next_file (enumerator, cancellable, &error);
653       
654       if (info == NULL)
655         {
656           /* If we get an error after first file, return that on next operation */
657           if (error != NULL && i > 0)
658             {
659               if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
660                 g_error_free (error); /* Never propagate cancel errors to other call */
661               else
662                 enumerator->priv->outstanding_error = error;
663               error = NULL;
664             }
665               
666           break;
667         }
668       else
669         files = g_list_prepend (files, info);
670     }
671
672   if (error)
673     g_task_return_error (task, error);
674   else
675     g_task_return_pointer (task, files, (GDestroyNotify)next_async_op_free);
676 }
677
678 static void
679 g_file_enumerator_real_next_files_async (GFileEnumerator     *enumerator,
680                                          int                  num_files,
681                                          int                  io_priority,
682                                          GCancellable        *cancellable,
683                                          GAsyncReadyCallback  callback,
684                                          gpointer             user_data)
685 {
686   GTask *task;
687
688   task = g_task_new (enumerator, cancellable, callback, user_data);
689   g_task_set_task_data (task, GINT_TO_POINTER (num_files), NULL);
690   g_task_set_priority (task, io_priority);
691
692   g_task_run_in_thread (task, next_files_thread);
693   g_object_unref (task);
694 }
695
696 static GList *
697 g_file_enumerator_real_next_files_finish (GFileEnumerator                *enumerator,
698                                           GAsyncResult                   *result,
699                                           GError                        **error)
700 {
701   g_return_val_if_fail (g_task_is_valid (result, enumerator), NULL);
702
703   return g_task_propagate_pointer (G_TASK (result), error);
704 }
705
706 static void
707 close_async_thread (GTask        *task,
708                     gpointer      source_object,
709                     gpointer      task_data,
710                     GCancellable *cancellable)
711 {
712   GFileEnumerator *enumerator = source_object;
713   GFileEnumeratorClass *class;
714   GError *error = NULL;
715   gboolean result;
716
717   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
718   result = class->close_fn (enumerator, cancellable, &error);
719   if (result)
720     g_task_return_boolean (task, TRUE);
721   else
722     g_task_return_error (task, error);
723 }
724
725 static void
726 g_file_enumerator_real_close_async (GFileEnumerator     *enumerator,
727                                     int                  io_priority,
728                                     GCancellable        *cancellable,
729                                     GAsyncReadyCallback  callback,
730                                     gpointer             user_data)
731 {
732   GTask *task;
733
734   task = g_task_new (enumerator, cancellable, callback, user_data);
735   g_task_set_priority (task, io_priority);
736   
737   g_task_run_in_thread (task, close_async_thread);
738   g_object_unref (task);
739 }
740
741 static gboolean
742 g_file_enumerator_real_close_finish (GFileEnumerator  *enumerator,
743                                      GAsyncResult     *result,
744                                      GError          **error)
745 {
746   g_return_val_if_fail (g_task_is_valid (result, enumerator), FALSE);
747
748   return g_task_propagate_boolean (G_TASK (result), error);
749 }