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
This commit is contained in:
Guy Harris 2009-02-15 21:47:57 +00:00
parent 8f2e6281c1
commit ace4af44fc
13 changed files with 200 additions and 105 deletions

View File

@ -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

View File

@ -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 <gerald@wireshark.org>
* 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));
}

View File

@ -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

View File

@ -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();

View File

@ -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);

View File

@ -42,6 +42,10 @@
#include <unistd.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
@ -56,9 +60,12 @@
#endif
#include "filesystem.h"
#include "report_err.h"
#include <wsutil/privileges.h>
#include <wsutil/file_util.h>
#include <wiretap/wtap.h> /* 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:
*/

View File

@ -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

View File

@ -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);
}

View File

@ -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 */

71
file.c
View File

@ -43,10 +43,6 @@
#include <fcntl.h>
#endif
#ifdef NEED_STRERROR_H
#include "strerror.h"
#endif
#include <epan/epan.h>
#include <epan/filesystem.h>
@ -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;
}

View File

@ -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);

View File

@ -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.
*/

View File

@ -1,4 +1,7 @@
/* tshark.c
*
* Text-mode variant of Wireshark, along the lines of tcpdump and snoop,
* by Gilbert Ramirez <gram@alumni.rice.edu> and Guy Harris <guy@alum.mit.edu>.
*
* $Id$
*
@ -6,9 +9,6 @@
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* Text-mode variant, by Gilbert Ramirez <gram@alumni.rice.edu>
* and Guy Harris <guy@alum.mit.edu>.
*
* 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.
*/