Ticket #4542 (closed defect: fixed)
Nanosecond precision timestamps support broken on macOS / BSD / AIX / Solaris
Reported by: | zaytsev | Owned by: | zaytsev |
---|---|---|---|
Priority: | major | Milestone: | 4.8.32 |
Component: | mc-vfs | Version: | master |
Keywords: | Cc: | ag | |
Blocked By: | Blocking: | #3960 | |
Branch state: | merged | Votes for changeset: | committed-master |
Description (last modified by zaytsev) (diff)
Followup ticket to:
- #3575 (implementation)
- #3821 (bugfix)
- #3927 (wrong AIX fix)
- #3960 (more wrong AIX)
- PR on GitHub https://github.com/MidnightCommander/mc/pull/130
Sadly no-one came around to fix this, so packagers still disable the support manually:
https://github.com/Homebrew/homebrew-core/blob/master/Formula/m/midnight-commander.rb
https://github.com/macports/macports-ports/blame/master/sysutils/mc/Portfile
Here are the notes how to possible fix this:
---
Unfortunately, I think that the easiest way to access XNU sources from macOS 10.13 right now would be to get hired as a kernel developer by Apple. The system is not even officially released to the public yet (target date is 25th of September), and sources are usually released some time after the final release.
Anyways, I believe that source code access is not really necessary in the first place, as I would speculate that all one needs to do is to add
AC_CHECK_MEMBERS([struct stat.st_blksize, struct stat.st_rdev, struct stat.st_mtim, struct stat.st_mtimespec])
and wherever we use HAVE_STRUCT_STAT_ST_MTIM *or* HAVE_UTIMENSAT replace it with
#ifdef HAVE_STRUCT_STAT_ST_MTIM st.st_atim.tv_nsec = st.st_mtim.tv_nsec = st.st_ctim.tv_nsec = 0; #elif defined HAVE_STRUCT_STAT_ST_MTIMESPEC st.st_atimespec.tv_nsec = st.st_mtimespec.tv_nsec = st.st_mtimespec.tv_nsec = 0; #endif
or something along these lines and you will magically not only fix the build, but gain nanosecond precision support for macOS 10.13+ *and* BSD at the same time. Of course, cruft keeps accumulating, so ideally one should think about defining clever struct manipulation functions limiting define proliferation...
Better yet would be to undertake a major refactoring to clean up our time mess afterwards, but that's, of course, just wishful thinking.
Attachments
Change History
comment:2 Changed 6 months ago by zaytsev
Apparently, macOS fixed itself: https://github.com/Homebrew/homebrew-core/pull/173306
Need to check what's up in the BSD land.
comment:3 Changed 6 months ago by zaytsev
stat -f %Fm filename can be used if ls is unable to show nanosecond timestamps.
comment:8 Changed 6 months ago by zaytsev
- Branch state changed from no branch to on review
- Milestone changed from Future Releases to 4.8.32
Branch: 4542_nanoseconds_cleanup
Initial changeset:934efd96383900ce38fb55d5592f6ac2aecb1280
Hi Andrew, appreciate reviewing this stuff, maybe you can check on Linux? I've checked it on macOS and it works, will be trying on AIX shortly, it's a bit of a pain to build. I hope my idea is clear. If not just ask. Please feel free to commit fixups directly if you don't like something. I tried my best to keep to your style.
comment:9 Changed 6 months ago by andrew_b
Let's move cleanup stuff to new branch 4524_cleanup or commit it directly to master.
Move #include <config.h> to .h is not a good idea. config.h must be included first in .c files, but indirectly includes via other headers became it not first.
As a result, ENABLE_EXT2FS_ATTR is not defined in local.c here:
#ifdef ENABLE_EXT2FS_ATTR #include <e2p/e2p.h> /* fgetflags(), fsetflags() */ #endif
but defined here:
CC local.lo src/vfs/local/local.c: In function 'local_fgetflags': src/vfs/local/local.c:198:12: warning: implicit declaration of function 'fgetflags'; did you mean 'mc_fgetflags'? [-Wimplicit-function-declaration] return fgetflags (path, flags); ^~~~~~~~~ mc_fgetflags src/vfs/local/local.c: In function 'local_fsetflags': src/vfs/local/local.c:209:12: warning: implicit declaration of function 'fsetflags'; did you mean 'mc_fsetflags'? [-Wimplicit-function-declaration] return fsetflags (path, flags); ^~~~~~~~~ mc_fsetflags
comment:10 follow-up: ↓ 11 Changed 6 months ago by zaytsev
Let's move cleanup stuff to new branch 4524_cleanup or commit it directly to master.
Sorry, I don't get what you want. I think it's better to have a separate branch for nanoseconds stuff instead of doing everything in cleanup. It's a new feature supporting it correctly on AIX & BSDs. The commits doing the refactoring make it possible to implement the new feature centrally, so I would also keep them to this branch.
If you want to take changeset:607fe8 and changeset:c50106 elsewhere, no problem, but I would prefer master, so that I can rebase this branch and continue testing. Regarding changeset:c50106, I'm not sure if something else has to be changed / removed. The function was present before glib 2.31 according to git blame of their tree, so maybe something went wrong at some point?
Move #include <config.h> to .h is not a good idea. config.h must be included first in .c files, but indirectly includes via other headers became it not first.
Ah, ok, thank you, I put it back. I thought it was unused, but I was wrong.
But am I allowed also to use config.h in h-files? Are there any rules for that? I need to know the structure of the struct and I want the functions to be in h-files, so that they can be inlined everywhere, where they are used.
comment:11 in reply to: ↑ 10 Changed 6 months ago by andrew_b
Replying to zaytsev:
If you want to take changeset:607fe8 and changeset:c50106 elsewhere, no problem, but I would prefer master,
Ok.
Regarding changeset:c50106, I'm not sure if something else has to be changed / removed. The function was present before glib 2.31 according to git blame of their tree, so maybe something went wrong at some point?
That's my mistake. There was no need to redefine g_direct_equal() in our code because it's implemented in glib since 2005.
Move #include <config.h> to .h is not a good idea. config.h must be included first in .c files, but indirectly includes via other headers became it not first.
Ah, ok, thank you, I put it back. I thought it was unused, but I was wrong.
But am I allowed also to use config.h in h-files?
I've never seen <config.h> included in h-files, only in c-files.
Are there any rules for that?
Probably yes, but Google can't help me.
I need to know the structure of the struct and I want the functions to be in h-files, so that they can be inlined everywhere, where they are used.
Your h-files are included in c-files after config.h so no problems.
But why you want make function inline?
comment:12 Changed 6 months ago by zaytsev
I've never seen <config.h> included in h-files, only in c-files.
Okay, I understand, so the rule is to use config.h in C-files so that it doesn't contaminate other files per mistake if used in an H-file, and use it first. I can check if there are other H-files where we include it by mistake.
But why you want make function inline?
These are nothing but accessor functions that reshuffle struct fields. Before my changes it was handled at every place where it was needed in the code. Now everywhere there is an extra function call, but the code is reused. I wanted to make it a function and not a macro, because macros are evil and non-type-safe. But it has some performance impact. For inline functions the impact is zero.
But if we don't care, then I can move these functions in a C-file, probably the impact will be some microseconds anyways which are not important...
comment:13 Changed 6 months ago by zaytsev
I have added a commit implementing this, took the two build fixes in master and rebased the branch squashing the fixups.
comment:14 Changed 5 months ago by andrew_b
I've created an alternative branch with some fixups: 4542_nanoseconds_2
Initial changeset:e89d65e17053e10912a2b1ed3afc9be06ec8c746
comment:15 Changed 5 months ago by andrew_b
- Type changed from enhancement to defect
- Component changed from mc-core to mc-vfs
comment:16 follow-up: ↓ 17 Changed 5 months ago by zaytsev
I'm a bit concerned about you removing config.h from vfs.h - it means vfs.h must be only included in C-files which include config.h themselves to work correctly. But I guess this is C life :-(
Thank you for the rest of the changes, I think I tried %ju but got some problems on Mac and AIX, and decided to use %llu. I will test again on Mac, AIX and I also wanted to check Solaris. Then report back.
comment:17 in reply to: ↑ 16 Changed 5 months ago by andrew_b
Replying to zaytsev:
I'm a bit concerned about you removing config.h from vfs.h - it means vfs.h must be only included in C-files which include config.h themselves to work correctly. But I guess this is C life :-(
Yes. We do compile c-files, not h-files. c-file must begin with include of config.h, then include system-wide h-files (from /usr/include), then project h-files.
Thank you for the rest of the changes, I think I tried %ju but got some problems on Mac and AIX, and decided to use %llu. I will test again on Mac, AIX and I also wanted to check Solaris. Then report back.
I get a warning for %llu:
src/vfs/shell/shell.c: In function 'shell_utime': src/vfs/shell/shell.c:1490:69: warning: format '%llu' expects argument of type 'long long unsigned int', but argument 7 has type 'long unsigned int' [-Wformat=] 1490 | "SHELL_FILENAME=%s SHELL_FILEATIME=%llu SHELL_FILEMTIME=%llu " | ~~~^ | | | long long unsigned int | %lu 1491 | "SHELL_TOUCHATIME=%s SHELL_TOUCHMTIME=%s SHELL_TOUCHATIME_W_NSEC=\"%s\" " 1492 | "SHELL_TOUCHMTIME_W_NSEC=\"%s\";\n", rpath, (uintmax_t) atime.tv_sec, | ~~~~~~~~~~~~~~~~~~~~~~~~ | | | long unsigned int src/vfs/shell/shell.c:1490:90: warning: format '%llu' expects argument of type 'long long unsigned int', but argument 8 has type 'long unsigned int' [-Wformat=] 1490 | "SHELL_FILENAME=%s SHELL_FILEATIME=%llu SHELL_FILEMTIME=%llu " | ~~~^ | | | long long unsigned int | %lu ...... 1493 | (uintmax_t) mtime.tv_sec, utcatime, utcmtime, utcatime_w_nsec, | ~~~~~~~~~~~~~~~~~~~~~~~~ | | | long unsigned int
and system_data_types(7) says:
The length modifier for uintmax_t for the printf(3) and the scanf(3) families of functions is j; resulting commonly in %ju or %jx for printing uintmax_t values. Conforming to: C99 and later; POSIX.1-2001 and later.
comment:18 Changed 4 months ago by andrew_b
@zaytsev: well? What is your plan here?
comment:19 Changed 4 months ago by zaytsev
Been busy with other stuff, but probably should just test on Solaris and be done with it. Will see how I can get back to it.
comment:22 Changed 4 months ago by zaytsev
Started building on Solaris, still struggling to compile the dependencies. Libffi is done:
https://github.com/libffi/libffi/pull/846
MAKE=gmake AR=gar READELF=greadelf \ ../configure --disable-static --enable-shared --prefix=/home/zaytsev/opt/libffi
Glib needs more work.
MAKE=gmake AR=gar \ CFLAGS=-D_XPG6 \ LIBFFI_LIBS=$HOME/opt/libffi/lib LIBFFI_CFLAGS=-I$HOME/opt/libffi/include \ ../configure \ --disable-static --enable-shared \ --with-libiconv=gnu --disable-dtrace --disable-compile-warnings \ --prefix=/home/zaytsev/opt/glib
Glib is done with lots of makefile editing to remove -Wl,... and disable linking binaries / tests. Maybe newer versions than glib-2.43.92.tar.xz are not as bad, but at some point they started depending on a non-autotools build system... even more pain.
Slang was "easy":
MAKE=gmake CFLAGS=-D_XPG6 ./configure --prefix=$HOME/opt/slang gmake install
mc was also okay, but patches are needed (see below):
XGETTEXT=gxgettext ./autogen.sh GLIB_LIBS="-L$HOME/opt/glib/lib -lglib-2.0" \ GLIB_CFLAGS="-I$HOME/opt/glib/include/glib-2.0 -I$HOME/opt/glib/lib/glib-2.0/include" \ SLANG_LIBS="-L$HOME/opt/slang/lib -lslang" SLANG_CFLAGS=-I$HOME/opt/slang/include \ MAKE=gmake \ ../configure --prefix=$HOME/opt/mc
comment:23 Changed 4 months ago by zaytsev
May I commit the following two patches directly to master?
From 1be8bbb4cf3667317f4361c0b749d9ee68032cf1 Mon Sep 17 00:00:00 2001 From: "Yury V. Zaytsev" <yury@shurup.com> Date: Sat, 27 Jul 2024 21:17:52 +0200 Subject: [PATCH 1/2] buildsys: support bootstrapping on Solaris by using backticks in autogen.sh Signed-off-by: Yury V. Zaytsev <yury@shurup.com> --- autogen.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/autogen.sh b/autogen.sh index ee76efc22..8c06da89c 100755 --- a/autogen.sh +++ b/autogen.sh @@ -2,7 +2,9 @@ set -e -srcdir="$(cd "$(dirname "$0")" && pwd)" +# Use backticks to support ksh on Solaris +basedir=`dirname "$0"` +srcdir=`cd "$basedir" && pwd` cd "$srcdir" -- 2.39.3 (Apple Git-146)
From 889ef3d4a7f3048ff9979e2fc6332d93f0242eed Mon Sep 17 00:00:00 2001 From: "Yury V. Zaytsev" <yury@shurup.com> Date: Sat, 27 Jul 2024 21:18:48 +0200 Subject: [PATCH 2/2] buildsys: fix ar check by doing it before toolchain checks implicitly looking for ar Signed-off-by: Yury V. Zaytsev <yury@shurup.com> --- configure.ac | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 12556f563..21c0ca71b 100644 --- a/configure.ac +++ b/configure.ac @@ -36,6 +36,10 @@ dnl ############################################################################ dnl Check for compiler dnl ############################################################################ +dnl This should be checked before toolchain macros, otherwise they will remember +dnl that ar cannot be found and linking via libtool will fail at a later stage +AC_CHECK_TOOLS([AR], [ar gar]) + AC_PROG_CC AM_PROG_CC_C_O @@ -211,8 +215,7 @@ dnl ############################################################################ dnl Check for other tools dnl ############################################################################ -AC_CHECK_TOOL(AR, ar, ar) -AC_CHECK_TOOL(INDENT, gindent, indent) +AC_CHECK_TOOLS([INDENT], [gindent indent]) mc_UNIT_TESTS -- 2.39.3 (Apple Git-146)
comment:24 Changed 4 months ago by zaytsev
N.B. Tested nanosecond timestamps on Solaris, they work now. Solaris supports ls -alsE to show them.
comment:25 follow-up: ↓ 29 Changed 4 months ago by zaytsev
I've retested on AIX 7.3 and it looks really good. The timestamps are also preserved.
I've looked at your changes, Andrew, and I agree with all of them, thank you for your help! Without you I've probably wouldn't come that far. How do we go about merging this branch? Shall I take yours, rebase and merge? Or you want to do this?
comment:26 Changed 4 months ago by zaytsev
Rebased - changeset: bfa0f041cf84ec169c3a72538bddf461dd8bd256 .
comment:28 Changed 4 months ago by zaytsev
- Summary changed from Timestamps with nanosecond precision support is broken on macOS to Nanosecond precision timestamps support broken on macOS / BSD / AIX / Solaris
comment:29 in reply to: ↑ 25 Changed 4 months ago by andrew_b
- Votes for changeset set to andrew_b
- Branch state changed from on review to approved
comment:30 Changed 4 months ago by zaytsev
Why not to the current branch before merge?
No problem, can do that :) Last time you didn't want "unrelated" patches fixing the build system in the topic branches, which is why I asked.
comment:31 Changed 4 months ago by zaytsev
- Status changed from accepted to testing
- Resolution set to fixed
Merged to master: [7e2cf63b4e4cf4cbb8ef253fbded134370c5e99b].
comment:33 Changed 4 months ago by zaytsev
- Votes for changeset changed from andrew_b to committed-master
- Branch state changed from approved to merged