changeset 27609:51d26dd80828

Use canonical paths in list of load paths (bug #56267). * load-path.cc: (octave::maybe_canonicalize): New static function. (load_path::set, load_path::add): Canonicalize paths if possible before setting the load path. (load_path::find_dir, load_path::find_matching_dirs, load_path::find_dir_info): Canonicalize input path if possible. (Faddpath): Revert change from 5a0543de1e47. (Frmpath): Revert change from 1397742ea0fe.
author Markus Mützel <markus.muetzel@gmx.de>
date Fri, 01 Nov 2019 21:57:03 +0100
parents 994db4a60d10
children 8586eb41abf5
files libinterp/corefcn/load-path.cc
diffstat 1 files changed, 48 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/load-path.cc	Fri Nov 01 21:31:42 2019 +0100
+++ b/libinterp/corefcn/load-path.cc	Fri Nov 01 21:57:03 2019 +0100
@@ -48,10 +48,41 @@
 
 namespace octave
 {
+  // Canonicalize file name (keeping the path relative) if it exists.
+  // Return it unmodified otherwise.
+
+  static std::string
+  maybe_canonicalize (const std::string& dir_arg)
+  {
+    bool is_absolute_path = octave::sys::env::absolute_pathname (dir_arg);
+
+    std::string canonical_dir = octave::sys::canonicalize_file_name (dir_arg);
+    std::string dir;
+    if (canonical_dir.empty ())
+      dir = dir_arg;
+    else
+      {
+        dir = canonical_dir;
+
+        if (! is_absolute_path)
+          {
+            // Remove current path from absolute path generated by
+            // canonicalize_file_name.
+            std::string cwd = octave::sys::canonicalize_file_name (".");
+            if (dir.compare (0, cwd.length (), cwd) == 0)
+              dir.erase (0, cwd.length ()+1);
+            if (dir.empty ())
+              dir = ".";
+          }
+      }
+
+    return dir;
+  }
+
   static void
   maybe_add_path_elts (std::string& path, const std::string& dir)
   {
-    std::string tpath = genpath (dir);
+    std::string tpath = genpath (maybe_canonicalize (dir));
 
     if (! tpath.empty ())
       {
@@ -254,6 +285,9 @@
     // Use a list when we need to preserve order.
     std::list<std::string> elts = split_path (p);
 
+    for (auto& elt : elts)
+      elt = maybe_canonicalize (elt);
+
     // Use a set when we need to search and order is not important.
     std::set<std::string> elts_set (elts.begin (), elts.end ());
 
@@ -568,6 +602,7 @@
       }
     else
       {
+        std::string canon_dir = maybe_canonicalize (dir);
         for (const auto& di : dir_info_list)
           {
             std::string dname = sys::env::make_absolute (di.dir_name);
@@ -581,11 +616,11 @@
                 dname_len--;
               }
 
-            size_t dir_len = dir.length ();
+            size_t dir_len = canon_dir.length ();
 
             if (dname_len > dir_len
                 && sys::file_ops::is_dir_sep (dname[dname_len - dir_len - 1])
-                && dir == dname.substr (dname_len - dir_len))
+                && canon_dir == dname.substr (dname_len - dir_len))
               {
                 sys::file_stat fs (di.dir_name);
 
@@ -614,6 +649,7 @@
       }
     else
       {
+        std::string canon_dir = maybe_canonicalize (dir);
         for (const auto& di : dir_info_list)
           {
             std::string dname = sys::env::make_absolute (di.dir_name);
@@ -627,11 +663,11 @@
                 dname_len--;
               }
 
-            size_t dir_len = dir.length ();
+            size_t dir_len = canon_dir.length ();
 
             if (dname_len > dir_len
                 && sys::file_ops::is_dir_sep (dname[dname_len - dir_len - 1])
-                && dir == dname.substr (dname_len - dir_len))
+                && canon_dir == dname.substr (dname_len - dir_len))
               {
                 sys::file_stat fs (di.dir_name);
 
@@ -941,6 +977,8 @@
   {
     std::string dir = sys::file_ops::tilde_expand (dir_arg);
 
+    dir = maybe_canonicalize (dir);
+
     auto retval = dir_info_list.cbegin ();
 
     while (retval != dir_info_list.cend ())
@@ -959,6 +997,8 @@
   {
     std::string dir = sys::file_ops::tilde_expand (dir_arg);
 
+    dir = maybe_canonicalize (dir);
+
     auto retval = dir_info_list.begin ();
 
     while (retval != dir_info_list.end ())
@@ -1029,6 +1069,8 @@
 
     dir = strip_trailing_separators (dir);
 
+    dir = maybe_canonicalize (dir);
+
     auto i = find_dir_info (dir);
 
     if (i != dir_info_list.end ())
@@ -2544,23 +2586,6 @@
                       }),
                      dir.end ());
 
-          bool is_absolute_path = octave::sys::env::absolute_pathname (dir);
-
-          std::string canonical_dir = octave::sys::canonicalize_file_name (dir);
-          if (! canonical_dir.empty ())
-            dir = canonical_dir;
-
-          if (! is_absolute_path)
-            {
-              // Remove current path from absolute path generated by
-              // canonicalize_file_name.
-              std::string cwd = octave::sys::canonicalize_file_name (".");
-              if (dir.compare (0, cwd.length (), cwd) == 0)
-                dir.erase (0, cwd.length ()+1);
-              if (dir.empty ())
-                dir = ".";
-            }
-
           auto pos = dir.find_last_of (octave::sys::file_ops::dir_sep_chars ());
           if (pos == std::string::npos)
             {
@@ -2633,15 +2658,11 @@
       std::string arg = args(i).xstring_value ("rmpath: all arguments must be strings");
       std::list<std::string> dir_elts = octave::split_path (arg);
 
-      for (auto dir : dir_elts)
+      for (const auto dir : dir_elts)
         {
           //dir = regexprep (dir_elts{j}, '//+', "/");
           //dir = regexprep (dir, '/$', "");
 
-          std::string canonical_dir = octave::sys::canonicalize_file_name (dir);
-          if (! canonical_dir.empty ())
-            dir = canonical_dir;
-
           if (! lp.remove (dir))
             warning ("rmpath: %s: not found", dir.c_str ());
           else