]> Savannah Git Hosting - gnulib.git/commitdiff
readutmp, boot-time: On Haiku, return the boot time.
authorBruno Haible <bruno@clisp.org>
Sat, 12 Aug 2023 17:40:28 +0000 (19:40 +0200)
committerBruno Haible <bruno@clisp.org>
Sat, 12 Aug 2023 17:40:28 +0000 (19:40 +0200)
* m4/readutmp.m4 (gl_PREREQ_READUTMP_H): Test whether <OS.h> exists.
* lib/boot-time-aux.h (get_haiku_boot_time,
get_haiku_boot_time_final_fallback): New functions.
* lib/readutmp.c: Include <OS.h>.
(read_utmp_from_file): If opening UTMP_FILE fails, continue processing
instead of failing. Invoke get_haiku_boot_time and
get_haiku_boot_time_final_fallback.
* lib/boot-time.c: Include <OS.h>.
(get_boot_time_uncached): Invoke get_haiku_boot_time and
get_haiku_boot_time_final_fallback.

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

index f1db83be86f284f2de2e5d3c572811fe83ea9516..30bf3bef826f664a09ea8f9cfef43347bf210b7d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2023-08-12  Bruno Haible  <bruno@clisp.org>
+
+       readutmp, boot-time: On Haiku, return the boot time.
+       * m4/readutmp.m4 (gl_PREREQ_READUTMP_H): Test whether <OS.h> exists.
+       * lib/boot-time-aux.h (get_haiku_boot_time,
+       get_haiku_boot_time_final_fallback): New functions.
+       * lib/readutmp.c: Include <OS.h>.
+       (read_utmp_from_file): If opening UTMP_FILE fails, continue processing
+       instead of failing. Invoke get_haiku_boot_time and
+       get_haiku_boot_time_final_fallback.
+       * lib/boot-time.c: Include <OS.h>.
+       (get_boot_time_uncached): Invoke get_haiku_boot_time and
+       get_haiku_boot_time_final_fallback.
+
 2023-08-12  Bruno Haible  <bruno@clisp.org>
 
        readutmp: Reduce code duplication.
index 8de834efd7dff87fa7b5e96c2aa8ba437d069037..8006b7213416f03aed21deaf0f60a8f4848b3d80 100644 (file)
@@ -227,6 +227,51 @@ get_bsd_boot_time_final_fallback (struct timespec *p_boot_time)
 
 #endif
 
+#if defined __HAIKU__
+
+static int
+get_haiku_boot_time (struct timespec *p_boot_time)
+{
+  /* On Haiku, /etc/utmp does not exist.  During boot,
+       1. the current time is restored, but possibly with a wrong time zone,
+          that is, with an offset of a few hours,
+       2. some symlinks and files get created,
+       3. the various devices are brought up, in particular the network device,
+       4. the correct date and time is set,
+       5. some more device nodes get created.
+     The boot time can be retrieved by looking at a directory created during
+     phase 5, such as /dev/input.  */
+  const char * const boot_touched_file = "/dev/input";
+  struct stat statbuf;
+  if (stat (boot_touched_file, &statbuf) >= 0)
+    {
+      *p_boot_time = get_stat_mtime (&statbuf);
+      return 0;
+    }
+  return -1;
+}
+
+#endif
+
+#if HAVE_OS_H /* BeOS, Haiku */
+
+/* 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_haiku_boot_time_final_fallback (struct timespec *p_boot_time)
+{
+  system_info si;
+
+  get_system_info (&si);
+  p_boot_time->tv_sec = si.boot_time / 1000000;
+  p_boot_time->tv_nsec = (si.boot_time % 1000000) * 1000;
+  return 0;
+}
+
+#endif
+
 #if defined __CYGWIN__ || defined _WIN32
 
 static int
index b27cb6c6b6f6f0381f8df1235aa8ea4ea4d64fea..53bd8b148bc09719f3c73c04d43a08070ad36371 100644 (file)
 # include <sys/sysctl.h>
 #endif
 
+#if HAVE_OS_H
+# include <OS.h>
+#endif
+
 #include "idx.h"
 #include "readutmp.h"
 #include "stat-time.h"
@@ -162,7 +166,7 @@ get_boot_time_uncached (struct timespec *p_boot_time)
     found_boot_time = runlevel_ts;
 #   endif
 
-#  else /* HP-UX */
+#  else /* HP-UX, Haiku */
 
   FILE *f = fopen (UTMP_FILE, "re");
 
