1 #include <time.h>
2 #include <errno.h>
3 #include <limits.h>
4 #include <stdbool.h>
5 #include <stdio.h>
6 #include <string.h>
7 
8 static bool
equal_tm(struct tm const * t,struct tm const * u)9 equal_tm (struct tm const *t, struct tm const *u)
10 {
11   return (t->tm_sec == u->tm_sec && t->tm_min == u->tm_min
12 	  && t->tm_hour == u->tm_hour && t->tm_mday == u->tm_mday
13 	  && t->tm_mon == u->tm_mon && t->tm_year == u->tm_year
14 	  && t->tm_wday == u->tm_wday && t->tm_yday == u->tm_yday
15 	  && t->tm_isdst == u->tm_isdst && t->tm_gmtoff == u->tm_gmtoff
16 	  && t->tm_zone == u->tm_zone);
17 }
18 
19 static int
do_test(void)20 do_test (void)
21 {
22   /* Calculate minimum time_t value.  This would be simpler with C11,
23      which has _Generic, but we cannot assume C11.  It would also
24      be simpler with intprops.h, which has TYPE_MINIMUM, but it's
25      better not to use glibc internals.  */
26   time_t time_t_min = -1;
27   time_t_min = (0 < time_t_min ? 0
28 		: sizeof time_t_min == sizeof (long int) ? LONG_MIN
29 		: sizeof time_t_min == sizeof (long long int) ? LLONG_MIN
30 		: 1);
31   if (time_t_min == 1)
32     {
33       printf ("unknown time type\n");
34       return 1;
35     }
36   time_t ymin = time_t_min / 60 / 60 / 24 / 366;
37   bool mktime_should_fail = ymin == 0 || INT_MIN + 1900 < ymin + 1970;
38 
39   struct tm tm0 = { .tm_year = INT_MIN, .tm_mday = 1, .tm_wday = -1 };
40   struct tm tm = tm0;
41   errno = 0;
42   time_t t = mktime (&tm);
43   long long int llt = t;
44   bool mktime_failed = tm.tm_wday == tm0.tm_wday;
45 
46   if (mktime_failed)
47     {
48       if (! mktime_should_fail)
49 	{
50 	  printf ("mktime failed but should have succeeded\n");
51 	  return 1;
52 	}
53       if (errno == 0)
54 	{
55 	  printf ("mktime failed without setting errno");
56 	  return 1;
57 	}
58       if (t != (time_t) -1)
59 	{
60 	  printf ("mktime returned %lld but did not set tm_wday\n", llt);
61 	  return 1;
62 	}
63       if (! equal_tm (&tm, &tm0))
64 	{
65 	  printf ("mktime (P) failed but modified *P\n");
66 	  return 1;
67 	}
68     }
69   else
70     {
71       if (mktime_should_fail)
72 	{
73 	  printf ("mktime succeeded but should have failed\n");
74 	  return 1;
75 	}
76       struct tm *lt = localtime (&t);
77       if (lt == NULL)
78 	{
79 	  printf ("mktime returned a value rejected by localtime\n");
80 	  return 1;
81 	}
82       if (! equal_tm (lt, &tm))
83 	{
84 	  printf ("mktime result does not match localtime result\n");
85 	  return 1;
86 	}
87     }
88   return 0;
89 }
90 
91 #define TIMEOUT 1000
92 #include "support/test-driver.c"
93