143003dfeSmillert /* A helper tool for perl's 2038 support.
243003dfeSmillert * See Porting/README.y2038 for details
343003dfeSmillert */
443003dfeSmillert
543003dfeSmillert #include <sys/types.h>
643003dfeSmillert #include <stdio.h>
743003dfeSmillert #include <time.h>
843003dfeSmillert #include <errno.h>
9*f3efcd01Safresh1 #include <string.h>
1043003dfeSmillert
1143003dfeSmillert int opt_v = 0;
1243003dfeSmillert int i;
1343003dfeSmillert struct tm *tmp;
1443003dfeSmillert time_t pt, pt_max, pt_min;
1543003dfeSmillert
1643003dfeSmillert static char hexbuf[80];
hex(time_t t)1743003dfeSmillert char *hex (time_t t)
1843003dfeSmillert {
1943003dfeSmillert if ((long long)t < 0)
2043003dfeSmillert sprintf (hexbuf, " -0x%016lx", -t);
2143003dfeSmillert else
2243003dfeSmillert sprintf (hexbuf, " 0x%016lx", t);
2343003dfeSmillert return (hexbuf);
2443003dfeSmillert } /* hex */
2543003dfeSmillert
gm_check(time_t t,int min_year,int max_year)2643003dfeSmillert void gm_check (time_t t, int min_year, int max_year)
2743003dfeSmillert {
2843003dfeSmillert tmp = gmtime (&t);
2943003dfeSmillert if ( tmp == NULL ||
3043003dfeSmillert /* Check tm_year overflow */
3143003dfeSmillert tmp->tm_year < min_year || tmp->tm_year > max_year) {
3243003dfeSmillert if (opt_v)
3343003dfeSmillert fprintf (stderr, "gmtime (%ld) failed with errno %d\n", t, errno);
3443003dfeSmillert }
3543003dfeSmillert else {
3643003dfeSmillert if (opt_v)
3743003dfeSmillert fprintf (stderr, "%3d:%s: %12ld-%02d-%02d %02d:%02d:%02d\n",
3843003dfeSmillert i, hex (t),
39*f3efcd01Safresh1 (long)(tmp->tm_year) + 1900, tmp->tm_mon + 1, tmp->tm_mday,
4043003dfeSmillert tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
4143003dfeSmillert pt = t;
4243003dfeSmillert }
4343003dfeSmillert } /* gm_check */
4443003dfeSmillert
check_gm_max()4543003dfeSmillert int check_gm_max ()
4643003dfeSmillert {
4743003dfeSmillert tmp = NULL;
4843003dfeSmillert pt = 0;
4943003dfeSmillert if (tmp == NULL || tmp->tm_year < 0) {
5043003dfeSmillert for (i = 63; i >= 0; i--) {
5143003dfeSmillert time_t x = pt | ((time_t)1 << i);
5243003dfeSmillert if (x < 0 || x < pt) continue;
5343003dfeSmillert gm_check (x, 69, 0x7fffffff);
5443003dfeSmillert }
5543003dfeSmillert }
5643003dfeSmillert pt_max = pt;
5743003dfeSmillert return (0);
5843003dfeSmillert } /* check_gm_max */
5943003dfeSmillert
check_gm_min()6043003dfeSmillert int check_gm_min ()
6143003dfeSmillert {
6243003dfeSmillert tmp = NULL;
6343003dfeSmillert pt = 0;
6443003dfeSmillert if (tmp == NULL) {
6543003dfeSmillert for (i = 36; i >= 0; i--) {
6643003dfeSmillert time_t x = pt - ((time_t)1 << i);
6743003dfeSmillert if (x > 0) continue;
6843003dfeSmillert gm_check (x, -1900, 70);
6943003dfeSmillert }
7043003dfeSmillert }
7143003dfeSmillert pt_min = pt;
7243003dfeSmillert return (0);
7343003dfeSmillert } /* check_gm_min */
7443003dfeSmillert
lt_check(time_t t,int min_year,int max_year)7543003dfeSmillert void lt_check (time_t t, int min_year, int max_year)
7643003dfeSmillert {
7743003dfeSmillert if (sizeof (time_t) > 4 && t > 0x7ffffffffffff000LL)
7843003dfeSmillert tmp = NULL;
7943003dfeSmillert else
8043003dfeSmillert tmp = localtime (&t);
8143003dfeSmillert if ( tmp == NULL ||
8243003dfeSmillert /* Check tm_year overflow */
8343003dfeSmillert tmp->tm_year < min_year || tmp->tm_year > max_year) {
8443003dfeSmillert if (opt_v)
8543003dfeSmillert fprintf (stderr, "localtime (%ld) failed with errno %d\n", t, errno);
8643003dfeSmillert }
8743003dfeSmillert else {
8843003dfeSmillert if (opt_v)
8943003dfeSmillert fprintf (stderr, "%3d:%s: %12ld-%02d-%02d %02d:%02d:%02d\n",
9043003dfeSmillert i, hex (t),
91*f3efcd01Safresh1 (long)(tmp->tm_year) + 1900, tmp->tm_mon + 1, tmp->tm_mday,
9243003dfeSmillert tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
9343003dfeSmillert pt = t;
9443003dfeSmillert }
9543003dfeSmillert } /* lt_check */
9643003dfeSmillert
check_lt_max()9743003dfeSmillert int check_lt_max ()
9843003dfeSmillert {
9943003dfeSmillert tmp = NULL;
10043003dfeSmillert pt = 0;
10143003dfeSmillert if (tmp == NULL || tmp->tm_year < 0) {
10243003dfeSmillert for (i = 63; i >= 0; i--) {
10343003dfeSmillert time_t x = pt | ((time_t)1 << i);
10443003dfeSmillert if (x < 0 || x < pt) continue;
10543003dfeSmillert lt_check (x, 69, 0x7fffffff);
10643003dfeSmillert }
10743003dfeSmillert }
10843003dfeSmillert pt_max = pt;
10943003dfeSmillert return (0);
11043003dfeSmillert } /* check_lt_max */
11143003dfeSmillert
check_lt_min()11243003dfeSmillert int check_lt_min ()
11343003dfeSmillert {
11443003dfeSmillert tmp = NULL;
11543003dfeSmillert pt = 0;
11643003dfeSmillert if (tmp == NULL) {
11743003dfeSmillert for (i = 36; i >= 0; i--) {
11843003dfeSmillert time_t x = pt - ((time_t)1 << i);
11943003dfeSmillert if (x > 0) continue;
12043003dfeSmillert lt_check (x, -1900, 70);
12143003dfeSmillert }
12243003dfeSmillert }
12343003dfeSmillert pt_min = pt;
12443003dfeSmillert return (0);
12543003dfeSmillert } /* check_lt_min */
12643003dfeSmillert
main(int argc,char * argv[])12743003dfeSmillert int main (int argc, char *argv[])
12843003dfeSmillert {
12943003dfeSmillert time_t gm_max, gm_min, lt_max, lt_min;
13043003dfeSmillert if (argc > 1 && strcmp (argv[1], "-v") == 0) opt_v++;
13143003dfeSmillert
13243003dfeSmillert check_gm_max (); gm_max = pt_max;
13343003dfeSmillert check_gm_min (); gm_min = pt_min;
13443003dfeSmillert check_lt_max (); lt_max = pt_max;
13543003dfeSmillert check_lt_min (); lt_min = pt_min;
13643003dfeSmillert
13743003dfeSmillert opt_v++;
13843003dfeSmillert printf ("======================\n");
139*f3efcd01Safresh1 printf ("Sizeof time_t = %d\n", (i = sizeof (time_t)));
14043003dfeSmillert printf ("gmtime () boundaries:\n");
14143003dfeSmillert gm_check (gm_max, 69, 0x7fffffff);
14243003dfeSmillert gm_check (gm_min, -1900, 70);
14343003dfeSmillert printf ("localtime () boundaries:\n");
14443003dfeSmillert lt_check (lt_max, 69, 0x7fffffff);
14543003dfeSmillert lt_check (lt_min, -1900, 70);
14643003dfeSmillert printf ("Configure variables:\n");
14743003dfeSmillert printf ("sGMTIME_max='%ld'\n", gm_max);
14843003dfeSmillert printf ("sGMTIME_min='%ld'\n", gm_min);
14943003dfeSmillert printf ("sLOCALTIME_max='%ld'\n", lt_max);
15043003dfeSmillert printf ("sLOCALTIME_min='%ld'\n", lt_min);
15143003dfeSmillert return (0);
15243003dfeSmillert } /* main */
153