@@ -216,6 +220,20 @@ get_boot_time_uncached (struct timespec *p_boot_time)
     }
 # endif
 
+# if defined __HAIKU__
+  if (found_boot_time.tv_sec == 0)
+    {
+      get_haiku_boot_time (&found_boot_time);
+    }
+# endif
+
+# if HAVE_OS_H
+  if (found_boot_time.tv_sec == 0)
+    {
+      get_haiku_boot_time_final_fallback (&found_boot_time);
+    }
+# endif
+
 # if defined __CYGWIN__ || defined _WIN32
   if (found_boot_time.tv_sec == 0)
     {
index d3ed04e2428720f32f2e27b4c5d2746bc30928b7..d0c63034663efce39c587a4ab24bfae87feb165b 100644 (file)
 # include <sys/sysctl.h>
 #endif
 
+#if HAVE_OS_H
+# include <OS.h>
+#endif
+
 #include "stat-time.h"
 #include "xalloc.h"
 
@@ -495,64 +499,74 @@ read_utmp_from_file (char const *file, idx_t *n_entries, STRUCT_UTMP **utmp_buf,
     }
 #   endif
 
-#  else /* old FreeBSD, OpenBSD, HP-UX */
+#  else /* old FreeBSD, OpenBSD, HP-UX, Haiku */
 
   FILE *f = fopen (file, "re");
 
-  if (! f)
-    return -1;
-
-  for (;;)
+  if (f != NULL)
     {
-      struct UTMP_STRUCT_NAME ut;
+      for (;;)
+        {
+          struct UTMP_STRUCT_NAME ut;
 
-      if (fread (&ut, sizeof ut, 1, f) == 0)
-        break;
-      a = add_utmp (a, options,
-                    UT_USER (&ut), strnlen (UT_USER (&ut), UT_USER_SIZE),
-                    #if (HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_ID : HAVE_STRUCT_UTMP_UT_ID)
-                    ut.ut_id, strnlen (ut.ut_id, UT_ID_SIZE),
-                    #else
-                    "", 0,
-                    #endif
-                    ut.ut_line, strnlen (ut.ut_line, UT_LINE_SIZE),
-                    #if (HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_HOST : HAVE_STRUCT_UTMP_UT_HOST)
-                    ut.ut_host, strnlen (ut.ut_host, UT_HOST_SIZE),
-                    #else
-                    "", 0,
-                    #endif
-                    #if (HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_PID : HAVE_STRUCT_UTMP_UT_PID)
-                    ut.ut_pid,
-                    #else
-                    0,
-                    #endif
-                    #if (HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_TYPE : HAVE_STRUCT_UTMP_UT_TYPE)
-                    ut.ut_type,
-                    #else
-                    0,
-                    #endif
-                    #if (HAVE_UTMPX_H ? 1 : HAVE_STRUCT_UTMP_UT_TV)
-                    (struct timespec) { .tv_sec = ut.ut_tv.tv_sec, .tv_nsec = ut.ut_tv.tv_usec * 1000 },
-                    #else
-                    (struct timespec) { .tv_sec = ut.ut_time, .tv_nsec = 0 },
-                    #endif
-                    #if (HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_SESSION : HAVE_STRUCT_UTMP_UT_SESSION)
-                    ut.ut_session,
-                    #else
-                    0,
-                    #endif
-                    UT_EXIT_E_TERMINATION (&ut), UT_EXIT_E_EXIT (&ut)
-                   );
-    }
+          if (fread (&ut, sizeof ut, 1, f) == 0)
+            break;
+          a = add_utmp (a, options,
+                        UT_USER (&ut), strnlen (UT_USER (&ut), UT_USER_SIZE),
+                        #if (HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_ID : HAVE_STRUCT_UTMP_UT_ID)
+                        ut.ut_id, strnlen (ut.ut_id, UT_ID_SIZE),
+                        #else
+                        "", 0,
+                        #endif
+                        ut.ut_line, strnlen (ut.ut_line, UT_LINE_SIZE),
+                        #if (HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_HOST : HAVE_STRUCT_UTMP_UT_HOST)
+                        ut.ut_host, strnlen (ut.ut_host, UT_HOST_SIZE),
+                        #else
+                        "", 0,
+                        #endif
+                        #if (HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_PID : HAVE_STRUCT_UTMP_UT_PID)
+                        ut.ut_pid,
+                        #else
+                        0,
+                        #endif
+                        #if (HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_TYPE : HAVE_STRUCT_UTMP_UT_TYPE)
+                        ut.ut_type,
+                        #else
+                        0,
+                        #endif
+                        #if (HAVE_UTMPX_H ? 1 : HAVE_STRUCT_UTMP_UT_TV)
+                        (struct timespec) { .tv_sec = ut.ut_tv.tv_sec, .tv_nsec = ut.ut_tv.tv_usec * 1000 },
+                        #else
+                        (struct timespec) { .tv_sec = ut.ut_time, .tv_nsec = 0 },
+                        #endif
+                        #if (HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_SESSION : HAVE_STRUCT_UTMP_UT_SESSION)
+                        ut.ut_session,
+                        #else
+                        0,
+                        #endif
+                        UT_EXIT_E_TERMINATION (&ut), UT_EXIT_E_EXIT (&ut)
+                       );
+        }
 
-  int saved_errno = ferror (f) ? errno : 0;
-  if (fclose (f) != 0)
-    saved_errno = errno;
-  if (saved_errno != 0)
+      int saved_errno = ferror (f) ? errno : 0;
+      if (fclose (f) != 0)
+        saved_errno = errno;
+      if (saved_errno != 0)
+        {
+          free (a.utmp);
+          errno = saved_errno;
+          return -1;
+        }
+    }
+  else
     {
-      free (a.utmp);
-      errno = saved_errno;
-      return -1;
+      if (strcmp (file, UTMP_FILE) != 0)
+        {
+          int saved_errno = errno;
+          free (a.utmp);
+          errno = saved_errno;
+          return -1;
+        }
     }
 
 #   if defined __OpenBSD__
