I installed the attached series of patches into GNU coreutils. The main
user-visible change is to add a new --resolution option to GNU 'date',
which queries clock_getres to print the clock resolution. 'date' and
similar programs now also support the %-N format, which prints subsecond
fractions just wide enough to cover the resolution.From 6812e6baa7882ed064d274ead8dcd84b556603ce Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Fri, 31 Dec 2021 00:45:03 -0800
Subject: [PATCH 1/5] build: port to AIX 7.1
This fixes a porting bug introduced in
2019-08-12T03:29:00Z!br...@clisp.org.
Problem discovered on AIX 7.1.
* src/local.mk (LDADD): Add $(LIB_MBRTOWC), since pretty much
every command uses quotearg or mbrtowc or whatever.
(src_sort_LDADD): Add $(LIBPMULTITHREAD) and
$(LIB_PTHREAD_SIGMASK) instead of $(LIBTHREAD).
---
NEWS | 3 +++
src/local.mk | 11 ++++++++---
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/NEWS b/NEWS
index 72453dc4b..b9d36c724 100644
--- a/NEWS
+++ b/NEWS
@@ -29,6 +29,9 @@ GNU coreutils NEWS -*- outline -*-
for B when A is a directory, possibly inflooping.
[bug introduced in coreutils-6.3]
+ AIX builds no longer fail because some library functions are not found.
+ [bug introduced in coreutils-8.32]
+
** Changes in behavior
timeout --foreground --kill-after=... will now exit with status 137
diff --git a/src/local.mk b/src/local.mk
index 0c8b65d39..d668bfc30 100644
--- a/src/local.mk
+++ b/src/local.mk
@@ -90,7 +90,9 @@ remove_ldadd =
# must precede $(LIBINTL) in order to ensure we use GNU getopt.
# But libcoreutils.a must also follow $(LIBINTL), since libintl uses
# replacement functions defined in libcoreutils.a.
-LDADD = src/libver.a lib/libcoreutils.a $(LIBINTL) lib/libcoreutils.a
+# Similarly for $(LIB_MBRTOWC).
+LDADD = src/libver.a lib/libcoreutils.a $(LIBINTL) $(LIB_MBRTOWC) \
+ lib/libcoreutils.a
# First, list all programs, to make listing per-program libraries easier.
# See [ below.
@@ -317,8 +319,11 @@ src_uname_LDADD += $(GETHOSTNAME_LIB)
# for strsignal
src_kill_LDADD += $(LIBTHREAD)
-# for pthread
-src_sort_LDADD += $(LIB_PTHREAD)
+# for pthread-cond, pthread-mutex, pthread-thread
+src_sort_LDADD += $(LIBPMULTITHREAD)
+
+# for pthread_sigmask
+src_sort_LDADD += $(LIB_PTHREAD_SIGMASK)
# Get the release year from lib/version-etc.c.
RELEASE_YEAR = \
--
2.32.0
From 1011b88594a9d6e940d51ce5b9443571d6ebef3b Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Fri, 31 Dec 2021 00:45:03 -0800
Subject: [PATCH 2/5] doc: Document , vs . in date --rfc-3339=ns
---
doc/coreutils.texi | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index f7ce1654b..49d2afbe2 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -16458,7 +16458,8 @@ For compatibility with older versions of @command{date},
Display the date using a format specified by
@uref{https://tools.ietf.org/search/rfc3339, Internet
RFC 3339}. This is like @option{--iso-8601}, except that a space rather
-than a @samp{T} separates dates from times.
+than a @samp{T} separates dates from times, and a period rather than
+a comma separates seconds from subseconds.
@dateParseNote
The argument @var{timespec} specifies how much of the time to include.
--
2.32.0
From 64b65cf4b8295cb35f4aa7431f91fccadb327ef6 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Fri, 31 Dec 2021 00:45:03 -0800
Subject: [PATCH 3/5] build: update gnulib submodule to latest
---
gnulib | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gnulib b/gnulib
index 8220e0f0b..972be3cee 160000
--- a/gnulib
+++ b/gnulib
@@ -1 +1 @@
-Subproject commit 8220e0f0b5f46ff61e1d19f8a1614508fa162abd
+Subproject commit 972be3cee24d6e9b84de7250c5bc7f078ac1a19d
--
2.32.0
From 0cd39a246af30d141be2676f1b4c1fd6616dfec5 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Fri, 31 Dec 2021 00:45:03 -0800
Subject: [PATCH 4/5] date: %-N now means suppress extra digits
* NEWS, doc/coreutils.texi: Mention this.
* bootstrap.conf (gnulib_modules): Add gettime-res.
* src/date.c (res_width, adjust_resolution): New functions.
(main): Adjust %-N to be %9N, or whatever, before using it.
---
NEWS | 4 ++++
bootstrap.conf | 1 +
doc/coreutils.texi | 6 ++++++
src/date.c | 40 ++++++++++++++++++++++++++++++++++++++--
4 files changed, 49 insertions(+), 2 deletions(-)
diff --git a/NEWS b/NEWS
index b9d36c724..79320820f 100644
--- a/NEWS
+++ b/NEWS
@@ -34,6 +34,10 @@ GNU coreutils NEWS -*- outline -*-
** Changes in behavior
+ date +'%-N' now suppresses excess trailing digits, instead of always
+ padding them with zeros to 9 digits. It uses clock_getres and
+ clock_gettime to infer the clock resolution.
+
timeout --foreground --kill-after=... will now exit with status 137
if the kill signal was sent, which is consistent with the behavior
when the --foreground option is not specified. This allows users to
diff --git a/bootstrap.conf b/bootstrap.conf
index c2f74f406..afa2cdcb9 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -119,6 +119,7 @@ gnulib_modules="
getpass-gnu
gettext-h
gettime
+ gettime-res
getugroups
getusershell
git-version-gen
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index 49d2afbe2..aa970da6c 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -16227,6 +16227,12 @@ The following optional flags can appear after the @samp{%}:
(hyphen) Do not pad the field; useful if the output is intended for
human consumption.
This is a GNU extension.
+As a special case, @samp{%-N} outputs only enough trailing digits to
+not lose information, assuming that the timestamp's resolution is the
+same as the current hardware clock. For example, if the hardware
+clock resolution is 1 microsecond, @samp{%s.%-N} outputs something
+like @samp{1640890100.395710}.
+
@item _
(underscore) Pad with spaces; useful if you need a fixed
number of characters in the output, but zeros are too distracting.
diff --git a/src/date.c b/src/date.c
index 4a7a4e243..b0a53ba6c 100644
--- a/src/date.c
+++ b/src/date.c
@@ -281,6 +281,39 @@ Show the local time for 9AM next Friday on the west coast of the US\n\
exit (status);
}
+/* Yield the number of decimal digits needed to output a time with the
+ nanosecond resolution RES, without losing information. */
+
+static int
+res_width (long int res)
+{
+ int i = 9;
+ for (long long int r = 1; (r *= 10) <= res; )
+ i--;
+ return i;
+}
+
+/* Return a newly allocated copy of FORMAT with each "%-N" adjusted to
+ be "%9N", "%6N", or whatever other resolution is appropriate for
+ the current platform. If no "%-N" appears, return NULL. */
+
+static char *
+adjust_resolution (char const *format)
+{
+ char *copy = NULL;
+
+ for (char const *f = format; *f; f++)
+ if (f[0] == '%' && f[1] == '-' && f[2] == 'N')
+ {
+ if (!copy)
+ copy = xstrdup (format);
+ copy[f + 1 - format] = '0' + res_width (gettime_res ());
+ f += 2;
+ }
+
+ return copy;
+}
+
/* Parse each line in INPUT_FILENAME as with --date and display each
resulting time and date. If the file cannot be opened, tell why
then exit. Issue a diagnostic for any lines that cannot be parsed.
@@ -505,11 +538,13 @@ main (int argc, char **argv)
}
}
+ char *format_copy = adjust_resolution (format);
+ char const *format_res = format_copy ? format_copy : format;
char const *tzstring = getenv ("TZ");
timezone_t tz = tzalloc (tzstring);
if (batch_file != NULL)
- ok = batch_convert (batch_file, format, tz, tzstring);
+ ok = batch_convert (batch_file, format_res, tz, tzstring);
else
{
bool valid_date = true;
@@ -568,10 +603,11 @@ main (int argc, char **argv)
}
}
- ok &= show_date (format, when, tz);
+ ok &= show_date (format_res, when, tz);
}
IF_LINT (tzfree (tz));
+ IF_LINT (free (format_copy));
return ok ? EXIT_SUCCESS : EXIT_FAILURE;
}
--
2.32.0
From 840ae54cf5e7b1bfa5755f7bb70c1b671ec36190 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Fri, 31 Dec 2021 00:45:03 -0800
Subject: [PATCH 5/5] date: new option --resolution
* NEWS, doc/coreutils.texi (Options for date): Mention this.
* src/date.c (RESOLUTION_OPTION): New constant.
(DEBUG_DATE_PARSING_OPTION): Rename from DEBUG_DATE_PARSING.
All uses changed.
(long_options, usage, main): Support --resolution.
---
NEWS | 2 ++
doc/coreutils.texi | 13 +++++++++++++
src/date.c | 40 +++++++++++++++++++++++++++++-----------
3 files changed, 44 insertions(+), 11 deletions(-)
diff --git a/NEWS b/NEWS
index 79320820f..7ce6a698f 100644
--- a/NEWS
+++ b/NEWS
@@ -50,6 +50,8 @@ GNU coreutils NEWS -*- outline -*-
not already exist, and cp is preserving mode and timestamps (e.g.,
'cp -p', 'cp -a').
+ The new 'date' option --resolution outputs the timestamp resolution.
+
sort --debug now diagnoses issues with --field-separator characters
that conflict with characters possibly used in numbers.
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index aa970da6c..4cd3d11b6 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -16436,6 +16436,19 @@ for the @option{--date} (@option{-d}) and @option{--file}
Display the date and time of the last modification of @var{file},
instead of the current date and time.
+@item --resolution
+@opindex --resolution
+Display the timestamp resolution instead of the time.
+Current clock timestamps that are output by @command{date}
+are integer multiples of the timestamp resolution.
+With this option, the format defaults to @samp{%s.%N}.
+For example, if the clock resolution is 1 millsecond,
+the output is:
+
+@example
+0.001000000
+@end example
+
@item -R
@itemx --rfc-email
@opindex -R
diff --git a/src/date.c b/src/date.c
index b0a53ba6c..b92c8ae5c 100644
--- a/src/date.c
+++ b/src/date.c
@@ -79,8 +79,9 @@ static char const rfc_email_format[] = "%a, %d %b %Y %H:%M:%S %z";
non-character as a pseudo short option, starting with CHAR_MAX + 1. */
enum
{
- RFC_3339_OPTION = CHAR_MAX + 1,
- DEBUG_DATE_PARSING
+ DEBUG_DATE_PARSING_OPTION = CHAR_MAX + 1,
+ RESOLUTION_OPTION,
+ RFC_3339_OPTION
};
static char const short_options[] = "d:f:I::r:Rs:u";
@@ -88,10 +89,11 @@ static char const short_options[] = "d:f:I::r:Rs:u";
static struct option const long_options[] =
{
{"date", required_argument, NULL, 'd'},
- {"debug", no_argument, NULL, DEBUG_DATE_PARSING},
+ {"debug", no_argument, NULL, DEBUG_DATE_PARSING_OPTION},
{"file", required_argument, NULL, 'f'},
{"iso-8601", optional_argument, NULL, 'I'},
{"reference", required_argument, NULL, 'r'},
+ {"resolution", no_argument, NULL, RESOLUTION_OPTION},
{"rfc-email", no_argument, NULL, 'R'},
{"rfc-822", no_argument, NULL, 'R'},
{"rfc-2822", no_argument, NULL, 'R'},
@@ -154,6 +156,10 @@ Display the current time in the given FORMAT, or set the system date.\n\
'hours', 'minutes', 'seconds', or 'ns'\n\
for date and time to the indicated precision.\n\
Example: 2006-08-14T02:34:56-06:00\n\
+"), stdout);
+ fputs (_("\
+ --resolution output the available resolution of timestamps\n\
+ Example: 0.000000001\n\
"), stdout);
fputs (_("\
-R, --rfc-email output date and time in RFC 5322 format.\n\
@@ -386,11 +392,11 @@ main (int argc, char **argv)
struct timespec when;
bool set_date = false;
char const *format = NULL;
+ bool get_resolution = false;
char *batch_file = NULL;
char *reference = NULL;
struct stat refstats;
bool ok;
- int option_specified_date;
initialize_main (&argc, &argv);
set_program_name (argv[0]);
@@ -410,12 +416,15 @@ main (int argc, char **argv)
case 'd':
datestr = optarg;
break;
- case DEBUG_DATE_PARSING:
+ case DEBUG_DATE_PARSING_OPTION:
parse_datetime_flags |= PARSE_DATETIME_DEBUG;
break;
case 'f':
batch_file = optarg;
break;
+ case RESOLUTION_OPTION:
+ get_resolution = true;
+ break;
case RFC_3339_OPTION:
{
static char const rfc_3339_format[][32] =
@@ -479,9 +488,8 @@ main (int argc, char **argv)
}
}
- option_specified_date = ((datestr ? 1 : 0)
- + (batch_file ? 1 : 0)
- + (reference ? 1 : 0));
+ int option_specified_date = (!!datestr + !!batch_file + !!reference
+ + get_resolution);
if (option_specified_date > 1)
{
@@ -524,9 +532,12 @@ main (int argc, char **argv)
if (!format)
{
- format = DATE_FMT_LANGINFO ();
- if (! *format)
+ if (get_resolution)
+ format = "%s.%N";
+ else
{
+ format = DATE_FMT_LANGINFO ();
+
/* Do not wrap the following literal format string with _(...).
For example, suppose LC_ALL is unset, LC_TIME=POSIX,
and LANG="ko_KR". In that case, POSIX says that LC_TIME
@@ -534,7 +545,8 @@ main (int argc, char **argv)
written by date, which means "date" must generate output
using the POSIX locale; but adding _() would cause "date"
to use a Korean translation of the format. */
- format = "%a %b %e %H:%M:%S %Z %Y";
+ if (! *format)
+ format = "%a %b %e %H:%M:%S %Z %Y";
}
}
@@ -579,6 +591,12 @@ main (int argc, char **argv)
die (EXIT_FAILURE, errno, "%s", quotef (reference));
when = get_stat_mtime (&refstats);
}
+ else if (get_resolution)
+ {
+ long int res = gettime_res ();
+ when.tv_sec = res / TIMESPEC_HZ;
+ when.tv_nsec = res % TIMESPEC_HZ;
+ }
else
{
if (set_datestr)
--
2.32.0