mirror of
https://git.mirrors.martin98.com/https://github.com/gulrak/filesystem
synced 2025-06-04 11:13:58 +08:00
Merge branch 'master' into cmake-alias-target
This commit is contained in:
commit
9f61ee0eb5
@ -1,5 +1,8 @@
|
||||
cmake_minimum_required(VERSION 3.7.2)
|
||||
project(ghcfilesystem)
|
||||
project(
|
||||
ghcfilesystem,
|
||||
VERSION 1.5.13
|
||||
)
|
||||
|
||||
if (POLICY CMP0077)
|
||||
cmake_policy(SET CMP0077 NEW)
|
||||
@ -15,7 +18,7 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
|
||||
else()
|
||||
option(GHC_FILESYSTEM_BUILD_EXAMPLES "Build examples" OFF)
|
||||
option(GHC_FILESYSTEM_BUILD_TESTING "Enable tests" OFF)
|
||||
option(GHC_FILESYSTEM_WITH_INSTALL "With install target" ON)
|
||||
option(GHC_FILESYSTEM_WITH_INSTALL "With install target" OFF)
|
||||
endif()
|
||||
option(GHC_FILESYSTEM_BUILD_STD_TESTING "Enable STD tests" ${GHC_FILESYSTEM_BUILD_TESTING})
|
||||
if(NOT DEFINED GHC_FILESYSTEM_TEST_COMPILE_FEATURES)
|
||||
@ -71,6 +74,15 @@ if(GHC_FILESYSTEM_WITH_INSTALL)
|
||||
"${PROJECT_BINARY_DIR}/cmake/ghc_filesystem-config.cmake"
|
||||
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ghc_filesystem"
|
||||
PATH_VARS CMAKE_INSTALL_INCLUDEDIR)
|
||||
install(FILES "${PROJECT_BINARY_DIR}/cmake/ghc_filesystem-config.cmake"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ghc_filesystem")
|
||||
write_basic_package_version_file(
|
||||
"${PROJECT_BINARY_DIR}/cmake/ghc_filesystem-config-version.cmake"
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY SameMinorVersion
|
||||
)
|
||||
install(
|
||||
FILES
|
||||
"${PROJECT_BINARY_DIR}/cmake/ghc_filesystem-config.cmake"
|
||||
"${PROJECT_BINARY_DIR}/cmake/ghc_filesystem-config-version.cmake"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ghc_filesystem"
|
||||
)
|
||||
endif()
|
||||
|
40
README.md
40
README.md
@ -43,8 +43,9 @@ macOS 10.12/10.14/10.15/11.6, Windows 10, Ubuntu 18.04, Ubuntu 20.04, CentOS 7,
|
||||
Alpine ARM/ARM64 Linux and Solaris 10 but should work on other systems too, as long as you have
|
||||
at least a C++11 compatible compiler. It should work with Android NDK, Emscripten and I even
|
||||
had reports of it being used on iOS (within sandboxing constraints) and with v1.5.6 there
|
||||
is experimental support for QNX. The support of Android NDK, Emscripten and QNX is not
|
||||
backed up by automated testing but PRs and bug reports are welcome for those too.
|
||||
is experimental support for QNX. The support of Android NDK, Emscripten, QNX, GNU/Hurd and Haiku is not
|
||||
backed up by automated testing but PRs and bug reports are welcome for those too and they are reported
|
||||
to work.
|
||||
It is of course in its own namespace `ghc::filesystem` to not interfere with a regular `std::filesystem`
|
||||
should you use it in a mixed C++17 environment (which is possible).
|
||||
|
||||
@ -584,6 +585,41 @@ to the expected behavior.
|
||||
|
||||
## Release Notes
|
||||
|
||||
### v1.5.13 (wip)
|
||||
|
||||
* Pull request [#163](https://github.com/gulrak/filesystem/pull/163), build
|
||||
support for Haiku (also fixes [#159](https://github.com/gulrak/filesystem/issues/159))
|
||||
* Pull request [#162](https://github.com/gulrak/filesystem/pull/162), fix for
|
||||
directory iterator treating all files subsequent to a symlink as symlink
|
||||
on Windows
|
||||
* Fix for [#160](https://github.com/gulrak/filesystem/issues/160), the cmake
|
||||
config now only sets install targets by default if the project is no
|
||||
subproject, as documented
|
||||
* Fix for [#157](https://github.com/gulrak/filesystem/issues/157), suppress
|
||||
C4191 warning on MSVC for GetProcAddress casts
|
||||
* Fix for [#156](https://github.com/gulrak/filesystem/issues/156), on POSIX
|
||||
`stem()`, `filename()` and `extension()` of `fs::path` would return wrong
|
||||
result if a colon was in the filename
|
||||
* Pull request [#154](https://github.com/gulrak/filesystem/pull/145), build
|
||||
support for GNU/Hurd
|
||||
* Pull request [#153](https://github.com/gulrak/filesystem/pull/153), fixed
|
||||
`fs::last_write_time(path, time, ec)` setter on iOS, tvOS and watchOS
|
||||
* Fix for [#151](https://github.com/gulrak/filesystem/issues/156),
|
||||
`fs::directory_entry::refresh()` now, consistently with `status()` will not
|
||||
throw on symlinks to non-existing targets, but make the entry have
|
||||
`file_type::not_found` as the type
|
||||
* Pull request [#149](https://github.com/gulrak/filesystem/pull/149), add
|
||||
version to CMake project and export it
|
||||
* Fix for [#146](https://github.com/gulrak/filesystem/issues/146), handle `EINTR`
|
||||
on POSIX directory iteration and file copy to avoid errors on network
|
||||
filesystems
|
||||
* Pull request [#145](https://github.com/gulrak/filesystem/pull/145), fix for
|
||||
Y2038 bug in timeToFILETIME on Windows
|
||||
* Pull request [#144](https://github.com/gulrak/filesystem/pull/144), `fs::copy_file()`
|
||||
now also copies the permissions
|
||||
* Pull request [#143](https://github.com/gulrak/filesystem/pull/143), fix
|
||||
for `fs::copy_file()` ignoring the `skip_existing` option.
|
||||
|
||||
### [v1.5.12](https://github.com/gulrak/filesystem/releases/tag/v1.5.12)
|
||||
|
||||
* Fix for [#142](https://github.com/gulrak/filesystem/issues/142), removed need
|
||||
|
@ -22,6 +22,9 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND (CMAKE_CXX_COMPILER_VERSION V
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)")
|
||||
target_link_libraries(filesystem_test xnet)
|
||||
endif()
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
|
||||
target_link_libraries(filesystem_test network)
|
||||
endif()
|
||||
target_compile_definitions(${targetName} PRIVATE USE_STD_FS)
|
||||
endif()
|
||||
|
||||
@ -34,6 +37,9 @@ if (CMAKE_COMPILER_IS_GNUCXX AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 8.0 O
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)")
|
||||
target_link_libraries(${targetName} xnet)
|
||||
endif()
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
|
||||
target_link_libraries(${targetName} network)
|
||||
endif()
|
||||
target_compile_options(${targetName} PRIVATE $<$<BOOL:${CYGWIN}>:-Wa,-mbig-obj>)
|
||||
target_compile_definitions(${targetName} PRIVATE USE_STD_FS)
|
||||
endif()
|
||||
@ -55,6 +61,9 @@ macro(AddTestExecutableWithStdCpp cppStd)
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)")
|
||||
target_link_libraries(filesystem_test_cpp${cppStd} xnet)
|
||||
endif()
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
|
||||
target_link_libraries(filesystem_test_cpp${cppStd} network)
|
||||
endif()
|
||||
target_compile_options(filesystem_test_cpp${cppStd} PRIVATE
|
||||
$<$<BOOL:${EMSCRIPTEN}>:-s DISABLE_EXCEPTION_CATCHING=0>
|
||||
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Werror -Wno-error=deprecated-declarations>
|
||||
|
@ -78,6 +78,8 @@
|
||||
#include <wasi/api.h>
|
||||
#elif defined(__QNX__)
|
||||
#define GHC_OS_QNX
|
||||
#elif defined(__HAIKU__)
|
||||
#define GHC_OS_HAIKU
|
||||
#else
|
||||
#error "Operating system currently not supported!"
|
||||
#endif
|
||||
@ -306,7 +308,7 @@
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
// ghc::filesystem version in decimal (major * 10000 + minor * 100 + patch)
|
||||
#define GHC_FILESYSTEM_VERSION 10512L
|
||||
#define GHC_FILESYSTEM_VERSION 10513L
|
||||
|
||||
#if !defined(GHC_WITH_EXCEPTIONS) && (defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND))
|
||||
#define GHC_WITH_EXCEPTIONS
|
||||
@ -1955,10 +1957,15 @@ GHC_INLINE void create_symlink(const path& target_name, const path& new_symlink,
|
||||
#if defined(__GNUC__) && __GNUC__ >= 8
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
||||
#elif defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__clang__)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4191)
|
||||
#endif
|
||||
static CreateSymbolicLinkW_fp api_call = reinterpret_cast<CreateSymbolicLinkW_fp>(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "CreateSymbolicLinkW"));
|
||||
#if defined(__GNUC__) && __GNUC__ >= 8
|
||||
#pragma GCC diagnostic pop
|
||||
#elif defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__clang__)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
if (api_call) {
|
||||
if (api_call(GHC_NATIVEWP(new_symlink), GHC_NATIVEWP(target_name), to_directory ? 1 : 0) == 0) {
|
||||
@ -1979,10 +1986,15 @@ GHC_INLINE void create_hardlink(const path& target_name, const path& new_hardlin
|
||||
#if defined(__GNUC__) && __GNUC__ >= 8
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
||||
#elif defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__clang__)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4191)
|
||||
#endif
|
||||
static CreateHardLinkW_fp api_call = reinterpret_cast<CreateHardLinkW_fp>(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW"));
|
||||
#if defined(__GNUC__) && __GNUC__ >= 8
|
||||
#pragma GCC diagnostic pop
|
||||
#elif defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__clang__)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
if (api_call) {
|
||||
if (api_call(GHC_NATIVEWP(new_hardlink), GHC_NATIVEWP(target_name), NULL) == 0) {
|
||||
@ -2260,41 +2272,43 @@ GHC_INLINE uintmax_t hard_links_from_INFO<BY_HANDLE_FILE_INFORMATION>(const BY_H
|
||||
}
|
||||
|
||||
template <typename INFO>
|
||||
GHC_INLINE DWORD reparse_tag_from_INFO(const INFO*)
|
||||
GHC_INLINE bool is_symlink_from_INFO(const path &p, const INFO* info, std::error_code& ec)
|
||||
{
|
||||
return 0;
|
||||
if ((info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
|
||||
auto reparseData = detail::getReparseData(p, ec);
|
||||
if (!ec && reparseData && IsReparseTagMicrosoft(reparseData->ReparseTag) && reparseData->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <>
|
||||
GHC_INLINE DWORD reparse_tag_from_INFO(const WIN32_FIND_DATAW* info)
|
||||
GHC_INLINE bool is_symlink_from_INFO(const path &, const WIN32_FIND_DATAW* info, std::error_code&)
|
||||
{
|
||||
return info->dwReserved0;
|
||||
// dwReserved0 is undefined unless dwFileAttributes includes the
|
||||
// FILE_ATTRIBUTE_REPARSE_POINT attribute according to microsoft
|
||||
// documentation. In practice, dwReserved0 is not reset which
|
||||
// causes it to report the incorrect symlink status.
|
||||
// Note that microsoft documentation does not say whether there is
|
||||
// a null value for dwReserved0, so we test for symlink directly
|
||||
// instead of returning the tag which requires returning a null
|
||||
// value for non-reparse-point files.
|
||||
return (info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) && info->dwReserved0 == IO_REPARSE_TAG_SYMLINK;
|
||||
}
|
||||
|
||||
template <typename INFO>
|
||||
GHC_INLINE file_status status_from_INFO(const path& p, const INFO* info, std::error_code& ec, uintmax_t* sz = nullptr, time_t* lwt = nullptr)
|
||||
{
|
||||
file_type ft = file_type::unknown;
|
||||
if (sizeof(INFO) == sizeof(WIN32_FIND_DATAW)) {
|
||||
if (detail::reparse_tag_from_INFO(info) == IO_REPARSE_TAG_SYMLINK) {
|
||||
ft = file_type::symlink;
|
||||
}
|
||||
if (is_symlink_from_INFO(p, info, ec)) {
|
||||
ft = file_type::symlink;
|
||||
}
|
||||
else if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
ft = file_type::directory;
|
||||
}
|
||||
else {
|
||||
if ((info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
|
||||
auto reparseData = detail::getReparseData(p, ec);
|
||||
if (!ec && reparseData && IsReparseTagMicrosoft(reparseData->ReparseTag) && reparseData->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
|
||||
ft = file_type::symlink;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ft == file_type::unknown) {
|
||||
if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
ft = file_type::directory;
|
||||
}
|
||||
else {
|
||||
ft = file_type::regular;
|
||||
}
|
||||
ft = file_type::regular;
|
||||
}
|
||||
perms prms = perms::owner_read | perms::group_read | perms::others_read;
|
||||
if (!(info->dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
|
||||
@ -3365,10 +3379,14 @@ GHC_INLINE path::impl_string_type::const_iterator path::iterator::increment(cons
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifdef GHC_OS_WINDOWS
|
||||
if (fromStart && i != _last && *i == ':') {
|
||||
++i;
|
||||
}
|
||||
else {
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
i = std::find(i, _last, preferred_separator);
|
||||
}
|
||||
}
|
||||
@ -3912,11 +3930,14 @@ GHC_INLINE bool copy_file(const path& from, const path& to, copy_options options
|
||||
ec = tecf;
|
||||
return false;
|
||||
}
|
||||
if (exists(st) && (!is_regular_file(st) || equivalent(from, to, ec) || (options & (copy_options::skip_existing | copy_options::overwrite_existing | copy_options::update_existing)) == copy_options::none)) {
|
||||
ec = tect ? tect : detail::make_error_code(detail::portable_error::exists);
|
||||
return false;
|
||||
}
|
||||
if (exists(st)) {
|
||||
if ((options & copy_options::skip_existing) == copy_options::skip_existing) {
|
||||
return false;
|
||||
}
|
||||
if (!is_regular_file(st) || equivalent(from, to, ec) || (options & (copy_options::overwrite_existing | copy_options::update_existing)) == copy_options::none) {
|
||||
ec = tect ? tect : detail::make_error_code(detail::portable_error::exists);
|
||||
return false;
|
||||
}
|
||||
if ((options & copy_options::update_existing) == copy_options::update_existing) {
|
||||
auto from_time = last_write_time(from, ec);
|
||||
if (ec) {
|
||||
@ -3956,15 +3977,33 @@ GHC_INLINE bool copy_file(const path& from, const path& to, copy_options options
|
||||
::close(in);
|
||||
return false;
|
||||
}
|
||||
if (st.permissions() != sf.permissions()) {
|
||||
if (::fchmod(out, static_cast<mode_t>(sf.permissions() & perms::all)) != 0) {
|
||||
ec = detail::make_system_error();
|
||||
::close(in);
|
||||
::close(out);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ssize_t br, bw;
|
||||
while ((br = ::read(in, buffer.data(), buffer.size())) > 0) {
|
||||
while (true) {
|
||||
do { br = ::read(in, buffer.data(), buffer.size()); } while(errno == EINTR);
|
||||
if(!br) {
|
||||
break;
|
||||
}
|
||||
if(br < 0) {
|
||||
ec = detail::make_system_error();
|
||||
::close(in);
|
||||
::close(out);
|
||||
return false;
|
||||
}
|
||||
ssize_t offset = 0;
|
||||
do {
|
||||
if ((bw = ::write(out, buffer.data() + offset, static_cast<size_t>(br))) > 0) {
|
||||
br -= bw;
|
||||
offset += bw;
|
||||
}
|
||||
else if (bw < 0) {
|
||||
else if (bw < 0 && errno != EINTR) {
|
||||
ec = detail::make_system_error();
|
||||
::close(in);
|
||||
::close(out);
|
||||
@ -4199,6 +4238,13 @@ GHC_INLINE path current_path(std::error_code& ec)
|
||||
return path();
|
||||
}
|
||||
return path(std::wstring(buffer.get()), path::native_format);
|
||||
#elif defined(__GLIBC__)
|
||||
std::unique_ptr<char, decltype(&std::free)> buffer { ::getcwd(NULL, 0), std::free };
|
||||
if (buffer == nullptr) {
|
||||
ec = detail::make_system_error();
|
||||
return path();
|
||||
}
|
||||
return path(buffer.get());
|
||||
#else
|
||||
size_t pathlen = static_cast<size_t>(std::max(int(::pathconf(".", _PC_PATH_MAX)), int(PATH_MAX)));
|
||||
std::unique_ptr<char[]> buffer(new char[pathlen + 1]);
|
||||
@ -4604,9 +4650,9 @@ GHC_INLINE void last_write_time(const path& p, file_time_type new_time, std::err
|
||||
if (!::SetFileTime(file.get(), 0, 0, &ft)) {
|
||||
ec = detail::make_system_error();
|
||||
}
|
||||
#elif defined(GHC_OS_MACOS)
|
||||
#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
|
||||
#if __MAC_OS_X_VERSION_MIN_REQUIRED < 101300
|
||||
#elif defined(GHC_OS_MACOS) && \
|
||||
(__MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_13) || (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_11_0) || \
|
||||
(__TV_OS_VERSION_MIN_REQUIRED < __TVOS_11_0) || (__WATCH_OS_VERSION_MIN_REQUIRED < __WATCHOS_4_0)
|
||||
struct ::stat fs;
|
||||
if (::stat(p.c_str(), &fs) == 0) {
|
||||
struct ::timeval tv[2];
|
||||
@ -4620,18 +4666,6 @@ GHC_INLINE void last_write_time(const path& p, file_time_type new_time, std::err
|
||||
}
|
||||
ec = detail::make_system_error();
|
||||
return;
|
||||
#else
|
||||
struct ::timespec times[2];
|
||||
times[0].tv_sec = 0;
|
||||
times[0].tv_nsec = UTIME_OMIT;
|
||||
times[1].tv_sec = std::chrono::duration_cast<std::chrono::seconds>(d).count();
|
||||
times[1].tv_nsec = 0; // std::chrono::duration_cast<std::chrono::nanoseconds>(d).count() % 1000000000;
|
||||
if (::utimensat(AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) {
|
||||
ec = detail::make_system_error();
|
||||
}
|
||||
return;
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#ifndef UTIME_OMIT
|
||||
#define UTIME_OMIT ((1l << 30) - 2l)
|
||||
@ -5259,7 +5293,7 @@ GHC_INLINE void directory_entry::refresh()
|
||||
{
|
||||
std::error_code ec;
|
||||
refresh(ec);
|
||||
if (ec) {
|
||||
if (ec && (_status.type() == file_type::none || _symlink_status.type() != file_type::symlink)) {
|
||||
throw filesystem_error(detail::systemErrorText(ec.value()), _path, ec);
|
||||
}
|
||||
}
|
||||
@ -5670,7 +5704,7 @@ public:
|
||||
, _entry(nullptr)
|
||||
{
|
||||
if (!path.empty()) {
|
||||
_dir = ::opendir(path.native().c_str());
|
||||
do { _dir = ::opendir(path.native().c_str()); } while(errno == EINTR);
|
||||
if (!_dir) {
|
||||
auto error = errno;
|
||||
_base = filesystem::path();
|
||||
@ -5697,7 +5731,7 @@ public:
|
||||
do {
|
||||
skip = false;
|
||||
errno = 0;
|
||||
_entry = ::readdir(_dir);
|
||||
do { _entry = ::readdir(_dir); } while(errno == EINTR);
|
||||
if (_entry) {
|
||||
_dir_entry._path = _base;
|
||||
_dir_entry._path.append_name(_entry->d_name);
|
||||
@ -5711,7 +5745,7 @@ public:
|
||||
::closedir(_dir);
|
||||
_dir = nullptr;
|
||||
_dir_entry._path.clear();
|
||||
if (errno) {
|
||||
if (errno && errno != EINTR) {
|
||||
ec = detail::make_system_error();
|
||||
}
|
||||
break;
|
||||
|
@ -25,6 +25,9 @@ if(GHC_COVERAGE)
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)")
|
||||
target_link_libraries(filesystem_test PUBLIC xnet)
|
||||
endif()
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
|
||||
target_link_libraries(filesystem_test PUBLIC network)
|
||||
endif()
|
||||
if("cxx_std_17" IN_LIST GHC_FILESYSTEM_TEST_COMPILE_FEATURES)
|
||||
AddTestExecutableWithStdCpp(17 filesystem_test.cpp catch.hpp)
|
||||
endif()
|
||||
@ -38,6 +41,9 @@ else()
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)")
|
||||
target_link_libraries(filesystem_test xnet)
|
||||
endif()
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
|
||||
target_link_libraries(filesystem_test network)
|
||||
endif()
|
||||
SetTestCompileOptions(filesystem_test)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
target_compile_definitions(filesystem_test PRIVATE _CRT_SECURE_NO_WARNINGS WIN32_LEAN_AND_MEAN NOMINMAX)
|
||||
@ -77,6 +83,9 @@ target_link_libraries(fwd_impl_test ghc_filesystem)
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)")
|
||||
target_link_libraries(fwd_impl_test xnet)
|
||||
endif()
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
|
||||
target_link_libraries(fwd_impl_test network)
|
||||
endif()
|
||||
SetTestCompileOptions(fwd_impl_test)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
target_compile_definitions(fwd_impl_test PRIVATE _CRT_SECURE_NO_WARNINGS WIN32_LEAN_AND_MEAN NOMINMAX)
|
||||
|
@ -99,7 +99,7 @@ using fstream = ghc::filesystem::fstream;
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
template <typename TP>
|
||||
std::time_t to_time_t(TP tp)
|
||||
static std::time_t to_time_t(TP tp)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
auto sctp = time_point_cast<system_clock::duration>(tp - TP::clock::now() + system_clock::now());
|
||||
@ -107,7 +107,7 @@ std::time_t to_time_t(TP tp)
|
||||
}
|
||||
|
||||
template <typename TP>
|
||||
TP from_time_t(std::time_t t)
|
||||
static TP from_time_t(std::time_t t)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
auto sctp = system_clock::from_time_t(t);
|
||||
@ -214,7 +214,8 @@ static void generateFile(const fs::path& pathname, int withSize = -1)
|
||||
}
|
||||
|
||||
#ifdef GHC_OS_WINDOWS
|
||||
inline bool isWow64Proc()
|
||||
#if !defined(_WIN64) && defined(KEY_WOW64_64KEY)
|
||||
static bool isWow64Proc()
|
||||
{
|
||||
typedef BOOL(WINAPI * IsWow64Process_t)(HANDLE, PBOOL);
|
||||
BOOL bIsWow64 = FALSE;
|
||||
@ -226,6 +227,7 @@ inline bool isWow64Proc()
|
||||
}
|
||||
return bIsWow64 == TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool is_symlink_creation_supported()
|
||||
{
|
||||
@ -303,13 +305,13 @@ public:
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
bool operator==(TestAllocator<T> const&, TestAllocator<U> const&) noexcept
|
||||
static bool operator==(TestAllocator<T> const&, TestAllocator<U> const&) noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool operator!=(TestAllocator<T> const& x, TestAllocator<U> const& y) noexcept
|
||||
static bool operator!=(TestAllocator<T> const& x, TestAllocator<U> const& y) noexcept
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
@ -790,6 +792,9 @@ TEST_CASE("fs.path.decompose - path decomposition", "[filesystem][path][fs.path.
|
||||
CHECK(fs::path("C:/foo").filename() == "foo");
|
||||
CHECK(fs::path("C:\\foo").filename() == "foo");
|
||||
CHECK(fs::path("C:foo").filename() == "foo");
|
||||
CHECK(fs::path("t:est.txt").filename() == "est.txt");
|
||||
#else
|
||||
CHECK(fs::path("t:est.txt").filename() == "t:est.txt");
|
||||
#endif
|
||||
|
||||
// stem()
|
||||
@ -807,6 +812,11 @@ TEST_CASE("fs.path.decompose - path decomposition", "[filesystem][path][fs.path.
|
||||
CHECK(fs::path("/foo/.profile").stem() == ".profile");
|
||||
CHECK(fs::path(".bar").stem() == ".bar");
|
||||
CHECK(fs::path("..bar").stem() == ".");
|
||||
#ifdef GHC_OS_WINDOWS
|
||||
CHECK(fs::path("t:est.txt").stem() == "est");
|
||||
#else
|
||||
CHECK(fs::path("t:est.txt").stem() == "t:est");
|
||||
#endif
|
||||
|
||||
// extension()
|
||||
CHECK(fs::path("/foo/bar.txt").extension() == ".txt");
|
||||
@ -814,6 +824,7 @@ TEST_CASE("fs.path.decompose - path decomposition", "[filesystem][path][fs.path.
|
||||
CHECK(fs::path("/foo/.profile").extension() == "");
|
||||
CHECK(fs::path(".bar").extension() == "");
|
||||
CHECK(fs::path("..bar").extension() == ".bar");
|
||||
CHECK(fs::path("t:est.txt").extension() == ".txt");
|
||||
|
||||
if (has_host_root_name_support()) {
|
||||
// //host-based root-names
|
||||
@ -1199,7 +1210,7 @@ TEST_CASE("fs.class.filesystem_error - class filesystem_error", "[filesystem][fi
|
||||
CHECK(fse.path2() == "some/other");
|
||||
}
|
||||
|
||||
constexpr fs::perms constExprOwnerAll()
|
||||
static constexpr fs::perms constExprOwnerAll()
|
||||
{
|
||||
return fs::perms::owner_read | fs::perms::owner_write | fs::perms::owner_exec;
|
||||
}
|
||||
@ -1377,6 +1388,16 @@ TEST_CASE("fs.dir.entry - class directory_entry", "[filesystem][directory_entry]
|
||||
CHECK(!(d2 != d2));
|
||||
CHECK(d1 == d1);
|
||||
CHECK(!(d1 == d2));
|
||||
if(is_symlink_creation_supported()) {
|
||||
fs::create_symlink(t.path() / "nonexistent", t.path() / "broken");
|
||||
for (auto d3 : fs::directory_iterator(t.path())) {
|
||||
CHECK_NOTHROW(d3.symlink_status());
|
||||
CHECK_NOTHROW(d3.status());
|
||||
CHECK_NOTHROW(d3.refresh());
|
||||
}
|
||||
fs::directory_entry entry(t.path() / "broken");
|
||||
CHECK_NOTHROW(entry.refresh());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("fs.class.directory_iterator - class directory_iterator", "[filesystem][directory_iterator][fs.class.directory_iterator]")
|
||||
@ -1778,6 +1799,19 @@ TEST_CASE("fs.op.copy_file - copy_file", "[filesystem][operations][fs.op.copy_fi
|
||||
CHECK_NOTHROW(fs::copy_file("foobar", "foobar2", ec));
|
||||
CHECK(ec);
|
||||
CHECK(!fs::exists("foobar"));
|
||||
fs::path file1("temp1.txt");
|
||||
fs::path file2("temp2.txt");
|
||||
generateFile(file1, 200);
|
||||
generateFile(file2, 200);
|
||||
auto allWrite = fs::perms::owner_write | fs::perms::group_write | fs::perms::others_write;
|
||||
CHECK_NOTHROW(fs::permissions(file1, allWrite, fs::perm_options::remove));
|
||||
CHECK((fs::status(file1).permissions() & fs::perms::owner_write) != fs::perms::owner_write);
|
||||
CHECK_NOTHROW(fs::permissions(file2, allWrite, fs::perm_options::add));
|
||||
CHECK((fs::status(file2).permissions() & fs::perms::owner_write) == fs::perms::owner_write);
|
||||
fs::copy_file(file1, file2, fs::copy_options::overwrite_existing);
|
||||
CHECK((fs::status(file2).permissions() & fs::perms::owner_write) != fs::perms::owner_write);
|
||||
CHECK_NOTHROW(fs::permissions(file1, allWrite, fs::perm_options::add));
|
||||
CHECK_NOTHROW(fs::permissions(file2, allWrite, fs::perm_options::add));
|
||||
}
|
||||
|
||||
TEST_CASE("fs.op.copy_symlink - copy_symlink", "[filesystem][operations][fs.op.copy_symlink]")
|
||||
|
Loading…
x
Reference in New Issue
Block a user