Bug Summary

File:builds/wireshark/wireshark/epan/color_filters.c
Warning:line 884, column 13
File position of the stream might be 'indeterminate' after a failed operation. Can cause undefined behavior

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 color_filters.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 -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-21/lib/clang/21 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /builds/wireshark/wireshark/epan -isystem /builds/wireshark/wireshark/build/epan -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /usr/include/lua5.4 -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -D epan_EXPORTS -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -I /builds/wireshark/wireshark/wiretap -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-nonliteral -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2026-04-10-100350-3642-1 -x c /builds/wireshark/wireshark/epan/color_filters.c
1/* color_filters.c
2 * Routines for color filters
3 *
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <[email protected]>
6 * Copyright 1998 Gerald Combs
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10/*
11 * Updated 1 Dec 10 jjm
12 */
13
14#include "config.h"
15#define WS_LOG_DOMAIN"Epan" LOG_DOMAIN_EPAN"Epan"
16
17#include <glib.h>
18
19#include <errno(*__errno_location ()).h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include <wsutil/filesystem.h>
25#include <wsutil/file_util.h>
26#include <wsutil/report_message.h>
27#include <wsutil/wslog.h>
28#include <wsutil/ws_assert.h>
29#include <wsutil/wmem/wmem_list.h>
30
31#include <epan/packet.h>
32#include "color_filters.h"
33#include "file.h"
34#include <epan/dfilter/dfilter.h>
35#include <epan/prefs.h>
36#include <epan/epan_dissect.h>
37
38/*
39 * Each line in the colorfilters file has the following format:
40 *
41 * @<filter name>@<filter string>@[<background>][<foreground>]
42 * Background and foreground colors are 16-bit comma-separated RGB
43 * triplets. Colors are 16 bits because that's what GdkColor used.
44 * We might want to use a more standard, copy+paste-able color scheme
45 * such as #RRGGBB instead.
46 */
47
48static int read_filters_file(const char *path, FILE *f, void *user_data, color_filter_add_cb_func add_cb);
49
50/* the currently active filters */
51static GSList *color_filter_list;
52
53/* keep "old" deleted filters in this list until
54 * the dissection no longer needs them (e.g. file is closed) */
55static GSList *color_filter_deleted_list;
56static GSList *color_filter_valid_list;
57
58/* Color Filters can en-/disabled. */
59static bool_Bool filters_enabled = true1;
60
61/* Session-level disabled (paused) filters */
62static GHashTable *session_disabled_filters;
63
64/* Remember if there are temporary coloring filters set to
65 * add sensitivity to the "Reset Coloring 1-10" menu item
66 */
67static bool_Bool tmp_colors_set;
68
69/* Create a new filter */
70color_filter_t *
71color_filter_new(const char *name, /* The name of the filter to create */
72 const char *filter_string, /* The string representing the filter */
73 color_t *bg_color, /* The background color */
74 color_t *fg_color, /* The foreground color */
75 bool_Bool disabled) /* Is the filter disabled? */
76{
77 color_filter_t *colorf;
78
79 colorf = g_new0(color_filter_t, 1)((color_filter_t *) g_malloc0_n ((1), sizeof (color_filter_t)
))
;
80 colorf->filter_name = g_strdup(name)g_strdup_inline (name);
81 colorf->filter_text = g_strdup(filter_string)g_strdup_inline (filter_string);
82 colorf->bg_color = *bg_color;
83 colorf->fg_color = *fg_color;
84 colorf->disabled = disabled;
85 return colorf;
86}
87
88/* Add ten empty (temporary) colorfilters for easy coloring */
89static void
90color_filters_add_tmp(GSList **cfl)
91{
92 char *name = NULL((void*)0);
93 uint32_t i;
94 char** bg_colors;
95 char** fg_colors;
96 unsigned long cval;
97 color_t bg_color, fg_color;
98 color_filter_t *colorf;
99
100 ws_assert(strlen(prefs.gui_colorized_fg)==69)do { if ((1) && !(strlen(prefs.gui_colorized_fg)==69)
) ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/color_filters.c"
, 100, __func__, "assertion failed: %s", "strlen(prefs.gui_colorized_fg)==69"
); } while (0)
;
101 ws_assert(strlen(prefs.gui_colorized_bg)==69)do { if ((1) && !(strlen(prefs.gui_colorized_bg)==69)
) ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/color_filters.c"
, 101, __func__, "assertion failed: %s", "strlen(prefs.gui_colorized_bg)==69"
); } while (0)
;
102 fg_colors = g_strsplit(prefs.gui_colorized_fg, ",", -1);
103 bg_colors = g_strsplit(prefs.gui_colorized_bg, ",", -1);
104
105 for ( i=1 ; i<=10 ; i++ ) {
106 name = ws_strdup_printf("%s%02d",CONVERSATION_COLOR_PREFIX,i)wmem_strdup_printf(((void*)0), "%s%02d","___conversation_color_filter___"
,i)
;
107
108 /* retrieve background and foreground colors */
109 cval = strtoul(fg_colors[i-1], NULL((void*)0), 16);
110 fg_color.red = RED_COMPONENT(cval)(uint16_t) (((((cval) >> 16) & 0xff) * 65535 / 255)
)
;
111 fg_color.green = GREEN_COMPONENT(cval)(uint16_t) (((((cval) >> 8) & 0xff) * 65535 / 255));
112 fg_color.blue = BLUE_COMPONENT(cval)(uint16_t) ( (((cval) & 0xff) * 65535 / 255));
113 cval = strtoul(bg_colors[i-1], NULL((void*)0), 16);
114 bg_color.red = RED_COMPONENT(cval)(uint16_t) (((((cval) >> 16) & 0xff) * 65535 / 255)
)
;
115 bg_color.green = GREEN_COMPONENT(cval)(uint16_t) (((((cval) >> 8) & 0xff) * 65535 / 255));
116 bg_color.blue = BLUE_COMPONENT(cval)(uint16_t) ( (((cval) & 0xff) * 65535 / 255));
117 colorf = color_filter_new(name, NULL((void*)0), &bg_color, &fg_color, true1);
118 colorf->filter_text = g_strdup("frame")g_strdup_inline ("frame");
119 *cfl = g_slist_append(*cfl, colorf);
120
121 g_free(name);
122 }
123
124 g_strfreev(fg_colors);
125 g_strfreev(bg_colors);
126}
127
128static int
129color_filters_find_by_name_cb(const void *arg1, const void *arg2)
130{
131 const color_filter_t *colorf = (const color_filter_t *)arg1;
132 const char *name = (const char *)arg2;
133
134 return strcmp(colorf->filter_name, name);
135}
136
137/* Get the filter of a temporary color filter */
138char*
139color_filters_get_tmp(uint8_t filt_nr)
140{
141 char* name = NULL((void*)0);
142 char* filter = NULL((void*)0);
143 GSList* cfl;
144 color_filter_t* colorf;
145 /* Only perform a lookup if the supplied filter number is in the expected range */
146 if (filt_nr < 1 || filt_nr > 10)
147 return NULL((void*)0);
148
149 name = ws_strdup_printf("%s%02d", CONVERSATION_COLOR_PREFIX, filt_nr)wmem_strdup_printf(((void*)0), "%s%02d", "___conversation_color_filter___"
, filt_nr)
;
150 cfl = g_slist_find_custom(color_filter_list, name, color_filters_find_by_name_cb);
151 colorf = (color_filter_t*)cfl->data;
152
153 if (!colorf->disabled)
154 filter = g_strdup(colorf->filter_text)g_strdup_inline (colorf->filter_text);
155
156 g_free(name);
157
158 return filter;
159}
160
161/* Set the filter off a temporary colorfilters and enable it */
162bool_Bool
163color_filters_set_tmp(uint8_t filt_nr, const char *filter, bool_Bool disabled, char **err_msg)
164{
165 char *name = NULL((void*)0);
166 const char *tmpfilter = NULL((void*)0);
167 GSList *cfl;
168 color_filter_t *colorf;
169 dfilter_t *compiled_filter;
170 uint8_t i;
171 df_error_t *df_err = NULL((void*)0);
172 /* Go through the temporary filters and look for the same filter string.
173 * If found, clear it so that a filter can be "moved" up and down the list
174 */
175 for ( i=1 ; i<=10 ; i++ ) {
176 /* If we need to reset the temporary filter (filter==NULL), don't look
177 * for other rules with the same filter string
178 */
179 if( i!=filt_nr && filter==NULL((void*)0) )
180 continue;
181
182 name = ws_strdup_printf("%s%02d",CONVERSATION_COLOR_PREFIX,i)wmem_strdup_printf(((void*)0), "%s%02d","___conversation_color_filter___"
,i)
;
183 cfl = g_slist_find_custom(color_filter_list, name, color_filters_find_by_name_cb);
184 colorf = (color_filter_t *)cfl->data;
185
186 /* Only change the filter rule if this is the rule to change or if
187 * a matching filter string has been found
188 */
189 if(colorf && ( i == filt_nr || filter == NULL((void*)0) || !strcmp(filter, colorf->filter_text) ) ) {
190 /* set filter string to "frame" if we are resetting the rules
191 * or if we found a matching filter string which need to be cleared
192 */
193 tmpfilter = ( (filter==NULL((void*)0)) || (i!=filt_nr) ) ? "frame" : filter;
194 if (!dfilter_compile(tmpfilter, &compiled_filter, &df_err)dfilter_compile_full(tmpfilter, &compiled_filter, &df_err
, (1U << 1)|(1U << 2), __func__)
) {
195 *err_msg = ws_strdup_printf( "Could not compile color filter name: \"%s\" text: \"%s\".\n%s", name, filter, df_err->msg)wmem_strdup_printf(((void*)0), "Could not compile color filter name: \"%s\" text: \"%s\".\n%s"
, name, filter, df_err->msg)
;
196 df_error_free(&df_err);
197 g_free(name);
198 return false0;
199 } else {
200 g_free(colorf->filter_text);
201 dfilter_free(colorf->c_colorfilter);
202 colorf->filter_text = g_strdup(tmpfilter)g_strdup_inline (tmpfilter);
203 colorf->c_colorfilter = compiled_filter;
204 colorf->disabled = ((i!=filt_nr) ? true1 : disabled);
205 /* Remember that there are now temporary coloring filters set */
206 if( filter )
207 tmp_colors_set = true1;
208 }
209 }
210 g_free(name);
211 }
212 return true1;
213}
214
215const color_filter_t *
216color_filters_tmp_color(uint8_t filter_num) {
217 char *name;
218 color_filter_t *colorf = NULL((void*)0);
219 GSList *cfl;
220
221 name = ws_strdup_printf("%s%02d", CONVERSATION_COLOR_PREFIX, filter_num)wmem_strdup_printf(((void*)0), "%s%02d", "___conversation_color_filter___"
, filter_num)
;
222 cfl = g_slist_find_custom(color_filter_list, name, color_filters_find_by_name_cb);
223 if (cfl) {
224 colorf = (color_filter_t *)cfl->data;
225 }
226 g_free(name);
227
228 return colorf;
229}
230
231/* Reset the temporary colorfilters */
232bool_Bool
233color_filters_reset_tmp(char **err_msg)
234{
235 uint8_t i;
236
237 for ( i=1 ; i<=10 ; i++ ) {
238 if (!color_filters_set_tmp(i, NULL((void*)0), true1, err_msg))
239 return false0;
240 }
241 /* Remember that there are now *no* temporary coloring filters set */
242 tmp_colors_set = false0;
243 return true1;
244}
245
246/* delete the specified filter */
247void
248color_filter_delete(color_filter_t *colorf)
249{
250 g_free(colorf->filter_name);
251 g_free(colorf->filter_text);
252 dfilter_free(colorf->c_colorfilter);
253 g_free(colorf);
254}
255
256/* delete the specified filter (called from g_slist_foreach) */
257static void
258color_filter_delete_cb(void *filter_arg)
259{
260 color_filter_t *colorf = (color_filter_t *)filter_arg;
261
262 color_filter_delete(colorf);
263}
264
265/* delete the specified list */
266void
267color_filter_list_delete(GSList **cfl)
268{
269 g_slist_free_full(*cfl, color_filter_delete_cb);
270 *cfl = NULL((void*)0);
271}
272
273/* clone a single list entries from normal to edit list */
274static color_filter_t *
275color_filter_clone(color_filter_t *colorf)
276{
277 color_filter_t *new_colorf;
278
279 new_colorf = g_new(color_filter_t, 1)((color_filter_t *) g_malloc_n ((1), sizeof (color_filter_t))
)
;
280 new_colorf->filter_name = g_strdup(colorf->filter_name)g_strdup_inline (colorf->filter_name);
281 new_colorf->filter_text = g_strdup(colorf->filter_text)g_strdup_inline (colorf->filter_text);
282 new_colorf->bg_color = colorf->bg_color;
283 new_colorf->fg_color = colorf->fg_color;
284 new_colorf->disabled = colorf->disabled;
285 new_colorf->c_colorfilter = NULL((void*)0);
286
287 return new_colorf;
288}
289
290static void
291color_filter_list_clone_cb(void *filter_arg, void *cfl_arg)
292{
293 GSList **cfl = (GSList **)cfl_arg;
294 color_filter_t *new_colorf;
295
296 new_colorf = color_filter_clone((color_filter_t *)filter_arg);
297 *cfl = g_slist_append(*cfl, new_colorf);
298}
299
300/* clone the specified list */
301static GSList *
302color_filter_list_clone(GSList *cfl)
303{
304 GSList *new_list = NULL((void*)0);
305
306 g_slist_foreach(cfl, color_filter_list_clone_cb, &new_list);
307
308 return new_list;
309}
310
311static bool_Bool
312color_filters_get(char** err_msg, color_filter_add_cb_func add_cb, const char* app_env_var_prefix)
313{
314 char *path;
315 FILE *f;
316 int ret;
317
318 /* start the list with the temporary colorizing rules */
319 color_filters_add_tmp(&color_filter_list);
320
321 /*
322 * Try to get the user's filters.
323 *
324 * Get the path for the file that would have their filters, and
325 * try to open it.
326 */
327 path = get_persconffile_path(COLORFILTERS_FILE_NAME"colorfilters", true1, app_env_var_prefix);
328 if ((f = ws_fopenfopen(path, "r")) == NULL((void*)0)) {
329 if (errno(*__errno_location ()) != ENOENT2) {
330 /* Error trying to open the file; give up. */
331 *err_msg = ws_strdup_printf("Could not open filter file\n\"%s\": %s.", path,wmem_strdup_printf(((void*)0), "Could not open filter file\n\"%s\": %s."
, path, g_strerror((*__errno_location ())))
332 g_strerror(errno))wmem_strdup_printf(((void*)0), "Could not open filter file\n\"%s\": %s."
, path, g_strerror((*__errno_location ())))
;
333 g_free(path);
334 return false0;
335 }
336 /* They don't have any filters; try to read the global filters */
337 g_free(path);
338 return color_filters_read_globals(&color_filter_list, err_msg, add_cb, app_env_var_prefix);
339 }
340
341 /*
342 * We've opened it; try to read it.
343 */
344 ret = read_filters_file(path, f, &color_filter_list, add_cb);
345 if (ret != 0) {
346 *err_msg = ws_strdup_printf("Error reading filter file\n\"%s\": %s.",wmem_strdup_printf(((void*)0), "Error reading filter file\n\"%s\": %s."
, path, g_strerror((*__errno_location ())))
347 path, g_strerror(errno))wmem_strdup_printf(((void*)0), "Error reading filter file\n\"%s\": %s."
, path, g_strerror((*__errno_location ())))
;
348 fclose(f);
349 g_free(path);
350 return false0;
351 }
352
353 /* Success. */
354 fclose(f);
355 g_free(path);
356 return true1;
357}
358
359/* Initialize the filter structures (reading from file) for general running, including app startup */
360bool_Bool
361color_filters_init(char** err_msg, color_filter_add_cb_func add_cb, const char* app_env_var_prefix)
362{
363 /* delete all currently existing filters */
364 color_filter_list_delete(&color_filter_list);
365
366 /* now try to construct the filters list */
367 bool_Bool result = color_filters_get(err_msg, add_cb, app_env_var_prefix);
368
369 /* Load paused filters from profile after loading color filters */
370 if (result) {
371 color_filter_read_paused(app_env_var_prefix);
372 }
373
374 return result;
375}
376
377bool_Bool
378color_filters_reload(char** err_msg, color_filter_add_cb_func add_cb, const char* app_env_var_prefix)
379{
380 /* "move" old entries to the deleted list
381 * we must keep them until the dissection no longer needs them */
382 color_filter_deleted_list = g_slist_concat(color_filter_deleted_list, color_filter_list);
383 color_filter_list = NULL((void*)0);
384
385 /* now try to construct the filters list */
386 return color_filters_get(err_msg, add_cb, app_env_var_prefix);
387}
388
389void
390color_filters_cleanup(void)
391{
392 /* delete the previously deleted filters */
393 color_filter_list_delete(&color_filter_deleted_list);
394
395 if (session_disabled_filters) {
396 g_hash_table_destroy(session_disabled_filters);
397 session_disabled_filters = NULL((void*)0);
398 }
399}
400
401typedef struct _color_clone
402{
403 void *user_data;
404 color_filter_add_cb_func add_cb;
405} color_clone_t;
406
407static void
408color_filters_clone_cb(void *filter_arg, void *user_data)
409{
410 color_clone_t* clone_data = (color_clone_t*)user_data;
411 color_filter_t * new_colorf = color_filter_clone((color_filter_t *)filter_arg);
412
413 clone_data->add_cb (new_colorf, clone_data->user_data);
414}
415
416void
417color_filters_clone(void *user_data, color_filter_add_cb_func add_cb)
418{
419 color_clone_t clone_data;
420
421 clone_data.user_data = user_data;
422 clone_data.add_cb = add_cb;
423 g_slist_foreach(color_filter_list, color_filters_clone_cb, &clone_data);
424}
425
426
427static void
428color_filter_compile_cb(void *filter_arg, void *err)
429{
430 color_filter_t *colorf = (color_filter_t *)filter_arg;
431 char **err_msg = (char**)err;
432 df_error_t *df_err = NULL((void*)0);
433
434 ws_assert(colorf->c_colorfilter == NULL)do { if ((1) && !(colorf->c_colorfilter == ((void*
)0))) ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/color_filters.c"
, 434, __func__, "assertion failed: %s", "colorf->c_colorfilter == ((void*)0)"
); } while (0)
;
435
436 /* If the filter is disabled it doesn't matter if it compiles or not. */
437 if (colorf->disabled) return;
438
439 if (!dfilter_compile(colorf->filter_text, &colorf->c_colorfilter, &df_err)dfilter_compile_full(colorf->filter_text, &colorf->
c_colorfilter, &df_err, (1U << 1)|(1U << 2), __func__
)
) {
440 *err_msg = ws_strdup_printf("Could not compile color filter name: \"%s\" text: \"%s\".\n%s",wmem_strdup_printf(((void*)0), "Could not compile color filter name: \"%s\" text: \"%s\".\n%s"
, colorf->filter_name, colorf->filter_text, df_err->
msg)
441 colorf->filter_name, colorf->filter_text, df_err->msg)wmem_strdup_printf(((void*)0), "Could not compile color filter name: \"%s\" text: \"%s\".\n%s"
, colorf->filter_name, colorf->filter_text, df_err->
msg)
;
442 df_error_free(&df_err);
443 /* this filter was compilable before, so this should never happen */
444 /* except if the OK button of the parent window has been clicked */
445 /* so don't use ws_assert_not_reached() but check the filters again */
446 }
447}
448
449static void
450color_filter_validate_cb(void *filter_arg, void *err)
451{
452 color_filter_t *colorf = (color_filter_t *)filter_arg;
453 char **err_msg = (char**)err;
454 df_error_t *df_err = NULL((void*)0);
455
456 ws_assert(colorf->c_colorfilter == NULL)do { if ((1) && !(colorf->c_colorfilter == ((void*
)0))) ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/color_filters.c"
, 456, __func__, "assertion failed: %s", "colorf->c_colorfilter == ((void*)0)"
); } while (0)
;
457
458 /* If the filter is disabled it doesn't matter if it compiles or not. */
459 if (colorf->disabled) return;
460
461 if (!dfilter_compile(colorf->filter_text, &colorf->c_colorfilter, &df_err)dfilter_compile_full(colorf->filter_text, &colorf->
c_colorfilter, &df_err, (1U << 1)|(1U << 2), __func__
)
) {
462 *err_msg = ws_strdup_printf("Disabling color filter name: \"%s\" filter: \"%s\".\n%s",wmem_strdup_printf(((void*)0), "Disabling color filter name: \"%s\" filter: \"%s\".\n%s"
, colorf->filter_name, colorf->filter_text, df_err->
msg)
463 colorf->filter_name, colorf->filter_text, df_err->msg)wmem_strdup_printf(((void*)0), "Disabling color filter name: \"%s\" filter: \"%s\".\n%s"
, colorf->filter_name, colorf->filter_text, df_err->
msg)
;
464 df_error_free(&df_err);
465
466 /* Disable the color filter in the list of color filters. */
467 colorf->disabled = true1;
468 }
469
470 /* XXX: What if the color filter tests "frame.coloring_rule.name" or
471 * "frame.coloring_rule.string"?
472 */
473}
474
475/* apply changes from the edit list */
476bool_Bool
477color_filters_apply(GSList *tmp_cfl, GSList *edit_cfl, char** err_msg)
478{
479 bool_Bool ret = true1;
480
481 *err_msg = NULL((void*)0);
482
483 /* "move" old entries to the deleted list
484 * we must keep them until the dissection no longer needs them */
485 color_filter_deleted_list = g_slist_concat(color_filter_deleted_list, color_filter_list);
486 color_filter_list = NULL((void*)0);
487
488 /* clone all list entries from tmp/edit to normal list */
489 color_filter_list_delete(&color_filter_valid_list);
490 color_filter_valid_list = color_filter_list_clone(tmp_cfl);
491 color_filter_valid_list = g_slist_concat(color_filter_valid_list,
492 color_filter_list_clone(edit_cfl) );
493
494 /* compile all filter */
495 g_slist_foreach(color_filter_valid_list, color_filter_validate_cb, err_msg);
496 if (*err_msg != NULL((void*)0)) {
497 ret = false0;
498 }
499
500 /* clone all list entries from tmp/edit to normal list */
501 color_filter_list = color_filter_list_clone(color_filter_valid_list);
502
503 /* compile all filter */
504 g_slist_foreach(color_filter_list, color_filter_compile_cb, err_msg);
505 if (*err_msg != NULL((void*)0)) {
506 ret = false0;
507 }
508
509 return ret;
510}
511
512bool_Bool
513color_filters_used(void)
514{
515 return color_filter_list != NULL((void*)0) && filters_enabled;
516}
517
518bool_Bool
519tmp_color_filters_used(void)
520{
521 return tmp_colors_set;
522}
523
524/* prepare the epan_dissect_t for the filter */
525static void
526prime_edt(void *data, void *user_data)
527{
528 color_filter_t *colorf = (color_filter_t *)data;
529 epan_dissect_t *edt = (epan_dissect_t *)user_data;
530
531 if (colorf->c_colorfilter != NULL((void*)0))
532 epan_dissect_prime_with_dfilter(edt, colorf->c_colorfilter);
533}
534
535/* Prime the epan_dissect_t with all the compiler
536 * color filters in 'color_filter_list'. */
537void
538color_filters_prime_edt(epan_dissect_t *edt)
539{
540 if (color_filters_used())
541 g_slist_foreach(color_filter_list, prime_edt, edt);
542}
543
544static int
545find_hfid(const void *data, const void *user_data)
546{
547 color_filter_t *colorf = (color_filter_t *)data;
548 int hfid = GPOINTER_TO_INT(user_data)((gint) (glong) (user_data));
549
550 if ((!colorf->disabled) && colorf->c_colorfilter != NULL((void*)0)) {
551 if (dfilter_interested_in_field(colorf->c_colorfilter, hfid)) {
552 return 0;
553 }
554 }
555 return -1;
556}
557
558bool_Bool
559color_filters_use_hfid(int hfid)
560{
561 GSList *item = NULL((void*)0);
562 if (color_filters_used())
563 item = g_slist_find_custom(color_filter_list, GINT_TO_POINTER(hfid)((gpointer) (glong) (hfid)), find_hfid);
564 return (item != NULL((void*)0));
565}
566
567static int
568find_proto(const void *data, const void *user_data)
569{
570 color_filter_t *colorf = (color_filter_t *)data;
571 int proto_id = GPOINTER_TO_INT(user_data)((gint) (glong) (user_data));
572
573 if ((!colorf->disabled) && colorf->c_colorfilter != NULL((void*)0)) {
574 if (dfilter_interested_in_proto(colorf->c_colorfilter, proto_id)) {
575 return 0;
576 }
577 }
578 return -1;
579}
580
581bool_Bool
582color_filters_use_proto(int proto_id)
583{
584 GSList *item = NULL((void*)0);
585 if (color_filters_used())
586 item = g_slist_find_custom(color_filter_list, GINT_TO_POINTER(proto_id)((gpointer) (glong) (proto_id)), find_proto);
587 return (item != NULL((void*)0));
588}
589
590/* * Return the color_t for later use */
591const color_filter_t *
592color_filters_colorize_packet(epan_dissect_t *edt)
593{
594 GSList *curr;
595 color_filter_t *colorf;
596
597 /* If we have color filters, "search" for the matching one. */
598 if ((edt->tree != NULL((void*)0)) && (color_filters_used())) {
599 curr = color_filter_list;
600
601 while(curr != NULL((void*)0)) {
602 colorf = (color_filter_t *)curr->data;
603 if ( (!colorf->disabled) &&
604 (colorf->c_colorfilter != NULL((void*)0)) &&
605 dfilter_apply_edt(colorf->c_colorfilter, edt) &&
606 !color_filter_is_session_disabled(colorf->filter_name)) {
607 return colorf;
608 }
609 curr = g_slist_next(curr)((curr) ? (((GSList *)(curr))->next) : ((void*)0));
610 }
611 }
612
613 return NULL((void*)0);
614}
615
616const color_filter_t *
617color_filters_colorize_packet_all(epan_dissect_t *edt,
618 wmem_allocator_t *scope, wmem_list_t **matches)
619{
620 const color_filter_t *first_match = NULL((void*)0);
621
622 if (matches) {
623 *matches = NULL((void*)0);
624 }
625
626 /* If we have color filters, collect ALL matching ones. */
627 if ((edt->tree != NULL((void*)0)) && (color_filters_used())) {
628 for (GSList *curr = color_filter_list; curr != NULL((void*)0); curr = g_slist_next(curr)((curr) ? (((GSList *)(curr))->next) : ((void*)0))) {
629 color_filter_t *colorf = (color_filter_t *)curr->data;
630 if ((!colorf->disabled) &&
631 (colorf->c_colorfilter != NULL((void*)0)) &&
632 dfilter_apply_edt(colorf->c_colorfilter, edt)) {
633
634 bool_Bool is_session_disabled = color_filter_is_session_disabled(colorf->filter_name);
635
636 /* Add to matches list even if paused (for Frame tree display) */
637 if (matches) {
638 if (*matches == NULL((void*)0)) {
639 *matches = wmem_list_new(scope);
640 }
641 wmem_list_append(*matches, colorf);
642 }
643
644 /* Only use non-paused filters for first_match */
645 if (!first_match && !is_session_disabled) {
646 first_match = colorf; /* Backward compatibility */
647 }
648 }
649 }
650 }
651
652 return first_match;
653}
654
655void
656color_filter_set_session_disabled(const char *filter_name, bool_Bool disabled)
657{
658 if (!filter_name) return;
659
660 if (!session_disabled_filters) {
661 session_disabled_filters = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL((void*)0));
662 }
663
664 if (disabled) {
665 g_hash_table_insert(session_disabled_filters, g_strdup(filter_name)g_strdup_inline (filter_name), GINT_TO_POINTER(1)((gpointer) (glong) (1)));
666 } else {
667 g_hash_table_remove(session_disabled_filters, filter_name);
668 }
669
670 /* Auto-save to profile directory after every change */
671 color_filter_write_paused(NULL((void*)0)); /* NULL uses default env prefix */
672}
673
674bool_Bool
675color_filter_is_session_disabled(const char *filter_name)
676{
677 if (!filter_name || !session_disabled_filters) {
678 return false0;
679 }
680 return g_hash_table_contains(session_disabled_filters, filter_name);
681}
682
683void
684color_filter_clear_session_disabled(void)
685{
686 if (session_disabled_filters) {
687 g_hash_table_remove_all(session_disabled_filters);
688 }
689 /* Restore from profile directory after clearing (workaround for rescan) */
690 color_filter_read_paused(NULL((void*)0));
691}
692
693#define PAUSED_FILTERS_FILE"paused_filters" "paused_filters"
694
695/* Get profile-specific paused filters file path */
696static char *
697get_paused_filters_path(const char *app_env_var_prefix)
698{
699 /* Use profile-specific path (true = use profile directory) */
700 return get_persconffile_path(PAUSED_FILTERS_FILE"paused_filters", true1, app_env_var_prefix);
701}
702
703/* Save paused filters to profile directory */
704void
705color_filter_write_paused(const char *app_env_var_prefix)
706{
707 if (!session_disabled_filters) return;
708
709 char *path = get_paused_filters_path(app_env_var_prefix);
710 if (!path) return;
711
712 FILE *f = ws_fopenfopen(path, "w");
713 if (!f) {
714 g_free(path);
715 return;
716 }
717
718 /* Write each paused filter name, one per line */
719 GHashTableIter iter;
720 gpointer key, value;
721 g_hash_table_iter_init(&iter, session_disabled_filters);
722 while (g_hash_table_iter_next(&iter, &key, &value)) {
723 fprintf(f, "%s\n", (const char*)key);
724 }
725
726 fclose(f);
727 g_free(path);
728}
729
730/* Read paused filters from profile directory */
731void
732color_filter_read_paused(const char *app_env_var_prefix)
733{
734 char *path = get_paused_filters_path(app_env_var_prefix);
735 if (!path) return;
736
737 FILE *f = ws_fopenfopen(path, "r");
738 g_free(path);
739
740 if (!f) return; /* File doesn't exist yet - that's OK */
741
742 char line[1024];
743 while (fgets(line, sizeof(line), f)) {
744 /* Remove trailing newline/whitespace */
745 line[strcspn(line, "\r\n")] = 0;
746 g_strstrip(line)g_strchomp (g_strchug (line)); /* GLib function to trim whitespace */
747
748 if (line[0] && line[0] != '#') { /* Skip empty lines and comments */
749 /* Add to session_disabled_filters without triggering auto-save */
750 if (!session_disabled_filters) {
751 session_disabled_filters = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL((void*)0));
752 }
753 g_hash_table_insert(session_disabled_filters, g_strdup(line)g_strdup_inline (line), GINT_TO_POINTER(1)((gpointer) (glong) (1)));
754 }
755 }
756
757 fclose(f);
758}
759
760/* Resume all paused filters (clears all and saves empty file) */
761void
762color_filter_resume_all(const char *app_env_var_prefix)
763{
764 /* Clear the hash table */
765 if (session_disabled_filters) {
766 g_hash_table_remove_all(session_disabled_filters);
767 }
768
769 /* Write empty file to profile directory */
770 char *path = get_paused_filters_path(app_env_var_prefix);
771 if (!path) return;
772
773 FILE *f = ws_fopenfopen(path, "w");
774 if (f) {
775 /* Write empty file (or just close it) */
776 fclose(f);
777 }
778 g_free(path);
779}
780
781/* read filters from the given file */
782/* XXX - Would it make more sense to use GStrings here instead of reallocing
783 our buffers? */
784static int
785read_filters_file(const char *path, FILE *f, void *user_data, color_filter_add_cb_func add_cb)
786{
787#define INIT_BUF_SIZE128 128
788 char *name;
789 char *filter_exp;
790 uint32_t name_len = INIT_BUF_SIZE128;
791 uint32_t filter_exp_len = INIT_BUF_SIZE128;
792 uint32_t i = 0;
793 int c;
794 uint16_t fg_r, fg_g, fg_b, bg_r, bg_g, bg_b;
795 bool_Bool disabled = false0;
796 bool_Bool skip_end_of_line = false0;
797 int ret = 0;
798
799 name = (char *)g_malloc(name_len + 1);
800 filter_exp = (char *)g_malloc(filter_exp_len + 1);
801
802 while (1) {
3
Loop condition is true. Entering loop body
37
Loop condition is true. Entering loop body
803
804 if (skip_end_of_line
3.1
'skip_end_of_line' is false
37.1
'skip_end_of_line' is true
) {
38
Taking true branch
805 do {
41
Loop condition is false. Exiting loop
806 c = ws_getc_unlockedgetc_unlocked(f);
807 } while (c != EOF(-1) && c != '\n');
39
Assuming the condition is true
40
Assuming the condition is false
808 if (c == EOF(-1))
42
Taking false branch
809 break;
810 disabled = false0;
811 skip_end_of_line = false0;
812 }
813
814 while ((c = ws_getc_unlockedgetc_unlocked(f)) != EOF(-1) && g_ascii_isspace(c)((g_ascii_table[(guchar) (c)] & G_ASCII_SPACE) != 0)) {
4
Assuming the condition is true
5
Loop condition is false. Execution continues on line 820
43
Assuming the condition is true
44
Loop condition is false. Execution continues on line 820
815 if (c == '\n') {
816 continue;
817 }
818 }
819
820 if (c == EOF(-1))
6
Taking false branch
45
Taking false branch
821 break;
822
823 if (c == '!') {
7
Assuming the condition is false
8
Taking false branch
46
Assuming the condition is false
47
Taking false branch
824 disabled = true1;
825 continue;
826 }
827
828 /* skip # comments and invalid lines */
829 if (c != '@') {
9
Assuming the condition is false
10
Taking false branch
48
Assuming the condition is false
49
Taking false branch
830 skip_end_of_line = true1;
831 continue;
832 }
833
834 /* we get the @ delimiter.
835 * Format is:
836 * @name@filter expression@[background r,g,b][foreground r,g,b]
837 */
838
839 /* retrieve name */
840 i = 0;
841 while (1) {
11
Loop condition is true. Entering loop body
16
Loop condition is true. Entering loop body
50
Loop condition is true. Entering loop body
55
Loop condition is true. Entering loop body
842 c = ws_getc_unlockedgetc_unlocked(f);
843 if (c == EOF(-1) || c == '@')
12
Assuming the condition is false
13
Assuming the condition is false
14
Taking false branch
17
Assuming the condition is false
18
Assuming the condition is true
19
Taking true branch
51
Assuming the condition is false
52
Assuming the condition is false
53
Taking false branch
56
Assuming the condition is false
57
Assuming the condition is true
58
Taking true branch
844 break;
20
Execution continues on line 852
59
Execution continues on line 852
845 if (i
14.1
'i' is < 'name_len'
53.1
'i' is < 'name_len'
>= name_len) {
15
Taking false branch
54
Taking false branch
846 /* buffer isn't long enough; double its length.*/
847 name_len *= 2;
848 name = (char *)g_realloc(name, name_len + 1);
849 }
850 name[i++] = c;
851 }
852 name[i] = '\0';
853
854 if (c == EOF(-1)) {
21
Taking false branch
60
Taking false branch
855 break;
856 } else if (i
21.1
'i' is not equal to 0
60.1
'i' is not equal to 0
== 0) {
22
Taking false branch
61
Taking false branch
857 skip_end_of_line = true1;
858 continue;
859 }
860
861 /* retrieve filter expression */
862 i = 0;
863 while (1) {
23
Loop condition is true. Entering loop body
28
Loop condition is true. Entering loop body
62
Loop condition is true. Entering loop body
67
Loop condition is true. Entering loop body
864 c = ws_getc_unlockedgetc_unlocked(f);
865 if (c == EOF(-1) || c == '@')
24
Assuming the condition is false
25
Assuming the condition is false
26
Taking false branch
29
Assuming the condition is false
30
Assuming the condition is true
31
Taking true branch
63
Assuming the condition is false
64
Assuming the condition is false
65
Taking false branch
68
Assuming the condition is false
69
Assuming the condition is true
70
Taking true branch
866 break;
32
Execution continues on line 874
71
Execution continues on line 874
867 if (i
26.1
'i' is < 'filter_exp_len'
65.1
'i' is < 'filter_exp_len'
>= filter_exp_len) {
27
Taking false branch
66
Taking false branch
868 /* buffer isn't long enough; double its length.*/
869 filter_exp_len *= 2;
870 filter_exp = (char *)g_realloc(filter_exp, filter_exp_len + 1);
871 }
872 filter_exp[i++] = c;
873 }
874 filter_exp[i] = '\0';
875
876 if (c == EOF(-1)) {
33
Taking false branch
72
Taking false branch
877 break;
878 } else if (i
33.1
'i' is not equal to 0
72.1
'i' is not equal to 0
== 0) {
34
Taking false branch
73
Taking false branch
879 skip_end_of_line = true1;
880 continue;
881 }
882
883 /* retrieve background and foreground colors */
884 if (fscanf(f,"[%hu,%hu,%hu][%hu,%hu,%hu]",
35
Assuming this stream operation fails
36
Taking false branch
74
File position of the stream might be 'indeterminate' after a failed operation. Can cause undefined behavior
885 &bg_r, &bg_g, &bg_b, &fg_r, &fg_g, &fg_b) == 6) {
886
887 /* we got a complete color filter */
888
889 color_t bg_color, fg_color;
890 color_filter_t *colorf;
891 dfilter_t *temp_dfilter = NULL((void*)0);
892 df_error_t *df_err = NULL((void*)0);
893
894 if (!disabled && !dfilter_compile(filter_exp, &temp_dfilter, &df_err)dfilter_compile_full(filter_exp, &temp_dfilter, &df_err
, (1U << 1)|(1U << 2), __func__)
) {
895 report_warning("Disabling color filter: Could not compile \"%s\" in colorfilters file \"%s\".\n%s", name, path, df_err->msg);
896 df_error_free(&df_err);
897
898 /* skip_end_of_line = true; */
899 disabled = true1;
900 }
901
902 fg_color.red = fg_r;
903 fg_color.green = fg_g;
904 fg_color.blue = fg_b;
905
906 bg_color.red = bg_r;
907 bg_color.green = bg_g;
908 bg_color.blue = bg_b;
909
910 colorf = color_filter_new(name, filter_exp, &bg_color,
911 &fg_color, disabled);
912 if(user_data == &color_filter_list) {
913 GSList **cfl = (GSList **)user_data;
914
915 /* internal call */
916 colorf->c_colorfilter = temp_dfilter;
917 *cfl = g_slist_append(*cfl, colorf);
918 } else {
919 /* external call */
920 /* just editing, don't need the compiled filter */
921 dfilter_free(temp_dfilter);
922 add_cb(colorf, user_data);
923 }
924 } /* if sscanf */
925
926 skip_end_of_line = true1;
927 }
928
929 if (ferror(f))
930 ret = errno(*__errno_location ());
931
932 g_free(name);
933 g_free(filter_exp);
934 return ret;
935}
936
937/* read filters from the filter file */
938bool_Bool
939color_filters_read_globals(void *user_data, char** err_msg, color_filter_add_cb_func add_cb, const char* app_env_var_prefix)
940{
941 char *path;
942 FILE *f;
943 int ret;
944
945 /*
946 * Try to get the global filters.
947 *
948 * Get the path for the file that would have the global filters, and
949 * try to open it.
950 */
951 path = get_datafile_path(COLORFILTERS_FILE_NAME"colorfilters", app_env_var_prefix);
952 if ((f = ws_fopenfopen(path, "r")) == NULL((void*)0)) {
953 if (errno(*__errno_location ()) != ENOENT2) {
954 /* Error trying to open the file; give up. */
955 *err_msg = ws_strdup_printf("Could not open global filter file\n\"%s\": %s.", path,wmem_strdup_printf(((void*)0), "Could not open global filter file\n\"%s\": %s."
, path, g_strerror((*__errno_location ())))
956 g_strerror(errno))wmem_strdup_printf(((void*)0), "Could not open global filter file\n\"%s\": %s."
, path, g_strerror((*__errno_location ())))
;
957 g_free(path);
958 return false0;
959 }
960
961 /*
962 * There is no global filter file; treat that as equivalent to
963 * that file existing bug being empty, and say we succeeded.
964 */
965 g_free(path);
966 return true1;
967 }
968
969 ret = read_filters_file(path, f, user_data, add_cb);
970 if (ret != 0) {
971 *err_msg = ws_strdup_printf("Error reading global filter file\n\"%s\": %s.",wmem_strdup_printf(((void*)0), "Error reading global filter file\n\"%s\": %s."
, path, g_strerror((*__errno_location ())))
972 path, g_strerror(errno))wmem_strdup_printf(((void*)0), "Error reading global filter file\n\"%s\": %s."
, path, g_strerror((*__errno_location ())))
;
973 fclose(f);
974 g_free(path);
975 return false0;
976 }
977
978 fclose(f);
979 g_free(path);
980 return true1;
981}
982
983/* read filters from some other filter file (import) */
984bool_Bool
985color_filters_import(const char *path, void *user_data, char **err_msg, color_filter_add_cb_func add_cb)
986{
987 FILE *f;
988 int ret;
989
990 if ((f = ws_fopenfopen(path, "r")) == NULL((void*)0)) {
1
Taking false branch
991 *err_msg = ws_strdup_printf("Could not open filter file\n%s\nfor reading: %s.",wmem_strdup_printf(((void*)0), "Could not open filter file\n%s\nfor reading: %s."
, path, g_strerror((*__errno_location ())))
992 path, g_strerror(errno))wmem_strdup_printf(((void*)0), "Could not open filter file\n%s\nfor reading: %s."
, path, g_strerror((*__errno_location ())))
;
993 return false0;
994 }
995
996 ret = read_filters_file(path, f, user_data, add_cb);
2
Calling 'read_filters_file'
997 if (ret != 0) {
998 *err_msg = ws_strdup_printf("Error reading filter file\n\"%s\": %s.",wmem_strdup_printf(((void*)0), "Error reading filter file\n\"%s\": %s."
, path, g_strerror((*__errno_location ())))
999 path, g_strerror(errno))wmem_strdup_printf(((void*)0), "Error reading filter file\n\"%s\": %s."
, path, g_strerror((*__errno_location ())))
;
1000 fclose(f);
1001 return false0;
1002 }
1003
1004 fclose(f);
1005 return true1;
1006}
1007
1008struct write_filter_data
1009{
1010 FILE *f;
1011 bool_Bool only_selected;
1012};
1013
1014/* save a single filter */
1015static void
1016write_filter(void *filter_arg, void *data_arg)
1017{
1018 struct write_filter_data *data = (struct write_filter_data *)data_arg;
1019 color_filter_t *colorf = (color_filter_t *)filter_arg;
1020 FILE *f = data->f;
1021
1022 if ( (!data->only_selected) &&
1023 (strstr(colorf->filter_name,CONVERSATION_COLOR_PREFIX"___conversation_color_filter___")==NULL((void*)0)) ) {
1024 fprintf(f,"%s@%s@%s@[%u,%u,%u][%u,%u,%u]\n",
1025 colorf->disabled ? "!" : "",
1026 colorf->filter_name,
1027 colorf->filter_text,
1028 colorf->bg_color.red,
1029 colorf->bg_color.green,
1030 colorf->bg_color.blue,
1031 colorf->fg_color.red,
1032 colorf->fg_color.green,
1033 colorf->fg_color.blue);
1034 }
1035}
1036
1037/* save filters in a filter file */
1038static bool_Bool
1039write_filters_file(GSList *cfl, FILE *f, bool_Bool only_selected, const char* app_name)
1040{
1041 struct write_filter_data data;
1042
1043 data.f = f;
1044 data.only_selected = only_selected;
1045
1046 fprintf(f,"# This file was created by %s. Edit with care.\n", app_name);
1047 g_slist_foreach(cfl, write_filter, &data);
1048 return true1;
1049}
1050
1051/* save filters in users filter file */
1052bool_Bool
1053color_filters_write(GSList *cfl, const char* app_name, const char* app_env_var_prefix, char** err_msg)
1054{
1055 char *pf_dir_path;
1056 char *path;
1057 FILE *f;
1058
1059 /* Create the directory that holds personal configuration files,
1060 if necessary. */
1061 if (create_persconffile_dir(app_env_var_prefix, &pf_dir_path) == -1) {
1062 *err_msg = ws_strdup_printf("Can't create directory\n\"%s\"\nfor color files: %s.",wmem_strdup_printf(((void*)0), "Can't create directory\n\"%s\"\nfor color files: %s."
, pf_dir_path, g_strerror((*__errno_location ())))
1063 pf_dir_path, g_strerror(errno))wmem_strdup_printf(((void*)0), "Can't create directory\n\"%s\"\nfor color files: %s."
, pf_dir_path, g_strerror((*__errno_location ())))
;
1064 g_free(pf_dir_path);
1065 return false0;
1066 }
1067
1068 path = get_persconffile_path(COLORFILTERS_FILE_NAME"colorfilters", true1, app_env_var_prefix);
1069 if ((f = ws_fopenfopen(path, "w+")) == NULL((void*)0)) {
1070 *err_msg = ws_strdup_printf("Could not open\n%s\nfor writing: %s.",wmem_strdup_printf(((void*)0), "Could not open\n%s\nfor writing: %s."
, path, g_strerror((*__errno_location ())))
1071 path, g_strerror(errno))wmem_strdup_printf(((void*)0), "Could not open\n%s\nfor writing: %s."
, path, g_strerror((*__errno_location ())))
;
1072 g_free(path);
1073 return false0;
1074 }
1075 g_free(path);
1076 write_filters_file(cfl, f, false0, app_name);
1077 fclose(f);
1078 return true1;
1079}
1080
1081/* save filters in some other filter file (export) */
1082bool_Bool
1083color_filters_export(const char *path, GSList *cfl, bool_Bool only_marked, const char* app_name, char** err_msg)
1084{
1085 FILE *f;
1086
1087 if ((f = ws_fopenfopen(path, "w+")) == NULL((void*)0)) {
1088 *err_msg = ws_strdup_printf("Could not open\n%s\nfor writing: %s.",wmem_strdup_printf(((void*)0), "Could not open\n%s\nfor writing: %s."
, path, g_strerror((*__errno_location ())))
1089 path, g_strerror(errno))wmem_strdup_printf(((void*)0), "Could not open\n%s\nfor writing: %s."
, path, g_strerror((*__errno_location ())))
;
1090 return false0;
1091 }
1092 write_filters_file(cfl, f, only_marked, app_name);
1093 fclose(f);
1094 return true1;
1095}
1096
1097/*
1098 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1099 *
1100 * Local variables:
1101 * c-basic-offset: 4
1102 * tab-width: 8
1103 * indent-tabs-mode: nil
1104 * End:
1105 *
1106 * vi: set shiftwidth=4 tabstop=8 expandtab:
1107 * :indentSize=4:tabSize=8:noTabs=true:
1108 */