xref: /openbsd-src/gnu/usr.bin/perl/Porting/timecheck.c (revision 256a93a44f36679bee503f12e49566c2183f6181)
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