diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2020-08-15 16:05:35 -0700 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2020-08-15 16:06:29 -0700 |
commit | c863cc75571098bf0aac1c2fb87b74cb9016dc68 (patch) | |
tree | 86102eea0b96105e6d7941a1f5b46c77d2c23bfa /lib | |
parent | 4b612ed38a58801c05b650c845bc56cd906bed18 (diff) | |
download | gnulib-c863cc75571098bf0aac1c2fb87b74cb9016dc68.tar.gz |
nstrftime: be more predictable about errno
This aligns nstrftime better with draft POSIX 202x strftime.
* lib/nstrftime.c: Include errno.h.
(width_add, __strftime_internal): Set errno on failure,
and preserve it on success. Check for mktime_z failure.
* modules/nstrftime (Depends-on): Add errno.
* modules/nstrftime-tests (Depends-on): Add atoll, intprops.
* tests/test-nstrftime.c: Include intprops.h, limits.h.
(errno_test): New test function.
(main): Call it.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/nstrftime.c | 14 | ||||
-rw-r--r-- | lib/strftime.h | 7 |
2 files changed, 19 insertions, 2 deletions
diff --git a/lib/nstrftime.c b/lib/nstrftime.c index 35b65bbbd6..28bc42fd66 100644 --- a/lib/nstrftime.c +++ b/lib/nstrftime.c @@ -33,6 +33,7 @@ #endif #include <ctype.h> +#include <errno.h> #include <time.h> #if HAVE_TZNAME && !HAVE_DECL_TZNAME @@ -162,7 +163,10 @@ extern char *tzname[]; size_t _w = pad == L_('-') || width < 0 ? 0 : width; \ size_t _incr = _n < _w ? _w : _n; \ if (_incr >= maxsize - i) \ - return 0; \ + { \ + errno = ERANGE; \ + return 0; \ + } \ if (p) \ { \ if (_n < _w) \ @@ -447,6 +451,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) size_t maxsize = (size_t) -1; #endif + int saved_errno = errno; int hour12 = tp->tm_hour; #ifdef _NL_CURRENT /* We cannot make the following values variables since we must delay @@ -1186,7 +1191,13 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) time_t t; ltm = *tp; + ltm.tm_yday = -1; t = mktime_z (tz, <m); + if (ltm.tm_yday < 0) + { + errno = EOVERFLOW; + return 0; + } /* Generate string value for T using time_t arithmetic; this works even if sizeof (long) < sizeof (time_t). */ @@ -1484,5 +1495,6 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) *p = L_('\0'); #endif + errno = saved_errno; return i; } diff --git a/lib/strftime.h b/lib/strftime.h index e850163157..fe0c4195a5 100644 --- a/lib/strftime.h +++ b/lib/strftime.h @@ -24,7 +24,12 @@ extern "C" { /* Just like strftime, but with two more arguments: POSIX requires that strftime use the local timezone information. Use the timezone __TZ instead. Use __NS as the number of - nanoseconds in the %N directive. */ + nanoseconds in the %N directive. + + On error, set errno and return 0. Otherwise, return the number of + bytes generated (not counting the trailing NUL), preserving errno + if the number is 0. This errno behavior is in draft POSIX 202x + plus some requested changes to POSIX. */ size_t nstrftime (char *restrict, size_t, char const *, struct tm const *, timezone_t __tz, int __ns); |