[Automatic manuf and enterprise-numbers update for 2010-04-04]
[obnox/wireshark/wip.git] / editcap.c
index 66df3f0ba1d35957bc5da97366c656a884dff4df..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
@@ -134,6 +136,90 @@ static gboolean dup_detect_by_time = FALSE;
 
 static int find_dct2000_real_data(guint8 *buf);
 
+static gchar *
+abs_time_to_str_with_sec_resolution(const struct wtap_nstime *abs_time)
+{
+    struct tm *tmp;
+    gchar *buf = g_malloc(16);
+    
+#ifdef _MSC_VER
+    /* calling localtime() on MSVC 2005 with huge values causes it to crash */
+    /* XXX - find the exact value that still does work */
+    /* XXX - using _USE_32BIT_TIME_T might be another way to circumvent this problem */
+    if(abs_time->secs > 2000000000) {
+        tmp = NULL;
+    } else
+#endif
+    tmp = localtime(&abs_time->secs);
+    if (tmp) {
+        g_snprintf(buf, 16, "%d%02d%02d%02d%02d%02d",
+            tmp->tm_year + 1900,
+            tmp->tm_mon+1,
+            tmp->tm_mday,
+            tmp->tm_hour,
+            tmp->tm_min,
+            tmp->tm_sec);
+    } else
+        strcpy(buf, "");
+
+    return buf;
+}
+
+static gchar*
+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_val);
+    g_snprintf(filenum, sizeof(filenum), "%05u", idx);
+    abs_str = g_strconcat(fprefix, "_", filenum, "_", timestr, fsuffix, NULL);
+    g_free(timestr);
+
+    return abs_str;
+}
+
+static gboolean
+fileset_extract_prefix_suffix(const char *fname, gchar **fprefix, gchar **fsuffix)
+{
+    char  *pfx, *last_pathsep;
+    gchar *save_file;
+
+    save_file = g_strdup(fname);
+    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,'.');
+    if (pfx != NULL && (last_pathsep == NULL || pfx > last_pathsep)) {
+      /* The pathname has a "." in it, and it's in the last component
+         of the pathname (because there is either only one component,
+         i.e. last_pathsep is null as there are no path separators,
+         or the "." is after the path separator before the last
+         component.
+
+         Treat it as a separator between the rest of the file name and
+         the file name suffix, and arrange that the names given to the
+         ring buffer files have the specified suffix, i.e. put the
+         changing part of the name *before* the suffix. */
+      pfx[0] = '\0';
+      *fprefix = g_strdup(save_file);
+      pfx[0] = '.'; /* restore capfile_name */
+      *fsuffix = g_strdup(pfx);
+    } else {
+      /* Either there's no "." in the pathname, or it's in a directory
+         component, so the last component has no suffix. */
+      *fprefix = g_strdup(save_file);
+      *fsuffix = NULL;
+    }
+    g_free(save_file);
+    return TRUE;
+}
+
 /* Add a selection item, a simple parser for now */
 static gboolean
 add_selection(char *sel)
@@ -208,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);
       }
   }
@@ -250,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);
     }
   }
@@ -274,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;
-  int frac_digits;
+  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);
       }
   }
@@ -315,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);
     }
   }
@@ -475,78 +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, "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",
@@ -559,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)
@@ -587,13 +691,11 @@ 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               */
   unsigned int choplen = 0;             /* No chop                */
-  wtap_dumper *pdh;
+  wtap_dumper *pdh = NULL;
   int count = 1;
   unsigned duplicate_count = 0;
   gint64 data_offset;
@@ -603,12 +705,13 @@ main(int argc, char *argv[])
   guint8 *buf;
   int split_packet_count = 0;
   int written_count = 0;
-  char *filename;
-  size_t filenamelen = 0;
+  char *filename = NULL;
   gboolean check_ts;
   int secs_per_block = 0;
   int block_cnt = 0;
   nstime_t block_start;
+  gchar *fprefix = NULL;
+  gchar *fsuffix = NULL;
 
 #ifdef HAVE_PLUGINS
   char* init_progfile_dir_error;
@@ -716,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;
 
@@ -759,7 +862,6 @@ main(int argc, char *argv[])
 
     case 'i': /* break capture file based on time interval */
       secs_per_block = atoi(optarg);
-      nstime_set_unset(&block_start);
       if(secs_per_block <= 0) {
         fprintf(stderr, "editcap: \"%s\" isn't a valid time interval\n\n", optarg);
         exit(1);
@@ -809,7 +911,7 @@ main(int argc, char *argv[])
 
   if ((argc - optind) < 1) {
 
-    usage();
+    usage(TRUE);
     exit(1);
 
   }
@@ -825,6 +927,8 @@ main(int argc, char *argv[])
     stoptime = mktime(&stoptm);
   }
 
+  nstime_set_unset(&block_start);
+
   if (starttime > stoptime) {
     fprintf(stderr, "editcap: start time is after the stop time\n");
     exit(1);
@@ -850,7 +954,7 @@ main(int argc, char *argv[])
       g_free(err_info);
       break;
     }
