*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 */
/* See the file NOTICE for conditions of use and distribution. */
/* A function for returning the time of day in various formats */
switch(type)
{
case tod_epoch:
- (void) sprintf(CS timebuf, TIME_T_FMT, now.tv_sec); /* Unix epoch format */
+ (void) snprintf(CS timebuf, sizeof(timebuf), TIME_T_FMT, now.tv_sec); /* Unix epoch format */
return timebuf; /* NB the above will be wrong if time_t is FP */
case tod_epoch_l:
/* Unix epoch/usec format */
- (void) sprintf(CS timebuf, TIME_T_FMT "%06ld", now.tv_sec, (long) now.tv_usec );
+ (void) snprintf(CS timebuf, sizeof(timebuf), TIME_T_FMT "%06ld", now.tv_sec, (long) now.tv_usec );
return timebuf;
case tod_zulu:
t = gmtime(&now.tv_sec);
- (void) sprintf(CS timebuf, "%04d%02d%02d%02d%02d%02dZ",
- 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min,
- t->tm_sec);
+ (void) snprintf(CS timebuf, sizeof(timebuf), "%04u%02u%02u%02u%02u%02uZ",
+ 1900 + (uint)t->tm_year, 1 + (uint)t->tm_mon, (uint)t->tm_mday, (uint)t->tm_hour, (uint)t->tm_min,
+ (uint)t->tm_sec);
return timebuf;
}
case tod_log_bare: /* Format used in logging without timezone */
#ifndef COMPILE_UTILITY
if (LOGGING(millisec))
- sprintf(CS timebuf, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
- 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday,
- t->tm_hour, t->tm_min, t->tm_sec, (int)(now.tv_usec/1000));
+ snprintf(CS timebuf, sizeof(timebuf), "%04u-%02u-%02u %02u:%02u:%02u.%03u",
+ 1900 + (uint)t->tm_year, 1 + (uint)t->tm_mon, (uint)t->tm_mday,
+ (uint)t->tm_hour, (uint)t->tm_min, (uint)t->tm_sec,
+ (uint)(now.tv_usec/1000));
else
#endif
- sprintf(CS timebuf, "%04d-%02d-%02d %02d:%02d:%02d",
- 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday,
- t->tm_hour, t->tm_min, t->tm_sec);
+ snprintf(CS timebuf, sizeof(timebuf), "%04u-%02u-%02u %02u:%02u:%02u",
+ 1900 + (uint)t->tm_year, 1 + (uint)t->tm_mon, (uint)t->tm_mday,
+ (uint)t->tm_hour, (uint)t->tm_min, (uint)t->tm_sec);
break;
#ifdef TESTING_LOG_DATESTAMP
case tod_log_datestamp_daily:
case tod_log_datestamp_monthly:
- sprintf(CS timebuf, "%04d%02d%02d%02d%02d",
- 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min);
+ snprintf(CS timebuf, sizeof(timebuf), "%04u%02u%02u%02u%02u",
+ 1900 + (uint)t->tm_year, 1 + (uint)t->tm_mon, (uint)t->tm_mday,
+ (uint)t->tm_hour, (uint)t->tm_min);
break;
#else
case tod_log_datestamp_daily:
- sprintf(CS timebuf, "%04d%02d%02d",
- 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday);
+ snprintf(CS timebuf, sizeof(timebuf), "%04u%02u%02u",
+ 1900 + (uint)t->tm_year, 1 + (uint)t->tm_mon, (uint)t->tm_mday);
break;
case tod_log_datestamp_monthly:
#ifndef COMPILE_UTILITY
- sprintf(CS timebuf, "%04d%02d",
- 1900 + t->tm_year, 1 + t->tm_mon);
+ snprintf(CS timebuf, sizeof(timebuf), "%04u%02u",
+ 1900 + (uint)t->tm_year, 1 + (uint)t->tm_mon);
#endif
break;
#endif
{
int diff_hour, diff_min;
struct tm local;
- memcpy(&local, t, sizeof(struct tm));
+ struct tm * lp = &local;
+ memcpy(lp, t, sizeof(struct tm));
if (f.timestamps_utc)
diff_hour = diff_min = 0;
{
struct tm * gmt = gmtime(&now.tv_sec);
- diff_min = 60*(local.tm_hour - gmt->tm_hour) + local.tm_min - gmt->tm_min;
- if (local.tm_year != gmt->tm_year)
- diff_min += (local.tm_year > gmt->tm_year)? 1440 : -1440;
- else if (local.tm_yday != gmt->tm_yday)
- diff_min += (local.tm_yday > gmt->tm_yday)? 1440 : -1440;
- diff_hour = diff_min/60;
- diff_min = abs(diff_min - diff_hour*60);
+ if (local.tm_sec == gmt->tm_sec) /* usual case */
+ {
+ diff_min = 60 * (local.tm_hour - gmt->tm_hour)
+ + local.tm_min - gmt->tm_min;
+ if (local.tm_year != gmt->tm_year)
+ diff_min += (local.tm_year > gmt->tm_year) ? 1440 : -1440;
+ else if (local.tm_yday != gmt->tm_yday)
+ diff_min += (local.tm_yday > gmt->tm_yday) ? 1440 : -1440;
+ diff_hour = diff_min/60;
+ diff_min = abs(diff_min - diff_hour*60);
+ }
+ else /* subminute offset, eg. TAI */
+ {
+ lp = gmt; /* pretend we're in UTC */
+ diff_min = diff_hour = 0;
+ }
}
switch(type)
case tod_log_zone: /* Format used in logging with timezone */
#ifndef COMPILE_UTILITY
if (LOGGING(millisec))
- (void) sprintf(CS timebuf,
- "%04d-%02d-%02d %02d:%02d:%02d.%03d %+03d%02d",
- 1900 + local.tm_year, 1 + local.tm_mon, local.tm_mday,
- local.tm_hour, local.tm_min, local.tm_sec, (int)(now.tv_usec/1000),
+ (void) snprintf(CS timebuf, sizeof(timebuf),
+ "%04u-%02u-%02u %02u:%02u:%02u.%03u %+03d%02d",
+ 1900 + (uint)lp->tm_year, 1 + (uint)lp->tm_mon, (uint)lp->tm_mday,
+ (uint)lp->tm_hour, (uint)lp->tm_min, (uint)lp->tm_sec, (uint)(now.tv_usec/1000),
diff_hour, diff_min);
else
#endif
- (void) sprintf(CS timebuf,
- "%04d-%02d-%02d %02d:%02d:%02d %+03d%02d",
- 1900 + local.tm_year, 1 + local.tm_mon, local.tm_mday,
- local.tm_hour, local.tm_min, local.tm_sec,
+ (void) snprintf(CS timebuf, sizeof(timebuf),
+ "%04u-%02u-%02u %02u:%02u:%02u %+03d%02d",
+ 1900 + (uint)lp->tm_year, 1 + (uint)lp->tm_mon, (uint)lp->tm_mday,
+ (uint)lp->tm_hour, (uint)lp->tm_min, (uint)lp->tm_sec,
diff_hour, diff_min);
break;
case tod_zone: /* Just the timezone offset */
- (void) sprintf(CS timebuf, "%+03d%02d", diff_hour, diff_min);
+ (void) snprintf(CS timebuf, sizeof(timebuf), "%+03d%02d", diff_hour, diff_min);
break;
/* tod_mbx: format used in MBX mailboxes - subtly different to tod_full */
- #ifdef SUPPORT_MBX
+#ifdef SUPPORT_MBX
case tod_mbx:
- {
- int len;
- (void) sprintf(CS timebuf, "%02d-", local.tm_mday);
- len = Ustrlen(timebuf);
- len += Ustrftime(timebuf + len, sizeof(timebuf) - len, "%b-%Y %H:%M:%S",
- &local);
- (void) sprintf(CS timebuf + len, " %+03d%02d", diff_hour, diff_min);
- }
+ {
+ int len = snprintf(CS timebuf, sizeof(timebuf),
+ "%02u-", (uint)lp->tm_mday);
+ len += Ustrftime(timebuf + len, sizeof(timebuf) - len,
+ "%b-%Y %H:%M:%S", lp);
+ (void) snprintf(CS timebuf + len, sizeof(timebuf)-len,
+ " %+03d%02d", diff_hour, diff_min);
+ }
break;
- #endif
+#endif
/* tod_full: format used in Received: headers (use as default just in case
called with a junk type value) */
default:
- {
- int len = Ustrftime(timebuf, sizeof(timebuf), "%a, ", &local);
- (void) sprintf(CS timebuf + len, "%02d ", local.tm_mday);
- len += Ustrlen(timebuf + len);
- len += Ustrftime(timebuf + len, sizeof(timebuf) - len, "%b %Y %H:%M:%S",
- &local);
- (void) sprintf(CS timebuf + len, " %+03d%02d", diff_hour, diff_min);
- }
+ {
+ int len = Ustrftime(timebuf, sizeof(timebuf), "%a, ", lp);
+ len += snprintf(CS timebuf + len, sizeof(timebuf)-len,
+ "%02u ", (uint)lp->tm_mday);
+ len += Ustrftime(timebuf + len, sizeof(timebuf) - len,
+ "%b %Y %H:%M:%S", lp);
+ (void) snprintf(CS timebuf + len, sizeof(timebuf)-len,
+ " %+03d%02d", diff_hour, diff_min);
+ }
break;
}
}