From 12087d1ecb57458dd5ec895f55989e736e7c64ad Mon Sep 17 00:00:00 2001 From: Aleksei Volkov Date: Tue, 29 Aug 2023 22:27:30 +0300 Subject: [PATCH] [ refactor ] Single syscall to get all time attributes of File --- libs/base/System/File/Meta.idr | 137 +++++++++++++++++------------ src/Core/Binary/Prims.idr | 15 ++-- src/Libraries/System/File/Meta.idr | 119 +++++++++++++++++++------ support/c/idris_file.c | 120 ++++++++++--------------- support/c/idris_file.h | 17 ++-- support/c/windows/win_utils.c | 71 +++++---------- support/c/windows/win_utils.h | 6 +- support/js/support_system_file.js | 14 +++ 8 files changed, 278 insertions(+), 221 deletions(-) diff --git a/libs/base/System/File/Meta.idr b/libs/base/System/File/Meta.idr index c16293f18fd..063f63fe4d9 100644 --- a/libs/base/System/File/Meta.idr +++ b/libs/base/System/File/Meta.idr @@ -1,12 +1,20 @@ ||| Functions for accessing file metadata. module System.File.Meta +import Data.String + +import System.FFI + import System.File.Handle import System.File.Support import public System.File.Types %default total +||| Pointer to a structure holding File's time attributes +FileTimePtr : Type +FileTimePtr = AnyPtr + %foreign supportC "idris2_fileSize" "node:lambda:fp=>require('fs').fstatSync(fp.fd).size" prim__fileSize : FilePtr -> PrimIO Int @@ -14,25 +22,33 @@ prim__fileSize : FilePtr -> PrimIO Int %foreign supportC "idris2_fileSize" prim__fPoll : FilePtr -> PrimIO Int -%foreign supportC "idris2_fileAccessTime" -prim__fileAccessTime : FilePtr -> PrimIO Int +%foreign supportC "idris2_fileTime" + "node:support:filetime,support_system_file" +prim__fileTime : FilePtr -> PrimIO FileTimePtr + +%foreign supportC "idris2_filetimeAccessTimeSec" + "node:lambda:ft=>ft.atime_sec" +prim__filetimeAccessTimeSec : FileTimePtr -> PrimIO Int -%foreign supportC "idris2_fileAccessTimeNs" -prim__fileAccessTimeNs : FilePtr -> PrimIO Int +%foreign supportC "idris2_filetimeAccessTimeNsec" + "node:lambda:ft=>ft.atime_nsec" +prim__filetimeAccessTimeNsec : FileTimePtr -> PrimIO Int -%foreign supportC "idris2_fileModifiedTime" - "node:lambda:fp=>require('fs').fstatSync(fp.fd).mtimeMs / 1000" -prim__fileModifiedTime : FilePtr -> PrimIO Int +%foreign supportC "idris2_filetimeModifiedTimeSec" + "node:lambda:ft=>ft.mtime_sec" +prim__filetimeModifiedTimeSec : FileTimePtr -> PrimIO Int -%foreign supportC "idris2_fileModifiedTimeNs" - "node:lambda:fp=>require('fs').fstatSync(fp.fd).mtimeMs * 1000000 % 1000000000" -prim__fileModifiedTimeNs : FilePtr -> PrimIO Int +%foreign supportC "idris2_filetimeModifiedTimeNsec" + "node:lambda:ft=>ft.mtime_nsec" +prim__filetimeModifiedTimeNsec : FileTimePtr -> PrimIO Int -%foreign supportC "idris2_fileStatusTime" -prim__fileStatusTime : FilePtr -> PrimIO Int +%foreign supportC "idris2_filetimeStatusTimeSec" + "node:lambda:ft=>ft.ctime_sec" +prim__filetimeStatusTimeSec : FileTimePtr -> PrimIO Int -%foreign supportC "idris2_fileStatusTimeNs" -prim__fileStatusTimeNs : FilePtr -> PrimIO Int +%foreign supportC "idris2_filetimeStatusTimeNsec" + "node:lambda:ft=>ft.ctime_nsec" +prim__filetimeStatusTimeNsec : FileTimePtr -> PrimIO Int %foreign supportC "idris2_fileIsTTY" "node:lambda:fp=>Number(require('tty').isatty(fp.fd))" @@ -53,59 +69,70 @@ firstExists : HasIO io => List String -> io (Maybe String) firstExists [] = pure Nothing firstExists (x :: xs) = if !(exists x) then pure (Just x) else firstExists xs -||| Get the File's atime. +||| Record that holds timestamps with nanosecond precision +public export +record Timestamp where + constructor MkTimestamp + sec : Int + nsec : Int + export -fileAccessTime : HasIO io => (h : File) -> io (Either FileError Int) -fileAccessTime (FHandle f) - = do res <- primIO (prim__fileAccessTime f) - if res > 0 - then ok res - else returnError +Eq Timestamp where + t == t' = (t.sec == t'.sec) && (t.nsec == t'.nsec) -||| Get the nanosecond part of File's atime. export -fileAccessTimeNs : HasIO io => (h : File) -> io (Either FileError Int) -fileAccessTimeNs (FHandle f) - = do res <- primIO (prim__fileAccessTimeNs f) - if res > 0 - then ok res - else returnError +Ord Timestamp where + t < t' = (t.sec < t'.sec) || (t.sec == t'.sec && t.nsec < t'.nsec) -||| Get the File's mtime. export -fileModifiedTime : HasIO io => (h : File) -> io (Either FileError Int) -fileModifiedTime (FHandle f) - = do res <- primIO (prim__fileModifiedTime f) - if res > 0 - then ok res +Show Timestamp where + show t = "\{show t.sec}.\{padLeft 9 '0' $ show t.nsec}" + +||| Record that holds file's time attributes +public export +record FileTime where + constructor MkFileTime + atime : Timestamp + mtime : Timestamp + ctime : Timestamp + +||| Get File's time attributes +export +fileTime : HasIO io => (h : File) -> io (Either FileError FileTime) +fileTime (FHandle f) + = do res <- primIO (prim__fileTime f) + ft <- parseFileTime res + free res + if ft.atime.sec > 0 + then ok ft else returnError + where + parseFileTime : FileTimePtr -> io FileTime + parseFileTime ft = pure $ MkFileTime { atime = MkTimestamp { sec = !(primIO (prim__filetimeAccessTimeSec ft)) + , nsec = !(primIO (prim__filetimeAccessTimeNsec ft)) + } + , mtime = MkTimestamp { sec = !(primIO (prim__filetimeModifiedTimeSec ft)) + , nsec = !(primIO (prim__filetimeModifiedTimeNsec ft)) + } + , ctime = MkTimestamp { sec = !(primIO (prim__filetimeStatusTimeSec ft)) + , nsec = !(primIO (prim__filetimeStatusTimeNsec ft)) + } + } -||| Get the nanosecond part of File's mtime. +||| Get the File's atime. export -fileModifiedTimeNs : HasIO io => (h : File) -> io (Either FileError Int) -fileModifiedTimeNs (FHandle f) - = do res <- primIO (prim__fileModifiedTimeNs f) - if res > 0 - then ok res - else returnError +fileAccessTime : HasIO io => (h : File) -> io (Either FileError Int) +fileAccessTime h = (fileTime h <&> (.atime.sec)) @{Compose} -||| Get the File's ctime. +||| Get the File's mtime. export -fileStatusTime : HasIO io => (h : File) -> io (Either FileError Int) -fileStatusTime (FHandle f) - = do res <- primIO (prim__fileStatusTime f) - if res > 0 - then ok res - else returnError +fileModifiedTime : HasIO io => (h : File) -> io (Either FileError Int) +fileModifiedTime h = (fileTime h <&> (.mtime.sec)) @{Compose} -||| Get the nanosecond part of File's ctime. +||| Get the File's ctime. export -fileStatusTimeNs : HasIO io => (h : File) -> io (Either FileError Int) -fileStatusTimeNs (FHandle f) - = do res <- primIO (prim__fileStatusTimeNs f) - if res > 0 - then ok res - else returnError +fileStatusTime : HasIO io => (h : File) -> io (Either FileError Int) +fileStatusTime h = (fileTime h <&> (.ctime.sec)) @{Compose} ||| Get the File's size. export diff --git a/src/Core/Binary/Prims.idr b/src/Core/Binary/Prims.idr index a9787eb5f55..adb22d210ba 100644 --- a/src/Core/Binary/Prims.idr +++ b/src/Core/Binary/Prims.idr @@ -12,7 +12,7 @@ import Data.String import Data.Vect import Libraries.Data.PosMap -import Libraries.System.File.Meta as L -- Remove after release 0.7.0 +import public Libraries.System.File.Meta as L -- Remove after release 0.7.0 import public Libraries.Utils.Binary import public Libraries.Utils.String @@ -442,18 +442,15 @@ TTC Nat where ||| Get a file's modified time. If it doesn't exist, return 0 (UNIX Epoch) export -modTime : String -> Core (Int, Int) +modTime : String -> Core L.Timestamp modTime fname = do Right f <- coreLift $ openFile fname Read - | Left err => pure (0, 0) -- Beginning of Time :) - Right s <- coreLift $ fileModifiedTime f + | Left err => pure $ MkTimestamp 0 0 -- Beginning of Time :) + Right t <- coreLift $ L.fileTime f | Left err => do coreLift $ closeFile f - pure (0, 0) - Right ns <- coreLift $ L.fileModifiedTimeNs f - | Left err => do coreLift $ closeFile f - pure (0, 0) + pure $ MkTimestamp 0 0 coreLift $ closeFile f - pure (s, ns) + pure $ t.mtime export hashFileWith : Maybe String -> String -> Core (Maybe String) diff --git a/src/Libraries/System/File/Meta.idr b/src/Libraries/System/File/Meta.idr index 5836791ba7a..a1fe07cdc30 100644 --- a/src/Libraries/System/File/Meta.idr +++ b/src/Libraries/System/File/Meta.idr @@ -1,45 +1,110 @@ module Libraries.System.File.Meta +import Data.String + +import System.FFI + import System.File.Handle import System.File.Support import public System.File.Types %default total -%foreign supportC "idris2_fileAccessTimeNs" -prim__fileAccessTimeNs : FilePtr -> PrimIO Int +||| Pointer to a structure holding File's time attributes +FileTimePtr : Type +FileTimePtr = AnyPtr + +%foreign supportC "idris2_fileTime" + "node:support:filetime,support_system_file" +prim__fileTime : FilePtr -> PrimIO FileTimePtr + +%foreign supportC "idris2_filetimeAccessTimeSec" + "node:lambda:ft=>ft.atime_sec" +prim__filetimeAccessTimeSec : FileTimePtr -> PrimIO Int + +%foreign supportC "idris2_filetimeAccessTimeNsec" + "node:lambda:ft=>ft.atime_nsec" +prim__filetimeAccessTimeNsec : FileTimePtr -> PrimIO Int -%foreign supportC "idris2_fileModifiedTimeNs" - "node:lambda:fp=>require('fs').fstatSync(fp.fd).mtimeMs * 1000000 % 1000000000" -prim__fileModifiedTimeNs : FilePtr -> PrimIO Int +%foreign supportC "idris2_filetimeModifiedTimeSec" + "node:lambda:ft=>ft.mtime_sec" +prim__filetimeModifiedTimeSec : FileTimePtr -> PrimIO Int -%foreign supportC "idris2_fileStatusTimeNs" -prim__fileStatusTimeNs : FilePtr -> PrimIO Int +%foreign supportC "idris2_filetimeModifiedTimeNsec" + "node:lambda:ft=>ft.mtime_nsec" +prim__filetimeModifiedTimeNsec : FileTimePtr -> PrimIO Int + +%foreign supportC "idris2_filetimeStatusTimeSec" + "node:lambda:ft=>ft.ctime_sec" +prim__filetimeStatusTimeSec : FileTimePtr -> PrimIO Int + +%foreign supportC "idris2_filetimeStatusTimeNsec" + "node:lambda:ft=>ft.ctime_nsec" +prim__filetimeStatusTimeNsec : FileTimePtr -> PrimIO Int + +||| Record that holds timestamps with nanosecond precision +public export +record Timestamp where + constructor MkTimestamp + sec : Int + nsec : Int -||| Get the nanosecond part of File's atime. export -fileAccessTimeNs : HasIO io => (h : File) -> io (Either FileError Int) -fileAccessTimeNs (FHandle f) - = do res <- primIO (prim__fileAccessTimeNs f) - if res > 0 - then ok res - else returnError +Eq Timestamp where + t == t' = (t.sec == t'.sec) && (t.nsec == t'.nsec) -||| Get the nanosecond part of File's mtime. export -fileModifiedTimeNs : HasIO io => (h : File) -> io (Either FileError Int) -fileModifiedTimeNs (FHandle f) - = do res <- primIO (prim__fileModifiedTimeNs f) - if res > 0 - then ok res - else returnError +Ord Timestamp where + t < t' = (t.sec < t'.sec) || (t.sec == t'.sec && t.nsec < t'.nsec) -||| Get the nanosecond part of File's ctime. export -fileStatusTimeNs : HasIO io => (h : File) -> io (Either FileError Int) -fileStatusTimeNs (FHandle f) - = do res <- primIO (prim__fileStatusTimeNs f) - if res > 0 - then ok res +Show Timestamp where + show t = "\{show t.sec}.\{padLeft 9 '0' $ show t.nsec}" + +||| Record that holds file's time attributes +public export +record FileTime where + constructor MkFileTime + atime : Timestamp + mtime : Timestamp + ctime : Timestamp + +||| Get File's time attributes +export +fileTime : HasIO io => (h : File) -> io (Either FileError FileTime) +fileTime (FHandle f) + = do res <- primIO (prim__fileTime f) + ft <- parseFileTime res + free res + if ft.atime.sec > 0 + then ok ft else returnError + where + parseFileTime : FileTimePtr -> io FileTime + parseFileTime ft = pure $ MkFileTime { atime = MkTimestamp { sec = !(primIO (prim__filetimeAccessTimeSec ft)) + , nsec = !(primIO (prim__filetimeAccessTimeNsec ft)) + } + , mtime = MkTimestamp { sec = !(primIO (prim__filetimeModifiedTimeSec ft)) + , nsec = !(primIO (prim__filetimeModifiedTimeNsec ft)) + } + , ctime = MkTimestamp { sec = !(primIO (prim__filetimeStatusTimeSec ft)) + , nsec = !(primIO (prim__filetimeStatusTimeNsec ft)) + } + } + +||| Get the File's atime. +export +fileAccessTime : HasIO io => (h : File) -> io (Either FileError Int) +fileAccessTime h = (fileTime h <&> (.atime.sec)) @{Compose} + +||| Get the File's mtime. +export +fileModifiedTime : HasIO io => (h : File) -> io (Either FileError Int) +fileModifiedTime h = (fileTime h <&> (.mtime.sec)) @{Compose} + +||| Get the File's ctime. +export +fileStatusTime : HasIO io => (h : File) -> io (Either FileError Int) +fileStatusTime h = (fileTime h <&> (.ctime.sec)) @{Compose} + diff --git a/support/c/idris_file.c b/support/c/idris_file.c index d43d60311e5..b66964aa289 100644 --- a/support/c/idris_file.c +++ b/support/c/idris_file.c @@ -177,39 +177,54 @@ size_t idris2_writeBufferData(FILE *h, const char *buffer, size_t loc, int idris2_eof(FILE *f) { return feof(f); } -int idris2_fileAccessTime(FILE *f) { - int fd = idris2_getFileNo(f); +struct filetime { + int atime_sec; + int atime_nsec; + int mtime_sec; + int mtime_nsec; + int ctime_sec; + int ctime_nsec; +}; - struct stat buf; - if (fstat(fd, &buf) == 0) { - return buf.st_atime; - } else { - return -1; - } -} +struct filetime *idris2_fileTime(FILE *f) { + struct filetime *ft = malloc(sizeof(*ft)); -int idris2_fileAccessTimeNs(FILE *f) { #ifdef _WIN32 - int64_t sec, nsec; - if (win32_getFileAccessTime(f, &sec, &nsec)) { - return -1; + if (win32_getFileTimes(f, &ft->atime_sec, &ft->atime_nsec, &ft->mtime_sec, + &ft->mtime_nsec, &ft->ctime_sec, &ft->ctime_nsec_)) { + ft->atime_sec = -1; + return ft; } - return nsec; + + return ft; #else int fd = idris2_getFileNo(f); struct stat buf; - if (fstat(fd, &buf) == 0) { + if (fstat(fd, &buf)) { + ft->atime_sec = -1; + return ft; + } + + ft->atime_sec = buf.st_atime; + ft->mtime_sec = buf.st_mtime; + ft->ctime_sec = buf.st_ctime; + #if defined(__MACH__) || defined(__APPLE__) - return buf.st_atimespec.tv_nsec; + ft->atime_nsec = buf.st_atimespec.tv_nsec; + ft->mtime_nsec = buf.st_mtimespec.tv_nsec; + ft->ctime_nsec = buf.st_ctimespec.tv_nsec; #elif (_POSIX_VERSION >= 200809L) || defined(__FreeBSD__) - return buf.st_atim.tv_nsec; + ft->atime_nsec = buf.st_atim.tv_nsec; + ft->mtime_nsec = buf.st_mtim.tv_nsec; + ft->ctime_nsec = buf.st_ctim.tv_nsec; #else - return 0; + ft->atime_nsec = 0; + ft->mtime_nsec = 0; + ft->ctime_nsec = 0; #endif - } else { - return -1; - } + + return ft; #endif } @@ -224,65 +239,24 @@ int idris2_fileModifiedTime(FILE *f) { } } -int idris2_fileModifiedTimeNs(FILE *f) { -#ifdef _WIN32 - int64_t sec, nsec; - if (win32_getFileModifiedTime(f, &sec, &nsec)) { - return -1; - } - return nsec; -#else - int fd = idris2_getFileNo(f); +int idris2_filetimeAccessTimeSec(struct filetime *ft) { return ft->atime_sec; } - struct stat buf; - if (fstat(fd, &buf) == 0) { -#if defined(__MACH__) || defined(__APPLE__) - return buf.st_mtimespec.tv_nsec; -#elif (_POSIX_VERSION >= 200809L) || defined(__FreeBSD__) - return buf.st_mtim.tv_nsec; -#else - return 0; -#endif - } else { - return -1; - } -#endif +int idris2_filetimeAccessTimeNsec(struct filetime *ft) { + return ft->atime_nsec; } -int idris2_fileStatusTime(FILE *f) { - int fd = idris2_getFileNo(f); +int idris2_filetimeModifiedTimeSec(struct filetime *ft) { + return ft->mtime_sec; +} - struct stat buf; - if (fstat(fd, &buf) == 0) { - return buf.st_ctime; - } else { - return -1; - } +int idris2_filetimeModifiedTimeNsec(struct filetime *ft) { + return ft->mtime_nsec; } -int idris2_fileStatusTimeNs(FILE *f) { -#ifdef _WIN32 - int64_t sec, nsec; - if (win32_getFileStatusTime(f, &sec, &nsec)) { - return -1; - } - return nsec; -#else - int fd = idris2_getFileNo(f); +int idris2_filetimeStatusTimeSec(struct filetime *ft) { return ft->ctime_sec; } - struct stat buf; - if (fstat(fd, &buf) == 0) { -#if defined(__MACH__) || defined(__APPLE__) - return buf.st_ctimespec.tv_nsec; -#elif (_POSIX_VERSION >= 200809L) || defined(__FreeBSD__) - return buf.st_ctim.tv_nsec; -#else - return 0; -#endif - } else { - return -1; - } -#endif +int idris2_filetimeStatusTimeNsec(struct filetime *ft) { + return ft->ctime_nsec; } int idris2_fileIsTTY(FILE *f) { diff --git a/support/c/idris_file.h b/support/c/idris_file.h index cf9df9e697b..2e9e4d70fd2 100644 --- a/support/c/idris_file.h +++ b/support/c/idris_file.h @@ -39,13 +39,18 @@ size_t idris2_writeBufferData(FILE *h, const char *buffer, size_t loc, size_t len); int idris2_eof(FILE *f); -int idris2_fileAccessTime(FILE *f); -int idris2_fileAccessTimeNs(FILE *f); + +struct filetime; + +struct filetime *idris2_fileTime(FILE *f); int idris2_fileModifiedTime(FILE *f); -int idris2_fileModifiedTimeNs(FILE *f); -int idris2_fileStatusTime(FILE *f); -int idris2_fileStatusTimeNs(FILE *f); -int idris2_fileIsTTY(FILE *f); + +int idris2_filetimeAccessTimeSec(struct filetime *f); +int idris2_filetimeAccessTimeNsec(struct filetime *f); +int idris2_filetimeModifiedTimeSec(struct filetime *f); +int idris2_filetimeModifiedTimeNsec(struct filetime *f); +int idris2_filetimeStatusTimeSec(struct filetime *f); +int idris2_filetimeStatusTimeNsec(struct filetime *f); FILE *idris2_stdin(); FILE *idris2_stdout(); diff --git a/support/c/windows/win_utils.c b/support/c/windows/win_utils.c index b6ecca3b5c0..65fa8723eca 100644 --- a/support/c/windows/win_utils.c +++ b/support/c/windows/win_utils.c @@ -165,63 +165,38 @@ long win32_getNProcessors() { int win32_getFileNo(FILE *f) { return _fileno(f); } -int win32_getFileAccessTime(FILE *f, int64_t *sec, int64_t *nsec) { +int win32_getFileTime(FILE *f, int64_t *atime_sec, int64_t *atime_nsec, + int64_t *mtime_sec, int64_t *mtime_nsec, + int64_t *ctime_sec, int64_t *ctime_nsec) { HANDLE wh = (HANDLE)_get_osfhandle(_fileno(f)); if (wh == INVALID_HANDLE_VALUE) { return -1; } - FILETIME ft; - if (GetFileTime(wh, NULL, &ft, NULL)) { - ULARGE_INTEGER t; - t.HighPart = ft.dwHighDateTime; - t.LowPart = ft.dwLowDateTime; - - *nsec = (t.QuadPart % 10000000) * 100; - *sec = t.QuadPart / 10000000; - *sec -= 11644473600; // LDAP epoch to Unix epoch - return 0; - } else { - return -1; - } -} + FILETIME atime, mtime, ctime; -int win32_getFileModifiedTime(FILE *f, int64_t *sec, int64_t *nsec) { - HANDLE wh = (HANDLE)_get_osfhandle(_fileno(f)); - if (wh == INVALID_HANDLE_VALUE) { - return -1; - } + if (GetFileTime(wh, &ctime, &atime, &mtime)) { + ULARGE_INTEGER at, mt, ct; - FILETIME ft; - if (GetFileTime(wh, NULL, NULL, &ft)) { - ULARGE_INTEGER t; - t.HighPart = ft.dwHighDateTime; - t.LowPart = ft.dwLowDateTime; - - *nsec = (t.QuadPart % 10000000) * 100; - *sec = t.QuadPart / 10000000; - *sec -= 11644473600; // LDAP epoch to Unix epoch - return 0; - } else { - return -1; - } -} + at.HighPart = atime.dwHighDateTime; + at.LowPart = atime.dwLowDateTime; + mt.HighPart = mtime.dwHighDateTime; + mt.LowPart = mtime.dwLowDateTime; + ct.HighPart = ctime.dwHighDateTime; + ct.LowPart = ctime.dwLowDateTime; -int win32_getFileStatusTime(FILE *f, int64_t *sec, int64_t *nsec) { - HANDLE wh = (HANDLE)_get_osfhandle(_fileno(f)); - if (wh == INVALID_HANDLE_VALUE) { - return -1; - } + *atime_sec = at.QuadPart / 10000000; + *atime_sec -= 11644473600; + *atime_nsec = (at.QuadPart % 10000000) * 100; + + *mtime_sec = mt.QuadPart / 10000000; + *mtime_sec -= 11644473600; + *mtime_nsec = (mt.QuadPart % 10000000) * 100; + + *ctime_sec = ct.QuadPart / 10000000; + *ctime_sec -= 11644473600; + *ctime_nsec = (ct.QuadPart % 10000000) * 100; - FILETIME ft; - if (GetFileTime(wh, &ft, NULL, NULL)) { - ULARGE_INTEGER t; - t.HighPart = ft.dwHighDateTime; - t.LowPart = ft.dwLowDateTime; - - *nsec = (t.QuadPart % 10000000) * 100; - *sec = t.QuadPart / 10000000; - *sec -= 11644473600; // LDAP epoch to Unix epoch return 0; } else { return -1; diff --git a/support/c/windows/win_utils.h b/support/c/windows/win_utils.h index 6c0885d31d6..11557a55f19 100644 --- a/support/c/windows/win_utils.h +++ b/support/c/windows/win_utils.h @@ -16,7 +16,7 @@ int win32_getPID(); long win32_getNProcessors(); int win32_getFileNo(FILE *); -int win32_getFileAccessTime(FILE *f, int64_t *sec, int64_t *nsec); -int win32_getFileModifiedTime(FILE *f, int64_t *sec, int64_t *nsec); -int win32_getFileStatusTime(FILE *f, int64_t *sec, int64_t *nsec); +int win32_getFileTime(FILE *f, int64_t *atime_sec, int64_t *atime_nsec, + int64_t *mtime_sec, int64_t *mtime_nsec, + int64_t *ctime_sec, int64_t *ctime_nsec); int win32_isTTY(int fd); diff --git a/support/js/support_system_file.js b/support/js/support_system_file.js index 9118cb44135..0436959667a 100644 --- a/support/js/support_system_file.js +++ b/support/js/support_system_file.js @@ -167,3 +167,17 @@ function support_system_file_pclose (file_ptr) { support_system_file_removeFile(name) return exit_code } + +function support_system_file_filetime(file_ptr) { + const {fd, name, exit_code} = file_ptr + const st = support_system_file_fs.fstatSync(fd) + const ft = { + atime_sec : _truncInt32(Math.trunc(st.atimeMs / 1000)), + atime_nsec : st.atimeMs * 1000000 % 1000000000, + mtime_sec : _truncInt32(Math.trunc(st.mtimeMs / 1000)), + mtime_nsec : st.mtimeMs * 1000000 % 1000000000, + ctime_sec : _truncInt32(Math.trunc(st.ctimeMs / 1000)), + ctime_nsec : st.mtimeMs * 1000000 % 1000000000 + }; + return ft +}