Have a common routine to convert FILETIME to nstime_t.
authorGuy Harris <guy@alum.mit.edu>
Mon, 20 Apr 2015 20:41:07 +0000 (13:41 -0700)
committerGuy Harris <guy@alum.mit.edu>
Mon, 20 Apr 2015 20:41:38 +0000 (20:41 +0000)
We had several copies of that code; put it into a filetime_to_nstime()
routine in wsutil, and call that common routine instead.

Change-Id: I1eb5579c36c129ff8d23f9212285ab3f63be0f43
Reviewed-on: https://code.wireshark.org/review/8142
Reviewed-by: Guy Harris <guy@alum.mit.edu>
epan/dissectors/packet-windows-common.c
wiretap/netmon.c
wsutil/nstime.c
wsutil/nstime.h

index 4d19ce83679477cc94b4b39691bb6867c5b5e1a5..fd0d302f25620ebf782c38eb36d9cf217f24264b 100644 (file)
@@ -1109,20 +1109,6 @@ value_string_ext ms_country_codes_ext = VALUE_STRING_EXT_INIT(ms_country_codes);
  /*module_t* module;*/
  /*pref_t* sid_display_hex;*/
 
-#ifndef TIME_T_MIN
-#define TIME_T_MIN ((time_t) ((time_t)0 < (time_t) -1 ? (time_t) 0 \
-                   : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1)))
-#endif
-#ifndef TIME_T_MAX
-#define TIME_T_MAX ((time_t) (~ (time_t) 0 - TIME_T_MIN))
-#endif
-
-/*
- * Number of seconds between the UN*X epoch (January 1, 1970, 00:00:00 GMT)
- * and the Windows NT epoch (January 1, 1601, 00:00:00 "GMT").
- */
-#define TIME_FIXUP_CONSTANT G_GUINT64_CONSTANT(11644473600)
-
 /*
  * Translate an 8-byte FILETIME value, given as the upper and lower 32 bits,
  * to an "nstime_t".
@@ -1147,12 +1133,6 @@ static gboolean
 nt_time_to_nstime(guint32 filetime_high, guint32 filetime_low, nstime_t *tv, gboolean onesec_resolution)
 {
        guint64 d;
-       gint64 secs;
-       int nsecs;
-       /* The next two lines are a fix needed for the
-           broken SCO compiler. JRA. */
-       time_t l_time_min = TIME_T_MIN;
-       time_t l_time_max = TIME_T_MAX;
 
        if (filetime_high == 0)
                return FALSE;
@@ -1163,23 +1143,7 @@ nt_time_to_nstime(guint32 filetime_high, guint32 filetime_low, nstime_t *tv, gbo
                d *= 10000000;
        }
 
-       /* Split into seconds and nanoseconds. */
-       secs = d / 10000000;
-       nsecs = (int)((d % 10000000)*100);
-
-       /* Now adjust the seconds. */
-       secs -= TIME_FIXUP_CONSTANT;
-
-       if (!(l_time_min <= secs && secs <= l_time_max))
-               return FALSE;
-
-       /*
-        * Get the time as seconds and nanoseconds.
-        */
-       tv->secs = (time_t) secs;
-       tv->nsecs = nsecs;
-
-       return TRUE;
+       return filetime_to_nstime(tv, d);
 }
 
 int
index 9a4ad1e9990bb9413d77a23a13cb4db8254d2a7c..73bc49259a7207aa162d792c510255d7b04b43b0 100644 (file)
@@ -441,20 +441,6 @@ typedef enum {
        RETRY
 } process_record_retval;
 
-/*
- * Number of seconds between the UN*X epoch (January 1, 1970, 00:00:00 GMT)
- * and the Windows NT epoch (January 1, 1601, 00:00:00 "GMT").
- */
-#define TIME_FIXUP_CONSTANT G_GUINT64_CONSTANT(11644473600)
-
-#ifndef TIME_T_MIN
-#define TIME_T_MIN ((time_t) ((time_t)0 < (time_t) -1 ? (time_t) 0 \
-                   : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1)))
-#endif
-#ifndef TIME_T_MAX
-#define TIME_T_MAX ((time_t) (~ (time_t) 0 - TIME_T_MIN))
-#endif
-
 static process_record_retval
 netmon_process_record(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr,
     Buffer *buf, int *err, gchar **err_info)
