stat: support printing birthtime
authorEric Blake <eblake@redhat.com>
Thu, 30 Sep 2010 22:31:50 +0000 (16:31 -0600)
committerEric Blake <eblake@redhat.com>
Fri, 1 Oct 2010 16:43:25 +0000 (10:43 -0600)
* src/stat.c (print_stat): New %w and %W formats.
(do_stat): Include %w in default format.
(usage): Document new specifiers.
* doc/coreutils.texi (stat invocation): Likewise.
* NEWS: Likewise.

NEWS
doc/coreutils.texi
src/stat.c
tests/Makefile.am
tests/misc/stat-birthtime [new file with mode: 0755]

diff --git a/NEWS b/NEWS
index 11a8b74..0c7cc38 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -36,8 +36,9 @@ GNU coreutils NEWS                                    -*- outline -*-
 
   sort now supports -d, -f, -i, -R, and -V in any combination.
 
-  stat now accepts the %m format directive to output
-  the mount point for a file.
+  stat now accepts the %m format directive to output the mount point
+  for a file.  It also accepts the %w and %W format directives for
+  outputting the birth time of a file, if one is available.
 
 ** Changes in behavior
 
index 52f1b20..12f103a 100644 (file)
@@ -10696,6 +10696,8 @@ The valid @var{format} directives for files with @option{--format} and
 @item %T - Minor device type in hex
 @item %u - User ID of owner
 @item %U - User name of owner
+@item %w - Time of file birth, or @samp{-} if unknown
+@item %W - Time of file birth as seconds since Epoch, or @samp{-}
 @item %x - Time of last access
 @item %X - Time of last access as seconds since Epoch
 @item %y - Time of last modification
index f985978..e1d68a5 100644 (file)
@@ -788,6 +788,26 @@ print_stat (char *pformat, size_t prefix_len, char m,
     case 'o':
       out_uint (pformat, prefix_len, statbuf->st_blksize);
       break;
+    case 'w':
+      {
+        struct timespec t = get_stat_birthtime (statbuf);
+        if (t.tv_nsec < 0)
+          out_string (pformat, prefix_len, "-");
+        else
+          out_string (pformat, prefix_len, human_time (t));
+      }
+      break;
+    case 'W':
+      {
+        struct timespec t = get_stat_birthtime (statbuf);
+        if (t.tv_nsec < 0)
+          out_string (pformat, prefix_len, "-");
+        else if (TYPE_SIGNED (time_t))
+          out_int (pformat, prefix_len, t.tv_sec);
+        else
+          out_uint (pformat, prefix_len, t.tv_sec);
+      }
+      break;
     case 'x':
       out_string (pformat, prefix_len, human_time (get_stat_atime (statbuf)));
       break;
@@ -1042,7 +1062,7 @@ do_stat (char const *filename, bool terse, char const *format)
     {
       if (terse)
         {
-          format = "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o\n";
+          format = "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %W %o\n";
         }
       else
         {
@@ -1056,7 +1076,7 @@ do_stat (char const *filename, bool terse, char const *format)
                 "Device: %Dh/%dd\tInode: %-10i  Links: %-5h"
                 " Device type: %t,%T\n"
                 "Access: (%04a/%10.10A)  Uid: (%5u/%8U)   Gid: (%5g/%8G)\n"
-                "Access: %x\n" "Modify: %y\n" "Change: %z\n";
+                "Access: %x\n" "Modify: %y\n" "Change: %z\n" " Birth: %w\n";
             }
           else
             {
@@ -1065,7 +1085,7 @@ do_stat (char const *filename, bool terse, char const *format)
                 "  Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
                 "Device: %Dh/%dd\tInode: %-10i  Links: %h\n"
                 "Access: (%04a/%10.10A)  Uid: (%5u/%8U)   Gid: (%5g/%8G)\n"
-                "Access: %x\n" "Modify: %y\n" "Change: %z\n";
+                "Access: %x\n" "Modify: %y\n" "Change: %z\n" " Birth: %w\n";
             }
         }
     }
@@ -1130,6 +1150,8 @@ The valid format sequences for files (without --file-system):\n\
       fputs (_("\
   %u   User ID of owner\n\
   %U   User name of owner\n\
+  %w   Time of file birth, or - if unknown\n\
+  %W   Time of file birth as seconds since Epoch, or - if unknown\n\
   %x   Time of last access\n\
   %X   Time of last access as seconds since Epoch\n\
   %y   Time of last modification\n\
index 3236637..a6a0594 100644 (file)
@@ -239,6 +239,7 @@ TESTS =                                             \
   misc/split-a                                 \
   misc/split-fail                              \
   misc/split-l                                 \
+  misc/stat-birthtime                          \
   misc/stat-fmt                                        \
   misc/stat-hyphen                             \
   misc/stat-mount                              \
diff --git a/tests/misc/stat-birthtime b/tests/misc/stat-birthtime
new file mode 100755 (executable)
index 0000000..b54268c
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/sh
+# ensure that stat attempts birthtime access
+
+# Copyright (C) 2010 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/init.sh"; path_prepend_ ../src
+
+# Whether birthtime is supported or not, it better not change even when
+# [acm]time are modified.  :)
+touch a || fail=1
+btime=$(stat --format %W a) || fail=1
+atime=$(stat --format %X a) || fail=1
+mtime=$(stat --format %Y a) || fail=1
+ctime=$(stat --format %Z a) || fail=1
+
+case $(stat --format %x a) in
+  *.000000000*) sleep 2;; # worst case file system is FAT
+  *) # FIXME: sleep .1 would be sufficient if %X is fixed to show nanoseconds
+ sleep 1;;
+esac
+
+touch a || fail=1
+test "x$btime" = x$(stat --format %W a) || fail=1
+test "x$atime" != x$(stat --format %X a) || fail=1
+test "x$mtime" != x$(stat --format %Y a) || fail=1
+test "x$ctime" != x$(stat --format %Z a) || fail=1
+
+Exit $fail