changeset 32219:792733e11f87

dir_entry: Support paths with non-ASCII characters on Windows (bug #64447). * dir-ops.cc (dir_entry::open): On Windows, check if a directory with the given name exists. Set m_dir to a dummy value. (dir_entry::read): Use wide character Windows API functions to allow traversing directories with non-ASCII characters in their name. (dir_entry::close): On Windows, set the dummy DIR pointer to nullptr.
author Markus Mützel <markus.muetzel@gmx.de>
date Mon, 24 Jul 2023 18:21:18 +0200
parents 3de184236b48
children e0dbf8def91c
files liboctave/system/dir-ops.cc
diffstat 1 files changed, 41 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/system/dir-ops.cc	Fri Jul 28 18:52:56 2023 +0200
+++ b/liboctave/system/dir-ops.cc	Mon Jul 24 18:21:18 2023 +0200
@@ -34,6 +34,10 @@
 #include <list>
 #include <string>
 
+#if defined (OCTAVE_USE_WINDOWS_API)
+#  include "windows.h"
+#endif
+
 #include "dirent-wrappers.h"
 
 #include "dir-ops.h"
@@ -58,10 +62,24 @@
 
       std::string fullname = sys::file_ops::tilde_expand (m_name);
 
+#if defined (OCTAVE_USE_WINDOWS_API)
+      std::string msg;
+
+      if (sys::dir_exists (fullname, msg))
+        // Never dereference this pointer!
+        // We just need something that is non-null.
+        m_dir = reinterpret_cast<void *> (1);
+      else
+        {
+          m_dir = nullptr;
+          m_errmsg = msg;
+        }
+#else
       m_dir = octave_opendir_wrapper (fullname.c_str ());
 
       if (! m_dir)
         m_errmsg = std::strerror (errno);
+#endif
     }
   else
     m_errmsg = "dir_entry::open: empty filename";
@@ -78,10 +96,29 @@
     {
       std::list<std::string> dirlist;
 
+#if defined (OCTAVE_USE_WINDOWS_API)
+      WIN32_FIND_DATAW find_file_data;
+      std::wstring pattern = u8_to_wstring (m_name + "\\*");
+      std::string file_name;
+
+      HANDLE h_find_file = FindFirstFileW (pattern.c_str (), &find_file_data);
+      if (h_find_file != INVALID_HANDLE_VALUE)
+        {
+          do
+            {
+              file_name = u8_from_wstring (find_file_data.cFileName);
+              dirlist.push_back (file_name);
+            }
+          while (FindNextFileW (h_find_file, &find_file_data));
+
+          FindClose (h_find_file);
+        }
+#else
       char *fname;
 
       while ((fname = octave_readdir_wrapper (m_dir)))
         dirlist.push_back (fname);
+#endif
 
       retval = string_vector (dirlist);
     }
@@ -94,12 +131,16 @@
 {
   bool retval = true;
 
+#if defined (OCTAVE_USE_WINDOWS_API)
+  m_dir = nullptr;
+#else
   if (m_dir)
     {
       retval = (octave_closedir_wrapper (m_dir) == 0);
 
       m_dir = nullptr;
     }
+#endif
 
   return retval;
 }