diff options
-rw-r--r-- | lib/pure/os.nim | 22 | ||||
-rw-r--r-- | lib/pure/times.nim | 8 | ||||
-rw-r--r-- | lib/windows/winlean.nim | 11 |
3 files changed, 35 insertions, 6 deletions
diff --git a/lib/pure/os.nim b/lib/pure/os.nim index a77bee99d..255a9a8de 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -329,20 +329,21 @@ proc expandFilename*(filename: string): string {.rtl, extern: "nos$1", c_free(cast[pointer](r)) when defined(Windows): - proc openHandle(path: string, followSymlink=true): Handle = + proc openHandle(path: string, followSymlink=true, writeAccess=false): Handle = var flags = FILE_FLAG_BACKUP_SEMANTICS or FILE_ATTRIBUTE_NORMAL if not followSymlink: flags = flags or FILE_FLAG_OPEN_REPARSE_POINT + let access = if writeAccess: GENERIC_WRITE else: 0'i32 when useWinUnicode: result = createFileW( - newWideCString(path), 0'i32, + newWideCString(path), access, FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, flags, 0 ) else: result = createFileA( - path, 0'i32, + path, access, FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, flags, 0 ) @@ -1654,3 +1655,18 @@ proc isHidden*(path: string): bool = result = (fileName[0] == '.') and (fileName[3] != '.') {.pop.} + +proc setLastModificationTime*(file: string, t: times.Time) = + ## Sets the `file`'s last modification time. `OSError` is raised in case of + ## an error. + when defined(posix): + let unixt = t.toUnix.int + var timevals = [Timeval(tv_sec: unixt), Timeval(tv_sec: unixt)] # [last access, last modification] + if utimes(file, timevals.addr) != 0: raiseOSError(osLastError()) + else: + let h = openHandle(path = file, writeAccess = true) + if h == INVALID_HANDLE_VALUE: raiseOSError(osLastError()) + var ft = t.toWinTime.toFILETIME + let res = setFileTime(h, nil, nil, ft.addr) + discard h.closeHandle + if res == 0'i32: raiseOSError(osLastError()) \ No newline at end of file diff --git a/lib/pure/times.nim b/lib/pure/times.nim index dc216477b..673f0b030 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -191,6 +191,7 @@ const secondsInHour = 60*60 secondsInDay = 60*60*24 minutesInHour = 60 + rateDiff = 10000000'i64 # 100 nsecs # The number of hectonanoseconds between 1601/01/01 (windows epoch) # and 1970/01/01 (unix epoch). epochDiff = 116444736000000000'i64 @@ -371,6 +372,10 @@ proc toUnix*(t: Time): int64 {.benign, tags: [], raises: [], noSideEffect.} = ## Convert ``t`` to a unix timestamp (seconds since ``1970-01-01T00:00:00Z``). t.seconds +proc toWinTime*(t: Time): int64 = + ## Convert ``t`` to a Windows file time (100-nanosecond intervals since ``1601-01-01T00:00:00Z``). + result = t.seconds * rateDiff + epochDiff + proc isLeapYear*(year: int): bool = ## Returns true if ``year`` is a leap year. year mod 4 == 0 and (year mod 100 != 0 or year mod 400 == 0) @@ -1713,9 +1718,6 @@ when not defined(JS): var clocksPerSec {.importc: "CLOCKS_PER_SEC", nodecl.}: int - const - rateDiff = 10000000'i64 # 100 nsecs - proc unixTimeToWinTime*(time: CTime): int64 = ## converts a UNIX `Time` (``time_t``) to a Windows file time result = int64(time) * rateDiff + epochDiff diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim index f40344396..62bc38da9 100644 --- a/lib/windows/winlean.nim +++ b/lib/windows/winlean.nim @@ -1086,3 +1086,14 @@ proc ConvertThreadToFiberEx*(param: pointer, flags: int32): pointer {.stdcall, d proc DeleteFiber*(fiber: pointer): void {.stdcall, discardable, dynlib: "kernel32", importc.} proc SwitchToFiber*(fiber: pointer): void {.stdcall, discardable, dynlib: "kernel32", importc.} proc GetCurrentFiber*(): pointer {.stdcall, importc, header: "Windows.h".} + +proc toFILETIME*(t: int64): FILETIME = + ## Convert the Windows file time timestamp ``t`` to ``FILETIME``. + result = FILETIME(dwLowDateTime: cast[DWORD](t), dwHighDateTime: DWORD(t shr 32)) + +type + LPFILETIME* = ptr FILETIME + +proc setFileTime*(hFile: HANDLE, lpCreationTime: LPFILETIME, + lpLastAccessTime: LPFILETIME, lpLastWriteTime: LPFILETIME): WINBOOL + {.stdcall, dynlib: "kernel32", importc: "SetFileTime".} |