diff options
author | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2021-03-29 14:40:30 -0300 |
---|---|---|
committer | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2021-03-31 17:20:14 -0300 |
commit | bfddda2570331da2ae4387b530456e6c4e230257 (patch) | |
tree | 63bd920593b38f7f65e282eb1e6ab1c9143bedd2 | |
parent | 18f0afa8485e8cd6434d118cb841d78d897230b6 (diff) | |
download | glibc-bfddda2570331da2ae4387b530456e6c4e230257.tar glibc-bfddda2570331da2ae4387b530456e6c4e230257.tar.gz glibc-bfddda2570331da2ae4387b530456e6c4e230257.tar.bz2 glibc-bfddda2570331da2ae4387b530456e6c4e230257.zip |
io: Check at runtime if timestamp supports nanoseconds
Now that non-LFS stat function is implemented on to on LFS, it will
use statx when available. It allows to check for nanosecond timestamp
if the kernel supports __NR_statx.
Checked on s390-linux-gnu with 4.12.14 kernel.
-rw-r--r-- | io/tst-stat.c | 7 | ||||
-rw-r--r-- | support/support.h | 2 | ||||
-rw-r--r-- | support/support_stat_nanoseconds.c | 40 |
3 files changed, 40 insertions, 9 deletions
diff --git a/io/tst-stat.c b/io/tst-stat.c index 397d480ecc..22b89bb3e7 100644 --- a/io/tst-stat.c +++ b/io/tst-stat.c @@ -25,6 +25,7 @@ #include <support/xunistd.h> #include <sys/stat.h> #include <sys/sysmacros.h> +#include <stdio.h> #include <unistd.h> static void @@ -73,6 +74,10 @@ do_test (void) test_t tests[] = { stat_check, lstat_check, fstat_check, fstatat_check }; + bool check_ns = support_stat_nanoseconds (path); + if (!check_ns) + printf ("warning: timestamp with nanoseconds not supportted\n"); + for (int i = 0; i < array_length (tests); i++) { struct stat st; @@ -92,7 +97,7 @@ do_test (void) TEST_COMPARE (stx.stx_ctime.tv_sec, st.st_ctim.tv_sec); TEST_COMPARE (stx.stx_mtime.tv_sec, st.st_mtim.tv_sec); - if (support_stat_nanoseconds ()) + if (check_ns) { TEST_COMPARE (stx.stx_ctime.tv_nsec, st.st_ctim.tv_nsec); TEST_COMPARE (stx.stx_mtime.tv_nsec, st.st_mtim.tv_nsec); diff --git a/support/support.h b/support/support.h index b0352726bf..e023d00857 100644 --- a/support/support.h +++ b/support/support.h @@ -142,7 +142,7 @@ static __inline bool support_path_support_time64 (const char *path) } /* Return true if stat supports nanoseconds resolution. */ -extern bool support_stat_nanoseconds (void); +extern bool support_stat_nanoseconds (const char *path); __END_DECLS diff --git a/support/support_stat_nanoseconds.c b/support/support_stat_nanoseconds.c index c0d5b2c3a9..6a9e49cc88 100644 --- a/support/support_stat_nanoseconds.c +++ b/support/support_stat_nanoseconds.c @@ -16,16 +16,42 @@ License along with the GNU C Library; if not, see <https://www.gnu.org/licenses/>. */ +#include <errno.h> +#include <fcntl.h> +#include <support/check.h> +#include <support/support.h> +#include <support/timespec.h> #include <stdbool.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> bool -support_stat_nanoseconds (void) +support_stat_nanoseconds (const char *path) { - /* s390 stat64 compat symbol does not support nanoseconds resolution - and it used on non-LFS [f,l]stat[at] implementations. */ -#if defined __linux__ && !defined __s390x__ && defined __s390__ - return false; -#else - return true; + bool support; +#ifdef __linux__ + /* Obtain the original timestamp to restore at the end. */ + struct stat ost; + TEST_VERIFY_EXIT (stat (path, &ost) == 0); + + const struct timespec tsp[] = { { 0, TIMESPEC_HZ - 1 }, + { 0, TIMESPEC_HZ / 2 } }; + TEST_VERIFY_EXIT (utimensat (AT_FDCWD, path, tsp, 0) == 0); + + struct stat st; + TEST_VERIFY_EXIT (stat (path, &st) == 0); + + support = st.st_atim.tv_nsec == tsp[0].tv_nsec + && st.st_mtim.tv_nsec == tsp[1].tv_nsec; + + /* Reset to original timestamps. */ + const struct timespec otsp[] = + { + { ost.st_atim.tv_sec, ost.st_atim.tv_nsec }, + { ost.st_mtim.tv_sec, ost.st_mtim.tv_nsec }, + }; + TEST_VERIFY_EXIT (utimensat (AT_FDCWD, path, otsp, 0) == 0); #endif + return support; } |