summaryrefslogtreecommitdiff
path: root/otherlibs
diff options
context:
space:
mode:
authorDavid Allsopp <david.allsopp@metastack.com>2017-02-20 14:41:12 +0100
committerDavid Allsopp <david.allsopp@metastack.com>2017-05-16 19:48:37 +0100
commit43e39de99bfd2580735a4f640dbe7d1e569d03fe (patch)
tree708d752e9e65c33b5a6db2eb941214b3cae30173 /otherlibs
parent946c6eaf5f0f6ab0c832524a0d8c15158cfe9c03 (diff)
downloadocaml-43e39de99bfd2580735a4f640dbe7d1e569d03fe.tar.gz
Ensure timestamps in Windows Unix.stat are UTC
The Microsoft CRT interprets the TZ environment variable, which can affect the conversion of Windows UTC SYSTEMTIME structs to __time64_t with _mktime64 as the Windows API uses the system's timezone setting which could differ from the TZ variable (especially if a native executable is invoked from within Cygwin).
Diffstat (limited to 'otherlibs')
-rw-r--r--otherlibs/win32unix/stat.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/otherlibs/win32unix/stat.c b/otherlibs/win32unix/stat.c
index 1630f99852..90bfc200d6 100644
--- a/otherlibs/win32unix/stat.c
+++ b/otherlibs/win32unix/stat.c
@@ -152,6 +152,8 @@ static int safe_do_stat(int do_lstat, int use_64, char* path, mlsize_t l, HANDLE
HANDLE h;
unsigned short mode;
int is_symlink = 0;
+ char* restore_TZ = NULL;
+ int failed = 0;
if (!path) {
h = fstat;
@@ -258,13 +260,41 @@ static int safe_do_stat(int do_lstat, int use_64, char* path, mlsize_t l, HANDLE
return 0;
}
+ /* PR#7385: ensure CRT is using system timezone */
+ restore_TZ = getenv("TZ");
+ if (restore_TZ && (i = strlen(restore_TZ)) == 0) {
+ restore_TZ = NULL;
+ } else {
+ if (!(restore_TZ = strdup(restore_TZ))) caml_raise_out_of_memory();
+ _putenv("TZ=");
+ }
+ /* It could be that TZ has been cleared but the CRT globals not updated, so
+ * always call _tzset.
+ */
+ _tzset();
+
if (!convert_time(&info.ftLastWriteTime, &res->st_mtime, 0) ||
!convert_time(&info.ftLastAccessTime, &res->st_atime, res->st_mtime) ||
!convert_time(&info.ftCreationTime, &res->st_ctime, res->st_mtime)) {
win32_maperr(GetLastError());
- return 0;
+ failed = 1;
}
+ if (restore_TZ) {
+ char* env = (char*)malloc(i + 4);
+ if (!env) {
+ free(restore_TZ);
+ caml_raise_out_of_memory();
+ }
+ env[0] = 'T'; env[1] = 'Z'; env[2] = '='; env[3] = '\0';
+ _putenv(strcat(env, restore_TZ));
+ free(env);
+ free(restore_TZ);
+ _tzset();
+ }
+
+ if (failed) return 0;
+
/*
* Note MS CRT (still) puts st_nlink = 1 and gives st_ino = 0
*/