On 23/12/18 12:30, Martin Bukatovic wrote:
> Dear coreutils list,
> 
> I'm interested in seeing btime (birth time) in stat output on GNU Linux
> distributions. Since statx syscall is available since Linux 4.11 [1] and
> glibc wrapper is available since 2.28 [2], now it's finally possible to
> use statx in coreutils tools to display btime.
> 
> I checked the source code of stat and related parts in gnulib
> (stat-time.h) briefly and it seems to me that the current support for
> reporting birth time of a file works on BSD systems and Solaris only.
> To add support for reading btime with Linux, it seems that gnulib
> functions needs to be generalized to use statx when compiled on recent
> Linux kernel. Is anybody already working on this?
> 
> In the meantime, I tried to quickly hack the stat code to add support
> for reading btime via statx in a similar way how btime is read on
> Solaris via getattrat (patch attached). This way, I was able to play
> with this feature quickly:
> 
> ```
> $ touch ~/tmp/testfile
> $ ./stat ~/tmp/testfile
>   File: /home/martin/tmp/testfile
>   Size: 0               Blocks: 0          IO Block: 4096   regular empty file
> Device: fd07h/64775d    Inode: 7388546     Links: 1
> Access: (0664/-rw-rw-r--)  Uid: ( 1000/  martin)   Gid: ( 1000/  martin)
> Access: 2018-12-23 21:18:27.717535190 +0100
> Modify: 2018-12-23 21:18:27.717535190 +0100
> Change: 2018-12-23 21:18:27.717535190 +0100
>  Birth: 2018-12-23 21:18:27.717535190 +0100
> $ touch ~/tmp/testfile
> $ ./stat ~/tmp/testfile
>   File: /home/martin/tmp/testfile
>   Size: 0               Blocks: 0          IO Block: 4096   regular empty file
> Device: fd07h/64775d    Inode: 7388546     Links: 1
> Access: (0664/-rw-rw-r--)  Uid: ( 1000/  martin)   Gid: ( 1000/  martin)
> Access: 2018-12-23 21:18:34.822543416 +0100
> Modify: 2018-12-23 21:18:34.822543416 +0100
> Change: 2018-12-23 21:18:34.822543416 +0100
>  Birth: 2018-12-23 21:18:27.717535190 +0100
> ```
> 
> But as I said, this is rather quick hack, I don't expect you to want
> to merge this.
> 
> [1] 
> https://kernelnewbies.org/Linux_4.11#statx.282.29.2C_a_modern_stat.282.29_alternative
> [2] https://www.sourceware.org/ml/libc-alpha/2018-08/msg00003.html
> 

Thanks for the patch and your patience.
I'm going to add the attached in the upcoming release.
I've adjusted slightly to handle symlinks,
and to test (st_mask & STATX_BTIME) on output.

Ideally we would only call statx() rather than stat() as well,
though for now the performance implications of that aren't
worth complicating things.

I've not actually tested the attached yet,
so it would be great if you could also.

thanks!
Pádraig
>From fc34bbe3795b6094da98e05de1a59aa267f7afc6 Mon Sep 17 00:00:00 2001
From: Martin Bukatovic <[email protected]>
Date: Sat, 2 Mar 2019 19:57:17 -0800
Subject: [PATCH] stat: print birth time on systems supporting statx

* configure.ac: Check for statx(), available on glibc >= 2.28.
* src/stat.c (get_birthtime): Call statx() when available.
* NEWS: Mention the improvement.
---
 NEWS         |  3 +++
 configure.ac |  3 +++
 src/stat.c   | 19 +++++++++++++++++++
 3 files changed, 25 insertions(+)

diff --git a/NEWS b/NEWS
index c190efe..d6c17e4 100644
--- a/NEWS
+++ b/NEWS
@@ -98,6 +98,9 @@ GNU coreutils NEWS                                    -*- outline -*-
   stat and tail now know about the "sdcardfs" file system on Android.
   stat -f -c%T now reports the file system type, and tail -f uses inotify.
 
+  stat now prints file creation time when supported by the file system,
+  on GNU Linux systems with glibc >= 2.28 and kernel >= 4.11.
+
 
 * Noteworthy changes in release 8.30 (2018-07-01) [stable]
 
diff --git a/configure.ac b/configure.ac
index 23086cd..0ee01b2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -317,6 +317,9 @@ if test $ac_cv_func_getattrat = yes; then
   AC_SUBST([LIB_NVPAIR])
 fi
 
+# glibc >= 2.28 and linux kernel >= 4.11
+AC_CHECK_FUNCS([statx])
+
 # SCO-ODT-3.0 is reported to need -los to link programs using initgroups
 AC_CHECK_FUNCS([initgroups])
 if test $ac_cv_func_initgroups = no; then
diff --git a/src/stat.c b/src/stat.c
index c8f1809..7c71c37 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -1009,6 +1009,25 @@ get_birthtime (int fd, char const *filename, struct stat const *st)
     }
 #endif
 
+#if HAVE_STATX
+  if (ts.tv_nsec < 0)
+    {
+      struct statx stx;
+      if ((fd < 0
+           ? statx(AT_FDCWD, filename,
+                   follow_links ? 0 : AT_SYMLINK_NOFOLLOW,
+                   STATX_BTIME, &stx)
+           : statx(fd, "", AT_EMPTY_PATH, STATX_BTIME, &stx)) == 0)
+        {
+          if ((stx.stx_mask & STATX_BTIME) && stx.stx_btime.tv_sec != 0)
+            {
+              ts.tv_sec = stx.stx_btime.tv_sec;
+              ts.tv_nsec = stx.stx_btime.tv_nsec;
+            }
+        }
+    }
+#endif
+
   return ts;
 }
 
-- 
2.9.3

Reply via email to