[Automatic manuf and enterprise-numbers update for 2010-04-04]
[obnox/wireshark/wip.git] / editcap.c
index 09558636f29206a3c083c3cc624843c1c08e64b6..724f7abdd9f37903f26774fd096f7717a86c0971 100644 (file)
--- a/editcap.c
+++ b/editcap.c
 
 #include "wtap.h"
 
-#ifdef NEED_GETOPT_H
-#include "getopt.h"
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+#include "wsgetopt.h"
 #endif
 
 #ifdef _WIN32
@@ -164,14 +166,14 @@ abs_time_to_str_with_sec_resolution(const struct wtap_nstime *abs_time)
 }
 
 static gchar*
-fileset_get_filename_by_pattern(guint idx,    const struct wtap_nstime *time, 
+fileset_get_filename_by_pattern(guint idx,    const struct wtap_nstime *time_val
                                     gchar *fprefix, gchar *fsuffix)
 {
     gchar filenum[5+1];
     gchar *timestr;
     gchar *abs_str;
 
-    timestr = abs_time_to_str_with_sec_resolution(time);
+    timestr = abs_time_to_str_with_sec_resolution(time_val);
     g_snprintf(filenum, sizeof(filenum), "%05u", idx);
     abs_str = g_strconcat(fprefix, "_", filenum, "_", timestr, fsuffix, NULL);
     g_free(timestr);
@@ -186,9 +188,10 @@ fileset_extract_prefix_suffix(const char *fname, gchar **fprefix, gchar **fsuffi
     gchar *save_file;
 
     save_file = g_strdup(fname);
-
-    if (!fprefix || !fsuffix || !save_file)
-        return FALSE;
+    if (save_file == NULL) {
+      fprintf(stderr, "editcap: Out of memory\n");
+      return FALSE;
+    }
 
     last_pathsep = strrchr(save_file, G_DIR_SEPARATOR);
     pfx = strrchr(save_file,'.');
@@ -291,40 +294,40 @@ check_timestamp(wtap *wth)
 }
 
 static void
-set_time_adjustment(char *optarg)
+set_time_adjustment(char *optarg_str_p)
 {
   char *frac, *end;
   long val;
   size_t frac_digits;
 
-  if (!optarg)
+  if (!optarg_str_p)
     return;
 
   /* skip leading whitespace */
-  while (*optarg == ' ' || *optarg == '\t') {
-      optarg++;
+  while (*optarg_str_p == ' ' || *optarg_str_p == '\t') {
+      optarg_str_p++;
   }
 
   /* check for a negative adjustment */
-  if (*optarg == '-') {
+  if (*optarg_str_p == '-') {
       time_adj.is_negative = 1;
-      optarg++;
+      optarg_str_p++;
   }
 
   /* collect whole number of seconds, if any */
-  if (*optarg == '.') {         /* only fractional (i.e., .5 is ok) */
+  if (*optarg_str_p == '.') {         /* only fractional (i.e., .5 is ok) */
       val  = 0;
-      frac = optarg;
+      frac = optarg_str_p;
   } else {
-      val = strtol(optarg, &frac, 10);
-      if (frac == NULL || frac == optarg || val == LONG_MIN || val == LONG_MAX) {
+      val = strtol(optarg_str_p, &frac, 10);
+      if (frac == NULL || frac == optarg_str_p || val == LONG_MIN || val == LONG_MAX) {
           fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n",
-                  optarg);
+                  optarg_str_p);
           exit(1);
       }
       if (val < 0) {            /* implies '--' since we caught '-' above  */
           fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n",
-                  optarg);
+                  optarg_str_p);
           exit(1);
       }
   }
@@ -333,10 +336,15 @@ set_time_adjustment(char *optarg)
   /* now collect the partial seconds, if any */
   if (*frac != '\0') {             /* chars left, so get fractional part */
     val = strtol(&(frac[1]), &end, 10);
+    /* if more than 6 fractional digits truncate to 6 */
+    if((end - &(frac[1])) > 6) {
+        frac[7] = 't'; /* 't' for truncate */
+        val = strtol(&(frac[1]), &end, 10);
+    }
     if (*frac != '.' || end == NULL || end == frac
         || val < 0 || val > ONE_MILLION || val == LONG_MIN || val == LONG_MAX) {
       fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n",
-              optarg);
+              optarg_str_p);
       exit(1);
     }
   }
@@ -357,39 +365,39 @@ set_time_adjustment(char *optarg)
 }
 
 static void
