LCOV - code coverage report
Current view: top level - gio/inotify - inotify-path.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 96.1 % 231 222
Test Date: 2024-11-26 05:23:01 Functions: 100.0 % 24 24
Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 8 -*- */
       2                 :             : 
       3                 :             : /* inotify-path.c - GVFS Monitor based on inotify.
       4                 :             : 
       5                 :             :    Copyright (C) 2006 John McCutchan
       6                 :             :    Copyright (C) 2009 Codethink Limited
       7                 :             : 
       8                 :             :    SPDX-License-Identifier: LGPL-2.1-or-later
       9                 :             : 
      10                 :             :    This library is free software; you can redistribute it and/or
      11                 :             :    modify it under the terms of the GNU Lesser General Public
      12                 :             :    License as published by the Free Software Foundation; either
      13                 :             :    version 2.1 of the License, or (at your option) any later version.
      14                 :             : 
      15                 :             :    This library is distributed in the hope that it will be useful,
      16                 :             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17                 :             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      18                 :             :    Lesser General Public License for more details.
      19                 :             : 
      20                 :             :    You should have received a copy of the GNU Lesser General Public License
      21                 :             :    along with this library; if not, see <http://www.gnu.org/licenses/>.
      22                 :             : 
      23                 :             :    Authors:
      24                 :             :                  John McCutchan <john@johnmccutchan.com>
      25                 :             :                  Ryan Lortie <desrt@desrt.ca>
      26                 :             : */
      27                 :             : 
      28                 :             : #include "config.h"
      29                 :             : 
      30                 :             : /* Don't put conflicting kernel types in the global namespace: */
      31                 :             : #define __KERNEL_STRICT_NAMES
      32                 :             : 
      33                 :             : #include <sys/inotify.h>
      34                 :             : #include <string.h>
      35                 :             : #include <glib.h>
      36                 :             : #include "inotify-kernel.h"
      37                 :             : #include "inotify-path.h"
      38                 :             : #include "inotify-missing.h"
      39                 :             : 
      40                 :             : #define IP_INOTIFY_DIR_MASK (IN_MODIFY|IN_ATTRIB|IN_MOVED_FROM|IN_MOVED_TO|IN_DELETE|IN_CREATE|IN_DELETE_SELF|IN_UNMOUNT|IN_MOVE_SELF|IN_CLOSE_WRITE)
      41                 :             : 
      42                 :             : #define IP_INOTIFY_FILE_MASK (IN_MODIFY|IN_ATTRIB|IN_CLOSE_WRITE)
      43                 :             : 
      44                 :             : /* Older libcs don't have this */
      45                 :             : #ifndef IN_ONLYDIR
      46                 :             : #define IN_ONLYDIR 0  
      47                 :             : #endif
      48                 :             : 
      49                 :             : typedef struct ip_watched_file_s {
      50                 :             :   gchar *filename;
      51                 :             :   gchar *path;
      52                 :             :   gint32 wd;
      53                 :             : 
      54                 :             :   GList *subs;
      55                 :             : } ip_watched_file_t;
      56                 :             : 
      57                 :             : typedef struct ip_watched_dir_s {
      58                 :             :   char *path;
      59                 :             :   /* TODO: We need to maintain a tree of watched directories
      60                 :             :    * so that we can deliver move/delete events to sub folders.
      61                 :             :    * Or the application could do it...
      62                 :             :    */
      63                 :             :   struct ip_watched_dir_s* parent;
      64                 :             :   GList*         children;
      65                 :             : 
      66                 :             :   /* basename -> ip_watched_file_t
      67                 :             :    * Maps basename to a ip_watched_file_t if the file is currently
      68                 :             :    * being directly watched for changes (ie: 'hardlinks' mode).
      69                 :             :    */
      70                 :             :   GHashTable *files_hash;
      71                 :             : 
      72                 :             :   /* Inotify state */
      73                 :             :   gint32 wd;
      74                 :             :   
      75                 :             :   /* List of inotify subscriptions */
      76                 :             :   GList *subs;
      77                 :             : } ip_watched_dir_t;
      78                 :             : 
      79                 :             : static gboolean     ip_debug_enabled = FALSE;
      80                 :             : #define IP_W if (ip_debug_enabled) g_warning
      81                 :             : 
      82                 :             : /* path -> ip_watched_dir */
      83                 :             : static GHashTable * path_dir_hash = NULL;
      84                 :             : /* inotify_sub * -> ip_watched_dir *
      85                 :             :  *
      86                 :             :  * Each subscription is attached to a watched directory or it is on
      87                 :             :  * the missing list
      88                 :             :  */
      89                 :             : static GHashTable * sub_dir_hash = NULL;
      90                 :             : /* This hash holds GLists of ip_watched_dir_t *'s
      91                 :             :  * We need to hold a list because symbolic links can share
      92                 :             :  * the same wd
      93                 :             :  */
      94                 :             : static GHashTable * wd_dir_hash = NULL;
      95                 :             : /* This hash holds GLists of ip_watched_file_t *'s
      96                 :             :  * We need to hold a list because links can share
      97                 :             :  * the same wd
      98                 :             :  */
      99                 :             : static GHashTable * wd_file_hash = NULL;
     100                 :             : 
     101                 :             : static ip_watched_dir_t *ip_watched_dir_new  (const char       *path,
     102                 :             :                                               int               wd);
     103                 :             : static void              ip_watched_dir_free (ip_watched_dir_t *dir);
     104                 :             : static gboolean          ip_event_callback   (ik_event_t       *event);
     105                 :             : 
     106                 :             : 
     107                 :             : static gboolean (*event_callback)(ik_event_t *event, inotify_sub *sub, gboolean file_event);
     108                 :             : 
     109                 :             : gboolean
     110                 :          57 : _ip_startup (gboolean (*cb)(ik_event_t *event, inotify_sub *sub, gboolean file_event))
     111                 :             : {
     112                 :             :   static gboolean initialized = FALSE;
     113                 :             :   static gboolean result = FALSE;
     114                 :             :   
     115                 :          57 :   if (initialized == TRUE)
     116                 :           0 :     return result;
     117                 :             : 
     118                 :          57 :   event_callback = cb;
     119                 :          57 :   result = _ik_startup (ip_event_callback);
     120                 :             : 
     121                 :          57 :   if (!result)
     122                 :           0 :     return FALSE;
     123                 :             : 
     124                 :          57 :   path_dir_hash = g_hash_table_new (g_str_hash, g_str_equal);
     125                 :          57 :   sub_dir_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
     126                 :          57 :   wd_dir_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
     127                 :          57 :   wd_file_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
     128                 :             :   
     129                 :          57 :   initialized = TRUE;
     130                 :          57 :   return TRUE;
     131                 :             : }
     132                 :             : 
     133                 :             : static void
     134                 :         389 : ip_map_path_dir (const char       *path, 
     135                 :             :                  ip_watched_dir_t *dir)
     136                 :             : {
     137                 :         389 :   g_assert (path && dir);
     138                 :         389 :   g_hash_table_insert (path_dir_hash, dir->path, dir);
     139                 :         389 : }
     140                 :             : 
     141                 :             : static void
     142                 :         676 : ip_map_sub_dir (inotify_sub      *sub, 
     143                 :             :                 ip_watched_dir_t *dir)
     144                 :             : {
     145                 :             :   /* Associate subscription and directory */
     146                 :         676 :   g_assert (dir && sub);
     147                 :         676 :   g_hash_table_insert (sub_dir_hash, sub, dir);
     148                 :         676 :   dir->subs = g_list_prepend (dir->subs, sub);
     149                 :         676 : }
     150                 :             : 
     151                 :             : static void
     152                 :         389 : ip_map_wd_dir (gint32            wd, 
     153                 :             :                ip_watched_dir_t *dir)
     154                 :             : {
     155                 :             :   GList *dir_list;
     156                 :             :   
     157                 :         389 :   g_assert (wd >= 0 && dir);
     158                 :         389 :   dir_list = g_hash_table_lookup (wd_dir_hash, GINT_TO_POINTER (wd));
     159                 :         389 :   dir_list = g_list_prepend (dir_list, dir);
     160                 :         389 :   g_hash_table_replace (wd_dir_hash, GINT_TO_POINTER (dir->wd), dir_list);
     161                 :         389 : }
     162                 :             : 
     163                 :             : static void
     164                 :           1 : ip_map_wd_file (gint32             wd,
     165                 :             :                 ip_watched_file_t *file)
     166                 :             : {
     167                 :             :   GList *file_list;
     168                 :             : 
     169                 :           1 :   g_assert (wd >= 0 && file);
     170                 :           1 :   file_list = g_hash_table_lookup (wd_file_hash, GINT_TO_POINTER (wd));
     171                 :           1 :   file_list = g_list_prepend (file_list, file);
     172                 :           1 :   g_hash_table_replace (wd_file_hash, GINT_TO_POINTER (wd), file_list);
     173                 :           1 : }
     174                 :             : 
     175                 :             : static void
     176                 :           1 : ip_unmap_wd_file (gint32             wd,
     177                 :             :                   ip_watched_file_t *file)
     178                 :             : {
     179                 :           1 :   GList *file_list = g_hash_table_lookup (wd_file_hash, GINT_TO_POINTER (wd));
     180                 :             : 
     181                 :           1 :   if (!file_list)
     182                 :           0 :     return;
     183                 :             : 
     184                 :           1 :   g_assert (wd >= 0 && file);
     185                 :           1 :   file_list = g_list_remove (file_list, file);
     186                 :           1 :   if (file_list == NULL)
     187                 :           1 :     g_hash_table_remove (wd_file_hash, GINT_TO_POINTER (wd));
     188                 :             :   else
     189                 :           0 :     g_hash_table_replace (wd_file_hash, GINT_TO_POINTER (wd), file_list);
     190                 :             : }
     191                 :             : 
     192                 :             : 
     193                 :             : static ip_watched_file_t *
     194                 :           1 : ip_watched_file_new (const gchar *dirname,
     195                 :             :                      const gchar *filename)
     196                 :             : {
     197                 :             :   ip_watched_file_t *file;
     198                 :             : 
     199                 :           1 :   file = g_new0 (ip_watched_file_t, 1);
     200                 :           1 :   file->path = g_strjoin ("/", dirname, filename, NULL);
     201                 :           1 :   file->filename = g_strdup (filename);
     202                 :           1 :   file->wd = -1;
     203                 :             : 
     204                 :           1 :   return file;
     205                 :             : }
     206                 :             : 
     207                 :             : static void
     208                 :           1 : ip_watched_file_free (ip_watched_file_t *file)
     209                 :             : {
     210                 :           1 :   g_assert (file->subs == NULL);
     211                 :           1 :   g_free (file->filename);
     212                 :           1 :   g_free (file->path);
     213                 :           1 :   g_free (file);
     214                 :           1 : }
     215                 :             : 
     216                 :             : static void
     217                 :           1 : ip_watched_file_add_sub (ip_watched_file_t *file,
     218                 :             :                          inotify_sub       *sub)
     219                 :             : {
     220                 :           1 :   file->subs = g_list_prepend (file->subs, sub);
     221                 :           1 : }
     222                 :             : 
     223                 :             : static void
     224                 :           1 : ip_watched_file_start (ip_watched_file_t *file)
     225                 :             : {
     226                 :           1 :   if (file->wd < 0)
     227                 :             :     {
     228                 :             :       gint err;
     229                 :             : 
     230                 :           1 :       file->wd = _ik_watch (file->path,
     231                 :             :                             IP_INOTIFY_FILE_MASK,
     232                 :             :                             &err);
     233                 :             : 
     234                 :           1 :       if (file->wd >= 0)
     235                 :           1 :         ip_map_wd_file (file->wd, file);
     236                 :             :     }
     237                 :           1 : }
     238                 :             : 
     239                 :             : static void
     240                 :           3 : ip_watched_file_stop (ip_watched_file_t *file)
     241                 :             : {
     242                 :           3 :   if (file->wd >= 0)
     243                 :             :     {
     244                 :           1 :       _ik_ignore (file->path, file->wd);
     245                 :           1 :       ip_unmap_wd_file (file->wd, file);
     246                 :           1 :       file->wd = -1;
     247                 :             :     }
     248                 :           3 : }
     249                 :             : 
     250                 :             : gboolean
     251                 :         679 : _ip_start_watching (inotify_sub *sub)
     252                 :             : {
     253                 :             :   gint32 wd;
     254                 :             :   int err;
     255                 :             :   ip_watched_dir_t *dir;
     256                 :             :   
     257                 :         679 :   g_assert (sub);
     258                 :         679 :   g_assert (!sub->cancelled);
     259                 :         679 :   g_assert (sub->dirname);
     260                 :             :   
     261                 :         679 :   IP_W ("Starting to watch %s\n", sub->dirname);
     262                 :         679 :   dir = g_hash_table_lookup (path_dir_hash, sub->dirname);
     263                 :             : 
     264                 :         679 :   if (dir == NULL)
     265                 :             :     {
     266                 :         392 :       IP_W ("Trying to add inotify watch ");
     267                 :         392 :       wd = _ik_watch (sub->dirname, IP_INOTIFY_DIR_MASK|IN_ONLYDIR, &err);
     268                 :         392 :       if (wd < 0)
     269                 :             :         {
     270                 :           3 :           IP_W ("Failed\n");
     271                 :           3 :           return FALSE;
     272                 :             :         }
     273                 :             :       else
     274                 :             :         {
     275                 :             :           /* Create new watched directory and associate it with the
     276                 :             :            * wd hash and path hash
     277                 :             :            */
     278                 :         389 :           IP_W ("Success\n");
     279                 :         389 :           dir = ip_watched_dir_new (sub->dirname, wd);
     280                 :         389 :           ip_map_wd_dir (wd, dir);
     281                 :         389 :           ip_map_path_dir (sub->dirname, dir);
     282                 :             :         }
     283                 :             :     }
     284                 :             :   else
     285                 :         287 :     IP_W ("Already watching\n");
     286                 :             : 
     287                 :         676 :   if (sub->hardlinks)
     288                 :             :     {
     289                 :             :       ip_watched_file_t *file;
     290                 :             : 
     291                 :           1 :       file = g_hash_table_lookup (dir->files_hash, sub->filename);
     292                 :             : 
     293                 :           1 :       if (file == NULL)
     294                 :             :         {
     295                 :           1 :           file = ip_watched_file_new (sub->dirname, sub->filename);
     296                 :           1 :           g_hash_table_insert (dir->files_hash, file->filename, file);
     297                 :             :         }
     298                 :             : 
     299                 :           1 :       ip_watched_file_add_sub (file, sub);
     300                 :           1 :       ip_watched_file_start (file);
     301                 :             :     }
     302                 :             : 
     303                 :         676 :   ip_map_sub_dir (sub, dir);
     304                 :             :   
     305                 :         676 :   return TRUE;
     306                 :             : }
     307                 :             : 
     308                 :             : static void
     309                 :         249 : ip_unmap_path_dir (const char       *path, 
     310                 :             :                    ip_watched_dir_t *dir)
     311                 :             : {
     312                 :         249 :   g_assert (path && dir);
     313                 :         249 :   g_hash_table_remove (path_dir_hash, dir->path);
     314                 :         249 : }
     315                 :             : 
     316                 :             : static void
     317                 :         169 : ip_unmap_wd_dir (gint32            wd, 
     318                 :             :                  ip_watched_dir_t *dir)
     319                 :             : {
     320                 :         169 :   GList *dir_list = g_hash_table_lookup (wd_dir_hash, GINT_TO_POINTER (wd));
     321                 :             :   
     322                 :         169 :   if (!dir_list)
     323                 :           0 :     return;
     324                 :             :   
     325                 :         169 :   g_assert (wd >= 0 && dir);
     326                 :         169 :   dir_list = g_list_remove (dir_list, dir);
     327                 :         169 :   if (dir_list == NULL) 
     328                 :         169 :     g_hash_table_remove (wd_dir_hash, GINT_TO_POINTER (dir->wd));
     329                 :             :   else
     330                 :           0 :     g_hash_table_replace (wd_dir_hash, GINT_TO_POINTER (dir->wd), dir_list);
     331                 :             : }
     332                 :             : 
     333                 :             : static void
     334                 :          82 : ip_unmap_wd (gint32 wd)
     335                 :             : {
     336                 :          82 :   GList *dir_list = g_hash_table_lookup (wd_dir_hash, GINT_TO_POINTER (wd));
     337                 :          82 :   if (!dir_list)
     338                 :           2 :     return;
     339                 :          80 :   g_assert (wd >= 0);
     340                 :          80 :   g_hash_table_remove (wd_dir_hash, GINT_TO_POINTER (wd));
     341                 :          80 :   g_list_free (dir_list);
     342                 :             : }
     343                 :             : 
     344                 :             : static void
     345                 :         484 : ip_unmap_sub_dir (inotify_sub      *sub,
     346                 :             :                   ip_watched_dir_t *dir)
     347                 :             : {
     348                 :         484 :   g_assert (sub && dir);
     349                 :         484 :   g_hash_table_remove (sub_dir_hash, sub);
     350                 :         484 :   dir->subs = g_list_remove (dir->subs, sub);
     351                 :             : 
     352                 :         484 :   if (sub->hardlinks)
     353                 :             :     {
     354                 :             :       ip_watched_file_t *file;
     355                 :             : 
     356                 :           1 :       file = g_hash_table_lookup (dir->files_hash, sub->filename);
     357                 :           1 :       file->subs = g_list_remove (file->subs, sub);
     358                 :             : 
     359                 :           1 :       if (file->subs == NULL)
     360                 :             :         {
     361                 :           1 :           g_hash_table_remove (dir->files_hash, sub->filename);
     362                 :           1 :           ip_watched_file_stop (file);
     363                 :           1 :           ip_watched_file_free (file);
     364                 :             :         }
     365                 :             :     }
     366                 :         484 :  }
     367                 :             : 
     368                 :             : static void
     369                 :          80 : ip_unmap_all_subs (ip_watched_dir_t *dir)
     370                 :             : {
     371                 :         363 :   while (dir->subs != NULL)
     372                 :         283 :     ip_unmap_sub_dir (dir->subs->data, dir);
     373                 :          80 : }
     374                 :             : 
     375                 :             : gboolean
     376                 :         484 : _ip_stop_watching (inotify_sub *sub)
     377                 :             : {
     378                 :         484 :   ip_watched_dir_t *dir = NULL;
     379                 :             :   
     380                 :         484 :   dir = g_hash_table_lookup (sub_dir_hash, sub);
     381                 :         484 :   if (!dir) 
     382                 :         283 :     return TRUE;
     383                 :             :   
     384                 :         201 :   ip_unmap_sub_dir (sub, dir);
     385                 :             :   
     386                 :             :   /* No one is subscribing to this directory any more */
     387                 :         201 :   if (dir->subs == NULL)
     388                 :             :     {
     389                 :         169 :       _ik_ignore (dir->path, dir->wd);
     390                 :         169 :       ip_unmap_wd_dir (dir->wd, dir);
     391                 :         169 :       ip_unmap_path_dir (dir->path, dir);
     392                 :         169 :       ip_watched_dir_free (dir);
     393                 :             :     }
     394                 :             :   
     395                 :         201 :   return TRUE;
     396                 :             : }
     397                 :             : 
     398                 :             : 
     399                 :             : static ip_watched_dir_t *
     400                 :         389 : ip_watched_dir_new (const char *path, 
     401                 :             :                     gint32      wd)
     402                 :             : {
     403                 :         389 :   ip_watched_dir_t *dir = g_new0 (ip_watched_dir_t, 1);
     404                 :             :   
     405                 :         389 :   dir->path = g_strdup (path);
     406                 :         389 :   dir->files_hash = g_hash_table_new (g_str_hash, g_str_equal);
     407                 :         389 :   dir->wd = wd;
     408                 :             :   
     409                 :         389 :   return dir;
     410                 :             : }
     411                 :             : 
     412                 :             : static void
     413                 :         249 : ip_watched_dir_free (ip_watched_dir_t *dir)
     414                 :             : {
     415                 :         249 :   g_assert_cmpint (g_hash_table_size (dir->files_hash), ==, 0);
     416                 :         249 :   g_assert (dir->subs == NULL);
     417                 :         249 :   g_free (dir->path);
     418                 :         249 :   g_hash_table_unref (dir->files_hash);
     419                 :         249 :   g_free (dir);
     420                 :         249 : }
     421                 :             : 
     422                 :             : static void
     423                 :          80 : ip_wd_delete (gpointer data, 
     424                 :             :               gpointer user_data)
     425                 :             : {
     426                 :          80 :   ip_watched_dir_t *dir = data;
     427                 :          80 :   GList *l = NULL;
     428                 :             :   
     429                 :         363 :   for (l = dir->subs; l; l = l->next)
     430                 :             :     {
     431                 :         283 :       inotify_sub *sub = l->data;
     432                 :             :       /* Add subscription to missing list */
     433                 :         283 :       _im_add (sub);
     434                 :             :     }
     435                 :          80 :   ip_unmap_all_subs (dir);
     436                 :             :   /* Unassociate the path and the directory */
     437                 :          80 :   ip_unmap_path_dir (dir->path, dir);
     438                 :          80 :   ip_watched_dir_free (dir);
     439                 :          80 : }
     440                 :             : 
     441                 :             : static gboolean
     442                 :         722 : ip_event_dispatch (GList      *dir_list, 
     443                 :             :                    GList      *file_list,
     444                 :             :                    ik_event_t *event)
     445                 :             : {
     446                 :         722 :   gboolean interesting = FALSE;
     447                 :             : 
     448                 :             :   GList *l;
     449                 :             :   
     450                 :         722 :   if (!event)
     451                 :           0 :     return FALSE;
     452                 :             : 
     453                 :        1220 :   for (l = dir_list; l; l = l->next)
     454                 :             :     {
     455                 :             :       GList *subl;
     456                 :         498 :       ip_watched_dir_t *dir = l->data;
     457                 :             :       
     458                 :        1590 :       for (subl = dir->subs; subl; subl = subl->next)
     459                 :             :         {
     460                 :        1092 :           inotify_sub *sub = subl->data;
     461                 :             :           
     462                 :             :           /* If the subscription and the event
     463                 :             :            * contain a filename and they don't
     464                 :             :            * match, we don't deliver this event.
     465                 :             :            */
     466                 :        1092 :           if (sub->filename &&
     467                 :         135 :               event->name &&
     468                 :         133 :               strcmp (sub->filename, event->name) &&
     469                 :          56 :               (!event->pair || !event->pair->name || strcmp (sub->filename, event->pair->name)))
     470                 :          41 :             continue;
     471                 :             :           
     472                 :             :           /* If the subscription has a filename
     473                 :             :            * but this event doesn't, we don't
     474                 :             :            * deliver this event.
     475                 :             :            */
     476                 :        1051 :           if (sub->filename && !event->name)
     477                 :           2 :             continue;
     478                 :             :           
     479                 :             :           /* If we're also watching the file directly
     480                 :             :            * don't report events that will also be
     481                 :             :            * reported on the file itself.
     482                 :             :            */
     483                 :        1049 :           if (sub->hardlinks)
     484                 :             :             {
     485                 :           6 :               event->mask &= ~IP_INOTIFY_FILE_MASK;
     486                 :           6 :               if (!event->mask)
     487                 :           4 :                 continue;
     488                 :             :             }
     489                 :             :           
     490                 :             :           /* FIXME: We might need to synthesize
     491                 :             :            * DELETE/UNMOUNT events when
     492                 :             :            * the filename doesn't match
     493                 :             :            */
     494                 :             :           
     495                 :        1045 :           interesting |= event_callback (event, sub, FALSE);
     496                 :             : 
     497                 :        1045 :           if (sub->hardlinks)
     498                 :             :             {
     499                 :             :               ip_watched_file_t *file;
     500                 :             : 
     501                 :           2 :               file = g_hash_table_lookup (dir->files_hash, sub->filename);
     502                 :             : 
     503                 :           2 :               if (file != NULL)
     504                 :             :                 {
     505                 :           2 :                   if (event->mask & (IN_MOVED_FROM | IN_DELETE))
     506                 :           2 :                     ip_watched_file_stop (file);
     507                 :             : 
     508                 :           2 :                   if (event->mask & (IN_MOVED_TO | IN_CREATE))
     509                 :           0 :                     ip_watched_file_start (file);
     510                 :             :                 }
     511                 :             :             }
     512                 :             :         }
     513                 :             :     }
     514                 :             : 
     515                 :         725 :   for (l = file_list; l; l = l->next)
     516                 :             :     {
     517                 :           3 :       ip_watched_file_t *file = l->data;
     518                 :             :       GList *subl;
     519                 :             : 
     520                 :           6 :       for (subl = file->subs; subl; subl = subl->next)
     521                 :             :         {
     522                 :           3 :           inotify_sub *sub = subl->data;
     523                 :             : 
     524                 :           3 :           interesting |= event_callback (event, sub, TRUE);
     525                 :             :         }
     526                 :             :     }
     527                 :             : 
     528                 :         722 :   return interesting;
     529                 :             : }
     530                 :             : 
     531                 :             : static gboolean
     532                 :         971 : ip_event_callback (ik_event_t *event)
     533                 :             : {
     534                 :         971 :   gboolean interesting = FALSE;
     535                 :         971 :   GList* dir_list = NULL;
     536                 :         971 :   GList *file_list = NULL;
     537                 :             : 
     538                 :             :   /* We can ignore the IGNORED events. Likewise, if the event queue overflowed,
     539                 :             :    * there is not much we can do to recover. */
     540                 :         971 :   if (event->mask & (IN_IGNORED | IN_Q_OVERFLOW))
     541                 :             :     {
     542                 :         250 :       _ik_event_free (event);
     543                 :         250 :       return TRUE;
     544                 :             :     }
     545                 :             : 
     546                 :         721 :   dir_list = g_hash_table_lookup (wd_dir_hash, GINT_TO_POINTER (event->wd));
     547                 :         721 :   file_list = g_hash_table_lookup (wd_file_hash, GINT_TO_POINTER (event->wd));
     548                 :             : 
     549                 :         721 :   if (event->mask & IP_INOTIFY_DIR_MASK)
     550                 :         721 :     interesting |= ip_event_dispatch (dir_list, file_list, event);
     551                 :             : 
     552                 :             :   /* Only deliver paired events if the wds are separate */
     553                 :         721 :   if (event->pair && event->pair->wd != event->wd)
     554                 :             :     {
     555                 :           1 :       dir_list = g_hash_table_lookup (wd_dir_hash, GINT_TO_POINTER (event->pair->wd));
     556                 :           1 :       file_list = g_hash_table_lookup (wd_file_hash, GINT_TO_POINTER (event->pair->wd));
     557                 :             : 
     558                 :           1 :       if (event->pair->mask & IP_INOTIFY_DIR_MASK)
     559                 :           1 :         interesting |= ip_event_dispatch (dir_list, file_list, event->pair);
     560                 :             :     }
     561                 :             : 
     562                 :             :   /* We have to manage the missing list
     563                 :             :    * when we get an event that means the
     564                 :             :    * file has been deleted/moved/unmounted.
     565                 :             :    */
     566                 :         721 :   if (event->mask & IN_DELETE_SELF ||
     567                 :         639 :       event->mask & IN_MOVE_SELF ||
     568                 :         639 :       event->mask & IN_UNMOUNT)
     569                 :             :     {
     570                 :             :       /* Add all subscriptions to missing list */
     571                 :          82 :       g_list_foreach (dir_list, ip_wd_delete, NULL);
     572                 :             :       /* Unmap all directories attached to this wd */
     573                 :          82 :       ip_unmap_wd (event->wd);
     574                 :             :     }
     575                 :             :   
     576                 :         721 :   _ik_event_free (event);
     577                 :             : 
     578                 :         721 :   return interesting;
     579                 :             : }
     580                 :             : 
     581                 :             : const char *
     582                 :          77 : _ip_get_path_for_wd (gint32 wd)
     583                 :             : {
     584                 :             :   GList *dir_list;
     585                 :             :   ip_watched_dir_t *dir;
     586                 :             : 
     587                 :          77 :   g_assert (wd >= 0);
     588                 :          77 :   dir_list = g_hash_table_lookup (wd_dir_hash, GINT_TO_POINTER (wd));
     589                 :          77 :   if (dir_list)
     590                 :             :     {
     591                 :          77 :       dir = dir_list->data;
     592                 :          77 :       if (dir)
     593                 :          77 :         return dir->path;
     594                 :             :     }
     595                 :             : 
     596                 :           0 :   return NULL;
     597                 :             : }
        

Generated by: LCOV version 2.0-1