-
Notifications
You must be signed in to change notification settings - Fork 861
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Patch] Add option to write to tempfiles and rename when complete #240
Comments
The suggested change: Index: tcpdump.1
===================================================================
RCS file: /tcpdump/master/tcpdump/tcpdump.1,v
retrieving revision 1.188
diff -u -r1.188 tcpdump.1
--- tcpdump.1 7 Jan 2008 00:16:06 -0000 1.188
+++ tcpdump.1 13 Feb 2008 15:22:09 -0000
@@ -29,7 +29,7 @@
.na
.B tcpdump
[
-.B \-AdDefKlLnNOpqRStuUvxX
+.B \-AbdDefKlLnNOpqRStuUvxX
] [
.B \-c
.I count
@@ -259,6 +259,14 @@
Print each packet (minus its link level header) in ASCII. Handy for
capturing web pages.
.TP
+.B \-b
+When writing to a file with -w, always write to a temporary file first,
+and on successful completion (ie. file size met with -C option), rename
+tmp file to file name, and continue. This should ensure that a cap-file
+is always complete. This is good for knowing when to further process a
+file. The temporary files are named \fIfile.tmp\fP, and are renamed to
+\fIfile\fP, where \fIfile\fP is the name specified with the -w option.
+.TP
.B \-c
Exit after receiving \fIcount\fP packets.
.TP
Index: tcpdump.c
===================================================================
RCS file: /tcpdump/master/tcpdump/tcpdump.c,v
retrieving revision 1.276
diff -u -r1.276 tcpdump.c
--- tcpdump.c 29 Jan 2008 10:49:27 -0000 1.276
+++ tcpdump.c 13 Feb 2008 15:22:09 -0000
@@ -93,6 +93,7 @@
int dflag; /* print filter code */
int Lflag; /* list available data link types and exit */
char *zflag = NULL; /* compress each savefile using a specified command (like gzip or bzip2) */
+int bflag; /* write to tempfiles and rename on completion */
static int infodelay;
static int infoprint;
@@ -305,6 +306,7 @@
struct dump_info {
char *WFileName;
char *CurrentFileName;
+ char *TempFileName;
pcap_t *pd;
pcap_dumper_t *p;
};
@@ -430,9 +432,11 @@
static void
-MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars)
+MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars, int tmpname)
{
char *filename = malloc(NAME_MAX + 1);
+ if (filename == NULL)
+ error("MakeFilename: malloc");
/* Process with strftime if Gflag is set. */
if (Gflag != 0) {
@@ -451,12 +455,23 @@
strncpy(filename, orig_name, NAME_MAX);
}
- if (cnt == 0 && max_chars == 0)
- strncpy(buffer, filename, NAME_MAX + 1);
- else
- if (snprintf(buffer, NAME_MAX + 1, "%s%0*d", filename, max_chars, cnt) > NAME_MAX)
- /* Report an error if the filename is too large */
- error("too many output files or filename is too long (> %d)", NAME_MAX);
+ if (cnt == 0 && max_chars == 0) {
+ if (tmpname == 0) {
+ strncpy(buffer, filename, NAME_MAX + 1);
+ } else {
+ snprintf(buffer, NAME_MAX + 1, "%s.tmp", filename);
+ }
+ } else {
+ if (tmpname == 0) {
+ if (snprintf(buffer, NAME_MAX + 1, "%s%0*d", filename, max_chars, cnt) > NAME_MAX)
+ /* Report an error if the filename is too large */
+ error("too many output files or filename is too long (> %d)", NAME_MAX);
+ } else {
+ if (snprintf(buffer, NAME_MAX + 1, "%s%0*d.tmp", filename, max_chars, cnt) > NAME_MAX)
+ /* Report an error if the filename is too large */
+ error("too many output files or filename is too long (> %d)", NAME_MAX);
+ }
+ }
free(filename);
}
@@ -516,6 +531,7 @@
infile = NULL;
RFileName = NULL;
WFileName = NULL;
+ bflag = 0;
if ((cp = strrchr(argv[0], '/')) != NULL)
program_name = cp + 1;
else
@@ -530,7 +546,7 @@
opterr = 0;
while (
- (op = getopt(argc, argv, "aA" B_FLAG "c:C:d" D_FLAG "eE:fF:G:i:KlLm:M:nNOpqr:Rs:StT:u" U_FLAG "vw:W:xXy:Yz:Z:")) != -1)
+ (op = getopt(argc, argv, "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:i:KlLm:M:nNOpqr:Rs:StT:u" U_FLAG "vw:W:xXy:Yz:Z:")) != -1)
switch (op) {
case 'a':
@@ -541,6 +557,10 @@
++Aflag;
break;
+ case 'b':
+ ++bflag;
+ break;
+
#ifdef WIN32
case 'B':
UserBufferSize = atoi(optarg)*1024;
@@ -1026,17 +1046,26 @@
pcap_dumper_t *p;
/* Do not exceed the default NAME_MAX for files. */
dumpinfo.CurrentFileName = (char *)malloc(NAME_MAX + 1);
-
if (dumpinfo.CurrentFileName == NULL)
error("malloc of dumpinfo.CurrentFileName");
+ dumpinfo.TempFileName = (char *)malloc(NAME_MAX + 1);
+ if (dumpinfo.TempFileName == NULL)
+ error("malloc of dumpinfo.TempFileName");
+
/* We do not need numbering for dumpfiles if Cflag isn't set. */
- if (Cflag != 0)
- MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, WflagChars);
- else
- MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, 0);
+ if (Cflag != 0) {
+ MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, WflagChars, 0);
+ MakeFilename(dumpinfo.TempFileName, WFileName, 0, WflagChars, bflag);
+ } else {
+ MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, 0, 0);
+ MakeFilename(dumpinfo.TempFileName, WFileName, 0, 0, bflag);
+ }
- p = pcap_dump_open(pd, dumpinfo.CurrentFileName);
+ if (bflag != 0)
+ p = pcap_dump_open(pd, dumpinfo.TempFileName);
+ else
+ p = pcap_dump_open(pd, dumpinfo.CurrentFileName);
if (p == NULL)
error("%s", pcap_geterr(pd));
if (Cflag != 0 || Gflag != 0) {
@@ -1314,6 +1343,11 @@
if (zflag != NULL)
compress_savefile(dump_info->CurrentFileName);
+ if (bflag != 0) {
+ if (rename(dump_info->TempFileName, dump_info->CurrentFileName) != 0)
+ error("dump_packet_and_trunc: rename");
+ }
+
/*
* Check to see if we've exceeded the Wflag (when
* not using Cflag).
@@ -1330,18 +1364,33 @@
dump_info->CurrentFileName = (char *)malloc(NAME_MAX + 1);
if (dump_info->CurrentFileName == NULL)
error("dump_packet_and_trunc: malloc");
+
+ if (dump_info->TempFileName != NULL)
+ free(dump_info->TempFileName);
+ /* Allocate space for max filename + \0. */
+ dump_info->TempFileName = (char *)malloc(NAME_MAX + 1);
+ if (dump_info->TempFileName == NULL)
+ error("dump_packet_and_trunc: malloc");
+
/*
* This is always the first file in the Cflag
* rotation: e.g. 0
* We also don't need numbering if Cflag is not set.
*/
- if (Cflag != 0)
+ if (Cflag != 0) {
MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0,
- WflagChars);
- else
- MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, 0);
+ WflagChars, 0);
+ MakeFilename(dump_info->TempFileName, dump_info->WFileName, 0,
+ WflagChars, bflag);
+ } else {
+ MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, 0, 0);
+ MakeFilename(dump_info->TempFileName, dump_info->WFileName, 0, 0, bflag);
+ }
- dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
+ if (bflag != 0)
+ dump_info->p = pcap_dump_open(dump_info->pd, dump_info->TempFileName);
+ else
+ dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
if (dump_info->p == NULL)
error("%s", pcap_geterr(pd));
}
@@ -1364,18 +1413,35 @@
if (zflag != NULL)
compress_savefile(dump_info->CurrentFileName);
+ if (bflag != 0) {
+ if (rename(dump_info->TempFileName, dump_info->CurrentFileName) != 0)
+ error("dump_packet_and_trunc: rename");
+ }
+
Cflag_count++;
if (Wflag > 0) {
if (Cflag_count >= Wflag)
Cflag_count = 0;
}
+
if (dump_info->CurrentFileName != NULL)
free(dump_info->CurrentFileName);
dump_info->CurrentFileName = (char *)malloc(NAME_MAX + 1);
if (dump_info->CurrentFileName == NULL)
error("dump_packet_and_trunc: malloc");
- MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, Cflag_count, WflagChars);
- dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
+ MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, Cflag_count, WflagChars, 0);
+
+ if (dump_info->TempFileName != NULL)
+ free(dump_info->TempFileName);
+ dump_info->TempFileName = (char *)malloc(NAME_MAX + 1);
+ if (dump_info->TempFileName == NULL)
+ error("dump_packet_and_trunc: malloc");
+ MakeFilename(dump_info->TempFileName, dump_info->WFileName, Cflag_count, WflagChars, bflag);
+
+ if (bflag != 0)
+ dump_info->p = pcap_dump_open(dump_info->pd, dump_info->TempFileName);
+ else
+ dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
if (dump_info->p == NULL)
error("%s", pcap_geterr(pd));
}
@@ -1599,7 +1665,7 @@
#endif /* WIN32 */
#endif /* HAVE_PCAP_LIB_VERSION */
(void)fprintf(stderr,
-"Usage: %s [-aAd" D_FLAG "efKlLnNOpqRStu" U_FLAG "vxX]" B_FLAG_USAGE " [-c count] [ -C file_size ]\n", program_name);
+"Usage: %s [-aAbd" D_FLAG "efKlLnNOpqRStu" U_FLAG "vxX]" B_FLAG_USAGE " [-c count] [ -C file_size ]\n", program_name);
(void)fprintf(stderr,
"\t\t[ -E algo:secret ] [ -F file ] [ -G seconds ] [ -i interface ]\n");
(void)fprintf(stderr, |
I don't object to the change, but now the main() function is in excess of 1000 lines. Can we move the getopt switch-statement to a new function? parse_cmdline(). BTW. Why is 'optarg' tested like this:
getopt() is given a 'z:' which AFAIK makes 'optarg' always be present. At least in the 'getopt()' I'm used to. |
With regard to |
A patch for what exactly? Here is something to start with. My wish is to put minimal code inside the getopt() switch. So I've added a
We can probably cleanup |
There should be a:
in there too. |
I cocked it up. Here is a patch that actually compiles:
|
Converted from SourceForge issue 1892841, submitted by fatkiss
This patch adds the option "-b" to tcpdump. When used together with the -w and -C options, tcpdump will write to file.tmp, and move it to file when done. Then it will write to file1.tmp, and move it to file1 when done, etc.
The resulting files have the same name as before, but you know which files tcpdump is and isn't writing to. Very useful for scripts trying to do something with the output.
Without the -b option, tcpdump's behaviour is unchanged.
-b was selected because none of the other available options made any more sense.
The patch includes an update to the man page.
This patch also checks the result of the malloc() at the beginning of MakeFilename(), it was assumed to work before.
The text was updated successfully, but these errors were encountered: