]> Savannah Git Hosting - gnulib.git/commitdiff
boot-time, readutmp: Add a Native Windows boot time fallback.
authorCollin Funk <collin.funk1@gmail.com>
Sat, 25 May 2024 02:23:25 +0000 (19:23 -0700)
committerBruno Haible <bruno@clisp.org>
Fri, 31 May 2024 15:35:16 +0000 (17:35 +0200)
* lib/boot-time-aux.h (initialize, get_windows_boot_time_fallback): New
functions.
* lib/boot-time.c [_WIN32 && !__CYGWIN__]: Include Windows headers and
<sys/time.h>.
(get_boot_time_uncached): Use the fallback.
* lib/readutmp.c [_WIN32 && !__CYGWIN__]: Include Windows headers and
<sys/time.h>.
(read_utmp_from_file): Use the fallback.
* modules/boot-time (Depends-on): Add gettimeofday.
* modules/readutmp (Depends-on): Add gettimeofday.

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

index e46a1a7572288f72383abeba77af239702ed6aab..12c2600d7a2fadc9eb541a6ccb1d83fa28c09ebe 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2024-05-24  Collin Funk  <collin.funk1@gmail.com>
+
+       boot-time, readutmp: Add a Native Windows boot time fallback.
+       * lib/boot-time-aux.h (initialize, get_windows_boot_time_fallback): New
+       functions.
+       * lib/boot-time.c [_WIN32 && !__CYGWIN__]: Include Windows headers and
+       <sys/time.h>.
+       (get_boot_time_uncached): Use the fallback.
+       * lib/readutmp.c [_WIN32 && !__CYGWIN__]: Include Windows headers and
+       <sys/time.h>.
+       (read_utmp_from_file): Use the fallback.
+       * modules/boot-time (Depends-on): Add gettimeofday.
+       * modules/readutmp (Depends-on): Add gettimeofday.
+
 2024-05-23  Bruno Haible  <bruno@clisp.org>
 
        mbrtoc32: Work around bug in Cygwin 3.5.3.
index b1add3023912afa289ee664d99f12f59a9191c49..8b98c4e57344213caac48d6a5414fc65e4cc9ed4 100644 (file)
@@ -345,4 +345,78 @@ get_windows_boot_time (struct timespec *p_boot_time)
   return -1;
 }
 
+# ifndef __CYGWIN__
+#  if !(_WIN32_WINNT >= _WIN32_WINNT_VISTA)
+
+/* Don't assume that UNICODE is not defined.  */
+#   undef LoadLibrary
+#   define LoadLibrary LoadLibraryA
+
+/* Avoid warnings from gcc -Wcast-function-type.  */
+#   define GetProcAddress \
+     (void *) GetProcAddress
+
+/* GetTickCount64 is only available on Windows Vista and later.  */
+typedef ULONGLONG (WINAPI * GetTickCount64FuncType) (void);
+
+static GetTickCount64FuncType GetTickCount64Func = NULL;
+static BOOL initialized = FALSE;
+
+static void
+initialize (void)
+{
+  HMODULE kernel32 = LoadLibrary ("kernel32.dll");
+  if (kernel32 != NULL)
+    {
+      GetTickCount64Func =
+        (GetTickCount64FuncType) GetProcAddress (kernel32, "GetTickCount64");
+    }
+  initialized = TRUE;
+}
+
+#  else
+
+#   define GetTickCount64Func GetTickCount64
+
+#  endif
+
+/* Fallback for Windows in the form:
+     boot time = current time - uptime
+   This uses the GetTickCount64 function which is only available on Windows
+   Vista and later. See:
+   <https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-gettickcount64>.  */
+static int
+get_windows_boot_time_fallback (struct timespec *p_boot_time)
+{
+#  if !(_WIN32_WINNT >= _WIN32_WINNT_VISTA)
+  if (! initialized)
+    initialize ();
+#  endif
+  if (GetTickCount64Func != NULL)
+    {
+      ULONGLONG uptime_ms = GetTickCount64Func ();
+      struct timespec uptime;
+      struct timespec result;
+      struct timeval tv;
+      if (gettimeofday (&tv, NULL) >= 0)
+        {
+          uptime.tv_sec = uptime_ms / 1000;
+          uptime.tv_nsec = (uptime_ms % 1000) * 1000000;
+          result.tv_sec = tv.tv_sec;
+          result.tv_nsec = tv.tv_usec * 1000;
+          if (result.tv_nsec < uptime.tv_nsec)
+            {
+              result.tv_nsec += 1000000000;
+              result.tv_sec -= 1;
+            }
+          result.tv_sec -= uptime.tv_sec;
+          result.tv_nsec -= uptime.tv_nsec;
+          *p_boot_time = result;
+          return 0;
+        }
+    }
+  return -1;
+}
+
+# endif
 #endif
index c1171e8024db0f7bf3db7b2add88a71003ad46bf..71562dcf751af3ca05d903e319d75f997f7776ee 100644 (file)
 # include <OS.h>
 #endif
 
+#if defined _WIN32 && ! defined __CYGWIN__
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# include <sysinfoapi.h>
+# include <sys/time.h>
+#endif
+
 #include "idx.h"
 #include "readutmp.h"
 #include "stat-time.h"
@@ -247,6 +254,10 @@ get_boot_time_uncached (struct timespec *p_boot_time)
     {
       /* Workaround for Windows:  */
       get_windows_boot_time (&found_boot_time);
+#  ifndef __CYGWIN__
+      if (found_boot_time.tv_sec == 0)
+        get_windows_boot_time_fallback (&found_boot_time);
+#  endif
     }
 # endif
 
index ae2e3ae8c676f8400b9069b09b6eb83607a85d07..82b9d4ca33af0311252857c4f98ca103a09c1571 100644 (file)
 # include <OS.h>
 #endif
 
+#if defined _WIN32 && ! defined __CYGWIN__
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# include <sysinfoapi.h>
+# include <sys/time.h>
+#endif
+
 #include "stat-time.h"
 #include "xalloc.h"
 
@@ -666,6 +673,22 @@ read_utmp_from_file (char const *file, idx_t *n_entries, STRUCT_UTMP **utmp_buf,
     }
 # endif
 
+# if defined _WIN32 && ! defined __CYGWIN__
+  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_windows_boot_time_fallback (&boot_time) >= 0)
+        a = add_utmp (a, options,
+                      "reboot", strlen ("reboot"),
+                      "", 0,
+                      "", 0,
+                      "", 0,
+                      0, BOOT_TIME, boot_time, 0, 0, 0);
+    }
+# endif
+
   a = finish_utmp (a);
 
   *n_entries = a.filled;
index 2d89969d5caed3f0beb8312d9161ef9a9153fb87..07e5e43bc6796eb2fd30c98092236b82bea57ff4 100644 (file)
@@ -12,6 +12,7 @@ Depends-on:
 extensions
 idx
 stat-time
+gettimeofday
 stdbool
 time-h
 unlocked-io-internal
index 469a7c22561e32b706e6dbcb64dea98eced0b763..01270991876e5cc36823c5b5469d635f3ed0305a 100644 (file)
@@ -12,6 +12,7 @@ Depends-on:
 extensions
 idx
 stat-time
+gettimeofday
 stdbool
 stdint
 strnlen