From 1cef8e27f4b07296217f8a3b5cbe4ce5e517a09e Mon Sep 17 00:00:00 2001 From: Sijmen Huizenga Date: Sat, 30 Sep 2023 19:05:12 +0200 Subject: [PATCH 1/3] parsre: fix tzone_offset test Resolves a bug that caused 8 of test cases being skipped in test_parser_tzone_offset Signed-off-by: Sijmen Huizenga --- tests/internal/parser.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/internal/parser.c b/tests/internal/parser.c index 6a560db716c..c4e4f235f98 100644 --- a/tests/internal/parser.c +++ b/tests/internal/parser.c @@ -33,15 +33,16 @@ struct tz_check tz_entries_ok[] = { {"+0000", 0}, {"+00:00", 0}, {"+00:59", 3540}, - {"-0600", -21000}, - {"-06:00", -21000}, + {"-0600", -21600}, + {"-06:00", -21600}, + {"Z", 0}, }; struct tz_check tz_entries_error[] = { {"0000", 0}, {"+00:90", 0}, {"--600", 0}, - {"-06:00", -21000}, + {"foo", 0}, }; /* Time Lookup */ @@ -134,16 +135,18 @@ void test_parser_tzone_offset() /* Valid offsets */ for (i = 0; i < sizeof(tz_entries_ok) / sizeof(struct tz_check); i++) { - t = &tz_entries_ok[0]; + t = &tz_entries_ok[i]; + TEST_CASE(t->val); len = strlen(t->val); ret = flb_parser_tzone_offset(t->val, len, &diff); - TEST_CHECK(ret == 0 && diff == t->diff); + TEST_CHECK(ret == 0); + TEST_CHECK_(diff == t->diff, "expected diff %d but got %d", t->diff, diff); } /* Invalid offsets */ for (i = 0; i < sizeof(tz_entries_error) / sizeof(struct tz_check); i++) { - t = &tz_entries_error[0]; + t = &tz_entries_error[i]; len = strlen(t->val); ret = flb_parser_tzone_offset(t->val, len, &diff); From b7ee1e8df5a4aa17a3f4e2ace0bc0bbe6bd75fa0 Mon Sep 17 00:00:00 2001 From: Sijmen Huizenga Date: Sat, 30 Sep 2023 19:09:52 +0200 Subject: [PATCH 2/3] parser: Fix hour validation in timezone offset parsing Signed-off-by: Sijmen Huizenga --- src/flb_parser.c | 5 +++-- tests/internal/parser.c | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/flb_parser.c b/src/flb_parser.c index 4ccecc91b1d..9e6a49233d8 100644 --- a/src/flb_parser.c +++ b/src/flb_parser.c @@ -530,7 +530,8 @@ static int parser_conf_file(const char *cfg, struct flb_cf *cf, name, cfg); goto fconf_early_error; } - + + /* skip_empty_values */ skip_empty = FLB_TRUE; tmp_str = get_parser_key(config, cf, s, "skip_empty_values"); @@ -1040,7 +1041,7 @@ int flb_parser_tzone_offset(const char *str, int len, int *tmdiff) min = ((p[2] - '0') * 10) + (p[3] - '0'); } - if (hour < 0 || hour > 59 || min < 0 || min > 59) { + if (hour < 0 || hour > 23 || min < 0 || min > 59) { return -1; } diff --git a/tests/internal/parser.c b/tests/internal/parser.c index c4e4f235f98..e48925aabbd 100644 --- a/tests/internal/parser.c +++ b/tests/internal/parser.c @@ -33,6 +33,7 @@ struct tz_check tz_entries_ok[] = { {"+0000", 0}, {"+00:00", 0}, {"+00:59", 3540}, + {"+23:59", 86340}, {"-0600", -21600}, {"-06:00", -21600}, {"Z", 0}, @@ -42,6 +43,7 @@ struct tz_check tz_entries_error[] = { {"0000", 0}, {"+00:90", 0}, {"--600", 0}, + {"+24:00", 0}, {"foo", 0}, }; From 33e624f7c46e4e0650b618665f423e8df30c620f Mon Sep 17 00:00:00 2001 From: Sijmen Huizenga Date: Sat, 30 Sep 2023 19:37:55 +0200 Subject: [PATCH 3/3] parser: Support system timezone in Time_Offset Add the 'System' option to Time_Offset that uses the system timezone to compute the UTC offset during startup. As proposed in #593 Signed-off-by: Sijmen Huizenga --- src/flb_parser.c | 21 +++++++++++++++++++++ tests/internal/parser.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/src/flb_parser.c b/src/flb_parser.c index 9e6a49233d8..5737a3e8ff8 100644 --- a/src/flb_parser.c +++ b/src/flb_parser.c @@ -43,6 +43,7 @@ #include #include #include +#include static inline uint32_t digits10(uint64_t v) { if (v < 10) return 1; @@ -993,6 +994,21 @@ int flb_parser_do(struct flb_parser *parser, const char *buf, size_t length, return -1; } +int system_utc_offset(int *tmdiff) +{ +#ifdef _WIN32 + // Adjust the sign to match tm_gmtoff + *tmdiff = -_timezone; + return 0; +#else + time_t currentTime = time(NULL); + struct tm localTime = {0}; + localtime_r(¤tTime, &localTime); + *tmdiff = localTime.tm_gmtoff; + return 0; +#endif +} + /* Given a timezone string, return it numeric offset */ int flb_parser_tzone_offset(const char *str, int len, int *tmdiff) { @@ -1009,6 +1025,11 @@ int flb_parser_tzone_offset(const char *str, int len, int *tmdiff) return 0; } + /* Check system timezones */ + if (*p == 'S') { + return system_utc_offset(tmdiff); + } + /* Unexpected timezone string */ if (*p != '+' && *p != '-') { *tmdiff = 0; diff --git a/tests/internal/parser.c b/tests/internal/parser.c index e48925aabbd..0f803715819 100644 --- a/tests/internal/parser.c +++ b/tests/internal/parser.c @@ -37,6 +37,8 @@ struct tz_check tz_entries_ok[] = { {"-0600", -21600}, {"-06:00", -21600}, {"Z", 0}, + // System is mocked to timezone "HST" is -10 hours + {"System", -36000}, }; struct tz_check tz_entries_error[] = { @@ -126,6 +128,35 @@ int flb_parser_regex_do(struct flb_parser *parser, void **out_buf, size_t *out_size, struct flb_time *out_time); +static char* mock_timezone(char *tz) +{ + char *original_tz = getenv("TZ"); + if (original_tz) { + original_tz = strdup(original_tz); + if (!original_tz) { + perror("Failed to allocate memory for original_tz"); + exit(EXIT_FAILURE); + } + } + + setenv("TZ", tz, 1); + tzset(); + + return original_tz; +} + +static void undo_mock_timezone(char *original_tz) +{ + if (original_tz) { + setenv("TZ", original_tz, 1); + } else { + unsetenv("TZ"); + } + tzset(); + free(original_tz); +} + + /* Parse timezone string and get the offset */ void test_parser_tzone_offset() { @@ -135,6 +166,9 @@ void test_parser_tzone_offset() int diff; struct tz_check *t; + /* Hawaii Standard Time chosen for not having daylight saving time */ + char *original_timezone = mock_timezone("HST"); + /* Valid offsets */ for (i = 0; i < sizeof(tz_entries_ok) / sizeof(struct tz_check); i++) { t = &tz_entries_ok[i]; @@ -154,6 +188,8 @@ void test_parser_tzone_offset() ret = flb_parser_tzone_offset(t->val, len, &diff); TEST_CHECK(ret != 0); } + + undo_mock_timezone(original_timezone); } static void load_json_parsers(struct flb_config *config)