]> Savannah Git Hosting - gnulib.git/commitdiff
readutmp, boot-time: Use the BSD sysctl as fallback.
authorBruno Haible <bruno@clisp.org>
Sat, 12 Aug 2023 13:09:50 +0000 (15:09 +0200)
committerBruno Haible <bruno@clisp.org>
Sat, 12 Aug 2023 13:09:50 +0000 (15:09 +0200)
* 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.

ChangeLog
lib/boot-time-aux.h
lib/boot-time.c
lib/readutmp.c
m4/readutmp.m4

index 9f9637c988c6277c0161922a94796f1ff6eea3b8..31aec050a8acb24b9ecbb739e7d7d5aa16aba2c4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+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).
index fc84086f3f50f652c8b3ef90640e88324c0aceca..8de834efd7dff87fa7b5e96c2aa8ba437d069037 100644 (file)
@@ -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
index 932ee22d69f5e64601bba6324a1fb2fcf51dd09a..b27cb6c6b6f6f0381f8df1235aa8ea4ea4d64fea 100644 (file)
 # 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"
@@ -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
index d7baa69909faabf6ced2313e6dde4381e6ffc37e..9a5b34054ab06109f7ab822082cb1b42a61ffd8c 100644 (file)
 # 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"
 
@@ -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, <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)
index 07eebcd43d5cb4c36a91024026948aee7cb77aa8..357bb8b3c80de2f442fb927c1a2b288be84c05ab 100644 (file)
@@ -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 <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])
 ])