Coverage Report

Created: 2025-06-13 06:55

/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
   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 Public License
18
   along with this library; if not, see <http://www.gnu.org/licenses/>.
19
20
   Authors: 
21
     John McCutchan <john@johnmccutchan.com>
22
*/
23
24
#include "config.h"
25
#include <glib.h>
26
#include "inotify-missing.h"
27
#include "inotify-path.h"
28
#include "glib-private.h"
29
30
0
#define SCAN_MISSING_TIME 4 /* 1/4 Hz */
31
32
static gboolean im_debug_enabled = FALSE;
33
0
#define IM_W if (im_debug_enabled) g_warning
34
35
/* We put inotify_sub's that are missing on this list */
36
static GList *missing_sub_list = NULL;
37
static gboolean im_scan_missing (gpointer user_data);
38
static gboolean scan_missing_running = FALSE;
39
static void (*missing_cb)(inotify_sub *sub) = NULL;
40
41
G_LOCK_EXTERN (inotify_lock);
42
43
/* inotify_lock must be held before calling */
44
void
45
_im_startup (void (*callback)(inotify_sub *sub))
46
0
{
47
0
  static gboolean initialized = FALSE;
48
  
49
0
  if (!initialized)
50
0
    {
51
0
      missing_cb = callback;
52
0
      initialized = TRUE;
53
0
    }
54
0
}
55
56
/* inotify_lock must be held before calling */
57
void
58
_im_add (inotify_sub *sub)
59
0
{
60
0
  if (g_list_find (missing_sub_list, sub))
61
0
    {
62
0
      IM_W ("asked to add %s to missing list but it's already on the list!\n", sub->dirname);
63
0
      return;
64
0
    }
65
66
0
  IM_W ("adding %s to missing list\n", sub->dirname);
67
0
  missing_sub_list = g_list_prepend (missing_sub_list, sub);
68
69
  /* If the timeout is turned off, we turn it back on */
70
0
  if (!scan_missing_running)
71
0
    {
72
0
      GSource *source;
73
74
0
      scan_missing_running = TRUE;
75
0
      source = g_timeout_source_new_seconds (SCAN_MISSING_TIME);
76
0
      g_source_set_callback (source, im_scan_missing, NULL, NULL);
77
0
      g_source_attach (source, GLIB_PRIVATE_CALL (g_get_worker_context) ());
78
0
      g_source_unref (source);
79
0
    }
80
0
}
81
82
/* inotify_lock must be held before calling */
83
void
84
_im_rm (inotify_sub *sub)
85
0
{
86
0
  GList *link;
87
  
88
0
  link = g_list_find (missing_sub_list, sub);
89
90
0
  if (!link)
91
0
    {
92
0
      IM_W ("asked to remove %s from missing list but it isn't on the list!\n", sub->dirname);
93
0
      return;
94
0
    }
95
96
0
  IM_W ("removing %s from missing list\n", sub->dirname);
97
98
0
  missing_sub_list = g_list_remove_link (missing_sub_list, link);
99
0
  g_list_free_1 (link);
100
0
}
101
102
/* Scans the list of missing subscriptions checking if they
103
 * are available yet.
104
 */
105
static gboolean
106
im_scan_missing (gpointer user_data)
107
0
{
108
0
  GList *nolonger_missing = NULL;
109
0
  GList *l;
110
  
111
0
  G_LOCK (inotify_lock);
112
  
113
0
  IM_W ("scanning missing list with %d items\n", g_list_length (missing_sub_list));
114
0
  for (l = missing_sub_list; l; l = l->next)
115
0
    {
116
0
      inotify_sub *sub = l->data;
117
0
      gboolean not_m = FALSE;
118
      
119
0
      IM_W ("checking %p\n", sub);
120
0
      g_assert (sub);
121
0
      g_assert (sub->dirname);
122
0
      not_m = _ip_start_watching (sub);
123
124
0
      if (not_m)
125
0
  {
126
0
    missing_cb (sub);
127
0
    IM_W ("removed %s from missing list\n", sub->dirname);
128
    /* We have to build a list of list nodes to remove from the
129
     * missing_sub_list. We do the removal outside of this loop.
130
     */
131
0
    nolonger_missing = g_list_prepend (nolonger_missing, l);
132
0
  } 
133
0
    }
134
135
0
  for (l = nolonger_missing; l ; l = l->next)
136
0
    {
137
0
      GList *llink = l->data;
138
0
      missing_sub_list = g_list_remove_link (missing_sub_list, llink);
139
0
      g_list_free_1 (llink);
140
0
    }
141
142
0
  g_list_free (nolonger_missing);
143
  
144
  /* If the missing list is now empty, we disable the timeout */
145
0
  if (missing_sub_list == NULL)
146
0
    {
147
0
      scan_missing_running = FALSE;
148
0
      G_UNLOCK (inotify_lock);
149
0
      return FALSE;
150
0
    }
151
0
  else
152
0
    {
153
0
      G_UNLOCK (inotify_lock);
154
0
      return TRUE;
155
0
    }
156
0
}