From ace4af44fc2aecc93c7663f6f27b8deaae5c2a72 Mon Sep 17 00:00:00 2001 From: Guy Harris Date: Sun, 15 Feb 2009 21:47:57 +0000 Subject: [PATCH] Add a routine to report write errors to the list of failure-reporting routines handled by epan/report_err.c. Move copy_binary_file() in file.c to epan/filesystem.c, and rename it to copy_file_binary_mode() (to clarify that it *can* copy text files; arguably, *all* files are "binary" unless you're on, say, an IBM 1401 :-)). Have it use the report_err.c routines, so it works in console-mode programs. Clean up some comments while we're at it. svn path=/trunk/; revision=27456 --- capinfos.c | 2 +- dftest.c | 19 +++++++++--- editcap.c | 2 +- epan/epan.c | 6 ++-- epan/epan.h | 6 +++- epan/filesystem.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++- epan/filesystem.h | 14 ++++++++- epan/report_err.c | 28 +++++++++++++++--- epan/report_err.h | 46 ++++++++++++++++++++--------- file.c | 71 +-------------------------------------------- gtk/main.c | 3 +- rawshark.c | 14 ++++++++- tshark.c | 20 ++++++++++--- 13 files changed, 200 insertions(+), 105 deletions(-) diff --git a/capinfos.c b/capinfos.c index 5941fffa87..1eb6b6a7e3 100644 --- a/capinfos.c +++ b/capinfos.c @@ -306,7 +306,7 @@ main(int argc, char *argv[]) g_warning("capinfos: init_progfile_dir(): %s", init_progfile_dir_error); g_free(init_progfile_dir_error); } else { - init_report_err(failure_message,NULL,NULL); + init_report_err(failure_message,NULL,NULL,NULL); init_plugins(); } #endif diff --git a/dftest.c b/dftest.c index 7317f3b561..84b198cbde 100644 --- a/dftest.c +++ b/dftest.c @@ -1,4 +1,5 @@ -/* dftest.c.c +/* dftest.c + * Shows display filter byte-code, for debugging dfilter routines. * * $Id$ * @@ -6,8 +7,6 @@ * By Gerald Combs * Copyright 1998 Gerald Combs * - * Shows display filter byte-code, for debugging dfilter routines. - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -55,6 +54,7 @@ static void failure_message(const char *msg_format, va_list ap); static void open_failure_message(const char *filename, int err, gboolean for_writing); static void read_failure_message(const char *filename, int err); +static void write_failure_message(const char *filename, int err); int main(int argc, char **argv) @@ -89,7 +89,8 @@ main(int argc, char **argv) in case any dissectors register preferences. */ epan_init(register_all_protocols, register_all_protocol_handoffs, NULL, NULL, - failure_message, open_failure_message, read_failure_message); + failure_message, open_failure_message, read_failure_message, + write_failure_message); /* now register the preferences for any non-dissector modules. we must do that before we read the preferences as well. */ @@ -191,3 +192,13 @@ read_failure_message(const char *filename, int err) fprintf(stderr, "dftest: An error occurred while reading from the file \"%s\": %s.\n", filename, strerror(err)); } + +/* + * Write errors are reported with an console message in "dftest". + */ +static void +write_failure_message(const char *filename, int err) +{ + fprintf(stderr, "dftest: An error occurred while writing to the file \"%s\": %s.\n", + filename, strerror(err)); +} diff --git a/editcap.c b/editcap.c index b91902cc0b..8c541e1b9c 100644 --- a/editcap.c +++ b/editcap.c @@ -428,7 +428,7 @@ main(int argc, char *argv[]) g_warning("capinfos: init_progfile_dir(): %s", init_progfile_dir_error); g_free(init_progfile_dir_error); } else { - init_report_err(failure_message,NULL,NULL); + init_report_err(failure_message,NULL,NULL,NULL); init_plugins(); } #endif diff --git a/epan/epan.c b/epan/epan.c index c835defd85..7e496c008f 100644 --- a/epan/epan.c +++ b/epan/epan.c @@ -75,9 +75,11 @@ epan_init(void (*register_all_protocols_func)(register_cb cb, gpointer client_da gpointer client_data, void (*report_failure)(const char *, va_list), void (*report_open_failure)(const char *, int, gboolean), - void (*report_read_failure)(const char *, int)) + void (*report_read_failure)(const char *, int), + void (*report_write_failure)(const char *, int)) { - init_report_err(report_failure, report_open_failure, report_read_failure); + init_report_err(report_failure, report_open_failure, + report_read_failure, report_write_failure); /* initialize memory allocation subsystem */ ep_init_chunk(); diff --git a/epan/epan.h b/epan/epan.h index c8b72d080b..01a8a84957 100644 --- a/epan/epan.h +++ b/epan/epan.h @@ -40,11 +40,15 @@ void epan_init(void (*register_all_protocols_func)(register_cb cb, gpointer clie void *client_data, void (*report_failure)(const char *, va_list), void (*report_open_failure)(const char *, int, gboolean), - void (*report_read_failure)(const char *, int)); + void (*report_read_failure)(const char *, int), + void (*report_write_failure)(const char *, int)); + /* cleanup the whole epan module, this is used to be called only once in a program */ void epan_cleanup(void); + /* Initialize the table of conversations. */ void epan_conversation_init(void); + /* Initialize the table of circuits. */ /* XXX - what is a circuit and should this better be combined with epan_conversation_init? */ void epan_circuit_init(void); diff --git a/epan/filesystem.c b/epan/filesystem.c index 6632eb1c82..cf1a347720 100644 --- a/epan/filesystem.c +++ b/epan/filesystem.c @@ -42,6 +42,10 @@ #include #endif +#ifdef HAVE_FCNTL_H +#include +#endif + #ifdef HAVE_SYS_STAT_H #include #endif @@ -56,9 +60,12 @@ #endif #include "filesystem.h" +#include "report_err.h" #include #include +#include /* for WTAP_ERR_SHORT_WRITE */ + #define PROFILES_DIR "profiles" #define U3_MY_CAPTURES "\\My Captures" @@ -1552,6 +1559,72 @@ files_identical(const char *fname1, const char *fname2) #endif } +/* + * Copy a file in binary mode, for those operating systems that care about + * such things. This should be OK for all files, even text files, as + * we'll copy the raw bytes, and we don't look at the bytes as we copy + * them. + * + * Returns TRUE on success, FALSE on failure. If a failure, it also + * displays a simple dialog window with the error message. + */ +gboolean +copy_file_binary_mode(const char *from_filename, const char *to_filename) +{ + int from_fd, to_fd, nread, nwritten, err; + guint8 pd[65536]; + + /* Copy the raw bytes of the file. */ + from_fd = ws_open(from_filename, O_RDONLY | O_BINARY, 0000 /* no creation so don't matter */); + if (from_fd < 0) { + report_open_failure(from_filename, errno, FALSE); + goto done; + } + + /* Use open() instead of creat() so that we can pass the O_BINARY + flag, which is relevant on Win32; it appears that "creat()" + may open the file in text mode, not binary mode, but we want + to copy the raw bytes of the file, so we need the output file + to be open in binary mode. */ + to_fd = ws_open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); + if (to_fd < 0) { + report_open_failure(to_filename, errno, TRUE); + ws_close(from_fd); + goto done; + } + + while ((nread = ws_read(from_fd, pd, sizeof pd)) > 0) { + nwritten = ws_write(to_fd, pd, nread); + if (nwritten < nread) { + if (nwritten < 0) + err = errno; + else + err = WTAP_ERR_SHORT_WRITE; + report_write_failure(to_filename, err); + ws_close(from_fd); + ws_close(to_fd); + goto done; + } + } + if (nread < 0) { + err = errno; + report_read_failure(from_filename, err); + ws_close(from_fd); + ws_close(to_fd); + goto done; + } + ws_close(from_fd); + if (ws_close(to_fd) < 0) { + report_write_failure(to_filename, errno); + goto done; + } + + return TRUE; + +done: + return FALSE; +} + /* * Editor modelines * @@ -1564,4 +1637,3 @@ files_identical(const char *fname1, const char *fname2) * ex: set shiftwidth=4 tabstop=4 noexpandtab * :indentSize=4:tabSize=4:noTabs=false: */ - diff --git a/epan/filesystem.h b/epan/filesystem.h index b8dba0fcd5..a97f8d7880 100644 --- a/epan/filesystem.h +++ b/epan/filesystem.h @@ -234,10 +234,22 @@ extern gboolean deletefile (const char *path); extern gboolean file_exists(const char *fname); /* - * Check, if two filenames are identical (with absolute and relative paths). + * Check if two filenames are identical (with absolute and relative paths). */ extern gboolean files_identical(const char *fname1, const char *fname2); +/* + * Copy a file in binary mode, for those operating systems that care about + * such things. This should be OK for all files, even text files, as + * we'll copy the raw bytes, and we don't look at the bytes as we copy + * them. + * + * Returns TRUE on success, FALSE on failure. If a failure, it also + * displays a simple dialog window with the error message. + */ +extern gboolean copy_file_binary_mode(const char *from_filename, + const char *to_filename); + #ifdef _WIN32 /* * utf8 version of getenv, needed to get win32 filename paths diff --git a/epan/report_err.c b/epan/report_err.c index 68924c64b8..ca03bb210c 100644 --- a/epan/report_err.c +++ b/epan/report_err.c @@ -1,6 +1,13 @@ -/* report_err.h -* Declarations of routines for dissectors to use to report errors to -* the user (e.g., problems with preference settings) +/* report_err.c +* Routines for code that can run in GUI and command-line environments to +* use to report errors to the user (e.g., I/O errors, or problems with +* preference settings). +* +* The application using libwireshark will register error-reporting +* routines, and the routines defined here will call the registered +* routines. That way, these routines can be called by code that +* doesn't itself know whether to pop up a dialog or print something +* to the standard error. * * $Id$ * @@ -33,13 +40,17 @@ static void (*report_failure_func)(const char *, va_list); static void (*report_open_failure_func)(const char *, int, gboolean); static void (*report_read_failure_func)(const char *, int); +static void (*report_write_failure_func)(const char *, int); void init_report_err(void (*report_failure)(const char *, va_list), void (*report_open_failure)(const char *, int, gboolean), - void (*report_read_failure)(const char *, int)) { + void (*report_read_failure)(const char *, int), + void (*report_write_failure)(const char *, int)) +{ report_failure_func = report_failure; report_open_failure_func = report_open_failure; report_read_failure_func = report_read_failure; + report_write_failure_func = report_write_failure; } /* @@ -78,3 +89,12 @@ report_read_failure(const char *filename, int err) (*report_read_failure_func)(filename, err); } +/* + * Report an error when trying to write a file. + * "err" is assumed to be a UNIX-style errno. + */ +void +report_write_failure(const char *filename, int err) +{ + (*report_write_failure_func)(filename, err); +} diff --git a/epan/report_err.h b/epan/report_err.h index 159cd96cee..9717221424 100644 --- a/epan/report_err.h +++ b/epan/report_err.h @@ -1,6 +1,13 @@ /* report_err.h - * Declarations of routines for dissectors to use to report errors to - * the user (e.g., problems with preference settings) + * Declarations of routines for code that can run in GUI and command-line + * environments to use to report errors to the user (e.g., I/O errors, or + * problems with preference settings). + * + * The application using libwireshark will register error-reporting + * routines, and the routines declared here will call the registered + * routines. That way, these routines can be called by code that + * doesn't itself know whether to pop up a dialog or print something + * to the standard error. * * $Id$ * @@ -36,24 +43,35 @@ extern "C" { extern void init_report_err( void (*report_failure)(const char *, va_list), void (*report_open_failure)(const char *, int, gboolean), - void (*report_read_failure)(const char *, int)); - -/* - * Report an error when trying to open a file. - */ -extern void report_open_failure(const char *filename, int err, - gboolean for_writing); - -/* - * Report an error when trying to read a file. - */ -extern void report_read_failure(const char *filename, int err); + void (*report_read_failure)(const char *, int), + void (*report_write_failure)(const char *, int)); /* * Report a general error. */ extern void report_failure(const char *msg_format, ...); +/* + * Report an error when trying to open a file. + * "err" is assumed to be an error code from Wiretap; positive values are + * UNIX-style errnos, so this can be used for open failures not from + * Wiretap as long as the failure code is just an errno. + */ +extern void report_open_failure(const char *filename, int err, + gboolean for_writing); + +/* + * Report an error when trying to read a file. + * "err" is assumed to be a UNIX-style errno. + */ +extern void report_read_failure(const char *filename, int err); + +/* + * Report an error when trying to write a file. + * "err" is assumed to be a UNIX-style errno. + */ +extern void report_write_failure(const char *filename, int err); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/file.c b/file.c index ca4e22911b..28fd5a9b99 100644 --- a/file.c +++ b/file.c @@ -43,10 +43,6 @@ #include #endif -#ifdef NEED_STRERROR_H -#include "strerror.h" -#endif - #include #include @@ -117,7 +113,6 @@ static void cf_open_failure_alert_box(const char *filename, int err, static const char *file_rename_error_message(int err); static void cf_write_failure_alert_box(const char *filename, int err); static void cf_close_failure_alert_box(const char *filename, int err); -static gboolean copy_binary_file(const char *from_filename, const char *to_filename); /* Update the progress bar this many times when reading a file. */ #define N_PROGBAR_UPDATES 100 @@ -3575,7 +3570,7 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f if (do_copy) { /* Copy the file, if we haven't moved it. */ - if (!copy_binary_file(from_filename, fname)) + if (!copy_file_binary_mode(from_filename, fname)) goto fail; } } else { @@ -3957,67 +3952,3 @@ cf_reload(capture_file *cf) { we should free up our copy. */ g_free(filename); } - -/* Copies a file in binary mode, for those operating systems that care about - * such things. - * Returns TRUE on success, FALSE on failure. If a failure, it also - * displays a simple dialog window with the error message. - */ -static gboolean -copy_binary_file(const char *from_filename, const char *to_filename) -{ - int from_fd, to_fd, nread, nwritten, err; - guint8 pd[65536]; - - /* Copy the raw bytes of the file. */ - from_fd = ws_open(from_filename, O_RDONLY | O_BINARY, 0000 /* no creation so don't matter */); - if (from_fd < 0) { - open_failure_alert_box(from_filename, errno, FALSE); - goto done; - } - - /* Use open() instead of creat() so that we can pass the O_BINARY - flag, which is relevant on Win32; it appears that "creat()" - may open the file in text mode, not binary mode, but we want - to copy the raw bytes of the file, so we need the output file - to be open in binary mode. */ - to_fd = ws_open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); - if (to_fd < 0) { - open_failure_alert_box(to_filename, errno, TRUE); - ws_close(from_fd); - goto done; - } - - while ((nread = ws_read(from_fd, pd, sizeof pd)) > 0) { - nwritten = ws_write(to_fd, pd, nread); - if (nwritten < nread) { - if (nwritten < 0) - err = errno; - else - err = WTAP_ERR_SHORT_WRITE; - write_failure_alert_box(to_filename, err); - ws_close(from_fd); - ws_close(to_fd); - goto done; - } - } - if (nread < 0) { - err = errno; - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, - "An error occurred while reading from the file \"%s\": %s.", - from_filename, strerror(err)); - ws_close(from_fd); - ws_close(to_fd); - goto done; - } - ws_close(from_fd); - if (ws_close(to_fd) < 0) { - write_failure_alert_box(to_filename, errno); - goto done; - } - - return TRUE; - -done: - return FALSE; -} diff --git a/gtk/main.c b/gtk/main.c index ed50229ae2..38d8eed4f5 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -2016,7 +2016,8 @@ main(int argc, char *argv[]) case any dissectors register preferences. */ epan_init(register_all_protocols,register_all_protocol_handoffs, splash_update, (gpointer) splash_win, - failure_alert_box,open_failure_alert_box,read_failure_alert_box); + failure_alert_box,open_failure_alert_box,read_failure_alert_box, + write_failure_alert_box); splash_update(RA_LISTENERS, NULL, (gpointer)splash_win); diff --git a/rawshark.c b/rawshark.c index dd5cc11036..9dc10bcb7b 100644 --- a/rawshark.c +++ b/rawshark.c @@ -154,6 +154,7 @@ static void open_failure_message(const char *filename, int err, gboolean for_writing); static void failure_message(const char *msg_format, va_list ap); static void read_failure_message(const char *filename, int err); +static void write_failure_message(const char *filename, int err); static void protocolinfo_init(char *field); static gboolean parse_field_string_format(char *format); @@ -492,7 +493,8 @@ main(int argc, char *argv[]) dissectors, and we must do it before we read the preferences, in case any dissectors register preferences. */ epan_init(register_all_protocols, register_all_protocol_handoffs, NULL, NULL, - failure_message, open_failure_message, read_failure_message); + failure_message, open_failure_message, read_failure_message, + write_failure_message); /* Now register the preferences for any non-dissector modules. We must do that before we read the preferences as well. */ @@ -1625,6 +1627,16 @@ read_failure_message(const char *filename, int err) filename, strerror(err)); } +/* + * Write errors are reported with an console message in Rawshark. + */ +static void +write_failure_message(const char *filename, int err) +{ + cmdarg_err("An error occurred while writing to the file \"%s\": %s.", + filename, strerror(err)); +} + /* * Report an error in command-line arguments. */ diff --git a/tshark.c b/tshark.c index 3c1cedaa1b..fbbec66536 100644 --- a/tshark.c +++ b/tshark.c @@ -1,4 +1,7 @@ /* tshark.c + * + * Text-mode variant of Wireshark, along the lines of tcpdump and snoop, + * by Gilbert Ramirez and Guy Harris . * * $Id$ * @@ -6,9 +9,6 @@ * By Gerald Combs * Copyright 1998 Gerald Combs * - * Text-mode variant, by Gilbert Ramirez - * and Guy Harris . - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -179,6 +179,7 @@ static void open_failure_message(const char *filename, int err, gboolean for_writing); static void failure_message(const char *msg_format, va_list ap); static void read_failure_message(const char *filename, int err); +static void write_failure_message(const char *filename, int err); capture_file cfile; @@ -834,7 +835,8 @@ main(int argc, char *argv[]) dissectors, and we must do it before we read the preferences, in case any dissectors register preferences. */ epan_init(register_all_protocols, register_all_protocol_handoffs, NULL, NULL, - failure_message, open_failure_message, read_failure_message); + failure_message, open_failure_message, read_failure_message, + write_failure_message); /* Register all tap listeners; we do this before we parse the arguments, as the "-z" argument can specify a registered tap. */ @@ -3132,6 +3134,16 @@ read_failure_message(const char *filename, int err) filename, strerror(err)); } +/* + * Write errors are reported with an console message in TShark. + */ +static void +write_failure_message(const char *filename, int err) +{ + cmdarg_err("An error occurred while writing to the file \"%s\": %s.", + filename, strerror(err)); +} + /* * Report an error in command-line arguments. */