Compare commits

..

No commits in common. "master" and "v1.5.10" have entirely different histories.

16 changed files with 2337 additions and 6659 deletions

View File

@ -1,6 +1,6 @@
freebsd_task:
freebsd_instance:
image_family: freebsd-14-0
image_family: freebsd-12-1
install_script: |
pkg install -y cmake
pw groupadd testgrp
@ -11,24 +11,25 @@ freebsd_task:
test_script: |
sudo -u testuser .ci/unix-test.sh
rockylinux8_task:
centos7_task:
container:
image: docker.io/rockylinux:8
image: centos:7
install_script: |
dnf group install -y "Development Tools"
dnf install cmake -y
yum install -y centos-release-scl
yum install -y devtoolset-9
curl -L https://github.com/Kitware/CMake/releases/download/v3.16.4/cmake-3.16.4-Linux-x86_64.tar.gz | tar xzvf - -C /usr/local --strip-components 1
build_script: |
.ci/unix-build.sh
source /opt/rh/devtoolset-9/enable && PATH=$PATH:/usr/local/bin .ci/unix-build.sh
test_script: |
.ci/unix-test.sh
PATH=$PATH:/usr/local/bin .ci/unix-test.sh
rockylinux9_task:
centos8_task:
container:
image: docker.io/rockylinux:9
image: centos:8
install_script: |
dnf group install -y "Development Tools"
dnf install cmake -y
yum group install -y "Development Tools"
curl -L https://github.com/Kitware/CMake/releases/download/v3.16.4/cmake-3.16.4-Linux-x86_64.tar.gz | tar xzvf - -C /usr/local --strip-components 1
build_script: |
.ci/unix-build.sh
PATH=$PATH:/usr/local/bin .ci/unix-build.sh
test_script: |
.ci/unix-test.sh
PATH=$PATH:/usr/local/bin .ci/unix-test.sh

View File

@ -10,42 +10,6 @@ jobs:
fail-fast: false
matrix:
config:
- name: "Ubuntu 22.04 GCC 11"
os: ubuntu-22.04
build_type: Release
packages: ninja-build
generator: Ninja
compatibility: "cxx_std_11;cxx_std_17;cxx_std_20"
cc: gcc
cxx: g++
- name: "Ubuntu 22.04 Clang 13.0"
os: ubuntu-22.04
build_type: Release
packages: ninja-build libc++-13-dev libc++abi-13-dev
generator: Ninja
compatibility: "cxx_std_11;cxx_std_17;cxx_std_20"
cc: clang-13
cxx: clang++-13
- name: "Ubuntu 22.04 Clang 15.0"
os: ubuntu-22.04
build_type: Release
packages: ninja-build libc++-15-dev libc++abi-15-dev
generator: Ninja
compatibility: "cxx_std_11;cxx_std_17;cxx_std_20"
cc: clang-15
cxx: clang++-15
- name: "Ubuntu 22.04 GCC 11 coverage"
os: ubuntu-22.04
build_type: Debug
packages: ninja-build lcov
generator: Ninja
compatibility: "cxx_std_11;cxx_std_17;cxx_std_20"
cc: gcc
cxx: g++
- name: "Ubuntu 20.04 GCC 9.3"
os: ubuntu-20.04
build_type: Release
@ -82,8 +46,71 @@ jobs:
cc: gcc
cxx: g++
- name: "Ubuntu 18.04 GCC 8.4"
os: ubuntu-18.04
build_type: Release
packages: ninja-build gcc-8 g++-8
generator: Ninja
compatibility: "cxx_std_11;cxx_std_17"
cc: gcc-8
cxx: g++-8
- name: "Ubuntu 18.04 GCC 7.5"
os: ubuntu-18.04
build_type: Release
packages: ninja-build
generator: Ninja
compatibility: "cxx_std_11;cxx_std_17"
cc: gcc-7
cxx: g++-7
- name: "Ubuntu 18.04 GCC 6.5"
os: ubuntu-18.04
build_type: Release
packages: ninja-build gcc-6 g++-6
generator: Ninja
compatibility: "cxx_std_11;cxx_std_17"
cc: gcc-6
cxx: g++-6
- name: "Ubuntu 18.04 GCC 5.5"
os: ubuntu-18.04
build_type: Release
packages: ninja-build gcc-5 g++-5
generator: Ninja
compatibility: "cxx_std_11;cxx_std_17"
cc: gcc-5
cxx: g++-5
- name: "Ubuntu 18.04 Clang 9.0"
os: ubuntu-18.04
build_type: Release
packages: ninja-build libc++-9-dev libc++abi-9-dev
generator: Ninja
compatibility: "cxx_std_11;cxx_std_17;cxx_std_20"
cc: clang
cxx: clang++
- name: "Ubuntu 18.04 Clang 6.0"
os: ubuntu-18.04
build_type: Release
packages: ninja-build clang-6.0
generator: Ninja
compatibility: "cxx_std_11;cxx_std_17"
cc: clang-6.0
cxx: clang++-6.0
- name: "Ubuntu 18.04 Clang 5.0"
os: ubuntu-18.04
build_type: Release
packages: ninja-build clang-5.0
generator: Ninja
compatibility: "cxx_std_11;cxx_std_17"
cc: clang-5.0
cxx: clang++-5.0
- name: "Windows MSVC 2019"
os: windows-2019
os: windows-latest
build_type: Release
packages: ninja
generator: "Visual Studio 16 2019"
@ -91,12 +118,12 @@ jobs:
cc: cl
cxx: cl
- name: "macOS 13 AppleClang"
os: macos-13
- name: "macOS 10.15 AppleClang"
os: macos-10.15
build_type: Release
packages: ninja
generator: Ninja
compatibility: "cxx_std_11;cxx_std_17;cxx_std_20"
compatibility: "cxx_std_11;cxx_std_17"
cc: clang
cxx: clang++

View File

