diff options
| author | David Allsopp <david.allsopp@metastack.com> | 2017-02-20 14:41:12 +0100 |
|---|---|---|
| committer | David Allsopp <david.allsopp@metastack.com> | 2017-05-16 19:48:37 +0100 |
| commit | 43e39de99bfd2580735a4f640dbe7d1e569d03fe (patch) | |
| tree | 708d752e9e65c33b5a6db2eb941214b3cae30173 /otherlibs | |
| parent | 946c6eaf5f0f6ab0c832524a0d8c15158cfe9c03 (diff) | |
| download | ocaml-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.c | 32 |
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 */ |
