changeset 31320:6a5e4ef80a95

Create directory for history file recursively (bug #62365). * liboctave/system/file-ops.cc, liboctave/system/file-ops.h (octave::sys::recursive_mkdir): Add new functions to create a directory making sure that all parent directories are also created. * liboctave/system/cmd-hist.cc (gnu_history::do_write): Use new function when creating directory for history.
author Markus Mützel <markus.muetzel@gmx.de>
date Sat, 15 Oct 2022 17:36:34 +0200
parents 6cf02f842e74
children 1d99e68c05c0
files liboctave/system/file-ops.cc liboctave/system/file-ops.h liboctave/util/cmd-hist.cc
diffstat 3 files changed, 61 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/system/file-ops.cc	Wed Oct 19 12:14:09 2022 -0400
+++ b/liboctave/system/file-ops.cc	Sat Oct 15 17:36:34 2022 +0200
@@ -416,6 +416,59 @@
       return status;
     }
 
+    int recursive_mkdir (const std::string& name, mode_t mode)
+    {
+      std::string msg;
+      return recursive_mkdir (name, mode, msg);
+    }
+
+    int recursive_mkdir (const std::string& name, mode_t mode, std::string& msg)
+    {
+      int status;
+
+      // account for root in absolute directories
+#if defined (OCTAVE_USE_WINDOWS_API)
+      // root of current drive
+      std::size_t skip_root = 0;
+      if (name.size () > 1)
+        {
+          if (name[1] == ':')
+            // drive root (e.g., C:\)
+            skip_root = 2;
+          else if (file_ops::is_dir_sep (name[0])
+                   && file_ops::is_dir_sep (name[1]))
+            {
+              // UNC path root (e.g., \\SERVER\share\)
+              skip_root = name.find_first_of (file_ops::dir_sep_chars (), 2);
+              skip_root = name.find_first_of (file_ops::dir_sep_chars (),
+                                              skip_root + 1);
+            }
+        }
+
+      std::size_t delim = name.find_first_of (file_ops::dir_sep_chars (),
+                                              skip_root + 1);
+#else
+      std::size_t delim = name.find_first_of (file_ops::dir_sep_chars (), 1);
+#endif
+
+      // iterate over all componenents of NAME and make directories
+      while (delim != std::string::npos)
+        {
+          std::string base = name.substr (0, delim);
+          sys::file_stat fs (base);
+          if (! fs.is_dir ())
+          {
+            status = mkdir (base, mode, msg);
+            if (status < 0)
+              return status;
+          }
+          delim = name.find_first_of (file_ops::dir_sep_chars (), delim + 1);
+        }
+
+      // finally, create requested directory
+      return mkdir (name, mode, msg);
+    }
+
     int mkfifo (const std::string& nm, mode_t md)
     {
       std::string msg;
--- a/liboctave/system/file-ops.h	Wed Oct 19 12:14:09 2022 -0400
+++ b/liboctave/system/file-ops.h	Sat Oct 15 17:36:34 2022 +0200
@@ -122,6 +122,12 @@
     mkdir (const std::string&, mode_t, std::string&);
 
     extern OCTAVE_API int
+    recursive_mkdir (const std::string& name, mode_t mode);
+
+    extern OCTAVE_API int
+    recursive_mkdir (const std::string& name, mode_t mode, std::string& msg);
+
+    extern OCTAVE_API int
     mkfifo (const std::string&, mode_t);
 
     extern OCTAVE_API int
--- a/liboctave/util/cmd-hist.cc	Wed Oct 19 12:14:09 2022 -0400
+++ b/liboctave/util/cmd-hist.cc	Sat Oct 15 17:36:34 2022 +0200
@@ -370,7 +370,8 @@
             if (! hist_dir.empty ())
               {
                 sys::file_stat fs (hist_dir);
-                if (! fs.is_dir () && (sys::mkdir (hist_dir, 0777) < 0))
+                if (! fs.is_dir ()
+                    && (sys::recursive_mkdir (hist_dir, 0777) < 0))
                   (*current_liboctave_error_handler)
                     ("%s: Could not create directory \"%s\" for history",
                      "gnu_history::do_write", hist_dir.c_str ());