Hi Bruno,
On 5/24/24 3:50 PM, Bruno Haible wrote:
> - In line 393 the #endif is misindented.
> - The readutmp module is a second user of boot-time-aux.h. It should also
> make a call to get_windows_boot_time_fallback.
Ah, now I see why those functions are in a header file. I've fixed
those in the attached patch and pushed it.
>> I've only tested it with a mingw compiler and wine so far.
>
> That's good enough. The CI will test it on "real" Windows.
I did a bit of testing using your ci-scratch method. My original patch
didn't work on Cygwin because the GetTickCount64 () symbol couldn't
be found. I was thinking that Cygwin needed the kernel.dll anyways but
maybe there are some restrictions to using the Windows API there.
Since Cygwin passes tests without the fallback I have just restricted
it to Native Windows.
Collin
From 4c2435dc1fc80c3740204c59c1c7b6d9adbe54d3 Mon Sep 17 00:00:00 2001
From: Collin Funk <collin.fu...@gmail.com>
Date: Fri, 24 May 2024 19:23:25 -0700
Subject: [PATCH] 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.
---
ChangeLog | 13 ++++++++
lib/boot-time-aux.h | 74 +++++++++++++++++++++++++++++++++++++++++++++
lib/boot-time.c | 11 +++++++
lib/readutmp.c | 23 ++++++++++++++
modules/boot-time | 1 +
5 files changed, 122 insertions(+)
diff --git a/ChangeLog b/ChangeLog
index d9112a810a..31fd396b43 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2024-05-24 Collin Funk <collin.fu...@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.
+
2024-05-24 Bruno Haible <br...@clisp.org>
putenv tests: Put the putenv() argument strings into writable memory.
diff --git a/lib/boot-time-aux.h b/lib/boot-time-aux.h
index b1add30239..8b98c4e573 100644
--- a/lib/boot-time-aux.h
+++ b/lib/boot-time-aux.h
@@ -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
diff --git a/lib/boot-time.c b/lib/boot-time.c
index c1171e8024..71562dcf75 100644
--- a/lib/boot-time.c
+++ b/lib/boot-time.c
@@ -43,6 +43,13 @@
# 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
diff --git a/lib/readutmp.c b/lib/readutmp.c
index ae2e3ae8c6..82b9d4ca33 100644
--- a/lib/readutmp.c
+++ b/lib/readutmp.c
@@ -51,6 +51,13 @@
# 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;
diff --git a/modules/boot-time b/modules/boot-time
index 2d89969d5c..07e5e43bc6 100644
--- a/modules/boot-time
+++ b/modules/boot-time
@@ -12,6 +12,7 @@ Depends-on:
extensions
idx
stat-time
+gettimeofday
stdbool
time-h
unlocked-io-internal
--
2.45.1