changeset 26843:f07542e3a9b9

Fix "exist" for drive letters and UNC shares on Windows (bug #55824). * sysdep.[h,cc] (drive_or_unc_share): New function. * variables.cc (symbol_exist): Use this function.
author Markus Mützel <markus.muetzel@gmx.de>
date Tue, 05 Mar 2019 22:24:00 +0100
parents 05d492bb8ab8
children d8712d26d086
files libinterp/corefcn/sysdep.cc libinterp/corefcn/sysdep.h libinterp/corefcn/variables.cc
diffstat 3 files changed, 58 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/sysdep.cc	Tue Mar 05 22:04:24 2019 +0100
+++ b/libinterp/corefcn/sysdep.cc	Tue Mar 05 22:24:00 2019 +0100
@@ -320,6 +320,57 @@
 #endif
   }
 
+  // Return TRUE if NAME refers to an existing drive letter or UNC share
+  
+  bool drive_or_unc_share (const std::string& name)
+  {
+#if defined (OCTAVE_USE_WINDOWS_API)
+    size_t len = name.length ();
+    bool candidate = false;
+    if (len > 1 && isalpha(name[0]) && name[1]==':' 
+         && (len == 2 || name[2] == '\\'))
+      candidate = true;
+    if (len > 4 && name[0] == '\\' && name[1] == '\\')
+      {
+        // It starts with two slashes.  Find the next slash.
+        size_t next_slash = name.find ("\\", 3);
+        if (next_slash != -1 && len > next_slash+1)
+          {
+            // Check if it ends with the share
+            size_t last_slash = name.find ("\\", next_slash+1);
+            if (last_slash == -1 ||
+                (len > next_slash+2 && last_slash == len-1))
+              candidate = true;
+          }
+      }
+
+    if (candidate)
+      {
+        // Open a handle to the file.
+        std::wstring wname = octave::sys::u8_to_wstring (name);
+        HANDLE h =
+          CreateFileW (wname.c_str (), FILE_READ_ATTRIBUTES,
+                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                       nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
+                       nullptr);
+        if (h != INVALID_HANDLE_VALUE)
+          {
+            CloseHandle (h);
+            return true;
+          }
+      }
+
+    return false;
+
+#else
+
+    octave_unused_parameter (name);
+
+    return false;
+
+#endif
+  }
+  
   void sysdep_init (void)
   {
     // Use a function from libgomp to force loading of OpenMP library.
--- a/libinterp/corefcn/sysdep.h	Tue Mar 05 22:04:24 2019 +0100
+++ b/libinterp/corefcn/sysdep.h	Tue Mar 05 22:24:00 2019 +0100
@@ -52,6 +52,8 @@
 
   extern OCTINTERP_API bool same_file_internal (const std::string&,
                                                 const std::string&);
+
+  extern OCTINTERP_API bool drive_or_unc_share (const std::string&);
 }
 
 #if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
--- a/libinterp/corefcn/variables.cc	Tue Mar 05 22:04:24 2019 +0100
+++ b/libinterp/corefcn/variables.cc	Tue Mar 05 22:24:00 2019 +0100
@@ -63,6 +63,7 @@
 #include "parse.h"
 #include "syminfo.h"
 #include "symtab.h"
+#include "sysdep.h"
 #include "unwind-prot.h"
 #include "utils.h"
 #include "variables.h"
@@ -270,6 +271,10 @@
       if (file_name.empty ())
         file_name = name;
 
+      // "stat" doesn't work on UNC shares and drive letters.
+      if ((search_any || search_file) && octave::drive_or_unc_share (file_name))
+        return 7;
+
       octave::sys::file_stat fs (file_name);
 
       if (fs)