# HG changeset patch
# User Markus Mützel <markus.muetzel@gmx.de>
# Date 1683458719 -7200
#      Sun May 07 13:25:19 2023 +0200
# Node ID e12f7908038f7a7f7728f7d649b3665e681b6279
# Parent  91014aeb91c867cb18f7f77f7d5597768686c88c
load-path: Avoid file_stat in more places on Windows.

diff -r 91014aeb91c8 -r e12f7908038f libinterp/corefcn/load-path.cc
--- a/libinterp/corefcn/load-path.cc	Sat May 06 18:12:59 2023 +0200
+++ b/libinterp/corefcn/load-path.cc	Sun May 07 13:25:19 2023 +0200
@@ -30,6 +30,10 @@
 #include <algorithm>
 #include <cctype>
 
+#if defined (OCTAVE_USE_WINDOWS_API)
+#  include "windows.h"
+#endif
+
 #include "dir-ops.h"
 #include "file-ops.h"
 #include "file-stat.h"
@@ -192,8 +196,12 @@
 //!
 //! @return true if directory contains modified subdirectories
 
+#if defined (OCTAVE_USE_WINDOWS_API)
+subdirs_modified (const std::string& d, const OCTAVE_TIME_T last_checked)
+#else
 static bool
 subdirs_modified (const std::string& d, const sys::time& last_checked)
+#endif
 {
   sys::dir_entry dir (d);
 
@@ -209,6 +217,27 @@
 
           std::string full_name = sys::file_ops::concat (d, fname);
 
+#if defined (OCTAVE_USE_WINDOWS_API)
+          if (sys::dir_exists (full_name)
+              && (fname[0] == '@' || fname[0] == '+' || fname == "private"))
+            {
+              std::wstring wfull_name = sys::u8_to_wstring (full_name);
+              HANDLE h_file
+                = CreateFile (wfull_name.c_str (), GENERIC_READ,
+                              FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0,
+                              nullptr);
+              FILETIME last_access_time;
+              GetFileTime (h_file, nullptr, &last_access_time, nullptr);
+              OCTAVE_TIME_T last_access
+                = (static_cast<OCTAVE_TIME_T>
+                     (last_access_time.dwHighDateTime)) >> 32
+                  | last_access_time.dwLowDateTime;
+              if ((last_access > last_checked)
+                  || ((fname[0] == '@' || fname[0] == '+')
+                      && subdirs_modified (full_name, last_checked)))
+                return true;
+            }
+#else
           sys::file_stat fs (full_name);
 
           // Check if directory AND if relevant (@,+,private)
@@ -219,6 +248,7 @@
                   || ((fname[0] == '@' || fname[0] == '+')
                       && subdirs_modified (full_name, last_checked))))
             return true;
+#endif
         }
     }
   else
@@ -1450,7 +1480,11 @@
 {
   is_relative = ! sys::env::absolute_pathname (dir_name);
 
+#if defined (OCTAVE_USE_WINDOWS_API)
+  dir_time_last_checked = 0;
+#else
   dir_time_last_checked = sys::time (static_cast<OCTAVE_TIME_T> (0));
+#endif
 
   sys::file_stat fs (dir_name);
 
@@ -1459,8 +1493,27 @@
       method_file_map.clear ();
       package_dir_map.clear ();
 
+#if defined (OCTAVE_USE_WINDOWS_API)
+      std::wstring wdir_name = sys::u8_to_wstring (dir_name);
+      HANDLE h_file
+        = CreateFile (wdir_name.c_str (), GENERIC_READ, FILE_SHARE_READ,
+                      nullptr, OPEN_EXISTING, 0, nullptr);
+      FILETIME last_access_time;
+      GetFileTime (h_file, nullptr, &last_access_time, nullptr);
+      dir_mtime
+        = (static_cast<OCTAVE_TIME_T> (last_access_time.dwHighDateTime)) >> 32
+          | last_access_time.dwLowDateTime;
+
+      FILETIME curr_file_time;
+      GetSystemTimeAsFileTime (&curr_file_time);
+      dir_time_last_checked
+        = (static_cast<OCTAVE_TIME_T> (curr_file_time.dwHighDateTime)) >> 32
+          | curr_file_time.dwLowDateTime;
+#else
       dir_mtime = fs.mtime ();
+
       dir_time_last_checked = sys::time ();
+#endif
 
       get_file_list (dir_name);
 
diff -r 91014aeb91c8 -r e12f7908038f libinterp/corefcn/load-path.h
--- a/libinterp/corefcn/load-path.h	Sat May 06 18:12:59 2023 +0200
+++ b/libinterp/corefcn/load-path.h	Sun May 07 13:25:19 2023 +0200
@@ -289,8 +289,13 @@
     std::string dir_name;
     std::string abs_dir_name;
     bool is_relative;
+#if defined (OCTAVE_USE_WINDOWS_API)
+    OCTAVE_TIME_T dir_mtime;
+    OCTAVE_TIME_T dir_time_last_checked;
+#else
     sys::time dir_mtime;
     sys::time dir_time_last_checked;
+#endif
     string_vector all_files;
     string_vector fcn_files;
     fcn_file_map_type private_file_map;
