Changes to implement:
16575074 stat could support birthtime/crtime on ZFS
These changes have already been accepted upstream. See:
http://git.savannah.gnu.org/gitweb/?p=coreutils.git;a=commitdiff;h=ea916c70a5fc47ee6036a05416bc7462fd8dc1cd
--- coreutils-8.16/configure.ac.orig 2014-03-18 20:12:23.362356112 -0700
+++ coreutils-8.16/configure.ac 2014-03-18 20:13:47.327463395 -0700
@@ -240,6 +240,13 @@
AC_DEFINE([LOCALTIME_CACHE], [1], [FIXME])
fi
+# Assume that if getattrat exists, it's compatible with Solaris 11.
+AC_CHECK_FUNCS([getattrat])
+if test $ac_cv_func_getattrat = yes; then
+ LIB_NVPAIR=-lnvpair
+ AC_SUBST([LIB_NVPAIR])
+fi
+
# 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
--- coreutils-8.16/src/Makefile.am.orig 2014-03-18 20:19:34.447566111 -0700
+++ coreutils-8.16/src/Makefile.am 2014-03-18 20:20:20.876086076 -0700
@@ -326,6 +326,9 @@
runcon_LDADD += $(LIB_SELINUX)
stat_LDADD += $(LIB_SELINUX)
+# for nvlist_lookup_uint64_array
+stat_LDADD += $(LIB_NVPAIR)
+
# for gettime, settime, utimecmp, utimens
copy_LDADD += $(LIB_CLOCK_GETTIME)
date_LDADD += $(LIB_CLOCK_GETTIME)
--- coreutils-8.16/src/stat.c.orig 2014-03-16 16:55:52.605732676 -0700
+++ coreutils-8.16/src/stat.c 2014-03-18 20:27:04.302699124 -0700
@@ -148,6 +148,11 @@
# endif
#endif
+#if HAVE_GETATTRAT
+# include <attr.h>
+# include <sys/nvpair.h>
+#endif
+
/* FIXME: these are used by printf.c, too */
#define isodigit(c) ('0' <= (c) && (c) <= '7')
#define octtobin(c) ((c) - '0')
@@ -689,7 +694,7 @@
/* Print statfs info. Return zero upon success, nonzero upon failure. */
static bool ATTRIBUTE_WARN_UNUSED_RESULT
print_statfs (char *pformat, size_t prefix_len, unsigned int m,
- char const *filename,
+ int fd, char const *filename,
void const *data)
{
STRUCT_STATVFS const *statfsbuf = data;
@@ -861,6 +866,38 @@
return fail;
}
+static struct timespec
+get_birthtime (int fd, char const *filename, struct stat const *st)
+{
+ struct timespec ts = get_stat_birthtime (st);
+
+#if HAVE_GETATTRAT
+ if (ts.tv_nsec < 0)
+ {
+ nvlist_t *response;
+ if ((fd < 0
+ ? getattrat (AT_FDCWD, XATTR_VIEW_READWRITE, filename, &response)
+ : fgetattr (fd, XATTR_VIEW_READWRITE, &response))
+ == 0)
+ {
+ uint64_t *val;
+ uint_t n;
+ if (nvlist_lookup_uint64_array (response, A_CRTIME, &val, &n) == 0
+ && 2 <= n
+ && val[0] <= TYPE_MAXIMUM (time_t)
+ && val[1] < 1000000000 * 2 /* for leap seconds */)
+ {
+ ts.tv_sec = val[0];
+ ts.tv_nsec = val[1];
+ }
+ nvlist_free (response);
+ }
+ }
+#endif
+
+ return ts;
+}
+
/* Map a TS with negative TS.tv_nsec to {0,0}. */
static inline struct timespec
neg_to_zero (struct timespec ts)
@@ -874,7 +911,7 @@
/* Print stat info. Return zero upon success, nonzero upon failure. */
static bool
print_stat (char *pformat, size_t prefix_len, unsigned int m,
- char const *filename, void const *data)
+ int fd, char const *filename, void const *data)
{
struct stat *statbuf = (struct stat *) data;
struct passwd *pw_ent;
@@ -967,7 +1004,7 @@
break;
case 'w':
{
- struct timespec t = get_stat_birthtime (statbuf);
+ struct timespec t = get_birthtime (fd, filename, statbuf);
if (t.tv_nsec < 0)
out_string (pformat, prefix_len, "-");
else
@@ -976,7 +1013,7 @@
break;
case 'W':
out_epoch_sec (pformat, prefix_len, statbuf,
- neg_to_zero (get_stat_birthtime (statbuf)));
+ neg_to_zero (get_birthtime (fd, filename, statbuf)));
break;
case 'x':
out_string (pformat, prefix_len, human_time (get_stat_atime (statbuf)));
@@ -1051,9 +1088,9 @@
calling PRINT_FUNC for each %-directive encountered.
Return zero upon success, nonzero upon failure. */
static bool ATTRIBUTE_WARN_UNUSED_RESULT
-print_it (char const *format, char const *filename,
+print_it (char const *format, int fd, char const *filename,
bool (*print_func) (char *, size_t, unsigned int,
- char const *, void const *),
+ int, char const *, void const *),
void const *data)
{
bool fail = false;
@@ -1102,7 +1139,8 @@
putchar ('%');
break;
default:
- fail |= print_func (dest, len + 1, fmt_code, filename, data);
+ fail |= print_func (dest, len + 1, fmt_code,
+ fd, filename, data);
break;
}
break;
@@ -1185,7 +1223,7 @@
return false;
}
- bool fail = print_it (format, filename, print_statfs, &statfsbuf);
+ bool fail = print_it (format, -1, filename, print_statfs, &statfsbuf);
return ! fail;
}
@@ -1194,11 +1232,12 @@
do_stat (char const *filename, char const *format,
char const *format2)
{
+ int fd = STREQ (filename, "-") ? 0 : -1;
struct stat statbuf;
- if (STREQ (filename, "-"))
+ if (0 <= fd)
{
- if (fstat (STDIN_FILENO, &statbuf) != 0)
+ if (fstat (fd, &statbuf) != 0)
{
error (0, errno, _("cannot stat standard input"));
return false;
@@ -1218,7 +1257,7 @@
if (S_ISBLK (statbuf.st_mode) || S_ISCHR (statbuf.st_mode))
format = format2;
- bool fail = print_it (format, filename, print_stat, &statbuf);
+ bool fail = print_it (format, fd, filename, print_stat, &statbuf);
return ! fail;
}