1258945Sroberto/*
2258945Sroberto * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
3258945Sroberto * Copyright (C) 1999-2001  Internet Software Consortium.
4258945Sroberto *
5258945Sroberto * Permission to use, copy, modify, and/or distribute this software for any
6258945Sroberto * purpose with or without fee is hereby granted, provided that the above
7258945Sroberto * copyright notice and this permission notice appear in all copies.
8258945Sroberto *
9258945Sroberto * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10258945Sroberto * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11258945Sroberto * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12258945Sroberto * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13258945Sroberto * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14258945Sroberto * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15258945Sroberto * PERFORMANCE OF THIS SOFTWARE.
16258945Sroberto */
17258945Sroberto
18258945Sroberto/* $Id: stdtime.c,v 1.19 2007/06/19 23:47:18 tbox Exp $ */
19258945Sroberto
20258945Sroberto/*! \file */
21258945Sroberto
22258945Sroberto#include <config.h>
23258945Sroberto
24258945Sroberto#include <stddef.h>	/* NULL */
25258945Sroberto#include <stdlib.h>	/* NULL */
26258945Sroberto#include <syslog.h>
27258945Sroberto
28258945Sroberto#include <sys/time.h>
29258945Sroberto
30258945Sroberto#include <isc/stdtime.h>
31258945Sroberto#include <isc/util.h>
32258945Sroberto
33258945Sroberto#ifndef ISC_FIX_TV_USEC
34258945Sroberto#define ISC_FIX_TV_USEC 1
35258945Sroberto#endif
36258945Sroberto
37258945Sroberto#define US_PER_S 1000000
38258945Sroberto
39258945Sroberto#if ISC_FIX_TV_USEC
40258945Srobertostatic inline void
41258945Srobertofix_tv_usec(struct timeval *tv) {
42258945Sroberto	isc_boolean_t fixed = ISC_FALSE;
43258945Sroberto
44258945Sroberto	if (tv->tv_usec < 0) {
45258945Sroberto		fixed = ISC_TRUE;
46258945Sroberto		do {
47258945Sroberto			tv->tv_sec -= 1;
48258945Sroberto			tv->tv_usec += US_PER_S;
49258945Sroberto		} while (tv->tv_usec < 0);
50258945Sroberto	} else if (tv->tv_usec >= US_PER_S) {
51258945Sroberto		fixed = ISC_TRUE;
52258945Sroberto		do {
53258945Sroberto			tv->tv_sec += 1;
54258945Sroberto			tv->tv_usec -= US_PER_S;
55258945Sroberto		} while (tv->tv_usec >=US_PER_S);
56258945Sroberto	}
57258945Sroberto	/*
58258945Sroberto	 * Call syslog directly as we are called from the logging functions.
59258945Sroberto	 */
60258945Sroberto	if (fixed)
61258945Sroberto		(void)syslog(LOG_ERR, "gettimeofday returned bad tv_usec: corrected");
62258945Sroberto}
63258945Sroberto#endif
64258945Sroberto
65258945Srobertovoid
66258945Srobertoisc_stdtime_get(isc_stdtime_t *t) {
67258945Sroberto	struct timeval tv;
68258945Sroberto
69258945Sroberto	/*
70258945Sroberto	 * Set 't' to the number of seconds since 00:00:00 UTC, January 1,
71258945Sroberto	 * 1970.
72258945Sroberto	 */
73258945Sroberto
74258945Sroberto	REQUIRE(t != NULL);
75258945Sroberto
76258945Sroberto	RUNTIME_CHECK(gettimeofday(&tv, NULL) != -1);
77258945Sroberto
78258945Sroberto#if ISC_FIX_TV_USEC
79258945Sroberto	fix_tv_usec(&tv);
80258945Sroberto	INSIST(tv.tv_usec >= 0);
81258945Sroberto#else
82258945Sroberto	INSIST(tv.tv_usec >= 0 && tv.tv_usec < US_PER_S);
83258945Sroberto#endif
84258945Sroberto
85258945Sroberto	*t = (unsigned int)tv.tv_sec;
86258945Sroberto}
87