1 /* 2 * Copyright (C) 2004-2008, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1998-2001, 2003 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /* $Id$ */ 19 20 /*! \file */ 21 22 #include <config.h> 23 24 #include <errno.h> 25 #include <limits.h> 26 #include <syslog.h> 27 #include <time.h> 28 29 #include <sys/time.h> /* Required for struct timeval on some platforms. */ 30 31 #include <isc/log.h> 32 #include <isc/print.h> 33 #include <isc/strerror.h> 34 #include <isc/string.h> 35 #include <isc/time.h> 36 #include <isc/util.h> 37 38 #define NS_PER_S 1000000000 /*%< Nanoseconds per second. */ 39 #define NS_PER_US 1000 /*%< Nanoseconds per microsecond. */ 40 #define US_PER_S 1000000 /*%< Microseconds per second. */ 41 42 /* 43 * All of the INSIST()s checks of nanoseconds < NS_PER_S are for 44 * consistency checking of the type. In lieu of magic numbers, it 45 * is the best we've got. The check is only performed on functions which 46 * need an initialized type. 47 */ 48 49 #ifndef ISC_FIX_TV_USEC 50 #define ISC_FIX_TV_USEC 1 51 #endif 52 53 /*% 54 *** Intervals 55 ***/ 56 57 static isc_interval_t zero_interval = { 0, 0 }; 58 isc_interval_t *isc_interval_zero = &zero_interval; 59 60 #if ISC_FIX_TV_USEC 61 static inline void 62 fix_tv_usec(struct timeval *tv) { 63 isc_boolean_t fixed = ISC_FALSE; 64 65 if (tv->tv_usec < 0) { 66 fixed = ISC_TRUE; 67 do { 68 tv->tv_sec -= 1; 69 tv->tv_usec += US_PER_S; 70 } while (tv->tv_usec < 0); 71 } else if (tv->tv_usec >= US_PER_S) { 72 fixed = ISC_TRUE; 73 do { 74 tv->tv_sec += 1; 75 tv->tv_usec -= US_PER_S; 76 } while (tv->tv_usec >=US_PER_S); 77 } 78 /* 79 * Call syslog directly as was are called from the logging functions. 80 */ 81 if (fixed) 82 (void)syslog(LOG_ERR, "gettimeofday returned bad tv_usec: corrected"); 83 } 84 #endif 85 86 void 87 isc_interval_set(isc_interval_t *i, 88 unsigned int seconds, unsigned int nanoseconds) 89 { 90 REQUIRE(i != NULL); 91 REQUIRE(nanoseconds < NS_PER_S); 92 93 i->seconds = seconds; 94 i->nanoseconds = nanoseconds; 95 } 96 97 isc_boolean_t 98 isc_interval_iszero(const isc_interval_t *i) { 99 REQUIRE(i != NULL); 100 INSIST(i->nanoseconds < NS_PER_S); 101 102 if (i->seconds == 0 && i->nanoseconds == 0) 103 return (ISC_TRUE); 104 105 return (ISC_FALSE); 106 } 107 108 109 /*** 110 *** Absolute Times 111 ***/ 112 113 static isc_time_t epoch = { 0, 0 }; 114 isc_time_t *isc_time_epoch = &epoch; 115 116 void 117 isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds) { 118 REQUIRE(t != NULL); 119 REQUIRE(nanoseconds < NS_PER_S); 120 121 t->seconds = seconds; 122 t->nanoseconds = nanoseconds; 123 } 124 125 void 126 isc_time_settoepoch(isc_time_t *t) { 127 REQUIRE(t != NULL); 128 129 t->seconds = 0; 130 t->nanoseconds = 0; 131 } 132 133 isc_boolean_t 134 isc_time_isepoch(const isc_time_t *t) { 135 REQUIRE(t != NULL); 136 INSIST(t->nanoseconds < NS_PER_S); 137 138 if (t->seconds == 0 && t->nanoseconds == 0) 139 return (ISC_TRUE); 140 141 return (ISC_FALSE); 142 } 143 144 145 isc_result_t 146 isc_time_now(isc_time_t *t) { 147 struct timeval tv; 148 char strbuf[ISC_STRERRORSIZE]; 149 150 REQUIRE(t != NULL); 151 152 if (gettimeofday(&tv, NULL) == -1) { 153 isc__strerror(errno, strbuf, sizeof(strbuf)); 154 UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf); 155 return (ISC_R_UNEXPECTED); 156 } 157 158 /* 159 * Does POSIX guarantee the signedness of tv_sec and tv_usec? If not, 160 * then this test will generate warnings for platforms on which it is 161 * unsigned. In any event, the chances of any of these problems 162 * happening are pretty much zero, but since the libisc library ensures 163 * certain things to be true ... 164 */ 165 #if ISC_FIX_TV_USEC 166 fix_tv_usec(&tv); 167 if (tv.tv_sec < 0) 168 return (ISC_R_UNEXPECTED); 169 #else 170 if (tv.tv_sec < 0 || tv.tv_usec < 0 || tv.tv_usec >= US_PER_S) 171 return (ISC_R_UNEXPECTED); 172 #endif 173 174 /* 175 * Ensure the tv_sec value fits in t->seconds. 176 */ 177 if (sizeof(tv.tv_sec) > sizeof(t->seconds) && 178 ((tv.tv_sec | (unsigned int)-1) ^ (unsigned int)-1) != 0U) 179 return (ISC_R_RANGE); 180 181 t->seconds = tv.tv_sec; 182 t->nanoseconds = tv.tv_usec * NS_PER_US; 183 184 return (ISC_R_SUCCESS); 185 } 186 187 isc_result_t 188 isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i) { 189 struct timeval tv; 190 char strbuf[ISC_STRERRORSIZE]; 191 192 REQUIRE(t != NULL); 193 REQUIRE(i != NULL); 194 INSIST(i->nanoseconds < NS_PER_S); 195 196 if (gettimeofday(&tv, NULL) == -1) { 197 isc__strerror(errno, strbuf, sizeof(strbuf)); 198 UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf); 199 return (ISC_R_UNEXPECTED); 200 } 201 202 /* 203 * Does POSIX guarantee the signedness of tv_sec and tv_usec? If not, 204 * then this test will generate warnings for platforms on which it is 205 * unsigned. In any event, the chances of any of these problems 206 * happening are pretty much zero, but since the libisc library ensures 207 * certain things to be true ... 208 */ 209 #if ISC_FIX_TV_USEC 210 fix_tv_usec(&tv); 211 if (tv.tv_sec < 0) 212 return (ISC_R_UNEXPECTED); 213 #else 214 if (tv.tv_sec < 0 || tv.tv_usec < 0 || tv.tv_usec >= US_PER_S) 215 return (ISC_R_UNEXPECTED); 216 #endif 217 218 /* 219 * Ensure the resulting seconds value fits in the size of an 220 * unsigned int. (It is written this way as a slight optimization; 221 * note that even if both values == INT_MAX, then when added 222 * and getting another 1 added below the result is UINT_MAX.) 223 */ 224 if ((tv.tv_sec > INT_MAX || i->seconds > INT_MAX) && 225 ((long long)tv.tv_sec + i->seconds > UINT_MAX)) 226 return (ISC_R_RANGE); 227 228 t->seconds = tv.tv_sec + i->seconds; 229 t->nanoseconds = tv.tv_usec * NS_PER_US + i->nanoseconds; 230 if (t->nanoseconds >= NS_PER_S) { 231 t->seconds++; 232 t->nanoseconds -= NS_PER_S; 233 } 234 235 return (ISC_R_SUCCESS); 236 } 237 238 int 239 isc_time_compare(const isc_time_t *t1, const isc_time_t *t2) { 240 REQUIRE(t1 != NULL && t2 != NULL); 241 INSIST(t1->nanoseconds < NS_PER_S && t2->nanoseconds < NS_PER_S); 242 243 if (t1->seconds < t2->seconds) 244 return (-1); 245 if (t1->seconds > t2->seconds) 246 return (1); 247 if (t1->nanoseconds < t2->nanoseconds) 248 return (-1); 249 if (t1->nanoseconds > t2->nanoseconds) 250 return (1); 251 return (0); 252 } 253 254 isc_result_t 255 isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result) 256 { 257 REQUIRE(t != NULL && i != NULL && result != NULL); 258 INSIST(t->nanoseconds < NS_PER_S && i->nanoseconds < NS_PER_S); 259 260 /* 261 * Ensure the resulting seconds value fits in the size of an 262 * unsigned int. (It is written this way as a slight optimization; 263 * note that even if both values == INT_MAX, then when added 264 * and getting another 1 added below the result is UINT_MAX.) 265 */ 266 if ((t->seconds > INT_MAX || i->seconds > INT_MAX) && 267 ((long long)t->seconds + i->seconds > UINT_MAX)) 268 return (ISC_R_RANGE); 269 270 result->seconds = t->seconds + i->seconds; 271 result->nanoseconds = t->nanoseconds + i->nanoseconds; 272 if (result->nanoseconds >= NS_PER_S) { 273 result->seconds++; 274 result->nanoseconds -= NS_PER_S; 275 } 276 277 return (ISC_R_SUCCESS); 278 } 279 280 isc_result_t 281 isc_time_subtract(const isc_time_t *t, const isc_interval_t *i, 282 isc_time_t *result) 283 { 284 REQUIRE(t != NULL && i != NULL && result != NULL); 285 INSIST(t->nanoseconds < NS_PER_S && i->nanoseconds < NS_PER_S); 286 287 if ((unsigned int)t->seconds < i->seconds || 288 ((unsigned int)t->seconds == i->seconds && 289 t->nanoseconds < i->nanoseconds)) 290 return (ISC_R_RANGE); 291 292 result->seconds = t->seconds - i->seconds; 293 if (t->nanoseconds >= i->nanoseconds) 294 result->nanoseconds = t->nanoseconds - i->nanoseconds; 295 else { 296 result->nanoseconds = NS_PER_S - i->nanoseconds + 297 t->nanoseconds; 298 result->seconds--; 299 } 300 301 return (ISC_R_SUCCESS); 302 } 303 304 isc_uint64_t 305 isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2) { 306 isc_uint64_t i1, i2, i3; 307 308 REQUIRE(t1 != NULL && t2 != NULL); 309 INSIST(t1->nanoseconds < NS_PER_S && t2->nanoseconds < NS_PER_S); 310 311 i1 = (isc_uint64_t)t1->seconds * NS_PER_S + t1->nanoseconds; 312 i2 = (isc_uint64_t)t2->seconds * NS_PER_S + t2->nanoseconds; 313 314 if (i1 <= i2) 315 return (0); 316 317 i3 = i1 - i2; 318 319 /* 320 * Convert to microseconds. 321 */ 322 i3 /= NS_PER_US; 323 324 return (i3); 325 } 326 327 isc_uint32_t 328 isc_time_seconds(const isc_time_t *t) { 329 REQUIRE(t != NULL); 330 INSIST(t->nanoseconds < NS_PER_S); 331 332 return ((isc_uint32_t)t->seconds); 333 } 334 335 isc_result_t 336 isc_time_secondsastimet(const isc_time_t *t, time_t *secondsp) { 337 time_t seconds; 338 339 REQUIRE(t != NULL); 340 INSIST(t->nanoseconds < NS_PER_S); 341 342 /* 343 * Ensure that the number of seconds represented by t->seconds 344 * can be represented by a time_t. Since t->seconds is an unsigned 345 * int and since time_t is mostly opaque, this is trickier than 346 * it seems. (This standardized opaqueness of time_t is *very* 347 * frustrating; time_t is not even limited to being an integral 348 * type.) 349 * 350 * The mission, then, is to avoid generating any kind of warning 351 * about "signed versus unsigned" while trying to determine if the 352 * the unsigned int t->seconds is out range for tv_sec, which is 353 * pretty much only true if time_t is a signed integer of the same 354 * size as the return value of isc_time_seconds. 355 * 356 * If the paradox in the if clause below is true, t->seconds is out 357 * of range for time_t. 358 */ 359 seconds = (time_t)t->seconds; 360 361 INSIST(sizeof(unsigned int) == sizeof(isc_uint32_t)); 362 INSIST(sizeof(time_t) >= sizeof(isc_uint32_t)); 363 364 if (t->seconds > (~0U>>1) && seconds <= (time_t)(~0U>>1)) 365 return (ISC_R_RANGE); 366 367 *secondsp = seconds; 368 369 return (ISC_R_SUCCESS); 370 } 371 372 isc_uint32_t 373 isc_time_nanoseconds(const isc_time_t *t) { 374 REQUIRE(t != NULL); 375 376 ENSURE(t->nanoseconds < NS_PER_S); 377 378 return ((isc_uint32_t)t->nanoseconds); 379 } 380 381 void 382 isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len) { 383 time_t now; 384 unsigned int flen; 385 386 REQUIRE(len > 0); 387 388 now = (time_t) t->seconds; 389 flen = strftime(buf, len, "%d-%b-%Y %X", localtime(&now)); 390 INSIST(flen < len); 391 if (flen != 0) 392 snprintf(buf + flen, len - flen, 393 ".%03u", t->nanoseconds / 1000000); 394 else 395 snprintf(buf, len, "99-Bad-9999 99:99:99.999"); 396 } 397 398 void 399 isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) { 400 time_t now; 401 unsigned int flen; 402 403 REQUIRE(len > 0); 404 405 now = (time_t)t->seconds; 406 flen = strftime(buf, len, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now)); 407 INSIST(flen < len); 408 } 409 410 void 411 isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) { 412 time_t now; 413 unsigned int flen; 414 415 REQUIRE(len > 0); 416 417 now = (time_t)t->seconds; 418 flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%SZ", gmtime(&now)); 419 INSIST(flen < len); 420 } 421