summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Wahlin <james@mongodb.com>2020-05-29 11:06:32 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-06-17 20:43:53 +0000
commitd71d29666e95a7dcbe145ca7e7ebaf74a1555563 (patch)
treeb1a5002c6497f0559ffafa211e83790035f1f7a2
parente141d191fce0176fbaaafb91d8eb5e127c8b25ed (diff)
downloadmongo-d71d29666e95a7dcbe145ca7e7ebaf74a1555563.tar.gz
SERVER-44273 Fix timeZoneInfo file load on Windows
(cherry picked from commit 56ef6a8f586e58f2d23911226c7880a7b678e0af)
-rw-r--r--jstests/libs/config_files/good_timezone_info/America/Sao_Paulobin0 -> 1444 bytes
-rw-r--r--jstests/noPassthrough/parse_zone_info.js17
-rw-r--r--src/third_party/timelib-2018.01/parse_zoneinfo.c11
3 files changed, 25 insertions, 3 deletions
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
--- /dev/null
+++ b/jstests/libs/config_files/good_timezone_info/America/Sao_Paulo
Binary files 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) {