-set_rel_time(char *optarg)
+set_rel_time(char *optarg_str_p)
 {
   char *frac, *end;
   long val;
   size_t frac_digits;
 
-  if (!optarg)
+  if (!optarg_str_p)
     return;
 
   /* skip leading whitespace */
-  while (*optarg == ' ' || *optarg == '\t') {
-      optarg++;
+  while (*optarg_str_p == ' ' || *optarg_str_p == '\t') {
+      optarg_str_p++;
   }
 
   /* ignore negative adjustment  */
-  if (*optarg == '-') {
-      optarg++;
+  if (*optarg_str_p == '-') {
+      optarg_str_p++;
   }
 
   /* collect whole number of seconds, if any */
-  if (*optarg == '.') {         /* only fractional (i.e., .5 is ok) */
+  if (*optarg_str_p == '.') {         /* only fractional (i.e., .5 is ok) */
       val  = 0;
-      frac = optarg;
+      frac = optarg_str_p;
   } else {
-      val = strtol(optarg, &frac, 10);
-      if (frac == NULL || frac == optarg || val == LONG_MIN || val == LONG_MAX) {
+      val = strtol(optarg_str_p, &frac, 10);
+      if (frac == NULL || frac == optarg_str_p || val == LONG_MIN || val == LONG_MAX) {
           fprintf(stderr, "1: editcap: \"%s\" isn't a valid rel time value\n",
-                  optarg);
+                  optarg_str_p);
           exit(1);
       }
       if (val < 0) {            /* implies '--' since we caught '-' above  */
           fprintf(stderr, "2: editcap: \"%s\" isn't a valid rel time value\n",
-                  optarg);
+                  optarg_str_p);
           exit(1);
       }
   }
@@ -398,10 +406,15 @@ set_rel_time(char *optarg)
   /* now collect the partial seconds, if any */
   if (*frac != '\0') {             /* chars left, so get fractional part */
     val = strtol(&(frac[1]), &end, 10);
+    /* if more than 9 fractional digits truncate to 9 */
+    if((end - &(frac[1])) > 9) {
+        frac[10] = 't'; /* 't' for truncate */
+        val = strtol(&(frac[1]), &end, 10);
+    }
     if (*frac != '.' || end == NULL || end == frac
         || val < 0 || val > ONE_BILLION || val == LONG_MIN || val == LONG_MAX) {
       fprintf(stderr, "3: editcap: \"%s\" isn't a valid rel time value\n",
-              optarg);
+              optarg_str_p);
       exit(1);
     }
   }
@@ -558,79 +571,86 @@ is_duplicate_rel_time(guint8* fd, guint32 len, const nstime_t *current) {
 }
 
 static void
-usage(void)
+usage(gboolean is_error)
 {
-  fprintf(stderr, "Editcap %s"
+  FILE *output;
+
+  if (!is_error)
+    output = stdout;
+  else
+    output = stderr;
+
+  fprintf(output, "Editcap %s"
 #ifdef SVNVERSION
-         " (" SVNVERSION ")"
+         " (" SVNVERSION " from " SVNPATH ")"
 #endif
          "\n", VERSION);
-  fprintf(stderr, "Edit and/or translate the format of capture files.\n");
-  fprintf(stderr, "See http://www.wireshark.org for more information.\n");
-  fprintf(stderr, "\n");
-  fprintf(stderr, "Usage: editcap [options] ... <infile> <outfile> [ <packet#>[-<packet#>] ... ]\n");
-  fprintf(stderr, "\n");
-  fprintf(stderr, "<infile> and <outfile> must both be present.\n");
-  fprintf(stderr, "A single packet or a range of packets can be selected.\n");
-  fprintf(stderr, "\n");
-  fprintf(stderr, "Packet selection:\n");
-  fprintf(stderr, "  -r                     keep the selected packets; default is to delete them.\n");
-  fprintf(stderr, "  -A <start time>        don't output packets whose timestamp is before the\n");
-  fprintf(stderr, "                         given time (format as YYYY-MM-DD hh:mm:ss).\n");
-  fprintf(stderr, "  -B <stop time>         don't output packets whose timestamp is after the\n");
-  fprintf(stderr, "                         given time (format as YYYY-MM-DD hh:mm:ss).\n");
-  fprintf(stderr, "\n");
-  fprintf(stderr, "Duplicate packet removal:\n");
-  fprintf(stderr, "  -d                     remove packet if duplicate (window == %d).\n", DEFAULT_DUP_DEPTH);
-  fprintf(stderr, "  -D <dup window>        remove packet if duplicate; configurable <dup window>\n");
-  fprintf(stderr, "                         Valid <dup window> values are 0 to %d.\n", MAX_DUP_DEPTH);
-  fprintf(stderr, "                         NOTE: A <dup window> of 0 with -v (verbose option) is\n");
-  fprintf(stderr, "                         useful to print MD5 hashes.\n");
-  fprintf(stderr, "  -w <dup time window>   remove packet if duplicate packet is found EQUAL TO OR\n");
-  fprintf(stderr, "                         LESS THAN <dup time window> prior to current packet.\n");
-  fprintf(stderr, "                         A <dup time window> is specified in relative seconds\n");
-  fprintf(stderr, "                         (e.g. 0.000001).\n");
-  fprintf(stderr, "\n");
-  fprintf(stderr, "           NOTE: The use of the 'Duplicate packet removal' options with\n");
-  fprintf(stderr, "           other editcap options except -v may not always work as expected.\n");
-  fprintf(stderr, "           Specifically the -r and -t options will very likely NOT have the\n");
-  fprintf(stderr, "           desired effect if combined with the -d, -D or -w.\n");
-  fprintf(stderr, "\n");
-  fprintf(stderr, "Packet manipulation:\n");
-  fprintf(stderr, "  -s <snaplen>           truncate each packet to max. <snaplen> bytes of data.\n");
-  fprintf(stderr, "  -C <choplen>           chop each packet at the end by <choplen> bytes.\n");
-  fprintf(stderr, "  -t <time adjustment>   adjust the timestamp of each packet;\n");
-  fprintf(stderr, "                         <time adjustment> is in relative seconds (e.g. -0.5).\n");
-  fprintf(stderr, "  -E <error probability> set the probability (between 0.0 and 1.0 incl.)\n");
-  fprintf(stderr, "                         that a particular packet byte will be randomly changed.\n");
-  fprintf(stderr, "\n");
-  fprintf(stderr, "Output File(s):\n");
-  fprintf(stderr, "  -c <packets per file>  split the packet output to different files\n");
-  fprintf(stderr, "                         based on uniform packet counts\n");
-  fprintf(stderr, "                         with a maximum of <packets per file> each.\n");
-  fprintf(stderr, "  -i <seconds per file>  split the packet output to different files\n");
-  fprintf(stderr, "                         based on uniform time intervals\n");
-  fprintf(stderr, "                         with a maximum of <seconds per file> each.\n");
-  fprintf(stderr, "  -F <capture type>      set the output file type; default is libpcap.\n");
-  fprintf(stderr, "                         an empty \"-F\" option will list the file types.\n");
-  fprintf(stderr, "  -T <encap type>        set the output file encapsulation type;\n");
-  fprintf(stderr, "                         default is the same as the input file.\n");
-  fprintf(stderr, "                         an empty \"-T\" option will list the encapsulation types.\n");
-  fprintf(stderr, "\n");
-  fprintf(stderr, "Miscellaneous:\n");
-  fprintf(stderr, "  -h                     display this help and exit.\n");
-  fprintf(stderr, "  -v                     verbose output.\n");
-  fprintf(stderr, "                         If -v is used with any of the 'Duplicate Packet\n");
-  fprintf(stderr, "                         Removal' options (-d, -D or -w) then Packet lengths\n");
-  fprintf(stderr, "                         and MD5 hashes are printed to standard-out.\n");
-  fprintf(stderr, "\n");
+  fprintf(output, "Edit and/or translate the format of capture files.\n");
+  fprintf(output, "See http://www.wireshark.org for more information.\n");
+  fprintf(output, "\n");
+  fprintf(output, "Usage: editcap [options] ... <infile> <outfile> [ <packet#>[-<packet#>] ... ]\n");
+  fprintf(output, "\n");
+  fprintf(output, "<infile> and <outfile> must both be present.\n");
+  fprintf(output, "A single packet or a range of packets can be selected.\n");
+  fprintf(output, "\n");
+  fprintf(output, "Packet selection:\n");
+  fprintf(output, "  -r                     keep the selected packets; default is to delete them.\n");
+  fprintf(output, "  -A <start time>        don't output packets whose timestamp is before the\n");
+  fprintf(output, "                         given time (format as YYYY-MM-DD hh:mm:ss).\n");
+  fprintf(output, "  -B <stop time>         don't output packets whose timestamp is after the\n");
+  fprintf(output, "                         given time (format as YYYY-MM-DD hh:mm:ss).\n");
+  fprintf(output, "\n");
+  fprintf(output, "Duplicate packet removal:\n");
+  fprintf(output, "  -d                     remove packet if duplicate (window == %d).\n", DEFAULT_DUP_DEPTH);
+  fprintf(output, "  -D <dup window>        remove packet if duplicate; configurable <dup window>\n");
+  fprintf(output, "                         Valid <dup window> values are 0 to %d.\n", MAX_DUP_DEPTH);
+  fprintf(output, "                         NOTE: A <dup window> of 0 with -v (verbose option) is\n");
+  fprintf(output, "                         useful to print MD5 hashes.\n");
+  fprintf(output, "  -w <dup time window>   remove packet if duplicate packet is found EQUAL TO OR\n");
+  fprintf(output, "                         LESS THAN <dup time window> prior to current packet.\n");
+  fprintf(output, "                         A <dup time window> is specified in relative seconds\n");
+  fprintf(output, "                         (e.g. 0.000001).\n");
+  fprintf(output, "\n");
+  fprintf(output, "           NOTE: The use of the 'Duplicate packet removal' options with\n");
+  fprintf(output, "           other editcap options except -v may not always work as expected.\n");
+  fprintf(output, "           Specifically the -r and -t options will very likely NOT have the\n");
+  fprintf(output, "           desired effect if combined with the -d, -D or -w.\n");
+  fprintf(output, "\n");
+  fprintf(output, "Packet manipulation:\n");
+  fprintf(output, "  -s <snaplen>           truncate each packet to max. <snaplen> bytes of data.\n");
+  fprintf(output, "  -C <choplen>           chop each packet at the end by <choplen> bytes.\n");
+  fprintf(output, "  -t <time adjustment>   adjust the timestamp of each packet;\n");
+  fprintf(output, "                         <time adjustment> is in relative seconds (e.g. -0.5).\n");
+  fprintf(output, "  -E <error probability> set the probability (between 0.0 and 1.0 incl.)\n");
+  fprintf(output, "                         that a particular packet byte will be randomly changed.\n");
+  fprintf(output, "\n");
+  fprintf(output, "Output File(s):\n");
+  fprintf(output, "  -c <packets per file>  split the packet output to different files\n");
+  fprintf(output, "                         based on uniform packet counts\n");
+  fprintf(output, "                         with a maximum of <packets per file> each.\n");
+  fprintf(output, "  -i <seconds per file>  split the packet output to different files\n");
+  fprintf(output, "                         based on uniform time intervals\n");
+  fprintf(output, "                         with a maximum of <seconds per file> each.\n");
+  fprintf(output, "  -F <capture type>      set the output file type; default is libpcap.\n");
+  fprintf(output, "                         an empty \"-F\" option will list the file types.\n");
+  fprintf(output, "  -T <encap type>        set the output file encapsulation type;\n");
+  fprintf(output, "                         default is the same as the input file.\n");
+  fprintf(output, "                         an empty \"-T\" option will list the encapsulation types.\n");
+  fprintf(output, "\n");
+  fprintf(output, "Miscellaneous:\n");
+  fprintf(output, "  -h                     display this help and exit.\n");
+  fprintf(output, "  -v                     verbose output.\n");
+  fprintf(output, "                         If -v is used with any of the 'Duplicate Packet\n");
+  fprintf(output, "                         Removal' options (-d, -D or -w) then Packet lengths\n");
+  fprintf(output, "                         and MD5 hashes are printed to standard-out.\n");
+  fprintf(output, "\n");
 }
 
 static void
 list_capture_types(void) {
     int i;
 
-    fprintf(stderr, "editcap: The available capture file types for \"F\":\n");
+    fprintf(stderr, "editcap: The available capture file types for the \"-F\" flag are:\n");
     for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
       if (wtap_dump_can_open(i))
         fprintf(stderr, "    %s - %s\n",
@@ -643,7 +663,7 @@ list_encap_types(void) {
     int i;
     const char *string;
 
-    fprintf(stderr, "editcap: The available encapsulation types for \"T\":\n");
+    fprintf(stderr, "editcap: The available encapsulation types for the \"-T\" flag are:\n");
     for (i = 0; i < WTAP_NUM_ENCAP_TYPES; i++) {
         string = wtap_encap_short_string(i);
         if (string != NULL)
@@ -671,8 +691,6 @@ main(int argc, char *argv[])
   wtap *wth;
   int i, j, err;
   gchar *err_info;
-  extern char *optarg;
-  extern int optind;
   int opt;
   char *p;
   unsigned int snaplen = 0;             /* No limit               */
@@ -801,13 +819,13 @@ main(int argc, char *argv[])
         list_encap_types();
         break;
       default:
-        usage();
+        usage(TRUE);
       }
       exit(1);
       break;
 
     case 'h':
-      usage();
+      usage(FALSE);
       exit(1);
       break;
 
@@ -893,7 +911,7 @@ main(int argc, char *argv[])
 
   if ((argc - optind) < 1) {
 
-    usage();
+    usage(TRUE);
     exit(1);
 
   }
@@ -936,7 +954,7 @@ main(int argc, char *argv[])
       g_free(err_info);
       break;
     }
-    exit(1);
+    exit(2);
 
   }
 
@@ -974,13 +992,13 @@ main(int argc, char *argv[])
         block_start.secs = phdr->ts.secs;
         block_start.nsecs = phdr->ts.nsecs;
 
-      if (split_packet_count > 0 || secs_per_block > 0) {
-        if (!fileset_extract_prefix_suffix(argv[optind+1], &fprefix, &fsuffix))
-            exit(5);
+        if (split_packet_count > 0 || secs_per_block > 0) {
+          if (!fileset_extract_prefix_suffix(argv[optind+1], &fprefix, &fsuffix))
+              exit(2);
 
-        filename = fileset_get_filename_by_pattern(block_cnt++, &phdr->ts, fprefix, fsuffix);
-      } else
-        filename = g_strdup(argv[optind+1]);
+          filename = fileset_get_filename_by_pattern(block_cnt++, &phdr->ts, fprefix, fsuffix);
+        } else
+          filename = g_strdup(argv[optind+1]);
 
         pdh = wtap_dump_open(filename, out_file_type,
             out_frame_type, wtap_snapshot_length(wth),
@@ -988,7 +1006,7 @@ main(int argc, char *argv[])
         if (pdh == NULL) {  
           fprintf(stderr, "editcap: Can't open or create %s: %s\n", filename,
                   wtap_strerror(err));
-          exit(1);
+          exit(2);
         }
       }
 
@@ -1002,7 +1020,7 @@ main(int argc, char *argv[])
           if (!wtap_dump_close(pdh, &err)) {
             fprintf(stderr, "editcap: Error writing to %s: %s\n", filename,
                 wtap_strerror(err));
-            exit(1);
+            exit(2);
           }
           block_start.secs = block_start.secs +  secs_per_block; /* reset for next interval */
           g_free(filename);
@@ -1019,7 +1037,7 @@ main(int argc, char *argv[])
           if (pdh == NULL) {
             fprintf(stderr, "editcap: Can't open or create %s: %s\n", filename,
               wtap_strerror(err));
-            exit(1);
+            exit(2);
           }
         }
       }
@@ -1032,7 +1050,7 @@ main(int argc, char *argv[])
           if (!wtap_dump_close(pdh, &err)) {
             fprintf(stderr, "editcap: Error writing to %s: %s\n", filename,
                 wtap_strerror(err));
-            exit(1);
+            exit(2);
           }
 
           g_free(filename);
@@ -1048,7 +1066,7 @@ main(int argc, char *argv[])
           if (pdh == NULL) {
             fprintf(stderr, "editcap: Can't open or create %s: %s\n", filename,
                 wtap_strerror(err));
-            exit(1);
+            exit(2);
           }
         }
       }
