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