Add a routine that, given a set of packet encapsulation types, returns

the per-file encapsulation type needed to write out a set of packets
with all those encapsulation types.  If there's only one such
encapsulation type, that's the type, otherwise WTAP_ENCAP_PER_PACKET is
needed.  Use that in wtap_dump_can_write_encaps().

Also use it in cf_save_packets() and cf_export_specified_packets(), so
that we can write out files with WTAP_ENCAP_PER_PACKET as the file
encapsulation type and only one actual per-packet encapsulation type in
some cases where that failed before.  This fixes the case that showed up
in bug 7505, although there are other cases where we *could* write out a
capture in a given file format but won't be able to do so; fixing those
will take more work.

#BACKPORT

(Note: this adds a routine to libwiretap, so, when backported, the
*minor* version of the library should be increased.  Code that worked
with the version of the library prior to this change will continue to
work, so there's no need to change the *major* version of the library.)

svn path=/trunk/; revision=43847
This commit is contained in:
Guy Harris 2012-07-20 04:00:29 +00:00
parent 99f7759357
commit 633de5c7d1
4 changed files with 51 additions and 17 deletions

16
file.c
View File

@ -4230,10 +4230,14 @@ cf_save_packets(capture_file *cf, const char *fname, guint save_format,
wtapng_section_t *shb_hdr = NULL;
wtapng_iface_descriptions_t *idb_inf = NULL;
int encap;
shb_hdr = wtap_file_get_shb_info(cf->wth);
idb_inf = wtap_file_get_idb_info(cf->wth);
/* Determine what file encapsulation type we should use. */
encap = wtap_dump_file_encap_type(cf->linktypes);
if (file_exists(fname)) {
/* We're overwriting an existing file; write out to a new file,
and, if that succeeds, rename the new file on top of the
@ -4243,10 +4247,10 @@ cf_save_packets(capture_file *cf, const char *fname, guint save_format,
we *HAVE* to do that, otherwise we're overwriting the file
from which we're reading the packets that we're writing!) */
fname_new = g_strdup_printf("%s~", fname);
pdh = wtap_dump_open_ng(fname_new, save_format, cf->lnk_t, cf->snap,
pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
compressed, shb_hdr, idb_inf, &err);
} else {
pdh = wtap_dump_open_ng(fname, save_format, cf->lnk_t, cf->snap,
pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
compressed, shb_hdr, idb_inf, &err);
}
g_free(idb_inf);
@ -4434,6 +4438,7 @@ cf_export_specified_packets(capture_file *cf, const char *fname,
save_callback_args_t callback_args;
wtapng_section_t *shb_hdr = NULL;
wtapng_iface_descriptions_t *idb_inf = NULL;
int encap;
cf_callback_invoke(cf_cb_file_export_specified_packets_started, (gpointer)fname);
@ -4447,6 +4452,9 @@ cf_export_specified_packets(capture_file *cf, const char *fname,
shb_hdr = wtap_file_get_shb_info(cf->wth);
idb_inf = wtap_file_get_idb_info(cf->wth);
/* Determine what file encapsulation type we should use. */
encap = wtap_dump_file_encap_type(cf->linktypes);
if (file_exists(fname)) {
/* We're overwriting an existing file; write out to a new file,
and, if that succeeds, rename the new file on top of the
@ -4456,10 +4464,10 @@ cf_export_specified_packets(capture_file *cf, const char *fname,
we *HAVE* to do that, otherwise we're overwriting the file
from which we're reading the packets that we're writing!) */
fname_new = g_strdup_printf("%s~", fname);
pdh = wtap_dump_open_ng(fname_new, save_format, cf->lnk_t, cf->snap,
pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
compressed, shb_hdr, idb_inf, &err);
} else {
pdh = wtap_dump_open_ng(fname, save_format, cf->lnk_t, cf->snap,
pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
compressed, shb_hdr, idb_inf, &err);
}
g_free(idb_inf);

View File

@ -761,6 +761,25 @@ int wtap_get_num_file_types(void)
return wtap_num_file_types;
}
/*
* Given a GArray of WTAP_ENCAP_ types, return the per-file encapsulation
* type that would be needed to write out a file with those types. If
* there's only one type, it's that type, otherwise it's
* WTAP_ENCAP_PER_PACKET.
*/
int
wtap_dump_file_encap_type(const GArray *file_encaps)
{
int encap;
encap = WTAP_ENCAP_PER_PACKET;
if (file_encaps->len == 1) {
/* OK, use the one-and-only encapsulation type. */
encap = g_array_index(file_encaps, gint, 0);
}
return encap;
}
/*
* Return TRUE if a capture with a given GArray of WTAP_ENCAP_ types
* can be written in a specified format, and FALSE if it can't.
@ -779,24 +798,24 @@ wtap_dump_can_write_encaps(int ft, const GArray *file_encaps)
}
/*
* OK, we can write in that format; can we write out all the
* specified encapsulation types in that format?
* Is the required per-file encapsulation type supported?
* This might be WTAP_ENCAP_PER_PACKET.
*/
if (!wtap_dump_can_write_encap(ft, wtap_dump_file_encap_type(file_encaps)))
return FALSE;
/*
* Yes. Are all the individual encapsulation types supported?
*/
if (file_encaps->len > 1) {
/*
* We have more than one encapsulation type,
* so that format needs to support
* WTAP_ENCAP_PER_PACKET.
*/
if (!wtap_dump_can_write_encap(ft, WTAP_ENCAP_PER_PACKET))
return FALSE;
}
for (i = 0; i < file_encaps->len; i++) {
if (!wtap_dump_can_write_encap(ft,
g_array_index(file_encaps, int, i)))
g_array_index(file_encaps, int, i))) {
/* No - one of them isn't. */
return FALSE;
}
}
/* Yes - we're OK. */
return TRUE;
}

View File

@ -35,6 +35,7 @@ wtap_dump_can_compress
wtap_dump_close
wtap_dump_fdopen
wtap_dump_fdopen_ng
wtap_dump_file_encap_type
wtap_dump_flush
wtap_dump_open
wtap_dump_open_ng

View File

@ -1107,6 +1107,12 @@ void wtap_close(wtap *wth);
gboolean wtap_dump_can_open(int filetype);
gboolean wtap_dump_can_write_encap(int filetype, int encap);
/**
* Given a GArray of WTAP_ENCAP_ types, return the per-file encapsulation
* type that would be needed to write out a file with those types.
*/
int wtap_dump_file_encap_type(const GArray *file_encaps);
/**
* Return TRUE if a capture with a given GArray of WTAP_ENCAP_ types
* can be written in a specified format, and FALSE if it can't.