Spot Spy Client
Spot Spy Client
Spot Spy Client
------------------------
//
// ghc::filesystem - A C++17-like filesystem implementation for
C++11/C++14/C++17/C++20
//
//---------------------------------------------------------------
------------------------
//
// Copyright (c) 2018, Steffen Schümann <s.schuemann@pobox.com>
//
// Permission is hereby granted, free of charge, to any person
obtaining a copy
// of this software and associated documentation files (the
"Software"), to deal
// in the Software without restriction, including without
limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell
// copies of the Software, and to permit persons to whom the
Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE
// 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
#ifndef GHC_OS_DETECTED
#if defined(__APPLE__) && defined(__MACH__)
#define GHC_OS_MACOS
#elif defined(__linux__)
#define GHC_OS_LINUX
#if defined(__ANDROID__)
#define GHC_OS_ANDROID
#endif
#elif defined(_WIN64)
#define GHC_OS_WINDOWS
#define GHC_OS_WIN64
#elif defined(_WIN32)
#define GHC_OS_WINDOWS
#define GHC_OS_WIN32
#elif defined(__sun) && defined(__SVR4)
#define GHC_OS_SOLARIS
#define GHC_NO_DIRENT_D_TYPE
#elif defined(__CYGWIN__)
#define GHC_OS_CYGWIN
#elif defined(__svr4__)
#define GHC_OS_SYS5R4
#elif defined(BSD)
#define GHC_OS_BSD
#elif defined(__EMSCRIPTEN__)
#define GHC_OS_WEB
#include <wasi/api.h>
#elif defined(__QNX__)
#define GHC_OS_QNX
#define GHC_NO_DIRENT_D_TYPE
#else
#error "Operating system currently not supported!"
#endif
#define GHC_OS_DETECTED
#if (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
#if _MSVC_LANG == 201703L
#define GHC_FILESYSTEM_RUNNING_CPP17
#else
#define GHC_FILESYSTEM_RUNNING_CPP20
#endif
#elif (defined(__cplusplus) && __cplusplus >= 201703L)
#if __cplusplus == 201703L
#define GHC_FILESYSTEM_RUNNING_CPP17
#else
#define GHC_FILESYSTEM_RUNNING_CPP20
#endif
#endif
#endif
#if defined(GHC_FILESYSTEM_IMPLEMENTATION)
#define GHC_EXPAND_IMPL
#define GHC_INLINE
#ifdef GHC_OS_WINDOWS
#ifndef GHC_FS_API
#define GHC_FS_API
#endif
#ifndef GHC_FS_API_CLASS
#define GHC_FS_API_CLASS
#endif
#else
#ifndef GHC_FS_API
#define GHC_FS_API __attribute__((visibility("default")))
#endif
#ifndef GHC_FS_API_CLASS
#define GHC_FS_API_CLASS __attribute__((visibility("default")))
#endif
#endif
#elif defined(GHC_FILESYSTEM_FWD)
#define GHC_INLINE
#ifdef GHC_OS_WINDOWS
#ifndef GHC_FS_API
#define GHC_FS_API extern
#endif
#ifndef GHC_FS_API_CLASS
#define GHC_FS_API_CLASS
#endif
#else
#ifndef GHC_FS_API
#define GHC_FS_API extern
#endif
#ifndef GHC_FS_API_CLASS
#define GHC_FS_API_CLASS
#endif
#endif
#else
#define GHC_EXPAND_IMPL
#define GHC_INLINE inline
#ifndef GHC_FS_API
#define GHC_FS_API
#endif
#ifndef GHC_FS_API_CLASS
#define GHC_FS_API_CLASS
#endif
#endif
#ifdef GHC_EXPAND_IMPL
#ifdef GHC_OS_WINDOWS
#include <windows.h>
// additional includes
#include <shellapi.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <wchar.h>
#include <winioctl.h>
#else
#include <dirent.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#ifdef GHC_OS_ANDROID
#include <android/api-level.h>
#if __ANDROID_API__ < 12
#include <sys/syscall.h>
#endif
#include <sys/vfs.h>
#define statvfs statfs
#else
#include <sys/statvfs.h>
#endif
#ifdef GHC_OS_CYGWIN
#include <strings.h>
#endif
#if !defined(__ANDROID__) || __ANDROID_API__ >= 26
#include <langinfo.h>
#endif
#endif
#ifdef GHC_OS_MACOS
#include <Availability.h>
#endif
#include <algorithm>
#include <cctype>
#include <chrono>
#include <clocale>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <functional>
#include <memory>
#include <stack>
#include <stdexcept>
#include <string>
#include <system_error>
#include <type_traits>
#include <utility>
#include <vector>
#else // GHC_EXPAND_IMPL
#if defined(GHC_HAS_STD_STRING_VIEW)
#include <string_view>
#elif defined(GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW)
#include <experimental/string_view>
#endif
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - -
// Behaviour Switches (see README.md, should match the config in
test/filesystem_test.cpp):
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - -
// Enforce C++17 API where possible when compiling for C++20,
handles the following cases:
// * fs::path::u8string() returns std::string instead of
std::u8string
// #define GHC_FILESYSTEM_ENFORCE_CPP17_API
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - -
// LWG #2682 disables the since then invalid use of the copy
option create_symlinks on directories
// configure LWG conformance ()
#define LWG_2682_BEHAVIOUR
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - -
// LWG #2395 makes crate_directory/create_directories not emit an
error if there is a regular
// file with that name, it is superseded by P1164R1, so only
activate if really needed
// #define LWG_2935_BEHAVIOUR
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - -
// LWG #2936 enables new element wise (more expensive) path
comparison
// * if this-
>root_name().native().compare(p.root_name().native()) != 0 return
result
// * 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()
// 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
// version defaults to std::wstring storage backend. Still all
std::string will be interpreted
// 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 (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,
// instead of replacing them with the unicode replacement
character (U+FFFD).
// #define GHC_RAISE_UNICODE_ERRORS
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - -
// Automatic prefix windows path with "\\?\" if they would break
the MAX_PATH length.
// instead of replacing them with the unicode replacement
character (U+FFFD).
#ifndef GHC_WIN_DISABLE_AUTO_PREFIXES
#define GHC_WIN_AUTO_PREFIX_LONG_PATH
#endif // GHC_WIN_DISABLE_AUTO_PREFIXES
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - -
namespace ghc {
namespace filesystem {
#if defined(GHC_HAS_CUSTOM_STRING_VIEW)
#define GHC_WITH_STRING_VIEW
#elif defined(GHC_HAS_STD_STRING_VIEW)
#define GHC_WITH_STRING_VIEW
using std::basic_string_view;
#elif defined(GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW)
#define GHC_WITH_STRING_VIEW
using std::experimental::basic_string_view;
#endif
#ifdef GHC_OS_WINDOWS
class path;
namespace detail {
bool has_executable_extension(const path& p);
}
#endif
// [fs.path.assign] assignments
path& operator=(const path& p);
path& operator=(path&& p) noexcept;
path& operator=(string_type&& source);
path& assign(string_type&& source);
template <class Source>
path& operator=(const Source& source);
template <class Source>
path& assign(const Source& source);
template <class InputIterator>
path& assign(InputIterator first, InputIterator last);
// [fs.path.append] appends
path& operator/=(const path& p);
template <class Source>
path& operator/=(const Source& source);
template <class Source>
path& append(const Source& source);
template <class InputIterator>
path& append(InputIterator first, InputIterator last);
// [fs.path.concat] concatenation
path& operator+=(const path& x);
path& operator+=(const string_type& x);
#ifdef GHC_WITH_STRING_VIEW
path& operator+=(basic_string_view<value_type> x);
#endif
path& operator+=(const value_type* x);
path& operator+=(value_type x);
template <class Source>
path_from_string<Source>& operator+=(const Source& x);
template <class EcharT>
path_type_EcharT<EcharT>& operator+=(EcharT x);
template <class Source>
path& concat(const Source& x);
template <class InputIterator>
path& concat(InputIterator first, InputIterator last);
// [fs.path.modifiers] modifiers
void clear() noexcept;
path& make_preferred();
path& remove_filename();
path& replace_filename(const path& replacement);
path& replace_extension(const path& replacement = path());
void swap(path& rhs) noexcept;
// [fs.path.compare] compare
int compare(const path& p) const noexcept;
int compare(const string_type& s) const;
#ifdef GHC_WITH_STRING_VIEW
int compare(basic_string_view<value_type> s) const;
#endif
int compare(const value_type* s) const;
// [fs.path.decompose] decomposition
path root_name() const;
path root_directory() const;
path root_path() const;
path relative_path() const;
path parent_path() const;
path filename() const;
path stem() const;
path extension() const;
// [fs.path.query] query
bool empty() const noexcept;
bool has_root_name() const;
bool has_root_directory() const;
bool has_root_path() const;
bool has_relative_path() const;
bool has_parent_path() const;
bool has_filename() const;
bool has_stem() const;
bool has_extension() const;
bool is_absolute() const;
bool is_relative() const;
// [fs.path.gen] generation
path lexically_normal() const;
path lexically_relative(const path& base) const;
path lexically_proximate(const path& base) const;
// [fs.path.itr] iterators
class iterator;
using const_iterator = iterator;
iterator begin() const;
iterator end() const;
private:
using impl_value_type = value_type;
using impl_string_type = std::basic_string<impl_value_type>;
friend class directory_iterator;
void append_name(const value_type* name);
static constexpr impl_value_type generic_separator = '/';
template <typename InputIterator>
class input_iterator_range
{
public:
typedef InputIterator iterator;
typedef InputIterator const_iterator;
typedef typename InputIterator::difference_type
difference_type;
iterator();
iterator(const path& p, const
impl_string_type::const_iterator& pos);
iterator& operator++();
iterator operator++(int);
iterator& operator--();
iterator operator--(int);
bool operator==(const iterator& other) const;
bool operator!=(const iterator& other) const;
reference operator*() const;
pointer operator->() const;
private:
friend class path;
impl_string_type::const_iterator increment(const
impl_string_type::const_iterator& pos) const;
impl_string_type::const_iterator decrement(const
impl_string_type::const_iterator& pos) const;
void updateCurrent();
impl_string_type::const_iterator _first;
impl_string_type::const_iterator _last;
impl_string_type::const_iterator _prefix;
impl_string_type::const_iterator _root;
impl_string_type::const_iterator _iter;
path _current;
};
struct space_info
{
uintmax_t capacity;
uintmax_t free;
uintmax_t available;
};
// [fs.enum] enumerations
// [fs.enum.file_type]
enum class file_type {
none,
not_found,
regular,
directory,
symlink,
block,
character,
fifo,
socket,
unknown,
};
// [fs.enum.perms]
enum class perms : uint16_t {
none = 0,
owner_read = 0400,
owner_write = 0200,
owner_exec = 0100,
owner_all = 0700,
group_read = 040,
group_write = 020,
group_exec = 010,
group_all = 070,
others_read = 04,
others_write = 02,
others_exec = 01,
others_all = 07,
all = 0777,
set_uid = 04000,
set_gid = 02000,
sticky_bit = 01000,
mask = 07777,
unknown = 0xffff
};
// [fs.enum.perm.opts]
enum class perm_options : uint16_t {
replace = 3,
add = 1,
remove = 2,
nofollow = 4,
};
// [fs.enum.copy.opts]
enum class copy_options : uint16_t {
none = 0,
skip_existing = 1,
overwrite_existing = 2,
update_existing = 4,
recursive = 8,
copy_symlinks = 0x10,
skip_symlinks = 0x20,
directories_only = 0x40,
create_symlinks = 0x80,
#ifndef GHC_OS_WEB
create_hard_links = 0x100
#endif
};
// [fs.enum.dir.opts]
enum class directory_options : uint16_t {
none = 0,
follow_directory_symlink = 1,
skip_permission_denied = 2,
};
using file_time_type =
std::chrono::time_point<std::chrono::system_clock>;
// assignments:
directory_entry& operator=(const directory_entry&) = default;
directory_entry& operator=(directory_entry&&) noexcept =
default;
// [fs.dir.entry.mods] modifiers
#ifdef GHC_WITH_EXCEPTIONS
void assign(const path& p);
void replace_filename(const path& p);
void refresh();
#endif
void assign(const path& p, std::error_code& ec);
void replace_filename(const path& p, std::error_code& ec);
void refresh(std::error_code& ec) noexcept;
// [fs.dir.entry.obs] observers
const filesystem::path& path() const noexcept;
operator const filesystem::path&() const noexcept;
#ifdef GHC_WITH_EXCEPTIONS
bool exists() const;
bool is_block_file() const;
bool is_character_file() const;
bool is_directory() const;
bool is_fifo() const;
bool is_other() const;
bool is_regular_file() const;
bool is_socket() const;
bool is_symlink() const;
uintmax_t file_size() const;
file_time_type last_write_time() const;
file_status status() const;
file_status symlink_status() const;
#endif
bool exists(std::error_code& ec) const noexcept;
bool is_block_file(std::error_code& ec) const noexcept;
bool is_character_file(std::error_code& ec) const noexcept;
bool is_directory(std::error_code& ec) const noexcept;
bool is_fifo(std::error_code& ec) const noexcept;
bool is_other(std::error_code& ec) const noexcept;
bool is_regular_file(std::error_code& ec) const noexcept;
bool is_socket(std::error_code& ec) const noexcept;
bool is_symlink(std::error_code& ec) const noexcept;
uintmax_t file_size(std::error_code& ec) const noexcept;
file_time_type last_write_time(std::error_code& ec) const
noexcept;
file_status status(std::error_code& ec) const noexcept;
file_status symlink_status(std::error_code& ec) const
noexcept;
#ifndef GHC_OS_WEB
#ifdef GHC_WITH_EXCEPTIONS
uintmax_t hard_link_count() const;
#endif
uintmax_t hard_link_count(std::error_code& ec) const
noexcept;
#endif
#ifdef GHC_HAS_THREEWAY_COMP
std::strong_ordering operator<=>(const directory_entry& rhs)
const noexcept;
#endif
bool operator<(const directory_entry& rhs) const noexcept;
bool operator==(const directory_entry& rhs) const noexcept;
bool operator!=(const directory_entry& rhs) const noexcept;
bool operator<=(const directory_entry& rhs) const noexcept;
bool operator>(const directory_entry& rhs) const noexcept;
bool operator>=(const directory_entry& rhs) const noexcept;
private:
friend class directory_iterator;
#ifdef GHC_WITH_EXCEPTIONS
file_type status_file_type() const;
#endif
file_type status_file_type(std::error_code& ec) const
noexcept;
filesystem::path _path;
file_status _status;
file_status _symlink_status;
uintmax_t _file_size = static_cast<uintmax_t>(-1);
#ifndef GHC_OS_WINDOWS
uintmax_t _hard_link_count = static_cast<uintmax_t>(-1);
#endif
time_t _last_write_time = 0;
};
private:
explicit proxy(const directory_entry& dir_entry)
: _dir_entry(dir_entry)
{
}
friend class directory_iterator;
friend class recursive_directory_iterator;
directory_entry _dir_entry;
};
using iterator_category = std::input_iterator_tag;
using value_type = directory_entry;
using difference_type = std::ptrdiff_t;
using pointer = const directory_entry*;
using reference = const directory_entry&;
private:
friend class recursive_directory_iterator;
class impl;
std::shared_ptr<impl> _impl;
};
// [fs.rec.dir.itr.members] observers
directory_options options() const;
int depth() const;
bool recursion_pending() const;
// [fs.rec.dir.itr.members] modifiers
recursive_directory_iterator&
recursive_directory_iterator& operator=(const
recursive_directory_iterator& rhs);
recursive_directory_iterator&
operator=(recursive_directory_iterator&& rhs) noexcept;
#ifdef GHC_WITH_EXCEPTIONS
recursive_directory_iterator& operator++();
#endif
recursive_directory_iterator& increment(std::error_code& ec)
noexcept;
#ifdef GHC_WITH_EXCEPTIONS
void pop();
#endif
void pop(std::error_code& ec);
void disable_recursion_pending();
private:
struct recursive_directory_iterator_impl
{
directory_options _options;
bool _recursion_pending;
std::stack<directory_iterator> _dir_iter_stack;
recursive_directory_iterator_impl(directory_options
options, bool recursion_pending)
: _options(options)
, _recursion_pending(recursion_pending)
{
}
};
std::shared_ptr<recursive_directory_iterator_impl> _impl;
};
#ifndef GHC_OS_WEB
#ifdef GHC_WITH_EXCEPTIONS
GHC_FS_API void create_hard_link(const path& to, const path&
new_hard_link);
GHC_FS_API uintmax_t hard_link_count(const path& p);
#endif
GHC_FS_API void create_hard_link(const path& to, const path&
new_hard_link, std::error_code& ec) noexcept;
GHC_FS_API uintmax_t hard_link_count(const path& p,
std::error_code& ec) noexcept;
#endif
private:
int _argc;
char** _argv;
int& _refargc;
char**& _refargv;
bool _isvalid;
#ifdef GHC_OS_WINDOWS
std::vector<std::string> _args;
std::vector<char*> _argp;
#endif
};
//---------------------------------------------------------------
----------------------------------
// Implementation
//---------------------------------------------------------------
----------------------------------
namespace detail {
enum utf8_states_t { S_STRT = 0, S_RJCT = 8 };
GHC_FS_API void appendUTF8(std::string& str, uint32_t unicode);
GHC_FS_API bool is_surrogate(uint32_t c);
GHC_FS_API bool is_high_surrogate(uint32_t c);
GHC_FS_API bool is_low_surrogate(uint32_t c);
GHC_FS_API unsigned consumeUtf8Fragment(const unsigned state,
const uint8_t fragment, uint32_t& codepoint);
enum class portable_error {
none = 0,
exists,
not_found,
not_supported,
not_implemented,
invalid_argument,
is_a_directory,
};
GHC_FS_API std::error_code make_error_code(portable_error err);
#ifdef GHC_OS_WINDOWS
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);
#endif
} // namespace detail
namespace detail {
#ifdef GHC_EXPAND_IMPL
#ifdef GHC_OS_WINDOWS
GHC_INLINE std::error_code make_system_error(uint32_t err)
{
return std::error_code(err ? static_cast<int>(err) :
static_cast<int>(::GetLastError()), std::system_category());
}
#else
GHC_INLINE std::error_code make_system_error(int err)
{
return std::error_code(err ? err : errno,
std::system_category());
}
#endif
#endif // GHC_EXPAND_IMPL
#ifdef GHC_EXPAND_IMPL
namespace detail {
#endif
namespace detail {
#ifdef GHC_USE_WCHAR_T
template <class StringType, class WString, typename
std::enable_if<path::_is_basic_string<WString>::value &&
(sizeof(typename WString::value_type) == 2) && (sizeof(typename
StringType::value_type) == 1), bool>::type = false>
inline StringType fromWChar(const WString& wString, const
typename StringType::allocator_type& alloc = typename
StringType::allocator_type())
{
auto temp = toUtf8(wString);
return StringType(temp.begin(), temp.end(), alloc);
}
} // namespace detail
#ifdef GHC_EXPAND_IMPL
namespace detail {
} // namespace detail
#endif // GHC_EXPAND_IMPL
template <class Source, typename>
inline path::path(const Source& source, format fmt)
#ifdef GHC_USE_WCHAR_T
: _path(detail::toWChar(source))
#else
: _path(detail::toUtf8(source))
#endif
{
postprocess_path_with_format(fmt);
}
#ifdef GHC_EXPAND_IMPL
namespace detail {
#ifdef GHC_OS_WINDOWS
using CreateSymbolicLinkW_fp = BOOLEAN(WINAPI*)(LPCWSTR, LPCWSTR,
DWORD);
using CreateHardLinkW_fp = BOOLEAN(WINAPI*)(LPCWSTR, LPCWSTR,
LPSECURITY_ATTRIBUTES);
#else
GHC_INLINE void create_symlink(const path& target_name, const
path& new_symlink, bool, std::error_code& ec)
{
if (::symlink(target_name.c_str(), new_symlink.c_str()) != 0)
{
ec = detail::make_system_error();
}
}
#ifndef GHC_OS_WEB
GHC_INLINE void create_hardlink(const path& target_name, const
path& new_hardlink, std::error_code& ec)
{
if (::link(target_name.c_str(), new_hardlink.c_str()) != 0) {
ec = detail::make_system_error();
}
}
#endif
#endif
#ifdef GHC_OS_WINDOWS
#ifndef REPARSE_DATA_BUFFER_HEADER_SIZE
typedef struct _REPARSE_DATA_BUFFER
{
ULONG ReparseTag;
USHORT ReparseDataLength;
USHORT Reserved;
union
{
struct
{
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
ULONG Flags;
WCHAR PathBuffer[1];
} SymbolicLinkReparseBuffer;
struct
{
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
WCHAR PathBuffer[1];
} MountPointReparseBuffer;
struct
{
UCHAR DataBuffer[1];
} GenericReparseBuffer;
} DUMMYUNIONNAME;
} REPARSE_DATA_BUFFER;
#ifndef MAXIMUM_REPARSE_DATA_BUFFER_SIZE
#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE (16 * 1024)
#endif
#endif
GHC_INLINE std::shared_ptr<REPARSE_DATA_BUFFER>
getReparseData(const path& p, std::error_code& ec)
{
std::shared_ptr<void> file(CreateFileW(GHC_NATIVEWP(p), 0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0,
OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT |
FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle);
if (file.get() == INVALID_HANDLE_VALUE) {
ec = detail::make_system_error();
return nullptr;
}
std::shared_ptr<REPARSE_DATA_BUFFER>
reparseData((REPARSE_DATA_BUFFER*)std::calloc(1,
MAXIMUM_REPARSE_DATA_BUFFER_SIZE), std::free);
ULONG bufferUsed;
if (DeviceIoControl(file.get(), FSCTL_GET_REPARSE_POINT, 0,
0, reparseData.get(), MAXIMUM_REPARSE_DATA_BUFFER_SIZE,
&bufferUsed, 0)) {
return reparseData;
}
else {
ec = detail::make_system_error();
}
return nullptr;
}
#endif
#ifdef GHC_OS_WINDOWS
GHC_INLINE time_t timeFromFILETIME(const FILETIME& ft)
{
ULARGE_INTEGER ull;
ull.LowPart = ft.dwLowDateTime;
ull.HighPart = ft.dwHighDateTime;
return static_cast<time_t>(ull.QuadPart / 10000000ULL -
11644473600ULL);
}
template <>
GHC_INLINE uintmax_t
hard_links_from_INFO<BY_HANDLE_FILE_INFORMATION>(const
BY_HANDLE_FILE_INFORMATION* info)
{
return info->nNumberOfLinks;
}
template <>
GHC_INLINE DWORD reparse_tag_from_INFO(const WIN32_FIND_DATAW*
info)
{
return info->dwReserved0;
}
#endif
GHC_INLINE bool is_not_found_error(std::error_code& ec)
{
#ifdef GHC_OS_WINDOWS
return ec.value() == ERROR_FILE_NOT_FOUND || ec.value() ==
ERROR_PATH_NOT_FOUND || ec.value() == ERROR_INVALID_NAME;
#else
return ec.value() == ENOENT || ec.value() == ENOTDIR;
#endif
}