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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
38 #include <epan/filesystem.h>
41 #include <wsutil/file_util.h>
44 * Old filter file name.
46 #define FILTER_FILE_NAME "filters"
49 * Capture filter file name.
51 #define CFILTER_FILE_NAME "cfilters"
54 * Display filter file name.
56 #define DFILTER_FILE_NAME "dfilters"
59 * List of capture filters - saved.
61 static GList
*capture_filters
= NULL
;
64 * List of display filters - saved.
66 static GList
*display_filters
= NULL
;
69 * List of capture filters - currently edited.
71 static GList
*capture_edited_filters
= NULL
;
74 * List of display filters - currently edited.
76 static GList
*display_edited_filters
= NULL
;
79 * Read in a list of filters.
81 * On success, "*pref_path_return" is set to NULL.
82 * On error, "*pref_path_return" is set to point to the pathname of
83 * the file we tried to read - it should be freed by our caller -
84 * and "*errno_return" is set to the error.
87 #define INIT_BUF_SIZE 128
90 add_filter_entry(GList
*fl
, const char *filt_name
, const char *filt_expr
)
94 filt
= (filter_def
*) g_malloc(sizeof(filter_def
));
95 filt
->name
= g_strdup(filt_name
);
96 filt
->strval
= g_strdup(filt_expr
);
97 return g_list_append(fl
, filt
);
101 remove_filter_entry(GList
*fl
, GList
*fl_entry
)
105 filt
= (filter_def
*) fl_entry
->data
;
107 g_free(filt
->strval
);
109 return g_list_remove_link(fl
, fl_entry
);
113 read_filter_list(filter_list_type_t list_type
, char **pref_path_return
,
121 char *filt_name
, *filt_expr
;
122 int filt_name_len
, filt_expr_len
;
123 int filt_name_index
, filt_expr_index
;
126 *pref_path_return
= NULL
; /* assume no error */
131 ff_name
= CFILTER_FILE_NAME
;
132 flpp
= &capture_filters
;
136 ff_name
= DFILTER_FILE_NAME
;
137 flpp
= &display_filters
;
141 g_assert_not_reached();
145 /* try to open personal "cfilters"/"dfilters" file */
146 ff_path
= get_persconffile_path(ff_name
, TRUE
);
147 if ((ff
= ws_fopen(ff_path
, "r")) == NULL
) {
149 * Did that fail because the file didn't exist?
151 if (errno
!= ENOENT
) {
155 *pref_path_return
= ff_path
;
156 *errno_return
= errno
;
161 * Yes. See if there's an "old style" personal "filters" file; if so, read it.
162 * This means that a user will start out with their capture and
163 * display filter lists being identical; each list may contain
164 * filters that don't belong in that list. The user can edit
165 * the filter lists, and delete the ones that don't belong in
169 ff_path
= get_persconffile_path(FILTER_FILE_NAME
, FALSE
);
170 if ((ff
= ws_fopen(ff_path
, "r")) == NULL
) {
172 * Did that fail because the file didn't exist?
174 if (errno
!= ENOENT
) {
178 *pref_path_return
= ff_path
;
179 *errno_return
= errno
;
184 * Try to open the global "cfilters/dfilters" file */
186 ff_path
= get_datafile_path(ff_name
);
187 if ((ff
= ws_fopen(ff_path
, "r")) == NULL
) {
190 * Well, that didn't work, either. Just give up.
191 * Return an error if the file existed but we couldn't open it.
193 if (errno
!= ENOENT
) {
194 *pref_path_return
= ff_path
;
195 *errno_return
= errno
;
204 /* If we already have a list of filters, discard it. */
205 /* this should never happen - this function is called only once for each list! */
207 *flpp
= remove_filter_entry(*flpp
, g_list_first(*flpp
));
210 /* Allocate the filter name buffer. */
211 filt_name_len
= INIT_BUF_SIZE
;
212 filt_name
= (char *)g_malloc(filt_name_len
+ 1);
213 filt_expr_len
= INIT_BUF_SIZE
;
214 filt_expr
= (char *)g_malloc(filt_expr_len
+ 1);
216 for (line
= 1; ; line
++) {
217 /* Lines in a filter file are of the form
221 where "name" is a name, in quotes - backslashes in the name
222 escape the next character, so quotes and backslashes can appear
223 in the name - and "expression" is a filter expression, not in
224 quotes, running to the end of the line. */
226 /* Skip over leading white space, if any. */
227 while ((c
= getc(ff
)) != EOF
&& isspace(c
)) {
235 break; /* Nothing more to read */
237 /* "c" is the first non-white-space character.
238 If it's not a quote, it's an error. */
240 g_warning("'%s' line %d doesn't have a quoted filter name.", ff_path
,
243 c
= getc(ff
); /* skip to the end of the line */
247 /* Get the name of the filter. */
251 if (c
== EOF
|| c
== '\n')
252 break; /* End of line - or end of file */
255 if (filt_name_index
>= filt_name_len
) {
256 /* Filter name buffer isn't long enough; double its length. */
258 filt_name
= (char *)g_realloc(filt_name
, filt_name_len
+ 1);
260 filt_name
[filt_name_index
] = '\0';
264 /* Next character is escaped */
266 if (c
== EOF
|| c
== '\n')
267 break; /* End of line - or end of file */
269 /* Add this character to the filter name string. */
270 if (filt_name_index
>= filt_name_len
) {
271 /* Filter name buffer isn't long enough; double its length. */
273 filt_name
= (char *)g_realloc(filt_name
, filt_name_len
+ 1);
275 filt_name
[filt_name_index
] = c
;
281 /* EOF, not error; no newline seen before EOF */
282 g_warning("'%s' line %d doesn't have a newline.", ff_path
,
285 break; /* nothing more to read */
289 /* No newline seen before end-of-line */
290 g_warning("'%s' line %d doesn't have a closing quote.", ff_path
,
295 /* Skip over separating white space, if any. */
296 while ((c
= getc(ff
)) != EOF
&& isspace(c
)) {
303 /* EOF, not error; no newline seen before EOF */
304 g_warning("'%s' line %d doesn't have a newline.", ff_path
,
307 break; /* nothing more to read */
311 /* No filter expression */
312 g_warning("'%s' line %d doesn't have a filter expression.", ff_path
,
317 /* "c" is the first non-white-space character; it's the first
318 character of the filter expression. */
321 /* Add this character to the filter expression string. */
322 if (filt_expr_index
>= filt_expr_len
) {
323 /* Filter expressioin buffer isn't long enough; double its length. */
325 filt_expr
= (char *)g_realloc(filt_expr
, filt_expr_len
+ 1);
327 filt_expr
[filt_expr_index
] = c
;
330 /* Get the next character. */
332 if (c
== EOF
|| c
== '\n')
338 /* EOF, not error; no newline seen before EOF */
339 g_warning("'%s' line %d doesn't have a newline.", ff_path
,
342 break; /* nothing more to read */
345 /* We saw the ending newline; terminate the filter expression string */
346 if (filt_expr_index
>= filt_expr_len
) {
347 /* Filter expressioin buffer isn't long enough; double its length. */
349 filt_expr
= (char *)g_realloc(filt_expr
, filt_expr_len
+ 1);
351 filt_expr
[filt_expr_index
] = '\0';
353 /* Add the new filter to the list of filters */
354 *flpp
= add_filter_entry(*flpp
, filt_name
, filt_expr
);
357 *pref_path_return
= ff_path
;
358 *errno_return
= errno
;
365 /* init the corresponding edited list */
368 copy_filter_list(CFILTER_EDITED_LIST
, CFILTER_LIST
);
371 copy_filter_list(DFILTER_EDITED_LIST
, DFILTER_LIST
);
374 g_assert_not_reached();
380 * Get a pointer to a list of filters.
383 get_filter_list(filter_list_type_t list_type
)
390 flpp
= &capture_filters
;
394 flpp
= &display_filters
;
397 case CFILTER_EDITED_LIST
:
398 flpp
= &capture_edited_filters
;
401 case DFILTER_EDITED_LIST
:
402 flpp
= &display_edited_filters
;
406 g_assert_not_reached();
413 * Get a pointer to the first entry in a filter list.
416 get_filter_list_first(filter_list_type_t list_type
)
420 flpp
= get_filter_list(list_type
);
421 return g_list_first(*flpp
);
425 * Add a new filter to the end of a list.
426 * Returns a pointer to the newly-added entry.
429 add_to_filter_list(filter_list_type_t list_type
, const char *name
,
430 const char *expression
)
434 flpp
= get_filter_list(list_type
);
435 *flpp
= add_filter_entry(*flpp
, name
, expression
);
437 return g_list_last(*flpp
);
441 * Remove a filter from a list.
444 remove_from_filter_list(filter_list_type_t list_type
, GList
*fl_entry
)
448 flpp
= get_filter_list(list_type
);
449 *flpp
= remove_filter_entry(*flpp
, fl_entry
);
453 * Write out a list of filters.
455 * On success, "*pref_path_return" is set to NULL.
456 * On error, "*pref_path_return" is set to point to the pathname of
457 * the file we tried to read - it should be freed by our caller -
458 * and "*errno_return" is set to the error.
461 save_filter_list(filter_list_type_t list_type
, char **pref_path_return
,
464 const gchar
*ff_name
;
465 gchar
*ff_path
, *ff_path_new
;
472 *pref_path_return
= NULL
; /* assume no error */
477 ff_name
= CFILTER_FILE_NAME
;
478 fl
= capture_filters
;
482 ff_name
= DFILTER_FILE_NAME
;
483 fl
= display_filters
;
487 g_assert_not_reached();
491 ff_path
= get_persconffile_path(ff_name
, TRUE
);
493 /* Write to "XXX.new", and rename if that succeeds.
494 That means we don't trash the file if we fail to write it out
496 ff_path_new
= g_strdup_printf("%s.new", ff_path
);
498 if ((ff
= ws_fopen(ff_path_new
, "w")) == NULL
) {
499 *pref_path_return
= ff_path
;
500 *errno_return
= errno
;
504 flpp
= g_list_first(fl
);
506 filt
= (filter_def
*) flpp
->data
;
508 /* Write out the filter name as a quoted string; escape any quotes
511 for (p
= (guchar
*)filt
->name
; (c
= *p
) != '\0'; p
++) {
512 if (c
== '"' || c
== '\\')
518 /* Separate the filter name and value with a space. */
521 /* Write out the filter expression and a newline. */
522 fprintf(ff
, "%s\n", filt
->strval
);
524 *pref_path_return
= ff_path
;
525 *errno_return
= errno
;
527 ws_unlink(ff_path_new
);
533 if (fclose(ff
) == EOF
) {
534 *pref_path_return
= ff_path
;
535 *errno_return
= errno
;
536 ws_unlink(ff_path_new
);
542 /* ANSI C doesn't say whether "rename()" removes the target if it
543 exists; the Win32 call to rename files doesn't do so, which I
544 infer is the reason why the MSVC++ "rename()" doesn't do so.
545 We must therefore remove the target file first, on Windows.
547 XXX - ws_rename() should be ws_stdio_rename() on Windows,
548 and ws_stdio_rename() uses MoveFileEx() with MOVEFILE_REPLACE_EXISTING,
549 so it should remove the target if it exists, so this stuff
550 shouldn't be necessary. Perhaps it dates back to when we were
551 calling rename(), with that being a wrapper around Microsoft's
552 _rename(), which didn't remove the target. */
553 if (ws_remove(ff_path
) < 0 && errno
!= ENOENT
) {
554 /* It failed for some reason other than "it's not there"; if
555 it's not there, we don't need to remove it, so we just
557 *pref_path_return
= ff_path
;
558 *errno_return
= errno
;
559 ws_unlink(ff_path_new
);
565 if (ws_rename(ff_path_new
, ff_path
) < 0) {
566 *pref_path_return
= ff_path
;
567 *errno_return
= errno
;
568 ws_unlink(ff_path_new
);
577 * Copy a filter list into another.
579 void copy_filter_list(filter_list_type_t dest_type
, filter_list_type_t src_type
)
586 g_assert(dest_type
!= src_type
);
588 flpp_dest
= get_filter_list(dest_type
);
589 flpp_src
= get_filter_list(src_type
);
590 /* throw away the "old" destination list - a NULL list is ok here */
592 *flpp_dest
= remove_filter_entry(*flpp_dest
, g_list_first(*flpp_dest
));
594 g_assert(g_list_length(*flpp_dest
) == 0);
596 /* copy the list entries */
597 for(flp_src
= g_list_first(*flpp_src
); flp_src
; flp_src
= g_list_next(flp_src
)) {
598 filt
= (filter_def
*)(flp_src
->data
);
600 *flpp_dest
= add_filter_entry(*flpp_dest
, filt
->name
, filt
->strval
);