@@ -591,6 +605,38 @@ read_utmp_from_file (char const *file, idx_t *n_entries, STRUCT_UTMP **utmp_buf,
     }
 #  endif
 
+#  if defined __HAIKU__
+  if ((options & (READ_UTMP_USER_PROCESS | READ_UTMP_NO_BOOT_TIME)) == 0
+      && strcmp (file, UTMP_FILE) == 0
+      && !have_boot_time (a))
+    {
+      struct timespec boot_time;
+      if (get_haiku_boot_time (&boot_time) >= 0)
+        a = add_utmp (a, options,
+                      "reboot", strlen ("reboot"),
+                      "", 0,
+                      "", 0,
+                      "", 0,
+                      0, BOOT_TIME, boot_time, 0, 0, 0);
+    }
+#  endif
+
+#  if HAVE_OS_H /* BeOS, Haiku */
+  if ((options & (READ_UTMP_USER_PROCESS | READ_UTMP_NO_BOOT_TIME)) == 0
+      && strcmp (file, UTMP_FILE) == 0
+      && !have_boot_time (a))
+    {
+      struct timespec boot_time;
+      if (get_haiku_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
index 357bb8b3c80de2f442fb927c1a2b288be84c05ab..827b573f46cf77d71a99c9a6526e096677a3124d 100644 (file)
@@ -1,4 +1,4 @@
-# readutmp.m4 serial 25
+# readutmp.m4 serial 26
 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,
@@ -112,4 +112,6 @@ AC_INCLUDES_DEFAULT
      #endif
     ])
   AC_CHECK_FUNCS([sysctl])
+
+  AC_CHECK_HEADERS_ONCE([OS.h])
 ])