summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2020-08-15 16:05:35 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2020-08-15 16:06:29 -0700
commitc863cc75571098bf0aac1c2fb87b74cb9016dc68 (patch)
tree86102eea0b96105e6d7941a1f5b46c77d2c23bfa /lib
parent4b612ed38a58801c05b650c845bc56cd906bed18 (diff)
downloadgnulib-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.c14
-rw-r--r--lib/strftime.h7
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, &ltm);
+ 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);