# HG changeset patch # User Markus Mützel # Date 1665848194 -7200 # Sat Oct 15 17:36:34 2022 +0200 # Node ID b3e6385581ecb2fd745f363affb1c120592881ef # Parent 2ec8fbbcd053532c21b4ade4a854309fd668c544 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. diff -r 2ec8fbbcd053 -r b3e6385581ec liboctave/system/file-ops.cc --- a/liboctave/system/file-ops.cc Sat Oct 15 15:50:33 2022 +0200 +++ 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); +#end + + // 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; diff -r 2ec8fbbcd053 -r b3e6385581ec liboctave/system/file-ops.h --- a/liboctave/system/file-ops.h Sat Oct 15 15:50:33 2022 +0200 +++ 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 diff -r 2ec8fbbcd053 -r b3e6385581ec liboctave/util/cmd-hist.cc --- a/liboctave/util/cmd-hist.cc Sat Oct 15 15:50:33 2022 +0200 +++ 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 ());