mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
Use higher time resolution when available in os.nim (#7709)
This commit is contained in:
committed by
Andreas Rumpf
parent
440212a154
commit
05b447374b
@@ -82,6 +82,14 @@ const
|
||||
# Special types
|
||||
type Sighandler = proc (a: cint) {.noconv.}
|
||||
|
||||
const StatHasNanoseconds* = defined(linux) or defined(freebsd) or
|
||||
defined(openbsd) or defined(dragonfly) ## \
|
||||
## Boolean flag that indicates if the system supports nanosecond time
|
||||
## resolution in the fields of ``Stat``. Note that the nanosecond based fields
|
||||
## (``Stat.st_atim``, ``Stat.st_mtim`` and ``Stat.st_ctim``) can be accessed
|
||||
## without checking this flag, because this module defines fallback procs
|
||||
## when they are not available.
|
||||
|
||||
# Platform specific stuff
|
||||
|
||||
when defined(linux) and defined(amd64):
|
||||
@@ -92,9 +100,9 @@ else:
|
||||
# There used to be this name in posix.nim a long time ago, not sure why!
|
||||
{.deprecated: [cSIG_HOLD: SIG_HOLD].}
|
||||
|
||||
when not defined(macosx) and not defined(android):
|
||||
when StatHasNanoseconds:
|
||||
proc st_atime*(s: Stat): Time {.inline.} =
|
||||
## Second-granularity time of last access
|
||||
## Second-granularity time of last access.
|
||||
result = s.st_atim.tv_sec
|
||||
proc st_mtime*(s: Stat): Time {.inline.} =
|
||||
## Second-granularity time of last data modification.
|
||||
@@ -102,6 +110,16 @@ when not defined(macosx) and not defined(android):
|
||||
proc st_ctime*(s: Stat): Time {.inline.} =
|
||||
## Second-granularity time of last status change.
|
||||
result = s.st_ctim.tv_sec
|
||||
else:
|
||||
proc st_atim*(s: Stat): TimeSpec {.inline.} =
|
||||
## Nanosecond-granularity time of last access.
|
||||
result.tv_sec = s.st_atime
|
||||
proc st_mtim*(s: Stat): TimeSpec {.inline.} =
|
||||
## Nanosecond-granularity time of last data modification.
|
||||
result.tv_sec = s.st_mtime
|
||||
proc st_ctim*(s: Stat): TimeSpec {.inline.} =
|
||||
## Nanosecond-granularity time of last data modification.
|
||||
result.tv_sec = s.st_ctime
|
||||
|
||||
when hasAioH:
|
||||
proc aio_cancel*(a1: cint, a2: ptr Taiocb): cint {.importc, header: "<aio.h>".}
|
||||
|
||||
@@ -215,14 +215,14 @@ type
|
||||
## For a typed memory object, the length in bytes.
|
||||
## For other file types, the use of this field is
|
||||
## unspecified.
|
||||
when defined(macosx) or defined(android):
|
||||
st_atime*: Time ## Time of last access.
|
||||
st_mtime*: Time ## Time of last data modification.
|
||||
st_ctime*: Time ## Time of last status change.
|
||||
else:
|
||||
when StatHasNanoseconds:
|
||||
st_atim*: Timespec ## Time of last access.
|
||||
st_mtim*: Timespec ## Time of last data modification.
|
||||
st_ctim*: Timespec ## Time of last status change.
|
||||
else:
|
||||
st_atime*: Time ## Time of last access.
|
||||
st_mtime*: Time ## Time of last data modification.
|
||||
st_ctime*: Time ## Time of last status change.
|
||||
st_blksize*: Blksize ## A file system-specific preferred I/O block size
|
||||
## for this object. In some file system types, this
|
||||
## may vary from file to file.
|
||||
|
||||
@@ -23,6 +23,10 @@ when defined(windows):
|
||||
import winlean
|
||||
elif defined(posix):
|
||||
import posix
|
||||
|
||||
proc toTime(ts: Timespec): times.Time {.inline.} =
|
||||
result = initTime(ts.tv_sec.int64, ts.tv_nsec.int)
|
||||
|
||||
else:
|
||||
{.error: "OS module not ported to your operating system!".}
|
||||
|
||||
@@ -186,7 +190,7 @@ proc getLastModificationTime*(file: string): times.Time {.rtl, extern: "nos$1".}
|
||||
when defined(posix):
|
||||
var res: Stat
|
||||
if stat(file, res) < 0'i32: raiseOSError(osLastError())
|
||||
return fromUnix(res.st_mtime.int64)
|
||||
result = res.st_mtim.toTime
|
||||
else:
|
||||
var f: WIN32_FIND_DATA
|
||||
var h = findFirstFile(file, f)
|
||||
@@ -199,7 +203,7 @@ proc getLastAccessTime*(file: string): times.Time {.rtl, extern: "nos$1".} =
|
||||
when defined(posix):
|
||||
var res: Stat
|
||||
if stat(file, res) < 0'i32: raiseOSError(osLastError())
|
||||
return fromUnix(res.st_atime.int64)
|
||||
result = res.st_atim.toTime
|
||||
else:
|
||||
var f: WIN32_FIND_DATA
|
||||
var h = findFirstFile(file, f)
|
||||
@@ -216,7 +220,7 @@ proc getCreationTime*(file: string): times.Time {.rtl, extern: "nos$1".} =
|
||||
when defined(posix):
|
||||
var res: Stat
|
||||
if stat(file, res) < 0'i32: raiseOSError(osLastError())
|
||||
return fromUnix(res.st_ctime.int64)
|
||||
result = res.st_ctim.toTime
|
||||
else:
|
||||
var f: WIN32_FIND_DATA
|
||||
var h = findFirstFile(file, f)
|
||||
@@ -228,10 +232,13 @@ proc fileNewer*(a, b: string): bool {.rtl, extern: "nos$1".} =
|
||||
## Returns true if the file `a` is newer than file `b`, i.e. if `a`'s
|
||||
## modification time is later than `b`'s.
|
||||
when defined(posix):
|
||||
result = getLastModificationTime(a) - getLastModificationTime(b) >= DurationZero
|
||||
# Posix's resolution sucks so, we use '>=' for posix.
|
||||
# If we don't have access to nanosecond resolution, use '>='
|
||||
when not StatHasNanoseconds:
|
||||
result = getLastModificationTime(a) >= getLastModificationTime(b)
|
||||
else:
|
||||
result = getLastModificationTime(a) > getLastModificationTime(b)
|
||||
else:
|
||||
result = getLastModificationTime(a) - getLastModificationTime(b) > DurationZero
|
||||
result = getLastModificationTime(a) > getLastModificationTime(b)
|
||||
|
||||
proc getCurrentDir*(): string {.rtl, extern: "nos$1", tags: [].} =
|
||||
## Returns the `current working directory`:idx:.
|
||||
@@ -1494,7 +1501,7 @@ type
|
||||
|
||||
template rawToFormalFileInfo(rawInfo, path, formalInfo): untyped =
|
||||
## Transforms the native file info structure into the one nim uses.
|
||||
## 'rawInfo' is either a 'TBY_HANDLE_FILE_INFORMATION' structure on Windows,
|
||||
## 'rawInfo' is either a 'BY_HANDLE_FILE_INFORMATION' structure on Windows,
|
||||
## or a 'Stat' structure on posix
|
||||
when defined(Windows):
|
||||
template merge(a, b): untyped = a or (b shl 32)
|
||||
@@ -1520,7 +1527,6 @@ template rawToFormalFileInfo(rawInfo, path, formalInfo): untyped =
|
||||
if (rawInfo.dwFileAttributes and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32:
|
||||
formalInfo.kind = succ(result.kind)
|
||||
|
||||
|
||||
else:
|
||||
template checkAndIncludeMode(rawMode, formalMode: untyped) =
|
||||
if (rawInfo.st_mode and rawMode) != 0'i32:
|
||||
@@ -1528,9 +1534,9 @@ template rawToFormalFileInfo(rawInfo, path, formalInfo): untyped =
|
||||
formalInfo.id = (rawInfo.st_dev, rawInfo.st_ino)
|
||||
formalInfo.size = rawInfo.st_size
|
||||
formalInfo.linkCount = rawInfo.st_Nlink.BiggestInt
|
||||
formalInfo.lastAccessTime = fromUnix(rawInfo.st_atime.int64)
|
||||
formalInfo.lastWriteTime = fromUnix(rawInfo.st_mtime.int64)
|
||||
formalInfo.creationTime = fromUnix(rawInfo.st_ctime.int64)
|
||||
formalInfo.lastAccessTime = rawInfo.st_atim.toTime
|
||||
formalInfo.lastWriteTime = rawInfo.st_mtim.toTime
|
||||
formalInfo.creationTime = rawInfo.st_ctim.toTime
|
||||
|
||||
result.permissions = {}
|
||||
checkAndIncludeMode(S_IRUSR, fpUserRead)
|
||||
@@ -1644,7 +1650,9 @@ proc setLastModificationTime*(file: string, t: times.Time) =
|
||||
## an error.
|
||||
when defined(posix):
|
||||
let unixt = posix.Time(t.toUnix)
|
||||
var timevals = [Timeval(tv_sec: unixt), Timeval(tv_sec: unixt)] # [last access, last modification]
|
||||
let micro = convert(Nanoseconds, Microseconds, t.nanosecond)
|
||||
var timevals = [Timeval(tv_sec: unixt, tv_usec: micro),
|
||||
Timeval(tv_sec: unixt, tv_usec: micro)] # [last access, last modification]
|
||||
if utimes(file, timevals.addr) != 0: raiseOSError(osLastError())
|
||||
else:
|
||||
let h = openHandle(path = file, writeAccess = true)
|
||||
|
||||
@@ -42,6 +42,7 @@ Raises
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
'''
|
||||
"""
|
||||
# test os path creation, iteration, and deletion
|
||||
@@ -129,3 +130,12 @@ echo fileExists("../dest/a/b/file.txt")
|
||||
|
||||
echo fileExists("../dest/a/b/c/fileC.txt")
|
||||
removeDir("../dest")
|
||||
|
||||
# Test get/set modification times
|
||||
# Should support at least microsecond resolution
|
||||
import times
|
||||
let tm = fromUnix(0) + 100.microseconds
|
||||
writeFile("a", "")
|
||||
setLastModificationTime("a", tm)
|
||||
echo getLastModificationTime("a") == tm
|
||||
removeFile("a")
|
||||
Reference in New Issue
Block a user