Index: libcxx/src/filesystem/filesystem_common.h =================================================================== --- libcxx/src/filesystem/filesystem_common.h +++ libcxx/src/filesystem/filesystem_common.h @@ -340,6 +340,8 @@ #define S_ISLNK(m) (((m) & _S_IFMT) == _S_IFLNK) #define S_ISSOCK(m) (((m) & _S_IFMT) == _S_IFSOCK) +#define O_NONBLOCK 0 + #else using TimeSpec = timespec; using StatT = struct stat; Index: libcxx/src/filesystem/operations.cpp =================================================================== --- libcxx/src/filesystem/operations.cpp +++ libcxx/src/filesystem/operations.cpp @@ -431,10 +431,102 @@ return stat_handle(h, buf); } +int mkdir(const wchar_t *path, int permissions) { + (void)permissions; + return _wmkdir(path); +} + +int symlink_file_dir(const wchar_t *oldname, const wchar_t *newname, + bool is_dir) { + DWORD flags = is_dir ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0; + if (CreateSymbolicLinkW(newname, oldname, + flags | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)) + return 0; + if (GetLastError() != ERROR_INVALID_PARAMETER) + return set_errno(); + if (CreateSymbolicLinkW(newname, oldname, flags)) + return 0; + return set_errno(); +} + +int symlink_file(const wchar_t *oldname, const wchar_t *newname) { + return symlink_file_dir(oldname, newname, false); +} + +int symlink_dir(const wchar_t *oldname, const wchar_t *newname) { + return symlink_file_dir(oldname, newname, true); +} + +int link(const wchar_t *oldname, const wchar_t *newname) { + if (CreateHardLinkW(newname, oldname, nullptr)) + return 0; + return set_errno(); +} + +int remove(const wchar_t *path) { + detail::WinHandle h(path, DELETE, FILE_FLAG_OPEN_REPARSE_POINT); + if (!h) + return set_errno(); + FILE_DISPOSITION_INFO info; + info.DeleteFile = TRUE; + if (!SetFileInformationByHandle(h, FileDispositionInfo, &info, sizeof(info))) + return set_errno(); + return 0; +} + +int truncate_handle(HANDLE h, off_t length) { + LARGE_INTEGER size_param; + size_param.QuadPart = length; + if (!SetFilePointerEx(h, size_param, 0, FILE_BEGIN)) + return set_errno(); + if (!SetEndOfFile(h)) + return set_errno(); + return 0; +} + +int ftruncate(int fd, off_t length) { + HANDLE h = reinterpret_cast(_get_osfhandle(fd)); + return truncate_handle(h, length); +} + +int truncate(const wchar_t *path, off_t length) { + detail::WinHandle h(path, GENERIC_WRITE, 0); + if (!h) + return set_errno(); + return truncate_handle(h, length); +} + +int rename(const wchar_t *from, const wchar_t *to) { + if (!(MoveFileExW(from, to, + MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING))) + return set_errno(); + return 0; +} + +template int open(const wchar_t *filename, Args... args) { + return _wopen(filename, args...); +} +int close(int fd) { return _close(fd); } +int chdir(const wchar_t *path) { return _wchdir(path); } #else +int symlink_file(const char *oldname, const char *newname) { + return ::symlink(oldname, newname); +} +int symlink_dir(const char *oldname, const char *newname) { + return ::symlink(oldname, newname); +} +using ::chdir; +using ::close; using ::fstat; +using ::ftruncate; +using ::link; using ::lstat; +using ::mkdir; +using ::open; +using ::remove; +using ::rename; using ::stat; +using ::truncate; #endif @@ -448,7 +540,7 @@ static FileDescriptor create(const path* p, error_code& ec, Args... args) { ec.clear(); int fd; - if ((fd = ::open(p->c_str(), args...)) == -1) { + if ((fd = detail::open(p->c_str(), args...)) == -1) { ec = capture_errno(); return FileDescriptor{p}; } @@ -474,7 +566,7 @@ void close() noexcept { if (fd != -1) - ::close(fd); + detail::close(fd); fd = -1; } @@ -564,7 +656,7 @@ // http://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html bool posix_ftruncate(const FileDescriptor& fd, off_t to_size, error_code& ec) { - if (::ftruncate(fd.fd, to_size) == -1) { + if (detail::ftruncate(fd.fd, to_size) == -1) { ec = capture_errno(); return true; } @@ -992,7 +1084,7 @@ bool __create_directory(const path& p, error_code* ec) { ErrorHandler err("create_directory", ec, &p); - if (::mkdir(p.c_str(), static_cast(perms::all)) == 0) + if (detail::mkdir(p.c_str(), static_cast(perms::all)) == 0) return true; if (errno != EEXIST) err.report(capture_errno()); @@ -1011,7 +1103,7 @@ return err.report(errc::not_a_directory, "the specified attribute path is invalid"); - if (::mkdir(p.c_str(), attr_stat.st_mode) == 0) + if (detail::mkdir(p.c_str(), attr_stat.st_mode) == 0) return true; if (errno != EEXIST) err.report(capture_errno()); @@ -1021,19 +1113,19 @@ void __create_directory_symlink(path const& from, path const& to, error_code* ec) { ErrorHandler err("create_directory_symlink", ec, &from, &to); - if (::symlink(from.c_str(), to.c_str()) != 0) + if (detail::symlink_dir(from.c_str(), to.c_str()) == -1) return err.report(capture_errno()); } void __create_hard_link(const path& from, const path& to, error_code* ec) { ErrorHandler err("create_hard_link", ec, &from, &to); - if (::link(from.c_str(), to.c_str()) == -1) + if (detail::link(from.c_str(), to.c_str()) == -1) return err.report(capture_errno()); } void __create_symlink(path const& from, path const& to, error_code* ec) { ErrorHandler err("create_symlink", ec, &from, &to); - if (::symlink(from.c_str(), to.c_str()) == -1) + if (detail::symlink_file(from.c_str(), to.c_str()) == -1) return err.report(capture_errno()); } @@ -1053,7 +1145,7 @@ void __current_path(const path& p, error_code* ec) { ErrorHandler err("current_path", ec, &p); - if (::chdir(p.c_str()) == -1) + if (detail::chdir(p.c_str()) == -1) err.report(capture_errno()); } @@ -1258,7 +1350,7 @@ bool __remove(const path& p, error_code* ec) { ErrorHandler err("remove", ec, &p); - if (::remove(p.c_str()) == -1) { + if (detail::remove(p.c_str()) == -1) { if (errno != ENOENT) err.report(capture_errno()); return false; @@ -1307,13 +1399,13 @@ void __rename(const path& from, const path& to, error_code* ec) { ErrorHandler err("rename", ec, &from, &to); - if (::rename(from.c_str(), to.c_str()) == -1) + if (detail::rename(from.c_str(), to.c_str()) == -1) err.report(capture_errno()); } void __resize_file(const path& p, uintmax_t size, error_code* ec) { ErrorHandler err("resize_file", ec, &p); - if (::truncate(p.c_str(), static_cast< ::off_t>(size)) == -1) + if (detail::truncate(p.c_str(), static_cast< ::off_t>(size)) == -1) return err.report(capture_errno()); }