From 32cef4c11b4705eaa22fb08254ab5a0181eee12d Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Sun, 4 May 2025 22:55:27 +0200 Subject: [PATCH] Fix change_times on Windows and simplify time handling in stat --- core/os/os2/file_windows.odin | 16 ++++------------ core/os/os2/stat_windows.odin | 34 +++++++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/core/os/os2/file_windows.odin b/core/os/os2/file_windows.odin index 068f2979f..94e51a14c 100644 --- a/core/os/os2/file_windows.odin +++ b/core/os/os2/file_windows.odin @@ -813,19 +813,11 @@ _chtimes :: proc(name: string, atime, mtime: time.Time) -> Error { defer close(f) return _fchtimes(f, atime, mtime) } + _fchtimes :: proc(f: ^File, atime, mtime: time.Time) -> Error { if f == nil || f.impl == nil { return nil } - d: win32.BY_HANDLE_FILE_INFORMATION - if !win32.GetFileInformationByHandle(_handle(f), &d) { - return _get_platform_error() - } - - to_windows_time :: #force_inline proc(t: time.Time) -> win32.LARGE_INTEGER { - // a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC) - return win32.LARGE_INTEGER(time.time_to_unix_nano(t) * 100 + 116444736000000000) - } atime, mtime := atime, mtime if time.time_to_unix_nano(atime) < time.time_to_unix_nano(mtime) { @@ -833,9 +825,9 @@ _fchtimes :: proc(f: ^File, atime, mtime: time.Time) -> Error { } info: win32.FILE_BASIC_INFO - info.LastAccessTime = to_windows_time(atime) - info.LastWriteTime = to_windows_time(mtime) - if !win32.SetFileInformationByHandle(_handle(f), .FileBasicInfo, &info, size_of(d)) { + info.LastAccessTime = time_as_filetime(atime) + info.LastWriteTime = time_as_filetime(mtime) + if !win32.SetFileInformationByHandle(_handle(f), .FileBasicInfo, &info, size_of(info)) { return _get_platform_error() } return nil diff --git a/core/os/os2/stat_windows.odin b/core/os/os2/stat_windows.odin index bf690bcd9..8c3d4a610 100644 --- a/core/os/os2/stat_windows.odin +++ b/core/os/os2/stat_windows.odin @@ -239,14 +239,30 @@ _file_type_mode_from_file_attributes :: proc(file_attributes: win32.DWORD, h: wi return } +// a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC) +time_as_filetime :: #force_inline proc(t: time.Time) -> (ft: win32.LARGE_INTEGER) { + win := u64(t._nsec / 100) + 116444736000000000 + return win32.LARGE_INTEGER(win) +} + +filetime_as_time_li :: #force_inline proc(ft: win32.LARGE_INTEGER) -> (t: time.Time) { + return {_nsec=(i64(ft) - 116444736000000000) * 100} +} + +filetime_as_time_ft :: #force_inline proc(ft: win32.FILETIME) -> (t: time.Time) { + return filetime_as_time_li(win32.LARGE_INTEGER(ft.dwLowDateTime) + win32.LARGE_INTEGER(ft.dwHighDateTime) << 32) +} + +filetime_as_time :: proc{filetime_as_time_ft, filetime_as_time_li} + _file_info_from_win32_file_attribute_data :: proc(d: ^win32.WIN32_FILE_ATTRIBUTE_DATA, name: string, allocator: runtime.Allocator) -> (fi: File_Info, e: Error) { fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow) type, mode := _file_type_mode_from_file_attributes(d.dwFileAttributes, nil, 0) fi.type = type fi.mode |= mode - fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)) - fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime)) - fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime)) + fi.creation_time = filetime_as_time(d.ftCreationTime) + fi.modification_time = filetime_as_time(d.ftLastWriteTime) + fi.access_time = filetime_as_time(d.ftLastAccessTime) fi.fullpath, e = full_path_from_name(name, allocator) fi.name = basename(fi.fullpath) return @@ -257,9 +273,9 @@ _file_info_from_win32_find_data :: proc(d: ^win32.WIN32_FIND_DATAW, name: string type, mode := _file_type_mode_from_file_attributes(d.dwFileAttributes, nil, 0) fi.type = type fi.mode |= mode - fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)) - fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime)) - fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime)) + fi.creation_time = filetime_as_time(d.ftCreationTime) + fi.modification_time = filetime_as_time(d.ftLastWriteTime) + fi.access_time = filetime_as_time(d.ftLastAccessTime) fi.fullpath, e = full_path_from_name(name, allocator) fi.name = basename(fi.fullpath) return @@ -289,9 +305,9 @@ _file_info_from_get_file_information_by_handle :: proc(path: string, h: win32.HA type, mode := _file_type_mode_from_file_attributes(d.dwFileAttributes, h, 0) fi.type = type fi.mode |= mode - fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)) - fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime)) - fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime)) + fi.creation_time = filetime_as_time(d.ftCreationTime) + fi.modification_time = filetime_as_time(d.ftLastWriteTime) + fi.access_time = filetime_as_time(d.ftLastAccessTime) return fi, nil }