LCOV - code coverage report
Current view: top level - gio - gfileenumerator.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 40.6 % 256 104
Test Date: 2024-11-26 05:23:01 Functions: 50.0 % 30 15
Branches: - 0 0

             Branch data     Line data    Source code
       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                 :        2121 : 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                 :         223 : g_file_enumerator_set_property (GObject      *object,
     100                 :             :                                 guint         property_id,
     101                 :             :                                 const GValue *value,
     102                 :             :                                 GParamSpec   *pspec)
     103                 :             : {
     104                 :             :   GFileEnumerator *enumerator;
     105                 :             :   
     106                 :         223 :   enumerator = G_FILE_ENUMERATOR (object);
     107                 :             :   
     108                 :         223 :   switch (property_id) {
     109                 :         223 :   case PROP_CONTAINER:
     110                 :         223 :     enumerator->priv->container = g_value_dup_object (value);
     111                 :         223 :     break;
     112                 :           0 :   default:
     113                 :           0 :     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     114                 :           0 :     break;
     115                 :             :   }
     116                 :         223 : }
     117                 :             : 
     118                 :             : static void
     119                 :         223 : g_file_enumerator_dispose (GObject *object)
     120                 :             : {
     121                 :             :   GFileEnumerator *enumerator;
     122                 :             : 
     123                 :         223 :   enumerator = G_FILE_ENUMERATOR (object);
     124                 :             :   
     125                 :         223 :   if (enumerator->priv->container) {
     126                 :         223 :     g_object_unref (enumerator->priv->container);
     127                 :         223 :     enumerator->priv->container = NULL;
     128                 :             :   }
     129                 :             : 
     130                 :         223 :   G_OBJECT_CLASS (g_file_enumerator_parent_class)->dispose (object);
     131                 :         223 : }
     132                 :             : 
     133                 :             : static void
     134                 :         223 : g_file_enumerator_finalize (GObject *object)
     135                 :             : {
     136                 :             :   GFileEnumerator *enumerator;
     137                 :             : 
     138                 :         223 :   enumerator = G_FILE_ENUMERATOR (object);
     139                 :             :   
     140                 :         223 :   if (!enumerator->priv->closed)
     141                 :         199 :     g_file_enumerator_close (enumerator, NULL, NULL);
     142                 :             : 
     143                 :         223 :   G_OBJECT_CLASS (g_file_enumerator_parent_class)->finalize (object);
     144                 :         223 : }
     145                 :             : 
     146                 :             : static void
     147                 :           5 : g_file_enumerator_class_init (GFileEnumeratorClass *klass)
     148                 :             : {
     149                 :           5 :   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     150                 :             : 
     151                 :           5 :   gobject_class->set_property = g_file_enumerator_set_property;
     152                 :           5 :   gobject_class->dispose = g_file_enumerator_dispose;
     153                 :           5 :   gobject_class->finalize = g_file_enumerator_finalize;
     154                 :             : 
     155                 :           5 :   klass->next_files_async = g_file_enumerator_real_next_files_async;
     156                 :           5 :   klass->next_files_finish = g_file_enumerator_real_next_files_finish;
     157                 :           5 :   klass->close_async = g_file_enumerator_real_close_async;
     158                 :           5 :   klass->close_finish = g_file_enumerator_real_close_finish;
     159                 :             : 
     160                 :             :   /**
     161                 :             :    * GFileEnumerator:container:
     162                 :             :    *
     163                 :             :    * The container that is being enumerated.
     164                 :             :    */
     165                 :           5 :   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                 :           5 : }
     173                 :             : 
     174                 :             : static void
     175                 :         223 : g_file_enumerator_init (GFileEnumerator *enumerator)
     176                 :             : {
     177                 :         223 :   enumerator->priv = g_file_enumerator_get_instance_private (enumerator);
     178                 :         223 : }
     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                 :         576 : g_file_enumerator_next_file (GFileEnumerator *enumerator,
     204                 :             :                              GCancellable *cancellable,
     205                 :             :                              GError **error)
     206                 :             : {
     207                 :             :   GFileEnumeratorClass *class;
     208                 :             :   GFileInfo *info;
     209                 :             :   
     210                 :         576 :   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
     211                 :         576 :   g_return_val_if_fail (enumerator != NULL, NULL);
     212                 :             :   
     213                 :         576 :   if (enumerator->priv->closed)
     214                 :             :     {
     215                 :           0 :       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
     216                 :             :                            _("Enumerator is closed"));
     217                 :           0 :       return NULL;
     218                 :             :     }
     219                 :             : 
     220                 :         576 :   if (enumerator->priv->pending)
     221                 :             :     {
     222                 :           0 :       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING,
     223                 :             :                            _("File enumerator has outstanding operation"));
     224                 :           0 :       return NULL;
     225                 :             :     }
     226                 :             : 
     227                 :         576 :   if (enumerator->priv->outstanding_error)
     228                 :             :     {
     229                 :           0 :       g_propagate_error (error, enumerator->priv->outstanding_error);
     230                 :           0 :       enumerator->priv->outstanding_error = NULL;
     231                 :           0 :       return NULL;
     232                 :             :     }
     233                 :             :   
     234                 :         576 :   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
     235                 :             : 
     236                 :         576 :   if (cancellable)
     237                 :           1 :     g_cancellable_push_current (cancellable);
     238                 :             :   
     239                 :         576 :   enumerator->priv->pending = TRUE;
     240                 :         576 :   info = (* class->next_file) (enumerator, cancellable, error);
     241                 :         576 :   enumerator->priv->pending = FALSE;
     242                 :             : 
     243                 :         576 :   if (cancellable)
     244                 :           1 :     g_cancellable_pop_current (cancellable);
     245                 :             :   
     246                 :         576 :   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                 :         223 : g_file_enumerator_close (GFileEnumerator  *enumerator,
     266                 :             :                          GCancellable     *cancellable,
     267                 :             :                          GError          **error)
     268                 :             : {
     269                 :             :   GFileEnumeratorClass *class;
     270                 :             : 
     271                 :         223 :   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), FALSE);
     272                 :         223 :   g_return_val_if_fail (enumerator != NULL, FALSE);
     273                 :             :   
     274                 :         223 :   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
     275                 :             : 
     276                 :         223 :   if (enumerator->priv->closed)
     277                 :           0 :     return TRUE;
     278                 :             :   
     279                 :         223 :   if (enumerator->priv->pending)
     280                 :             :     {
     281                 :           0 :       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING,
     282                 :             :                            _("File enumerator has outstanding operation"));
     283                 :           0 :       return FALSE;
     284                 :             :     }
     285                 :             : 
     286                 :         223 :   if (cancellable)
     287                 :           0 :     g_cancellable_push_current (cancellable);
     288                 :             :   
     289                 :         223 :   enumerator->priv->pending = TRUE;
     290                 :         223 :   (* class->close_fn) (enumerator, cancellable, error);
     291                 :         223 :   enumerator->priv->pending = FALSE;
     292                 :         223 :   enumerator->priv->closed = TRUE;
     293                 :             : 
     294                 :         223 :   if (cancellable)
     295                 :           0 :     g_cancellable_pop_current (cancellable);
     296                 :             :   
     297                 :         223 :   return TRUE;
     298                 :             : }
     299                 :             : 
     300                 :             : static void
     301                 :           0 : next_async_callback_wrapper (GObject      *source_object,
     302                 :             :                              GAsyncResult *res,
     303                 :             :                              gpointer      user_data)
     304                 :             : {
     305                 :           0 :   GFileEnumerator *enumerator = G_FILE_ENUMERATOR (source_object);
     306                 :             : 
     307                 :           0 :   enumerator->priv->pending = FALSE;
     308                 :           0 :   if (enumerator->priv->outstanding_callback)
     309                 :           0 :     (*enumerator->priv->outstanding_callback) (source_object, res, user_data);
     310                 :           0 :   g_object_unref (enumerator);
     311                 :           0 : }
     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](iface.AsyncResult.html#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                 :           0 : 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                 :           0 :   g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
     399                 :           0 :   g_return_if_fail (enumerator != NULL);
     400                 :           0 :   g_return_if_fail (num_files >= 0);
     401                 :             : 
     402                 :           0 :   if (num_files == 0)
     403                 :             :     {
     404                 :             :       GTask *task;
     405                 :             : 
     406                 :           0 :       task = g_task_new (enumerator, cancellable, callback, user_data);
     407                 :           0 :       g_task_set_source_tag (task, g_file_enumerator_next_files_async);
     408                 :           0 :       g_task_return_pointer (task, NULL, NULL);
     409                 :           0 :       g_object_unref (task);
     410                 :           0 :       return;
     411                 :             :     }
     412                 :             :   
     413                 :           0 :   if (enumerator->priv->closed)
     414                 :             :     {
     415                 :           0 :       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                 :           0 :                                _("File enumerator is already closed"));
     419                 :           0 :       return;
     420                 :             :     }
     421                 :             :   
     422                 :           0 :   if (enumerator->priv->pending)
     423                 :             :     {
     424                 :           0 :       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                 :           0 :                                _("File enumerator has outstanding operation"));
     428                 :           0 :       return;
     429                 :             :     }
     430                 :             : 
     431                 :           0 :   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
     432                 :             :   
     433                 :           0 :   enumerator->priv->pending = TRUE;
     434                 :           0 :   enumerator->priv->outstanding_callback = callback;
     435                 :           0 :   g_object_ref (enumerator);
     436                 :           0 :   (* 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                 :           0 : g_file_enumerator_next_files_finish (GFileEnumerator  *enumerator,
     455                 :             :                                      GAsyncResult     *result,
     456                 :             :                                      GError          **error)
     457                 :             : {
     458                 :             :   GFileEnumeratorClass *class;
     459                 :             :   
     460                 :           0 :   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
     461                 :           0 :   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
     462                 :             :   
     463                 :           0 :   if (g_async_result_legacy_propagate_error (result, error))
     464                 :           0 :     return NULL;
     465                 :           0 :   else if (g_async_result_is_tagged (result, g_file_enumerator_next_files_async))
     466                 :           0 :     return g_task_propagate_pointer (G_TASK (result), error);
     467                 :             :   
     468                 :           0 :   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
     469                 :           0 :   return class->next_files_finish (enumerator, result, error);
     470                 :             : }
     471                 :             : 
     472                 :             : static void
     473                 :           0 : close_async_callback_wrapper (GObject      *source_object,
     474                 :             :                               GAsyncResult *res,
     475                 :             :                               gpointer      user_data)
     476                 :             : {
     477                 :           0 :   GFileEnumerator *enumerator = G_FILE_ENUMERATOR (source_object);
     478                 :             :   
     479                 :           0 :   enumerator->priv->pending = FALSE;
     480                 :           0 :   enumerator->priv->closed = TRUE;
     481                 :           0 :   if (enumerator->priv->outstanding_callback)
     482                 :           0 :     (*enumerator->priv->outstanding_callback) (source_object, res, user_data);
     483                 :           0 :   g_object_unref (enumerator);
     484                 :           0 : }
     485                 :             : 
     486                 :             : /**
     487                 :             :  * g_file_enumerator_close_async:
     488                 :             :  * @enumerator: a #GFileEnumerator.
     489                 :             :  * @io_priority: the [I/O priority](iface.AsyncResult.html#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                 :           0 : 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                 :           0 :   g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
     512                 :             : 
     513                 :           0 :   if (enumerator->priv->closed)
     514                 :             :     {
     515                 :           0 :       g_task_report_new_error (enumerator, callback, user_data,
     516                 :             :                                g_file_enumerator_close_async,
     517                 :             :                                G_IO_ERROR, G_IO_ERROR_CLOSED,
     518                 :           0 :                                _("File enumerator is already closed"));
     519                 :           0 :       return;
     520                 :             :     }
     521                 :             :   
     522                 :           0 :   if (enumerator->priv->pending)
     523                 :             :     {
     524                 :           0 :       g_task_report_new_error (enumerator, callback, user_data,
     525                 :             :                                g_file_enumerator_close_async,
     526                 :             :                                G_IO_ERROR, G_IO_ERROR_PENDING,
     527                 :           0 :                                _("File enumerator has outstanding operation"));
     528                 :           0 :       return;
     529                 :             :     }
     530                 :             : 
     531                 :           0 :   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
     532                 :             :   
     533                 :           0 :   enumerator->priv->pending = TRUE;
     534                 :           0 :   enumerator->priv->outstanding_callback = callback;
     535                 :           0 :   g_object_ref (enumerator);
     536                 :           0 :   (* 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                 :           0 : g_file_enumerator_close_finish (GFileEnumerator  *enumerator,
     562                 :             :                                 GAsyncResult     *result,
     563                 :             :                                 GError          **error)
     564                 :             : {
     565                 :             :   GFileEnumeratorClass *class;
     566                 :             : 
     567                 :           0 :   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), FALSE);
     568                 :           0 :   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
     569                 :             :   
     570                 :           0 :   if (g_async_result_legacy_propagate_error (result, error))
     571                 :           0 :     return FALSE;
     572                 :           0 :   else if (g_async_result_is_tagged (result, g_file_enumerator_close_async))
     573                 :           0 :     return g_task_propagate_boolean (G_TASK (result), error);
     574                 :             : 
     575                 :           0 :   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
     576                 :           0 :   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                 :           9 : g_file_enumerator_is_closed (GFileEnumerator *enumerator)
     589                 :             : {
     590                 :           9 :   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), TRUE);
     591                 :             :   
     592                 :           9 :   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                 :           0 : g_file_enumerator_has_pending (GFileEnumerator *enumerator)
     605                 :             : {
     606                 :           0 :   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), TRUE);
     607                 :             :   
     608                 :           0 :   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                 :           0 : g_file_enumerator_set_pending (GFileEnumerator *enumerator,
     620                 :             :                                gboolean         pending)
     621                 :             : {
     622                 :           0 :   g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
     623                 :             :   
     624                 :           0 :   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                 :         298 : g_file_enumerator_iterate (GFileEnumerator  *direnum,
     679                 :             :                            GFileInfo       **out_info,
     680                 :             :                            GFile           **out_child,
     681                 :             :                            GCancellable     *cancellable,
     682                 :             :                            GError          **error)
     683                 :             : {
     684                 :         298 :   gboolean ret = FALSE;
     685                 :         298 :   GError *temp_error = NULL;
     686                 :         298 :   GFileInfo *ret_info = NULL;
     687                 :             : 
     688                 :             :   static GQuark cached_info_quark;
     689                 :             :   static GQuark cached_child_quark;
     690                 :             :   static gsize quarks_initialized;
     691                 :             : 
     692                 :         298 :   g_return_val_if_fail (direnum != NULL, FALSE);
     693                 :         298 :   g_return_val_if_fail (out_info != NULL || out_child != NULL, FALSE);
     694                 :             : 
     695                 :         298 :   if (g_once_init_enter (&quarks_initialized))
     696                 :             :     {
     697                 :           1 :       cached_info_quark = g_quark_from_static_string ("g-cached-info");
     698                 :           1 :       cached_child_quark = g_quark_from_static_string ("g-cached-child");
     699                 :           1 :       g_once_init_leave (&quarks_initialized, 1);
     700                 :             :     }
     701                 :             : 
     702                 :         298 :   ret_info = g_file_enumerator_next_file (direnum, cancellable, &temp_error);
     703                 :         298 :   if (temp_error != NULL)
     704                 :             :     {
     705                 :           0 :       g_propagate_error (error, temp_error);
     706                 :           0 :       goto out;
     707                 :             :     }
     708                 :             : 
     709                 :         298 :   if (ret_info)
     710                 :             :     { 
     711                 :         198 :       if (out_child != NULL)
     712                 :             :         {
     713                 :           2 :           const char *name = g_file_info_get_name (ret_info);
     714                 :             : 
     715                 :           2 :           if (G_UNLIKELY (name == NULL))
     716                 :             :             {
     717                 :           0 :               g_critical ("g_file_enumerator_iterate() created without standard::name");
     718                 :             :               g_return_val_if_reached (FALSE);
     719                 :             :             }
     720                 :             :           else
     721                 :             :             {
     722                 :           2 :               *out_child = g_file_get_child (g_file_enumerator_get_container (direnum), name);
     723                 :           2 :               g_object_set_qdata_full ((GObject*)direnum, cached_child_quark, *out_child, (GDestroyNotify)g_object_unref);
     724                 :             :             }
     725                 :             :         }
     726                 :         198 :       if (out_info != NULL)
     727                 :             :         {
     728                 :         196 :           g_object_set_qdata_full ((GObject*)direnum, cached_info_quark, ret_info, (GDestroyNotify)g_object_unref);
     729                 :         196 :           *out_info = ret_info;
     730                 :             :         }
     731                 :             :       else
     732                 :           2 :         g_object_unref (ret_info);
     733                 :             :     }
     734                 :             :   else
     735                 :             :     {
     736                 :         100 :       if (out_info)
     737                 :          99 :         *out_info = NULL;
     738                 :         100 :       if (out_child)
     739                 :           1 :         *out_child = NULL;
     740                 :             :     }
     741                 :             : 
     742                 :         298 :   ret = TRUE;
     743                 :         298 :  out:
     744                 :         298 :   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                 :          11 : g_file_enumerator_get_container (GFileEnumerator *enumerator)
     759                 :             : {
     760                 :          11 :   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
     761                 :             : 
     762                 :          11 :   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                 :          55 : g_file_enumerator_get_child (GFileEnumerator *enumerator,
     791                 :             :                              GFileInfo       *info)
     792                 :             : {
     793                 :             :   const gchar *name;
     794                 :             : 
     795                 :          55 :   g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
     796                 :          55 :   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
     797                 :             : 
     798                 :          55 :   name = g_file_info_get_name (info);
     799                 :             : 
     800                 :          55 :   if (G_UNLIKELY (name == NULL))
     801                 :             :     {
     802                 :           0 :       g_critical ("GFileEnumerator created without standard::name");
     803                 :             :       g_return_val_if_reached (NULL);
     804                 :             :     }
     805                 :             : 
     806                 :          55 :   return g_file_get_child (enumerator->priv->container, name);
     807                 :             : }
     808                 :             : 
     809                 :             : static void
     810                 :           0 : next_async_op_free (GList *files)
     811                 :             : {
     812                 :           0 :   g_list_free_full (files, g_object_unref);
     813                 :           0 : }
     814                 :             : 
     815                 :             : static void
     816                 :           0 : next_files_thread (GTask        *task,
     817                 :             :                    gpointer      source_object,
     818                 :             :                    gpointer      task_data,
     819                 :             :                    GCancellable *cancellable)
     820                 :             : {
     821                 :           0 :   GFileEnumerator *enumerator = source_object;
     822                 :           0 :   int num_files = GPOINTER_TO_INT (task_data);
     823                 :             :   GFileEnumeratorClass *class;
     824                 :           0 :   GList *files = NULL;
     825                 :           0 :   GError *error = NULL;
     826                 :             :   GFileInfo *info;
     827                 :             :   int i;
     828                 :             : 
     829                 :           0 :   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
     830                 :             : 
     831                 :           0 :   for (i = 0; i < num_files; i++)
     832                 :             :     {
     833                 :           0 :       if (g_cancellable_set_error_if_cancelled (cancellable, &error))
     834                 :           0 :         info = NULL;
     835                 :             :       else
     836                 :           0 :         info = class->next_file (enumerator, cancellable, &error);
     837                 :             :       
     838                 :           0 :       if (info == NULL)
     839                 :             :         {
     840                 :             :           /* If we get an error after first file, return that on next operation */
     841                 :           0 :           if (error != NULL && i > 0)
     842                 :             :             {
     843                 :           0 :               if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
     844                 :           0 :                 g_error_free (error); /* Never propagate cancel errors to other call */
     845                 :             :               else
     846                 :           0 :                 enumerator->priv->outstanding_error = error;
     847                 :           0 :               error = NULL;
     848                 :             :             }
     849                 :             :               
     850                 :           0 :           break;
     851                 :             :         }
     852                 :             :       else
     853                 :           0 :         files = g_list_prepend (files, info);
     854                 :             :     }
     855                 :             : 
     856                 :           0 :   if (error)
     857                 :             :     {
     858                 :           0 :       g_list_free_full (files, g_object_unref);
     859                 :           0 :       g_task_return_error (task, error);
     860                 :             :     }
     861                 :             :   else
     862                 :           0 :     g_task_return_pointer (task, files, (GDestroyNotify)next_async_op_free);
     863                 :           0 : }
     864                 :             : 
     865                 :             : static void
     866                 :           0 : 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                 :           0 :   task = g_task_new (enumerator, cancellable, callback, user_data);
     876                 :           0 :   g_task_set_source_tag (task, g_file_enumerator_real_next_files_async);
     877                 :           0 :   g_task_set_task_data (task, GINT_TO_POINTER (num_files), NULL);
     878                 :           0 :   g_task_set_priority (task, io_priority);
     879                 :             : 
     880                 :           0 :   g_task_run_in_thread (task, next_files_thread);
     881                 :           0 :   g_object_unref (task);
     882                 :           0 : }
     883                 :             : 
     884                 :             : static GList *
     885                 :           0 : g_file_enumerator_real_next_files_finish (GFileEnumerator                *enumerator,
     886                 :             :                                           GAsyncResult                   *result,
     887                 :             :                                           GError                        **error)
     888                 :             : {
     889                 :           0 :   g_return_val_if_fail (g_task_is_valid (result, enumerator), NULL);
     890                 :             : 
     891                 :           0 :   return g_task_propagate_pointer (G_TASK (result), error);
     892                 :             : }
     893                 :             : 
     894                 :             : static void
     895                 :           0 : close_async_thread (GTask        *task,
     896                 :             :                     gpointer      source_object,
     897                 :             :                     gpointer      task_data,
     898                 :             :                     GCancellable *cancellable)
     899                 :             : {
     900                 :           0 :   GFileEnumerator *enumerator = source_object;
     901                 :             :   GFileEnumeratorClass *class;
     902                 :           0 :   GError *error = NULL;
     903                 :             :   gboolean result;
     904                 :             : 
     905                 :           0 :   class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
     906                 :           0 :   result = class->close_fn (enumerator, cancellable, &error);
     907                 :           0 :   if (result)
     908                 :           0 :     g_task_return_boolean (task, TRUE);
     909                 :             :   else
     910                 :           0 :     g_task_return_error (task, error);
     911                 :           0 : }
     912                 :             : 
     913                 :             : static void
     914                 :           0 : 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                 :           0 :   task = g_task_new (enumerator, cancellable, callback, user_data);
     923                 :           0 :   g_task_set_source_tag (task, g_file_enumerator_real_close_async);
     924                 :           0 :   g_task_set_priority (task, io_priority);
     925                 :             :   
     926                 :           0 :   g_task_run_in_thread (task, close_async_thread);
     927                 :           0 :   g_object_unref (task);
     928                 :           0 : }
     929                 :             : 
     930                 :             : static gboolean
     931                 :           0 : g_file_enumerator_real_close_finish (GFileEnumerator  *enumerator,
     932                 :             :                                      GAsyncResult     *result,
     933                 :             :                                      GError          **error)
     934                 :             : {
     935                 :           0 :   g_return_val_if_fail (g_task_is_valid (result, enumerator), FALSE);
     936                 :             : 
     937                 :           0 :   return g_task_propagate_boolean (G_TASK (result), error);
     938                 :             : }
        

Generated by: LCOV version 2.0-1