From 26cd9f5930ade9df43ff105215a0f941c8aa39f1 Mon Sep 17 00:00:00 2001 From: Timothy Stack Date: Tue, 22 Nov 2016 08:38:45 -0800 Subject: [PATCH] [ptime] make sure the full time stamp is matched Fixes #389 Fixes #390 --- src/Makefile.am | 4 ++++ src/lnav_util.cc | 6 ++++-- src/lnav_util.hh | 5 +++++ src/logfile_sub_source.cc | 2 +- src/logfile_sub_source.hh | 2 +- src/ptimec.hh | 16 +++++++++++----- src/view_curses.hh | 2 +- test/formats/timestamp/format.json | 6 +++++- test/logfile_epoch.1 | 2 ++ test/test_logfile.sh | 8 ++++++++ 10 files changed, 42 insertions(+), 11 deletions(-) create mode 100644 test/logfile_epoch.1 diff --git a/src/Makefile.am b/src/Makefile.am index 4725bb15..1061a49a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -38,12 +38,16 @@ init-sql.c: bin2c TIME_FORMATS = \ "@%@" \ "%Y-%m-%d %H:%M:%S" \ + "%Y-%m-%d %H:%M:%S%z" \ "%Y-%m-%d %H:%M" \ "%Y-%m-%dT%H:%M:%S.%f%z" \ "%y-%m-%dT%H:%M:%S.%f%z" \ "%Y-%m-%dT%H:%M:%SZ" \ "%Y-%m-%dT%H:%M:%S" \ + "%Y-%m-%dT%H:%M:%S%z" \ "%Y/%m/%d %H:%M:%S" \ + "%Y/%m/%d %H:%M:%S %z" \ + "%Y/%m/%d %H:%M:%S%z" \ "%Y/%m/%d %H:%M" \ "%a %b %d %H:%M:%S %Y" \ "%a %b %d %H:%M:%S %Z %Y" \ diff --git a/src/lnav_util.cc b/src/lnav_util.cc index 45636e56..abbc1163 100644 --- a/src/lnav_util.cc +++ b/src/lnav_util.cc @@ -547,7 +547,8 @@ const char *date_time_scanner::scan(const char *time_dest, tm_out->et_tm.tm_zone = NULL; } #endif - if (func(tm_out, time_dest, off, time_len)) { + if (func(tm_out, time_dest, off, time_len) && + (time_dest[off] == '.' || time_dest[off] == ',' || off == time_len)) { retval = &time_dest[off]; if (tm_out->et_tm.tm_year < 70) { @@ -577,7 +578,8 @@ const char *date_time_scanner::scan(const char *time_dest, tm_out->et_tm.tm_zone = NULL; } #endif - if (ptime_fmt(time_fmt[curr_time_fmt], tm_out, time_dest, off, time_len)) { + if (ptime_fmt(time_fmt[curr_time_fmt], tm_out, time_dest, off, time_len) && + (time_dest[off] == '.' || time_dest[off] == ',' || off == time_len)) { retval = &time_dest[off]; if (tm_out->et_tm.tm_year < 70) { tm_out->et_tm.tm_year = 80; diff --git a/src/lnav_util.hh b/src/lnav_util.hh index 31251ff2..bbb68ee5 100644 --- a/src/lnav_util.hh +++ b/src/lnav_util.hh @@ -293,6 +293,11 @@ struct date_time_scanner { * requested time falls outside of a fifteen minute range. */ void to_localtime(time_t t, struct exttm &tm_out) { + if (t < (24 * 60 * 60)) { + // Don't convert and risk going past the epoch. + return; + } + if (t < this->dts_local_offset_valid || t >= this->dts_local_offset_expiry) { time_t new_gmt; diff --git a/src/logfile_sub_source.cc b/src/logfile_sub_source.cc index 68a8d444..a816fe40 100644 --- a/src/logfile_sub_source.cc +++ b/src/logfile_sub_source.cc @@ -291,7 +291,7 @@ void logfile_sub_source::text_attrs_for_line(textview_curses &lv, } if (this->lss_token_shift_size) { - shift_string_attrs(value_out, this->lss_token_shift_start, + shift_string_attrs(value_out, this->lss_token_shift_start + 1, this->lss_token_shift_size); } diff --git a/src/logfile_sub_source.hh b/src/logfile_sub_source.hh index a060a290..f14082a9 100644 --- a/src/logfile_sub_source.hh +++ b/src/logfile_sub_source.hh @@ -125,7 +125,7 @@ public: this->lss_min_log_time.tv_usec != 0); }; - void set_min_log_time(struct timeval &tv) { + void set_min_log_time(const struct timeval &tv) { this->lss_min_log_time = tv; }; diff --git a/src/ptimec.hh b/src/ptimec.hh index 8571ee3a..683f0714 100644 --- a/src/ptimec.hh +++ b/src/ptimec.hh @@ -667,10 +667,16 @@ inline void ftime_y(char *dst, off_t &off_inout, ssize_t len, const struct exttm inline bool ptime_z(struct exttm *dst, const char *str, off_t &off_inout, ssize_t len) { - PTIME_CONSUME(5, { + int consume_amount = 5; + + if ((off_inout + 6) <= len && str[off_inout + 3] == ':') { + consume_amount = 6; + } + PTIME_CONSUME(consume_amount, { long sign; long hours; long mins; + int skip_colon = (consume_amount == 6) ? 1 : 0; if (str[off_inout] == '+') { sign = 1; @@ -683,11 +689,11 @@ inline bool ptime_z(struct exttm *dst, const char *str, off_t &off_inout, ssize_ } hours = ( - (str[off_inout + 0] - '0') * 10 + - (str[off_inout + 1] - '0') * 1) * 60 * 60; + (str[off_inout + 1] - '0') * 10 + + (str[off_inout + 2] - '0') * 1) * 60 * 60; mins = ( - (str[off_inout + 2] - '0') * 10 + - (str[off_inout + 3] - '0') * 1) * 60; + (str[off_inout + skip_colon + 3] - '0') * 10 + + (str[off_inout + skip_colon + 4] - '0') * 1) * 60; dst->et_gmtoff = sign * (hours + mins); #ifdef HAVE_STRUCT_TM_TM_ZONE dst->et_tm.tm_gmtoff = sign * (hours + mins); diff --git a/src/view_curses.hh b/src/view_curses.hh index a657422b..a908f051 100644 --- a/src/view_curses.hh +++ b/src/view_curses.hh @@ -317,7 +317,7 @@ inline void shift_string_attrs(string_attrs_t &sa, int32_t start, int32_t amount for (string_attrs_t::iterator iter = sa.begin(); iter != sa.end(); ++iter) { struct line_range *existing_lr = &iter->sa_range; - if (existing_lr->lr_start > start) { + if (existing_lr->lr_start >= start) { existing_lr->lr_start += amount; } if (existing_lr->lr_end != -1 && start < existing_lr->lr_end) { diff --git a/test/formats/timestamp/format.json b/test/formats/timestamp/format.json index 9cd476fb..86545f8c 100644 --- a/test/formats/timestamp/format.json +++ b/test/formats/timestamp/format.json @@ -4,10 +4,14 @@ "regex": { "std": { "pattern": "^(?\\d+) (?.*)$" + }, + "non_epoch": { + "pattern": "^(?\\d+-\\d+-\\d+ \\d+:\\d+:\\d+\\.\\d+) (?.*)$" } }, "timestamp-format" : [ - "%i" + "%i", + "%Y-%m-%d %H:%M:%S.%f" ], "sample": [ { diff --git a/test/logfile_epoch.1 b/test/logfile_epoch.1 new file mode 100644 index 00000000..645f0517 --- /dev/null +++ b/test/logfile_epoch.1 @@ -0,0 +1,2 @@ +2015-04-09 19:58:07.123000 Hello, World! +2015-04-09 19:58:07.456000 Goodbye, World! diff --git a/test/test_logfile.sh b/test/test_logfile.sh index 24dd5e87..b52f8ebc 100644 --- a/test/test_logfile.sh +++ b/test/test_logfile.sh @@ -166,6 +166,14 @@ Apr 10 02:58:07 2015 -- 456 EOF +run_test ./drive_logfile -t -f epoch_log ${srcdir}/logfile_epoch.1 + +check_output "epoch_log timestamp interpreted incorrectly?" <