Make "merge_files()" and "merge_append_files()" return a tri-state

indication - success, read failure, write failure - and have their
callers handle read failures by looking for the file that got the read
failure and reporting the failure in question.

Free up the err_info string returned by "wtap_read()" after using it.

svn path=/trunk/; revision=12423
This commit is contained in:
Guy Harris 2004-10-28 01:52:05 +00:00
parent dc2280bc1e
commit 66e85e4e43
4 changed files with 145 additions and 45 deletions

81
file.c
View File

@ -493,11 +493,12 @@ cf_read(capture_file *cf)
snprintf(errmsg_errno, sizeof(errmsg_errno), snprintf(errmsg_errno, sizeof(errmsg_errno),
"The capture file has a packet with a network type that Ethereal doesn't support.\n(%s)", "The capture file has a packet with a network type that Ethereal doesn't support.\n(%s)",
err_info); err_info);
g_free(err_info);
errmsg = errmsg_errno; errmsg = errmsg_errno;
break; break;
case WTAP_ERR_CANT_READ: case WTAP_ERR_CANT_READ:
errmsg = "An attempt to read from the file failed for" errmsg = "An attempt to read from the capture file failed for"
" some unknown reason."; " some unknown reason.";
break; break;
@ -510,6 +511,7 @@ cf_read(capture_file *cf)
snprintf(errmsg_errno, sizeof(errmsg_errno), snprintf(errmsg_errno, sizeof(errmsg_errno),
"The capture file appears to be damaged or corrupt.\n(%s)", "The capture file appears to be damaged or corrupt.\n(%s)",
err_info); err_info);
g_free(err_info);
errmsg = errmsg_errno; errmsg = errmsg_errno;
break; break;
@ -977,7 +979,11 @@ cf_merge_files(const char *out_filename, int out_fd, int in_file_count,
int err, close_err; int err, close_err;
gchar *err_info; gchar *err_info;
int err_fileno; int err_fileno;
gboolean ret; merge_status_e status;
int i;
char errmsg_errno[1024+1];
gchar err_str[2048+1];
char *errmsg;
/* open the input files */ /* open the input files */
if (!merge_open_in_files(in_file_count, in_filenames, &in_files, if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
@ -998,19 +1004,76 @@ cf_merge_files(const char *out_filename, int out_fd, int in_file_count,
/* do the merge (or append) */ /* do the merge (or append) */
if (do_append) if (do_append)
ret = merge_append_files(in_file_count, in_files, &out_file, &err); status = merge_append_files(in_file_count, in_files, &out_file, &err);
else else
ret = merge_files(in_file_count, in_files, &out_file, &err); status = merge_files(in_file_count, in_files, &out_file, &err);
merge_close_in_files(in_file_count, in_files); merge_close_in_files(in_file_count, in_files);
if (ret) if (status == MERGE_SUCCESS) {
ret = merge_close_outfile(&out_file, &err); if (!merge_close_outfile(&out_file, &err))
else status = MERGE_WRITE_ERROR;
} else
merge_close_outfile(&out_file, &close_err); merge_close_outfile(&out_file, &close_err);
if (!ret) switch (status) {
case MERGE_SUCCESS:
break;
case MERGE_READ_ERROR:
/*
* Find the file on which we got the error, and report the error.
*/
for (i = 0; i < in_file_count; i++) {
if (!in_files[i].ok) {
/* Put up a message box noting that the read failed somewhere along
the line. */
switch (err) {
case WTAP_ERR_UNSUPPORTED_ENCAP:
snprintf(errmsg_errno, sizeof(errmsg_errno),
"The capture file %%s has a packet with a network type that Ethereal doesn't support.\n(%s)",
err_info);
g_free(err_info);
errmsg = errmsg_errno;
break;
case WTAP_ERR_CANT_READ:
errmsg = "An attempt to read from the capture file %s failed for"
" some unknown reason.";
break;
case WTAP_ERR_SHORT_READ:
errmsg = "The capture file %s appears to have been cut short"
" in the middle of a packet.";
break;
case WTAP_ERR_BAD_RECORD:
snprintf(errmsg_errno, sizeof(errmsg_errno),
"The capture file %%sappears to be damaged or corrupt.\n(%s)",
err_info);
g_free(err_info);
errmsg = errmsg_errno;
break;
default:
snprintf(errmsg_errno, sizeof(errmsg_errno),
"An error occurred while reading the"
" capture file %%s: %s.", wtap_strerror(err));
errmsg = errmsg_errno;
break;
}
snprintf(err_str, sizeof err_str, errmsg, in_files[i].filename);
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_str);
}
}
break;
case MERGE_WRITE_ERROR:
cf_write_failure_alert_box(out_filename, err); cf_write_failure_alert_box(out_filename, err);
return ret; break;
}
return (status == MERGE_SUCCESS);
} }
gboolean gboolean

36
merge.c
View File

@ -217,7 +217,7 @@ earliest(int count, merge_in_file_t in_files[]) {
/* /*
* actually merge the files * actually merge the files
*/ */
gboolean merge_status_e
merge_files(int count, merge_in_file_t in_files[], merge_out_file_t *out_file, int *err) merge_files(int count, merge_in_file_t in_files[], merge_out_file_t *out_file, int *err)
{ {
int i; int i;
@ -227,10 +227,8 @@ merge_files(int count, merge_in_file_t in_files[], merge_out_file_t *out_file, i
in_files[i].ok = wtap_read(in_files[i].wth, &(in_files[i].err), in_files[i].ok = wtap_read(in_files[i].wth, &(in_files[i].err),
&(in_files[i].err_info), &(in_files[i].err_info),
&(in_files[i].data_offset)); &(in_files[i].data_offset));
if (!in_files[i].ok) { if (!in_files[i].ok)
/* Read failure, not write failure. */ return MERGE_READ_ERROR;
return TRUE;
}
} }
/* now keep writing the earliest frame until we're out of frames */ /* now keep writing the earliest frame until we're out of frames */
@ -240,20 +238,18 @@ merge_files(int count, merge_in_file_t in_files[], merge_out_file_t *out_file, i
* input file * input file
*/ */
if(!write_frame(in_files[i].wth, out_file, err)) if(!write_frame(in_files[i].wth, out_file, err))
return FALSE; return MERGE_WRITE_ERROR;
in_files[i].ok = wtap_read(in_files[i].wth, &(in_files[i].err), in_files[i].ok = wtap_read(in_files[i].wth, &(in_files[i].err),
&(in_files[i].err_info), &(in_files[i].err_info),
&(in_files[i].data_offset)); &(in_files[i].data_offset));
if (!in_files[i].ok) { if (!in_files[i].ok)
/* Read failure, not write failure. */ return MERGE_READ_ERROR;
return TRUE;
}
} }
return TRUE; return MERGE_SUCCESS;
} }
static gboolean static merge_status_e
append_loop(merge_in_file_t in_files[], int i, int count, append_loop(merge_in_file_t in_files[], int i, int count,
merge_out_file_t *out_file, int *err) merge_out_file_t *out_file, int *err)
{ {
@ -266,33 +262,35 @@ append_loop(merge_in_file_t in_files[], int i, int count,
while ( (wtap_read(in_files[i].wth, err, &err_info, &data_offset)) ) { while ( (wtap_read(in_files[i].wth, err, &err_info, &data_offset)) ) {
if(!write_frame(in_files[i].wth, out_file, err)) if(!write_frame(in_files[i].wth, out_file, err))
return FALSE; /* failure */ return MERGE_WRITE_ERROR;
if (count > 0 && ++loop >= count) if (count > 0 && ++loop >= count)
break; break;
} }
if (*err != 0) { if (*err != 0) {
/* Read failure, not write failure. */
in_files[i].ok = FALSE; in_files[i].ok = FALSE;
in_files[i].err = *err; in_files[i].err = *err;
in_files[i].err_info = err_info; in_files[i].err_info = err_info;
return MERGE_READ_ERROR;
} }
return TRUE; return MERGE_SUCCESS;
} }
/* /*
* routine to concatenate files * routine to concatenate files
*/ */
gboolean merge_status_e
merge_append_files(int count, merge_in_file_t in_files[], merge_append_files(int count, merge_in_file_t in_files[],
merge_out_file_t *out_file, int *err) merge_out_file_t *out_file, int *err)
{ {
int i; int i;
merge_status_e status;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
if (!append_loop(in_files, i, 0, out_file, err)) status = append_loop(in_files, i, 0, out_file, err);
return FALSE; if (status != MERGE_SUCCESS)
return status;
} }
return TRUE; return MERGE_SUCCESS;
} }

