From d71d29666e95a7dcbe145ca7e7ebaf74a1555563 Mon Sep 17 00:00:00 2001 From: James Wahlin Date: Fri, 29 May 2020 11:06:32 -0400 Subject: SERVER-44273 Fix timeZoneInfo file load on Windows (cherry picked from commit 56ef6a8f586e58f2d23911226c7880a7b678e0af) --- .../config_files/good_timezone_info/America/Sao_Paulo | Bin 0 -> 1444 bytes jstests/noPassthrough/parse_zone_info.js | 17 ++++++++++++++++- src/third_party/timelib-2018.01/parse_zoneinfo.c | 11 +++++++++-- 3 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 jstests/libs/config_files/good_timezone_info/America/Sao_Paulo diff --git a/jstests/libs/config_files/good_timezone_info/America/Sao_Paulo b/jstests/libs/config_files/good_timezone_info/America/Sao_Paulo new file mode 100644 index 00000000000..13ff083869a Binary files /dev/null and b/jstests/libs/config_files/good_timezone_info/America/Sao_Paulo differ diff --git a/jstests/noPassthrough/parse_zone_info.js b/jstests/noPassthrough/parse_zone_info.js index 9e9343e020f..c9836de08e3 100644 --- a/jstests/noPassthrough/parse_zone_info.js +++ b/jstests/noPassthrough/parse_zone_info.js @@ -1,4 +1,4 @@ -// Tests the parsing of the timeZoneInfo parameter. +// Tests the parsing of the timeZoneInfo parameter and file use. (function() { // Test that a bad file causes startup to fail. let conn = MongoRunner.runMongod({timeZoneInfo: "jstests/libs/config_files/bad_timezone_info"}); @@ -16,5 +16,20 @@ assert(rawMongoProgramOutput().includes("Error creating service context") || // Test that startup can succeed with a good file. conn = MongoRunner.runMongod({timeZoneInfo: "jstests/libs/config_files/good_timezone_info"}); assert.neq(conn, null, "expected launching mongod with good timezone rules to succeed"); + +// Test that can use file-provided timezones in an expression. +const testDB = conn.getDB("test"); +const coll = testDB.parse_zone_info; +assert.commandWorked(coll.insert({x: new Date()})); +assert.doesNotThrow( + () => coll.aggregate([{$set: {x_parts: {$dateToParts: {date: "$x", timezone: "GMT"}}}}])); +assert.doesNotThrow( + () => coll.aggregate( + [{$set: {x_parts: {$dateToParts: {date: "$x", timezone: "America/Sao_Paulo"}}}}])); + +// Confirm that attempt to use a non-existent timezone in an expression fails. +const err = assert.throws( + () => coll.aggregate([{$set: {x_parts: {$dateToParts: {date: "$x", timezone: "Unknown"}}}}])); +assert.eq(err.code, 40485); MongoRunner.stopMongod(conn); }()); diff --git a/src/third_party/timelib-2018.01/parse_zoneinfo.c b/src/third_party/timelib-2018.01/parse_zoneinfo.c index 875d7564074..977f5abf578 100644 --- a/src/third_party/timelib-2018.01/parse_zoneinfo.c +++ b/src/third_party/timelib-2018.01/parse_zoneinfo.c @@ -52,6 +52,8 @@ # define TIMELIB_DIR_SEPARATOR "/" #endif +#define TIMELIB_NAME_SEPARATOR "/" + /* Filter out some non-tzdata files and the posix/right databases, if * present. */ static int index_filter(const struct dirent *ent) @@ -123,7 +125,12 @@ static char *read_tzfile(const char *directory, const char *timezone, size_t *le return NULL; } + /* O_BINARY is required to properly read the file on windows */ +#ifdef _WIN32 + fd = open(fname, O_RDONLY | O_BINARY); +#else fd = open(fname, O_RDONLY); +#endif free(fname); if (fd == -1) { @@ -257,7 +264,7 @@ static int create_zone_index(const char *directory, timelib_tzdb *db) struct stat st; const char *leaf = ents[count - 1]->d_name; - snprintf(name, sizeof(name), "%s%s%s%s%s", directory, TIMELIB_DIR_SEPARATOR, top, TIMELIB_DIR_SEPARATOR, leaf); + snprintf(name, sizeof(name), "%s%s%s%s%s", directory, TIMELIB_NAME_SEPARATOR, top, TIMELIB_NAME_SEPARATOR, leaf); if (strlen(name) && stat(name, &st) == 0) { /* Name, relative to the zoneinfo prefix. */ @@ -267,7 +274,7 @@ static int create_zone_index(const char *directory, timelib_tzdb *db) root++; } - snprintf(name, sizeof(name), "%s%s%s", root, *root ? TIMELIB_DIR_SEPARATOR : "", leaf); + snprintf(name, sizeof(name), "%s%s%s", root, *root ? TIMELIB_NAME_SEPARATOR : "", leaf); if (S_ISDIR(st.st_mode)) { if (dirstack_top == dirstack_size) { -- cgit v1.2.1