GNU Octave 11.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
file-ops.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1996-2026 The Octave Project Developers
4//
5// See the file COPYRIGHT.md in the top-level directory of this
6// distribution or <https://octave.org/copyright/>.
7//
8// This file is part of Octave.
9//
10// Octave is free software: you can redistribute it and/or modify it
11// under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// Octave is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with Octave; see the file COPYING. If not, see
22// <https://www.gnu.org/licenses/>.
23//
24////////////////////////////////////////////////////////////////////////
25
26#if defined (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#include <cerrno>
31#include <cstdio>
32#include <cstdlib>
33#include <cstring>
34
35#include <vector>
36
37#if defined (OCTAVE_USE_WINDOWS_API)
38# include <cctype>
39# include <system_error>
40
41# include <windows.h>
42# include "unwind-prot.h"
43#else
45#endif
46
47#include "areadlink-wrapper.h"
48#include "dir-ops.h"
49#include "file-ops.h"
50#include "file-stat.h"
52#include "oct-env.h"
53#include "oct-locbuf.h"
54#include "oct-password.h"
55#include "oct-sysdep.h"
56#include "quit.h"
57#include "stat-wrappers.h"
58#include "str-vec.h"
59#include "unistd-wrappers.h"
60
62
63// The following tilde-expansion code was stolen and adapted from
64// readline.
65
66// The default value of tilde_additional_prefixes. This is set to
67// whitespace preceding a tilde so that simple programs which do not
68// perform any word separation get desired behavior.
69static const char *default_prefixes[] = { " ~", "\t~", ":~", nullptr };
70
71// The default value of tilde_additional_suffixes. This is set to
72// whitespace or newline so that simple programs which do not perform
73// any word separation get desired behavior.
74static const char *default_suffixes[] = { " ", "\n", ":", nullptr };
75
76static std::size_t
77tilde_find_prefix (const std::string& s, std::size_t& len)
78{
79 len = 0;
80
81 std::size_t s_len = s.length ();
82
83 if (s_len == 0 || s[0] == '~')
84 return 0;
85
86 string_vector prefixes = sys::file_ops::tilde_additional_prefixes;
87
88 if (! prefixes.empty ())
89 {
90 for (std::size_t i = 0; i < s_len; i++)
91 {
92 for (int j = 0; j < prefixes.numel (); j++)
93 {
94 std::size_t pfx_len = prefixes[j].length ();
95
96 if (prefixes[j] == s.substr (i, pfx_len))
97 {
98 len = pfx_len - 1;
99 return i + len;
100 }
101 }
102 }
103 }
104
105 return s_len;
106}
107
108// Find the end of a tilde expansion in S, and return the index
109// of the character which ends the tilde definition.
110
111static std::size_t
112tilde_find_suffix (const std::string& s)
113{
114 std::size_t s_len = s.length ();
115
116 string_vector suffixes = sys::file_ops::tilde_additional_suffixes;
117
118 std::size_t i = 0;
119
120 for ( ; i < s_len; i++)
121 {
122 if (sys::file_ops::is_dir_sep (s[i]))
123 break;
124
125 if (! suffixes.empty ())
126 {
127 for (int j = 0; j < suffixes.numel (); j++)
128 {
129 std::size_t sfx_len = suffixes[j].length ();
130
131 if (suffixes[j] == s.substr (i, sfx_len))
132 return i;
133 }
134 }
135 }
136
137 return i;
138}
139
140// Take FNAME and return the tilde prefix we want expanded.
141
142static std::string
143isolate_tilde_prefix (const std::string& fname)
144{
145 std::size_t f_len = fname.length ();
146
147 std::size_t len = 1;
148
149 while (len < f_len && ! sys::file_ops::is_dir_sep (fname[len]))
150 len++;
151
152 return fname.substr (1, len);
153}
154
155// Do the work of tilde expansion on FILENAME. FILENAME starts with a
156// tilde.
157
158static std::string
159tilde_expand_word (const std::string& filename)
160{
161 std::size_t f_len = filename.length ();
162
163 if (f_len == 0 || filename[0] != '~')
164 return std::string (filename);
165
166 // A leading '~/' or a bare '~' is *always* translated to the value
167 // of $HOME or the home directory of the current user, regardless of
168 // any preexpansion hook.
169
170 if (f_len == 1 || sys::file_ops::is_dir_sep (filename[1]))
171 return sys::env::get_home_directory () + filename.substr (1);
172
173 std::string username = isolate_tilde_prefix (filename);
174
175 std::size_t user_len = username.length ();
176
177 std::string dirname;
178
179 if (sys::file_ops::tilde_expansion_preexpansion_hook)
180 {
181 std::string expansion
182 = sys::file_ops::tilde_expansion_preexpansion_hook (username);
183
184 if (! expansion.empty ())
185 return expansion + filename.substr (user_len+1);
186 }
187
188 // No preexpansion hook, or the preexpansion hook failed. Look in the
189 // password database.
190
191 sys::password pw = sys::password::getpwnam (username);
192
193 if (! pw)
194 {
195 // If the calling program has a special syntax for expanding tildes,
196 // and we couldn't find a standard expansion, then let them try.
197
198 if (sys::file_ops::tilde_expansion_failure_hook)
199 {
200 std::string expansion
201 = sys::file_ops::tilde_expansion_failure_hook (username);
202
203 if (! expansion.empty ())
204 dirname = expansion + filename.substr (user_len+1);
205 }
206
207 // If we don't have a failure hook, or if the failure hook did not
208 // expand the tilde, return a copy of what we were passed.
209
210 if (dirname.empty ())
211 dirname = filename;
212 }
213 else
214 dirname = pw.dir () + filename.substr (user_len+1);
215
216 return dirname;
217}
218
221
223{
224#if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))
225 return ':';
226#else
227 return 0;
228#endif
229}
230
231char
233{
234#if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))
235 return '\\';
236#else
237 return '/';
238#endif
239}
240
241std::string
243{
244#if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))
245 return R"(\)";
246#else
247 return "/";
248#endif
249}
250
251std::string
253{
254#if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)
255 return R"(/\)";
256#else
257 return dir_sep_str ();
258#endif
259}
260
262
264
266
268
269bool
271{
272#if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))
273 return c == dev_sep_char ();
274#else
275 octave_unused_parameter (c);
276
277 return false;
278#endif
279}
280
281bool
283{
284 std::string tmp = dir_sep_chars ();
285 return tmp.find (c) != std::string::npos;
286}
287
288std::string
289tilde_expand (const std::string& name)
290{
291 if (name.find ('~') == std::string::npos)
292 return std::string (name);
293 else
294 {
295 std::string result;
296
297 std::size_t name_len = name.length ();
298
299 // Scan through S expanding tildes as we come to them.
300
301 std::size_t pos = 0;
302
303 while (1)
304 {
305 if (pos > name_len)
306 break;
307
308 std::size_t len;
309
310 // Make START point to the tilde which starts the expansion.
311
312 std::size_t start = tilde_find_prefix (name.substr (pos), len);
313
314 result.append (name.substr (pos, start));
315
316 // Advance STRING to the starting tilde.
317
318 pos += start;
319
320 // Make FINI be the index of one after the last character of the
321 // username.
322
323 std::size_t fini = tilde_find_suffix (name.substr (pos));
324
325 // If both START and FINI are zero, we are all done.
326
327 if (! (start || fini))
328 break;
329
330 // Expand the entire tilde word, and copy it into RESULT.
331
332 std::string tilde_word = name.substr (pos, fini);
333
334 pos += fini;
335
336 std::string expansion = tilde_expand_word (tilde_word);
337
338 result.append (expansion);
339 }
340
341 return result;
342 }
343}
344
347{
348 int n = names.numel ();
349
350 string_vector retval (n);
351
352 for (int i = 0; i < n; i++)
353 retval[i] = tilde_expand (names[i]);
354
355 return retval;
356}
357
358std::string
359concat (const std::string& dir, const std::string& file)
360{
361 return dir.empty ()
362 ? file
363 : (is_dir_sep (dir.back ())
364 ? dir + file
365 : dir + dir_sep_char () + file);
366}
367
368std::string
369dirname (const std::string& path)
370{
371 std::size_t ipos = path.find_last_of (dir_sep_chars ());
372
373 return (ipos != std::string::npos) ? path.substr (0, ipos) : "";
374}
375
376std::string
377tail (const std::string& path)
378{
379 std::size_t ipos = path.find_last_of (dir_sep_chars ());
380
381 if (ipos != std::string::npos)
382 ipos++;
383 else
384 ipos = 0;
385
386 return path.substr (ipos);
387}
388
389std::string
390native_separator_path (const std::string& path)
391{
392 std::string retval;
393
394 if (dir_sep_char () == '/')
395 retval = path;
396 else
397 {
398 std::size_t n = path.length ();
399 for (std::size_t i = 0; i < n; i++)
400 {
401 if (path[i] == '/')
402 retval += dir_sep_char();
403 else
404 retval += path[i];
405 }
406 }
407
408 return retval;
409}
410
411OCTAVE_END_NAMESPACE(file_ops)
412
413int mkdir (const std::string& nm, mode_t md)
414{
415 std::string msg;
416 return mkdir (nm, md, msg);
417}
418
419int
420mkdir (const std::string& name, mode_t mode, std::string& msg)
421{
422 msg = "";
423
424 int status = octave_mkdir_wrapper (name.c_str (), mode);
425
426 if (status < 0)
427 msg = std::strerror (errno);
428
429 return status;
430}
431
432int
433recursive_mkdir (const std::string& name, mode_t mode)
434{
435 std::string msg;
436 return recursive_mkdir (name, mode, msg);
437}
438
439int
440recursive_mkdir (const std::string& name, mode_t mode, std::string& msg)
441{
442 int status;
443
444 // account for root in absolute directories
445#if defined (OCTAVE_USE_WINDOWS_API)
446 // root of current drive
447 std::size_t skip_root = 0;
448 if (name.size () > 1)
449 {
450 if (name[1] == ':')
451 // drive root (e.g., C:\‍)
452 skip_root = 2;
453 else if (file_ops::is_dir_sep (name[0])
454 && file_ops::is_dir_sep (name[1]))
455 {
456 // UNC path root (e.g., \\SERVER\share\‍)
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 (),
459 skip_root + 1);
460 }
461 }
462
463 std::size_t delim = name.find_first_of (file_ops::dir_sep_chars (),
464 skip_root + 1);
465#else
466 std::size_t delim = name.find_first_of (file_ops::dir_sep_chars (), 1);
467#endif
468
469 // iterate over all componenents of NAME and make directories
470 while (delim != std::string::npos)
471 {
472 std::string base = name.substr (0, delim);
473 sys::file_stat fs (base);
474 if (! fs.is_dir ())
475 {
476 status = mkdir (base, mode, msg);
477 if (status < 0)
478 return status;
479 }
480 delim = name.find_first_of (file_ops::dir_sep_chars (), delim + 1);
481 }
482
483 // finally, create requested directory
484 return mkdir (name, mode, msg);
485}
486
487int
488mkfifo (const std::string& nm, mode_t md)
489{
490 std::string msg;
491 return mkfifo (nm, md, msg);
492}
493
494int
495mkfifo (const std::string& name, mode_t mode, std::string& msg)
496{
497 msg = "";
498
499 int status = octave_mkfifo_wrapper (name.c_str (), mode);
500
501 if (status < 0)
502 msg = std::strerror (errno);
503
504 return status;
505}
506
507int
508link (const std::string& old_name, const std::string& new_name)
509{
510 std::string msg;
511 return link (old_name, new_name, msg);
512}
513
514int
515link (const std::string& old_name, const std::string& new_name,
516 std::string& msg)
517{
518 msg = "";
519
520 int status = -1;
521
522 status = octave_link_wrapper (old_name.c_str (), new_name.c_str ());
523
524 if (status < 0)
525 msg = std::strerror (errno);
526
527 return status;
528}
529
530int
531symlink (const std::string& old_name, const std::string& new_name)
532{
533 std::string msg;
534 return symlink (old_name, new_name, msg);
535}
536
537int
538symlink (const std::string& old_name, const std::string& new_name,
539 std::string& msg)
540{
541 msg = "";
542
543 int status = -1;
544
545 status = octave_symlink_wrapper (old_name.c_str (), new_name.c_str ());
546
547 if (status < 0)
548 msg = std::strerror (errno);
549
550 return status;
551}
552
553int
554readlink (const std::string& path, std::string& result)
555{
556 std::string msg;
557 return readlink (path, result, msg);
558}
559
560int
561readlink (const std::string& path, std::string& result, std::string& msg)
562{
563 int status = -1;
564
565 msg = "";
566
567 char *buf = octave_areadlink_wrapper (path.c_str ());
568
569 if (! buf)
570 msg = std::strerror (errno);
571 else
572 {
573 result = buf;
574 ::free (buf);
575 status = 0;
576 }
577
578 return status;
579}
580
581int
582rename (const std::string& from, const std::string& to)
583{
584 std::string msg;
585 return rename (from, to, msg);
586}
587
588int
589rename (const std::string& from, const std::string& to,
590 std::string& msg)
591{
592 int status = -1;
593
594 msg = "";
595
596 // Do nothing if source and target are the same file.
597 if (same_file (to, from))
598 return 0;
599
600 // The behavior of std::rename with existing target is not defined by the
601 // standard. Implementations differ vastly. For Octave, use the following
602 // for the case that the target already exists:
603 // If the source and the target are regular files, overwrite the target.
604 // In other cases, fail.
605 if (file_exists (to))
606 {
607 if (file_exists (to, false) && file_exists (from, false))
608 {
609#if ! defined (OCTAVE_USE_WINDOWS_API)
610 unlink (to);
611#endif
612 }
613 else
614 {
615 msg = "Target already exists.";
616 return status;
617 }
618 }
619
620#if defined (OCTAVE_USE_WINDOWS_API)
621 std::wstring wfrom = u8_to_wstring (from);
622 std::wstring wto = u8_to_wstring (to);
623
624 DWORD from_attr = GetFileAttributesW (wfrom.c_str ());
625 DWORD to_attr = GetFileAttributesW (wto.c_str ());
626
627 if (from_attr == INVALID_FILE_ATTRIBUTES)
628 {
629 // from does not exist
630 const std::error_condition econd
631 = std::system_category ().default_error_condition (ERROR_FILE_NOT_FOUND);
632 msg = econd.message ();
633 return status;
634 }
635
636 if (from_attr & FILE_ATTRIBUTE_DIRECTORY)
637 {
638 // rename directory
639 if (to_attr != INVALID_FILE_ATTRIBUTES)
640 {
641 // target already exists
642 msg = "Cannot replace with directory";
643 return status;
644 }
645
646 if (MoveFileExW (wfrom.c_str (), wto.c_str (), 0))
647 return 0;
648
649 const std::error_condition econd
650 = std::system_category ().default_error_condition (GetLastError ());
651 msg = econd.message ();
652 return status;
653 }
654
655 // use MoveFileExW with MOVEFILE_REPLACE_EXISTING in a retry loop
656 // files might be locked by anti-virus, indexers, etc.
657
658 static const int max_retries = 10;
659
660 for (int attempt = 0; attempt < max_retries; ++attempt)
661 {
662 if (MoveFileExW (wfrom.c_str (), wto.c_str (), MOVEFILE_REPLACE_EXISTING))
663 return 0;
664
665 DWORD err = GetLastError ();
666
667 if (err != ERROR_SHARING_VIOLATION
668 && err != ERROR_ACCESS_DENIED
669 && err != ERROR_LOCK_VIOLATION
670 && err != ERROR_DRIVE_LOCKED)
671 {
672 // return if the error is not potentially transient
673 const std::error_condition econd
674 = std::system_category ().default_error_condition (err);
675 msg = econd.message ();
676 return status;
677 }
678
679 if (attempt + 1 < max_retries)
680 {
681 // wait before next try
682 Sleep (5);
683 }
684 }
685
686 const std::error_condition econd
687 = std::system_category ().default_error_condition (GetLastError ());
688 msg = econd.message ();
689
690#else
691 status = std::rename (from.c_str (), to.c_str ());
692
693 if (status < 0)
694 msg = std::strerror (errno);
695#endif
696
697 return status;
698}
699
700int
701rmdir (const std::string& name)
702{
703 std::string msg;
704 return rmdir (name, msg);
705}
706
707int
708rmdir (const std::string& name, std::string& msg)
709{
710 msg = "";
711
712 int status = -1;
713
714 status = octave_rmdir_wrapper (name.c_str ());
715
716 if (status < 0)
717 msg = std::strerror (errno);
718
719 return status;
720}
721
722// And a version that works recursively.
723
724int
725recursive_rmdir (const std::string& name)
726{
727 std::string msg;
728 return recursive_rmdir (name, msg);
729}
730
731int
732recursive_rmdir (const std::string& name, std::string& msg)
733{
734 msg = "";
735
736 int status = 0;
737
738 string_vector dirlist;
739
740 if (get_dirlist (name, dirlist, msg))
741 {
742 for (octave_idx_type i = 0; i < dirlist.numel (); i++)
743 {
744 octave_quit ();
745
746 std::string nm = dirlist[i];
747
748 // Skip current directory and parent.
749 if (nm == "." || nm == "..")
750 continue;
751
752 std::string fullnm = name + file_ops::dir_sep_str () + nm;
753
754 // Get info about the file. Don't follow links.
755 file_stat fs (fullnm, false);
756
757 if (fs)
758 {
759 if (fs.is_dir ())
760 {
761 status = recursive_rmdir (fullnm, msg);
762
763 if (status < 0)
764 break;
765 }
766 else
767 {
768 status = unlink (fullnm, msg);
769
770 if (status < 0)
771 break;
772 }
773 }
774 else
775 {
776 msg = fs.error ();
777 break;
778 }
779 }
780
781 if (status >= 0)
782 status = rmdir (name, msg);
783 }
784 else
785 status = -1;
786
787 return status;
788}
789
790int
791umask (mode_t mode)
792{
793 return octave_umask_wrapper (mode);
794}
795
796int
797unlink (const std::string& name)
798{
799 std::string msg;
800 return unlink (name, msg);
801}
802
803int
804unlink (const std::string& name, std::string& msg)
805{
806 msg = "";
807
808 int status = -1;
809
810 status = octave_unlink_wrapper (name.c_str ());
811
812 if (status < 0)
813 msg = std::strerror (errno);
814
815 return status;
816}
817
818std::string
819tempnam (const std::string& dir, const std::string& pfx)
820{
821 std::string msg;
822 return tempnam (dir, pfx, msg);
823}
824
825std::string
826tempnam (const std::string& dir, const std::string& pfx,
827 std::string& msg)
828{
829 msg = "";
830
831 std::string retval;
832
833 // get dir path to use for template
834 std::string templatename;
835 if (dir.empty ())
836 templatename = env::get_temp_directory ();
837 else if (! file_stat (dir, false).is_dir ())
838 templatename = env::get_temp_directory ();
839 else
840 templatename = dir;
841
842 // add dir sep char if it is not there
843 if (*templatename.rbegin () != file_ops::dir_sep_char ())
844 templatename += file_ops::dir_sep_char ();
845
846 if (pfx.empty ())
847 templatename += "file";
848 else
849 templatename += pfx;
850
851 // add the required XXXXXX for the template
852 templatename += "XXXXXX";
853
854 // create and copy template to char array for call to gen_tempname
855 OCTAVE_LOCAL_BUFFER (char, tname, templatename.length () + 1);
856
857 strcpy (tname, templatename.c_str ());
858
859 if (octave_gen_tempname_wrapper (tname) == -1)
860 msg = std::strerror (errno);
861 else
862 retval = tname;
863
864 return retval;
865}
866
867std::string
868canonicalize_file_name (const std::string& name)
869{
870 std::string msg;
871 return canonicalize_file_name (name, msg);
872}
873
874std::string
875canonicalize_file_name (const std::string& name, std::string& msg)
876{
877 msg = "";
878
879 std::string retval;
880
881 // FIXME: Consider replacing this with std::filesystem::canonical on all
882 // platforms once we allow using C++17.
883
884#if defined (OCTAVE_USE_WINDOWS_API)
885 // open file handle
886 std::wstring wname = u8_to_wstring (name);
887 HANDLE h_file = CreateFileW (wname.c_str (), GENERIC_READ,
888 FILE_SHARE_READ, nullptr, OPEN_EXISTING,
889 FILE_FLAG_BACKUP_SEMANTICS, nullptr);
890
891 // Might have been a symbolic link that points to a network share.
892 // It looks like opening a network share itself (not a file or folder
893 // *on* a share) might return an invalid handle. As a workaround, try to
894 // open a handle to the symbolic link itself (and do not resolve it).
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);
900
901 if (h_file == INVALID_HANDLE_VALUE)
902 {
903 msg = "Unable to open file \"" + name + "\"";
904 return retval;
905 }
906
907 unwind_action close_file_handle (CloseHandle, h_file);
908
909 const std::size_t buf_size = 32767;
910 wchar_t buffer[buf_size] = L"";
911
912 // query canonical name
913 DWORD len = GetFinalPathNameByHandleW (h_file, buffer, buf_size,
914 FILE_NAME_NORMALIZED);
915 if (len >= buf_size)
916 {
917 msg = "Error querying normalized name for \"" + name + "\"";
918 return retval;
919 }
920
921 retval = u8_from_wstring (std::wstring (buffer, len));
922
923 // remove prefix
924 // "Normal" paths are prefixed by "\\?\".
925 // UNC paths are prefixed by "\\?\UNC\".
926 if (retval.compare (0, 8, R"(\\?\UNC\)") == 0)
927 {
928 retval = retval.erase (2, 6);
929
930 // If the initial path looked like a mapped network drive, replace
931 // portion of path that corresponds to mapped root with drive root.
932 if (name.size () < 3 || name[1] != ':')
933 return retval;
934
935 // UNC path corresponding to original drive letter (mappped drive)
936 std::wstring orig_map = wname.substr (0, 3);
937 orig_map[2] = L'\\';
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,
942 nullptr);
943
944 if (h_map == INVALID_HANDLE_VALUE)
945 // cannot determine common root
946 return retval;
947
948 unwind_action close_map_handle (CloseHandle, h_map);
949 len = GetFinalPathNameByHandleW (h_map, buffer, buf_size,
950 FILE_NAME_NORMALIZED);
951
952 std::string orig_root
953 = u8_from_wstring (std::wstring (buffer, len));
954
955 if (orig_root.compare (0, 8, R"(\\?\UNC\)"))
956 // root was not a mapped share
957 return retval;
958
959 orig_root = orig_root.erase (2, 6);
960 // trim trailing file separators from UNC path corresponding to root
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 ();
964
965 if (retval.compare (0, orig_root.size (), orig_root))
966 // start of UNC path doesn't match mapped drive root
967 return retval;
968
969 // file is on mapped share
970 size_t sep_pos = orig_root.size ();
971 if (sep_pos != retval.size ())
972 retval = retval.substr (sep_pos-2);
973 else
974 retval.resize (2); // no file component
975 retval[0] = std::toupper (name[0]);
976 retval[1] = ':';
977 }
978 else if (retval.compare (0, 4, R"(\\?\)") == 0)
979 retval = retval.erase (0, 4);
980#else
981 char *tmp = octave_canonicalize_file_name_wrapper (name.c_str ());
982
983 if (tmp)
984 {
985 retval = tmp;
986 free (tmp);
987 }
988
989 if (retval.empty ())
990 msg = std::strerror (errno);
991#endif
992
993 return retval;
994}
995
996OCTAVE_END_NAMESPACE(sys)
997OCTAVE_END_NAMESPACE(octave)
char * octave_canonicalize_file_name_wrapper(const char *name)
bool is_dir() const
Definition file-stat.cc:64
std::string error() const
Definition file-stat.h:146
static std::string get_temp_directory()
Definition oct-env.cc:151
bool empty() const
Definition str-vec.h:75
octave_idx_type numel() const
Definition str-vec.h:98
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
int unlink(const std::string &name)
Definition file-ops.cc:797
bool is_dir_sep(char c)
Definition file-ops.cc:282
int rename(const std::string &from, const std::string &to)
Definition file-ops.cc:582
int symlink(const std::string &old_name, const std::string &new_name)
Definition file-ops.cc:531
std::string concat(const std::string &dir, const std::string &file)
Definition file-ops.cc:359
std::string canonicalize_file_name(const std::string &name)
Definition file-ops.cc:868
std::string dir_sep_str()
Definition file-ops.cc:242
int readlink(const std::string &path, std::string &result)
Definition file-ops.cc:554
std::string native_separator_path(const std::string &path)
Definition file-ops.cc:390
string_vector tilde_additional_suffixes
Definition file-ops.cc:267
int rmdir(const std::string &name)
Definition file-ops.cc:701
int mkfifo(const std::string &nm, mode_t md)
Definition file-ops.cc:488
std::string dir_sep_chars()
Definition file-ops.cc:252
std::string tempnam(const std::string &dir, const std::string &pfx)
Definition file-ops.cc:819
std::string dirname(const std::string &path)
Definition file-ops.cc:369
bool is_dev_sep(char c)
Definition file-ops.cc:270
tilde_expansion_hook tilde_expansion_failure_hook
Definition file-ops.cc:263
char dir_sep_char()
Definition file-ops.cc:232
int link(const std::string &old_name, const std::string &new_name)
Definition file-ops.cc:508
tilde_expansion_hook tilde_expansion_preexpansion_hook
Definition file-ops.cc:261
int recursive_mkdir(const std::string &name, mode_t mode)
Definition file-ops.cc:433
string_vector tilde_additional_prefixes
Definition file-ops.cc:265
char dev_sep_char()
Definition file-ops.cc:222
int recursive_rmdir(const std::string &name)
Definition file-ops.cc:725
int mkdir(const std::string &nm, mode_t md)
Definition file-ops.cc:413
std::string tilde_expand(const std::string &name)
Definition file-ops.cc:289
int umask(mode_t mode)
Definition file-ops.cc:791
std::string tail(const std::string &path)
Definition file-ops.cc:377
std::string(* tilde_expansion_hook)(const std::string &)
Definition file-ops.h:42
int octave_gen_tempname_wrapper(char *tmpl)
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition oct-locbuf.h:44
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)
void free(void *)
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)
F77_RET_T len
Definition xerbla.cc:61