@@ -747,43 +733,20 @@ netmon_process_record(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr,
 
                phdr->pkt_encap = pkt_encap;
                if (netmon->version_major > 2 || netmon->version_minor > 2) {
-                       /*
-                        * This code is based on the Samba code:
-                        *
-                        *      Unix SMB/Netbios implementation.
-                        *      Version 1.9.
-                        *      time handling functions
-                        *      Copyright (C) Andrew Tridgell 1992-1998
-                        */
                        guint64 d;
-                       gint64 utcsecs;
-                       /* The next two lines are a fix needed for the
-                           broken SCO compiler. JRA. */
-                       time_t l_time_min = TIME_T_MIN;
-                       time_t l_time_max = TIME_T_MAX;
 
                        d = pletoh64(trlr.trlr_2_3.utc_timestamp);
 
-                       /* Split into seconds and nanoseconds. */
-                       utcsecs = d / 10000000;
-                       nsecs = (int)((d % 10000000)*100);
-
-                       /* Now adjust the seconds. */
-                       utcsecs -= TIME_FIXUP_CONSTANT;
-
-                       if (!(l_time_min <= secs && secs <= l_time_max)) {
-                               *err = WTAP_ERR_BAD_FILE;
-                               *err_info = g_strdup_printf("netmon: time stamp outside supported range");
-                               return FAILURE;
-                       }
-
                        /*
                         * Get the time as seconds and nanoseconds.
                         * and overwrite the time stamp obtained
                         * from the record header.
                         */
-                       phdr->ts.secs = (time_t) utcsecs;
-                       phdr->ts.nsecs = nsecs;
+                       if (!filetime_to_nstime(&phdr->ts, d)) {
+                               *err = WTAP_ERR_BAD_FILE;
+                               *err_info = g_strdup_printf("netmon: time stamp outside supported range");
+                               return FAILURE;
+                       }
                }
        }
 
index 439f31a7833baa288b513c0017a516bac623e378..ff6626abc1b738dc540b11268eb8d3cfe2abe1ba 100644 (file)
@@ -186,6 +186,82 @@ double nstime_to_sec(const nstime_t *nstime)
     return ((double)nstime->secs + (double)nstime->nsecs/1000000000);
 }
 
+/*
+ * Number of seconds between the UN*X epoch (January 1, 1970, 00:00:00 GMT)
+ * and the Windows NT epoch (January 1, 1601 in the proleptic Gregorian
+ * calendar, 00:00:00 "GMT")
+ *
+ * This is
+ *
+ *     369*365.25*24*60*60-(3*24*60*60+6*60*60)
+ *
+ * 1970-1601 is 369; 365.25 is the average length of a year in days,
+ * including leap years.
+ *
+ * 3 days are subtracted because 1700, 1800, and 1900 were not leap
+ * years, as, while they're all evenly divisible by 4, they're also
+ * evently divisible by 100, but not evently divisible by 400, so
+ * we need to compensate for using the average length of a year in
+ * days, which assumes a leap year every 4 years, *including* every
+ * 100 years.
+ *
+ * I'm not sure what the extra 6 hours are that are being subtracted.  
+ */
+#define TIME_FIXUP_CONSTANT G_GUINT64_CONSTANT(11644473600)
+
+#ifndef TIME_T_MIN
+#define TIME_T_MIN ((time_t) ((time_t)0 < (time_t) -1 ? (time_t) 0 \
+                   : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1)))
+#endif
+#ifndef TIME_T_MAX
+#define TIME_T_MAX ((time_t) (~ (time_t) 0 - TIME_T_MIN))
+#endif
+
+/*
+ * function: filetime_to_nstime
+ * converts a Windows FILETIME value to an nstime_t
+ * returns TRUE if the conversion succeeds, FALSE if it doesn't
+ * (for example, with a 32-bit time_t, the time overflows or
+ * underflows time_t)
+ */
+gboolean
+filetime_to_nstime(nstime_t *nstime, guint64 filetime)
+{
+    /*
+     * This code is based on the Samba code:
+     *
+     *  Unix SMB/Netbios implementation.
+     *  Version 1.9.
+     *  time handling functions
+     *  Copyright (C) Andrew Tridgell 1992-1998
+     */
+    gint64 secs;
+    int nsecs;
+    /* The next two lines are a fix needed for the
+       broken SCO compiler. JRA. */
+    time_t l_time_min = TIME_T_MIN;
+    time_t l_time_max = TIME_T_MAX;
+
+    /* Split into seconds and nanoseconds. */
+    secs = filetime / 10000000;
+    nsecs = (int)((filetime % 10000000)*100);
+
+    /* Now adjust the seconds. */
+    secs -= TIME_FIXUP_CONSTANT;
+
+    if (!(l_time_min <= secs && secs <= l_time_max)) {
+        /* The result won't fit in a time_t */
+        return FALSE;
+    }
+
+    /*
+     * Get the time as seconds and nanoseconds.
+     */
+    nstime->secs = (time_t) secs;
+    nstime->nsecs = nsecs;
+    return TRUE;
+}
+
 /*
  * Editor modelines
  *
index a74457c8b6a269a5f791d63b91efed88ee3d4067..c72daa19c600a5c526e5900009722099dbd4a0cf 100644 (file)
@@ -102,6 +102,10 @@ WS_DLL_PUBLIC double nstime_to_msec(const nstime_t *nstime);
 /** converts nstime to double, time base is seconds */
 WS_DLL_PUBLIC double nstime_to_sec(const nstime_t *nstime);
 
+/** converts Windows FILETIME to nstime, returns TRUE on success,
+    FALSE on failure */
+WS_DLL_PUBLIC gboolean filetime_to_nstime(nstime_t *nstime, guint64 filetime);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */