Subject: more on inittodr() algorithms
To: None <tech-kern@NetBSD.ORG>
From: Perry E. Metzger <perry@piermont.com>
List: tech-kern
Date: 07/27/1997 11:28:48
For reference, this is the code I'm thinking of using (approximately)
to arbitrate between some failsafe year, the rtc time, and the time
from the file system. (I'm probably going to rearrange the code a bit
more, and probably will turn the 2days/30days into #defines.

----------------------------------------------------------------------

/* from clock_subr.h */
#define FAILSAFE_BASE_YEAR	1997	/* No clock should be less than this */
#define FAILSAFE_BASE_SECS	((FAILSAFE_BASE_YEAR - POSIX_BASE_YEAR)*SECYR)

/* from clock_subr.c, which includes clock_subr.h */
void
set_time_failsafe(rtc_time, fs_time)
	time_t rtc_time, fs_time;
{
	time_t new_time;
	int warning, fs_time_bad, rtc_time_bad, delta;
	
	warning = fs_time_bad = rtc_time_bad = 0;

	if (fs_time < FAILSAFE_BASE_SECS) { 
		/*
		 * its reasonable to call inittodr(0), so we only warn
		 * if fs_time is nonzero.
		 */
		if (fs_time != 0) {
			printf("WARNING: file system time is older than %d\n",
			    FAILSAFE_BASE_YEAR);
			printf("WARNING: preposterous file system time\n");
		}
		fs_time_bad = 1;
		fs_time = FAILSAFE_BASE_SECS;
	}

	if (rtc_time < FAILSAFE_BASE_SECS) {
		if (rtc_time == 0) {
			/*
			 * this means the clock was broken, lost its
			 * battery, wasn't found, or is otherwise
			 * known bad.
			 */
			printf("WARNING: real time clock is invalid.");
		}
		else {
			printf("WARNING: real time clock is older than %d\n",
			    FAILSAFE_BASE_YEAR);
			printf("WARNING: "
			    "preposterous real time clock value\n");
		}
		rtc_time_bad = 1;
		rtc_time = FAILSAFE_BASE_SECS
		warning = 1;
	}

	/*
	 * note that if both fs_time and rtc_time are bad, this line
	 * implies that the time gets set to the failsafe time.
	 */
	new_time = rtc_time;

	/* compute time difference */
	delta = rtc_time - fs_time;
	if (delta < 0)
		delta = -delta;

	/* warn if we gained/lost more than two days */
	if (!rtc_time_bad && !fs_time_bad && (delta > (2 * SECDAY))) {
		printf("WARNING: clock %s %d days",
		    rtc_time < fs_time ? "lost" : "gained",
		    delta / SECDAY);
		warning = 1;
	}

	/* if we lost more than 30 days, assume something is wrong. */
	if (!rtc_time_bad && !fs_time_bad) {
		if ((delta > 30 * SECDAY) && (rtc_time < fs_time)) {
			printf("WARNING: real time clock much older "
			    "than file system time.\n");
			rtc_time_bad = 1;
			warning = 1;
		}
	}

	if (rtc_time_bad && !fs_time_bad) {
		printf("WARNING: Using file system time "
		    "instead of real time clock.\n");
		new_time =  fs_time;
		warning = 1;
	}

	if (warning)
		printf("WARNING: CHECK AND RESET THE DATE!\n");

	time.tv_sec = new_time;
	time.tv_usec = 0;
}