From 5aa41b0f12465e4278f0b36ee4ab5890d5c5de32 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Tue, 1 Oct 2024 16:54:05 +0200 Subject: [PATCH] FEAT: improved file-related time values precision on POSIX platforms and resolved correct creation time on Linux (when possible) resolves: https://github.com/Oldes/Rebol-issues/issues/2626 related to: https://github.com/Oldes/Rebol-issues/issues/2624 --- src/core/p-file.c | 2 +- src/os/posix/dev-file.c | 77 +++++++++++++++++++++++++++++++++++++++-- src/os/posix/host-lib.c | 5 ++- 3 files changed, 80 insertions(+), 4 deletions(-) diff --git a/src/core/p-file.c b/src/core/p-file.c index b003e8b5be..09cfd046f4 100644 --- a/src/core/p-file.c +++ b/src/core/p-file.c @@ -474,7 +474,7 @@ REBINT Mode_Syms[] = { REBINT result, error; REBOOL opened = FALSE; // had to be opened (shortcut case) - //Print("FILE ACTION: %r", Get_Action_Word(action)); + //Debug_Fmt_("FILE ACTION: %r\n", Get_Action_Word(action)); port = Validate_Port_With_Request(port_value, RDI_FILE, &file); diff --git a/src/os/posix/dev-file.c b/src/os/posix/dev-file.c index a3423d14ee..b5f3e5e679 100644 --- a/src/os/posix/dev-file.c +++ b/src/os/posix/dev-file.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -52,6 +51,51 @@ #include "reb-host.h" #include "host-lib.h" +#ifdef TO_LINUX +#include +//#include +#include +#define statx foo +#define statx_timestamp foo_timestamp +struct statx; +struct statx_timestamp; +#include +#undef statx +#undef statx_timestamp + +#define AT_STATX_SYNC_TYPE 0x6000 +#define AT_STATX_SYNC_AS_STAT 0x0000 +#define AT_STATX_FORCE_SYNC 0x2000 +#define AT_STATX_DONT_SYNC 0x4000 + +// Manually define SYS_statx if not present in the system headers +# ifndef SYS_statx +# if defined __aarch64__ || defined __arm__ +# define SYS_statx 397 +# elif defined __alpha__ +# define SYS_statx 522 +# elif defined __i386__ || defined __powerpc64__ +# define SYS_statx 383 +# elif defined __sparc__ +# define SYS_statx 360 +# elif defined __x86_64__ +# define SYS_statx 332 +# else +# warning "SYS_statx not defined for your architecture" +# endif +# endif + +static __attribute__((unused)) +ssize_t statx(int dfd, const char *filename, unsigned flags, unsigned int mask, struct statx *buffer) +{ + return syscall(SYS_statx, dfd, filename, flags, mask, buffer); +} +#else +// stat on non Linux systems +#include +#endif + + #ifndef O_BINARY #define O_BINARY 0 #endif @@ -64,6 +108,7 @@ #define S_IWRITE S_IWUSR #endif + // NOTE: the code below assumes a file id will never by zero. This should // be safe. In posix, zero is stdin, which is handled by dev-stdio.c. @@ -126,6 +171,34 @@ static REBOOL Seek_File_64(REBREQ *file) static int Get_File_Info(REBREQ *file) { +#ifdef SYS_statx + struct statx infox; + if (statx(AT_FDCWD | AT_STATX_FORCE_SYNC, file->file.path, 0, STATX_BASIC_STATS | STATX_BTIME, &infox) == -1) { + goto use_stat; + } + + if (S_ISDIR(infox.stx_mode)) { + SET_FLAG(file->modes, RFM_DIR); + file->file.size = MIN_I64; // using MIN_I64 to notify, that size should be reported as NONE + } + else { + CLR_FLAG(file->modes, RFM_DIR); + file->file.size = infox.stx_size; + } + file->file.modified_time.l = (i32)(infox.stx_mtime.tv_sec); + file->file.accessed_time.l = (i32)(infox.stx_atime.tv_sec); + file->file.modified_time.h = (i32)(infox.stx_mtime.tv_nsec); + file->file.accessed_time.h = (i32)(infox.stx_atime.tv_nsec); + + if (infox.stx_btime.tv_sec) { + file->file.created_time.l = (i32)(infox.stx_btime.tv_sec); + file->file.created_time.h = (i32)(infox.stx_btime.tv_nsec); + } else { + file->file.created_time = file->file.modified_time; + } + return DR_DONE; +#endif +use_stat: struct stat info; if (stat(file->file.path, &info)) { @@ -143,7 +216,7 @@ static int Get_File_Info(REBREQ *file) } file->file.modified_time.l = (i32)(info.st_mtime); file->file.accessed_time.l = (i32)(info.st_atime); - file->file.created_time.l = (i32)(info.st_ctime); + file->file.created_time.l = (i32)(info.st_ctime); return DR_DONE; } diff --git a/src/os/posix/host-lib.c b/src/os/posix/host-lib.c index cd31fd53cb..78ceedd9dc 100644 --- a/src/os/posix/host-lib.c +++ b/src/os/posix/host-lib.c @@ -723,7 +723,10 @@ RL_LIB *RL; // Link back to reb-lib from embedded extensions (like for now: host ** ***********************************************************************/ { - Convert_Date((time_t *)&time->l, dat, 0); + time_t stime; + stime = time->l; + Convert_Date(&stime, dat, 0); + dat->nano = time->h; }