Hi, I noticed that apr_stat() on macOS gives only a resolution of seconds for mtime/ctime/atime while running tests of Subversion on macOS. However, according to man page of stat(2) [1], it provides a resolution of nanoseconds for mtime/ctime/atime.
[[[ Process 62313 launched: '/tmp/stat' (x86_64) Process 62313 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 frame #0: 0x0000000100003e65 stat`main(argc=1, argv=<unavailable>) at stat.c:14:9 [opt] 11 apr_finfo_t finfo; 12 stat(filename, &statbuf); 13 apr_stat(&finfo, filename, 0, NULL); -> 14 printf("%s:\n", filename); 15 printf(" %19s %20s\n", "apr_stat", "stat"); 16 printf(" mtime: %19lld %10lld.%09ld\n", 17 (int64_t) finfo.mtime, Target 0: (stat) stopped. warning: stat was compiled with optimization - stepping may behave oddly; variables may not be available. (lldb) p finfo.mtime (apr_time_t) 1704523440000000 (lldb) p statbuf.st_mtimespec (timespec) (tv_sec = 1704523440, tv_nsec = 172445899) ]]] I think we could check `struct stat.st_{m,c,a}timespec.tv_nsec` in the configure script. [1] https://man.freebsd.org/cgi/man.cgi?query=stat&sektion=2&apropos=0&manpath=macOS+10.13.6#DESCRIPTION Proposed patch: [[[ Support microseconds of mtime/atime/ctime in apr_stat() on macOS. * configure.in (Checking for File Info Support): Add struct stat.st_atimespec.tv_nsec, struct stat.st_mtimespec.tv_nsec, struct stat.st_ctimespec.tv_nsec. * file_io/unix/filestat.c (fill_out_finfo): Use st_mtimespec.tv_nsec, st_atimensec.tv_nsec and st_ctimensec.tv_nsec if available. Index: configure.in =================================================================== --- configure.in (revision 1915079) +++ configure.in (working copy) @@ -2876,7 +2876,9 @@ AC_MSG_NOTICE([Checking for File Info Support...]) AC_CHECK_MEMBERS([struct stat.st_blocks, struct stat.st_atimensec, struct stat.st_ctimensec, struct stat.st_mtimensec, struct stat.st_atim.tv_nsec, struct stat.st_ctim.tv_nsec, struct stat.st_mtim.tv_nsec, -struct stat.st_atime_n, struct stat.st_ctime_n, struct stat.st_mtime_n],,,[ +struct stat.st_atime_n, struct stat.st_ctime_n, struct stat.st_mtime_n, +struct stat.st_atimespec.tv_nsec, struct stat.st_mtimespec.tv_nsec, +struct stat.st_ctimespec.tv_nsec],,,[ #ifdef HAVE_SYS_TYPES_H #include <sys/types.h> #endif Index: file_io/unix/filestat.c =================================================================== --- file_io/unix/filestat.c (revision 1915079) +++ file_io/unix/filestat.c (working copy) @@ -96,6 +96,8 @@ static void fill_out_finfo(apr_finfo_t *finfo, str finfo->atime += info->st_atimensec / APR_TIME_C(1000); #elif defined(HAVE_STRUCT_STAT_ST_ATIME_N) finfo->atime += info->st_atime_n / APR_TIME_C(1000); +#elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC) + finfo->atime += info->st_atimespec.tv_nsec / APR_TIME_C(1000); #endif apr_time_ansi_put(&finfo->mtime, info->st_mtime); @@ -105,6 +107,8 @@ static void fill_out_finfo(apr_finfo_t *finfo, str finfo->mtime += info->st_mtimensec / APR_TIME_C(1000); #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N) finfo->mtime += info->st_mtime_n / APR_TIME_C(1000); +#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC) + finfo->mtime += info->st_mtimespec.tv_nsec / APR_TIME_C(1000); #endif apr_time_ansi_put(&finfo->ctime, info->st_ctime); @@ -114,6 +118,8 @@ static void fill_out_finfo(apr_finfo_t *finfo, str finfo->ctime += info->st_ctimensec / APR_TIME_C(1000); #elif defined(HAVE_STRUCT_STAT_ST_CTIME_N) finfo->ctime += info->st_ctime_n / APR_TIME_C(1000); +#elif defined(HAVE_STRUCT_STAT_ST_CTIMESPEC_TV_NSEC) + finfo->ctime += info->st_ctimespec.tv_nsec / APR_TIME_C(1000); #endif #ifdef HAVE_STRUCT_STAT_ST_BLOCKS ]]] -- Jun Omae <jun6...@gmail.com> (大前 潤)