Coverage Report

Created: 2025-06-13 06:21

/src/glib/gio/inotify/inotify-missing.c
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 8 -*- */
2
3
/* inotify-missing.c - GVFS Monitor based on inotify.
4
5
   Copyright (C) 2005 John McCutchan
6
7
   SPDX-License-Identifier: LGPL-2.1-or-later
8
9
   This library is free software; you can redistribute it and/or
10
   modify it under the terms of the GNU Lesser General Public
11
   License as published by the Free Software Foundation; either
12
   version 2.1 of the License, or (at your option) any later version.
13
14
   This library is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
   Lesser General Public License for more details.
18
19
   You should have received a copy of the GNU Lesser General Public License
20
   along with this library; if not, see <http://www.gnu.org/licenses/>.
21
22
   Authors: 
23
     John McCutchan <john@johnmccutchan.com>
24
*/
25
26
#include "config.h"
27
#include <glib.h>
28
#include "inotify-missing.h"
29
#include "inotify-path.h"
30
#include "glib-private.h"
31
32
0
#define SCAN_MISSING_TIME 4 /* 1/4 Hz */
33
34
static gboolean im_debug_enabled = FALSE;
35
0
#define IM_W if (im_debug_enabled) g_warning
36
37
/* We put inotify_sub's that are missing on this list */
38
static GList *missing_sub_list = NULL;
39
static gboolean im_scan_missing (gpointer user_data);
40
static gboolean scan_missing_running = FALSE;
41
static void (*missing_cb)(inotify_sub *sub) = NULL;
42
43
G_LOCK_EXTERN (inotify_lock);
44
45
/* inotify_lock must be held before calling */
46
void
47
_im_startup (void (*callback)(inotify_sub *sub))
48
0
{
49
0
  static gboolean initialized = FALSE;
50
  
51
0
  if (!initialized)
52
0
    {
53
0
      missing_cb = callback;
54
0
      initialized = TRUE;
55
0
    }
56
0
}
57
58
/* inotify_lock must be held before calling */
59
void
60
_im_add (inotify_sub *sub)
61
0
{
62
0
  if (g_list_find (missing_sub_list, sub))
63
0
    {
64
0
      IM_W ("asked to add %s to missing list but it's already on the list!\n", sub->dirname);
65
0
      return;
66
0
    }
67
68
0
  IM_W ("adding %s to missing list\n", sub->dirname);
69
0
  missing_sub_list = g_list_prepend (missing_sub_list, sub);
70
71
  /* If the timeout is turned off, we turn it back on */
72
0
  if (!scan_missing_running)
73
0
    {
74
0
      GSource *source;
75
76
0
      scan_missing_running = TRUE;
77
0
      source = g_timeout_source_new_seconds (SCAN_MISSING_TIME);
78
0
      g_source_set_callback (source, im_scan_missing, NULL, NULL);
79
0
      g_source_attach (source, GLIB_PRIVATE_CALL (g_get_worker_context) ());
80
0
      g_source_unref (source);
81
0
    }
82
0
}
83
84
/* inotify_lock must be held before calling */
85
void
86
_im_rm (inotify_sub *sub)
87
0
{
88
0
  GList *link;
89
  
90
0
  link = g_list_find (missing_sub_list, sub);
91
92
0
  if (!link)
93
0
    {
94
0
      IM_W ("asked to remove %s from missing list but it isn't on the list!\n", sub->dirname);
95
0
      return;
96
0
    }
97
98
0
  IM_W ("removing %s from missing list\n", sub->dirname);
99
100
0
  missing_sub_list = g_list_remove_link (missing_sub_list, link);
101
0
  g_list_free_1 (link);
102
0
}
103
104
/* Scans the list of missing subscriptions checking if they
105
 * are available yet.
106
 */
107
static gboolean
108
im_scan_missing (gpointer user_data)
109
0
{
110
0
  GList *nolonger_missing = NULL;
111
0
  GList *l;
112
  
113
0
  G_LOCK (inotify_lock);
114
  
115
0
  IM_W ("scanning missing list with %d items\n", g_list_length (missing_sub_list));
116
0
  for (l = missing_sub_list; l; l = l->next)
117
0
    {
118
0
      inotify_sub *sub = l->data;
119
0
      gboolean not_m = FALSE;
120
      
121
0
      IM_W ("checking %p\n", sub);
122
0
      g_assert (sub);
123
0
      g_assert (sub->dirname);
124
0
      not_m = _ip_start_watching (sub);
125
126
0
      if (not_m)
127
0
  {
128
0
    missing_cb (sub);
129
0
    IM_W ("removed %s from missing list\n", sub->dirname);
130
    /* We have to build a list of list nodes to remove from the
131
     * missing_sub_list. We do the removal outside of this loop.
132
     */
133
0
    nolonger_missing = g_list_prepend (nolonger_missing, l);
134
0
  } 
135
0
    }
136
137
0
  for (l = nolonger_missing; l ; l = l->next)
138
0
    {
139
0
      GList *llink = l->data;
140
0
      missing_sub_list = g_list_remove_link (missing_sub_list, llink);
141
0
      g_list_free_1 (llink);
142
0
    }
143
144
0
  g_list_free (nolonger_missing);
145
  
146
  /* If the missing list is now empty, we disable the timeout */
147
0
  if (missing_sub_list == NULL)
148
0
    {
149
0
      scan_missing_running = FALSE;
150
0
      G_UNLOCK (inotify_lock);
151
0
      return FALSE;
152
0
    }
153
0
  else
154
0
    {
155
0
      G_UNLOCK (inotify_lock);
156
0
      return TRUE;
157
0
    }
158
0
}