Bug Summary

File:menu-monitor.c
Warning:line 168, column 3
Value stored to 'event' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name menu-monitor.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/libmenu -fcoverage-compilation-dir=/rootdir/libmenu -resource-dir /usr/lib/llvm-21/lib/clang/21 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gio-unix-2.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -D CAFEMENU_I_KNOW_THIS_IS_UNSTABLE -D PIC -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -analyzer-checker deadcode.DeadStores -analyzer-checker security.ArrayBound -analyzer-checker unix.cstring.NotNullTerminated -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2026-07-25-091244-11078-1 -x c menu-monitor.c
1/*
2 * Copyright (C) 2005 Red Hat, Inc.
3 * Copyright (C) 2006 Mark McLoughlin
4 * Copyright (C) 2007 Sebastian Dröge
5 * Copyright (C) 2008 Vincent Untz
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 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
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 */
22
23#include <config.h>
24
25#include "menu-monitor.h"
26
27#include <gio/gio.h>
28
29#include "menu-util.h"
30
31struct MenuMonitor {
32 char* path;
33 guint refcount;
34
35 GSList* notifies;
36
37 GFileMonitor* monitor;
38
39 guint is_directory: 1;
40};
41
42typedef struct {
43 MenuMonitor* monitor;
44 MenuMonitorEvent event;
45 char* path;
46} MenuMonitorEventInfo;
47
48typedef struct {
49 MenuMonitorNotifyFunc notify_func;
50 gpointer user_data;
51 guint refcount;
52} MenuMonitorNotify;
53
54static MenuMonitorNotify* cafe_menu_monitor_notify_refmenu_monitor_notify_ref(MenuMonitorNotify* notify);
55static void cafe_menu_monitor_notify_unrefmenu_monitor_notify_unref(MenuMonitorNotify* notify);
56
57static GHashTable* monitors_registry = NULL((void*)0);
58static guint events_idle_handler = 0;
59static GSList* pending_events = NULL((void*)0);
60
61static gpointer
62cafe_menu_monitor_notify_ref_copy (gconstpointer src,
63 gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__)))
64{
65 return cafe_menu_monitor_notify_refmenu_monitor_notify_ref ((MenuMonitorNotify *) src);
66}
67
68static void invoke_notifies(MenuMonitor* monitor, MenuMonitorEvent event, const char* path)
69{
70 GSList *copy;
71 GSList *tmp;
72
73 copy = g_slist_copy_deep (monitor->notifies, cafe_menu_monitor_notify_ref_copy, NULL((void*)0));
74
75 tmp = copy;
76 while (tmp != NULL((void*)0))
77 {
78 MenuMonitorNotify *notify = tmp->data;
79 GSList *next = tmp->next;
80
81 if (notify->notify_func)
82 {
83 notify->notify_func (monitor, event, path, notify->user_data);
84 }
85
86 cafe_menu_monitor_notify_unrefmenu_monitor_notify_unref(notify);
87
88 tmp = next;
89 }
90
91 g_slist_free (copy);
92}
93
94static gboolean emit_events_in_idle (gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__)))
95{
96 GSList *events_to_emit;
97 GSList *tmp;
98
99 events_to_emit = pending_events;
100
101 pending_events = NULL((void*)0);
102 events_idle_handler = 0;
103
104 tmp = events_to_emit;
105 while (tmp != NULL((void*)0))
106 {
107 MenuMonitorEventInfo *event_info = tmp->data;
108
109 cafe_menu_monitor_refmenu_monitor_ref(event_info->monitor);
110
111 tmp = tmp->next;
112 }
113
114 tmp = events_to_emit;
115 while (tmp != NULL((void*)0))
116 {
117 MenuMonitorEventInfo *event_info = tmp->data;
118
119 invoke_notifies (event_info->monitor,
120 event_info->event,
121 event_info->path);
122
123 menu_monitor_unref (event_info->monitor);
124 event_info->monitor = NULL((void*)0);
125
126 g_free (event_info->path);
127 event_info->path = NULL((void*)0);
128
129 event_info->event = MENU_MONITOR_EVENT_INVALID;
130
131 g_free (event_info);
132
133 tmp = tmp->next;
134 }
135
136 g_slist_free (events_to_emit);
137
138 return G_SOURCE_REMOVE(0);
139}
140
141static void menu_monitor_queue_event(MenuMonitorEventInfo* event_info)
142{
143 pending_events = g_slist_append (pending_events, event_info);
144
145 if (events_idle_handler == 0)
146 {
147 events_idle_handler = g_idle_add (emit_events_in_idle, NULL((void*)0));
148 }
149}
150
151static inline char* get_registry_key(const char* path, gboolean is_directory)
152{
153 return g_strdup_printf ("%s:%s",
154 path,
155 is_directory ? "<dir>" : "<file>");
156}
157
158static gboolean monitor_callback (GFileMonitor *monitor G_GNUC_UNUSED__attribute__ ((__unused__)),
159 GFile *child,
160 GFile *other_file G_GNUC_UNUSED__attribute__ ((__unused__)),
161 GFileMonitorEvent eflags,
162 gpointer user_data)
163{
164 MenuMonitorEventInfo *event_info;
165 MenuMonitorEvent event;
166 MenuMonitor *menu_monitor = (MenuMonitor *) user_data;
167
168 event = MENU_MONITOR_EVENT_INVALID;
Value stored to 'event' is never read
169 switch (eflags)
170 {
171 case G_FILE_MONITOR_EVENT_CHANGED:
172 event = MENU_MONITOR_EVENT_CHANGED;
173 break;
174 case G_FILE_MONITOR_EVENT_CREATED:
175 event = MENU_MONITOR_EVENT_CREATED;
176 break;
177 case G_FILE_MONITOR_EVENT_DELETED:
178 event = MENU_MONITOR_EVENT_DELETED;
179 break;
180 default:
181 return TRUE(!(0));
182 }
183
184 event_info = g_new0 (MenuMonitorEventInfo, 1)((MenuMonitorEventInfo *) g_malloc0_n ((1), sizeof (MenuMonitorEventInfo
)))
;
185
186 event_info->path = g_file_get_path (child);
187 event_info->event = event;
188 event_info->monitor = menu_monitor;
189
190 menu_monitor_queue_event (event_info);
191
192 return TRUE(!(0));
193}
194
195static MenuMonitor* register_monitor(const char* path, gboolean is_directory)
196{
197 MenuMonitor *retval;
198 GFile *file;
199
200 retval = g_new0 (MenuMonitor, 1)((MenuMonitor *) g_malloc0_n ((1), sizeof (MenuMonitor)));
201
202 retval->path = g_strdup (path)g_strdup_inline (path);
203 retval->refcount = 1;
204 retval->is_directory = is_directory != FALSE(0);
205
206 file = g_file_new_for_path (retval->path);
207
208 if (file == NULL((void*)0))
209 {
210 menu_verbose ("Not adding monitor on '%s', failed to create GFile\n",
211 retval->path);
212 return retval;
213 }
214
215 if (retval->is_directory)
216 retval->monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE,
217 NULL((void*)0), NULL((void*)0));
218 else
219 retval->monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE,
220 NULL((void*)0), NULL((void*)0));
221
222 g_object_unref (G_OBJECT (file)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((file)), (((GType) ((20) << (2))))))))
);
223
224 if (retval->monitor == NULL((void*)0))
225 {
226 menu_verbose ("Not adding monitor on '%s', failed to create monitor\n",
227 retval->path);
228 return retval;
229 }
230
231 g_signal_connect (retval->monitor, "changed",g_signal_connect_data ((retval->monitor), ("changed"), (((
GCallback) (monitor_callback))), (retval), ((void*)0), (GConnectFlags
) 0)
232 G_CALLBACK (monitor_callback), retval)g_signal_connect_data ((retval->monitor), ("changed"), (((
GCallback) (monitor_callback))), (retval), ((void*)0), (GConnectFlags
) 0)
;
233
234 return retval;
235}
236
237static MenuMonitor* lookup_monitor(const char* path, gboolean is_directory)
238{
239 MenuMonitor *retval;
240 char *registry_key;
241
242 retval = NULL((void*)0);
243
244 registry_key = get_registry_key (path, is_directory);
245
246 if (monitors_registry == NULL((void*)0))
247 {
248 monitors_registry = g_hash_table_new_full (g_str_hash,
249 g_str_equal,
250 g_free,
251 NULL((void*)0));
252 }
253 else
254 {
255 retval = g_hash_table_lookup (monitors_registry, registry_key);
256 }
257
258 if (retval == NULL((void*)0))
259 {
260 retval = register_monitor (path, is_directory);
261 g_hash_table_insert (monitors_registry, registry_key, retval);
262
263 return retval;
264 }
265 else
266 {
267 g_free (registry_key);
268
269 return cafe_menu_monitor_refmenu_monitor_ref(retval);
270 }
271}
272
273MenuMonitor* cafe_menu_monitor_file_getmenu_get_file_monitor(const char* path)
274{
275 g_return_val_if_fail(path != NULL, NULL)do { if ((path != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "path != NULL"); return
(((void*)0)); } } while (0)
;
276
277 return lookup_monitor(path, FALSE(0));
278}
279
280MenuMonitor* menu_get_directory_monitor(const char* path)
281{
282 g_return_val_if_fail (path != NULL, NULL)do { if ((path != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "path != NULL"); return
(((void*)0)); } } while (0)
;
283
284 return lookup_monitor (path, TRUE(!(0)));
285}
286
287MenuMonitor* cafe_menu_monitor_refmenu_monitor_ref(MenuMonitor* monitor)
288{
289 g_return_val_if_fail(monitor != NULL, NULL)do { if ((monitor != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "monitor != NULL"
); return (((void*)0)); } } while (0)
;
290 g_return_val_if_fail(monitor->refcount > 0, NULL)do { if ((monitor->refcount > 0)) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "monitor->refcount > 0"
); return (((void*)0)); } } while (0)
;
291
292 monitor->refcount++;
293
294 return monitor;
295}
296
297static void menu_monitor_clear_pending_events(MenuMonitor* monitor)
298{
299 GSList *tmp;
300
301 tmp = pending_events;
302 while (tmp != NULL((void*)0))
303 {
304 MenuMonitorEventInfo *event_info = tmp->data;
305 GSList *next = tmp->next;
306
307 if (event_info->monitor == monitor)
308 {
309 pending_events = g_slist_delete_link (pending_events, tmp);
310
311 g_free (event_info->path);
312 event_info->path = NULL((void*)0);
313
314 event_info->monitor = NULL((void*)0);
315 event_info->event = MENU_MONITOR_EVENT_INVALID;
316
317 g_free (event_info);
318 }
319
320 tmp = next;
321 }
322}
323
324void menu_monitor_unref(MenuMonitor* monitor)
325{
326 char *registry_key;
327
328 g_return_if_fail (monitor != NULL)do { if ((monitor != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "monitor != NULL"
); return; } } while (0)
;
329 g_return_if_fail (monitor->refcount > 0)do { if ((monitor->refcount > 0)) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "monitor->refcount > 0"
); return; } } while (0)
;
330
331 if (--monitor->refcount > 0)
332 return;
333
334 registry_key = get_registry_key (monitor->path, monitor->is_directory);
335 g_hash_table_remove (monitors_registry, registry_key);
336 g_free (registry_key);
337
338 if (g_hash_table_size (monitors_registry) == 0)
339 {
340 g_hash_table_destroy (monitors_registry);
341 monitors_registry = NULL((void*)0);
342 }
343
344 if (monitor->monitor)
345 {
346 g_file_monitor_cancel (monitor->monitor);
347 g_object_unref (monitor->monitor);
348 monitor->monitor = NULL((void*)0);
349 }
350
351 g_slist_free_full (monitor->notifies, (GDestroyNotify) cafe_menu_monitor_notify_unrefmenu_monitor_notify_unref);
352 monitor->notifies = NULL((void*)0);
353
354 menu_monitor_clear_pending_events (monitor);
355
356 g_free (monitor->path);
357 monitor->path = NULL((void*)0);
358
359 g_free (monitor);
360}
361
362static MenuMonitorNotify* cafe_menu_monitor_notify_refmenu_monitor_notify_ref(MenuMonitorNotify* notify)
363{
364 g_return_val_if_fail(notify != NULL, NULL)do { if ((notify != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "notify != NULL")
; return (((void*)0)); } } while (0)
;
365 g_return_val_if_fail(notify->refcount > 0, NULL)do { if ((notify->refcount > 0)) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "notify->refcount > 0"
); return (((void*)0)); } } while (0)
;
366
367 notify->refcount++;
368
369 return notify;
370}
371
372static void cafe_menu_monitor_notify_unrefmenu_monitor_notify_unref(MenuMonitorNotify* notify)
373{
374 g_return_if_fail(notify != NULL)do { if ((notify != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "notify != NULL")
; return; } } while (0)
;
375 g_return_if_fail(notify->refcount > 0)do { if ((notify->refcount > 0)) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "notify->refcount > 0"
); return; } } while (0)
;
376
377 if (--notify->refcount > 0)
378 {
379 return;
380 }
381
382 g_free(notify);
383}
384
385void menu_monitor_add_notify(MenuMonitor* monitor, MenuMonitorNotifyFunc notify_func, gpointer user_data)
386{
387 MenuMonitorNotify* notify;
388
389 g_return_if_fail(monitor != NULL)do { if ((monitor != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "monitor != NULL"
); return; } } while (0)
;
390 g_return_if_fail(notify_func != NULL)do { if ((notify_func != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "notify_func != NULL"
); return; } } while (0)
;
391
392 GSList* tmp = monitor->notifies;
393
394 while (tmp != NULL((void*)0))
395 {
396 notify = tmp->data;
397
398 if (notify->notify_func == notify_func && notify->user_data == user_data)
399 {
400 break;
401 }
402
403 tmp = tmp->next;
404 }
405
406 if (tmp == NULL((void*)0))
407 {
408 notify = g_new0(MenuMonitorNotify, 1)((MenuMonitorNotify *) g_malloc0_n ((1), sizeof (MenuMonitorNotify
)))
;
409 notify->notify_func = notify_func;
410 notify->user_data = user_data;
411 notify->refcount = 1;
412
413 monitor->notifies = g_slist_append(monitor->notifies, notify);
414 }
415}
416
417void cafe_menu_monitor_notify_removemenu_monitor_remove_notify(MenuMonitor* monitor, MenuMonitorNotifyFunc notify_func, gpointer user_data)
418{
419 GSList* tmp = monitor->notifies;
420
421 while (tmp != NULL((void*)0))
422 {
423 MenuMonitorNotify* notify = tmp->data;
424 GSList* next = tmp->next;
425
426 if (notify->notify_func == notify_func && notify->user_data == user_data)
427 {
428 notify->notify_func = NULL((void*)0);
429 notify->user_data = NULL((void*)0);
430
431 cafe_menu_monitor_notify_unrefmenu_monitor_notify_unref(notify);
432
433 monitor->notifies = g_slist_delete_link(monitor->notifies, tmp);
434 }
435
436 tmp = next;
437 }
438}