Add a check for wtmp records which have invalid values for ut_time. Wtmp
records with time==0 get "the time of the last valid record", while records where time goes backwards (compared to the previous record) are skipped. Also prints a message saying how many records were changed or skipped due to these checks. Check was inspired by a simpler check in OpenBSD's version. This is all meant to sidestep problems that Tillman Hodgson noticed with 'ac' when running sparc64 with 64-bit time_t's. The real problem is whatever is creating wtmp records with ut_time==0, of course, but I have not yet figured out what is doing that. Reviewed by: no screams from freebsd-sparc64 or bde MFC after: 2 weeks
This commit is contained in:
parent
c38a857969
commit
e3b218cd7b
@ -510,21 +510,65 @@ ac(FILE *fp)
|
||||
struct utmp_list *lp, *head = NULL;
|
||||
struct utmp usr;
|
||||
struct tm *ltm;
|
||||
time_t secs;
|
||||
int day = -1;
|
||||
time_t prev_secs, secs, ut_timecopy;
|
||||
int day, rfound, tchanged, tskipped;
|
||||
|
||||
day = -1;
|
||||
prev_secs = 1; /* Minimum acceptable date == 1970 */
|
||||
rfound = tchanged = tskipped = 0;
|
||||
secs = 0;
|
||||
while (fread((char *)&usr, sizeof(usr), 1, fp) == 1) {
|
||||
rfound++;
|
||||
/*
|
||||
* The type of utmp.ut_time is not necessary type time_t, as
|
||||
* it is explicitly defined as type int32_t. Copy the value
|
||||
* for platforms where sizeof(time_t) != size(int32_t).
|
||||
*/
|
||||
ut_timecopy = _time32_to_time(usr.ut_time);
|
||||
/*
|
||||
* With sparc64 using 64-bit time_t's, there is some system
|
||||
* routine which sets ut_time==0 (the high-order word of a
|
||||
* 64-bit time) instead of a 32-bit time value. For those
|
||||
* wtmp files, it is "more-accurate" to substitute the most-
|
||||
* recent time found, instead of throwing away the entire
|
||||
* record. While it is still just a guess, it is a better
|
||||
* guess than throwing away a log-off record and therefore
|
||||
* counting a session as if it continued to the end of the
|
||||
* month, or the next system-reboot.
|
||||
*/
|
||||
if (ut_timecopy == 0 && prev_secs > 1) {
|
||||
#ifdef DEBUG
|
||||
if (Debug)
|
||||
printf("%s - date changed to: %s",
|
||||
debug_pfx(&usr, &usr), ctime(&prev_secs));
|
||||
#endif
|
||||
tchanged++;
|
||||
usr.ut_time = ut_timecopy = prev_secs;
|
||||
}
|
||||
/*
|
||||
* Skip records where the time goes backwards.
|
||||
*/
|
||||
if (ut_timecopy < prev_secs) {
|
||||
#ifdef DEBUG
|
||||
if (Debug)
|
||||
printf("%s - bad date, record skipped\n",
|
||||
debug_pfx(&usr, &usr));
|
||||
#endif
|
||||
tskipped++;
|
||||
continue; /* Skip this invalid record. */
|
||||
}
|
||||
prev_secs = ut_timecopy;
|
||||
|
||||
if (!FirstTime)
|
||||
FirstTime = usr.ut_time;
|
||||
FirstTime = ut_timecopy;
|
||||
if (Flags & AC_D) {
|
||||
time_t t = _int_to_time(usr.ut_time);
|
||||
ltm = localtime(&t);
|
||||
ltm = localtime(&ut_timecopy);
|
||||
if (day >= 0 && day != ltm->tm_yday) {
|
||||
day = ltm->tm_yday;
|
||||
/*
|
||||
* print yesterday's total
|
||||
*/
|
||||
secs = usr.ut_time;
|
||||
secs = ut_timecopy;
|
||||
secs -= ltm->tm_sec;
|
||||
secs -= 60 * ltm->tm_min;
|
||||
secs -= 3600 * ltm->tm_hour;
|
||||
@ -534,10 +578,10 @@ ac(FILE *fp)
|
||||
}
|
||||
switch(*usr.ut_line) {
|
||||
case '|':
|
||||
secs = usr.ut_time;
|
||||
secs = ut_timecopy;
|
||||
break;
|
||||
case '{':
|
||||
secs -= usr.ut_time;
|
||||
secs -= ut_timecopy;
|
||||
/*
|
||||
* adjust time for those logged in
|
||||
*/
|
||||
@ -546,7 +590,7 @@ ac(FILE *fp)
|
||||
break;
|
||||
case '~': /* reboot or shutdown */
|
||||
head = log_out(head, &usr);
|
||||
FirstTime = usr.ut_time; /* shouldn't be needed */
|
||||
FirstTime = ut_timecopy; /* shouldn't be needed */
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
@ -575,13 +619,13 @@ ac(FILE *fp)
|
||||
(void)strcpy(usr.ut_line, "~");
|
||||
|
||||
if (Flags & AC_D) {
|
||||
time_t t = _int_to_time(usr.ut_time);
|
||||
ltm = localtime(&t);
|
||||
ut_timecopy = _time32_to_time(usr.ut_time);
|
||||
ltm = localtime(&ut_timecopy);
|
||||
if (day >= 0 && day != ltm->tm_yday) {
|
||||
/*
|
||||
* print yesterday's total
|
||||
*/
|
||||
secs = usr.ut_time;
|
||||
secs = ut_timecopy;
|
||||
secs -= ltm->tm_sec;
|
||||
secs -= 60 * ltm->tm_min;
|
||||
secs -= 3600 * ltm->tm_hour;
|
||||
@ -600,6 +644,14 @@ ac(FILE *fp)
|
||||
show_users(Users);
|
||||
show("total", Total);
|
||||
}
|
||||
|
||||
if (tskipped > 0)
|
||||
printf("(Skipped %d of %d records due to invalid time values)\n",
|
||||
tskipped, rfound);
|
||||
if (tchanged > 0)
|
||||
printf("(Changed %d of %d records to have a more likely time value)\n",
|
||||
tchanged, rfound);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user