-    exit(1);
+    exit(2);
 
   }
 
@@ -869,37 +973,6 @@ main(int argc, char *argv[])
     if (out_frame_type == -2)
       out_frame_type = wtap_file_encap(wth);
 
-    if (split_packet_count > 0) {
-      filenamelen = strlen(argv[optind+1]) + 20;
-      filename = (char *) g_malloc(filenamelen);
-      if (!filename) {
-        exit(5);
-      }
-      g_snprintf(filename, (gulong) filenamelen, "%s-%05d", argv[optind+1], 0);
-    } else {
-      if (secs_per_block > 0) {
-        filenamelen = strlen(argv[optind+1]) + 7;
-        filename = (char *) g_malloc(filenamelen);
-        if (!filename) {
-          exit(5);
-          }
-        g_snprintf(filename, (gulong) filenamelen, "%s-%05d", argv[optind+1], block_cnt);
-        }
-      else {
-        filename = 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(1);
-    }
-
     for (i = optind + 2; i < argc; i++)
       if (add_selection(argv[i]) == FALSE)
         break;
@@ -913,30 +986,50 @@ main(int argc, char *argv[])
     }
 
     while (wtap_read(wth, &err, &err_info, &data_offset)) {
+      phdr = wtap_phdr(wth);
 
-      if (secs_per_block > 0) {
-        phdr = wtap_phdr(wth);
+      if (nstime_is_unset(&block_start)) {  /* should only be the first packet */
+        block_start.secs = phdr->ts.secs;
+        block_start.nsecs = phdr->ts.nsecs;
 
-        if (nstime_is_unset(&block_start)) {  /* should only be the first packet */
-          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(2);
 
-        while ((phdr->ts.secs - block_start.secs >  secs_per_block) || 
-            (phdr->ts.secs - block_start.secs == secs_per_block && 
+          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),
+            FALSE /* compressed */, &err);
+        if (pdh == NULL) {  
+          fprintf(stderr, "editcap: Can't open or create %s: %s\n", filename,
+                  wtap_strerror(err));
+          exit(2);
+        }
+      }
+
+      g_assert(filename);
+
+      if (secs_per_block > 0) {
+        while ((phdr->ts.secs - block_start.secs >  secs_per_block) ||
+               (phdr->ts.secs - block_start.secs == secs_per_block &&
                 phdr->ts.nsecs >= block_start.nsecs )) { /* time for the next file */
 
           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_snprintf(filename, (gulong) filenamelen, "%s-%05d",argv[optind+1], ++block_cnt);
+          g_free(filename);
+          filename = fileset_get_filename_by_pattern(block_cnt++, &phdr->ts, fprefix, fsuffix);
+          g_assert(filename);
 
           if (verbose) {
             fprintf(stderr, "Continuing writing in file %s\n", filename);
-            }
+          }
 
           pdh = wtap_dump_open(filename, out_file_type,
              out_frame_type, wtap_snapshot_length(wth), FALSE /* compressed */, &err);
@@ -944,32 +1037,37 @@ 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);
           }
         }
       }
 
-      if (split_packet_count > 0 && (written_count % split_packet_count == 0)) {
-        if (!wtap_dump_close(pdh, &err)) {
+      if (split_packet_count > 0) {
 
-          fprintf(stderr, "editcap: Error writing to %s: %s\n", filename,
-              wtap_strerror(err));
-          exit(1);
-        }
+        /* time for the next file? */
+        if (written_count > 0 && 
+            written_count % split_packet_count == 0) {
+          if (!wtap_dump_close(pdh, &err)) {
+            fprintf(stderr, "editcap: Error writing to %s: %s\n", filename,
+                wtap_strerror(err));
+            exit(2);
+          }
 
-        g_snprintf(filename, (gulong) filenamelen, "%s-%05d",argv[optind+1], count / split_packet_count);
+          g_free(filename);
+          filename = fileset_get_filename_by_pattern(block_cnt++, &phdr->ts, fprefix, fsuffix);
+          g_assert(filename);
 
-        if (verbose) {
-          fprintf(stderr, "Continuing writing in file %s\n", filename);
-        }
-
-        pdh = wtap_dump_open(filename, out_file_type,
-            out_frame_type, wtap_snapshot_length(wth), FALSE /* compressed */, &err);
-        if (pdh == NULL) {
+          if (verbose) {
+            fprintf(stderr, "Continuing writing in file %s\n", filename);
+          }
 
-          fprintf(stderr, "editcap: Can't open or create %s: %s\n", filename,
-              wtap_strerror(err));
-          exit(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);
+          }
         }
       }
 
@@ -1142,13 +1240,16 @@ 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(fprefix);
+    g_free(fsuffix);
+
     if (err != 0) {
       /* Print a message noting that the read failed somewhere along the line. */
       fprintf(stderr,
@@ -1165,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) {