date: recognize bogus FreeBSD gmtime output

Most gmtime implementations return a NULL value when they encounter an error (and this behavior is specified by ANSI C and POSIX). FreeBSD's implementation, however, will simply leave the "struct tm" untouched. Let's also recognize this and convert it to a NULL (with this patch, t4212 should pass on FreeBSD). Reported-by: René Scharfe <l.s.r@web.de> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Apr 1, 2014 at 17:28 UTC 6654754779d2a90af91a9c6b93d7e4e7ee16cfab
4 files changed +45
Makefile
+8
@@ -342,6 +342,9 @@ all::
342 # Define DEFAULT_HELP_FORMAT to "man", "info" or "html"
343 # (defaults to "man") if you want to have a different default when
344 # "git help" is called without a parameter specifying the format.
345 +#
346 +# Define GMTIME_UNRELIABLE_ERRORS if your gmtime() function does not
347 +# return NULL when it receives a bogus time_t.
348
349 GIT-VERSION-FILE: FORCE
350 @$(SHELL_PATH) ./GIT-VERSION-GEN
@@ -1464,6 +1467,11 @@ ifneq (,$(XDL_FAST_HASH))
1467 BASIC_CFLAGS += -DXDL_FAST_HASH
1468 endif
1469
1470 +ifdef GMTIME_UNRELIABLE_ERRORS
1471 + COMPAT_OBJS += compat/gmtime.o
1472 + BASIC_CFLAGS += -DGMTIME_UNRELIABLE_ERRORS
1473 +endif
1474 +
1475 ifeq ($(TCLTK_PATH),)
1476 NO_TCLTK = NoThanks
1477 endif
compat/gmtime.c new
+29
@@ -0,0 +1,29 @@
1 +#include "../git-compat-util.h"
2 +#undef gmtime
3 +#undef gmtime_r
4 +
5 +struct tm *git_gmtime(const time_t *timep)
6 +{
7 + static struct tm result;
8 + return git_gmtime_r(timep, &result);
9 +}
10 +
11 +struct tm *git_gmtime_r(const time_t *timep, struct tm *result)
12 +{
13 + struct tm *ret;
14 +
15 + memset(result, 0, sizeof(*result));
16 + ret = gmtime_r(timep, result);
17 +
18 + /*
19 + * Rather than NULL, FreeBSD gmtime simply leaves the "struct tm"
20 + * untouched when it encounters overflow. Since "mday" cannot otherwise
21 + * be zero, we can test this very quickly.
22 + */
23 + if (ret && !ret->tm_mday) {
24 + ret = NULL;
25 + errno = EOVERFLOW;
26 + }
27 +
28 + return ret;
29 +}
config.mak.uname
+1
@@ -189,6 +189,7 @@ ifeq ($(uname_S),FreeBSD)
189 endif
190 PYTHON_PATH = /usr/local/bin/python
191 HAVE_PATHS_H = YesPlease
192 + GMTIME_UNRELIABLE_ERRORS = UnfortunatelyYes
193 endif
194 ifeq ($(uname_S),OpenBSD)
195 NO_STRCASESTR = YesPlease
git-compat-util.h
+7
@@ -697,4 +697,11 @@ void warn_on_inaccessible(const char *path);
697 /* Get the passwd entry for the UID of the current process. */
698 struct passwd *xgetpwuid_self(void);
699
700 +#ifdef GMTIME_UNRELIABLE_ERRORS
701 +struct tm *git_gmtime(const time_t *);
702 +struct tm *git_gmtime_r(const time_t *, struct tm *);
703 +#define gmtime git_gmtime
704 +#define gmtime_r git_gmtime_r
705 +#endif
706 +
707 #endif