+2023-08-12 Bruno Haible <bruno@clisp.org>
+
+ readutmp, boot-time: Use the BSD sysctl as fallback.
+ * m4/readutmp.m4 (gl_PREREQ_READUTMP_H): Test for <sys/param.h>,
+ <sys/sysctl.h>, sysctl.
+ * lib/boot-time-aux.h (get_bsd_boot_time_final_fallback): New function.
+ * lib/readutmp.c: Include <sys/param.h> and <sys/sysctl.h>.
+ (read_utmp_from_file): Invoke get_bsd_boot_time_final_fallback as a
+ fallback.
+ * lib/boot-time.c: Include <sys/param.h> and <sys/sysctl.h>.
+ (get_boot_time_uncached): Invoke get_bsd_boot_time_final_fallback as a
+ fallback.
+
2023-08-12 Bruno Haible <bruno@clisp.org>
readutmp: Fix compilation error on OpenBSD (regression 2023-08-11).
#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)
return -1;
}
-# endif
+#endif
# include <time.h>
#endif
+#if HAVE_SYS_SYSCTL_H && !defined __minix
+# if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+# endif
+# include <sys/sysctl.h>
+#endif
+
#include "idx.h"
#include "readutmp.h"
#include "stat-time.h"
{
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. */
}
# 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
# include <systemd/sd-login.h>
#endif
+#if HAVE_SYS_SYSCTL_H && !defined __minix
+# if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+# endif
+# include <sys/sysctl.h>
+#endif
+
#include "stat-time.h"
#include "xalloc.h"
# 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, <utmpx.h> and <utmp.h> 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)
-# 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,
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
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 <sys/sysctl.h> requires <sys/param.h> on OpenBSD 4.0.
+ AC_CHECK_HEADERS([sys/sysctl.h],,,
+ [AC_INCLUDES_DEFAULT
+ #if HAVE_SYS_PARAM_H
+ # include <sys/param.h>
+ #endif
+ ])
+ AC_CHECK_FUNCS([sysctl])
])