26#if defined (HAVE_CONFIG_H)
37#if defined (OCTAVE_USE_WINDOWS_API)
39# include <system_error>
69static const char *default_prefixes[] = {
" ~",
"\t~",
":~",
nullptr };
74static const char *default_suffixes[] = {
" ",
"\n",
":",
nullptr };
77tilde_find_prefix (
const std::string& s, std::size_t&
len)
81 std::size_t s_len = s.length ();
83 if (s_len == 0 || s[0] ==
'~')
86 string_vector prefixes = sys::file_ops::tilde_additional_prefixes;
88 if (! prefixes.
empty ())
90 for (std::size_t i = 0; i < s_len; i++)
92 for (
int j = 0; j < prefixes.
numel (); j++)
94 std::size_t pfx_len = prefixes[j].length ();
96 if (prefixes[j] == s.substr (i, pfx_len))
112tilde_find_suffix (
const std::string& s)
114 std::size_t s_len = s.length ();
116 string_vector suffixes = sys::file_ops::tilde_additional_suffixes;
120 for ( ; i < s_len; i++)
122 if (sys::file_ops::is_dir_sep (s[i]))
125 if (! suffixes.
empty ())
127 for (
int j = 0; j < suffixes.
numel (); j++)
129 std::size_t sfx_len = suffixes[j].length ();
131 if (suffixes[j] == s.substr (i, sfx_len))
143isolate_tilde_prefix (
const std::string& fname)
145 std::size_t f_len = fname.length ();
149 while (
len < f_len && ! sys::file_ops::is_dir_sep (fname[
len]))
152 return fname.substr (1,
len);
159tilde_expand_word (
const std::string& filename)
161 std::size_t f_len = filename.length ();
163 if (f_len == 0 || filename[0] !=
'~')
164 return std::string (filename);
170 if (f_len == 1 || sys::file_ops::is_dir_sep (filename[1]))
171 return sys::env::get_home_directory () + filename.substr (1);
173 std::string username = isolate_tilde_prefix (filename);
175 std::size_t user_len = username.length ();
179 if (sys::file_ops::tilde_expansion_preexpansion_hook)
181 std::string expansion
182 = sys::file_ops::tilde_expansion_preexpansion_hook (username);
184 if (! expansion.empty ())
185 return expansion + filename.substr (user_len+1);
191 sys::password pw = sys::password::getpwnam (username);
198 if (sys::file_ops::tilde_expansion_failure_hook)
200 std::string expansion
201 = sys::file_ops::tilde_expansion_failure_hook (username);
203 if (! expansion.empty ())
204 dirname = expansion + filename.substr (user_len+1);
214 dirname = pw.dir () + filename.substr (user_len+1);
224#if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))
234#if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))
244#if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))
254#if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)
272#if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))
275 octave_unused_parameter (c);
285 return tmp.find (c) != std::string::npos;
291 if (name.find (
'~') == std::string::npos)
292 return std::string (name);
297 std::size_t name_len = name.length ();
312 std::size_t start = tilde_find_prefix (name.substr (pos),
len);
314 result.append (name.substr (pos, start));
323 std::size_t fini = tilde_find_suffix (name.substr (pos));
327 if (! (start || fini))
332 std::string tilde_word = name.substr (pos, fini);
336 std::string expansion = tilde_expand_word (tilde_word);
338 result.append (expansion);
348 int n = names.
numel ();
352 for (
int i = 0; i < n; i++)
359concat (
const std::string& dir,
const std::string& file)
373 return (ipos != std::string::npos) ? path.substr (0, ipos) :
"";
381 if (ipos != std::string::npos)
386 return path.substr (ipos);
398 std::size_t n = path.length ();
399 for (std::size_t i = 0; i < n; i++)
411OCTAVE_END_NAMESPACE(file_ops)
416 return mkdir (nm, md, msg);
420mkdir (
const std::string& name, mode_t mode, std::string& msg)
427 msg = std::strerror (errno);
445#if defined (OCTAVE_USE_WINDOWS_API)
447 std::size_t skip_root = 0;
448 if (name.size () > 1)
453 else if (file_ops::is_dir_sep (name[0])
454 && file_ops::is_dir_sep (name[1]))
457 skip_root = name.find_first_of (file_ops::dir_sep_chars (), 2);
458 skip_root = name.find_first_of (file_ops::dir_sep_chars (),
463 std::size_t delim = name.find_first_of (file_ops::dir_sep_chars (),
466 std::size_t delim = name.find_first_of (file_ops::dir_sep_chars (), 1);
470 while (delim != std::string::npos)
472 std::string base = name.substr (0, delim);
473 sys::file_stat fs (base);
476 status =
mkdir (base, mode, msg);
480 delim = name.find_first_of (file_ops::dir_sep_chars (), delim + 1);
484 return mkdir (name, mode, msg);
491 return mkfifo (nm, md, msg);
495mkfifo (
const std::string& name, mode_t mode, std::string& msg)
502 msg = std::strerror (errno);
508link (
const std::string& old_name,
const std::string& new_name)
511 return link (old_name, new_name, msg);
515link (
const std::string& old_name,
const std::string& new_name,
525 msg = std::strerror (errno);
531symlink (
const std::string& old_name,
const std::string& new_name)
534 return symlink (old_name, new_name, msg);
538symlink (
const std::string& old_name,
const std::string& new_name,
548 msg = std::strerror (errno);
554readlink (
const std::string& path, std::string& result)
557 return readlink (path, result, msg);
561readlink (
const std::string& path, std::string& result, std::string& msg)
570 msg = std::strerror (errno);
582rename (
const std::string& from,
const std::string& to)
585 return rename (from, to, msg);
589rename (
const std::string& from,
const std::string& to,
609#if ! defined (OCTAVE_USE_WINDOWS_API)
615 msg =
"Target already exists.";
620#if defined (OCTAVE_USE_WINDOWS_API)
624 DWORD from_attr = GetFileAttributesW (wfrom.c_str ());
625 DWORD to_attr = GetFileAttributesW (wto.c_str ());
627 if (from_attr == INVALID_FILE_ATTRIBUTES)
630 const std::error_condition econd
631 = std::system_category ().default_error_condition (ERROR_FILE_NOT_FOUND);
632 msg = econd.message ();
636 if (from_attr & FILE_ATTRIBUTE_DIRECTORY)
639 if (to_attr != INVALID_FILE_ATTRIBUTES)
642 msg =
"Cannot replace with directory";
646 if (MoveFileExW (wfrom.c_str (), wto.c_str (), 0))
649 const std::error_condition econd
650 = std::system_category ().default_error_condition (GetLastError ());
651 msg = econd.message ();
658 static const int max_retries = 10;
660 for (
int attempt = 0; attempt < max_retries; ++attempt)
662 if (MoveFileExW (wfrom.c_str (), wto.c_str (), MOVEFILE_REPLACE_EXISTING))
665 DWORD err = GetLastError ();
667 if (err != ERROR_SHARING_VIOLATION
668 && err != ERROR_ACCESS_DENIED
669 && err != ERROR_LOCK_VIOLATION
670 && err != ERROR_DRIVE_LOCKED)
673 const std::error_condition econd
674 = std::system_category ().default_error_condition (err);
675 msg = econd.message ();
679 if (attempt + 1 < max_retries)
686 const std::error_condition econd
687 = std::system_category ().default_error_condition (GetLastError ());
688 msg = econd.message ();
691 status = std::rename (from.c_str (), to.c_str ());
694 msg = std::strerror (errno);
704 return rmdir (name, msg);
708rmdir (
const std::string& name, std::string& msg)
717 msg = std::strerror (errno);
746 std::string nm = dirlist[i];
749 if (nm ==
"." || nm ==
"..")
752 std::string fullnm = name + file_ops::dir_sep_str () + nm;
768 status =
unlink (fullnm, msg);
782 status =
rmdir (name, msg);
800 return unlink (name, msg);
804unlink (
const std::string& name, std::string& msg)
813 msg = std::strerror (errno);
819tempnam (
const std::string& dir,
const std::string& pfx)
822 return tempnam (dir, pfx, msg);
826tempnam (
const std::string& dir,
const std::string& pfx,
834 std::string templatename;
837 else if (!
file_stat (dir,
false).is_dir ())
843 if (*templatename.rbegin () != file_ops::dir_sep_char ())
844 templatename += file_ops::dir_sep_char ();
847 templatename +=
"file";
852 templatename +=
"XXXXXX";
857 strcpy (tname, templatename.c_str ());
860 msg = std::strerror (errno);
884#if defined (OCTAVE_USE_WINDOWS_API)
887 HANDLE h_file = CreateFileW (wname.c_str (), GENERIC_READ,
888 FILE_SHARE_READ,
nullptr, OPEN_EXISTING,
889 FILE_FLAG_BACKUP_SEMANTICS,
nullptr);
895 if (h_file == INVALID_HANDLE_VALUE)
896 h_file = CreateFileW (wname.c_str (), GENERIC_READ,
897 FILE_SHARE_READ,
nullptr, OPEN_EXISTING,
898 FILE_FLAG_BACKUP_SEMANTICS
899 | FILE_FLAG_OPEN_REPARSE_POINT,
nullptr);
901 if (h_file == INVALID_HANDLE_VALUE)
903 msg =
"Unable to open file \"" + name +
"\"";
909 const std::size_t buf_size = 32767;
910 wchar_t buffer[buf_size] = L
"";
913 DWORD
len = GetFinalPathNameByHandleW (h_file, buffer, buf_size,
914 FILE_NAME_NORMALIZED);
917 msg =
"Error querying normalized name for \"" + name +
"\"";
926 if (retval.compare (0, 8, R
"(\\?\UNC\)") == 0)
928 retval = retval.erase (2, 6);
932 if (name.size () < 3 || name[1] !=
':')
936 std::wstring orig_map = wname.substr (0, 3);
938 HANDLE h_map = CreateFileW (orig_map.c_str (), GENERIC_READ,
939 FILE_SHARE_READ,
nullptr, OPEN_EXISTING,
940 FILE_FLAG_BACKUP_SEMANTICS
941 | FILE_FLAG_OPEN_REPARSE_POINT,
944 if (h_map == INVALID_HANDLE_VALUE)
949 len = GetFinalPathNameByHandleW (h_map, buffer, buf_size,
950 FILE_NAME_NORMALIZED);
952 std::string orig_root
955 if (orig_root.compare (0, 8, R
"(\\?\UNC\)"))
959 orig_root = orig_root.erase (2, 6);
961 std::string file_seps = file_ops::dir_sep_chars ();
962 while (file_seps.find (orig_root.back ()) != std::string::npos)
963 orig_root.pop_back ();
965 if (retval.compare (0, orig_root.size (), orig_root))
970 size_t sep_pos = orig_root.size ();
971 if (sep_pos != retval.size ())
972 retval = retval.substr (sep_pos-2);
975 retval[0] = std::toupper (name[0]);
978 else if (retval.compare (0, 4, R
"(\\?\)") == 0)
979 retval = retval.erase (0, 4);
990 msg = std::strerror (errno);
996OCTAVE_END_NAMESPACE(sys)
997OCTAVE_END_NAMESPACE(octave)
char * octave_areadlink_wrapper(const char *name)
char * octave_canonicalize_file_name_wrapper(const char *name)
std::string error() const
static std::string get_temp_directory()
octave_idx_type numel() const
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
int unlink(const std::string &name)
int rename(const std::string &from, const std::string &to)
int symlink(const std::string &old_name, const std::string &new_name)
std::string concat(const std::string &dir, const std::string &file)
std::string canonicalize_file_name(const std::string &name)
std::string dir_sep_str()
int readlink(const std::string &path, std::string &result)
std::string native_separator_path(const std::string &path)
string_vector tilde_additional_suffixes
int rmdir(const std::string &name)
int mkfifo(const std::string &nm, mode_t md)
std::string dir_sep_chars()
std::string tempnam(const std::string &dir, const std::string &pfx)
std::string dirname(const std::string &path)
tilde_expansion_hook tilde_expansion_failure_hook
int link(const std::string &old_name, const std::string &new_name)
tilde_expansion_hook tilde_expansion_preexpansion_hook
int recursive_mkdir(const std::string &name, mode_t mode)
string_vector tilde_additional_prefixes
int recursive_rmdir(const std::string &name)
int mkdir(const std::string &nm, mode_t md)
std::string tilde_expand(const std::string &name)
std::string tail(const std::string &path)
std::string(* tilde_expansion_hook)(const std::string &)
int octave_gen_tempname_wrapper(char *tmpl)
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
std::string u8_from_wstring(const std::wstring &wchar_string)
bool file_exists(const std::string &filename, bool is_dir)
std::wstring u8_to_wstring(const std::string &utf8_string)
bool get_dirlist(const std::string &dirname, string_vector &dirlist, std::string &msg)
bool same_file(const std::string &file1, const std::string &file2)
int octave_mkdir_wrapper(const char *name, mode_t mode)
int octave_mkfifo_wrapper(const char *name, mode_t mode)
int octave_umask_wrapper(mode_t mode)
int octave_rmdir_wrapper(const char *nm)
int octave_unlink_wrapper(const char *nm)
int octave_symlink_wrapper(const char *nm1, const char *nm2)
int octave_link_wrapper(const char *nm1, const char *nm2)