@@ -1222,14 +1240,13 @@ main(int argc, char *argv[])
                        &err)) {
           fprintf(stderr, "editcap: Error writing to %s: %s\n",
                   filename, wtap_strerror(err));
-          exit(1);
+          exit(2);
         }
         written_count++;
       }
       count++;
     }
 
-    g_free(filename);
     g_free(fprefix);
     g_free(fsuffix);
 
@@ -1249,13 +1266,28 @@ main(int argc, char *argv[])
       }
     }
 
+    if (!pdh) {
+      /* No valid packages found, open the outfile so we can write an empty header */
+      g_free (filename);
+      filename = g_strdup(argv[optind+1]);
+
+      pdh = wtap_dump_open(filename, out_file_type,
+                          out_frame_type, wtap_snapshot_length(wth), FALSE /* compressed */, &err);
+      if (pdh == NULL) {
+       fprintf(stderr, "editcap: Can't open or create %s: %s\n", filename, 
+               wtap_strerror(err));
+       exit(2);
+      }
+    }
+
     if (!wtap_dump_close(pdh, &err)) {
 
       fprintf(stderr, "editcap: Error writing to %s: %s\n", filename,
           wtap_strerror(err));
-      exit(1);
+      exit(2);
 
     }
+    g_free(filename);
   }
 
   if (dup_detect) {