9146b653db04c79d37dcd5ba987757eae5cc3dcd
[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 #GFile<!-- -->s, 
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 #GFileInfo<!---->s, 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  * Return value: (transfer full): A #GFileInfo or %NULL on error or end of enumerator.
195  *    Free the returned object with g_object_unref() when no longer needed.
196  **/
197 GFileInfo *
198 g_file_enumerator_next_file (GFileEnumerator *enumerator,
199                              GCancellable *cancellable,
200                              GError **error)
201 {
202   GFileEnumeratorClass *class;
203   GFileInfo *info;
204   
205   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
206   g_return_val_if_fail (enumerator != NULL, NULL);
207   
208   if (enumerator->priv->closed)
209     {
210       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
211                            _("Enumerator is closed"));
212       return NULL;
213     }
214
215   if (enumerator->priv->pending)
216     {
217       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING,
218                            _("File enumerator has outstanding operation"));
219       return NULL;
220     }
221
222   if (enumerator->priv->outstanding_error)
223     {
224       g_propagate_error (error, enumerator->priv->outstanding_error);
225       enumerator->priv->outstanding_error = NULL;
226       return NULL;
227     }
228   
229   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
230
231   if (cancellable)
232     g_cancellable_push_current (cancellable);
233   
234   enumerator->priv->pending = TRUE;
235   info = (* class->next_file) (enumerator, cancellable, error);
236   enumerator->priv->pending = FALSE;
237
238   if (cancellable)
239     g_cancellable_pop_current (cancellable);
240   
241   return info;
242 }
243   
244 /**
245  * g_file_enumerator_close:
246  * @enumerator: a #GFileEnumerator.
247  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore. 
248  * @error: location to store the error occurring, or %NULL to ignore
249  *
250  * Releases all resources used by this enumerator, making the
251  * enumerator return %G_IO_ERROR_CLOSED on all calls.
252  *
253  * This will be automatically called when the last reference
254  * is dropped, but you might want to call this function to make 
255  * sure resources are released as early as possible.
256  *
257  * Return value: #TRUE on success or #FALSE on error.
258  **/
259 gboolean
260 g_file_enumerator_close (GFileEnumerator  *enumerator,
261                          GCancellable     *cancellable,
262                          GError          **error)
263 {
264   GFileEnumeratorClass *class;
265
266   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), FALSE);
267   g_return_val_if_fail (enumerator != NULL, FALSE);
268   
269   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
270
271   if (enumerator->priv->closed)
272     return TRUE;
273   
274   if (enumerator->priv->pending)
275     {
276       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING,
277                            _("File enumerator has outstanding operation"));
278       return FALSE;
279     }
280
281   if (cancellable)
282     g_cancellable_push_current (cancellable);
283   
284   enumerator->priv->pending = TRUE;
285   (* class->close_fn) (enumerator, cancellable, error);
286   enumerator->priv->pending = FALSE;
287   enumerator->priv->closed = TRUE;
288
289   if (cancellable)
290     g_cancellable_pop_current (cancellable);
291   
292   return TRUE;
293 }
294
295 static void
296 next_async_callback_wrapper (GObject      *source_object,
297                              GAsyncResult *res,
298                              gpointer      user_data)
299 {
300   GFileEnumerator *enumerator = G_FILE_ENUMERATOR (source_object);
301
302   enumerator->priv->pending = FALSE;
303   if (enumerator->priv->outstanding_callback)
304     (*enumerator->priv->outstanding_callback) (source_object, res, user_data);
305   g_object_unref (enumerator);
306 }
307
308 /**
309  * g_file_enumerator_next_files_async:
310  * @enumerator: a #GFileEnumerator.
311  * @num_files: the number of file info objects to request
312  * @io_priority: the <link linkend="io-priority">io priority</link>
313  *     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 #GFileInfo<!---->s. 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 <link linkend="io-priority">I/O priority</link> 
440  *     of the request.
441  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore. 
442  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
443  * @user_data: (closure): the data to pass to callback function
444  *
445  * Asynchronously closes the file enumerator. 
446  *
447  * If @cancellable is not %NULL, then the operation can be cancelled by
448  * triggering the cancellable object from another thread. If the operation
449  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned in 
450  * g_file_enumerator_close_finish(). 
451  **/
452 void
453 g_file_enumerator_close_async (GFileEnumerator     *enumerator,
454                                int                  io_priority,
455                                GCancellable        *cancellable,
456                                GAsyncReadyCallback  callback,
457                                gpointer             user_data)
458 {
459   GFileEnumeratorClass *class;
460
461   g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
462
463   if (enumerator->priv->closed)
464     {
465       g_task_report_new_error (enumerator, callback, user_data,
466                                g_file_enumerator_close_async,
467                                G_IO_ERROR, G_IO_ERROR_CLOSED,
468                                _("File enumerator is already closed"));
469       return;
470     }
471   
472   if (enumerator->priv->pending)
473     {
474       g_task_report_new_error (enumerator, callback, user_data,
475                                g_file_enumerator_close_async,
476                                G_IO_ERROR, G_IO_ERROR_PENDING,
477                                _("File enumerator has outstanding operation"));
478       return;
479     }
480
481   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
482   
483   enumerator->priv->pending = TRUE;
484   enumerator->priv->outstanding_callback = callback;
485   g_object_ref (enumerator);
486   (* class->close_async) (enumerator, io_priority, cancellable,
487                           close_async_callback_wrapper, user_data);
488 }
489
490 /**
491  * g_file_enumerator_close_finish:
492  * @enumerator: a #GFileEnumerator.
493  * @result: a #GAsyncResult.
494  * @error: a #GError location to store the error occurring, or %NULL to 
495  * ignore.
496  * 
497  * Finishes closing a file enumerator, started from g_file_enumerator_close_async().
498  * 
499  * If the file enumerator was already closed when g_file_enumerator_close_async() 
500  * was called, then this function will report %G_IO_ERROR_CLOSED in @error, and 
501  * return %FALSE. If the file enumerator had pending operation when the close 
502  * operation was started, then this function will report %G_IO_ERROR_PENDING, and
503  * return %FALSE.  If @cancellable was not %NULL, then the operation may have been 
504  * cancelled by triggering the cancellable object from another thread. If the operation
505  * was cancelled, the error %G_IO_ERROR_CANCELLED will be set, and %FALSE will be 
506  * returned. 
507  * 
508  * Returns: %TRUE if the close operation has finished successfully.
509  **/
510 gboolean
511 g_file_enumerator_close_finish (GFileEnumerator  *enumerator,
512                                 GAsyncResult     *result,
513                                 GError          **error)
514 {
515   GFileEnumeratorClass *class;
516
517   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), FALSE);
518   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
519   
520   if (g_async_result_legacy_propagate_error (result, error))
521     return FALSE;
522   else if (g_async_result_is_tagged (result, g_file_enumerator_close_async))
523     return g_task_propagate_boolean (G_TASK (result), error);
524
525   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
526   return class->close_finish (enumerator, result, error);
527 }
528
529 /**
530  * g_file_enumerator_is_closed:
531  * @enumerator: a #GFileEnumerator.
532  *
533  * Checks if the file enumerator has been closed.
534  * 
535  * Returns: %TRUE if the @enumerator is closed.
536  **/
537 gboolean
538 g_file_enumerator_is_closed (GFileEnumerator *enumerator)
539 {
540   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), TRUE);
541   
542   return enumerator->priv->closed;
543 }
544
545 /**
546  * g_file_enumerator_has_pending:
547  * @enumerator: a #GFileEnumerator.
548  * 
549  * Checks if the file enumerator has pending operations.
550  *
551  * Returns: %TRUE if the @enumerator has pending operations.
552  **/
553 gboolean
554 g_file_enumerator_has_pending (GFileEnumerator *enumerator)
555 {
556   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), TRUE);
557   
558   return enumerator->priv->pending;
559 }
560
561 /**
562  * g_file_enumerator_set_pending:
563  * @enumerator: a #GFileEnumerator.
564  * @pending: a boolean value.
565  * 
566  * Sets the file enumerator as having pending operations.
567  **/
568 void
569 g_file_enumerator_set_pending (GFileEnumerator *enumerator,
570                                gboolean         pending)
571 {
572   g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
573   
574   enumerator->priv->pending = pending;
575 }
576
577 /**
578  * g_file_enumerator_get_container:
579  * @enumerator: a #GFileEnumerator
580  *
581  * Get the #GFile container which is being enumerated.
582  *
583  * Returns: (transfer none): the #GFile which is being enumerated.
584  *
585  * Since: 2.18
586  */
587 GFile *
588 g_file_enumerator_get_container (GFileEnumerator *enumerator)
589 {
590   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
591
592   return enumerator->priv->container;
593 }
594
595 /**
596  * g_file_enumerator_get_child:
597  * @enumerator: a #GFileEnumerator
598  * @info: a #GFileInfo gotten from g_file_enumerator_next_file()
599  *   or the async equivalents.
600  *
601  * Return a new #GFile which refers to the file named by @info in the source
602  * directory of @enumerator.  This function is primarily intended to be used
603  * inside loops with g_file_enumerator_next_file().
604  *
605  * This is a convenience method that's equivalent to:
606  * |[
607  *   gchar *name = g_file_info_get_name (info);
608  *   GFile *child = g_file_get_child (g_file_enumerator_get_container (enumr),
609  *                                    name);
610  * ]|
611  *
612  * Returns: (transfer full): a #GFile for the #GFileInfo passed it.
613  *
614  * Since: 2.36
615  */
616 GFile *
617 g_file_enumerator_get_child (GFileEnumerator *enumerator,
618                              GFileInfo       *info)
619 {
620   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
621
622   return g_file_get_child (enumerator->priv->container,
623                            g_file_info_get_name (info));
624 }
625
626 static void
627 next_async_op_free (GList *files)
628 {
629   g_list_free_full (files, g_object_unref);
630 }
631
632 static void
633 next_files_thread (GTask        *task,
634                    gpointer      source_object,
635                    gpointer      task_data,
636                    GCancellable *cancellable)
637 {
638   GFileEnumerator *enumerator = source_object;
639   int num_files = GPOINTER_TO_INT (task_data);
640   GFileEnumeratorClass *class;
641   GList *files = NULL;
642   GError *error = NULL;
643   GFileInfo *info;
644   int i;
645
646   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
647
648   for (i = 0; i < num_files; i++)
649     {
650       if (g_cancellable_set_error_if_cancelled (cancellable, &error))
651         info = NULL;
652       else
653         info = class->next_file (enumerator, cancellable, &error);
654       
655       if (info == NULL)
656         {
657           /* If we get an error after first file, return that on next operation */
658           if (error != NULL && i > 0)
659             {
660               if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
661                 g_error_free (error); /* Never propagate cancel errors to other call */
662               else
663                 enumerator->priv->outstanding_error = error;
664               error = NULL;
665             }
666               
667           break;
668         }
669       else
670         files = g_list_prepend (files, info);
671     }
672
673   if (error)
674     g_task_return_error (task, error);
675   else
676     g_task_return_pointer (task, files, (GDestroyNotify)next_async_op_free);
677 }
678
679 static void
680 g_file_enumerator_real_next_files_async (GFileEnumerator     *enumerator,
681                                          int                  num_files,
682                                          int                  io_priority,
683                                          GCancellable        *cancellable,
684                                          GAsyncReadyCallback  callback,
685                                          gpointer             user_data)
686 {
687   GTask *task;
688
689   task = g_task_new (enumerator, cancellable, callback, user_data);
690   g_task_set_task_data (task, GINT_TO_POINTER (num_files), NULL);
691   g_task_set_priority (task, io_priority);
692
693   g_task_run_in_thread (task, next_files_thread);
694   g_object_unref (task);
695 }
696
697 static GList *
698 g_file_enumerator_real_next_files_finish (GFileEnumerator                *enumerator,
699                                           GAsyncResult                   *result,
700                                           GError                        **error)
701 {
702   g_return_val_if_fail (g_task_is_valid (result, enumerator), NULL);
703
704   return g_task_propagate_pointer (G_TASK (result), error);
705 }
706
707 static void
708 close_async_thread (GTask        *task,
709                     gpointer      source_object,
710                     gpointer      task_data,
711                     GCancellable *cancellable)
712 {
713   GFileEnumerator *enumerator = source_object;
714   GFileEnumeratorClass *class;
715   GError *error = NULL;
716   gboolean result;
717
718   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
719   result = class->close_fn (enumerator, cancellable, &error);
720   if (result)
721     g_task_return_boolean (task, TRUE);
722   else
723     g_task_return_error (task, error);
724 }
725
726 static void
727 g_file_enumerator_real_close_async (GFileEnumerator     *enumerator,
728                                     int                  io_priority,
729                                     GCancellable        *cancellable,
730                                     GAsyncReadyCallback  callback,
731                                     gpointer             user_data)
732 {
733   GTask *task;
734
735   task = g_task_new (enumerator, cancellable, callback, user_data);
736   g_task_set_priority (task, io_priority);
737   
738   g_task_run_in_thread (task, close_async_thread);
739   g_object_unref (task);
740 }
741
742 static gboolean
743 g_file_enumerator_real_close_finish (GFileEnumerator  *enumerator,
744                                      GAsyncResult     *result,
745                                      GError          **error)
746 {
747   g_return_val_if_fail (g_task_is_valid (result, enumerator), FALSE);
748
749   return g_task_propagate_boolean (G_TASK (result), error);
750 }