#include <__assert>
#include <__config>
#include <__utility/unreachable.h>
#include <array>
#include <climits>
#include <cstdlib>
#include <filesystem>
#include <iterator>
#include <string_view>
#include <type_traits>
#include <vector>
#include "error.h"
#include "file_descriptor.h"
#include "path_parser.h"
#include "posix_compat.h"
#include "time_utils.h"
#if defined(_LIBCPP_WIN32API)
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
# include <windows.h>
#else
# include <dirent.h>
# include <sys/stat.h>
# include <sys/statvfs.h>
# include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if __has_include(<sys/sendfile.h>)
# include <sys/sendfile.h>
#define _LIBCPP_FILESYSTEM_USE_SENDFILE
#elif defined(__APPLE__) || __has_include(<copyfile.h>)
# include <copyfile.h>
#define _LIBCPP_FILESYSTEM_USE_COPYFILE
#else
# include <fstream>
#define _LIBCPP_FILESYSTEM_USE_FSTREAM
#endif
#if defined(__ELF__) && defined(_LIBCPP_LINK_RT_LIB)
# pragma comment(lib, "rt")
#endif
_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
capture_errno;
ErrorHandler;
StatT;
TimeSpec;
createView;
PathParser;
string_view_t;
static path __do_absolute(const path& p, path* cwd, error_code* ec) { … }
path __absolute(const path& p, error_code* ec) { … }
path __canonical(path const& orig_p, error_code* ec) { … }
void __copy(const path& from, const path& to, copy_options options, error_code* ec) { … }
namespace detail {
namespace {
#if defined(_LIBCPP_FILESYSTEM_USE_SENDFILE)
bool copy_file_impl(FileDescriptor& read_fd, FileDescriptor& write_fd, error_code& ec) { … }
#elif defined(_LIBCPP_FILESYSTEM_USE_COPYFILE)
bool copy_file_impl(FileDescriptor& read_fd, FileDescriptor& write_fd, error_code& ec) {
struct CopyFileState {
copyfile_state_t state;
CopyFileState() { state = copyfile_state_alloc(); }
~CopyFileState() { copyfile_state_free(state); }
private:
CopyFileState(CopyFileState const&) = delete;
CopyFileState& operator=(CopyFileState const&) = delete;
};
CopyFileState cfs;
if (fcopyfile(read_fd.fd, write_fd.fd, cfs.state, COPYFILE_DATA) < 0) {
ec = capture_errno();
return false;
}
ec.clear();
return true;
}
#elif defined(_LIBCPP_FILESYSTEM_USE_FSTREAM)
bool copy_file_impl(FileDescriptor& read_fd, FileDescriptor& write_fd, error_code& ec) {
ifstream in;
in.__open(read_fd.fd, ios::binary);
if (!in.is_open()) {
ec = capture_errno();
return false;
}
read_fd.fd = -1;
ofstream out;
out.__open(write_fd.fd, ios::binary);
if (!out.is_open()) {
ec = capture_errno();
return false;
}
write_fd.fd = -1;
if (in.good() && out.good()) {
using InIt = istreambuf_iterator<char>;
using OutIt = ostreambuf_iterator<char>;
InIt bin(in);
InIt ein;
OutIt bout(out);
copy(bin, ein, bout);
}
if (out.fail() || in.fail()) {
ec = make_error_code(errc::io_error);
return false;
}
ec.clear();
return true;
}
#else
# error "Unknown implementation for copy_file_impl"
#endif
}
}
bool __copy_file(const path& from, const path& to, copy_options options, error_code* ec) { … }
void __copy_symlink(const path& existing_symlink, const path& new_symlink, error_code* ec) { … }
bool __create_directories(const path& p, error_code* ec) { … }
bool __create_directory(const path& p, error_code* ec) { … }
bool __create_directory(path const& p, path const& attributes, error_code* ec) { … }
void __create_directory_symlink(path const& from, path const& to, error_code* ec) { … }
void __create_hard_link(const path& from, const path& to, error_code* ec) { … }
void __create_symlink(path const& from, path const& to, error_code* ec) { … }
path __current_path(error_code* ec) { … }
void __current_path(const path& p, error_code* ec) { … }
bool __equivalent(const path& p1, const path& p2, error_code* ec) { … }
uintmax_t __file_size(const path& p, error_code* ec) { … }
uintmax_t __hard_link_count(const path& p, error_code* ec) { … }
bool __fs_is_empty(const path& p, error_code* ec) { … }
file_time_type __last_write_time(const path& p, error_code* ec) { … }
void __last_write_time(const path& p, file_time_type new_time, error_code* ec) { … }
void __permissions(const path& p, perms prms, perm_options opts, error_code* ec) { … }
path __read_symlink(const path& p, error_code* ec) { … }
bool __remove(const path& p, error_code* ec) { … }
#if defined(_LIBCPP_WIN32API) || defined(__MVS__)
#define REMOVE_ALL_USE_DIRECTORY_ITERATOR
#endif
#if defined(REMOVE_ALL_USE_DIRECTORY_ITERATOR)
namespace {
uintmax_t remove_all_impl(path const& p, error_code& ec) {
const auto npos = static_cast<uintmax_t>(-1);
const file_status st = __symlink_status(p, &ec);
if (ec)
return npos;
uintmax_t count = 1;
if (is_directory(st)) {
for (directory_iterator it(p, ec); !ec && it != directory_iterator(); it.increment(ec)) {
auto other_count = remove_all_impl(it->path(), ec);
if (ec)
return npos;
count += other_count;
}
if (ec)
return npos;
}
if (!__remove(p, &ec))
return npos;
return count;
}
}
uintmax_t __remove_all(const path& p, error_code* ec) {
ErrorHandler<uintmax_t> err("remove_all", ec, &p);
error_code mec;
auto count = remove_all_impl(p, mec);
if (mec) {
if (mec == errc::no_such_file_or_directory)
return 0;
return err.report(mec);
}
return count;
}
#else
namespace …
uintmax_t __remove_all(const path& p, error_code* ec) { … }
#endif
void __rename(const path& from, const path& to, error_code* ec) { … }
void __resize_file(const path& p, uintmax_t size, error_code* ec) { … }
space_info __space(const path& p, error_code* ec) { … }
file_status __status(const path& p, error_code* ec) { … }
file_status __symlink_status(const path& p, error_code* ec) { … }
path __temp_directory_path(error_code* ec) { … }
path __weakly_canonical(const path& p, error_code* ec) { … }
_LIBCPP_END_NAMESPACE_FILESYSTEM