Hi,
Tested on i686/x86_64-MinGW-W64 Please test possible regressions on posix platform. -- Regards, niXman ___________________________________________________ Dual-target(32 & 64-bit) MinGW-W64 compilers for 32 and 64-bit Windows: https://sf.net/p/mingw-w64/
Index: libstdc++-v3/src/filesystem/dir.cc =================================================================== --- libstdc++-v3/src/filesystem/dir.cc (revision 245367) +++ libstdc++-v3/src/filesystem/dir.cc (working copy) @@ -41,9 +41,10 @@ #endif #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS -# undef opendir -# define opendir _wopendir -#endif +# include "fs-win32.h" +#else +# include "fs-posix.h" +#endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS namespace fs = std::experimental::filesystem; @@ -51,7 +52,7 @@ { _Dir() : dirp(nullptr) { } - _Dir(DIR* dirp, const fs::path& path) : dirp(dirp), path(path) { } + _Dir(os_DIR_t* dirp, const fs::path& path) : dirp(dirp), path(path) { } _Dir(_Dir&& d) : dirp(std::exchange(d.dirp, nullptr)), path(std::move(d.path)), @@ -60,11 +61,11 @@ _Dir& operator=(_Dir&&) = delete; - ~_Dir() { if (dirp) ::closedir(dirp); } + ~_Dir() { if (dirp) ::os_closedir(dirp); } bool advance(std::error_code*, directory_options = directory_options::none); - DIR* dirp; + os_DIR_t* dirp; fs::path path; directory_entry entry; file_type type = file_type::none; @@ -87,7 +88,7 @@ if (ec) ec->clear(); - if (DIR* dirp = ::opendir(p.c_str())) + if (os_DIR_t* dirp = ::os_opendir(p.c_str())) return {dirp, p}; const int err = errno; @@ -105,7 +106,7 @@ } inline fs::file_type - get_file_type(const ::dirent& d __attribute__((__unused__))) + get_file_type(const ::os_dirent_t& d __attribute__((__unused__))) { #ifdef _GLIBCXX_HAVE_STRUCT_DIRENT_D_TYPE switch (d.d_type) @@ -145,13 +146,14 @@ ec->clear(); int err = std::exchange(errno, 0); - const auto entp = readdir(dirp); + const auto entp = ::os_readdir(dirp); std::swap(errno, err); if (entp) { // skip past dot and dot-dot - if (!strcmp(entp->d_name, ".") || !strcmp(entp->d_name, "..")) + if (!std::char_traits<path::value_type>::compare(entp->d_name, _WS("."), 1) || + !std::char_traits<path::value_type>::compare(entp->d_name, _WS(".."), 2)) return advance(ec, options); entry = fs::directory_entry{path / entp->d_name}; type = get_file_type(*entp); @@ -239,7 +241,7 @@ error_code* ec) : _M_options(options), _M_pending(true) { - if (DIR* dirp = ::opendir(p.c_str())) + if (os_DIR_t* dirp = ::os_opendir(p.c_str())) { auto sp = std::make_shared<_Dir_stack>(); sp->push(_Dir{ dirp, p }); Index: libstdc++-v3/src/filesystem/fs-posix.h =================================================================== --- libstdc++-v3/src/filesystem/fs-posix.h (nonexistent) +++ libstdc++-v3/src/filesystem/fs-posix.h (working copy) @@ -0,0 +1,49 @@ + +// Copyright (C) 2014-2017 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +#ifndef _GLIBCXX_EXPERIMENTAL_FS_POSIX_H +#define _GLIBCXX_EXPERIMENTAL_FS_POSIX_H 1 + +#define os_DIR_t DIR +#define os_dirent_t dirent +#define os_open open +#define os_opendir opendir +#define os_closedir closedir +#define os_readdir readdir_r +#define os_stat stat +#define os_stat_t stat +#define os_chmod chmod +#define os_mkdir mkdir +#define os_getcwd getcwd +#define os_chdir chdir +#define os_utimbuf_t utimbuf +#define os_utime utime +#define os_remove remove +#define os_rename rename +#define os_truncate truncate + +#define os_utime utime + +#define _WS(x) x + +#endif // _GLIBCXX_EXPERIMENTAL_FS_POSIX_H Index: libstdc++-v3/src/filesystem/fs-win32.h =================================================================== --- libstdc++-v3/src/filesystem/fs-win32.h (nonexistent) +++ libstdc++-v3/src/filesystem/fs-win32.h (working copy) @@ -0,0 +1,64 @@ + +// Copyright (C) 2014-2017 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +#ifndef _GLIBCXX_EXPERIMENTAL_FS_WIN32_H +#define _GLIBCXX_EXPERIMENTAL_FS_WIN32_H 1 + +#define os_DIR_t _WDIR +#define os_dirent_t _wdirent +#define os_open _wopen +#define os_opendir _wopendir +#define os_closedir _wclosedir +#define os_readdir _wreaddir +#define os_stat _wstat +#define os_stat_t _stat +#define os_chmod _wchmod +#define os_mkdir _wmkdir +#define os_getcwd _wgetcwd +#define os_chdir _wchdir +#define os_utimbuf_t _utimbuf +#define os_utime _wutime +#define os_remove _wremove +#define os_rename _wrename + +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> + +inline int _wtruncate(const wchar_t *fname, _off64_t size) { + int fd = ::os_open(fname, _O_BINARY|_O_RDWR); + if (fd == -1) return fd; + int ret = ::ftruncate64(fd, size), err=0; + _get_errno(&err); + _close(fd); + _set_errno(err); + return ret; +} + +#define os_truncate _wtruncate + +#define os_utime _wutime + +#define _WS(x) L##x + +#endif // _GLIBCXX_EXPERIMENTAL_FS_WIN32_H Index: libstdc++-v3/src/filesystem/ops.cc =================================================================== --- libstdc++-v3/src/filesystem/ops.cc (revision 245367) +++ libstdc++-v3/src/filesystem/ops.cc (working copy) @@ -56,11 +56,10 @@ #endif #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS -# undef utime -# define utime _wutime -# undef chmod -# define chmod _wchmod -#endif +# include "fs-win32.h" +#else +# include "fs-posix.h" +#endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS namespace fs = std::experimental::filesystem; @@ -88,11 +87,7 @@ namespace { -#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS - inline bool is_dot(wchar_t c) { return c == L'.'; } -#else - inline bool is_dot(char c) { return c == '.'; } -#endif + inline bool is_dot(fs::path::value_type c) { return c == _WS('.'); } inline bool is_dot(const fs::path& path) { @@ -111,7 +106,7 @@ void operator()(void* p) const { ::free(p); } }; - using char_ptr = std::unique_ptr<char[], free_as_in_malloc>; + using char_ptr = std::unique_ptr<fs::path::value_type[], free_as_in_malloc>; } fs::path @@ -250,7 +245,7 @@ #ifdef _GLIBCXX_HAVE_SYS_STAT_H namespace { - typedef struct ::stat stat_type; + typedef struct ::os_stat_t stat_type; inline fs::file_type make_file_type(const stat_type& st) noexcept @@ -267,10 +262,12 @@ return file_type::block; else if (S_ISFIFO(st.st_mode)) return file_type::fifo; +#ifndef _GLIBCXX_FILESYSTEM_IS_WINDOWS else if (S_ISLNK(st.st_mode)) return file_type::symlink; else if (S_ISSOCK(st.st_mode)) return file_type::socket; +#endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS #endif return file_type::unknown; @@ -323,7 +320,7 @@ if (to_st == nullptr) { - if (::stat(to.c_str(), &st1)) + if (::os_stat(to.c_str(), &st1)) { int err = errno; if (!is_not_found_errno(err)) @@ -345,7 +342,7 @@ if (from_st == nullptr) { - if (::stat(from.c_str(), &st2)) + if (::os_stat(from.c_str(), &st2)) { ec.assign(errno, std::generic_category()); return false; @@ -410,7 +407,7 @@ int fd; }; - CloseFD in = { ::open(from.c_str(), O_RDONLY) }; + CloseFD in = { ::os_open(from.c_str(), O_RDONLY) }; if (in.fd == -1) { ec.assign(errno, std::generic_category()); @@ -421,7 +418,7 @@ oflag |= O_TRUNC; else oflag |= O_EXCL; - CloseFD out = { ::open(to.c_str(), oflag, S_IWUSR) }; + CloseFD out = { ::os_open(to.c_str(), oflag, S_IWUSR) }; if (out.fd == -1) { if (errno == EEXIST && is_set(option, opts::skip_existing)) @@ -436,7 +433,7 @@ #elif defined _GLIBCXX_USE_FCHMODAT if (::fchmodat(AT_FDCWD, to.c_str(), from_st->st_mode, 0)) #else - if (::chmod(to.c_str(), from_st->st_mode)) + if (::os_chmod(to.c_str(), from_st->st_mode)) #endif { ec.assign(errno, std::generic_category()); @@ -502,16 +499,24 @@ stat_type from_st, to_st; // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2681. filesystem::copy() cannot copy symlinks +#ifndef _GLIBCXX_FILESYSTEM_IS_WINDOWS if (use_lstat || copy_symlinks ? ::lstat(from.c_str(), &from_st) : ::stat(from.c_str(), &from_st)) +#else + if (::os_stat(from.c_str(), &from_st)) +#endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS { ec.assign(errno, std::generic_category()); return; } +#ifndef _GLIBCXX_FILESYSTEM_IS_WINDOWS if (use_lstat ? ::lstat(to.c_str(), &to_st) : ::stat(to.c_str(), &to_st)) +#else + if (::os_stat(to.c_str(), &to_st)) +#endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS { if (!is_not_found_errno(errno)) { @@ -696,8 +701,12 @@ { bool created = false; #ifdef _GLIBCXX_HAVE_SYS_STAT_H +#ifndef _GLIBCXX_FILESYSTEM_IS_WINDOWS ::mode_t mode = static_cast<std::underlying_type_t<fs::perms>>(perm); - if (::mkdir(p.c_str(), mode)) + if (::os_mkdir(p.c_str(), mode)) +#else + if (::os_mkdir(p.c_str())) +#endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS { const int err = errno; if (err != EEXIST || !is_directory(p)) @@ -752,7 +761,7 @@ { #ifdef _GLIBCXX_HAVE_SYS_STAT_H stat_type st; - if (::stat(attributes.c_str(), &st)) + if (::os_stat(attributes.c_str(), &st)) { ec.assign(errno, std::generic_category()); return false; @@ -801,7 +810,7 @@ fs::create_hard_link(const path& to, const path& new_hard_link, error_code& ec) noexcept { -#ifdef _GLIBCXX_HAVE_UNISTD_H +#if !defined(_GLIBCXX_FILESYSTEM_IS_WINDOWS) && defined(_GLIBCXX_HAVE_UNISTD_H) if (::link(to.c_str(), new_hard_link.c_str())) ec.assign(errno, std::generic_category()); else @@ -825,7 +834,7 @@ fs::create_symlink(const path& to, const path& new_symlink, error_code& ec) noexcept { -#ifdef _GLIBCXX_HAVE_UNISTD_H +#if !defined(_GLIBCXX_FILESYSTEM_IS_WINDOWS) && defined(_GLIBCXX_HAVE_UNISTD_H) if (::symlink(to.c_str(), new_symlink.c_str())) ec.assign(errno, std::generic_category()); else @@ -851,8 +860,8 @@ { path p; #ifdef _GLIBCXX_HAVE_UNISTD_H -#ifdef __GLIBC__ - if (char_ptr cwd = char_ptr{::getcwd(nullptr, 0)}) +#if defined(__GLIBC__) || defined(_GLIBCXX_FILESYSTEM_IS_WINDOWS) + if (char_ptr cwd = char_ptr{::os_getcwd(nullptr, 0)}) { p.assign(cwd.get()); ec.clear(); @@ -910,7 +919,7 @@ fs::current_path(const path& p, error_code& ec) noexcept { #ifdef _GLIBCXX_HAVE_UNISTD_H - if (::chdir(p.c_str())) + if (::os_chdir(p.c_str())) ec.assign(errno, std::generic_category()); else ec.clear(); @@ -937,7 +946,7 @@ int err = 0; file_status s1, s2; stat_type st1, st2; - if (::stat(p1.c_str(), &st1) == 0) + if (::os_stat(p1.c_str(), &st1) == 0) s1 = make_file_status(st1); else if (is_not_found_errno(errno)) s1.type(file_type::not_found); @@ -944,7 +953,7 @@ else err = errno; - if (::stat(p2.c_str(), &st2) == 0) + if (::os_stat(p2.c_str(), &st2) == 0) s2 = make_file_status(st2); else if (is_not_found_errno(errno)) s2.type(file_type::not_found); @@ -994,7 +1003,7 @@ { #ifdef _GLIBCXX_HAVE_SYS_STAT_H stat_type st; - if (::stat(p.c_str(), &st)) + if (::os_stat(p.c_str(), &st)) { ec.assign(errno, std::generic_category()); return deflt; @@ -1044,8 +1053,14 @@ std::uintmax_t fs::hard_link_count(const path& p, error_code& ec) noexcept { +#ifndef _GLIBCXX_FILESYSTEM_IS_WINDOWS return do_stat(p, ec, std::mem_fn(&stat::st_nlink), static_cast<uintmax_t>(-1)); +#else + ec = std::make_error_code(std::errc::not_supported); + + return static_cast<uintmax_t>(-1); +#endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS } bool @@ -1120,11 +1135,11 @@ else ec.clear(); #elif _GLIBCXX_HAVE_UTIME_H - ::utimbuf times; + ::os_utimbuf_t times; times.modtime = s.count(); times.actime = do_stat(p, ec, [](const auto& st) { return st.st_atime; }, times.modtime); - if (::utime(p.c_str(), ×)) + if (::os_utime(p.c_str(), ×)) ec.assign(errno, std::generic_category()); else ec.clear(); @@ -1177,7 +1192,7 @@ #else if (nofollow && is_symlink(st)) ec = std::make_error_code(std::errc::operation_not_supported); - else if (::chmod(p.c_str(), static_cast<mode_t>(prms))) + else if (::os_chmod(p.c_str(), static_cast<mode_t>(prms))) err = errno; #endif @@ -1199,7 +1214,7 @@ fs::path fs::read_symlink(const path& p, error_code& ec) { -#ifdef _GLIBCXX_HAVE_SYS_STAT_H +#if !defined(_GLIBCXX_FILESYSTEM_IS_WINDOWS) && defined(_GLIBCXX_HAVE_SYS_STAT_H) stat_type st; if (::lstat(p.c_str(), &st)) { @@ -1237,7 +1252,7 @@ { if (exists(symlink_status(p, ec))) { - if (::remove(p.c_str()) == 0) + if (::os_remove(p.c_str()) == 0) { ec.clear(); return true; @@ -1284,7 +1299,7 @@ void fs::rename(const path& from, const path& to, error_code& ec) noexcept { - if (::rename(from.c_str(), to.c_str())) + if (::os_rename(from.c_str(), to.c_str())) ec.assign(errno, std::generic_category()); else ec.clear(); @@ -1305,7 +1320,7 @@ #ifdef _GLIBCXX_HAVE_UNISTD_H if (size > static_cast<uintmax_t>(std::numeric_limits<off_t>::max())) ec.assign(EINVAL, std::generic_category()); - else if (::truncate(p.c_str(), size)) + else if (::os_truncate(p.c_str(), size)) ec.assign(errno, std::generic_category()); else ec.clear(); @@ -1358,7 +1373,7 @@ { file_status status; stat_type st; - if (::stat(p.c_str(), &st)) + if (::os_stat(p.c_str(), &st)) { int err = errno; ec.assign(err, std::generic_category()); @@ -1376,11 +1391,13 @@ } return status; } +#endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS fs::file_status fs::symlink_status(const fs::path& p, std::error_code& ec) noexcept { file_status status; +#if !defined(_GLIBCXX_FILESYSTEM_IS_WINDOWS) && defined(_GLIBCXX_HAVE_SYS_STAT_H) stat_type st; if (::lstat(p.c_str(), &st)) { @@ -1394,9 +1411,11 @@ status = make_file_status(st); ec.clear(); } +#else + ec = std::make_error_code(std::errc::not_supported); +#endif return status; } -#endif fs::file_status fs::status(const fs::path& p) Index: libstdc++-v3/src/filesystem/path.cc =================================================================== --- libstdc++-v3/src/filesystem/path.cc (revision 245367) +++ libstdc++-v3/src/filesystem/path.cc (working copy) @@ -296,7 +296,7 @@ std::pair<const path::string_type*, std::size_t> path::_M_find_extension() const { - const std::string* s = nullptr; + const path::string_type* s = nullptr; if (_M_type != _Type::_Multi) s = &_M_pathname;