Ken Brown wrote:
> I don't know what's going on, but it seems clear that pagefile.sys can't 
> be used reliably on Cygwin to get a boot time.  I wonder if 
> get_boot_time should simply bail out on Cygwin and always give a boot 
> time of 0.  Or do you have a better idea?

I'm committing this workaround.


2024-05-04  Bruno Haible  <br...@clisp.org>

        readutmp, boot-time: Work around a Cygwin 3.5.3 bug.
        Reported by Ken Brown <kbr...@cornell.edu> in
        <https://lists.gnu.org/archive/html/bug-gnulib/2024-05/msg00035.html>.
        * lib/boot-time-aux.h (get_windows_boot_time): On Cygwin, ignore
        pagefile.sys if it appears to be a directory, and use another file as
        a fallback.

diff --git a/lib/boot-time-aux.h b/lib/boot-time-aux.h
index a94cdb3f30..7f8c5405e4 100644
--- a/lib/boot-time-aux.h
+++ b/lib/boot-time-aux.h
@@ -304,19 +304,35 @@ get_windows_boot_time (struct timespec *p_boot_time)
      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.  */
-  const char * const boot_touched_file =
-    #if defined __CYGWIN__ && !defined _WIN32
-    /* It is more portable to use /proc/cygdrive/c than /cygdrive/c.  */
-    "/proc/cygdrive/c/pagefile.sys"
-    #else
-    "C:\\pagefile.sys"
-    #endif
-    ;
-  struct stat statbuf;
-  if (stat (boot_touched_file, &statbuf) >= 0)
+  const char * const boot_touched_files[] =
     {
-      *p_boot_time = get_stat_mtime (&statbuf);
-      return 0;
+      #if defined __CYGWIN__ && !defined _WIN32
+      /* It is more portable to use /proc/cygdrive/c than /cygdrive/c.  */
+      "/proc/cygdrive/c/pagefile.sys",
+      /* A fallback, working around a Cygwin 3.5.3 bug.  It has a modification
+         time about 1.5 minutes after the last boot; but that's better than
+         nothing.  */
+      
"/proc/cygdrive/c/ProgramData/Microsoft/Windows/DeviceMetadataCache/dmrc.idx"
+      #else
+      "C:\\pagefile.sys"
+      #endif
+    };
+  for (idx_t i = 0; i < SIZEOF (boot_touched_files); i++)
+    {
+      const char *filename = boot_touched_files[i];
+      struct stat statbuf;
+      if (stat (filename, &statbuf) >= 0)
+        {
+# if defined __CYGWIN__ && !defined _WIN32
+          /* Work around a Cygwin 3.5.3 bug.
+             <https://cygwin.com/pipermail/cygwin/2024-May/255931.html>  */
+          if (!S_ISDIR (statbuf.st_mode))
+# endif
+            {
+              *p_boot_time = get_stat_mtime (&statbuf);
+              return 0;
+            }
+        }
     }
   return -1;
 }




Reply via email to