1 /* gettime.c - Wrapper for time functions
2 * Copyright (C) 1998, 2002, 2007, 2011 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * This file is free software; you can redistribute it and/or modify
7 * it under the terms of either
9 * - the GNU Lesser General Public License as published by the Free
10 * Software Foundation; either version 3 of the License, or (at
11 * your option) any later version.
15 * - the GNU General Public License as published by the Free
16 * Software Foundation; either version 2 of the License, or (at
17 * your option) any later version.
19 * or both in parallel, as here.
21 * This file is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, see <https://www.gnu.org/licenses/>.
34 #ifdef HAVE_LANGINFO_H
42 #ifdef HAVE_UNSIGNED_TIME_T
43 # define IS_INVALID_TIME_T(a) ((a) == (time_t)(-1))
45 /* Error or 32 bit time_t and value after 2038-01-19. */
46 # define IS_INVALID_TIME_T(a) ((a) < 0)
50 static unsigned long timewarp;
51 static enum { NORMAL = 0, FROZEN, FUTURE, PAST } timemode;
53 /* Correction used to map to real Julian days. */
54 #define JD_DIFF 1721060L
57 /* Wrapper for the time(3). We use this here so we can fake the time
62 time_t current = time (NULL);
63 if (current == (time_t)(-1))
64 log_fatal ("time() failed\n");
66 if (timemode == NORMAL)
68 else if (timemode == FROZEN)
70 else if (timemode == FUTURE)
71 return current + timewarp;
73 return current - timewarp;
77 /* Wrapper around gmtime_r.
79 On systems without gmtime_r this implementation works within gnupg
80 because we use only one thread a time. FIXME: An independent
81 library may use gmtime in one of its own thread (or via
82 npth_enter/npth_leave) - in this case we run into a problem. The
83 solution would be to use a mutex here. */
85 gnupg_gmtime (const time_t *timep, struct tm *result)
88 return gmtime_r (timep, result);
94 memcpy (result, tp, sizeof *result);
100 /* Return the current time (possibly faked) in ISO format. */
102 gnupg_get_isotime (gnupg_isotime_t timebuf)
104 time_t atime = gnupg_get_time ();
108 tp = gnupg_gmtime (&atime, &tmbuf);
112 snprintf (timebuf, 16, "%04d%02d%02dT%02d%02d%02d",
113 1900 + tp->tm_year, tp->tm_mon+1, tp->tm_mday,
114 tp->tm_hour, tp->tm_min, tp->tm_sec);
118 /* Set the time to NEWTIME so that gnupg_get_time returns a time
119 starting with this one. With FREEZE set to 1 the returned time
120 will never change. Just for completeness, a value of (time_t)-1
121 for NEWTIME gets you back to reality. Note that this is obviously
122 not thread-safe but this is not required. */
124 gnupg_set_time (time_t newtime, int freeze)
126 time_t current = time (NULL);
128 if ( newtime == (time_t)-1 || current == newtime)
136 timewarp = newtime == (time_t)-1 ? current : newtime;
138 else if (newtime > current)
141 timewarp = newtime - current;
146 timewarp = current - newtime;
150 /* Returns true when we are in timewarp mode */
152 gnupg_faked_time_p (void)
158 /* This function is used by gpg because OpenPGP defines the timestamp
159 as an unsigned 32 bit value. */
161 make_timestamp (void)
163 time_t t = gnupg_get_time ();
170 * Scan a date string and return a timestamp.
171 * The only supported format is "yyyy-mm-dd"
172 * Returns 0 for an invalid date.
175 scan_isodatestr( const char *string )
177 int year, month, day;
182 if( strlen(string) != 10 || string[4] != '-' || string[7] != '-' )
184 for( i=0; i < 4; i++ )
185 if( !digitp (string+i) )
187 if( !digitp (string+5) || !digitp(string+6) )
189 if( !digitp(string+8) || !digitp(string+9) )
192 month = atoi(string+5);
193 day = atoi(string+8);
194 /* some basic checks */
195 if( year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 )
197 memset( &tmbuf, 0, sizeof tmbuf );
199 tmbuf.tm_mon = month-1;
200 tmbuf.tm_year = year - 1900;
202 stamp = mktime( &tmbuf );
203 if( stamp == (time_t)-1 )
210 isotime_p (const char *string)
217 for (s=string, i=0; i < 8; i++, s++)
222 for (s++, i=9; i < 15; i++, s++)
225 if ( !(!*s || (isascii (*s) && isspace(*s)) || *s == ':' || *s == ','))
226 return 0; /* Wrong delimiter. */
232 /* Scan a string and return true if the string represents the human
233 readable format of an ISO time. This format is:
234 yyyy-mm-dd[ hh[:mm[:ss]]]
235 Scanning stops at the second space or at a comma. If DATE_ONLY is
236 true the time part is not expected and the scanning stops at the
237 first space or at a comma. */
239 isotime_human_p (const char *string, int date_only)
246 for (s=string, i=0; i < 4; i++, s++)
252 if (!digitp (s) || !digitp (s+1) || s[2] != '-')
258 if (!digitp (s) || !digitp (s+1))
264 if (!*s || *s == ',')
265 return 1; /* Okay; only date given. */
269 return 1; /* Okay; only date was requested. */
272 return 1; /* Okay, second space stops scanning. */
273 if (!digitp (s) || !digitp (s+1))
279 if (!*s || *s == ',')
280 return 1; /* Okay; only date and hour given. */
284 if (!digitp (s) || !digitp (s+1))
290 if (!*s || *s == ',')
291 return 1; /* Okay; only date, hour and minute given. */
295 if (!digitp (s) || !digitp (s+1))
301 if (!*s || *s == ',' || spacep (s))
302 return 1; /* Okay; date, hour and minute and second given. */
304 return 0; /* Unexpected delimiter. */
307 /* Convert a standard isotime or a human readable variant into an
308 isotime structure. The allowed formats are those described by
309 isotime_p and isotime_human_p. The function returns 0 on failure
310 or the length of the scanned string on success. */
312 string2isotime (gnupg_isotime_t atime, const char *string)
314 gnupg_isotime_t dummyatime;
320 if (isotime_p (string))
322 memcpy (atime, string, 15);
326 if (!isotime_human_p (string, 0))
328 atime[0] = string[0];
329 atime[1] = string[1];
330 atime[2] = string[2];
331 atime[3] = string[3];
332 atime[4] = string[5];
333 atime[5] = string[6];
334 atime[6] = string[8];
335 atime[7] = string[9];
337 memset (atime+9, '0', 6);
339 if (!spacep (string+10))
341 if (spacep (string+11))
342 return 11; /* As per def, second space stops scanning. */
343 atime[9] = string[11];
344 atime[10] = string[12];
345 if (string[13] != ':')
347 atime[11] = string[14];
348 atime[12] = string[15];
349 if (string[16] != ':')
351 atime[13] = string[17];
352 atime[14] = string[18];
357 /* Scan an ISO timestamp and return an Epoch based timestamp. The only
358 supported format is "yyyymmddThhmmss" delimited by white space, nul, a
359 colon or a comma. Returns (time_t)(-1) for an invalid string. */
361 isotime2epoch (const char *string)
363 int year, month, day, hour, minu, sec;
366 if (!isotime_p (string))
369 year = atoi_4 (string);
370 month = atoi_2 (string + 4);
371 day = atoi_2 (string + 6);
372 hour = atoi_2 (string + 9);
373 minu = atoi_2 (string + 11);
374 sec = atoi_2 (string + 13);
377 if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31
378 || hour > 23 || minu > 59 || sec > 61 )
381 memset (&tmbuf, 0, sizeof tmbuf);
384 tmbuf.tm_hour = hour;
386 tmbuf.tm_mon = month-1;
387 tmbuf.tm_year = year - 1900;
389 return timegm (&tmbuf);
393 /* Convert an Epoch time to an iso time stamp. */
395 epoch2isotime (gnupg_isotime_t timebuf, time_t atime)
397 if (atime == (time_t)(-1))
405 tp = gmtime_r (&atime, &tmbuf);
407 tp = gmtime (&atime);
409 snprintf (timebuf, 16, "%04d%02d%02dT%02d%02d%02d",
410 1900 + tp->tm_year, tp->tm_mon+1, tp->tm_mday,
411 tp->tm_hour, tp->tm_min, tp->tm_sec);
416 /* Parse a short ISO date string (YYYY-MM-DD) into a TM structure.
417 Returns 0 on success. */
419 isodate_human_to_tm (const char *string, struct tm *t)
421 int year, month, day;
423 if (!isotime_human_p (string, 1))
426 year = atoi_4 (string);
427 month = atoi_2 (string + 5);
428 day = atoi_2 (string + 8);
431 if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31)
434 memset (t, 0, sizeof *t);
440 t->tm_year = year - 1900;
446 /* This function is a copy of gpgme/src/conversion.c:_gpgme_timegm.
447 If you change it, then update the other one too. */
448 #ifdef HAVE_W32_SYSTEM
450 _win32_timegm (struct tm *tm)
452 /* This one is thread safe. */
455 unsigned long long cnsecs;
457 st.wYear = tm->tm_year + 1900;
458 st.wMonth = tm->tm_mon + 1;
459 st.wDay = tm->tm_mday;
460 st.wHour = tm->tm_hour;
461 st.wMinute = tm->tm_min;
462 st.wSecond = tm->tm_sec;
463 st.wMilliseconds = 0; /* Not available. */
464 st.wDayOfWeek = 0; /* Ignored. */
466 /* System time is UTC thus the conversion is pretty easy. */
467 if (!SystemTimeToFileTime (&st, &ft))
469 gpg_err_set_errno (EINVAL);
473 cnsecs = (((unsigned long long)ft.dwHighDateTime << 32)
475 cnsecs -= 116444736000000000ULL; /* The filetime epoch is 1601-01-01. */
476 return (time_t)(cnsecs / 10000000ULL);
481 /* Parse the string TIMESTAMP into a time_t. The string may either be
482 seconds since Epoch or in the ISO 8601 format like
483 "20390815T143012". Returns 0 for an empty string or seconds since
484 Epoch. Leading spaces are skipped. If ENDP is not NULL, it will
485 point to the next non-parsed character in TIMESTRING.
487 This function is a copy of
488 gpgme/src/conversion.c:_gpgme_parse_timestamp. If you change it,
489 then update the other one too. */
491 parse_timestamp (const char *timestamp, char **endp)
493 /* Need to skip leading spaces, because that is what strtoul does
494 but not our ISO 8601 checking code. */
495 while (*timestamp && *timestamp== ' ')
500 if (strlen (timestamp) >= 15 && timestamp[8] == 'T')
505 year = atoi_4 (timestamp);
510 *endp = (char*)(timestamp + 15);
512 /* Fixme: We would better use a configure test to see whether
513 mktime can handle dates beyond 2038. */
514 if (sizeof (time_t) <= 4 && year >= 2038)
515 return (time_t)2145914603; /* 2037-12-31 23:23:23 */
517 memset (&buf, 0, sizeof buf);
518 buf.tm_year = year - 1900;
519 buf.tm_mon = atoi_2 (timestamp+4) - 1;
520 buf.tm_mday = atoi_2 (timestamp+6);
521 buf.tm_hour = atoi_2 (timestamp+9);
522 buf.tm_min = atoi_2 (timestamp+11);
523 buf.tm_sec = atoi_2 (timestamp+13);
525 #ifdef HAVE_W32_SYSTEM
526 return _win32_timegm (&buf);
529 return timegm (&buf);
537 #warning fixme: we must somehow reset TZ here. It is not threadsafe anyway.
541 #endif /* !HAVE_TIMEGM */
542 #endif /* !HAVE_W32_SYSTEM */
545 return (time_t)strtoul (timestamp, endp, 10);
551 add_days_to_timestamp( u32 stamp, u16 days )
553 return stamp + days*86400L;
558 * Return a string with a time value in the form: x Y, n D, n H
562 strtimevalue( u32 value )
564 static char buffer[30];
565 unsigned int years, days, hours, minutes;
568 minutes = value % 60;
576 sprintf(buffer,"%uy%ud%uh%um", years, days, hours, minutes );
580 return strchr( buffer, 'y' ) + 1;
581 return strchr( buffer, 'd' ) + 1;
586 /* Return a malloced string with the time elapsed between NOW and
587 SINCE. May return NULL on error. */
589 elapsed_time_string (time_t since, time_t now)
594 unsigned int days, hours, minutes, seconds;
597 now = gnupg_get_time ();
599 diff = difftime (now, since);
601 return xtrystrdup ("time-warp");
603 seconds = (unsigned long)diff % 60;
604 value = (unsigned long)(diff / 60);
605 minutes = value % 60;
612 result = xtryasprintf ("%ud%uh%um%us", days, hours, minutes, seconds);
614 result = xtryasprintf ("%uh%um%us", hours, minutes, seconds);
616 result = xtryasprintf ("%um%us", minutes, seconds);
618 result = xtryasprintf ("%us", seconds);
625 * Note: this function returns GMT
628 strtimestamp (u32 stamp)
630 static char buffer[11+5];
632 time_t atime = stamp;
634 if (IS_INVALID_TIME_T (atime))
636 strcpy (buffer, "????" "-??" "-??");
640 tp = gmtime( &atime );
641 snprintf (buffer, sizeof buffer, "%04d-%02d-%02d",
642 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
649 * Note: this function returns GMT
652 isotimestamp (u32 stamp)
654 static char buffer[25+5];
656 time_t atime = stamp;
658 if (IS_INVALID_TIME_T (atime))
660 strcpy (buffer, "????" "-??" "-??" " " "??" ":" "??" ":" "??");
664 tp = gmtime ( &atime );
665 snprintf (buffer, sizeof buffer, "%04d-%02d-%02d %02d:%02d:%02d",
666 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
667 tp->tm_hour, tp->tm_min, tp->tm_sec);
674 * Note: this function returns local time
677 asctimestamp (u32 stamp)
679 static char buffer[50];
680 #if defined (HAVE_STRFTIME) && defined (HAVE_NL_LANGINFO)
684 time_t atime = stamp;
686 if (IS_INVALID_TIME_T (atime))
688 strcpy (buffer, "????" "-??" "-??");
692 tp = localtime( &atime );
694 # if defined(HAVE_NL_LANGINFO)
695 mem2str( fmt, nl_langinfo(D_T_FMT), DIM(fmt)-3 );
696 if (!strstr( fmt, "%Z" ))
698 /* NOTE: gcc -Wformat-noliteral will complain here. I have found no
699 way to suppress this warning. */
700 strftime (buffer, DIM(buffer)-1, fmt, tp);
701 # elif defined(HAVE_W32CE_SYSTEM)
702 /* tzset is not available but %Z nevertheless prints a default
703 nonsense timezone ("WILDABBR"). Thus we don't print the time
705 strftime (buffer, DIM(buffer)-1, "%c", tp);
707 /* FIXME: we should check whether the locale appends a " %Z" These
708 * locales from glibc don't put the " %Z": fi_FI hr_HR ja_JP lt_LT
709 * lv_LV POSIX ru_RU ru_SU sv_FI sv_SE zh_CN. */
710 strftime (buffer, DIM(buffer)-1, "%c %Z", tp);
712 buffer[DIM(buffer)-1] = 0;
714 mem2str( buffer, asctime(tp), DIM(buffer) );
720 /* Return the timestamp STAMP in RFC-2822 format. This is always done
721 * in the C locale. We return the gmtime to avoid computing the
722 * timezone. The caller must release the returned string.
724 * Example: "Mon, 27 Jun 2016 1:42:00 +0000".
727 rfctimestamp (u32 stamp)
729 time_t atime = stamp;
730 struct tm tmbuf, *tp;
733 if (IS_INVALID_TIME_T (atime))
735 gpg_err_set_errno (EINVAL);
739 tp = gnupg_gmtime (&atime, &tmbuf);
742 return xtryasprintf ("%.3s, %02d %.3s %04d %02d:%02d:%02d +0000",
743 &"SunMonTueWedThuFriSat"[(tp->tm_wday%7)*3],
745 &"JanFebMarAprMayJunJulAugSepOctNovDec"
755 days_per_year (int y)
763 return s ? 366 : 365;
767 days_per_month (int y, int m)
773 case 1: case 3: case 5: case 7: case 8: case 10: case 12:
781 case 4: case 6: case 9: case 11:
788 /* Convert YEAR, MONTH and DAY into the Julian date. We assume that
789 it is already noon. We do not support dates before 1582-10-15. */
791 date2jd (int year, int month, int day)
795 jd = 365L * year + 31 * (month-1) + day + JD_DIFF;
799 jd -= (4 * month + 23) / 10;
801 jd += year / 4 - ((year / 100 + 1) *3) / 4;
806 /* Convert a Julian date back to YEAR, MONTH and DAY. Return day of
807 the year or 0 on error. This function uses some more or less
808 arbitrary limits, most important is that days before 1582 are not
811 jd2date (unsigned long jd, int *year, int *month, int *day)
818 if (jd < 1721425 || jd > 2843085)
821 y = (jd - JD_DIFF) / 366;
824 while ((delta = jd - date2jd (y, m, d)) > days_per_year (y))
827 m = (delta / 31) + 1;
828 while( (delta = jd - date2jd (y, m, d)) > days_per_month (y,m))
836 if (d > days_per_month (y, m))
854 return (jd - date2jd (y, 1, 1)) + 1;
858 /* Check that the 15 bytes in ATIME represent a valid ISO time. Note
859 that this function does not expect a string but a plain 15 byte
862 check_isotime (const gnupg_isotime_t atime)
868 return gpg_error (GPG_ERR_NO_VALUE);
870 for (s=atime, i=0; i < 8; i++, s++)
872 return gpg_error (GPG_ERR_INV_TIME);
874 return gpg_error (GPG_ERR_INV_TIME);
875 for (s++, i=9; i < 15; i++, s++)
877 return gpg_error (GPG_ERR_INV_TIME);
882 /* Dump the ISO time T to the log stream without a LF. */
884 dump_isotime (const gnupg_isotime_t t)
887 log_printf ("%s", _("[none]"));
889 log_printf ("%.4s-%.2s-%.2s %.2s:%.2s:%s",
890 t, t+4, t+6, t+9, t+11, t+13);
894 /* Copy one ISO date to another, this is inline so that we can do a
895 minimal sanity check. A null date (empty string) is allowed. */
897 gnupg_copy_time (gnupg_isotime_t d, const gnupg_isotime_t s)
901 if ((strlen (s) != 15 || s[8] != 'T'))
911 /* Add SECONDS to ATIME. SECONDS may not be negative and is limited
912 to about the equivalent of 62 years which should be more then
913 enough for our purposes. */
915 add_seconds_to_isotime (gnupg_isotime_t atime, int nseconds)
918 int year, month, day, hour, minute, sec, ndays;
921 err = check_isotime (atime);
925 if (nseconds < 0 || nseconds >= (0x7fffffff - 61) )
926 return gpg_error (GPG_ERR_INV_VALUE);
928 year = atoi_4 (atime+0);
929 month = atoi_2 (atime+4);
930 day = atoi_2 (atime+6);
931 hour = atoi_2 (atime+9);
932 minute= atoi_2 (atime+11);
933 sec = atoi_2 (atime+13);
935 if (year <= 1582) /* The julian date functions don't support this. */
936 return gpg_error (GPG_ERR_INV_VALUE);
946 jd = date2jd (year, month, day) + ndays;
947 jd2date (jd, &year, &month, &day);
949 if (year > 9999 || month > 12 || day > 31
950 || year < 0 || month < 1 || day < 1)
951 return gpg_error (GPG_ERR_INV_VALUE);
953 snprintf (atime, 16, "%04d%02d%02dT%02d%02d%02d",
954 year, month, day, hour, minute, sec);
960 add_days_to_isotime (gnupg_isotime_t atime, int ndays)
963 int year, month, day, hour, minute, sec;
966 err = check_isotime (atime);
970 if (ndays < 0 || ndays >= 9999*366 )
971 return gpg_error (GPG_ERR_INV_VALUE);
973 year = atoi_4 (atime+0);
974 month = atoi_2 (atime+4);
975 day = atoi_2 (atime+6);
976 hour = atoi_2 (atime+9);
977 minute= atoi_2 (atime+11);
978 sec = atoi_2 (atime+13);
980 if (year <= 1582) /* The julian date functions don't support this. */
981 return gpg_error (GPG_ERR_INV_VALUE);
983 jd = date2jd (year, month, day) + ndays;
984 jd2date (jd, &year, &month, &day);
986 if (year > 9999 || month > 12 || day > 31
987 || year < 0 || month < 1 || day < 1)
988 return gpg_error (GPG_ERR_INV_VALUE);
990 snprintf (atime, 16, "%04d%02d%02dT%02d%02d%02d",
991 year, month, day, hour, minute, sec);