00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023
00024 #include <errno.h>
00025 #include <limits.h>
00026 #include <stdlib.h>
00027 #include <syslog.h>
00028 #include <time.h>
00029
00030 #include <sys/time.h>
00031
00032 #include <isc/log.h>
00033 #include <isc/print.h>
00034 #include <isc/strerror.h>
00035 #include <isc/string.h>
00036 #include <isc/time.h>
00037 #include <isc/tm.h>
00038 #include <isc/util.h>
00039
00040 #define NS_PER_S 1000000000
00041 #define NS_PER_US 1000
00042 #define US_PER_S 1000000
00043
00044
00045
00046
00047
00048
00049
00050
00051 #ifndef ISC_FIX_TV_USEC
00052 #define ISC_FIX_TV_USEC 1
00053 #endif
00054
00055
00056
00057
00058
00059 static const isc_interval_t zero_interval = { 0, 0 };
00060 const isc_interval_t * const isc_interval_zero = &zero_interval;
00061
00062 #if ISC_FIX_TV_USEC
00063 static inline void
00064 fix_tv_usec(struct timeval *tv) {
00065 isc_boolean_t fixed = ISC_FALSE;
00066
00067 if (tv->tv_usec < 0) {
00068 fixed = ISC_TRUE;
00069 do {
00070 tv->tv_sec -= 1;
00071 tv->tv_usec += US_PER_S;
00072 } while (tv->tv_usec < 0);
00073 } else if (tv->tv_usec >= US_PER_S) {
00074 fixed = ISC_TRUE;
00075 do {
00076 tv->tv_sec += 1;
00077 tv->tv_usec -= US_PER_S;
00078 } while (tv->tv_usec >=US_PER_S);
00079 }
00080
00081
00082
00083 if (fixed)
00084 (void)syslog(LOG_ERR, "gettimeofday returned bad tv_usec: corrected");
00085 }
00086 #endif
00087
00088 void
00089 isc_interval_set(isc_interval_t *i,
00090 unsigned int seconds, unsigned int nanoseconds)
00091 {
00092 REQUIRE(i != NULL);
00093 REQUIRE(nanoseconds < NS_PER_S);
00094
00095 i->seconds = seconds;
00096 i->nanoseconds = nanoseconds;
00097 }
00098
00099 isc_boolean_t
00100 isc_interval_iszero(const isc_interval_t *i) {
00101 REQUIRE(i != NULL);
00102 INSIST(i->nanoseconds < NS_PER_S);
00103
00104 if (i->seconds == 0 && i->nanoseconds == 0)
00105 return (ISC_TRUE);
00106
00107 return (ISC_FALSE);
00108 }
00109
00110
00111
00112
00113
00114
00115 static const isc_time_t epoch = { 0, 0 };
00116 const isc_time_t * const isc_time_epoch = &epoch;
00117
00118 void
00119 isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds) {
00120 REQUIRE(t != NULL);
00121 REQUIRE(nanoseconds < NS_PER_S);
00122
00123 t->seconds = seconds;
00124 t->nanoseconds = nanoseconds;
00125 }
00126
00127 void
00128 isc_time_settoepoch(isc_time_t *t) {
00129 REQUIRE(t != NULL);
00130
00131 t->seconds = 0;
00132 t->nanoseconds = 0;
00133 }
00134
00135 isc_boolean_t
00136 isc_time_isepoch(const isc_time_t *t) {
00137 REQUIRE(t != NULL);
00138 INSIST(t->nanoseconds < NS_PER_S);
00139
00140 if (t->seconds == 0 && t->nanoseconds == 0)
00141 return (ISC_TRUE);
00142
00143 return (ISC_FALSE);
00144 }
00145
00146
00147 isc_result_t
00148 isc_time_now(isc_time_t *t) {
00149 struct timeval tv;
00150 char strbuf[ISC_STRERRORSIZE];
00151
00152 REQUIRE(t != NULL);
00153
00154 if (gettimeofday(&tv, NULL) == -1) {
00155 isc__strerror(errno, strbuf, sizeof(strbuf));
00156 UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf);
00157 return (ISC_R_UNEXPECTED);
00158 }
00159
00160
00161
00162
00163
00164
00165
00166
00167 #if ISC_FIX_TV_USEC
00168 fix_tv_usec(&tv);
00169 if (tv.tv_sec < 0)
00170 return (ISC_R_UNEXPECTED);
00171 #else
00172 if (tv.tv_sec < 0 || tv.tv_usec < 0 || tv.tv_usec >= US_PER_S)
00173 return (ISC_R_UNEXPECTED);
00174 #endif
00175
00176
00177
00178
00179 if (sizeof(tv.tv_sec) > sizeof(t->seconds) &&
00180 ((tv.tv_sec | (unsigned int)-1) ^ (unsigned int)-1) != 0U)
00181 return (ISC_R_RANGE);
00182
00183 t->seconds = tv.tv_sec;
00184 t->nanoseconds = tv.tv_usec * NS_PER_US;
00185
00186 return (ISC_R_SUCCESS);
00187 }
00188
00189 isc_result_t
00190 isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i) {
00191 struct timeval tv;
00192 char strbuf[ISC_STRERRORSIZE];
00193
00194 REQUIRE(t != NULL);
00195 REQUIRE(i != NULL);
00196 INSIST(i->nanoseconds < NS_PER_S);
00197
00198 if (gettimeofday(&tv, NULL) == -1) {
00199 isc__strerror(errno, strbuf, sizeof(strbuf));
00200 UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf);
00201 return (ISC_R_UNEXPECTED);
00202 }
00203
00204
00205
00206
00207
00208
00209
00210
00211 #if ISC_FIX_TV_USEC
00212 fix_tv_usec(&tv);
00213 if (tv.tv_sec < 0)
00214 return (ISC_R_UNEXPECTED);
00215 #else
00216 if (tv.tv_sec < 0 || tv.tv_usec < 0 || tv.tv_usec >= US_PER_S)
00217 return (ISC_R_UNEXPECTED);
00218 #endif
00219
00220
00221
00222
00223
00224
00225
00226 if ((tv.tv_sec > INT_MAX || i->seconds > INT_MAX) &&
00227 ((long long)tv.tv_sec + i->seconds > UINT_MAX))
00228 return (ISC_R_RANGE);
00229
00230 t->seconds = tv.tv_sec + i->seconds;
00231 t->nanoseconds = tv.tv_usec * NS_PER_US + i->nanoseconds;
00232 if (t->nanoseconds >= NS_PER_S) {
00233 t->seconds++;
00234 t->nanoseconds -= NS_PER_S;
00235 }
00236
00237 return (ISC_R_SUCCESS);
00238 }
00239
00240 int
00241 isc_time_compare(const isc_time_t *t1, const isc_time_t *t2) {
00242 REQUIRE(t1 != NULL && t2 != NULL);
00243 INSIST(t1->nanoseconds < NS_PER_S && t2->nanoseconds < NS_PER_S);
00244
00245 if (t1->seconds < t2->seconds)
00246 return (-1);
00247 if (t1->seconds > t2->seconds)
00248 return (1);
00249 if (t1->nanoseconds < t2->nanoseconds)
00250 return (-1);
00251 if (t1->nanoseconds > t2->nanoseconds)
00252 return (1);
00253 return (0);
00254 }
00255
00256 isc_result_t
00257 isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result)
00258 {
00259 REQUIRE(t != NULL && i != NULL && result != NULL);
00260 INSIST(t->nanoseconds < NS_PER_S && i->nanoseconds < NS_PER_S);
00261
00262
00263
00264
00265
00266
00267
00268 if ((t->seconds > INT_MAX || i->seconds > INT_MAX) &&
00269 ((long long)t->seconds + i->seconds > UINT_MAX))
00270 return (ISC_R_RANGE);
00271
00272 result->seconds = t->seconds + i->seconds;
00273 result->nanoseconds = t->nanoseconds + i->nanoseconds;
00274 if (result->nanoseconds >= NS_PER_S) {
00275 result->seconds++;
00276 result->nanoseconds -= NS_PER_S;
00277 }
00278
00279 return (ISC_R_SUCCESS);
00280 }
00281
00282 isc_result_t
00283 isc_time_subtract(const isc_time_t *t, const isc_interval_t *i,
00284 isc_time_t *result)
00285 {
00286 REQUIRE(t != NULL && i != NULL && result != NULL);
00287 INSIST(t->nanoseconds < NS_PER_S && i->nanoseconds < NS_PER_S);
00288
00289 if ((unsigned int)t->seconds < i->seconds ||
00290 ((unsigned int)t->seconds == i->seconds &&
00291 t->nanoseconds < i->nanoseconds))
00292 return (ISC_R_RANGE);
00293
00294 result->seconds = t->seconds - i->seconds;
00295 if (t->nanoseconds >= i->nanoseconds)
00296 result->nanoseconds = t->nanoseconds - i->nanoseconds;
00297 else {
00298 result->nanoseconds = NS_PER_S - i->nanoseconds +
00299 t->nanoseconds;
00300 result->seconds--;
00301 }
00302
00303 return (ISC_R_SUCCESS);
00304 }
00305
00306 isc_uint64_t
00307 isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2) {
00308 isc_uint64_t i1, i2, i3;
00309
00310 REQUIRE(t1 != NULL && t2 != NULL);
00311 INSIST(t1->nanoseconds < NS_PER_S && t2->nanoseconds < NS_PER_S);
00312
00313 i1 = (isc_uint64_t)t1->seconds * NS_PER_S + t1->nanoseconds;
00314 i2 = (isc_uint64_t)t2->seconds * NS_PER_S + t2->nanoseconds;
00315
00316 if (i1 <= i2)
00317 return (0);
00318
00319 i3 = i1 - i2;
00320
00321
00322
00323
00324 i3 /= NS_PER_US;
00325
00326 return (i3);
00327 }
00328
00329 isc_uint32_t
00330 isc_time_seconds(const isc_time_t *t) {
00331 REQUIRE(t != NULL);
00332 INSIST(t->nanoseconds < NS_PER_S);
00333
00334 return ((isc_uint32_t)t->seconds);
00335 }
00336
00337 isc_result_t
00338 isc_time_secondsastimet(const isc_time_t *t, time_t *secondsp) {
00339 time_t seconds;
00340
00341 REQUIRE(t != NULL);
00342 INSIST(t->nanoseconds < NS_PER_S);
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 seconds = (time_t)t->seconds;
00362
00363 INSIST(sizeof(unsigned int) == sizeof(isc_uint32_t));
00364 INSIST(sizeof(time_t) >= sizeof(isc_uint32_t));
00365
00366 if (t->seconds > (~0U>>1) && seconds <= (time_t)(~0U>>1))
00367 return (ISC_R_RANGE);
00368
00369 *secondsp = seconds;
00370
00371 return (ISC_R_SUCCESS);
00372 }
00373
00374 isc_uint32_t
00375 isc_time_nanoseconds(const isc_time_t *t) {
00376 REQUIRE(t != NULL);
00377
00378 ENSURE(t->nanoseconds < NS_PER_S);
00379
00380 return ((isc_uint32_t)t->nanoseconds);
00381 }
00382
00383 void
00384 isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len) {
00385 time_t now;
00386 unsigned int flen;
00387
00388 REQUIRE(len > 0);
00389
00390 now = (time_t) t->seconds;
00391 flen = strftime(buf, len, "%d-%b-%Y %X", localtime(&now));
00392 INSIST(flen < len);
00393 if (flen != 0)
00394 snprintf(buf + flen, len - flen,
00395 ".%03u", t->nanoseconds / 1000000);
00396 else {
00397 strncpy(buf, "99-Bad-9999 99:99:99.999", len);
00398 buf[len - 1] = 0;
00399 }
00400 }
00401
00402 void
00403 isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) {
00404 time_t now;
00405 unsigned int flen;
00406
00407 REQUIRE(len > 0);
00408
00409
00410
00411
00412 now = (time_t)t->seconds;
00413 flen = strftime(buf, len, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now));
00414 INSIST(flen < len);
00415 }
00416
00417 isc_result_t
00418 isc_time_parsehttptimestamp(char *buf, isc_time_t *t) {
00419 struct tm t_tm;
00420 time_t when;
00421 char *p;
00422
00423 REQUIRE(buf != NULL);
00424 REQUIRE(t != NULL);
00425 p = isc_tm_strptime(buf, "%a, %d %b %Y %H:%M:%S", &t_tm);
00426 if (p == NULL)
00427 return (ISC_R_UNEXPECTED);
00428 when = isc_tm_timegm(&t_tm);
00429 if (when == -1)
00430 return (ISC_R_UNEXPECTED);
00431 isc_time_set(t, when, 0);
00432 return (ISC_R_SUCCESS);
00433 }
00434
00435 void
00436 isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) {
00437 time_t now;
00438 unsigned int flen;
00439
00440 REQUIRE(len > 0);
00441
00442 now = (time_t)t->seconds;
00443 flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%SZ", gmtime(&now));
00444 INSIST(flen < len);
00445 }