summaryrefslogtreecommitdiff
path: root/support/support_stat_nanoseconds.c
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2021-03-29 14:40:30 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2021-03-31 17:20:14 -0300
commitbfddda2570331da2ae4387b530456e6c4e230257 (patch)
tree63bd920593b38f7f65e282eb1e6ab1c9143bedd2 /support/support_stat_nanoseconds.c
parent18f0afa8485e8cd6434d118cb841d78d897230b6 (diff)
downloadglibc-bfddda2570331da2ae4387b530456e6c4e230257.tar.gz
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.
Diffstat (limited to 'support/support_stat_nanoseconds.c')
-rw-r--r--support/support_stat_nanoseconds.c40
1 files changed, 33 insertions, 7 deletions
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;
}