@ -1,8 +1,5 @@
cmake_minimum_required(VERSION 3.7.2)
project(
ghcfilesystem,
VERSION 1.5.15
)
project(ghcfilesystem)
if (POLICY CMP0077)
cmake_policy(SET CMP0077 NEW)
@ -18,7 +15,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" OFF)
option(GHC_FILESYSTEM_WITH_INSTALL "With install target" ON)
endif()
option(GHC_FILESYSTEM_BUILD_STD_TESTING "Enable STD tests" ${GHC_FILESYSTEM_BUILD_TESTING})
if(NOT DEFINED GHC_FILESYSTEM_TEST_COMPILE_FEATURES)
@ -35,14 +32,9 @@ endif()
if(CMAKE_CXX_STANDARD LESS 11)
message(FATAL_ERROR "CMAKE_CXX_STANDARD is less than 11, ghc::filesystem only works with C++11 and above.")
endif()
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
message(STATUS "System name: ${CMAKE_SYSTEM_NAME}")
message(STATUS "Compiler ID: ${CMAKE_CXX_COMPILER_ID}")
message(STATUS "CMAKE_CXX_COMPILE_FEATURES: ${CMAKE_CXX_COMPILE_FEATURES}")
endif()
add_library(ghc_filesystem INTERFACE)
add_library(ghcFilesystem::ghc_filesystem ALIAS ghc_filesystem)
target_include_directories(ghc_filesystem INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
@ -76,15 +68,7 @@ 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)
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"
)
install(FILES "${PROJECT_BINARY_DIR}/cmake/ghc_filesystem-config.cmake"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ghc_filesystem")
add_library(ghcFilesystem::ghc_filesystem ALIAS ghc_filesystem)
endif()

299
README.md
View File

@ -3,52 +3,48 @@
[![CMake Build Matrix](https://github.com/gulrak/filesystem/actions/workflows/build_cmake.yml/badge.svg?branch=master)](https://github.com/gulrak/filesystem/actions/workflows/build_cmake.yml)
[![Build Status](https://ci.appveyor.com/api/projects/status/t07wp3k2cddo0hpo/branch/master?svg=true)](https://ci.appveyor.com/project/gulrak/filesystem)
[![Build Status](https://api.cirrus-ci.com/github/gulrak/filesystem.svg?branch=master)](https://cirrus-ci.com/github/gulrak/filesystem)
[![Build Status](https://cloud.drone.io/api/badges/gulrak/filesystem/status.svg?ref=refs/heads/master)](https://cloud.drone.io/gulrak/filesystem)
[![Coverage Status](https://coveralls.io/repos/github/gulrak/filesystem/badge.svg?branch=master)](https://coveralls.io/github/gulrak/filesystem?branch=master)
[![Latest Release Tag](https://img.shields.io/github/tag/gulrak/filesystem.svg)](https://github.com/gulrak/filesystem/tree/v1.5.14)
<!-- [![Build Status](https://cloud.drone.io/api/badges/gulrak/filesystem/status.svg?ref=refs/heads/master)](https://cloud.drone.io/gulrak/filesystem) -->
[![Latest Release Tag](https://img.shields.io/github/tag/gulrak/filesystem.svg)](https://github.com/gulrak/filesystem/tree/v1.5.10)
<!-- TOC -->
* [Filesystem](#filesystem)
* [Motivation](#motivation)
* [Why the namespace GHC?](#why-the-namespace-ghc)
* [Platforms](#platforms)
* [Tests](#tests)
* [Usage](#usage)
* [Downloads](#downloads)
* [Using it as Single-File-Header](#using-it-as-single-file-header)
* [Using it as Forwarding-/Implementation-Header](#using-it-as-forwarding-implementation-header)
* [Git Submodule and CMake](#git-submodule-and-cmake)
* [Versioning](#versioning)
* [Documentation](#documentation)
* [`ghc::filesystem::ifstream`, `ghc::filesystem::ofstream`, `ghc::filesystem::fstream`](#ghcfilesystemifstream--ghcfilesystemofstream--ghcfilesystemfstream)
* [`ghc::filesystem::u8arguments`](#ghcfilesystemu8arguments)
* [Differences](#differences)
* [LWG Defects](#lwg-defects)
* [Not Implemented on C++ before C++17](#not-implemented-on-c-before-c17)
* [Differences in API](#differences-in-api)
* [Differences of Specific Interfaces](#differences-of-specific-interfaces)
* [Differences in Behavior](#differences-in-behavior)
* [fs.path (ref)](#fspath--ref-)
* [Open Issues](#open-issues)
* [Windows](#windows)
* [Symbolic Links on Windows](#symbolic-links-on-windows)
* [Permissions](#permissions)
* [Release Notes](#release-notes)
<!-- TOC -->
- [Filesystem](#filesystem)
- [Motivation](#motivation)
- [Why the namespace GHC?](#why-the-namespace-ghc)
- [Platforms](#platforms)
- [Tests](#tests)
- [Usage](#usage)
- [Downloads](#downloads)
- [Using it as Single-File-Header](#using-it-as-single-file-header)
- [Using it as Forwarding-/Implementation-Header](#using-it-as-forwarding-implementation-header)
- [Git Submodule and CMake](#git-submodule-and-cmake)
- [Versioning](#versioning)
- [Documentation](#documentation)
- [`ghc::filesystem::ifstream`, `ghc::filesystem::ofstream`, `ghc::filesystem::fstream`](#ghcfilesystemifstream-ghcfilesystemofstream-ghcfilesystemfstream)
- [`ghc::filesystem::u8arguments`](#ghcfilesystemu8arguments)
- [Differences](#differences)
- [LWG Defects](#lwg-defects)
- [Not Implemented on C++ before C++17](#not-implemented-on-c-before-c17)
- [Differences in API](#differences-in-api)
- [Differences of Specific Interfaces](#differences-of-specific-interfaces)
- [Differences in Behavior](#differences-in-behavior)
- [fs.path](#fspath-refhttpsencppreferencecomwcppfilesystempath)
- [Open Issues](#open-issues)
- [Windows](#windows)
- [Symbolic Links on Windows](#symbolic-links-on-windows)
- [Permissions](#permissions)
- [Release Notes](#release-notes)
# Filesystem
This is a header-only single-file `std::filesystem` compatible helper library,
based on the C++17 and C++20 specs, but implemented for C++11, C++14, C++17 or C++20
(tightly following the C++17 standard with very few documented exceptions). It is currently tested on
macOS 10.12/10.14/10.15/11.6, Windows 10, Ubuntu 18.04, Ubuntu 20.04, CentOS 7, CentOS 8, FreeBSD 12,
Alpine ARM/ARM64 Linux and Solaris 10 but should work on other systems too, as long as you have
macOS 10.12/10.14/10.15, Windows 10, Ubuntu 18.04, Ubuntu 20.04, CentOS 7, CentOS 8, FreeBSD 12
and Alpine ARM/ARM64 Linux 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, QNX, and since 1.5.14
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.
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.
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).
@ -91,15 +87,15 @@ to do with Haskell**, sorry for the name clash).
## Platforms
`ghc::filesystem` is developed on macOS but CI tested on macOS, Windows,
various Linux Distributions, FreeBSD and starting with v1.5.12 on Solaris.
It should work on any of these with a C++11-capable compiler. Also there are some
checks to hopefully better work on Android, but as I currently don't test with the
Android NDK, I wouldn't call it a supported platform yet, same is valid for using
it with Emscripten. It is now part of the detected platforms, I fixed the obvious
issues and ran some tests with it, so it should be fine. All in all, I don't see it
replacing `std::filesystem` where full C++17 or C++20 is available, it doesn't try
to be a "better" `std::filesystem`, just an almost drop-in if you can't use it
(with the exception of the UTF-8 preference).
various Linux Distributions and FreeBSD. It should work on any of these with a C++11-capable
compiler. Also there are some checks to hopefully better work on Android, but
as I currently don't test with the Android NDK, I wouldn't call it a
supported platform yet, same is valid for using it with Emscripten. It is now
part of the detected platforms, I fixed the obvious issues and ran some tests with
it, so it should be fine. All in all, I don't see it replacing `std::filesystem`
where full C++17 or C++20 is available, it doesn't try to be a "better"
`std::filesystem`, just an almost drop-in if you can't use it (with the exception
of the UTF-8 preference).
:information_source: **Important:** _This implementation is following the ["UTF-8 Everywhere" philosophy](https://utf8everywhere.org/) in that all
`std::string` instances will be interpreted the same as `std::u8string` encoding
@ -111,10 +107,8 @@ Unit tests are currently run with:
* macOS 10.12: Xcode 9.2 (clang-900.0.39.2), GCC 9.2, Clang 9.0, macOS 10.13: Xcode 10.1, macOS 10.14: Xcode 11.2, macOS 10.15: Xcode 11.6, Xcode 12.4
* Windows: Visual Studio 2017, Visual Studio 2015, Visual Studio 2019, MinGW GCC 6.3 (Win32), GCC 7.2 (Win64), Cygwin GCC 10.2 (no CI yet)
* Linux (Ubuntu): GCC (5.5, 6.5, 7.4, 8.3, 9.2), Clang (5.0, 6.0, 7.1, 8.0, 9.0)
* ~~Linux (Alpine ARM/ARM64): GCC 9.2.0~~ (The Drone build scripts stopped working,
as they where a contribution, I couldn't figure out what went wrong, any help appreciated.)
* Linux (Alpine ARM/ARM64): GCC 9.2.0
* FreeBSD: Clang 8.0
* Solaris: GCC 5.5
## Tests
@ -154,8 +148,8 @@ in the standard, and there might be issues in these implementations too.
### Downloads
The latest release version is [v1.5.14](https://github.com/gulrak/filesystem/tree/v1.5.14) and
source archives can be found [here](https://github.com/gulrak/filesystem/releases/tag/v1.5.14).
The latest release version is [v1.5.10](https://github.com/gulrak/filesystem/tree/v1.5.10) and
source archives can be found [here](https://github.com/gulrak/filesystem/releases/tag/v1.5.10).
The latest pre-native-backend version is [v1.4.0](https://github.com/gulrak/filesystem/tree/v1.4.0) and
source archives can be found [here](https://github.com/gulrak/filesystem/releases/tag/v1.4.0).
@ -176,68 +170,43 @@ Everything is in the namespace `ghc::filesystem`, so one way to use it only as
a fallback could be:
```cpp
#if _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include)
// ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus
// _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
#if __has_include(<filesystem>) // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html
#define GHC_USE_STD_FS
// Old Apple OSs don't support std::filesystem, though the header is available at compile
// time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0,
// and watchOS 6.0.
#ifdef __APPLE__
#include <Availability.h>
// Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS
// released after std::filesystem, where std::filesystem is always available.
// (All other __<platform>_VERSION_MIN_REQUIREDs will be undefined and thus 0.)
#if __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \
|| __IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \
|| __TV_OS_VERSION_MIN_REQUIRED && __TV_OS_VERSION_MIN_REQUIRED < 130000 \
|| __WATCH_OS_VERSION_MAX_ALLOWED && __WATCH_OS_VERSION_MAX_ALLOWED < 60000
#undef GHC_USE_STD_FS
#include <Availability.h> // for deployment target to support pre-catalina targets without std::fs
#endif
#endif
#endif
#endif
#ifdef GHC_USE_STD_FS
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
#define GHC_USE_STD_FS
#include <filesystem>
namespace fs = std::filesystem;
#else
#include "filesystem.hpp"
#endif
#endif
#ifndef GHC_USE_STD_FS
#include <ghc/filesystem.hpp>
namespace fs = ghc::filesystem;
#endif
```
**Note that this code uses a two-stage preprocessor condition because Visual Studio 2015
doesn't like the `(<...>)` syntax, even if it could cut evaluation early before. This code also
used the minimum deployment target to detect if `std::filesystem` really is available on macOS
compilation.**
**Note also, this detection now works on MSVC versions prior to 15.7 on, or without setting
the `/Zc:__cplusplus` compile switch that would fix `__cplusplus` on MSVC. (Without the switch
the compiler always reports `199711L`
([see](https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/)),
but `_MSVC_LANG` works without it.**
If you want to also use the `fstream` wrapper with `path` support as fallback,
you might use:
```cpp
#if _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include)
// ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus
// _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
#if __has_include(<filesystem>) // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html
#define GHC_USE_STD_FS
// Old Apple OSs don't support std::filesystem, though the header is available at compile
// time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0,
// and watchOS 6.0.
#ifdef __APPLE__
#include <Availability.h>
// Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS
// released after std::filesystem, where std::filesystem is always available.
// (All other __<platform>_VERSION_MIN_REQUIREDs will be undefined and thus 0.)
#if __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \
|| __IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \
|| __TV_OS_VERSION_MIN_REQUIRED && __TV_OS_VERSION_MIN_REQUIRED < 130000 \
|| __WATCH_OS_VERSION_MAX_ALLOWED && __WATCH_OS_VERSION_MAX_ALLOWED < 60000
#undef GHC_USE_STD_FS
#include <Availability.h> // for deployment target to support pre-catalina targets without std::fs
#endif
#endif
#endif
#endif
#ifdef GHC_USE_STD_FS
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
#define GHC_USE_STD_FS
#include <filesystem>
namespace fs {
using namespace std::filesystem;
@ -245,8 +214,10 @@ you might use:
using ofstream = std::ofstream;
using fstream = std::fstream;
}
#else
#include "filesystem.hpp"
#endif
#endif
#ifndef GHC_USE_STD_FS
#include <ghc/filesystem.hpp>
namespace fs {
using namespace ghc::filesystem;
using ifstream = ghc::filesystem::ifstream;
@ -292,31 +263,12 @@ If you use the forwarding/implementation approach, you can still use the dynamic
switching like this:
```cpp
#if _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include)
// ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus
// _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
#if __has_include(<filesystem>) // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html
#define GHC_USE_STD_FS
// Old Apple OSs don't support std::filesystem, though the header is available at compile
// time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0,
// and watchOS 6.0.
#ifdef __APPLE__
#include <Availability.h>
// Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS
// released after std::filesystem, where std::filesystem is always available.
// (All other __<platform>_VERSION_MIN_REQUIREDs will be undefined and thus 0.)
#if __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \
|| __IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \
|| __TV_OS_VERSION_MIN_REQUIRED && __TV_OS_VERSION_MIN_REQUIRED < 130000 \
|| __WATCH_OS_VERSION_MAX_ALLOWED && __WATCH_OS_VERSION_MAX_ALLOWED < 60000
#undef GHC_USE_STD_FS
#include <Availability.h> // for deployment target to support pre-catalina targets without std::fs
#endif
#endif
#endif
#endif
#ifdef GHC_USE_STD_FS
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
#define GHC_USE_STD_FS
#include <filesystem>
namespace fs {
using namespace std::filesystem;
@ -324,8 +276,10 @@ switching like this:
using ofstream = std::ofstream;
using fstream = std::fstream;
}
#else
#include "fs_fwd.hpp"
#endif
#endif
#ifndef GHC_USE_STD_FS
#include <ghc/fs-fwd.hpp>
namespace fs {
using namespace ghc::filesystem;
using ifstream = ghc::filesystem::ifstream;
@ -339,38 +293,25 @@ and in the implementation hiding cpp, you might use (before any include that inc
to take precedence:
```cpp
#if _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include)
// ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus
// _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
#if __has_include(<filesystem>) // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html
#define GHC_USE_STD_FS
// Old Apple OSs don't support std::filesystem, though the header is available at compile
// time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0,
// and watchOS 6.0.
#ifdef __APPLE__
#ifdef __APPLE__ // for deployment target to support pre-catalina targets without std::fs
#include <Availability.h>
// Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS
// released after std::filesystem, where std::filesystem is always available.
// (All other __<platform>_VERSION_MIN_REQUIREDs will be undefined and thus 0.)
#if __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \
|| __IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \
|| __TV_OS_VERSION_MIN_REQUIRED && __TV_OS_VERSION_MIN_REQUIRED < 130000 \
|| __WATCH_OS_VERSION_MAX_ALLOWED && __WATCH_OS_VERSION_MAX_ALLOWED < 60000
#undef GHC_USE_STD_FS
#endif
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
#define GHC_USE_STD_FS
#endif
#endif
#endif
#endif
#ifndef GHC_USE_STD_FS
#include "fs_impl.hpp"
#define GHC_FILESYSTEM_IMPLEMENTATION
#include <ghc/filesystem.hpp>
#endif
```
:information_source: **Hint:** There are additional helper headers, named `ghc/fs_std_fwd.hpp` and
`ghc/fs_std_impl.hpp` that use this technique, so you can simply include them
if you want to dynamically select the filesystem implementation.
if you want to dynamically select the filesystem implementation. they also
enable the `wchar_t` support on `ghc::filesystem` on Windows, so the resulting
implementation in the `fs` namespace will be compatible.
@ -397,10 +338,6 @@ The `CMakeLists.txt` offers a few options to customize its behavior:
`CMAKE_CXX_COMPILE_FEATURES` when the detection of C++17 or C++20 for additional tests
is not working (e.g. `cxx_std_20` to enforce building a `filesystem_test_cpp20` with C++20).
### Bazel
Please use [hedronvision/bazel-cc-filesystem-backport](https://github.com/hedronvision/bazel-cc-filesystem-backport), which will automatically set everything up for you.
### Versioning
There is a version macro `GHC_FILESYSTEM_VERSION` defined in case future changes
@ -466,7 +403,7 @@ int main(int argc, char* argv[])
exit(EXIT_FAILURE);
}
// now use argc/argv as usual, they have utf-8 encoding on windows
// now use argc/argv as usual, they have utf-8 enconding on windows
// ...
return 0;
@ -646,60 +583,6 @@ to the expected behavior.
## Release Notes
### v1.5.15 (wip)
* Fix for [#166](https://github.com/gulrak/filesystem/issues/166),
`extension()` did return non empty result for the directory name
`".."`
### [v1.5.14](https://github.com/gulrak/filesystem/releases/tag/v1.5.14)
* 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
* Pull request [#161](https://github.com/gulrak/filesystem/pull/161), the
CMake alias `ghcFilesystem::ghc_filesystem` is now set unconditionally
* 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
for `GHC_NO_DIRENT_D_TYPE` on systems that don't support `dirent::d_type` and
fixed build configuration and tests to support Solaris as new platform.
* Pull request [#138](https://github.com/gulrak/filesystem/pull/138), if the
platform uses the POSIX backend and has no `PATH_MAX`, one is defined.
* Pull request [#137](https://github.com/gulrak/filesystem/pull/137), update
of Catch2 to version v2.13.7
* Added macOS 11 to the automatically tested platforms.
### [v1.5.10](https://github.com/gulrak/filesystem/releases/tag/v1.5.10)
* Pull request [#136](https://github.com/gulrak/filesystem/pull/136), the Windows
@ -716,7 +599,7 @@ to the expected behavior.
### [v1.5.8](https://github.com/gulrak/filesystem/releases/tag/v1.5.8)
* Fix for [#125](https://github.com/gulrak/filesystem/issues/124), where
* Fix for [#125]((https://github.com/gulrak/filesystem/issues/124), where
`fs::create_directories` on Windows no longer breaks on long filenames.
### [v1.5.6](https://github.com/gulrak/filesystem/releases/tag/v1.5.6)

View File

@ -1,5 +1,6 @@
macro(AddExecutableWithStdFS targetName)
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 7.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0))
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 7.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0))
if(APPLE)
include_directories(/usr/local/opt/llvm/include)
link_directories(/usr/local/opt/llvm/lib)
@ -19,12 +20,6 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND (CMAKE_CXX_COMPILER_VERSION V
target_link_libraries(${targetName} -stdlib=libc++)
endif()
endif()
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,12 +29,6 @@ if (CMAKE_COMPILER_IS_GNUCXX AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 8.0 O
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0)
target_link_libraries(${targetName} -lstdc++fs)
endif()
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()
@ -58,12 +47,6 @@ macro(AddTestExecutableWithStdCpp cppStd)
add_executable(filesystem_test_cpp${cppStd} ${ARGN})
set_property(TARGET filesystem_test_cpp${cppStd} PROPERTY CXX_STANDARD ${cppStd})
target_link_libraries(filesystem_test_cpp${cppStd} ghc_filesystem)
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>

View File

@ -25,6 +25,23 @@
// SOFTWARE.
//
//---------------------------------------------------------------------------------------
//
// To dynamically select std::filesystem where available on most platforms,
// you could use:
//
// #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
// #if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
// #define GHC_USE_STD_FS
// #include <filesystem>
// namespace fs = std::filesystem;
// #endif
// #endif
// #ifndef GHC_USE_STD_FS
// #include <ghc/filesystem.hpp>
// namespace fs = ghc::filesystem;
// #endif
//
//---------------------------------------------------------------------------------------
#ifndef GHC_FILESYSTEM_H
#define GHC_FILESYSTEM_H
@ -36,7 +53,7 @@
#ifndef GHC_OS_DETECTED
#if defined(__APPLE__) && defined(__MACH__)
#define GHC_OS_APPLE
#define GHC_OS_MACOS
#elif defined(__linux__)
#define GHC_OS_LINUX
#if defined(__ANDROID__)
@ -50,8 +67,6 @@
#define GHC_OS_WIN32
#elif defined(__CYGWIN__)
#define GHC_OS_CYGWIN
#elif defined(__sun) && defined(__SVR4)
#define GHC_OS_SOLARIS
#elif defined(__svr4__)
#define GHC_OS_SYS5R4
#elif defined(BSD)
@ -61,8 +76,7 @@
#include <wasi/api.h>
#elif defined(__QNX__)
#define GHC_OS_QNX
#elif defined(__HAIKU__)
#define GHC_OS_HAIKU
#define GHC_NO_DIRENT_D_TYPE
#else
#error "Operating system currently not supported!"
#endif
@ -164,7 +178,7 @@
#include <langinfo.h>
#endif
#endif
#ifdef GHC_OS_APPLE
#ifdef GHC_OS_MACOS
#include <Availability.h>
#endif
@ -240,10 +254,6 @@
#include <experimental/string_view>
#endif
#if !defined(GHC_OS_WINDOWS) && !defined(PATH_MAX)
#define PATH_MAX 4096
#endif
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Behaviour Switches (see README.md, should match the config in test/filesystem_test.cpp):
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -264,19 +274,19 @@
// * if this->has_root_directory() and !p.has_root_directory() return -1
// * if !this->has_root_directory() and p.has_root_directory() return -1
// * else result of element wise comparison of path iteration where first comparison is != 0 or 0
// if all comparisons are 0 (on Windows this implementation does case-insensitive root_name()
// if all comparisons are 0 (on Windows this implementation does case insensitive root_name()
// comparison)
#define LWG_2936_BEHAVIOUR
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// LWG #2937 enforces that fs::equivalent emits an error, if !fs::exists(p1)||!exists(p2)
#define LWG_2937_BEHAVIOUR
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// UTF8-Everywhere is the original behaviour of ghc::filesystem. But since v1.5 the Windows
// UTF8-Everywhere is the original behaviour of ghc::filesystem. But since v1.5 the windows
// version defaults to std::wstring storage backend. Still all std::string will be interpreted
// as UTF-8 encoded. With this define you can enforce the old behavior on Windows, using
// as UTF-8 encoded. With this define you can enfoce the old behavior on Windows, using
// std::string as backend and for fs::path::native() and char for fs::path::c_str(). This
// needs more conversions, so it is (and was before v1.5) slower, bot might help keeping source
// homogeneous in a multi-platform project.
// needs more conversions so it is (an was before v1.5) slower, bot might help keeping source
// homogeneous in a multi platform project.
// #define GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Raise errors/exceptions when invalid unicode codepoints or UTF-8 sequences are found,
@ -291,7 +301,7 @@
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// ghc::filesystem version in decimal (major * 10000 + minor * 100 + patch)
#define GHC_FILESYSTEM_VERSION 10515L
#define GHC_FILESYSTEM_VERSION 10510L
#if !defined(GHC_WITH_EXCEPTIONS) && (defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND))
#define GHC_WITH_EXCEPTIONS
@ -1142,10 +1152,6 @@ GHC_FS_API void create_hard_link(const path& to, const path& new_hard_link, std:
GHC_FS_API uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcept;
#endif
#if defined(GHC_OS_WINDOWS) && (!defined(__GLIBCXX__) || (defined(_GLIBCXX_HAVE__WFOPEN) && defined(_GLIBCXX_USE_WCHAR_T)))
#define GHC_HAS_FSTREAM_OPEN_WITH_WCHAR
#endif
// Non-C++17 add-on std::fstream wrappers with path
template <class charT, class traits = std::char_traits<charT>>
class basic_filebuf : public std::basic_filebuf<charT, traits>
@ -1157,7 +1163,7 @@ public:
const basic_filebuf& operator=(const basic_filebuf&) = delete;
basic_filebuf<charT, traits>* open(const path& p, std::ios_base::openmode mode)
{
#ifdef GHC_HAS_FSTREAM_OPEN_WITH_WCHAR
#if defined(GHC_OS_WINDOWS) && !defined(__GLIBCXX__)
return std::basic_filebuf<charT, traits>::open(p.wstring().c_str(), mode) ? this : 0;
#else
return std::basic_filebuf<charT, traits>::open(p.string().c_str(), mode) ? this : 0;
@ -1170,7 +1176,7 @@ class basic_ifstream : public std::basic_ifstream<charT, traits>
{
public:
basic_ifstream() {}
#ifdef GHC_HAS_FSTREAM_OPEN_WITH_WCHAR
#if defined(GHC_OS_WINDOWS) && !defined(__GLIBCXX__)
explicit basic_ifstream(const path& p, std::ios_base::openmode mode = std::ios_base::in)
: std::basic_ifstream<charT, traits>(p.wstring().c_str(), mode)
{
@ -1193,7 +1199,7 @@ class basic_ofstream : public std::basic_ofstream<charT, traits>
{
public:
basic_ofstream() {}
#ifdef GHC_HAS_FSTREAM_OPEN_WITH_WCHAR
#if defined(GHC_OS_WINDOWS) && !defined(__GLIBCXX__)
explicit basic_ofstream(const path& p, std::ios_base::openmode mode = std::ios_base::out)
: std::basic_ofstream<charT, traits>(p.wstring().c_str(), mode)
{
@ -1216,7 +1222,7 @@ class basic_fstream : public std::basic_fstream<charT, traits>
{
public:
basic_fstream() {}
#ifdef GHC_HAS_FSTREAM_OPEN_WITH_WCHAR
#if defined(GHC_OS_WINDOWS) && !defined(__GLIBCXX__)
explicit basic_fstream(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
: std::basic_fstream<charT, traits>(p.wstring().c_str(), mode)
{
@ -1292,65 +1298,6 @@ GHC_FS_API std::error_code make_error_code(portable_error err);
GHC_FS_API std::error_code make_system_error(uint32_t err = 0);
#else
GHC_FS_API std::error_code make_system_error(int err = 0);
template <typename T, typename = int>
struct has_d_type : std::false_type{};
template <typename T>
struct has_d_type<T, decltype((void)T::d_type, 0)> : std::true_type {};
template <typename T>
GHC_INLINE file_type file_type_from_dirent_impl(const T&, std::false_type)
{
return file_type::none;
}
template <typename T>
GHC_INLINE file_type file_type_from_dirent_impl(const T& t, std::true_type)
{
switch (t.d_type) {
#ifdef DT_BLK
case DT_BLK:
return file_type::block;
#endif
#ifdef DT_CHR
case DT_CHR:
return file_type::character;
#endif
#ifdef DT_DIR
case DT_DIR:
return file_type::directory;
#endif
#ifdef DT_FIFO
case DT_FIFO:
return file_type::fifo;
#endif
#ifdef DT_LNK
case DT_LNK:
return file_type::symlink;
#endif
#ifdef DT_REG
case DT_REG:
return file_type::regular;
#endif
#ifdef DT_SOCK
case DT_SOCK:
return file_type::socket;
#endif
#ifdef DT_UNKNOWN
case DT_UNKNOWN:
return file_type::none;
#endif
default:
return file_type::unknown;
}
}
template <class T>
GHC_INLINE file_type file_type_from_dirent(const T& t)
{
return file_type_from_dirent_impl(t, has_d_type<T>{});
}
#endif
} // namespace detail
@ -1944,15 +1891,10 @@ 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) {
@ -1973,15 +1915,10 @@ 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) {
@ -2240,10 +2177,10 @@ GHC_INLINE time_t timeFromFILETIME(const FILETIME& ft)
GHC_INLINE void timeToFILETIME(time_t t, FILETIME& ft)
{
ULARGE_INTEGER ull;
ull.QuadPart = static_cast<ULONGLONG>((t * 10000000LL) + 116444736000000000LL);
ft.dwLowDateTime = ull.LowPart;
ft.dwHighDateTime = ull.HighPart;
LONGLONG ll;
ll = Int32x32To64(t, 10000000) + 116444736000000000;
ft.dwLowDateTime = static_cast<DWORD>(ll);
ft.dwHighDateTime = static_cast<DWORD>(ll >> 32);
}
template <typename INFO>
@ -2259,44 +2196,42 @@ GHC_INLINE uintmax_t hard_links_from_INFO<BY_HANDLE_FILE_INFORMATION>(const BY_H
}
template <typename INFO>
GHC_INLINE bool is_symlink_from_INFO(const path &p, const INFO* info, std::error_code& ec)
GHC_INLINE DWORD reparse_tag_from_INFO(const INFO*)
{
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;
return 0;
}
template <>
GHC_INLINE bool is_symlink_from_INFO(const path &, const WIN32_FIND_DATAW* info, std::error_code&)
GHC_INLINE DWORD reparse_tag_from_INFO(const WIN32_FIND_DATAW* info)
{
// 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;
return info->dwReserved0;
}
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 (is_symlink_from_INFO(p, info, ec)) {
if (sizeof(INFO) == sizeof(WIN32_FIND_DATAW)) {
if (detail::reparse_tag_from_INFO(info) == IO_REPARSE_TAG_SYMLINK) {
ft = file_type::symlink;
}
else if ((info->dwFileAttributes & FILE_ATTRIBUTE_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;
}
}
perms prms = perms::owner_read | perms::group_read | perms::others_read;
if (!(info->dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
prms = prms | perms::owner_write | perms::group_write | perms::others_write;
@ -3157,7 +3092,7 @@ GHC_INLINE path path::extension() const
auto iter = end();
const auto& fn = *--iter;
impl_string_type::size_type pos = fn._path.rfind('.');
if (pos != std::string::npos && pos > 0 && fn._path != "..") {
if (pos != std::string::npos && pos > 0) {
return path(fn._path.substr(pos), native_format);
}
}
@ -3306,9 +3241,6 @@ GHC_INLINE path path::lexically_relative(const path& base) const
--count;
}
}
if (count == 0 && (a == end() || a->empty())) {
return path(".");
}
if (count < 0) {
return path();
}
@ -3369,14 +3301,10 @@ 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);
}
}
@ -3920,14 +3848,11 @@ GHC_INLINE bool copy_file(const path& from, const path& to, copy_options options
ec = tecf;
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) {
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::update_existing) == copy_options::update_existing) {
auto from_time = last_write_time(from, ec);
if (ec) {
@ -3967,33 +3892,15 @@ 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 (true) {
do { br = ::read(in, buffer.data(), buffer.size()); } while(errno == EINTR && !br);
if(!br) {
break;
}
if(br < 0) {
ec = detail::make_system_error();
::close(in);
::close(out);
return false;
}
while ((br = ::read(in, buffer.data(), buffer.size())) > 0) {
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 && errno != EINTR) {
else if (bw < 0) {
ec = detail::make_system_error();
::close(in);
::close(out);
@ -4228,13 +4135,6 @@ 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 { ::get_current_dir_name(), 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]);
@ -4640,11 +4540,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_APPLE) && \
(__MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101300 \
|| __IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED < 110000 \
|| __TV_OS_VERSION_MIN_REQUIRED && __TVOS_VERSION_MIN_REQUIRED < 110000 \
|| __WATCH_OS_VERSION_MIN_REQUIRED && __WATCHOS_VERSION_MIN_REQUIRED < 40000)
#elif defined(GHC_OS_MACOS)
#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
#if __MAC_OS_X_VERSION_MIN_REQUIRED < 101300
struct ::stat fs;
if (::stat(p.c_str(), &fs) == 0) {
struct ::timeval tv[2];
@ -4658,6 +4556,18 @@ 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)
@ -4670,7 +4580,7 @@ GHC_INLINE void last_write_time(const path& p, file_time_type new_time, std::err
#if defined(__ANDROID_API__) && __ANDROID_API__ < 12
if (syscall(__NR_utimensat, AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) {
#else
if (::utimensat((int)AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) {
if (::utimensat(AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) {
#endif
ec = detail::make_system_error();
}
@ -5285,7 +5195,7 @@ GHC_INLINE void directory_entry::refresh()
{
std::error_code ec;
refresh(ec);
if (ec && (_status.type() == file_type::none || _symlink_status.type() != file_type::symlink)) {
if (ec) {
throw filesystem_error(detail::systemErrorText(ec.value()), _path, ec);
}
}
@ -5696,7 +5606,7 @@ public:
, _entry(nullptr)
{
if (!path.empty()) {
do { _dir = ::opendir(path.native().c_str()); } while(errno == EINTR && !_dir);
_dir = ::opendir(path.native().c_str());
if (!_dir) {
auto error = errno;
_base = filesystem::path();
@ -5723,7 +5633,7 @@ public:
do {
skip = false;
errno = 0;
do { _entry = ::readdir(_dir); } while(errno == EINTR && !_entry);
_entry = ::readdir(_dir);
if (_entry) {
_dir_entry._path = _base;
_dir_entry._path.append_name(_entry->d_name);
@ -5737,7 +5647,7 @@ public:
::closedir(_dir);
_dir = nullptr;
_dir_entry._path.clear();
if (errno && errno != EINTR) {
if (errno) {
ec = detail::make_system_error();
}
break;
@ -5748,16 +5658,48 @@ public:
void copyToDirEntry()
{
#ifdef GHC_NO_DIRENT_D_TYPE
_dir_entry._symlink_status = file_status();
_dir_entry._status = file_status();
#else
_dir_entry._symlink_status.permissions(perms::unknown);
auto ft = detail::file_type_from_dirent(*_entry);
_dir_entry._symlink_status.type(ft);
if (ft != file_type::symlink) {
switch (_entry->d_type) {
case DT_BLK:
_dir_entry._symlink_status.type(file_type::block);
break;
case DT_CHR:
_dir_entry._symlink_status.type(file_type::character);
break;
case DT_DIR:
_dir_entry._symlink_status.type(file_type::directory);
break;
case DT_FIFO:
_dir_entry._symlink_status.type(file_type::fifo);
break;
case DT_LNK:
_dir_entry._symlink_status.type(file_type::symlink);
break;
case DT_REG:
_dir_entry._symlink_status.type(file_type::regular);
break;
case DT_SOCK:
_dir_entry._symlink_status.type(file_type::socket);
break;
case DT_UNKNOWN:
_dir_entry._symlink_status.type(file_type::none);
break;
default:
_dir_entry._symlink_status.type(file_type::unknown);
break;
}
if (_entry->d_type != DT_LNK) {
_dir_entry._status = _dir_entry._symlink_status;
}
else {
_dir_entry._status.type(file_type::none);
_dir_entry._status.permissions(perms::unknown);
}
#endif
_dir_entry._file_size = static_cast<uintmax_t>(-1);
_dir_entry._hard_link_count = static_cast<uintmax_t>(-1);
_dir_entry._last_write_time = 0;

View File

@ -25,7 +25,7 @@
// SOFTWARE.
//
//---------------------------------------------------------------------------------------
// fs_fwd.hpp - The forwarding header for the header/implementation separated usage of
// fs_fwd.hpp - The forwarding header for the header/implementation seperated usage of
// ghc::filesystem.
// This file can be include at any place, where ghc::filesystem api is needed while
// not bleeding implementation details (e.g. system includes) into the global namespace,
@ -34,5 +34,5 @@
#ifndef GHC_FILESYSTEM_FWD_H
#define GHC_FILESYSTEM_FWD_H
#define GHC_FILESYSTEM_FWD
#include "filesystem.hpp"
#include <ghc/filesystem.hpp>
#endif // GHC_FILESYSTEM_FWD_H

View File

@ -25,11 +25,11 @@
// SOFTWARE.
//
//---------------------------------------------------------------------------------------
// fs_impl.hpp - The implementation header for the header/implementation separated usage of
// fs_impl.hpp - The implementation header for the header/implementation seperated usage of
// ghc::filesystem.
// This file can be used to hide the implementation of ghc::filesystem into a single cpp.
// The cpp has to include this before including fs_fwd.hpp directly or via a different
// header to work.
//---------------------------------------------------------------------------------------
#define GHC_FILESYSTEM_IMPLEMENTATION
#include "filesystem.hpp"
#include <ghc/filesystem.hpp>

View File

@ -31,32 +31,12 @@
//---------------------------------------------------------------------------------------
#ifndef GHC_FILESYSTEM_STD_H
#define GHC_FILESYSTEM_STD_H
#if defined(_MSVC_LANG) && _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include)
// ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus
// _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
#if __has_include(<filesystem>) // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html
#define GHC_USE_STD_FS
// Old Apple OSs don't support std::filesystem, though the header is available at compile
// time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0,
// and watchOS 6.0.
#ifdef __APPLE__
#if defined(__APPLE__)
#include <Availability.h>
// Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS
// released after std::filesystem, where std::filesystem is always available.
// (All other __<platform>_VERSION_MIN_REQUIREDs will be undefined and thus 0.)
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \
|| defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \
|| defined(__TV_OS_VERSION_MIN_REQUIRED) && __TV_OS_VERSION_MIN_REQUIRED < 130000 \
|| defined(__WATCH_OS_VERSION_MAX_ALLOWED) && __WATCH_OS_VERSION_MAX_ALLOWED < 60000
#undef GHC_USE_STD_FS
#endif
#endif
#endif
#endif
#ifdef GHC_USE_STD_FS
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
#define GHC_USE_STD_FS
#include <filesystem>
namespace fs {
using namespace std::filesystem;
@ -64,8 +44,11 @@
using ofstream = std::ofstream;
using fstream = std::fstream;
}
#else
#include "filesystem.hpp"
#endif
#endif
#ifndef GHC_USE_STD_FS
//#define GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE
#include <ghc/filesystem.hpp>
namespace fs {
using namespace ghc::filesystem;
using ifstream = ghc::filesystem::ifstream;
@ -73,5 +56,5 @@
using fstream = ghc::filesystem::fstream;
}
#endif
#endif // GHC_FILESYSTEM_STD_H

View File

@ -25,7 +25,7 @@
// SOFTWARE.
//
//---------------------------------------------------------------------------------------
// fs_std_fwd.hpp - The forwarding header for the header/implementation separated usage of
// fs_std_fwd.hpp - The forwarding header for the header/implementation seperated usage of
// ghc::filesystem that uses std::filesystem if it detects it.
// This file can be include at any place, where fs::filesystem api is needed while
// not bleeding implementation details (e.g. system includes) into the global namespace,
@ -33,32 +33,12 @@
//---------------------------------------------------------------------------------------
#ifndef GHC_FILESYSTEM_STD_FWD_H
#define GHC_FILESYSTEM_STD_FWD_H
#if defined(_MSVC_LANG) && _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include)
// ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus
// _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
#if __has_include(<filesystem>) // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html
#define GHC_USE_STD_FS
// Old Apple OSs don't support std::filesystem, though the header is available at compile
// time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0,
// and watchOS 6.0.
#ifdef __APPLE__
#if defined(__APPLE__)
#include <Availability.h>
// Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS
// released after std::filesystem, where std::filesystem is always available.
// (All other __<platform>_VERSION_MIN_REQUIREDs will be undefined and thus 0.)
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \
|| defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \
|| defined(__TV_OS_VERSION_MIN_REQUIRED) && __TV_OS_VERSION_MIN_REQUIRED < 130000 \
|| defined(__WATCH_OS_VERSION_MAX_ALLOWED) && __WATCH_OS_VERSION_MAX_ALLOWED < 60000
#undef GHC_USE_STD_FS
#endif
#endif
#endif
#endif
#ifdef GHC_USE_STD_FS
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
#define GHC_USE_STD_FS
#include <filesystem>
namespace fs {
using namespace std::filesystem;
@ -66,8 +46,12 @@
using ofstream = std::ofstream;
using fstream = std::fstream;
}
#else
#include "fs_fwd.hpp"
#endif
#endif
#ifndef GHC_USE_STD_FS
//#define GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE
#define GHC_FILESYSTEM_FWD
#include <ghc/filesystem.hpp>
namespace fs {
using namespace ghc::filesystem;
using ifstream = ghc::filesystem::ifstream;
@ -75,5 +59,5 @@
using fstream = ghc::filesystem::fstream;
}
#endif
#endif // GHC_FILESYSTEM_STD_FWD_H

View File

@ -25,36 +25,22 @@
// SOFTWARE.
//
//---------------------------------------------------------------------------------------
// fs_std_impl.hpp - The implementation header for the header/implementation separated usage of
// fs_std_impl.hpp - The implementation header for the header/implementation seperated usage of
// ghc::filesystem that does nothing if std::filesystem is detected.
// This file can be used to hide the implementation of ghc::filesystem into a single cpp.
// The cpp has to include this before including fs_std_fwd.hpp directly or via a different
// header to work.
//---------------------------------------------------------------------------------------
#if defined(_MSVC_LANG) && _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include)
// ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus
// _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
#if __has_include(<filesystem>) // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html
#define GHC_USE_STD_FS
// Old Apple OSs don't support std::filesystem, though the header is available at compile
// time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0,
// and watchOS 6.0.
#ifdef __APPLE__
#if defined(__APPLE__)
#include <Availability.h>
// Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS
// released after std::filesystem, where std::filesystem is always available.
// (All other __<platform>_VERSION_MIN_REQUIREDs will be undefined and thus 0.)
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \
|| defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \
|| defined(__TV_OS_VERSION_MIN_REQUIRED) && __TV_OS_VERSION_MIN_REQUIRED < 130000 \
|| defined(__WATCH_OS_VERSION_MAX_ALLOWED) && __WATCH_OS_VERSION_MAX_ALLOWED < 60000
#undef GHC_USE_STD_FS
#endif
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
#define GHC_USE_STD_FS
#endif
#endif
#endif
#endif
#ifndef GHC_USE_STD_FS
#include "fs_impl.hpp"
//#define GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE
#define GHC_FILESYSTEM_IMPLEMENTATION
#include <ghc/filesystem.hpp>
#endif

View File

@ -3,20 +3,6 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
set(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS ON)
include(ParseAndAddCatchTests)
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND UNIX AND NOT APPLE AND NOT BSD)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
set(CMAKE_EXE_LINKER_FLAGS "-lc++abi")
endif()
function(SetTestCompileOptions target_name)
target_compile_options(${target_name} 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-deprecated-declarations>
$<$<CXX_COMPILER_ID:GNU>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Wno-psabi -Werror -Wno-deprecated-declarations>
$<$<CXX_COMPILER_ID:MSVC>:/WX /wd4996>
$<$<BOOL:${CYGWIN}>:-Wa,-mbig-obj>)
endfunction()
if(GHC_COVERAGE)
message("Generating test runner for coverage run...")
set(CMAKE_EXE_LINKER_FLAGS "${CMCMAKE_EXE_LINKER_FLAGS} --coverage")
@ -27,12 +13,6 @@ if(GHC_COVERAGE)
target_compile_options(filesystem_test PUBLIC --coverage)
endif()
target_link_libraries(filesystem_test PUBLIC ghc_filesystem --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()
@ -43,13 +23,12 @@ else()
message("Generating test runner for normal test...")
add_executable(filesystem_test filesystem_test.cpp catch.hpp)
target_link_libraries(filesystem_test ghc_filesystem)
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)
target_compile_options(filesystem_test 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>
$<$<CXX_COMPILER_ID:GNU>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Wno-psabi -Werror>
$<$<CXX_COMPILER_ID:MSVC>:/WX>
$<$<BOOL:${CYGWIN}>:-Wa,-mbig-obj>)
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
target_compile_definitions(filesystem_test PRIVATE _CRT_SECURE_NO_WARNINGS WIN32_LEAN_AND_MEAN NOMINMAX)
endif()
@ -63,7 +42,10 @@ else()
if(WIN32)
add_executable(filesystem_test_char filesystem_test.cpp catch.hpp)
target_link_libraries(filesystem_test_char ghc_filesystem)
SetTestCompileOptions(filesystem_test_char)
target_compile_options(filesystem_test_char PRIVATE
$<$<CXX_COMPILER_ID:Clang>:-Wall -Wextra -Werror>
$<$<CXX_COMPILER_ID:GNU>:-Wall -Werror>
$<$<CXX_COMPILER_ID:MSVC>:/WX>)
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
target_compile_definitions(filesystem_test_char PRIVATE _CRT_SECURE_NO_WARNINGS GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE)
else()
@ -85,13 +67,12 @@ add_test(multifile_test multifile_test)
add_executable(fwd_impl_test fwd_test.cpp impl_test.cpp)
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)
target_compile_options(fwd_impl_test 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>
$<$<CXX_COMPILER_ID:GNU>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Wno-psabi -Werror>
$<$<CXX_COMPILER_ID:MSVC>:/WX>
$<$<BOOL:${CYGWIN}>:-Wa,-mbig-obj>)
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
target_compile_definitions(fwd_impl_test PRIVATE _CRT_SECURE_NO_WARNINGS WIN32_LEAN_AND_MEAN NOMINMAX)
endif()
@ -102,4 +83,9 @@ if(NOT MSVC)
target_compile_options(exception PRIVATE -fno-exceptions)
endif()
target_include_directories(exception PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../include)
SetTestCompileOptions(exception)
target_compile_options(exception 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>
$<$<CXX_COMPILER_ID:GNU>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Wno-psabi -Werror>
$<$<CXX_COMPILER_ID:MSVC>:/WX>
$<$<BOOL:${CYGWIN}>:-Wa,-mbig-obj>)

File diff suppressed because it is too large Load Diff

View File

@ -99,7 +99,7 @@ using fstream = ghc::filesystem::fstream;
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <typename TP>
static std::time_t to_time_t(TP tp)
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 @@ static std::time_t to_time_t(TP tp)
}
template <typename TP>
static TP from_time_t(std::time_t t)
TP from_time_t(std::time_t t)
{
using namespace std::chrono;
auto sctp = system_clock::from_time_t(t);
@ -214,8 +214,7 @@ static void generateFile(const fs::path& pathname, int withSize = -1)
}
#ifdef GHC_OS_WINDOWS
#if !defined(_WIN64) && defined(KEY_WOW64_64KEY)
static bool isWow64Proc()
inline bool isWow64Proc()
{
typedef BOOL(WINAPI * IsWow64Process_t)(HANDLE, PBOOL);
BOOL bIsWow64 = FALSE;
@ -227,7 +226,6 @@ static bool isWow64Proc()
}
return bIsWow64 == TRUE;
}
#endif
static bool is_symlink_creation_supported()
{
@ -305,13 +303,13 @@ public:
};
template <class T, class U>
static bool operator==(TestAllocator<T> const&, TestAllocator<U> const&) noexcept
bool operator==(TestAllocator<T> const&, TestAllocator<U> const&) noexcept
{
return true;
}
template <class T, class U>
static bool operator!=(TestAllocator<T> const& x, TestAllocator<U> const& y) noexcept
bool operator!=(TestAllocator<T> const& x, TestAllocator<U> const& y) noexcept
{
return !(x == y);
}
@ -792,9 +790,6 @@ 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()
@ -812,13 +807,6 @@ 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
CHECK(fs::path("/foo/.").stem() == ".");
CHECK(fs::path("/foo/..").stem() == "..");
// extension()
CHECK(fs::path("/foo/bar.txt").extension() == ".txt");
@ -826,9 +814,6 @@ 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");
CHECK(fs::path("/foo/.").extension() == "");
CHECK(fs::path("/foo/..").extension() == "");
if (has_host_root_name_support()) {
// //host-based root-names
@ -965,10 +950,6 @@ TEST_CASE("fs.path.gen - path generation", "[filesystem][path][fs.path.gen]")
// lexically_relative()
CHECK(fs::path("/a/d").lexically_relative("/a/b/c") == "../../d");
CHECK(fs::path("/a/b/c").lexically_relative("/a/d") == "../b/c");
CHECK(fs::path("/a/b/c").lexically_relative("/a/b/c/d/..") == ".");
CHECK(fs::path("/a/b/c/").lexically_relative("/a/b/c/d/..") == ".");
CHECK(fs::path("").lexically_relative("/a/..") == "");
CHECK(fs::path("").lexically_relative("a/..") == ".");
CHECK(fs::path("a/b/c").lexically_relative("a") == "b/c");
CHECK(fs::path("a/b/c").lexically_relative("a/b/c/x/y") == "../..");
CHECK(fs::path("a/b/c").lexically_relative("a/b/c") == ".");
@ -1218,7 +1199,7 @@ TEST_CASE("fs.class.filesystem_error - class filesystem_error", "[filesystem][fi
CHECK(fse.path2() == "some/other");
}
static constexpr fs::perms constExprOwnerAll()
constexpr fs::perms constExprOwnerAll()
{
return fs::perms::owner_read | fs::perms::owner_write | fs::perms::owner_exec;
}
@ -1396,16 +1377,6 @@ 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]")
@ -1807,19 +1778,6 @@ 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]")
@ -2205,7 +2163,6 @@ public:
fs::path character_path() const
{
#ifndef GHC_OS_SOLARIS
std::error_code ec;
if (fs::exists("/dev/null", ec)) {
return "/dev/null";
@ -2213,7 +2170,6 @@ public:
else if (fs::exists("NUL", ec)) {
return "NUL";
}
#endif
return fs::path();
}
fs::path temp_path() const { return _t.path(); }

View File

@ -27,7 +27,7 @@
#include <ghc/filesystem.hpp>
namespace fs = ghc::filesystem;
// This test and the one in multi2.cpp doesn't actually test relevant functionality,
// This test and the one in multi2.cpp doesn't actualy test relevant functionality,
// it is just used to check that it is possible to include filesystem.h in multiple
// source files.
TEST_CASE("Multifile-test 1", "[multi]")