(root)/
glib-2.79.0/
gio/
gfileenumerator.c
       1  /* GIO - GLib Input, Output and Streaming Library
       2   * 
       3   * Copyright (C) 2006-2007 Red Hat, Inc.
       4   *
       5   * SPDX-License-Identifier: LGPL-2.1-or-later
       6   *
       7   * This library is free software; you can redistribute it and/or
       8   * modify it under the terms of the GNU Lesser General Public
       9   * License as published by the Free Software Foundation; either
      10   * version 2.1 of the License, or (at your option) any later version.
      11   *
      12   * This library is distributed in the hope that it will be useful,
      13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15   * Lesser General Public License for more details.
      16   *
      17   * You should have received a copy of the GNU Lesser General
      18   * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      19   *
      20   * Author: Alexander Larsson <alexl@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 "gioerror.h"
      30  #include "glibintl.h"
      31  
      32  struct _GFileEnumeratorPrivate {
      33    /* TODO: Should be public for subclasses? */
      34    GFile *container;
      35    guint closed : 1;
      36    guint pending : 1;
      37    GAsyncReadyCallback outstanding_callback;
      38    GError *outstanding_error;
      39  };
      40  
      41  /**
      42   * GFileEnumerator:
      43   * 
      44   * `GFileEnumerator` allows you to operate on a set of [iface@Gio.File] objects,
      45   * returning a [class@Gio.FileInfo] structure for each file enumerated (e.g.
      46   * [method@Gio.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   * [method@Gio.FileEnumerator.next_file] or its asynchronous version,
      51   * [method@Gio.FileEnumerator.next_files_async]. Note that the asynchronous
      52   * version will return a list of [class@Gio.FileInfo] objects, 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 [method@GLib.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 [method@Gio.FileEnumerator.close], or
      67   * its asynchronous version, [method@Gio.FileEnumerator.close_async]. Once
      68   * a `GFileEnumerator` is closed, no further actions may be performed
      69   * on it, and it should be freed with [method@GObject.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    /**
     161     * GFileEnumerator:container:
     162     *
     163     * The container that is being enumerated.
     164     */
     165    g_object_class_install_property
     166      (gobject_class, PROP_CONTAINER,
     167       g_param_spec_object ("container", NULL, NULL,
     168                            G_TYPE_FILE,
     169                            G_PARAM_WRITABLE |
     170                            G_PARAM_CONSTRUCT_ONLY |
     171                            G_PARAM_STATIC_STRINGS));
     172  }
     173  
     174  static void
     175  g_file_enumerator_init (GFileEnumerator *enumerator)
     176  {
     177    enumerator->priv = g_file_enumerator_get_instance_private (enumerator);
     178  }
     179  
     180  /**
     181   * g_file_enumerator_next_file:
     182   * @enumerator: a #GFileEnumerator.
     183   * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
     184   * @error: location to store the error occurring, or %NULL to ignore
     185   *
     186   * Returns information for the next file in the enumerated object.
     187   * Will block until the information is available. The #GFileInfo 
     188   * returned from this function will contain attributes that match the 
     189   * attribute string that was passed when the #GFileEnumerator was created.
     190   *
     191   * See the documentation of #GFileEnumerator for information about the
     192   * order of returned files.
     193   *
     194   * On error, returns %NULL and sets @error to the error. If the
     195   * enumerator is at the end, %NULL will be returned and @error will
     196   * be unset.
     197   *
     198   * Returns: (nullable) (transfer full): A #GFileInfo or %NULL on error
     199   *    or end of enumerator.  Free the returned object with
     200   *    g_object_unref() when no longer needed.
     201   **/
     202  GFileInfo *
     203  g_file_enumerator_next_file (GFileEnumerator *enumerator,
     204  			     GCancellable *cancellable,
     205  			     GError **error)
     206  {
     207    GFileEnumeratorClass *class;
     208    GFileInfo *info;
     209    
     210    g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
     211    g_return_val_if_fail (enumerator != NULL, NULL);
     212    
     213    if (enumerator->priv->closed)
     214      {
     215        g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
     216                             _("Enumerator is closed"));
     217        return NULL;
     218      }
     219  
     220    if (enumerator->priv->pending)
     221      {
     222        g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING,
     223                             _("File enumerator has outstanding operation"));
     224        return NULL;
     225      }
     226  
     227    if (enumerator->priv->outstanding_error)
     228      {
     229        g_propagate_error (error, enumerator->priv->outstanding_error);
     230        enumerator->priv->outstanding_error = NULL;
     231        return NULL;
     232      }
     233    
     234    class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
     235  
     236    if (cancellable)
     237      g_cancellable_push_current (cancellable);
     238    
     239    enumerator->priv->pending = TRUE;
     240    info = (* class->next_file) (enumerator, cancellable, error);
     241    enumerator->priv->pending = FALSE;
     242  
     243    if (cancellable)
     244      g_cancellable_pop_current (cancellable);
     245    
     246    return info;
     247  }
     248    
     249  /**
     250   * g_file_enumerator_close:
     251   * @enumerator: a #GFileEnumerator.
     252   * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
     253   * @error: location to store the error occurring, or %NULL to ignore
     254   *
     255   * Releases all resources used by this enumerator, making the
     256   * enumerator return %G_IO_ERROR_CLOSED on all calls.
     257   *
     258   * This will be automatically called when the last reference
     259   * is dropped, but you might want to call this function to make 
     260   * sure resources are released as early as possible.
     261   *
     262   * Returns: #TRUE on success or #FALSE on error.
     263   **/
     264  gboolean
     265  g_file_enumerator_close (GFileEnumerator  *enumerator,
     266  			 GCancellable     *cancellable,
     267  			 GError          **error)
     268  {
     269    GFileEnumeratorClass *class;
     270  
     271    g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), FALSE);
     272    g_return_val_if_fail (enumerator != NULL, FALSE);
     273    
     274    class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
     275  
     276    if (enumerator->priv->closed)
     277      return TRUE;
     278    
     279    if (enumerator->priv->pending)
     280      {
     281        g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING,
     282                             _("File enumerator has outstanding operation"));
     283        return FALSE;
     284      }
     285  
     286    if (cancellable)
     287      g_cancellable_push_current (cancellable);
     288    
     289    enumerator->priv->pending = TRUE;
     290    (* class->close_fn) (enumerator, cancellable, error);
     291    enumerator->priv->pending = FALSE;
     292    enumerator->priv->closed = TRUE;
     293  
     294    if (cancellable)
     295      g_cancellable_pop_current (cancellable);
     296    
     297    return TRUE;
     298  }
     299  
     300  static void
     301  next_async_callback_wrapper (GObject      *source_object,
     302  			     GAsyncResult *res,
     303  			     gpointer      user_data)
     304  {
     305    GFileEnumerator *enumerator = G_FILE_ENUMERATOR (source_object);
     306  
     307    enumerator->priv->pending = FALSE;
     308    if (enumerator->priv->outstanding_callback)
     309      (*enumerator->priv->outstanding_callback) (source_object, res, user_data);
     310    g_object_unref (enumerator);
     311  }
     312  
     313  /**
     314   * g_file_enumerator_next_files_async:
     315   * @enumerator: a #GFileEnumerator.
     316   * @num_files: the number of file info objects to request
     317   * @io_priority: the [I/O priority][io-priority] of the request
     318   * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
     319   * @callback: (scope async) (closure user_data): a #GAsyncReadyCallback
     320   *   to call when the request is satisfied
     321   * @user_data: the data to pass to callback function
     322   *
     323   * Request information for a number of files from the enumerator asynchronously.
     324   * When all I/O for the operation is finished the @callback will be called with
     325   * the requested information. 
     326   *
     327   * See the documentation of #GFileEnumerator for information about the
     328   * order of returned files.
     329   *
     330   * Once the end of the enumerator is reached, or if an error occurs, the
     331   * @callback will be called with an empty list. In this case, the previous call
     332   * to g_file_enumerator_next_files_async() will typically have returned fewer
     333   * than @num_files items.
     334   *
     335   * If a request is cancelled the callback will be called with
     336   * %G_IO_ERROR_CANCELLED.
     337   *
     338   * This leads to the following pseudo-code usage:
     339   * |[
     340   * g_autoptr(GFile) dir = get_directory ();
     341   * g_autoptr(GFileEnumerator) enumerator = NULL;
     342   * g_autolist(GFileInfo) files = NULL;
     343   * g_autoptr(GError) local_error = NULL;
     344   *
     345   * enumerator = yield g_file_enumerate_children_async (dir,
     346   *                                                     G_FILE_ATTRIBUTE_STANDARD_NAME ","
     347   *                                                     G_FILE_ATTRIBUTE_STANDARD_TYPE,
     348   *                                                     G_FILE_QUERY_INFO_NONE,
     349   *                                                     G_PRIORITY_DEFAULT,
     350   *                                                     cancellable,
     351   *                                                     …,
     352   *                                                     &local_error);
     353   * if (enumerator == NULL)
     354   *   g_error ("Error enumerating: %s", local_error->message);
     355   *
     356   * // Loop until no files are returned, either because the end of the enumerator
     357   * // has been reached, or an error was returned.
     358   * do
     359   *   {
     360   *     files = yield g_file_enumerator_next_files_async (enumerator,
     361   *                                                       5,  // number of files to request
     362   *                                                       G_PRIORITY_DEFAULT,
     363   *                                                       cancellable,
     364   *                                                       …,
     365   *                                                       &local_error);
     366   *
     367   *     // Process the returned files, but don’t assume that exactly 5 were returned.
     368   *     for (GList *l = files; l != NULL; l = l->next)
     369   *       {
     370   *         GFileInfo *info = l->data;
     371   *         handle_file_info (info);
     372   *       }
     373   *   }
     374   * while (files != NULL);
     375   *
     376   * if (local_error != NULL &&
     377   *     !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
     378   *   g_error ("Error while enumerating: %s", local_error->message);
     379   * ]|
     380   *
     381   * During an async request no other sync and async calls are allowed, and will
     382   * result in %G_IO_ERROR_PENDING errors. 
     383   *
     384   * Any outstanding I/O request with higher priority (lower numerical value) will
     385   * be executed before an outstanding request with lower priority. Default
     386   * priority is %G_PRIORITY_DEFAULT.
     387   **/
     388  void
     389  g_file_enumerator_next_files_async (GFileEnumerator     *enumerator,
     390  				    int                  num_files,
     391  				    int                  io_priority,
     392  				    GCancellable        *cancellable,
     393  				    GAsyncReadyCallback  callback,
     394  				    gpointer             user_data)
     395  {
     396    GFileEnumeratorClass *class;
     397  
     398    g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
     399    g_return_if_fail (enumerator != NULL);
     400    g_return_if_fail (num_files >= 0);
     401  
     402    if (num_files == 0)
     403      {
     404        GTask *task;
     405  
     406        task = g_task_new (enumerator, cancellable, callback, user_data);
     407        g_task_set_source_tag (task, g_file_enumerator_next_files_async);
     408        g_task_return_pointer (task, NULL, NULL);
     409        g_object_unref (task);
     410        return;
     411      }
     412    
     413    if (enumerator->priv->closed)
     414      {
     415        g_task_report_new_error (enumerator, callback, user_data,
     416                                 g_file_enumerator_next_files_async,
     417                                 G_IO_ERROR, G_IO_ERROR_CLOSED,
     418                                 _("File enumerator is already closed"));
     419        return;
     420      }
     421    
     422    if (enumerator->priv->pending)
     423      {
     424        g_task_report_new_error (enumerator, callback, user_data,
     425                                 g_file_enumerator_next_files_async,
     426                                 G_IO_ERROR, G_IO_ERROR_PENDING,
     427                                 _("File enumerator has outstanding operation"));
     428        return;
     429      }
     430  
     431    class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
     432    
     433    enumerator->priv->pending = TRUE;
     434    enumerator->priv->outstanding_callback = callback;
     435    g_object_ref (enumerator);
     436    (* class->next_files_async) (enumerator, num_files, io_priority, cancellable, 
     437  			       next_async_callback_wrapper, user_data);
     438  }
     439  
     440  /**
     441   * g_file_enumerator_next_files_finish:
     442   * @enumerator: a #GFileEnumerator.
     443   * @result: a #GAsyncResult.
     444   * @error: a #GError location to store the error occurring, or %NULL to 
     445   * ignore.
     446   * 
     447   * Finishes the asynchronous operation started with g_file_enumerator_next_files_async().
     448   * 
     449   * Returns: (transfer full) (element-type Gio.FileInfo): a #GList of #GFileInfos. You must free the list with 
     450   *     g_list_free() and unref the infos with g_object_unref() when you're 
     451   *     done with them.
     452   **/
     453  GList *
     454  g_file_enumerator_next_files_finish (GFileEnumerator  *enumerator,
     455  				     GAsyncResult     *result,
     456  				     GError          **error)
     457  {
     458    GFileEnumeratorClass *class;
     459    
     460    g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
     461    g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
     462    
     463    if (g_async_result_legacy_propagate_error (result, error))
     464      return NULL;
     465    else if (g_async_result_is_tagged (result, g_file_enumerator_next_files_async))
     466      return g_task_propagate_pointer (G_TASK (result), error);
     467    
     468    class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
     469    return class->next_files_finish (enumerator, result, error);
     470  }
     471  
     472  static void
     473  close_async_callback_wrapper (GObject      *source_object,
     474  			      GAsyncResult *res,
     475  			      gpointer      user_data)
     476  {
     477    GFileEnumerator *enumerator = G_FILE_ENUMERATOR (source_object);
     478    
     479    enumerator->priv->pending = FALSE;
     480    enumerator->priv->closed = TRUE;
     481    if (enumerator->priv->outstanding_callback)
     482      (*enumerator->priv->outstanding_callback) (source_object, res, user_data);
     483    g_object_unref (enumerator);
     484  }
     485  
     486  /**
     487   * g_file_enumerator_close_async:
     488   * @enumerator: a #GFileEnumerator.
     489   * @io_priority: the [I/O priority][io-priority] of the request
     490   * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
     491   * @callback: (scope async) (closure user_data): a #GAsyncReadyCallback
     492   *   to call when the request is satisfied
     493   * @user_data: the data to pass to callback function
     494   *
     495   * Asynchronously closes the file enumerator. 
     496   *
     497   * If @cancellable is not %NULL, then the operation can be cancelled by
     498   * triggering the cancellable object from another thread. If the operation
     499   * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned in 
     500   * g_file_enumerator_close_finish(). 
     501   **/
     502  void
     503  g_file_enumerator_close_async (GFileEnumerator     *enumerator,
     504  			       int                  io_priority,
     505  			       GCancellable        *cancellable,
     506  			       GAsyncReadyCallback  callback,
     507  			       gpointer             user_data)
     508  {
     509    GFileEnumeratorClass *class;
     510  
     511    g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
     512  
     513    if (enumerator->priv->closed)
     514      {
     515        g_task_report_new_error (enumerator, callback, user_data,
     516                                 g_file_enumerator_close_async,
     517                                 G_IO_ERROR, G_IO_ERROR_CLOSED,
     518                                 _("File enumerator is already closed"));
     519        return;
     520      }
     521    
     522    if (enumerator->priv->pending)
     523      {
     524        g_task_report_new_error (enumerator, callback, user_data,
     525                                 g_file_enumerator_close_async,
     526                                 G_IO_ERROR, G_IO_ERROR_PENDING,
     527                                 _("File enumerator has outstanding operation"));
     528        return;
     529      }
     530  
     531    class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
     532    
     533    enumerator->priv->pending = TRUE;
     534    enumerator->priv->outstanding_callback = callback;
     535    g_object_ref (enumerator);
     536    (* class->close_async) (enumerator, io_priority, cancellable,
     537  			  close_async_callback_wrapper, user_data);
     538  }
     539  
     540  /**
     541   * g_file_enumerator_close_finish:
     542   * @enumerator: a #GFileEnumerator.
     543   * @result: a #GAsyncResult.
     544   * @error: a #GError location to store the error occurring, or %NULL to 
     545   * ignore.
     546   * 
     547   * Finishes closing a file enumerator, started from g_file_enumerator_close_async().
     548   * 
     549   * If the file enumerator was already closed when g_file_enumerator_close_async() 
     550   * was called, then this function will report %G_IO_ERROR_CLOSED in @error, and 
     551   * return %FALSE. If the file enumerator had pending operation when the close 
     552   * operation was started, then this function will report %G_IO_ERROR_PENDING, and
     553   * return %FALSE.  If @cancellable was not %NULL, then the operation may have been 
     554   * cancelled by triggering the cancellable object from another thread. If the operation
     555   * was cancelled, the error %G_IO_ERROR_CANCELLED will be set, and %FALSE will be 
     556   * returned. 
     557   * 
     558   * Returns: %TRUE if the close operation has finished successfully.
     559   **/
     560  gboolean
     561  g_file_enumerator_close_finish (GFileEnumerator  *enumerator,
     562  				GAsyncResult     *result,
     563  				GError          **error)
     564  {
     565    GFileEnumeratorClass *class;
     566  
     567    g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), FALSE);
     568    g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
     569    
     570    if (g_async_result_legacy_propagate_error (result, error))
     571      return FALSE;
     572    else if (g_async_result_is_tagged (result, g_file_enumerator_close_async))
     573      return g_task_propagate_boolean (G_TASK (result), error);
     574  
     575    class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
     576    return class->close_finish (enumerator, result, error);
     577  }
     578  
     579  /**
     580   * g_file_enumerator_is_closed:
     581   * @enumerator: a #GFileEnumerator.
     582   *
     583   * Checks if the file enumerator has been closed.
     584   * 
     585   * Returns: %TRUE if the @enumerator is closed.
     586   **/
     587  gboolean
     588  g_file_enumerator_is_closed (GFileEnumerator *enumerator)
     589  {
     590    g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), TRUE);
     591    
     592    return enumerator->priv->closed;
     593  }
     594  
     595  /**
     596   * g_file_enumerator_has_pending:
     597   * @enumerator: a #GFileEnumerator.
     598   * 
     599   * Checks if the file enumerator has pending operations.
     600   *
     601   * Returns: %TRUE if the @enumerator has pending operations.
     602   **/
     603  gboolean
     604  g_file_enumerator_has_pending (GFileEnumerator *enumerator)
     605  {
     606    g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), TRUE);
     607    
     608    return enumerator->priv->pending;
     609  }
     610  
     611  /**
     612   * g_file_enumerator_set_pending:
     613   * @enumerator: a #GFileEnumerator.
     614   * @pending: a boolean value.
     615   * 
     616   * Sets the file enumerator as having pending operations.
     617   **/
     618  void
     619  g_file_enumerator_set_pending (GFileEnumerator *enumerator,
     620  			       gboolean         pending)
     621  {
     622    g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
     623    
     624    enumerator->priv->pending = pending;
     625  }
     626  
     627  /**
     628   * g_file_enumerator_iterate:
     629   * @direnum: an open #GFileEnumerator
     630   * @out_info: (out) (transfer none) (optional): Output location for the next #GFileInfo, or %NULL
     631   * @out_child: (out) (transfer none) (optional): Output location for the next #GFile, or %NULL
     632   * @cancellable: a #GCancellable
     633   * @error: a #GError
     634   *
     635   * This is a version of g_file_enumerator_next_file() that's easier to
     636   * use correctly from C programs.  With g_file_enumerator_next_file(),
     637   * the gboolean return value signifies "end of iteration or error", which
     638   * requires allocation of a temporary #GError.
     639   *
     640   * In contrast, with this function, a %FALSE return from
     641   * g_file_enumerator_iterate() *always* means
     642   * "error".  End of iteration is signaled by @out_info or @out_child being %NULL.
     643   *
     644   * Another crucial difference is that the references for @out_info and
     645   * @out_child are owned by @direnum (they are cached as hidden
     646   * properties).  You must not unref them in your own code.  This makes
     647   * memory management significantly easier for C code in combination
     648   * with loops.
     649   *
     650   * Finally, this function optionally allows retrieving a #GFile as
     651   * well.
     652   *
     653   * You must specify at least one of @out_info or @out_child.
     654   *
     655   * The code pattern for correctly using g_file_enumerator_iterate() from C
     656   * is:
     657   *
     658   * |[
     659   * direnum = g_file_enumerate_children (file, ...);
     660   * while (TRUE)
     661   *   {
     662   *     GFileInfo *info;
     663   *     if (!g_file_enumerator_iterate (direnum, &info, NULL, cancellable, error))
     664   *       goto out;
     665   *     if (!info)
     666   *       break;
     667   *     ... do stuff with "info"; do not unref it! ...
     668   *   }
     669   * 
     670   * out:
     671   *   g_object_unref (direnum); // Note: frees the last @info
     672   * ]|
     673   *
     674   *
     675   * Since: 2.44
     676   */
     677  gboolean
     678  g_file_enumerator_iterate (GFileEnumerator  *direnum,
     679                             GFileInfo       **out_info,
     680                             GFile           **out_child,
     681                             GCancellable     *cancellable,
     682                             GError          **error)
     683  {
     684    gboolean ret = FALSE;
     685    GError *temp_error = NULL;
     686    GFileInfo *ret_info = NULL;
     687  
     688    static GQuark cached_info_quark;
     689    static GQuark cached_child_quark;
     690    static gsize quarks_initialized;
     691  
     692    g_return_val_if_fail (direnum != NULL, FALSE);
     693    g_return_val_if_fail (out_info != NULL || out_child != NULL, FALSE);
     694  
     695    if (g_once_init_enter (&quarks_initialized))
     696      {
     697        cached_info_quark = g_quark_from_static_string ("g-cached-info");
     698        cached_child_quark = g_quark_from_static_string ("g-cached-child");
     699        g_once_init_leave (&quarks_initialized, 1);
     700      }
     701  
     702    ret_info = g_file_enumerator_next_file (direnum, cancellable, &temp_error);
     703    if (temp_error != NULL)
     704      {
     705        g_propagate_error (error, temp_error);
     706        goto out;
     707      }
     708  
     709    if (ret_info)
     710      { 
     711        if (out_child != NULL)
     712          {
     713            const char *name = g_file_info_get_name (ret_info);
     714  
     715            if (G_UNLIKELY (name == NULL))
     716              {
     717                g_critical ("g_file_enumerator_iterate() created without standard::name");
     718                g_return_val_if_reached (FALSE);
     719              }
     720            else
     721              {
     722                *out_child = g_file_get_child (g_file_enumerator_get_container (direnum), name);
     723                g_object_set_qdata_full ((GObject*)direnum, cached_child_quark, *out_child, (GDestroyNotify)g_object_unref);
     724              }
     725          }
     726        if (out_info != NULL)
     727          {
     728            g_object_set_qdata_full ((GObject*)direnum, cached_info_quark, ret_info, (GDestroyNotify)g_object_unref);
     729            *out_info = ret_info;
     730          }
     731        else
     732          g_object_unref (ret_info);
     733      }
     734    else
     735      {
     736        if (out_info)
     737          *out_info = NULL;
     738        if (out_child)
     739          *out_child = NULL;
     740      }
     741  
     742    ret = TRUE;
     743   out:
     744    return ret;
     745  }
     746  
     747  /**
     748   * g_file_enumerator_get_container:
     749   * @enumerator: a #GFileEnumerator
     750   *
     751   * Get the #GFile container which is being enumerated.
     752   *
     753   * Returns: (transfer none): the #GFile which is being enumerated.
     754   *
     755   * Since: 2.18
     756   */
     757  GFile *
     758  g_file_enumerator_get_container (GFileEnumerator *enumerator)
     759  {
     760    g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
     761  
     762    return enumerator->priv->container;
     763  }
     764  
     765  /**
     766   * g_file_enumerator_get_child:
     767   * @enumerator: a #GFileEnumerator
     768   * @info: a #GFileInfo gotten from g_file_enumerator_next_file()
     769   *   or the async equivalents.
     770   *
     771   * Return a new #GFile which refers to the file named by @info in the source
     772   * directory of @enumerator.  This function is primarily intended to be used
     773   * inside loops with g_file_enumerator_next_file().
     774   *
     775   * To use this, %G_FILE_ATTRIBUTE_STANDARD_NAME must have been listed in the
     776   * attributes list used when creating the #GFileEnumerator.
     777   *
     778   * This is a convenience method that's equivalent to:
     779   * |[<!-- language="C" -->
     780   *   gchar *name = g_file_info_get_name (info);
     781   *   GFile *child = g_file_get_child (g_file_enumerator_get_container (enumr),
     782   *                                    name);
     783   * ]|
     784   *
     785   * Returns: (transfer full): a #GFile for the #GFileInfo passed it.
     786   *
     787   * Since: 2.36
     788   */
     789  GFile *
     790  g_file_enumerator_get_child (GFileEnumerator *enumerator,
     791                               GFileInfo       *info)
     792  {
     793    const gchar *name;
     794  
     795    g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
     796    g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
     797  
     798    name = g_file_info_get_name (info);
     799  
     800    if (G_UNLIKELY (name == NULL))
     801      {
     802        g_critical ("GFileEnumerator created without standard::name");
     803        g_return_val_if_reached (NULL);
     804      }
     805  
     806    return g_file_get_child (enumerator->priv->container, name);
     807  }
     808  
     809  static void
     810  next_async_op_free (GList *files)
     811  {
     812    g_list_free_full (files, g_object_unref);
     813  }
     814  
     815  static void
     816  next_files_thread (GTask        *task,
     817                     gpointer      source_object,
     818                     gpointer      task_data,
     819                     GCancellable *cancellable)
     820  {
     821    GFileEnumerator *enumerator = source_object;
     822    int num_files = GPOINTER_TO_INT (task_data);
     823    GFileEnumeratorClass *class;
     824    GList *files = NULL;
     825    GError *error = NULL;
     826    GFileInfo *info;
     827    int i;
     828  
     829    class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
     830  
     831    for (i = 0; i < num_files; i++)
     832      {
     833        if (g_cancellable_set_error_if_cancelled (cancellable, &error))
     834  	info = NULL;
     835        else
     836  	info = class->next_file (enumerator, cancellable, &error);
     837        
     838        if (info == NULL)
     839  	{
     840  	  /* If we get an error after first file, return that on next operation */
     841  	  if (error != NULL && i > 0)
     842  	    {
     843  	      if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
     844  		g_error_free (error); /* Never propagate cancel errors to other call */
     845  	      else
     846  		enumerator->priv->outstanding_error = error;
     847  	      error = NULL;
     848  	    }
     849  	      
     850  	  break;
     851  	}
     852        else
     853  	files = g_list_prepend (files, info);
     854      }
     855  
     856    if (error)
     857      {
     858        g_list_free_full (files, g_object_unref);
     859        g_task_return_error (task, error);
     860      }
     861    else
     862      g_task_return_pointer (task, files, (GDestroyNotify)next_async_op_free);
     863  }
     864  
     865  static void
     866  g_file_enumerator_real_next_files_async (GFileEnumerator     *enumerator,
     867  					 int                  num_files,
     868  					 int                  io_priority,
     869  					 GCancellable        *cancellable,
     870  					 GAsyncReadyCallback  callback,
     871  					 gpointer             user_data)
     872  {
     873    GTask *task;
     874  
     875    task = g_task_new (enumerator, cancellable, callback, user_data);
     876    g_task_set_source_tag (task, g_file_enumerator_real_next_files_async);
     877    g_task_set_task_data (task, GINT_TO_POINTER (num_files), NULL);
     878    g_task_set_priority (task, io_priority);
     879  
     880    g_task_run_in_thread (task, next_files_thread);
     881    g_object_unref (task);
     882  }
     883  
     884  static GList *
     885  g_file_enumerator_real_next_files_finish (GFileEnumerator                *enumerator,
     886  					  GAsyncResult                   *result,
     887  					  GError                        **error)
     888  {
     889    g_return_val_if_fail (g_task_is_valid (result, enumerator), NULL);
     890  
     891    return g_task_propagate_pointer (G_TASK (result), error);
     892  }
     893  
     894  static void
     895  close_async_thread (GTask        *task,
     896                      gpointer      source_object,
     897                      gpointer      task_data,
     898                      GCancellable *cancellable)
     899  {
     900    GFileEnumerator *enumerator = source_object;
     901    GFileEnumeratorClass *class;
     902    GError *error = NULL;
     903    gboolean result;
     904  
     905    class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
     906    result = class->close_fn (enumerator, cancellable, &error);
     907    if (result)
     908      g_task_return_boolean (task, TRUE);
     909    else
     910      g_task_return_error (task, error);
     911  }
     912  
     913  static void
     914  g_file_enumerator_real_close_async (GFileEnumerator     *enumerator,
     915  				    int                  io_priority,
     916  				    GCancellable        *cancellable,
     917  				    GAsyncReadyCallback  callback,
     918  				    gpointer             user_data)
     919  {
     920    GTask *task;
     921  
     922    task = g_task_new (enumerator, cancellable, callback, user_data);
     923    g_task_set_source_tag (task, g_file_enumerator_real_close_async);
     924    g_task_set_priority (task, io_priority);
     925    
     926    g_task_run_in_thread (task, close_async_thread);
     927    g_object_unref (task);
     928  }
     929  
     930  static gboolean
     931  g_file_enumerator_real_close_finish (GFileEnumerator  *enumerator,
     932                                       GAsyncResult     *result,
     933                                       GError          **error)
     934  {
     935    g_return_val_if_fail (g_task_is_valid (result, enumerator), FALSE);
     936  
     937    return g_task_propagate_boolean (G_TASK (result), error);
     938  }