2 * Code for reading and writing the filters file.
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program 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
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
40 #include <epan/filesystem.h>
43 #include <wsutil/file_util.h>
46 * Old filter file name.
48 #define FILTER_FILE_NAME "filters"
51 * Capture filter file name.
53 #define CFILTER_FILE_NAME "cfilters"
56 * Display filter file name.
58 #define DFILTER_FILE_NAME "dfilters"
61 * List of capture filters - saved.
63 static GList *capture_filters = NULL;
66 * List of display filters - saved.
68 static GList *display_filters = NULL;
71 * List of capture filters - currently edited.
73 static GList *capture_edited_filters = NULL;
76 * List of display filters - currently edited.
78 static GList *display_edited_filters = NULL;
81 * Read in a list of filters.
83 * On success, "*pref_path_return" is set to NULL.
84 * On error, "*pref_path_return" is set to point to the pathname of
85 * the file we tried to read - it should be freed by our caller -
86 * and "*errno_return" is set to the error.
89 #define INIT_BUF_SIZE 128
92 add_filter_entry(GList *fl, const char *filt_name, const char *filt_expr)
96 filt = (filter_def *) g_malloc(sizeof(filter_def));
97 filt->name = g_strdup(filt_name);
98 filt->strval = g_strdup(filt_expr);
99 return g_list_append(fl, filt);
103 remove_filter_entry(GList *fl, GList *fl_entry)
107 filt = (filter_def *) fl_entry->data;
109 g_free(filt->strval);
111 return g_list_remove_link(fl, fl_entry);
115 read_filter_list(filter_list_type_t list_type, char **pref_path_return,
123 char *filt_name, *filt_expr;
124 int filt_name_len, filt_expr_len;
125 int filt_name_index, filt_expr_index;
128 *pref_path_return = NULL; /* assume no error */
133 ff_name = CFILTER_FILE_NAME;
134 flpp = &capture_filters;
138 ff_name = DFILTER_FILE_NAME;
139 flpp = &display_filters;
143 g_assert_not_reached();
147 /* try to open personal "cfilters"/"dfilters" file */
148 ff_path = get_persconffile_path(ff_name, TRUE, FALSE);
149 if ((ff = ws_fopen(ff_path, "r")) == NULL) {
151 * Did that fail because the file didn't exist?
153 if (errno != ENOENT) {
157 *pref_path_return = ff_path;
158 *errno_return = errno;
163 * Yes. See if there's an "old style" personal "filters" file; if so, read it.
164 * This means that a user will start out with their capture and
165 * display filter lists being identical; each list may contain
166 * filters that don't belong in that list. The user can edit
167 * the filter lists, and delete the ones that don't belong in
171 ff_path = get_persconffile_path(FILTER_FILE_NAME, FALSE, FALSE);
172 if ((ff = ws_fopen(ff_path, "r")) == NULL) {
174 * Did that fail because the file didn't exist?
176 if (errno != ENOENT) {
180 *pref_path_return = ff_path;
181 *errno_return = errno;
186 * Try to open the global "cfilters/dfilters" file */
188 ff_path = get_datafile_path(ff_name);
189 if ((ff = ws_fopen(ff_path, "r")) == NULL) {
192 * Well, that didn't work, either. Just give up.
193 * Return an error if the file existed but we couldn't open it.
195 if (errno != ENOENT) {
196 *pref_path_return = ff_path;
197 *errno_return = errno;
206 /* If we already have a list of filters, discard it. */
207 /* this should never happen - this function is called only once for each list! */
209 *flpp = remove_filter_entry(*flpp, g_list_first(*flpp));
212 /* Allocate the filter name buffer. */
213 filt_name_len = INIT_BUF_SIZE;
214 filt_name = (char *)g_malloc(filt_name_len + 1);
215 filt_expr_len = INIT_BUF_SIZE;
216 filt_expr = (char *)g_malloc(filt_expr_len + 1);
218 for (line = 1; ; line++) {
219 /* Lines in a filter file are of the form
223 where "name" is a name, in quotes - backslashes in the name
224 escape the next character, so quotes and backslashes can appear
225 in the name - and "expression" is a filter expression, not in
226 quotes, running to the end of the line. */
228 /* Skip over leading white space, if any. */
229 while ((c = getc(ff)) != EOF && isspace(c)) {
237 break; /* Nothing more to read */
239 /* "c" is the first non-white-space character.
240 If it's not a quote, it's an error. */
242 g_warning("'%s' line %d doesn't have a quoted filter name.", ff_path,
245 c = getc(ff); /* skip to the end of the line */
249 /* Get the name of the filter. */
253 if (c == EOF || c == '\n')
254 break; /* End of line - or end of file */
257 if (filt_name_index >= filt_name_len) {
258 /* Filter name buffer isn't long enough; double its length. */
260 filt_name = (char *)g_realloc(filt_name, filt_name_len + 1);
262 filt_name[filt_name_index] = '\0';
266 /* Next character is escaped */
268 if (c == EOF || c == '\n')
269 break; /* End of line - or end of file */
271 /* Add this character to the filter name string. */
272 if (filt_name_index >= filt_name_len) {
273 /* Filter name buffer isn't long enough; double its length. */
275 filt_name = (char *)g_realloc(filt_name, filt_name_len + 1);
277 filt_name[filt_name_index] = c;
283 /* EOF, not error; no newline seen before EOF */
284 g_warning("'%s' line %d doesn't have a newline.", ff_path,
287 break; /* nothing more to read */
291 /* No newline seen before end-of-line */
292 g_warning("'%s' line %d doesn't have a closing quote.", ff_path,
297 /* Skip over separating white space, if any. */
298 while ((c = getc(ff)) != EOF && isspace(c)) {
305 /* EOF, not error; no newline seen before EOF */
306 g_warning("'%s' line %d doesn't have a newline.", ff_path,
309 break; /* nothing more to read */
313 /* No filter expression */
314 g_warning("'%s' line %d doesn't have a filter expression.", ff_path,
319 /* "c" is the first non-white-space character; it's the first
320 character of the filter expression. */
323 /* Add this character to the filter expression string. */
324 if (filt_expr_index >= filt_expr_len) {
325 /* Filter expressioin buffer isn't long enough; double its length. */
327 filt_expr = (char *)g_realloc(filt_expr, filt_expr_len + 1);
329 filt_expr[filt_expr_index] = c;
332 /* Get the next character. */
334 if (c == EOF || c == '\n')
340 /* EOF, not error; no newline seen before EOF */
341 g_warning("'%s' line %d doesn't have a newline.", ff_path,
344 break; /* nothing more to read */
347 /* We saw the ending newline; terminate the filter expression string */
348 if (filt_expr_index >= filt_expr_len) {
349 /* Filter expressioin buffer isn't long enough; double its length. */
351 filt_expr = (char *)g_realloc(filt_expr, filt_expr_len + 1);
353 filt_expr[filt_expr_index] = '\0';
355 /* Add the new filter to the list of filters */
356 *flpp = add_filter_entry(*flpp, filt_name, filt_expr);
359 *pref_path_return = ff_path;
360 *errno_return = errno;
367 /* init the corresponding edited list */
370 copy_filter_list(CFILTER_EDITED_LIST, CFILTER_LIST);
373 copy_filter_list(DFILTER_EDITED_LIST, DFILTER_LIST);
376 g_assert_not_reached();
382 * Get a pointer to a list of filters.
385 get_filter_list(filter_list_type_t list_type)
392 flpp = &capture_filters;
396 flpp = &display_filters;
399 case CFILTER_EDITED_LIST:
400 flpp = &capture_edited_filters;
403 case DFILTER_EDITED_LIST:
404 flpp = &display_edited_filters;
408 g_assert_not_reached();
415 * Get a pointer to the first entry in a filter list.
418 get_filter_list_first(filter_list_type_t list_type)
422 flpp = get_filter_list(list_type);
423 return g_list_first(*flpp);
427 * Add a new filter to the end of a list.
428 * Returns a pointer to the newly-added entry.
431 add_to_filter_list(filter_list_type_t list_type, const char *name,
432 const char *expression)
436 flpp = get_filter_list(list_type);
437 *flpp = add_filter_entry(*flpp, name, expression);
439 return g_list_last(*flpp);
443 * Remove a filter from a list.
446 remove_from_filter_list(filter_list_type_t list_type, GList *fl_entry)
450 flpp = get_filter_list(list_type);
451 *flpp = remove_filter_entry(*flpp, fl_entry);
455 * Write out a list of filters.
457 * On success, "*pref_path_return" is set to NULL.
458 * On error, "*pref_path_return" is set to point to the pathname of
459 * the file we tried to read - it should be freed by our caller -
460 * and "*errno_return" is set to the error.
463 save_filter_list(filter_list_type_t list_type, char **pref_path_return,
466 const gchar *ff_name;
467 gchar *ff_path, *ff_path_new;
474 *pref_path_return = NULL; /* assume no error */
479 ff_name = CFILTER_FILE_NAME;
480 fl = capture_filters;
484 ff_name = DFILTER_FILE_NAME;
485 fl = display_filters;
489 g_assert_not_reached();
493 ff_path = get_persconffile_path(ff_name, TRUE, TRUE);
495 /* Write to "XXX.new", and rename if that succeeds.
496 That means we don't trash the file if we fail to write it out
498 ff_path_new = g_strdup_printf("%s.new", ff_path);
500 if ((ff = ws_fopen(ff_path_new, "w")) == NULL) {
501 *pref_path_return = ff_path;
502 *errno_return = errno;
506 flpp = g_list_first(fl);
508 filt = (filter_def *) flpp->data;
510 /* Write out the filter name as a quoted string; escape any quotes
513 for (p = (guchar *)filt->name; (c = *p) != '\0'; p++) {
514 if (c == '"' || c == '\\')
520 /* Separate the filter name and value with a space. */
523 /* Write out the filter expression and a newline. */
524 fprintf(ff, "%s\n", filt->strval);
526 *pref_path_return = ff_path;
527 *errno_return = errno;
529 ws_unlink(ff_path_new);
535 if (fclose(ff) == EOF) {
536 *pref_path_return = ff_path;
537 *errno_return = errno;
538 ws_unlink(ff_path_new);
544 /* ANSI C doesn't say whether "rename()" removes the target if it
545 exists; the Win32 call to rename files doesn't do so, which I
546 infer is the reason why the MSVC++ "rename()" doesn't do so.
547 We must therefore remove the target file first, on Windows.
549 XXX - ws_rename() should be ws_stdio_rename() on Windows,
550 and ws_stdio_rename() uses MoveFileEx() with MOVEFILE_REPLACE_EXISTING,
551 so it should remove the target if it exists, so this stuff
552 shouldn't be necessary. Perhaps it dates back to when we were
553 calling rename(), with that being a wrapper around Microsoft's
554 _rename(), which didn't remove the target. */
555 if (ws_remove(ff_path) < 0 && errno != ENOENT) {
556 /* It failed for some reason other than "it's not there"; if
557 it's not there, we don't need to remove it, so we just
559 *pref_path_return = ff_path;
560 *errno_return = errno;
561 ws_unlink(ff_path_new);
567 if (ws_rename(ff_path_new, ff_path) < 0) {
568 *pref_path_return = ff_path;
569 *errno_return = errno;
570 ws_unlink(ff_path_new);
579 * Copy a filter list into another.
581 void copy_filter_list(filter_list_type_t dest_type, filter_list_type_t src_type)
588 g_assert(dest_type != src_type);
590 flpp_dest = get_filter_list(dest_type);
591 flpp_src = get_filter_list(src_type);
592 /* throw away the "old" destination list - a NULL list is ok here */
594 *flpp_dest = remove_filter_entry(*flpp_dest, g_list_first(*flpp_dest));
596 g_assert(g_list_length(*flpp_dest) == 0);
598 /* copy the list entries */
599 for(flp_src = g_list_first(*flpp_src); flp_src; flp_src = g_list_next(flp_src)) {
600 filt = (filter_def *)(flp_src->data);
602 *flpp_dest = add_filter_entry(*flpp_dest, filt->name, filt->strval);