Thoughts about a bug in share(1M) and utmpx

When I submitted bug 6318057 (share(1M) shouldn’t break if the system time is wrong) I had a nagging doubt and if I’ve learned anything from working in software it’s listen to those nagging doubts.

Essentially I didn’t know how utmpx(4) was used and, in particular, what was contained in the very first entry.

The essence of the bug is that share(1M) checks the time of the sharetab(4) file against the last shutdown time as read from the first entry in utmpx. If the current time is earlier than the last shutdown time (for whatever reason) the sharetab is cleared every time share is run resulting in only one thing ever being shared.

But surely, I thought, utmpx is cleared on boot so the first entry must be the boot time and not the shutdown time?

Not so.

Here’s some simple code to check the times from utmpx.

#include ‹stdio.h›
#include ‹utmpx.h›
#include ‹time.h›
#include ‹stdlib.h›
#define BUFSIZE 100
static char *ut_type_name[] = {
main(int argc, char **argv)
struct utmpx *utmpxp;
char buf[100];
int i, recs;
if (argc > 1) {
recs = atoi(argv[1]);
} else {
recs = 2;
for (i = 0; i ut_xtime);
(void) printf("Time is %s, ", buf);
(void) printf("Type is %d (%s)\n", utmpxp->ut_type,
utmpxp->ut_type ut_type] :
return (0);

When run it shows the first and second entry in utmpx are:

Time is Mon Oct  3 03:46:24 BST 2005, Type is 10 (DOWN_TIME)
Time is Mon Oct  3 03:53:32 BST 2005, Type is 2 (BOOT_TIME)

In other words, the first record in utmpx and thus the record read by share is the DOWN_TIME. You can see this logic from the SMF svc.startd(1M) code where we do indeed clear utmpx …

150 	utmpx_clear_old();
151 	utmpx_write_boottime();

But we also write a DOWN_TIME record:

370 	if (stat(WTMPX_FILE, &stbuf) == 0 && stbuf.st_size != 0) {
371 		tstamp = (stbuf.st_atime >= stbuf.st_mtime) ?
372 		    stbuf.st_atime : stbuf.st_mtime;
373 		utmpx_write_entry(DOWN_TIME, DOWN_MSG, tstamp);
374 	}
376 	/*
377 	 * The boot time (or start time, for a non-global zone) is retrieved in
378 	 * log_init().
379 	 */
380 	tstamp = st->st_start_time.tv_sec;
382 	utmpx_write_entry(BOOT_TIME, BOOT_MSG, tstamp);

So that explains why the first record is DOWN_TIME not BOOT_TIME. I feel happier now 🙂

Technorati Tag:
Technorati Tag:

Leave a comment

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: