On Minix 3.3, the boot time returned by read_utmp is 1970-01-01 00:00:00. Two workarounds are possible: - Take the time of the "system down" or "run-level m" entry instead, like the workaround for Raspbian does. - Use the time stamp of the file /var/run/syslogd.pid, like the workarounds for Alpine Linux, OpenBSD, Windows. I'm choosing the first one.
2023-08-11 Bruno Haible <br...@clisp.org> readutmp: Fix the boot time returned on Minix. * lib/readutmp.c (read_utmp_from_file): [__minix] When the time of the BOOT_TIME entry is very close to the Epoch, replace it with the time from the "run-level m" entry. diff --git a/lib/readutmp.c b/lib/readutmp.c index c19ec2f6b1..40cee0e58c 100644 --- a/lib/readutmp.c +++ b/lib/readutmp.c @@ -373,7 +373,7 @@ read_utmp_from_file (char const *file, idx_t *n_entries, STRUCT_UTMP **utmp_buf, SET_UTMP_ENT (); -# if defined __linux__ && !defined __ANDROID__ +# if (defined __linux__ && !defined __ANDROID__) || defined __minix bool file_is_utmp = (strcmp (file, UTMP_FILE) == 0); /* Timestamp of the "runlevel" entry, if any. */ struct timespec runlevel_ts = {0}; @@ -461,6 +461,12 @@ read_utmp_from_file (char const *file, idx_t *n_entries, STRUCT_UTMP **utmp_buf, && memcmp (UT_USER (ut), "runlevel", strlen ("runlevel") + 1) == 0 && memcmp (ut->ut_line, "~", strlen ("~") + 1) == 0) runlevel_ts = ts; +# endif +# if defined __minix + if (file_is_utmp + && UT_USER (ut)[0] == '\0' + && memcmp (ut->ut_line, "run-level ", strlen ("run-level ")) == 0) + runlevel_ts = ts; # endif } @@ -571,6 +577,30 @@ read_utmp_from_file (char const *file, idx_t *n_entries, STRUCT_UTMP **utmp_buf, } # endif +# if defined __minix + /* On Minix, during boot, + 1. an entry gets written into /var/run/utmp, with ut_type = BOOT_TIME, + ut_user = "", ut_line = "system boot", time = 1970-01-01 00:00:00, + 2. an entry gets written into /var/run/utmp, with + ut_user = "", ut_line = "run-level m", time = correct value. + In this case, copy the time from the "run-level m" entry to the + "system boot" entry. */ + if ((options & (READ_UTMP_USER_PROCESS | READ_UTMP_NO_BOOT_TIME)) == 0 + && file_is_utmp) + { + for (idx_t i = 0; i < a.filled; i++) + { + struct gl_utmp *ut = &a.utmp[i]; + if (UT_TYPE_BOOT_TIME (ut)) + { + if (ut->ut_ts.tv_sec <= 60 && runlevel_ts.tv_sec != 0) + ut->ut_ts = runlevel_ts; + break; + } + } + } +# endif + # else /* old FreeBSD, OpenBSD, HP-UX */ FILE *f = fopen (file, "re");