19
merge.h
View File

@ -114,15 +114,25 @@ merge_select_frame_type(int in_file_count, merge_in_file_t in_files[]);
extern int extern int
merge_max_snapshot_length(int in_file_count, merge_in_file_t in_files[]); merge_max_snapshot_length(int in_file_count, merge_in_file_t in_files[]);
/*
* Status from the merge-files routines.
*/
typedef enum {
MERGE_SUCCESS,
MERGE_READ_ERROR,
MERGE_WRITE_ERROR
} merge_status_e;
/** Merge the packets from the input files into the output file sorted chronologically. /** Merge the packets from the input files into the output file sorted chronologically.
* *
* @param in_file_count number of entries in in_files * @param in_file_count number of entries in in_files
* @param in_files input file array * @param in_files input file array
* @param out_file the output file array * @param out_file the output file array
* @param err wiretap error, if failed * @param err wiretap error, if failed
* @return TRUE on success or read failure, FALSE on write failure * @return MERGE_SUCCESS on success, MERGE_READ_ERROR on read error,
* MERGE_WRITE_ERROR on write error
*/ */
extern gboolean extern merge_status_e
merge_files(int in_file_count, merge_in_file_t in_files[], merge_out_file_t *out_file, int *err); merge_files(int in_file_count, merge_in_file_t in_files[], merge_out_file_t *out_file, int *err);
/** Append the packets from the input files into the output file. /** Append the packets from the input files into the output file.
@ -131,9 +141,10 @@ merge_files(int in_file_count, merge_in_file_t in_files[], merge_out_file_t *out
* @param in_files input file array * @param in_files input file array
* @param out_file the output file array * @param out_file the output file array
* @param err wiretap error, if failed * @param err wiretap error, if failed
* @return TRUE on success or read failure, FALSE on write failure * @return MERGE_SUCCESS on success, MERGE_READ_ERROR on read error,
* MERGE_WRITE_ERROR on write error
*/ */
extern gboolean extern merge_status_e
merge_append_files(int in_file_count, merge_in_file_t in_files[], merge_append_files(int in_file_count, merge_in_file_t in_files[],
merge_out_file_t *out_file, int *err); merge_out_file_t *out_file, int *err);

View File

@ -142,7 +142,7 @@ main(int argc, char *argv[])
gchar *err_info; gchar *err_info;
int err_fileno; int err_fileno;
char *out_filename = NULL; char *out_filename = NULL;
gboolean ret; merge_status_e status;
/* Process the options first */ /* Process the options first */
while ((opt = getopt(argc, argv, "hvas:T:F:w:")) != -1) { while ((opt = getopt(argc, argv, "hvas:T:F:w:")) != -1) {
@ -194,7 +194,7 @@ main(int argc, char *argv[])
case '?': /* Bad options if GNU getopt */ case '?': /* Bad options if GNU getopt */
usage(); usage();
exit(1); return 1;
break; break;
} }
@ -208,11 +208,11 @@ main(int argc, char *argv[])
if (!out_filename) { if (!out_filename) {
fprintf(stderr, "mergecap: an output filename must be set with -w\n"); fprintf(stderr, "mergecap: an output filename must be set with -w\n");
fprintf(stderr, " run with -h for help\n"); fprintf(stderr, " run with -h for help\n");
exit(1); return 1;
} }
if (in_file_count < 1) { if (in_file_count < 1) {
fprintf(stderr, "mergecap: No input files were specified\n"); fprintf(stderr, "mergecap: No input files were specified\n");
exit(1); return 1;
} }
/* open the input files */ /* open the input files */
@ -229,7 +229,7 @@ main(int argc, char *argv[])
g_free(err_info); g_free(err_info);
break; break;
} }
exit(1); return 2;
} }
if (verbose) { if (verbose) {
@ -309,21 +309,49 @@ main(int argc, char *argv[])
/* do the merge (or append) */ /* do the merge (or append) */
if (do_append) if (do_append)
ret = merge_append_files(in_file_count, in_files, &out_file, &err); status = merge_append_files(in_file_count, in_files, &out_file, &err);
else else
ret = merge_files(in_file_count, in_files, &out_file, &err); status = merge_files(in_file_count, in_files, &out_file, &err);
merge_close_in_files(in_file_count, in_files); merge_close_in_files(in_file_count, in_files);
if (ret) if (status == MERGE_SUCCESS) {
ret = merge_close_outfile(&out_file, &err); if (!merge_close_outfile(&out_file, &err))
else status = MERGE_WRITE_ERROR;
} else
merge_close_outfile(&out_file, &close_err); merge_close_outfile(&out_file, &close_err);
if (!ret) { switch (status) {
case MERGE_SUCCESS:
break;
case MERGE_READ_ERROR:
/*
* Find the file on which we got the error, and report the error.
*/
for (i = 0; i < in_file_count; i++) {
if (!in_files[i].ok) {
fprintf(stderr, "mergecap: Error reading %s: %s\n",
in_files[i].filename, wtap_strerror(in_files[i].err));
switch (err) {
case WTAP_ERR_UNSUPPORTED:
case WTAP_ERR_UNSUPPORTED_ENCAP:
case WTAP_ERR_BAD_RECORD:
fprintf(stderr, "(%s)\n", in_files[i].err_info);
g_free(in_files[i].err_info);
break;
}
}
}
break;
case MERGE_WRITE_ERROR:
fprintf(stderr, "mergecap: Error writing to outfile: %s\n", fprintf(stderr, "mergecap: Error writing to outfile: %s\n",
wtap_strerror(err)); wtap_strerror(err));
break;
} }
free(in_files); free(in_files);
return ret ? 0 : 2; return (status == MERGE_SUCCESS) ? 0 : 2;
} }