gdesktopappinfo: Initialize sn_id to NULL
[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: (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  * Returns: #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 [I/O priority][io-priority] of the request 
313  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
314  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
315  * @user_data: (closure): the data to pass to callback function
316  *
317  * Request information for a number of files from the enumerator asynchronously.
318  * When all i/o for the operation is finished the @callback will be called with
319  * the requested information. 
320
321  * See the documentation of #GFileEnumerator for information about the
322  * order of returned files.
323  *
324  * The callback can be called with less than @num_files files in case of error
325  * or at the end of the enumerator. In case of a partial error the callback will
326  * be called with any succeeding items and no error, and on the next request the
327  * error will be reported. If a request is cancelled the callback will be called
328  * with %G_IO_ERROR_CANCELLED.
329  *
330  * During an async request no other sync and async calls are allowed, and will
331  * result in %G_IO_ERROR_PENDING errors. 
332  *
333  * Any outstanding i/o request with higher priority (lower numerical value) will
334  * be executed before an outstanding request with lower priority. Default
335  * priority is %G_PRIORITY_DEFAULT.
336  **/
337 void
338 g_file_enumerator_next_files_async (GFileEnumerator     *enumerator,
339                                     int                  num_files,
340                                     int                  io_priority,
341                                     GCancellable        *cancellable,
342                                     GAsyncReadyCallback  callback,
343                                     gpointer             user_data)
344 {
345   GFileEnumeratorClass *class;
346
347   g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
348   g_return_if_fail (enumerator != NULL);
349   g_return_if_fail (num_files >= 0);
350
351   if (num_files == 0)
352     {
353       GTask *task;
354
355       task = g_task_new (enumerator, cancellable, callback, user_data);
356       g_task_set_source_tag (task, g_file_enumerator_next_files_async);
357       g_task_return_pointer (task, NULL, NULL);
358       g_object_unref (task);
359       return;
360     }
361   
362   if (enumerator->priv->closed)
363     {
364       g_task_report_new_error (enumerator, callback, user_data,
365                                g_file_enumerator_next_files_async,
366                                G_IO_ERROR, G_IO_ERROR_CLOSED,
367                                _("File enumerator is already closed"));
368       return;
369     }
370   
371   if (enumerator->priv->pending)
372     {
373       g_task_report_new_error (enumerator, callback, user_data,
374                                g_file_enumerator_next_files_async,
375                                G_IO_ERROR, G_IO_ERROR_PENDING,
376                                _("File enumerator has outstanding operation"));
377       return;
378     }
379
380   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
381   
382   enumerator->priv->pending = TRUE;
383   enumerator->priv->outstanding_callback = callback;
384   g_object_ref (enumerator);
385   (* class->next_files_async) (enumerator, num_files, io_priority, cancellable, 
386                                next_async_callback_wrapper, user_data);
387 }
388
389 /**
390  * g_file_enumerator_next_files_finish:
391  * @enumerator: a #GFileEnumerator.
392  * @result: a #GAsyncResult.
393  * @error: a #GError location to store the error occurring, or %NULL to 
394  * ignore.
395  * 
396  * Finishes the asynchronous operation started with g_file_enumerator_next_files_async().
397  * 
398  * Returns: (transfer full) (element-type Gio.FileInfo): a #GList of #GFileInfo<!---->s. You must free the list with 
399  *     g_list_free() and unref the infos with g_object_unref() when you're 
400  *     done with them.
401  **/
402 GList *
403 g_file_enumerator_next_files_finish (GFileEnumerator  *enumerator,
404                                      GAsyncResult     *result,
405                                      GError          **error)
406 {
407   GFileEnumeratorClass *class;
408   
409   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
410   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
411   
412   if (g_async_result_legacy_propagate_error (result, error))
413     return NULL;
414   else if (g_async_result_is_tagged (result, g_file_enumerator_next_files_async))
415     return g_task_propagate_pointer (G_TASK (result), error);
416   
417   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
418   return class->next_files_finish (enumerator, result, error);
419 }
420
421 static void
422 close_async_callback_wrapper (GObject      *source_object,
423                               GAsyncResult *res,
424                               gpointer      user_data)
425 {
426   GFileEnumerator *enumerator = G_FILE_ENUMERATOR (source_object);
427   
428   enumerator->priv->pending = FALSE;
429   enumerator->priv->closed = TRUE;
430   if (enumerator->priv->outstanding_callback)
431     (*enumerator->priv->outstanding_callback) (source_object, res, user_data);
432   g_object_unref (enumerator);
433 }
434
435 /**
436  * g_file_enumerator_close_async:
437  * @enumerator: a #GFileEnumerator.
438  * @io_priority: the [I/O priority][io-priority] of the request
439  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore. 
440  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
441  * @user_data: (closure): the data to pass to callback function
442  *
443  * Asynchronously closes the file enumerator. 
444  *
445  * If @cancellable is not %NULL, then the operation can be cancelled by
446  * triggering the cancellable object from another thread. If the operation
447  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned in 
448  * g_file_enumerator_close_finish(). 
449  **/
450 void
451 g_file_enumerator_close_async (GFileEnumerator     *enumerator,
452                                int                  io_priority,
453                                GCancellable        *cancellable,
454                                GAsyncReadyCallback  callback,
455                                gpointer             user_data)
456 {
457   GFileEnumeratorClass *class;
458
459   g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
460
461   if (enumerator->priv->closed)
462     {
463       g_task_report_new_error (enumerator, callback, user_data,
464                                g_file_enumerator_close_async,
465                                G_IO_ERROR, G_IO_ERROR_CLOSED,
466                                _("File enumerator is already closed"));
467       return;
468     }
469   
470   if (enumerator->priv->pending)
471     {
472       g_task_report_new_error (enumerator, callback, user_data,
473                                g_file_enumerator_close_async,
474                                G_IO_ERROR, G_IO_ERROR_PENDING,
475                                _("File enumerator has outstanding operation"));
476       return;
477     }
478
479   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
480   
481   enumerator->priv->pending = TRUE;
482   enumerator->priv->outstanding_callback = callback;
483   g_object_ref (enumerator);
484   (* class->close_async) (enumerator, io_priority, cancellable,
485                           close_async_callback_wrapper, user_data);
486 }
487
488 /**
489  * g_file_enumerator_close_finish:
490  * @enumerator: a #GFileEnumerator.
491  * @result: a #GAsyncResult.
492  * @error: a #GError location to store the error occurring, or %NULL to 
493  * ignore.
494  * 
495  * Finishes closing a file enumerator, started from g_file_enumerator_close_async().
496  * 
497  * If the file enumerator was already closed when g_file_enumerator_close_async() 
498  * was called, then this function will report %G_IO_ERROR_CLOSED in @error, and 
499  * return %FALSE. If the file enumerator had pending operation when the close 
500  * operation was started, then this function will report %G_IO_ERROR_PENDING, and
501  * return %FALSE.  If @cancellable was not %NULL, then the operation may have been 
502  * cancelled by triggering the cancellable object from another thread. If the operation
503  * was cancelled, the error %G_IO_ERROR_CANCELLED will be set, and %FALSE will be 
504  * returned. 
505  * 
506  * Returns: %TRUE if the close operation has finished successfully.
507  **/
508 gboolean
509 g_file_enumerator_close_finish (GFileEnumerator  *enumerator,
510                                 GAsyncResult     *result,
511                                 GError          **error)
512 {
513   GFileEnumeratorClass *class;
514
515   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), FALSE);
516   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
517   
518   if (g_async_result_legacy_propagate_error (result, error))
519     return FALSE;
520   else if (g_async_result_is_tagged (result, g_file_enumerator_close_async))
521     return g_task_propagate_boolean (G_TASK (result), error);
522
523   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
524   return class->close_finish (enumerator, result, error);
525 }
526
527 /**
528  * g_file_enumerator_is_closed:
529  * @enumerator: a #GFileEnumerator.
530  *
531  * Checks if the file enumerator has been closed.
532  * 
533  * Returns: %TRUE if the @enumerator is closed.
534  **/
535 gboolean
536 g_file_enumerator_is_closed (GFileEnumerator *enumerator)
537 {
538   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), TRUE);
539   
540   return enumerator->priv->closed;
541 }
542
543 /**
544  * g_file_enumerator_has_pending:
545  * @enumerator: a #GFileEnumerator.
546  * 
547  * Checks if the file enumerator has pending operations.
548  *
549  * Returns: %TRUE if the @enumerator has pending operations.
550  **/
551 gboolean
552 g_file_enumerator_has_pending (GFileEnumerator *enumerator)
553 {
554   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), TRUE);
555   
556   return enumerator->priv->pending;
557 }
558
559 /**
560  * g_file_enumerator_set_pending:
561  * @enumerator: a #GFileEnumerator.
562  * @pending: a boolean value.
563  * 
564  * Sets the file enumerator as having pending operations.
565  **/
566 void
567 g_file_enumerator_set_pending (GFileEnumerator *enumerator,
568                                gboolean         pending)
569 {
570   g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
571   
572   enumerator->priv->pending = pending;
573 }
574
575 /**
576  * g_file_enumerator_get_container:
577  * @enumerator: a #GFileEnumerator
578  *
579  * Get the #GFile container which is being enumerated.
580  *
581  * Returns: (transfer none): the #GFile which is being enumerated.
582  *
583  * Since: 2.18
584  */
585 GFile *
586 g_file_enumerator_get_container (GFileEnumerator *enumerator)
587 {
588   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
589
590   return enumerator->priv->container;
591 }
592
593 /**
594  * g_file_enumerator_get_child:
595  * @enumerator: a #GFileEnumerator
596  * @info: a #GFileInfo gotten from g_file_enumerator_next_file()
597  *   or the async equivalents.
598  *
599  * Return a new #GFile which refers to the file named by @info in the source
600  * directory of @enumerator.  This function is primarily intended to be used
601  * inside loops with g_file_enumerator_next_file().
602  *
603  * This is a convenience method that's equivalent to:
604  * |[<!-- language="C" -->
605  *   gchar *name = g_file_info_get_name (info);
606  *   GFile *child = g_file_get_child (g_file_enumerator_get_container (enumr),
607  *                                    name);
608  * ]|
609  *
610  * Returns: (transfer full): a #GFile for the #GFileInfo passed it.
611  *
612  * Since: 2.36
613  */
614 GFile *
615 g_file_enumerator_get_child (GFileEnumerator *enumerator,
616                              GFileInfo       *info)
617 {
618   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
619
620   return g_file_get_child (enumerator->priv->container,
621                            g_file_info_get_name (info));
622 }
623
624 static void
625 next_async_op_free (GList *files)
626 {
627   g_list_free_full (files, g_object_unref);
628 }
629
630 static void
631 next_files_thread (GTask        *task,
632                    gpointer      source_object,
633                    gpointer      task_data,
634                    GCancellable *cancellable)
635 {
636   GFileEnumerator *enumerator = source_object;
637   int num_files = GPOINTER_TO_INT (task_data);
638   GFileEnumeratorClass *class;
639   GList *files = NULL;
640   GError *error = NULL;
641   GFileInfo *info;
642   int i;
643
644   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
645
646   for (i = 0; i < num_files; i++)
647     {
648       if (g_cancellable_set_error_if_cancelled (cancellable, &error))
649         info = NULL;
650       else
651         info = class->next_file (enumerator, cancellable, &error);
652       
653       if (info == NULL)
654         {
655           /* If we get an error after first file, return that on next operation */
656           if (error != NULL && i > 0)
657             {
658               if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
659                 g_error_free (error); /* Never propagate cancel errors to other call */
660               else
661                 enumerator->priv->outstanding_error = error;
662               error = NULL;
663             }
664               
665           break;
666         }
667       else
668         files = g_list_prepend (files, info);
669     }
670
671   if (error)
672     g_task_return_error (task, error);
673   else
674     g_task_return_pointer (task, files, (GDestroyNotify)next_async_op_free);
675 }
676
677 static void
678 g_file_enumerator_real_next_files_async (GFileEnumerator     *enumerator,
679                                          int                  num_files,
680                                          int                  io_priority,
681                                          GCancellable        *cancellable,
682                                          GAsyncReadyCallback  callback,
683                                          gpointer             user_data)
684 {
685   GTask *task;
686
687   task = g_task_new (enumerator, cancellable, callback, user_data);
688   g_task_set_task_data (task, GINT_TO_POINTER (num_files), NULL);
689   g_task_set_priority (task, io_priority);
690
691   g_task_run_in_thread (task, next_files_thread);
692   g_object_unref (task);
693 }
694
695 static GList *
696 g_file_enumerator_real_next_files_finish (GFileEnumerator                *enumerator,
697                                           GAsyncResult                   *result,
698                                           GError                        **error)
699 {
700   g_return_val_if_fail (g_task_is_valid (result, enumerator), NULL);
701
702   return g_task_propagate_pointer (G_TASK (result), error);
703 }
704
705 static void
706 close_async_thread (GTask        *task,
707                     gpointer      source_object,
708                     gpointer      task_data,
709                     GCancellable *cancellable)
710 {
711   GFileEnumerator *enumerator = source_object;
712   GFileEnumeratorClass *class;
713   GError *error = NULL;
714   gboolean result;
715
716   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
717   result = class->close_fn (enumerator, cancellable, &error);
718   if (result)
719     g_task_return_boolean (task, TRUE);
720   else
721     g_task_return_error (task, error);
722 }
723
724 static void
725 g_file_enumerator_real_close_async (GFileEnumerator     *enumerator,
726                                     int                  io_priority,
727                                     GCancellable        *cancellable,
728                                     GAsyncReadyCallback  callback,
729                                     gpointer             user_data)
730 {
731   GTask *task;
732
733   task = g_task_new (enumerator, cancellable, callback, user_data);
734   g_task_set_priority (task, io_priority);
735   
736   g_task_run_in_thread (task, close_async_thread);
737   g_object_unref (task);
738 }
739
740 static gboolean
741 g_file_enumerator_real_close_finish (GFileEnumerator  *enumerator,
742                                      GAsyncResult     *result,
743                                      GError          **error)
744 {
745   g_return_val_if_fail (g_task_is_valid (result, enumerator), FALSE);
746
747   return g_task_propagate_boolean (G_TASK (result), error);
748 }