1 // Filesystem operations -*- C++ -*-
3 // Copyright (C) 2014-2015 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
25 #include <experimental/filesystem>
31 #ifdef _GLIBCXX_HAVE_UNISTD_H
33 # if defined(_GLIBCXX_HAVE_SYS_STAT_H) && defined(_GLIBCXX_HAVE_SYS_TYPES_H)
34 # include <sys/types.h>
35 # include <sys/stat.h>
38 #ifdef _GLIBCXX_HAVE_FCNTL_H
41 #ifdef _GLIBCXX_HAVE_SYS_STATVFS_H
42 # include <sys/statvfs.h>
44 #ifdef _GLIBCXX_HAVE_GNU_SENDFILE
45 # include <sys/sendfile.h>
47 # include <ext/stdio_filebuf.h>
51 namespace fs
= std::experimental::filesystem
;
54 fs::absolute(const path
& p
, const path
& base
)
56 const bool has_root_dir
= p
.has_root_directory();
57 const bool has_root_name
= p
.has_root_name();
59 if (has_root_dir
&& has_root_name
)
63 abs
= base
.is_absolute() ? base
: absolute(base
);
65 abs
= abs
.root_name() / p
;
66 else if (has_root_name
)
67 abs
= p
.root_name() / abs
.root_directory() / abs
.relative_path()
77 struct free_as_in_malloc
79 void operator()(void* p
) const { ::free(p
); }
82 using char_ptr
= std::unique_ptr
<char[], free_as_in_malloc
>;
86 fs::canonical(const path
& p
, const path
& base
, error_code
& ec
)
89 #ifdef _GLIBCXX_USE_REALPATH
90 if (char_ptr rp
= char_ptr
{::realpath(absolute(p
, base
).c_str(), nullptr)})
96 ec
.assign(errno
, std::generic_category());
98 ec
= std::make_error_code(std::errc::not_supported
);
104 fs::canonical(const path
& p
, error_code
& ec
)
106 path cur
= current_path(ec
);
109 return canonical(p
, cur
, ec
);
113 fs::canonical(const path
& p
, const path
& base
)
116 path can
= canonical(p
, base
, ec
);
118 _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot canonicalize", p
, ec
));
123 fs::copy(const path
& from
, const path
& to
, copy_options options
)
126 copy(from
, to
, options
, ec
);
128 _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot copy", from
, to
, ec
));
133 template<typename Bitmask
>
134 bool is_set(Bitmask obj
, Bitmask bits
)
136 return (obj
& bits
) != Bitmask::none
;
140 #ifdef _GLIBCXX_HAVE_SYS_STAT_H
144 make_file_status(const struct ::stat
& st
)
146 using fs::file_status
;
150 perms perm
= static_cast<perms
>(st
.st_mode
) & perms::mask
;
151 #ifdef _GLIBCXX_HAVE_S_ISREG
152 if (S_ISREG(st
.st_mode
))
153 ft
= file_type::regular
;
154 else if (S_ISDIR(st
.st_mode
))
155 ft
= file_type::directory
;
156 else if (S_ISCHR(st
.st_mode
))
157 ft
= file_type::character
;
158 else if (S_ISBLK(st
.st_mode
))
159 ft
= file_type::block
;
160 else if (S_ISFIFO(st
.st_mode
))
161 ft
= file_type::fifo
;
162 else if (S_ISLNK(st
.st_mode
))
163 ft
= file_type::symlink
;
164 else if (S_ISSOCK(st
.st_mode
))
165 ft
= file_type::socket
;
168 ft
= file_type::unknown
;
169 return file_status
{ft
, perm
};
173 is_not_found_errno(int err
)
175 return err
== ENOENT
|| err
== ENOTDIR
;
178 inline fs::file_time_type
179 file_time(const struct ::stat
& st
)
181 using namespace std::chrono
;
182 return fs::file_time_type
{
183 #ifdef _GLIBCXX_USE_ST_MTIM
184 seconds
{st
.st_mtim
.tv_sec
} + nanoseconds
{st
.st_mtim
.tv_nsec
}
192 do_copy_file(const fs::path
& from
, const fs::path
& to
,
193 fs::copy_options option
,
194 struct ::stat
* from_st
, struct ::stat
* to_st
,
195 std::error_code
& ec
) noexcept
197 struct ::stat st1
, st2
;
198 fs::file_status t
, f
;
200 if (to_st
== nullptr)
202 if (::stat(to
.c_str(), &st1
))
205 if (!is_not_found_errno(err
))
207 ec
.assign(err
, std::generic_category());
214 else if (to_st
== from_st
)
217 if (to_st
== nullptr)
218 t
= fs::file_status
{fs::file_type::not_found
};
220 t
= make_file_status(*to_st
);
222 if (from_st
== nullptr)
224 if (::stat(from
.c_str(), &st2
))
226 ec
.assign(errno
, std::generic_category());
232 f
= make_file_status(*from_st
);
236 if (!is_other(t
) && !is_other(f
)
237 && to_st
->st_dev
== from_st
->st_dev
238 && to_st
->st_ino
== from_st
->st_ino
)
240 ec
= std::make_error_code(std::errc::file_exists
);
244 if (is_set(option
, fs::copy_options::skip_existing
))
249 else if (is_set(option
, fs::copy_options::update_existing
))
251 if (file_time(*from_st
) <= file_time(*to_st
))
257 else if (!is_set(option
, fs::copy_options::overwrite_existing
))
259 ec
= std::make_error_code(std::errc::file_exists
);
265 ~CloseFD() { if (fd
!= -1) ::close(fd
); }
269 CloseFD in
= { ::open(from
.c_str(), O_RDONLY
) };
272 ec
.assign(errno
, std::generic_category());
275 CloseFD out
= { ::open(to
.c_str(), O_WRONLY
|O_CREAT
) };
278 ec
.assign(errno
, std::generic_category());
282 #ifdef _GLIBCXX_HAVE_GNU_SENDFILE
283 auto n
= ::sendfile(out
.fd
, in
.fd
, nullptr, from_st
->st_size
);
284 if (n
!= from_st
->st_size
)
286 ec
.assign(errno
, std::generic_category());
290 __gnu_cxx::stdio_filebuf
<char> sbin(in
.fd
, std::ios::in
);
291 __gnu_cxx::stdio_filebuf
<char> sbout(out
.fd
, std::ios::out
);
292 if (std::ostream(&sbout
) << &sbin
)
299 ec
= std::make_error_code(std::errc::io_error
);
304 #ifdef _GLIBCXX_HAVE_FCHMOD
305 if (::fchmod(out
.fd
, from_st
->st_mode
))
307 if (::chmod(to
.c_str(), from_st
->st_mode
))
310 ec
.assign(errno
, std::generic_category());
319 fs::copy(const path
& from
, const path
& to
, copy_options options
,
320 error_code
& ec
) noexcept
322 bool skip_symlinks
= is_set(options
, copy_options::skip_symlinks
);
323 bool create_symlinks
= is_set(options
, copy_options::create_symlinks
);
324 bool use_lstat
= create_symlinks
|| skip_symlinks
;
327 struct ::stat from_st
, to_st
;
329 ? ::lstat(from
.c_str(), &from_st
)
330 : ::stat(from
.c_str(), &from_st
))
332 ec
.assign(errno
, std::generic_category());
336 ? ::lstat(to
.c_str(), &to_st
)
337 : ::stat(to
.c_str(), &to_st
))
339 if (!is_not_found_errno(errno
))
341 ec
.assign(errno
, std::generic_category());
344 t
= file_status
{file_type::not_found
};
347 t
= make_file_status(to_st
);
348 f
= make_file_status(from_st
);
350 if (exists(t
) && !is_other(t
) && !is_other(f
)
351 && to_st
.st_dev
== from_st
.st_dev
&& to_st
.st_ino
== from_st
.st_ino
)
353 ec
= std::make_error_code(std::errc::file_exists
);
356 if (is_other(f
) || is_other(t
))
358 ec
= std::make_error_code(std::errc::not_supported
);
361 if (is_directory(f
) && is_regular_file(t
))
363 ec
= std::make_error_code(std::errc::is_a_directory
);
371 else if (!exists(t
) && is_set(options
, copy_options::copy_symlinks
))
372 copy_symlink(from
, to
, ec
);
374 // Not clear what should be done here.
375 // "Otherwise report an error as specified in Error reporting (7)."
376 ec
= std::make_error_code(std::errc::invalid_argument
);
378 else if (is_regular_file(f
))
380 if (is_set(options
, copy_options::directories_only
))
382 else if (create_symlinks
)
383 create_symlink(from
, to
, ec
);
384 else if (is_set(options
, copy_options::create_hard_links
))
385 create_hard_link(from
, to
, ec
);
386 else if (is_directory(t
))
387 do_copy_file(from
, to
/ from
.filename(), options
, &from_st
, 0, ec
);
390 auto ptr
= exists(t
) ? &to_st
: &from_st
;
391 do_copy_file(from
, to
, options
, &from_st
, ptr
, ec
);
394 else if (is_directory(f
) && (is_set(options
, copy_options::recursive
)
395 || options
== copy_options::none
))
398 if (!create_directory(to
, from
, ec
))
400 // set an unused bit in options to disable further recursion
401 if (!is_set(options
, copy_options::recursive
))
402 options
|= static_cast<copy_options
>(4096);
403 for (const directory_entry
& x
: directory_iterator(from
))
404 copy(x
.path(), to
/x
.path().filename(), options
, ec
);
406 // "Otherwise no effects." (should ec.clear() be called?)
410 fs::copy_file(const path
& from
, const path
& to
, copy_options option
)
413 bool result
= copy_file(from
, to
, option
, ec
);
415 _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot copy file", from
, to
,
421 fs::copy_file(const path
& from
, const path
& to
, copy_options option
,
422 error_code
& ec
) noexcept
424 #ifdef _GLIBCXX_HAVE_SYS_STAT_H
425 return do_copy_file(from
, to
, option
, nullptr, nullptr, ec
);
427 ec
= std::make_error_code(std::errc::not_supported
);
434 fs::copy_symlink(const path
& existing_symlink
, const path
& new_symlink
)
437 copy_symlink(existing_symlink
, new_symlink
, ec
);
439 _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot copy symlink",
440 existing_symlink
, new_symlink
, ec
));
444 fs::copy_symlink(const path
& existing_symlink
, const path
& new_symlink
,
445 error_code
& ec
) noexcept
447 auto p
= read_symlink(existing_symlink
, ec
);
450 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
453 create_directory_symlink(p
, new_symlink
, ec
);
457 create_symlink(p
, new_symlink
, ec
);
462 fs::create_directories(const path
& p
)
465 bool result
= create_directories(p
, ec
);
467 _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create directories", p
,
473 fs::create_directories(const path
& p
, error_code
& ec
) noexcept
475 std::stack
<path
> missing
;
478 while (!p
.empty() && !exists(pp
, ec
) && !ec
.value())
481 pp
= pp
.parent_path();
483 while (!missing
.empty() && !ec
.value())
485 create_directory(missing
.top(), ec
);
488 return missing
.empty();
494 create_dir(const fs::path
& p
, fs::perms perm
, std::error_code
& ec
)
496 #ifdef _GLIBCXX_HAVE_SYS_STAT_H
497 ::mode_t mode
= static_cast<std::underlying_type_t
<fs::perms
>>(perm
);
498 if (::mkdir(p
.c_str(), mode
))
500 ec
.assign(errno
, std::generic_category());
509 ec
= std::make_error_code(std::errc::not_supported
);
516 fs::create_directory(const path
& p
)
519 bool result
= create_directory(p
, ec
);
521 _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create directory", p
,
527 fs::create_directory(const path
& p
, error_code
& ec
) noexcept
529 return create_dir(p
, perms::all
, ec
);
534 fs::create_directory(const path
& p
, const path
& attributes
)
537 bool result
= create_directory(p
, attributes
, ec
);
539 _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create directory", p
,
545 fs::create_directory(const path
& p
, const path
& attributes
,
546 error_code
& ec
) noexcept
548 #ifdef _GLIBCXX_HAVE_SYS_STAT_H
550 if (::stat(attributes
.c_str(), &st
))
552 ec
.assign(errno
, std::generic_category());
555 return create_dir(p
, static_cast<perms
>(st
.st_mode
), ec
);
557 ec
= std::make_error_code(std::errc::not_supported
);
564 fs::create_directory_symlink(const path
& to
, const path
& new_symlink
)
567 create_directory_symlink(to
, new_symlink
, ec
);
569 _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create directory symlink",
570 to
, new_symlink
, ec
));
574 fs::create_directory_symlink(const path
& to
, const path
& new_symlink
,
575 error_code
& ec
) noexcept
577 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
578 ec
= std::make_error_code(std::errc::not_supported
);
580 create_symlink(to
, new_symlink
, ec
);
586 fs::create_hard_link(const path
& to
, const path
& new_hard_link
)
589 create_hard_link(to
, new_hard_link
, ec
);
591 _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create hard link",
592 to
, new_hard_link
, ec
));
596 fs::create_hard_link(const path
& to
, const path
& new_hard_link
,
597 error_code
& ec
) noexcept
599 #ifdef _GLIBCXX_HAVE_UNISTD_H
600 if (::link(to
.c_str(), new_hard_link
.c_str()))
601 ec
.assign(errno
, std::generic_category());
605 ec
= std::make_error_code(std::errc::not_supported
);
610 fs::create_symlink(const path
& to
, const path
& new_symlink
)
613 create_symlink(to
, new_symlink
, ec
);
615 _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create symlink",
616 to
, new_symlink
, ec
));
620 fs::create_symlink(const path
& to
, const path
& new_symlink
,
621 error_code
& ec
) noexcept
623 #ifdef _GLIBCXX_HAVE_UNISTD_H
624 if (::symlink(to
.c_str(), new_symlink
.c_str()))
625 ec
.assign(errno
, std::generic_category());
629 ec
= std::make_error_code(std::errc::not_supported
);
638 path p
= current_path(ec
);
640 _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot get current path", ec
));
645 fs::current_path(error_code
& ec
)
648 #ifdef _GLIBCXX_HAVE_UNISTD_H
650 if (char_ptr cwd
= char_ptr
{::getcwd(nullptr, 0)})
656 ec
.assign(errno
, std::generic_category());
658 long path_max
= pathconf(".", _PC_PATH_MAX
);
662 else if (path_max
> 10240)
666 for (char_ptr buf
; p
.empty(); size
*= 2)
668 if (char* ptr
= realloc(buf
.release(), size
))
671 if (char* ptr
= getcwd(buf
.get(), size
))
678 ec
.assign(errno
, std::generic_category());
684 ec
= std::make_error_code(std::errc::not_enough_memory
);
689 #else // _GLIBCXX_HAVE_UNISTD_H
690 ec
= std::make_error_code(std::errc::not_supported
);
696 fs::current_path(const path
& p
)
701 _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot set current path", ec
));
705 fs::current_path(const path
& p
, error_code
& ec
) noexcept
707 #ifdef _GLIBCXX_HAVE_UNISTD_H
708 if (int err
= ::chdir(p
.c_str()))
709 ec
.assign(err
, std::generic_category());
713 ec
= std::make_error_code(std::errc::not_supported
);
718 fs::equivalent(const path
& p1
, const path
& p2
)
721 auto result
= equivalent(p1
, p2
, ec
);
723 _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot check file equivalence",
729 fs::equivalent(const path
& p1
, const path
& p2
, error_code
& ec
) noexcept
731 #ifdef _GLIBCXX_HAVE_SYS_STAT_H
732 struct ::stat st1
, st2
;
733 if (::stat(p1
.c_str(), &st1
) == 0 && ::stat(p2
.c_str(), &st2
) == 0)
735 file_status s1
= make_file_status(st1
);
736 file_status s2
= make_file_status(st2
);
737 if (is_other(s1
) && is_other(s2
))
739 ec
= std::make_error_code(std::errc::not_supported
);
743 return st1
.st_dev
== st2
.st_dev
&& st1
.st_ino
== st2
.st_ino
;
745 else if (is_not_found_errno(errno
))
747 ec
= std::make_error_code(std::errc::no_such_file_or_directory
);
750 ec
.assign(errno
, std::generic_category());
752 ec
= std::make_error_code(std::errc::not_supported
);
758 fs::file_size(const path
& p
)
761 auto sz
= file_size(p
, ec
);
763 _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot get file size", p
, ec
));
769 template<typename Accessor
, typename T
>
771 do_stat(const fs::path
& p
, std::error_code
& ec
, Accessor f
, T deflt
)
773 #ifdef _GLIBCXX_HAVE_SYS_STAT_H
775 if (::stat(p
.c_str(), &st
))
777 ec
.assign(errno
, std::generic_category());
783 ec
= std::make_error_code(std::errc::not_supported
);
790 fs::file_size(const path
& p
, error_code
& ec
) noexcept
792 return do_stat(p
, ec
, std::mem_fn(&stat::st_size
),
793 static_cast<uintmax_t>(-1));
797 fs::hard_link_count(const path
& p
)
800 auto count
= hard_link_count(p
, ec
);
802 _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot get link count", p
, ec
));
807 fs::hard_link_count(const path
& p
, error_code
& ec
) noexcept
809 return do_stat(p
, ec
, std::mem_fn(&stat::st_nlink
),
810 static_cast<uintmax_t>(-1));
814 fs::is_empty(const path
& p
)
816 return fs::is_directory(status(p
))
817 ? fs::directory_iterator(p
) == fs::directory_iterator()
818 : fs::file_size(p
) == 0;
822 fs::is_empty(const path
& p
, error_code
& ec
) noexcept
824 auto s
= status(p
, ec
);
827 return fs::is_directory(s
)
828 ? fs::directory_iterator(p
, ec
) == fs::directory_iterator()
829 : fs::file_size(p
, ec
) == 0;
833 fs::last_write_time(const path
& p
)
836 auto t
= last_write_time(p
, ec
);
838 _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot get file time", p
, ec
));
843 fs::last_write_time(const path
& p
, error_code
& ec
) noexcept
845 return do_stat(p
, ec
, [](const auto& st
) { return file_time(st
); },
846 file_time_type::min());
850 fs::last_write_time(const path
& p
, file_time_type new_time
)
853 last_write_time(p
, new_time
, ec
);
855 _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot set file time", p
, ec
));
859 fs::last_write_time(const path
& p
, file_time_type new_time
,
860 error_code
& ec
) noexcept
862 auto d
= new_time
.time_since_epoch();
863 auto s
= chrono::duration_cast
<chrono::seconds
>(d
);
864 auto ns
= chrono::duration_cast
<chrono::nanoseconds
>(d
- s
);
865 #ifdef _GLIBCXX_USE_UTIMENSAT
866 struct ::timespec ts
[2] = {
868 { static_cast<std::time_t>(s
.count()), static_cast<long>(ns
.count()) }
870 if (utimensat(AT_FDCWD
, p
.c_str(), ts
, 0))
871 ec
.assign(errno
, std::generic_category());
875 ec
= std::make_error_code(std::errc::not_supported
);
880 fs::permissions(const path
& p
, perms prms
)
883 permissions(p
, prms
, ec
);
885 _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot set permissions", p
, ec
));
888 void fs::permissions(const path
& p
, perms prms
, error_code
& ec
) noexcept
890 if (int err
= ::fchmodat(AT_FDCWD
, p
.c_str(), static_cast<mode_t
>(prms
), 0))
891 ec
.assign(err
, std::generic_category());
897 fs::read_symlink(const path
& p
)
900 path tgt
= read_symlink(p
, ec
);
902 _GLIBCXX_THROW_OR_ABORT(filesystem_error("read_symlink", p
, ec
));
906 fs::path
fs::read_symlink(const path
& p
, error_code
& ec
)
908 #ifdef _GLIBCXX_HAVE_SYS_STAT_H
910 if (::lstat(p
.c_str(), &st
))
912 ec
.assign(errno
, std::generic_category());
915 std::string
buf(st
.st_size
, '\0');
916 ssize_t len
= ::readlink(p
.c_str(), &buf
.front(), buf
.size());
919 ec
.assign(errno
, std::generic_category());
922 return path
{buf
.data(), buf
.data()+len
};
924 ec
= std::make_error_code(std::errc::not_supported
);
931 fs::remove(const path
& p
)
934 bool result
= fs::remove(p
, ec
);
936 _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove", p
, ec
));
941 fs::remove(const path
& p
, error_code
& ec
) noexcept
943 if (exists(symlink_status(p
, ec
)))
945 if (::remove(p
.c_str()) == 0)
951 ec
.assign(errno
, std::generic_category());
958 fs::remove_all(const path
& p
)
961 bool result
= remove_all(p
, ec
);
963 _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p
, ec
));
968 fs::remove_all(const path
& p
, error_code
& ec
) noexcept
970 auto fs
= symlink_status(p
, ec
);
972 if (ec
.value() == 0 && fs
.type() == file_type::directory
)
973 for (directory_iterator
d(p
, ec
), end
; ec
.value() == 0 && d
!= end
; ++d
)
974 count
+= fs::remove(d
->path(), ec
);
977 return fs::remove(p
, ec
) ? ++count
: -1; // fs:remove() calls ec.clear()
981 fs::rename(const path
& from
, const path
& to
)
984 rename(from
, to
, ec
);
986 _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot rename", from
, to
, ec
));
990 fs::rename(const path
& from
, const path
& to
, error_code
& ec
) noexcept
992 if (::rename(from
.c_str(), to
.c_str()))
993 ec
.assign(errno
, std::generic_category());
999 fs::resize_file(const path
& p
, uintmax_t size
)
1002 resize_file(p
, size
, ec
);
1004 _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot resize file", p
, ec
));
1008 fs::resize_file(const path
& p
, uintmax_t size
, error_code
& ec
) noexcept
1010 #ifdef _GLIBCXX_HAVE_UNISTD_H
1011 if (size
> static_cast<uintmax_t>(std::numeric_limits
<off_t
>::max()))
1012 ec
.assign(EINVAL
, std::generic_category());
1013 else if (::truncate(p
.c_str(), size
))
1014 ec
.assign(errno
, std::generic_category());
1018 ec
= std::make_error_code(std::errc::not_supported
);
1024 fs::space(const path
& p
)
1027 space_info s
= space(p
, ec
);
1029 _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot get free space", p
, ec
));
1034 fs::space(const path
& p
, error_code
& ec
) noexcept
1037 static_cast<uintmax_t>(-1),
1038 static_cast<uintmax_t>(-1),
1039 static_cast<uintmax_t>(-1)
1041 #ifdef _GLIBCXX_HAVE_SYS_STATVFS_H
1043 if (int err
= ::statvfs(p
.c_str(), &f
))
1044 ec
.assign(err
, std::generic_category());
1048 f
.f_blocks
* f
.f_frsize
,
1049 f
.f_bfree
* f
.f_frsize
,
1050 f
.f_bavail
* f
.f_frsize
1058 #ifdef _GLIBCXX_HAVE_SYS_STAT_H
1060 fs::status(const fs::path
& p
, std::error_code
& ec
) noexcept
1064 if (::stat(p
.c_str(), &st
))
1067 ec
.assign(err
, std::generic_category());
1068 if (is_not_found_errno(err
))
1069 status
= file_status
{file_type::not_found
};
1073 status
= make_file_status(st
);
1080 fs::symlink_status(const fs::path
& p
, std::error_code
& ec
) noexcept
1084 if (::lstat(p
.c_str(), &st
))
1087 ec
.assign(err
, std::generic_category());
1088 if (is_not_found_errno(err
))
1089 status
= file_status
{file_type::not_found
};
1093 status
= make_file_status(st
);
1101 fs::status(const fs::path
& p
)
1104 auto s
= status(p
, ec
);
1106 _GLIBCXX_THROW_OR_ABORT(filesystem_error("status", p
, ec
));
1111 fs::symlink_status(const fs::path
& p
)
1114 auto s
= symlink_status(p
, ec
);
1116 _GLIBCXX_THROW_OR_ABORT(filesystem_error("symlink_status", ec
));
1121 fs::system_complete(const path
& p
)
1124 path comp
= system_complete(p
, ec
);
1126 _GLIBCXX_THROW_OR_ABORT(filesystem_error("system_complete", p
, ec
));
1131 fs::system_complete(const path
& p
, error_code
& ec
)
1133 path base
= current_path(ec
);
1134 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
1135 if (p
.is_absolute() || !p
.has_root_name()
1136 || p
.root_name() == base
.root_name())
1137 return absolute(p
, base
);
1139 ec
= std::make_error_code(std::errc::not_supported
);
1144 return absolute(p
, base
);
1148 fs::path
fs::temp_directory_path()
1151 path tmp
= temp_directory_path(ec
);
1153 _GLIBCXX_THROW_OR_ABORT(filesystem_error("temp_directory_path", ec
));
1157 fs::path
fs::temp_directory_path(error_code
& ec
)
1159 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
1162 const char* tmpdir
= ::getenv("TMPDIR");