From d87389976e71521818c7b11234208bb076a0f4ab Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sat, 12 Aug 2023 15:09:50 +0200 Subject: [PATCH] readutmp, boot-time: Use the BSD sysctl as fallback. * m4/readutmp.m4 (gl_PREREQ_READUTMP_H): Test for , , sysctl. * lib/boot-time-aux.h (get_bsd_boot_time_final_fallback): New function. * lib/readutmp.c: Include and . (read_utmp_from_file): Invoke get_bsd_boot_time_final_fallback as a fallback. * lib/boot-time.c: Include and . (get_boot_time_uncached): Invoke get_bsd_boot_time_final_fallback as a fallback. --- ChangeLog | 13 +++++++++++++ lib/boot-time-aux.h | 32 ++++++++++++++++++++++++++++++-- lib/boot-time.c | 32 ++++++++++++++++++++++++-------- lib/readutmp.c | 42 +++++++++++++++++++++++++++++++++++++----- m4/readutmp.m4 | 14 ++++++++++++-- 5 files changed, 116 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9f9637c988..31aec050a8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2023-08-12 Bruno Haible + + readutmp, boot-time: Use the BSD sysctl as fallback. + * m4/readutmp.m4 (gl_PREREQ_READUTMP_H): Test for , + , sysctl. + * lib/boot-time-aux.h (get_bsd_boot_time_final_fallback): New function. + * lib/readutmp.c: Include and . + (read_utmp_from_file): Invoke get_bsd_boot_time_final_fallback as a + fallback. + * lib/boot-time.c: Include and . + (get_boot_time_uncached): Invoke get_bsd_boot_time_final_fallback as a + fallback. + 2023-08-12 Bruno Haible readutmp: Fix compilation error on OpenBSD (regression 2023-08-11). diff --git a/lib/boot-time-aux.h b/lib/boot-time-aux.h index fc84086f3f..8de834efd7 100644 --- a/lib/boot-time-aux.h +++ b/lib/boot-time-aux.h @@ -199,7 +199,35 @@ get_openbsd_boot_time (struct timespec *p_boot_time) #endif -# if defined __CYGWIN__ || defined _WIN32 +#if HAVE_SYS_SYSCTL_H && HAVE_SYSCTL \ + && defined CTL_KERN && defined KERN_BOOTTIME \ + && !defined __minix +/* macOS, FreeBSD, GNU/kFreeBSD, NetBSD, OpenBSD */ +/* On Minix 3.3 this sysctl produces garbage results. Therefore avoid it. */ + +/* The following approach is only usable as a fallback, because it produces + wrong values after the date has been bumped in the running system, which + happens frequently if the system is running in a virtual machine and this + VM has been put into "saved" or "sleep" state and then resumed. */ +static int +get_bsd_boot_time_final_fallback (struct timespec *p_boot_time) +{ + static int request[2] = { CTL_KERN, KERN_BOOTTIME }; + struct timeval result; + size_t result_len = sizeof result; + + if (sysctl (request, 2, &result, &result_len, NULL, 0) >= 0) + { + p_boot_time->tv_sec = result.tv_sec; + p_boot_time->tv_nsec = result.tv_usec * 1000; + return 0; + } + return -1; +} + +#endif + +#if defined __CYGWIN__ || defined _WIN32 static int get_windows_boot_time (struct timespec *p_boot_time) @@ -225,4 +253,4 @@ get_windows_boot_time (struct timespec *p_boot_time) return -1; } -# endif +#endif diff --git a/lib/boot-time.c b/lib/boot-time.c index 932ee22d69..b27cb6c6b6 100644 --- a/lib/boot-time.c +++ b/lib/boot-time.c @@ -32,6 +32,13 @@ # include #endif +#if HAVE_SYS_SYSCTL_H && !defined __minix +# if HAVE_SYS_PARAM_H +# include +# endif +# include +#endif + #include "idx.h" #include "readutmp.h" #include "stat-time.h" @@ -66,14 +73,7 @@ get_boot_time_uncached (struct timespec *p_boot_time) { struct timespec found_boot_time = {0}; -# if !(HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_TYPE : HAVE_STRUCT_UTMP_UT_TYPE) /* old FreeBSD, OpenBSD, native Windows */ - -# if defined __OpenBSD__ - /* Workaround for OpenBSD: */ - get_openbsd_boot_time (&found_boot_time); -# endif - -# else +# if (HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_TYPE : HAVE_STRUCT_UTMP_UT_TYPE) /* Try to find the boot time in the /var/run/utmp file. */ @@ -198,6 +198,22 @@ get_boot_time_uncached (struct timespec *p_boot_time) } # endif +# else /* old FreeBSD, OpenBSD, native Windows */ + +# if defined __OpenBSD__ + /* Workaround for OpenBSD: */ + get_openbsd_boot_time (&found_boot_time); +# endif + +# endif + +# if HAVE_SYS_SYSCTL_H && HAVE_SYSCTL \ + && defined CTL_KERN && defined KERN_BOOTTIME \ + && !defined __minix + if (found_boot_time.tv_sec == 0) + { + get_bsd_boot_time_final_fallback (&found_boot_time); + } # endif # if defined __CYGWIN__ || defined _WIN32 diff --git a/lib/readutmp.c b/lib/readutmp.c index d7baa69909..9a5b34054a 100644 --- a/lib/readutmp.c +++ b/lib/readutmp.c @@ -40,6 +40,13 @@ # include #endif +#if HAVE_SYS_SYSCTL_H && !defined __minix +# if HAVE_SYS_PARAM_H +# include +# endif +# include +#endif + #include "stat-time.h" #include "xalloc.h" @@ -570,14 +577,39 @@ read_utmp_from_file (char const *file, idx_t *n_entries, STRUCT_UTMP **utmp_buf, # endif +# if HAVE_SYS_SYSCTL_H && HAVE_SYSCTL \ + && defined CTL_KERN && defined KERN_BOOTTIME \ + && !defined __minix + if ((options & (READ_UTMP_USER_PROCESS | READ_UTMP_NO_BOOT_TIME)) == 0 + && strcmp (file, UTMP_FILE) == 0) + { + bool have_boot_time = false; + for (idx_t i = 0; i < a.filled; i++) + { + struct gl_utmp *ut = &a.utmp[i]; + if (UT_TYPE_BOOT_TIME (ut)) + { + have_boot_time = true; + break; + } + } + if (!have_boot_time) + { + struct timespec boot_time; + if (get_bsd_boot_time_final_fallback (&boot_time) >= 0) + a = add_utmp (a, options, + "reboot", strlen ("reboot"), + "", 0, + "", 0, + "", 0, + 0, BOOT_TIME, boot_time, 0, 0, 0); + } + } +# endif + # endif # if defined __CYGWIN__ || defined _WIN32 - /* On Cygwin, /var/run/utmp is empty. - On native Windows, and don't exist. - Instead, on Windows, the boot time can be retrieved by looking at the - time stamp of a file that (normally) gets touched only during the boot - process, namely C:\pagefile.sys. */ if ((options & (READ_UTMP_USER_PROCESS | READ_UTMP_NO_BOOT_TIME)) == 0 && strcmp (file, UTMP_FILE) == 0 && a.filled == 0) diff --git a/m4/readutmp.m4 b/m4/readutmp.m4 index 07eebcd43d..357bb8b3c8 100644 --- a/m4/readutmp.m4 +++ b/m4/readutmp.m4 @@ -1,4 +1,4 @@ -# readutmp.m4 serial 24 +# readutmp.m4 serial 25 dnl Copyright (C) 2002-2023 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -45,7 +45,7 @@ AC_DEFUN([gl_READUTMP], gl_PREREQ_READUTMP_H ]) -# Prerequisites of readutmp.h. +# Prerequisites of readutmp.h and boot-time-aux.h. AC_DEFUN_ONCE([gl_PREREQ_READUTMP_H], [ dnl Persuade utmpx.h to declare utmpxname @@ -102,4 +102,14 @@ AC_INCLUDES_DEFAULT AC_CHECK_MEMBERS([struct utmpx.ut_exit.e_termination],,,[$utmp_includes]) AC_CHECK_MEMBERS([struct utmp.ut_exit.e_termination],,,[$utmp_includes]) fi + + AC_CHECK_HEADERS_ONCE([sys/param.h]) + dnl requires on OpenBSD 4.0. + AC_CHECK_HEADERS([sys/sysctl.h],,, + [AC_INCLUDES_DEFAULT + #if HAVE_SYS_PARAM_H + # include + #endif + ]) + AC_CHECK_FUNCS([sysctl]) ]) -- 2.39.5