Assumption all years since 1970 have been exactly 365 days long has it's
problems when leap years happen. Lets use struct tm fields that are
provided by localtime_r(), making year and day to be correctly compared even
when it's late new years eve somewhere else than UTC-0.
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
Print a message when the format_iso_time() buffer is exceeded, because
there is more than one type of failure that returns -1.
Also remove the corresponding message from hwclock.c.
Signed-off-by: J William Piggott <elseifthen@gmx.com>
Year can wrap when adding the tm struct epoch during iso formatting:
hwclock --utc --noadjfile --predict --date '67768034678844900 seconds'
-2147481749-12-31 23:59:59.000000-05:00
Patched:
hwclock --utc --noadjfile --predict --date '67768034678844900 seconds'
2147485547-12-31 23:59:59.000000-05:00
Comparable to date(1):
date -Ins --date '67768034678844900 seconds'
2147485547-12-31T23:59:59,547886165-0500
Note: the 'seconds' argument is relative to the current time, so
reaching this max year output is a moving target. The values shown
above were invalid one second later. They then overflow tm_year
upon conversion with localtime(3) and friends, which causes them
to return NULL indicating that an error occurred.
Signed-off-by: J William Piggott <elseifthen@gmx.com>
Test for libc time conversion errors in ISO time format functions.
hwclock --utc --noadjfile --predict --date '67768034678846520 seconds'
Segmentation fault
Patched:
hwclock --utc --noadjfile --predict --date '67768034678846520 seconds'
hwclock: time 67768036191695381 is out of range.
Comparable to date(1):
date --date '67768034678846520 seconds'
date: time 67768036191695384 is out of range
Signed-off-by: J William Piggott <elseifthen@gmx.com>
Use reentrant time functions to avoid sending a NULL pointer to
format_iso_time() (and to be reentrant ;). Followup commits test for
errors and tm_year wrapping (illustrated below).
hwclock --utc --noadjfile --predict --date '67768034678849400 seconds'
Segmentation fault
Patched
hwclock --utc --noadjfile --predict --date '67768034678849400 seconds'
-2147481748-01-00 00:10:46.000000-05:00
Signed-off-by: J William Piggott <elseifthen@gmx.com>
* Start the ISO format flags at bit 0 instead of bit 1.
* Remove unnecessary _8601 from ISO format flag names to
avoid line wrapping and to ease readability.
* ISO timestamps have date-time-timzone in common, so move
the TIMEZONE flag to bit 2 causing all timestamp masks
to have the first three bits set and the last four bits
as timestamp 'options'.
* Change the 'SPACE' flag to a 'T' flag, because it makes
the code and comments more concise.
* Add common ISO timestamp masks.
* Implement the ISO timestamp masks in all applicable code
using the strxxx_iso() functions.
Signed-off-by: J William Piggott <elseifthen@gmx.com>
This new function returns the GMT offset relative to its
argument. It is used in this patch to fix two bugs:
1) On platforms that the tm struct excludes tm_gmtoff,
hwclock assumes a one hour DST offset. This can cause
an incorrect kernel timezone setting. For example:
Master branch tested with tm_gmtoff illustrates the correct offset:
$ TZ="Australia/Lord_Howe" hwclock --hctosys --test | grep settimeofday
Calling settimeofday(1507494204.192398, -660)
Master branch tested without tm_gmtoff has an incorrect offset:
$ TZ="Australia/Lord_Howe" hwclock --hctosys --test | grep settimeofday
Calling settimeofday(1507494249.193852, -690)
Patched tested without tm_gmtoff has the correct offset:
$ TZ="Australia/Lord_Howe" hwclock --hctosys --test | grep settimeofday
Calling settimeofday(1507494260.194208, -660)
2) ISO 8601 'extended' format requires all time elements
to use a colon (:).
Current invalid ISO 8601:
$ hwclock
2017-10-08 16:25:17.895462-0400
Patched:
$ hwclock
2017-10-08 16:25:34.141895-04:00
Also required by this change:
login-utils/last.c: increase ISO out_len and in_len by one to
accommodate the addition of the timezone colon.
Signed-off-by: J William Piggott <elseifthen@gmx.com>
Local timegm() is a replacement function in cases it is missing from libc
implementation. Hopefully the replacement is never, or very rarely, used.
CC: Ruediger Meier <ruediger.meier@ga-group.nl>
Reviewed-by: J William Piggott <elseifthen@gmx.com>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
When timestamps are intented to be conversable back from string to binary it
is best to stick with UTC-0 timezone. This is needed in utmpdump(1).
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
- use buffers rather than allocate memory
- support .usec and ,usec convention
- use strftime for timezone (we need to care about daylight
saving time)
Signed-off-by: Karel Zak <kzak@redhat.com>