X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=reordercap.c;h=7bd0c8962d55566a2f513c97d1a88224c3c27fef;hb=94ea9af46ce1c751b340dcccc8b07976a3f48b7c;hp=40b3c53263e10404390a6158fd01486c9adcf1f2;hpb=0aa59a3df0d225dc3f7d341785910caa56718799;p=metze%2Fwireshark%2Fwip.git diff --git a/reordercap.c b/reordercap.c index 40b3c53263..7bd0c8962d 100644 --- a/reordercap.c +++ b/reordercap.c @@ -1,5 +1,5 @@ /* Reorder the frames from an input dump file, and write to output dump file. - * Martin Mathieson + * Martin Mathieson and Jakub Jawadzki * * $Id$ * @@ -23,42 +23,49 @@ * */ +#include "config.h" + #include #include #include -#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif #include "wtap.h" +#ifndef HAVE_GETOPT +#include "wsutil/wsgetopt.h" +#endif /* Show command-line usage */ -/* TODO: add reoder list length as an optional param? */ static void usage(void) { - printf("usage: reorder \n"); + fprintf(stderr, "Reordercap %s" +#ifdef SVNVERSION + " (" SVNVERSION " from " SVNPATH ")" +#endif + "\n", VERSION); + fprintf(stderr, "Reorder timestamps of input file frames into output file.\n"); + fprintf(stderr, "See http://www.wireshark.org for more information.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Usage: reordercap [options] \n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -n don't write to output file if the input file is ordered.\n"); } /* Remember where this frame was in the file */ typedef struct FrameRecord_t { gint64 offset; guint32 length; + guint num; struct wtap_nstime time; - - /* List item pointers */ - struct FrameRecord_t *prev; - struct FrameRecord_t *next; } FrameRecord_t; -/* This is pretty big, but I don't mind waiting a few seconds */ -#define MAX_REORDER_LIST_LENGTH 3000 -static int g_FrameRecordCount; - -/* This is the list of frames, sorted by time. Later frames at the front, earlier - ones at the end */ -static FrameRecord_t *g_FrameListHead; -static FrameRecord_t *g_FrameListTail; - /**************************************************/ /* Debugging only */ @@ -66,207 +73,79 @@ static FrameRecord_t *g_FrameListTail; /* Enable this symbol to see debug output */ /* #define REORDER_DEBUG */ -#ifdef REORDER_DEBUG -static void ReorderListDebugPrint(void) -{ - int count=0; - FrameRecord_t *tmp = g_FrameListHead; - printf("\n"); - while (tmp != NULL) { - printf("%6d: offset=%6llu, length=%6u, time=%lu:%u", - ++count, tmp->offset, tmp->length, tmp->time.secs, tmp->time.nsecs); - - if (tmp == g_FrameListHead) { - printf(" (head)"); - } - if (tmp == g_FrameListTail) { - printf(" (tail)\n"); - } - printf("\n"); - - tmp = tmp->next; - } - printf("\n"); -} -#else -#define ReorderListDebugPrint() -#endif - #ifdef REORDER_DEBUG #define DEBUG_PRINT printf #else #define DEBUG_PRINT(...) #endif - /**************************************************/ -/* Counting frames that weren't in order */ -static int g_OutOfOrder = 0; - -/* Is time1 later than time2? */ -static gboolean isLaterTime(struct wtap_nstime time1, - struct wtap_nstime time2) -{ - if (time1.secs > time2.secs) { - return TRUE; - } - if (time1.secs == time2.secs) { - return (time1.nsecs > time2.nsecs); - } - else { - return FALSE; - } -} - -/* Is the reorder list empty? */ -static gboolean ReorderListEmpty(void) -{ - return (g_FrameRecordCount == 0); -} - -/* Is the reorder list full? */ -static gboolean ReorderListFull(void) -{ - return (g_FrameRecordCount >= MAX_REORDER_LIST_LENGTH); -} - -/* Add a new frame to the reorder list */ -/* Adding later ones to the front */ -static void ReorderListAdd(gint64 offset, guint32 length, - struct wtap_nstime time) +static void +frame_write(FrameRecord_t *frame, wtap *wth, wtap_dumper *pdh) { - FrameRecord_t *tmp; - FrameRecord_t *newFrameRecord = g_malloc(sizeof(FrameRecord_t)); - - /* Populate fields */ - DEBUG_PRINT("\nAdded with offset=%06llu, length=%05u, secs=%lu, nsecs=%d\n", - offset, length, time.secs, time.nsecs); - newFrameRecord->offset = offset; - newFrameRecord->length = length; - newFrameRecord->time = time; - - /* We will definitely add it below, so inc counter */ - g_FrameRecordCount++; - - /* First time, this will be the head */ - if (g_FrameListHead == NULL) { - DEBUG_PRINT("this item will be head - only item\n"); - g_FrameListHead = newFrameRecord; - newFrameRecord->prev = NULL; - newFrameRecord->next = NULL; - g_FrameListTail = newFrameRecord; - return; - } - - /* Look for the place in the list where this item fits */ - tmp = g_FrameListHead; - while (tmp != NULL) { - if (isLaterTime(time, tmp->time)) { - DEBUG_PRINT("Time was Later, writing before element\n"); - - /* Insert newFrameRecord *before* tmp */ - - /* Fix up prev item */ - if (tmp == g_FrameListHead) { - /* Inserting before existing head */ - g_FrameListHead = newFrameRecord; - } - else { - /* Our prev is tmps old prev */ - newFrameRecord->prev = tmp->prev; - /* Its next points to us */ - newFrameRecord->prev->next = newFrameRecord; - } - - /* Fix up next item */ - newFrameRecord->next = tmp; - tmp->prev = newFrameRecord; - - g_OutOfOrder++; - - return; - } - - /* Didn't find an item to insert in front of */ - if (tmp->next == NULL) { - DEBUG_PRINT("Reached the end of the list, so insert here\n"); - - /* We are the new last item */ - tmp->next = newFrameRecord; - newFrameRecord->prev = tmp; - newFrameRecord->next = NULL; - g_FrameListTail = newFrameRecord; - - return; - } - else { - /* Move onto the next item */ - DEBUG_PRINT("Time was earlier, move to next position\n"); - tmp = tmp->next; - } - } -} - -/* Dump the earliest item in the reorder list to the output file, and pop it */ -static void ReorderListDumpEarliest(wtap *wth, wtap_dumper *pdh) -{ - union wtap_pseudo_header pseudo_header; int err; gchar *errinfo; - const struct wtap_pkthdr *phdr; - guint8 buf[16000]; - struct wtap_pkthdr new_phdr; + struct wtap_pkthdr phdr; + guint8 buf[65535]; - FrameRecord_t *prev_tail = g_FrameListTail; - - DEBUG_PRINT("\nDumping frame (offset=%llu, length=%u) (%u items in list)\n", - g_FrameListHead->offset, g_FrameListHead->length, - g_FrameRecordCount); + DEBUG_PRINT("\nDumping frame (offset=%" G_GINT64_MODIFIER "u, length=%u)\n", + frame->offset, frame->length); /* Re-read the first frame from the stored location */ wtap_seek_read(wth, - g_FrameListTail->offset, - &pseudo_header, + frame->offset, + &phdr, buf, - g_FrameListTail->length, + frame->length, &err, &errinfo); - DEBUG_PRINT("re-read: err is %u, buf is (%s)\n", err, buf); - - /* Get packet header */ - phdr = wtap_phdr(wth); + DEBUG_PRINT("re-read: err is %d, buf is (%s)\n", err, buf); /* Copy, and set length and timestamp from item. */ - memcpy((void*)&new_phdr, phdr, sizeof(struct wtap_pkthdr)); - new_phdr.len = g_FrameListTail->length; - new_phdr.ts.secs = g_FrameListTail->time.secs; - new_phdr.ts.nsecs = g_FrameListTail->time.nsecs; + /* TODO: remove when wtap_seek_read() will read phdr */ + phdr.ts = frame->time; /* Dump frame to outfile */ - if (!wtap_dump(pdh, &new_phdr, &pseudo_header, buf, &err)) { + if (!wtap_dump(pdh, &phdr, buf, &err)) { printf("Error (%s) writing frame to outfile\n", wtap_strerror(err)); exit(1); } +} - /* Now remove this (the last/earliest) item from the list */ - if (g_FrameListTail->prev == NULL) { - g_FrameListTail = NULL; - g_FrameListHead = NULL; - } - else { - /* 2nd last item is now last */ - g_FrameListTail->prev->next = NULL; - g_FrameListTail = g_FrameListTail->prev; - } +/* Comparing timestamps between 2 frames. + -1 if (t1 < t2) + 0 if (t1 == t2) + 1 if (t1 > t2) +*/ +static int +frames_compare(gconstpointer a, gconstpointer b) +{ + const FrameRecord_t *frame1 = *(const FrameRecord_t **) a; + const FrameRecord_t *frame2 = *(const FrameRecord_t **) b; - /* And free the struct */ - g_free(prev_tail); - g_FrameRecordCount--; + const struct wtap_nstime *time1 = &frame1->time; + const struct wtap_nstime *time2 = &frame2->time; - DEBUG_PRINT("Frame written, %u remaining\n", g_FrameRecordCount); -} + if (time1->secs > time2->secs) + return 1; + if (time1->secs < time2->secs) + return -1; + + /* time1->secs == time2->secs */ + if (time1->nsecs > time2->nsecs) + return 1; + if (time1->nsecs < time2->nsecs) + return -1; + /* time1->nsecs == time2->nsecs */ + + if (frame1->num > frame2->num) + return 1; + if (frame1->num < frame2->num) + return -1; + return 0; +} /********************************************************************/ @@ -280,14 +159,35 @@ int main(int argc, char *argv[]) gchar *err_info; gint64 data_offset; const struct wtap_pkthdr *phdr; - guint32 read_count = 0; + guint wrong_order_count = 0; + gboolean write_output_regardless = TRUE; + guint i; - /* 1st arg is infile, 2nd arg is outfile */ + GPtrArray *frames; + FrameRecord_t *prevFrame = NULL; + + int opt; + int file_count; char *infile; char *outfile; - if (argc == 3) { - infile = argv[1]; - outfile = argv[2]; + + /* Process the options first */ + while ((opt = getopt(argc, argv, "n")) != -1) { + switch (opt) { + case 'n': + write_output_regardless = FALSE; + break; + case '?': + usage(); + exit(1); + } + } + + /* Remaining args are file names */ + file_count = argc - optind; + if (file_count == 2) { + infile = argv[optind]; + outfile = argv[optind+1]; } else { usage(); @@ -300,7 +200,6 @@ int main(int argc, char *argv[]) printf("reorder: Can't open %s: %s\n", infile, wtap_strerror(err)); exit(1); } - DEBUG_PRINT("file_type is %u\n", wtap_file_type(wth)); /* Open outfile (same filetype/encap as input file) */ @@ -310,41 +209,59 @@ int main(int argc, char *argv[]) exit(1); } + /* Allocate the array of frame pointers. */ + frames = g_ptr_array_new(); /* Read each frame from infile */ while (wtap_read(wth, &err, &err_info, &data_offset)) { - read_count++; + FrameRecord_t *newFrameRecord; + phdr = wtap_phdr(wth); - /* Add it to the reordering list */ - ReorderListAdd(data_offset, phdr->len, phdr->ts); - ReorderListDebugPrint(); + newFrameRecord = g_slice_new(FrameRecord_t); + newFrameRecord->num = frames->len + 1; + newFrameRecord->offset = data_offset; + newFrameRecord->length = phdr->len; + newFrameRecord->time = phdr->ts; - /* If/when the list gets full, dump the earliest item out */ - if (ReorderListFull()) { - DEBUG_PRINT("List is full, dumping earliest!\n"); + if (prevFrame && frames_compare(&newFrameRecord, &prevFrame) < 0) { + wrong_order_count++; + } - /* Write out the earliest one */ - ReorderListDumpEarliest(wth, pdh); - ReorderListDebugPrint(); + g_ptr_array_add(frames, newFrameRecord); + prevFrame = newFrameRecord; + } + printf("%u frames, %u out of order\n", frames->len, wrong_order_count); + + /* Sort the frames */ + if (wrong_order_count > 0) { + g_ptr_array_sort(frames, frames_compare); + } + + /* Write out each sorted frame in turn */ + for (i = 0; i < frames->len; i++) { + FrameRecord_t *frame = (FrameRecord_t *)frames->pdata[i]; + + /* Avoid writing if already sorted and configured to */ + if (write_output_regardless || (wrong_order_count > 0)) { + frame_write(frame, wth, pdh); } + g_slice_free(FrameRecord_t, frame); } - /* Flush out the remaining (ordered) frames */ - while (!ReorderListEmpty()) { - ReorderListDumpEarliest(wth, pdh); - ReorderListDebugPrint(); + if (!write_output_regardless && (wrong_order_count == 0)) { + printf("Not writing output file because input file is already in order!\n"); } + /* Free the whole array */ + g_ptr_array_free(frames, TRUE); + /* Close outfile */ if (!wtap_dump_close(pdh, &err)) { - printf("reorder: Error closing %s: %s\n", outfile, wtap_strerror(err)); + printf("Error closing %s: %s\n", outfile, wtap_strerror(err)); exit(1); } - /* Write how many frames, and how many were out of order */ - printf("%u frames, %u out of order\n", read_count, g_OutOfOrder); - /* Finally, close infile */ wtap_fdclose(wth);