1*89c4ff92SAndroid Build Coastguard Worker //---------------------------------------------------------------------------------------
2*89c4ff92SAndroid Build Coastguard Worker //
3*89c4ff92SAndroid Build Coastguard Worker // ghc::filesystem - A C++17-like filesystem implementation for C++11/C++14/C++17
4*89c4ff92SAndroid Build Coastguard Worker //
5*89c4ff92SAndroid Build Coastguard Worker //---------------------------------------------------------------------------------------
6*89c4ff92SAndroid Build Coastguard Worker //
7*89c4ff92SAndroid Build Coastguard Worker // Copyright (c) 2018, Steffen Schümann <[email protected]>
8*89c4ff92SAndroid Build Coastguard Worker //
9*89c4ff92SAndroid Build Coastguard Worker // SPDX-License-Identifier: MIT
10*89c4ff92SAndroid Build Coastguard Worker //
11*89c4ff92SAndroid Build Coastguard Worker // Permission is hereby granted, free of charge, to any person obtaining a copy
12*89c4ff92SAndroid Build Coastguard Worker // of this software and associated documentation files (the "Software"), to deal
13*89c4ff92SAndroid Build Coastguard Worker // in the Software without restriction, including without limitation the rights
14*89c4ff92SAndroid Build Coastguard Worker // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15*89c4ff92SAndroid Build Coastguard Worker // copies of the Software, and to permit persons to whom the Software is
16*89c4ff92SAndroid Build Coastguard Worker // furnished to do so, subject to the following conditions:
17*89c4ff92SAndroid Build Coastguard Worker //
18*89c4ff92SAndroid Build Coastguard Worker // The above copyright notice and this permission notice shall be included in all
19*89c4ff92SAndroid Build Coastguard Worker // copies or substantial portions of the Software.
20*89c4ff92SAndroid Build Coastguard Worker //
21*89c4ff92SAndroid Build Coastguard Worker // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22*89c4ff92SAndroid Build Coastguard Worker // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23*89c4ff92SAndroid Build Coastguard Worker // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24*89c4ff92SAndroid Build Coastguard Worker // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25*89c4ff92SAndroid Build Coastguard Worker // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26*89c4ff92SAndroid Build Coastguard Worker // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27*89c4ff92SAndroid Build Coastguard Worker // SOFTWARE.
28*89c4ff92SAndroid Build Coastguard Worker //
29*89c4ff92SAndroid Build Coastguard Worker //---------------------------------------------------------------------------------------
30*89c4ff92SAndroid Build Coastguard Worker //
31*89c4ff92SAndroid Build Coastguard Worker // To dynamically select std::filesystem where available, you could use:
32*89c4ff92SAndroid Build Coastguard Worker //
33*89c4ff92SAndroid Build Coastguard Worker // #if defined(__cplusplus) && __cplusplus >= 201703L && defined(__has_include) && __has_include(<filesystem>)
34*89c4ff92SAndroid Build Coastguard Worker // #include <filesystem>
35*89c4ff92SAndroid Build Coastguard Worker // namespace fs = std::filesystem;
36*89c4ff92SAndroid Build Coastguard Worker // #else
37*89c4ff92SAndroid Build Coastguard Worker // #include <ghc/filesystem.hpp>
38*89c4ff92SAndroid Build Coastguard Worker // namespace fs = ghc::filesystem;
39*89c4ff92SAndroid Build Coastguard Worker // #endif
40*89c4ff92SAndroid Build Coastguard Worker //
41*89c4ff92SAndroid Build Coastguard Worker //---------------------------------------------------------------------------------------
42*89c4ff92SAndroid Build Coastguard Worker #ifndef GHC_FILESYSTEM_H
43*89c4ff92SAndroid Build Coastguard Worker #define GHC_FILESYSTEM_H
44*89c4ff92SAndroid Build Coastguard Worker
45*89c4ff92SAndroid Build Coastguard Worker // #define BSD manifest constant only in
46*89c4ff92SAndroid Build Coastguard Worker // sys/param.h
47*89c4ff92SAndroid Build Coastguard Worker #ifndef _WIN32
48*89c4ff92SAndroid Build Coastguard Worker #include <sys/param.h>
49*89c4ff92SAndroid Build Coastguard Worker #endif
50*89c4ff92SAndroid Build Coastguard Worker
51*89c4ff92SAndroid Build Coastguard Worker #ifndef GHC_OS_DETECTED
52*89c4ff92SAndroid Build Coastguard Worker #if defined(__APPLE__) && defined(__MACH__)
53*89c4ff92SAndroid Build Coastguard Worker #define GHC_OS_MACOS
54*89c4ff92SAndroid Build Coastguard Worker #elif defined(__linux__)
55*89c4ff92SAndroid Build Coastguard Worker #define GHC_OS_LINUX
56*89c4ff92SAndroid Build Coastguard Worker #if defined(__ANDROID__)
57*89c4ff92SAndroid Build Coastguard Worker #define GHC_OS_ANDROID
58*89c4ff92SAndroid Build Coastguard Worker #endif
59*89c4ff92SAndroid Build Coastguard Worker #elif defined(_WIN64)
60*89c4ff92SAndroid Build Coastguard Worker #define GHC_OS_WINDOWS
61*89c4ff92SAndroid Build Coastguard Worker #define GHC_OS_WIN64
62*89c4ff92SAndroid Build Coastguard Worker #elif defined(_WIN32)
63*89c4ff92SAndroid Build Coastguard Worker #define GHC_OS_WINDOWS
64*89c4ff92SAndroid Build Coastguard Worker #define GHC_OS_WIN32
65*89c4ff92SAndroid Build Coastguard Worker #elif defined(__svr4__)
66*89c4ff92SAndroid Build Coastguard Worker #define GHC_OS_SYS5R4
67*89c4ff92SAndroid Build Coastguard Worker #elif defined(BSD)
68*89c4ff92SAndroid Build Coastguard Worker #define GHC_OS_BSD
69*89c4ff92SAndroid Build Coastguard Worker #else
70*89c4ff92SAndroid Build Coastguard Worker #error "Operating system currently not supported!"
71*89c4ff92SAndroid Build Coastguard Worker #endif
72*89c4ff92SAndroid Build Coastguard Worker #define GHC_OS_DETECTED
73*89c4ff92SAndroid Build Coastguard Worker #endif
74*89c4ff92SAndroid Build Coastguard Worker
75*89c4ff92SAndroid Build Coastguard Worker #if defined(GHC_FILESYSTEM_IMPLEMENTATION)
76*89c4ff92SAndroid Build Coastguard Worker #define GHC_EXPAND_IMPL
77*89c4ff92SAndroid Build Coastguard Worker #define GHC_INLINE
78*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
79*89c4ff92SAndroid Build Coastguard Worker #define GHC_FS_API
80*89c4ff92SAndroid Build Coastguard Worker #define GHC_FS_API_CLASS
81*89c4ff92SAndroid Build Coastguard Worker #else
82*89c4ff92SAndroid Build Coastguard Worker #define GHC_FS_API __attribute__((visibility("default")))
83*89c4ff92SAndroid Build Coastguard Worker #define GHC_FS_API_CLASS __attribute__((visibility("default")))
84*89c4ff92SAndroid Build Coastguard Worker #endif
85*89c4ff92SAndroid Build Coastguard Worker #elif defined(GHC_FILESYSTEM_FWD)
86*89c4ff92SAndroid Build Coastguard Worker #define GHC_INLINE
87*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
88*89c4ff92SAndroid Build Coastguard Worker #define GHC_FS_API extern
89*89c4ff92SAndroid Build Coastguard Worker #define GHC_FS_API_CLASS
90*89c4ff92SAndroid Build Coastguard Worker #else
91*89c4ff92SAndroid Build Coastguard Worker #define GHC_FS_API extern
92*89c4ff92SAndroid Build Coastguard Worker #define GHC_FS_API_CLASS
93*89c4ff92SAndroid Build Coastguard Worker #endif
94*89c4ff92SAndroid Build Coastguard Worker #else
95*89c4ff92SAndroid Build Coastguard Worker #define GHC_EXPAND_IMPL
96*89c4ff92SAndroid Build Coastguard Worker #define GHC_INLINE inline
97*89c4ff92SAndroid Build Coastguard Worker #define GHC_FS_API
98*89c4ff92SAndroid Build Coastguard Worker #define GHC_FS_API_CLASS
99*89c4ff92SAndroid Build Coastguard Worker #endif
100*89c4ff92SAndroid Build Coastguard Worker
101*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_EXPAND_IMPL
102*89c4ff92SAndroid Build Coastguard Worker
103*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
104*89c4ff92SAndroid Build Coastguard Worker #include <windows.h>
105*89c4ff92SAndroid Build Coastguard Worker // additional includes
106*89c4ff92SAndroid Build Coastguard Worker #include <shellapi.h>
107*89c4ff92SAndroid Build Coastguard Worker #include <sys/stat.h>
108*89c4ff92SAndroid Build Coastguard Worker #include <sys/types.h>
109*89c4ff92SAndroid Build Coastguard Worker #include <wchar.h>
110*89c4ff92SAndroid Build Coastguard Worker #include <winioctl.h>
111*89c4ff92SAndroid Build Coastguard Worker #else
112*89c4ff92SAndroid Build Coastguard Worker #include <dirent.h>
113*89c4ff92SAndroid Build Coastguard Worker #include <fcntl.h>
114*89c4ff92SAndroid Build Coastguard Worker #include <langinfo.h>
115*89c4ff92SAndroid Build Coastguard Worker #include <sys/param.h>
116*89c4ff92SAndroid Build Coastguard Worker #include <sys/stat.h>
117*89c4ff92SAndroid Build Coastguard Worker #include <sys/statvfs.h>
118*89c4ff92SAndroid Build Coastguard Worker #include <sys/time.h>
119*89c4ff92SAndroid Build Coastguard Worker #include <sys/types.h>
120*89c4ff92SAndroid Build Coastguard Worker #include <unistd.h>
121*89c4ff92SAndroid Build Coastguard Worker #include <limits.h>
122*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_ANDROID
123*89c4ff92SAndroid Build Coastguard Worker #include <android/api-level.h>
124*89c4ff92SAndroid Build Coastguard Worker #endif
125*89c4ff92SAndroid Build Coastguard Worker #endif
126*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_MACOS
127*89c4ff92SAndroid Build Coastguard Worker #include <Availability.h>
128*89c4ff92SAndroid Build Coastguard Worker #endif
129*89c4ff92SAndroid Build Coastguard Worker
130*89c4ff92SAndroid Build Coastguard Worker #include <algorithm>
131*89c4ff92SAndroid Build Coastguard Worker #include <cctype>
132*89c4ff92SAndroid Build Coastguard Worker #include <chrono>
133*89c4ff92SAndroid Build Coastguard Worker #include <clocale>
134*89c4ff92SAndroid Build Coastguard Worker #include <cstdlib>
135*89c4ff92SAndroid Build Coastguard Worker #include <cstring>
136*89c4ff92SAndroid Build Coastguard Worker #include <fstream>
137*89c4ff92SAndroid Build Coastguard Worker #include <functional>
138*89c4ff92SAndroid Build Coastguard Worker #include <memory>
139*89c4ff92SAndroid Build Coastguard Worker #include <stack>
140*89c4ff92SAndroid Build Coastguard Worker #include <stdexcept>
141*89c4ff92SAndroid Build Coastguard Worker #include <string>
142*89c4ff92SAndroid Build Coastguard Worker #include <system_error>
143*89c4ff92SAndroid Build Coastguard Worker #include <type_traits>
144*89c4ff92SAndroid Build Coastguard Worker #include <utility>
145*89c4ff92SAndroid Build Coastguard Worker #include <vector>
146*89c4ff92SAndroid Build Coastguard Worker
147*89c4ff92SAndroid Build Coastguard Worker #else // GHC_EXPAND_IMPL
148*89c4ff92SAndroid Build Coastguard Worker #include <chrono>
149*89c4ff92SAndroid Build Coastguard Worker #include <fstream>
150*89c4ff92SAndroid Build Coastguard Worker #include <memory>
151*89c4ff92SAndroid Build Coastguard Worker #include <stack>
152*89c4ff92SAndroid Build Coastguard Worker #include <stdexcept>
153*89c4ff92SAndroid Build Coastguard Worker #include <string>
154*89c4ff92SAndroid Build Coastguard Worker #include <system_error>
155*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
156*89c4ff92SAndroid Build Coastguard Worker #include <vector>
157*89c4ff92SAndroid Build Coastguard Worker #endif
158*89c4ff92SAndroid Build Coastguard Worker #endif // GHC_EXPAND_IMPL
159*89c4ff92SAndroid Build Coastguard Worker
160*89c4ff92SAndroid Build Coastguard Worker //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
161*89c4ff92SAndroid Build Coastguard Worker // Behaviour Switches (see README.md, should match the config in test/filesystem_test.cpp):
162*89c4ff92SAndroid Build Coastguard Worker //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
163*89c4ff92SAndroid Build Coastguard Worker // LWG #2682 disables the since then invalid use of the copy option create_symlinks on directories
164*89c4ff92SAndroid Build Coastguard Worker // configure LWG conformance ()
165*89c4ff92SAndroid Build Coastguard Worker #define LWG_2682_BEHAVIOUR
166*89c4ff92SAndroid Build Coastguard Worker //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
167*89c4ff92SAndroid Build Coastguard Worker // LWG #2395 makes crate_directory/create_directories not emit an error if there is a regular
168*89c4ff92SAndroid Build Coastguard Worker // file with that name, it is superceded by P1164R1, so only activate if really needed
169*89c4ff92SAndroid Build Coastguard Worker // #define LWG_2935_BEHAVIOUR
170*89c4ff92SAndroid Build Coastguard Worker //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
171*89c4ff92SAndroid Build Coastguard Worker // LWG #2937 enforces that fs::equivalent emits an error, if !fs::exists(p1)||!exists(p2)
172*89c4ff92SAndroid Build Coastguard Worker #define LWG_2937_BEHAVIOUR
173*89c4ff92SAndroid Build Coastguard Worker //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
174*89c4ff92SAndroid Build Coastguard Worker // UTF8-Everywhere is the original behaviour of ghc::filesystem. With this define you can
175*89c4ff92SAndroid Build Coastguard Worker // enable the more standard conforming implementation option that uses wstring on Windows
176*89c4ff92SAndroid Build Coastguard Worker // as ghc::filesystem::string_type.
177*89c4ff92SAndroid Build Coastguard Worker // #define GHC_WIN_WSTRING_STRING_TYPE
178*89c4ff92SAndroid Build Coastguard Worker //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
179*89c4ff92SAndroid Build Coastguard Worker // Raise errors/exceptions when invalid unicode codepoints or UTF-8 sequences are found,
180*89c4ff92SAndroid Build Coastguard Worker // instead of replacing them with the unicode replacement character (U+FFFD).
181*89c4ff92SAndroid Build Coastguard Worker // #define GHC_RAISE_UNICODE_ERRORS
182*89c4ff92SAndroid Build Coastguard Worker //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
183*89c4ff92SAndroid Build Coastguard Worker
184*89c4ff92SAndroid Build Coastguard Worker // ghc::filesystem version in decimal (major * 10000 + minor * 100 + patch)
185*89c4ff92SAndroid Build Coastguard Worker #define GHC_FILESYSTEM_VERSION 10302L
186*89c4ff92SAndroid Build Coastguard Worker
187*89c4ff92SAndroid Build Coastguard Worker namespace ghc {
188*89c4ff92SAndroid Build Coastguard Worker namespace filesystem {
189*89c4ff92SAndroid Build Coastguard Worker
190*89c4ff92SAndroid Build Coastguard Worker // temporary existing exception type for yet unimplemented parts
191*89c4ff92SAndroid Build Coastguard Worker class GHC_FS_API_CLASS not_implemented_exception : public std::logic_error
192*89c4ff92SAndroid Build Coastguard Worker {
193*89c4ff92SAndroid Build Coastguard Worker public:
not_implemented_exception()194*89c4ff92SAndroid Build Coastguard Worker not_implemented_exception()
195*89c4ff92SAndroid Build Coastguard Worker : std::logic_error("function not implemented yet.")
196*89c4ff92SAndroid Build Coastguard Worker {
197*89c4ff92SAndroid Build Coastguard Worker }
198*89c4ff92SAndroid Build Coastguard Worker };
199*89c4ff92SAndroid Build Coastguard Worker
200*89c4ff92SAndroid Build Coastguard Worker template<typename char_type>
201*89c4ff92SAndroid Build Coastguard Worker class path_helper_base
202*89c4ff92SAndroid Build Coastguard Worker {
203*89c4ff92SAndroid Build Coastguard Worker public:
204*89c4ff92SAndroid Build Coastguard Worker using value_type = char_type;
205*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
206*89c4ff92SAndroid Build Coastguard Worker static constexpr value_type preferred_separator = '\\';
207*89c4ff92SAndroid Build Coastguard Worker #else
208*89c4ff92SAndroid Build Coastguard Worker static constexpr value_type preferred_separator = '/';
209*89c4ff92SAndroid Build Coastguard Worker #endif
210*89c4ff92SAndroid Build Coastguard Worker };
211*89c4ff92SAndroid Build Coastguard Worker
212*89c4ff92SAndroid Build Coastguard Worker #if __cplusplus < 201703L
213*89c4ff92SAndroid Build Coastguard Worker template <typename char_type>
214*89c4ff92SAndroid Build Coastguard Worker constexpr char_type path_helper_base<char_type>::preferred_separator;
215*89c4ff92SAndroid Build Coastguard Worker #endif
216*89c4ff92SAndroid Build Coastguard Worker
217*89c4ff92SAndroid Build Coastguard Worker // 30.10.8 class path
218*89c4ff92SAndroid Build Coastguard Worker class GHC_FS_API_CLASS path
219*89c4ff92SAndroid Build Coastguard Worker #if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_WSTRING_STRING_TYPE)
220*89c4ff92SAndroid Build Coastguard Worker #define GHC_USE_WCHAR_T
221*89c4ff92SAndroid Build Coastguard Worker : private path_helper_base<std::wstring::value_type>
222*89c4ff92SAndroid Build Coastguard Worker {
223*89c4ff92SAndroid Build Coastguard Worker public:
224*89c4ff92SAndroid Build Coastguard Worker using path_helper_base<std::wstring::value_type>::value_type;
225*89c4ff92SAndroid Build Coastguard Worker #else
226*89c4ff92SAndroid Build Coastguard Worker : private path_helper_base<std::string::value_type>
227*89c4ff92SAndroid Build Coastguard Worker {
228*89c4ff92SAndroid Build Coastguard Worker public:
229*89c4ff92SAndroid Build Coastguard Worker using path_helper_base<std::string::value_type>::value_type;
230*89c4ff92SAndroid Build Coastguard Worker #endif
231*89c4ff92SAndroid Build Coastguard Worker using string_type = std::basic_string<value_type>;
232*89c4ff92SAndroid Build Coastguard Worker using path_helper_base<value_type>::preferred_separator;
233*89c4ff92SAndroid Build Coastguard Worker
234*89c4ff92SAndroid Build Coastguard Worker // 30.10.10.1 enumeration format
235*89c4ff92SAndroid Build Coastguard Worker /// The path format in wich the constructor argument is given.
236*89c4ff92SAndroid Build Coastguard Worker enum format {
237*89c4ff92SAndroid Build Coastguard Worker generic_format, ///< The generic format, internally used by
238*89c4ff92SAndroid Build Coastguard Worker ///< ghc::filesystem::path with slashes
239*89c4ff92SAndroid Build Coastguard Worker native_format, ///< The format native to the current platform this code
240*89c4ff92SAndroid Build Coastguard Worker ///< is build for
241*89c4ff92SAndroid Build Coastguard Worker auto_format, ///< Try to auto-detect the format, fallback to native
242*89c4ff92SAndroid Build Coastguard Worker };
243*89c4ff92SAndroid Build Coastguard Worker
244*89c4ff92SAndroid Build Coastguard Worker template <class T>
245*89c4ff92SAndroid Build Coastguard Worker struct _is_basic_string : std::false_type
246*89c4ff92SAndroid Build Coastguard Worker {
247*89c4ff92SAndroid Build Coastguard Worker };
248*89c4ff92SAndroid Build Coastguard Worker template <class CharT, class Traits, class Alloc>
249*89c4ff92SAndroid Build Coastguard Worker struct _is_basic_string<std::basic_string<CharT, Traits, Alloc>> : std::true_type
250*89c4ff92SAndroid Build Coastguard Worker {
251*89c4ff92SAndroid Build Coastguard Worker };
252*89c4ff92SAndroid Build Coastguard Worker #ifdef __cpp_lib_string_view
253*89c4ff92SAndroid Build Coastguard Worker template <class CharT>
254*89c4ff92SAndroid Build Coastguard Worker struct _is_basic_string<std::basic_string_view<CharT>> : std::true_type
255*89c4ff92SAndroid Build Coastguard Worker {
256*89c4ff92SAndroid Build Coastguard Worker };
257*89c4ff92SAndroid Build Coastguard Worker #endif
258*89c4ff92SAndroid Build Coastguard Worker
259*89c4ff92SAndroid Build Coastguard Worker template <typename T1, typename T2 = void>
260*89c4ff92SAndroid Build Coastguard Worker using path_type = typename std::enable_if<!std::is_same<path, T1>::value, path>::type;
261*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_USE_WCHAR_T
262*89c4ff92SAndroid Build Coastguard Worker template <typename T>
263*89c4ff92SAndroid Build Coastguard Worker using path_from_string = typename std::enable_if<_is_basic_string<T>::value || std::is_same<char const*, typename std::decay<T>::type>::value || std::is_same<char*, typename std::decay<T>::type>::value ||
264*89c4ff92SAndroid Build Coastguard Worker std::is_same<wchar_t const*, typename std::decay<T>::type>::value || std::is_same<wchar_t*, typename std::decay<T>::type>::value,
265*89c4ff92SAndroid Build Coastguard Worker path>::type;
266*89c4ff92SAndroid Build Coastguard Worker template <typename T>
267*89c4ff92SAndroid Build Coastguard Worker using path_type_EcharT = typename std::enable_if<std::is_same<T, char>::value || std::is_same<T, char16_t>::value || std::is_same<T, char32_t>::value, path>::type;
268*89c4ff92SAndroid Build Coastguard Worker #else
269*89c4ff92SAndroid Build Coastguard Worker template <typename T>
270*89c4ff92SAndroid Build Coastguard Worker using path_from_string = typename std::enable_if<_is_basic_string<T>::value || std::is_same<char const*, typename std::decay<T>::type>::value || std::is_same<char*, typename std::decay<T>::type>::value, path>::type;
271*89c4ff92SAndroid Build Coastguard Worker template <typename T>
272*89c4ff92SAndroid Build Coastguard Worker using path_type_EcharT = typename std::enable_if<std::is_same<T, char>::value || std::is_same<T, char16_t>::value || std::is_same<T, char32_t>::value || std::is_same<T, wchar_t>::value, path>::type;
273*89c4ff92SAndroid Build Coastguard Worker #endif
274*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.4.1 constructors and destructor
275*89c4ff92SAndroid Build Coastguard Worker path() noexcept;
276*89c4ff92SAndroid Build Coastguard Worker path(const path& p);
277*89c4ff92SAndroid Build Coastguard Worker path(path&& p) noexcept;
278*89c4ff92SAndroid Build Coastguard Worker path(string_type&& source, format fmt = auto_format);
279*89c4ff92SAndroid Build Coastguard Worker template <class Source, typename = path_from_string<Source>>
280*89c4ff92SAndroid Build Coastguard Worker path(const Source& source, format fmt = auto_format);
281*89c4ff92SAndroid Build Coastguard Worker template <class InputIterator>
282*89c4ff92SAndroid Build Coastguard Worker path(InputIterator first, InputIterator last, format fmt = auto_format);
283*89c4ff92SAndroid Build Coastguard Worker template <class Source, typename = path_from_string<Source>>
284*89c4ff92SAndroid Build Coastguard Worker path(const Source& source, const std::locale& loc, format fmt = auto_format);
285*89c4ff92SAndroid Build Coastguard Worker template <class InputIterator>
286*89c4ff92SAndroid Build Coastguard Worker path(InputIterator first, InputIterator last, const std::locale& loc, format fmt = auto_format);
287*89c4ff92SAndroid Build Coastguard Worker ~path();
288*89c4ff92SAndroid Build Coastguard Worker
289*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.4.2 assignments
290*89c4ff92SAndroid Build Coastguard Worker path& operator=(const path& p);
291*89c4ff92SAndroid Build Coastguard Worker path& operator=(path&& p) noexcept;
292*89c4ff92SAndroid Build Coastguard Worker path& operator=(string_type&& source);
293*89c4ff92SAndroid Build Coastguard Worker path& assign(string_type&& source);
294*89c4ff92SAndroid Build Coastguard Worker template <class Source>
295*89c4ff92SAndroid Build Coastguard Worker path& operator=(const Source& source);
296*89c4ff92SAndroid Build Coastguard Worker template <class Source>
297*89c4ff92SAndroid Build Coastguard Worker path& assign(const Source& source);
298*89c4ff92SAndroid Build Coastguard Worker template <class InputIterator>
299*89c4ff92SAndroid Build Coastguard Worker path& assign(InputIterator first, InputIterator last);
300*89c4ff92SAndroid Build Coastguard Worker
301*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.4.3 appends
302*89c4ff92SAndroid Build Coastguard Worker path& operator/=(const path& p);
303*89c4ff92SAndroid Build Coastguard Worker template <class Source>
304*89c4ff92SAndroid Build Coastguard Worker path& operator/=(const Source& source);
305*89c4ff92SAndroid Build Coastguard Worker template <class Source>
306*89c4ff92SAndroid Build Coastguard Worker path& append(const Source& source);
307*89c4ff92SAndroid Build Coastguard Worker template <class InputIterator>
308*89c4ff92SAndroid Build Coastguard Worker path& append(InputIterator first, InputIterator last);
309*89c4ff92SAndroid Build Coastguard Worker
310*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.4.4 concatenation
311*89c4ff92SAndroid Build Coastguard Worker path& operator+=(const path& x);
312*89c4ff92SAndroid Build Coastguard Worker path& operator+=(const string_type& x);
313*89c4ff92SAndroid Build Coastguard Worker #ifdef __cpp_lib_string_view
314*89c4ff92SAndroid Build Coastguard Worker path& operator+=(std::basic_string_view<value_type> x);
315*89c4ff92SAndroid Build Coastguard Worker #endif
316*89c4ff92SAndroid Build Coastguard Worker path& operator+=(const value_type* x);
317*89c4ff92SAndroid Build Coastguard Worker path& operator+=(value_type x);
318*89c4ff92SAndroid Build Coastguard Worker template <class Source>
319*89c4ff92SAndroid Build Coastguard Worker path_from_string<Source>& operator+=(const Source& x);
320*89c4ff92SAndroid Build Coastguard Worker template <class EcharT>
321*89c4ff92SAndroid Build Coastguard Worker path_type_EcharT<EcharT>& operator+=(EcharT x);
322*89c4ff92SAndroid Build Coastguard Worker template <class Source>
323*89c4ff92SAndroid Build Coastguard Worker path& concat(const Source& x);
324*89c4ff92SAndroid Build Coastguard Worker template <class InputIterator>
325*89c4ff92SAndroid Build Coastguard Worker path& concat(InputIterator first, InputIterator last);
326*89c4ff92SAndroid Build Coastguard Worker
327*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.4.5 modifiers
328*89c4ff92SAndroid Build Coastguard Worker void clear() noexcept;
329*89c4ff92SAndroid Build Coastguard Worker path& make_preferred();
330*89c4ff92SAndroid Build Coastguard Worker path& remove_filename();
331*89c4ff92SAndroid Build Coastguard Worker path& replace_filename(const path& replacement);
332*89c4ff92SAndroid Build Coastguard Worker path& replace_extension(const path& replacement = path());
333*89c4ff92SAndroid Build Coastguard Worker void swap(path& rhs) noexcept;
334*89c4ff92SAndroid Build Coastguard Worker
335*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.4.6 native format observers
336*89c4ff92SAndroid Build Coastguard Worker const string_type& native() const; // this implementation doesn't support noexcept for native()
337*89c4ff92SAndroid Build Coastguard Worker const value_type* c_str() const; // this implementation doesn't support noexcept for c_str()
338*89c4ff92SAndroid Build Coastguard Worker operator string_type() const;
339*89c4ff92SAndroid Build Coastguard Worker template <class EcharT, class traits = std::char_traits<EcharT>, class Allocator = std::allocator<EcharT>>
340*89c4ff92SAndroid Build Coastguard Worker std::basic_string<EcharT, traits, Allocator> string(const Allocator& a = Allocator()) const;
341*89c4ff92SAndroid Build Coastguard Worker std::string string() const;
342*89c4ff92SAndroid Build Coastguard Worker std::wstring wstring() const;
343*89c4ff92SAndroid Build Coastguard Worker std::string u8string() const;
344*89c4ff92SAndroid Build Coastguard Worker std::u16string u16string() const;
345*89c4ff92SAndroid Build Coastguard Worker std::u32string u32string() const;
346*89c4ff92SAndroid Build Coastguard Worker
347*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.4.7 generic format observers
348*89c4ff92SAndroid Build Coastguard Worker template <class EcharT, class traits = std::char_traits<EcharT>, class Allocator = std::allocator<EcharT>>
349*89c4ff92SAndroid Build Coastguard Worker std::basic_string<EcharT, traits, Allocator> generic_string(const Allocator& a = Allocator()) const;
350*89c4ff92SAndroid Build Coastguard Worker const std::string& generic_string() const; // this is different from the standard, that returns by value
351*89c4ff92SAndroid Build Coastguard Worker std::wstring generic_wstring() const;
352*89c4ff92SAndroid Build Coastguard Worker std::string generic_u8string() const;
353*89c4ff92SAndroid Build Coastguard Worker std::u16string generic_u16string() const;
354*89c4ff92SAndroid Build Coastguard Worker std::u32string generic_u32string() const;
355*89c4ff92SAndroid Build Coastguard Worker
356*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.4.8 compare
357*89c4ff92SAndroid Build Coastguard Worker int compare(const path& p) const noexcept;
358*89c4ff92SAndroid Build Coastguard Worker int compare(const string_type& s) const;
359*89c4ff92SAndroid Build Coastguard Worker #ifdef __cpp_lib_string_view
360*89c4ff92SAndroid Build Coastguard Worker int compare(std::basic_string_view<value_type> s) const;
361*89c4ff92SAndroid Build Coastguard Worker #endif
362*89c4ff92SAndroid Build Coastguard Worker int compare(const value_type* s) const;
363*89c4ff92SAndroid Build Coastguard Worker
364*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.4.9 decomposition
365*89c4ff92SAndroid Build Coastguard Worker path root_name() const;
366*89c4ff92SAndroid Build Coastguard Worker path root_directory() const;
367*89c4ff92SAndroid Build Coastguard Worker path root_path() const;
368*89c4ff92SAndroid Build Coastguard Worker path relative_path() const;
369*89c4ff92SAndroid Build Coastguard Worker path parent_path() const;
370*89c4ff92SAndroid Build Coastguard Worker path filename() const;
371*89c4ff92SAndroid Build Coastguard Worker path stem() const;
372*89c4ff92SAndroid Build Coastguard Worker path extension() const;
373*89c4ff92SAndroid Build Coastguard Worker
374*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.4.10 query
375*89c4ff92SAndroid Build Coastguard Worker bool empty() const noexcept;
376*89c4ff92SAndroid Build Coastguard Worker bool has_root_name() const;
377*89c4ff92SAndroid Build Coastguard Worker bool has_root_directory() const;
378*89c4ff92SAndroid Build Coastguard Worker bool has_root_path() const;
379*89c4ff92SAndroid Build Coastguard Worker bool has_relative_path() const;
380*89c4ff92SAndroid Build Coastguard Worker bool has_parent_path() const;
381*89c4ff92SAndroid Build Coastguard Worker bool has_filename() const;
382*89c4ff92SAndroid Build Coastguard Worker bool has_stem() const;
383*89c4ff92SAndroid Build Coastguard Worker bool has_extension() const;
384*89c4ff92SAndroid Build Coastguard Worker bool is_absolute() const;
385*89c4ff92SAndroid Build Coastguard Worker bool is_relative() const;
386*89c4ff92SAndroid Build Coastguard Worker
387*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.4.11 generation
388*89c4ff92SAndroid Build Coastguard Worker path lexically_normal() const;
389*89c4ff92SAndroid Build Coastguard Worker path lexically_relative(const path& base) const;
390*89c4ff92SAndroid Build Coastguard Worker path lexically_proximate(const path& base) const;
391*89c4ff92SAndroid Build Coastguard Worker
392*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.5 iterators
393*89c4ff92SAndroid Build Coastguard Worker class iterator;
394*89c4ff92SAndroid Build Coastguard Worker using const_iterator = iterator;
395*89c4ff92SAndroid Build Coastguard Worker iterator begin() const;
396*89c4ff92SAndroid Build Coastguard Worker iterator end() const;
397*89c4ff92SAndroid Build Coastguard Worker
398*89c4ff92SAndroid Build Coastguard Worker private:
399*89c4ff92SAndroid Build Coastguard Worker using impl_value_type = std::string::value_type;
400*89c4ff92SAndroid Build Coastguard Worker using impl_string_type = std::basic_string<impl_value_type>;
401*89c4ff92SAndroid Build Coastguard Worker friend class directory_iterator;
402*89c4ff92SAndroid Build Coastguard Worker void append_name(const char* name);
403*89c4ff92SAndroid Build Coastguard Worker static constexpr impl_value_type generic_separator = '/';
404*89c4ff92SAndroid Build Coastguard Worker template <typename InputIterator>
405*89c4ff92SAndroid Build Coastguard Worker class input_iterator_range
406*89c4ff92SAndroid Build Coastguard Worker {
407*89c4ff92SAndroid Build Coastguard Worker public:
408*89c4ff92SAndroid Build Coastguard Worker typedef InputIterator iterator;
409*89c4ff92SAndroid Build Coastguard Worker typedef InputIterator const_iterator;
410*89c4ff92SAndroid Build Coastguard Worker typedef typename InputIterator::difference_type difference_type;
411*89c4ff92SAndroid Build Coastguard Worker
input_iterator_range(const InputIterator & first,const InputIterator & last)412*89c4ff92SAndroid Build Coastguard Worker input_iterator_range(const InputIterator& first, const InputIterator& last)
413*89c4ff92SAndroid Build Coastguard Worker : _first(first)
414*89c4ff92SAndroid Build Coastguard Worker , _last(last)
415*89c4ff92SAndroid Build Coastguard Worker {
416*89c4ff92SAndroid Build Coastguard Worker }
417*89c4ff92SAndroid Build Coastguard Worker
begin() const418*89c4ff92SAndroid Build Coastguard Worker InputIterator begin() const { return _first; }
end() const419*89c4ff92SAndroid Build Coastguard Worker InputIterator end() const { return _last; }
420*89c4ff92SAndroid Build Coastguard Worker
421*89c4ff92SAndroid Build Coastguard Worker private:
422*89c4ff92SAndroid Build Coastguard Worker InputIterator _first;
423*89c4ff92SAndroid Build Coastguard Worker InputIterator _last;
424*89c4ff92SAndroid Build Coastguard Worker };
425*89c4ff92SAndroid Build Coastguard Worker friend void swap(path& lhs, path& rhs) noexcept;
426*89c4ff92SAndroid Build Coastguard Worker friend size_t hash_value(const path& p) noexcept;
427*89c4ff92SAndroid Build Coastguard Worker static void postprocess_path_with_format(impl_string_type& p, format fmt);
428*89c4ff92SAndroid Build Coastguard Worker impl_string_type _path;
429*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
430*89c4ff92SAndroid Build Coastguard Worker impl_string_type native_impl() const;
431*89c4ff92SAndroid Build Coastguard Worker mutable string_type _native_cache;
432*89c4ff92SAndroid Build Coastguard Worker #else
433*89c4ff92SAndroid Build Coastguard Worker const impl_string_type& native_impl() const;
434*89c4ff92SAndroid Build Coastguard Worker #endif
435*89c4ff92SAndroid Build Coastguard Worker };
436*89c4ff92SAndroid Build Coastguard Worker
437*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.6 path non-member functions
438*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void swap(path& lhs, path& rhs) noexcept;
439*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API size_t hash_value(const path& p) noexcept;
440*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool operator==(const path& lhs, const path& rhs) noexcept;
441*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool operator!=(const path& lhs, const path& rhs) noexcept;
442*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool operator<(const path& lhs, const path& rhs) noexcept;
443*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool operator<=(const path& lhs, const path& rhs) noexcept;
444*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool operator>(const path& lhs, const path& rhs) noexcept;
445*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool operator>=(const path& lhs, const path& rhs) noexcept;
446*89c4ff92SAndroid Build Coastguard Worker
447*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API path operator/(const path& lhs, const path& rhs);
448*89c4ff92SAndroid Build Coastguard Worker
449*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.6.1 path inserter and extractor
450*89c4ff92SAndroid Build Coastguard Worker template <class charT, class traits>
451*89c4ff92SAndroid Build Coastguard Worker std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const path& p);
452*89c4ff92SAndroid Build Coastguard Worker template <class charT, class traits>
453*89c4ff92SAndroid Build Coastguard Worker std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>& is, path& p);
454*89c4ff92SAndroid Build Coastguard Worker
455*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.6.2 path factory functions
456*89c4ff92SAndroid Build Coastguard Worker template <class Source, typename = path::path_from_string<Source>>
457*89c4ff92SAndroid Build Coastguard Worker path u8path(const Source& source);
458*89c4ff92SAndroid Build Coastguard Worker template <class InputIterator>
459*89c4ff92SAndroid Build Coastguard Worker path u8path(InputIterator first, InputIterator last);
460*89c4ff92SAndroid Build Coastguard Worker
461*89c4ff92SAndroid Build Coastguard Worker // 30.10.9 class filesystem_error
462*89c4ff92SAndroid Build Coastguard Worker class GHC_FS_API_CLASS filesystem_error : public std::system_error
463*89c4ff92SAndroid Build Coastguard Worker {
464*89c4ff92SAndroid Build Coastguard Worker public:
465*89c4ff92SAndroid Build Coastguard Worker filesystem_error(const std::string& what_arg, std::error_code ec);
466*89c4ff92SAndroid Build Coastguard Worker filesystem_error(const std::string& what_arg, const path& p1, std::error_code ec);
467*89c4ff92SAndroid Build Coastguard Worker filesystem_error(const std::string& what_arg, const path& p1, const path& p2, std::error_code ec);
468*89c4ff92SAndroid Build Coastguard Worker const path& path1() const noexcept;
469*89c4ff92SAndroid Build Coastguard Worker const path& path2() const noexcept;
470*89c4ff92SAndroid Build Coastguard Worker const char* what() const noexcept override;
471*89c4ff92SAndroid Build Coastguard Worker
472*89c4ff92SAndroid Build Coastguard Worker private:
473*89c4ff92SAndroid Build Coastguard Worker std::string _what_arg;
474*89c4ff92SAndroid Build Coastguard Worker std::error_code _ec;
475*89c4ff92SAndroid Build Coastguard Worker path _p1, _p2;
476*89c4ff92SAndroid Build Coastguard Worker };
477*89c4ff92SAndroid Build Coastguard Worker
478*89c4ff92SAndroid Build Coastguard Worker class GHC_FS_API_CLASS path::iterator
479*89c4ff92SAndroid Build Coastguard Worker {
480*89c4ff92SAndroid Build Coastguard Worker public:
481*89c4ff92SAndroid Build Coastguard Worker using value_type = const path;
482*89c4ff92SAndroid Build Coastguard Worker using difference_type = std::ptrdiff_t;
483*89c4ff92SAndroid Build Coastguard Worker using pointer = const path*;
484*89c4ff92SAndroid Build Coastguard Worker using reference = const path&;
485*89c4ff92SAndroid Build Coastguard Worker using iterator_category = std::bidirectional_iterator_tag;
486*89c4ff92SAndroid Build Coastguard Worker
487*89c4ff92SAndroid Build Coastguard Worker iterator();
488*89c4ff92SAndroid Build Coastguard Worker iterator(const impl_string_type::const_iterator& first, const impl_string_type::const_iterator& last, const impl_string_type::const_iterator& pos);
489*89c4ff92SAndroid Build Coastguard Worker iterator& operator++();
490*89c4ff92SAndroid Build Coastguard Worker iterator operator++(int);
491*89c4ff92SAndroid Build Coastguard Worker iterator& operator--();
492*89c4ff92SAndroid Build Coastguard Worker iterator operator--(int);
493*89c4ff92SAndroid Build Coastguard Worker bool operator==(const iterator& other) const;
494*89c4ff92SAndroid Build Coastguard Worker bool operator!=(const iterator& other) const;
495*89c4ff92SAndroid Build Coastguard Worker reference operator*() const;
496*89c4ff92SAndroid Build Coastguard Worker pointer operator->() const;
497*89c4ff92SAndroid Build Coastguard Worker
498*89c4ff92SAndroid Build Coastguard Worker private:
499*89c4ff92SAndroid Build Coastguard Worker impl_string_type::const_iterator increment(const std::string::const_iterator& pos) const;
500*89c4ff92SAndroid Build Coastguard Worker impl_string_type::const_iterator decrement(const std::string::const_iterator& pos) const;
501*89c4ff92SAndroid Build Coastguard Worker void updateCurrent();
502*89c4ff92SAndroid Build Coastguard Worker impl_string_type::const_iterator _first;
503*89c4ff92SAndroid Build Coastguard Worker impl_string_type::const_iterator _last;
504*89c4ff92SAndroid Build Coastguard Worker impl_string_type::const_iterator _root;
505*89c4ff92SAndroid Build Coastguard Worker impl_string_type::const_iterator _iter;
506*89c4ff92SAndroid Build Coastguard Worker path _current;
507*89c4ff92SAndroid Build Coastguard Worker };
508*89c4ff92SAndroid Build Coastguard Worker
509*89c4ff92SAndroid Build Coastguard Worker struct space_info
510*89c4ff92SAndroid Build Coastguard Worker {
511*89c4ff92SAndroid Build Coastguard Worker uintmax_t capacity;
512*89c4ff92SAndroid Build Coastguard Worker uintmax_t free;
513*89c4ff92SAndroid Build Coastguard Worker uintmax_t available;
514*89c4ff92SAndroid Build Coastguard Worker };
515*89c4ff92SAndroid Build Coastguard Worker
516*89c4ff92SAndroid Build Coastguard Worker // 30.10.10, enumerations
517*89c4ff92SAndroid Build Coastguard Worker enum class file_type {
518*89c4ff92SAndroid Build Coastguard Worker none,
519*89c4ff92SAndroid Build Coastguard Worker not_found,
520*89c4ff92SAndroid Build Coastguard Worker regular,
521*89c4ff92SAndroid Build Coastguard Worker directory,
522*89c4ff92SAndroid Build Coastguard Worker symlink,
523*89c4ff92SAndroid Build Coastguard Worker block,
524*89c4ff92SAndroid Build Coastguard Worker character,
525*89c4ff92SAndroid Build Coastguard Worker fifo,
526*89c4ff92SAndroid Build Coastguard Worker socket,
527*89c4ff92SAndroid Build Coastguard Worker unknown,
528*89c4ff92SAndroid Build Coastguard Worker };
529*89c4ff92SAndroid Build Coastguard Worker
530*89c4ff92SAndroid Build Coastguard Worker enum class perms : uint16_t {
531*89c4ff92SAndroid Build Coastguard Worker none = 0,
532*89c4ff92SAndroid Build Coastguard Worker
533*89c4ff92SAndroid Build Coastguard Worker owner_read = 0400,
534*89c4ff92SAndroid Build Coastguard Worker owner_write = 0200,
535*89c4ff92SAndroid Build Coastguard Worker owner_exec = 0100,
536*89c4ff92SAndroid Build Coastguard Worker owner_all = 0700,
537*89c4ff92SAndroid Build Coastguard Worker
538*89c4ff92SAndroid Build Coastguard Worker group_read = 040,
539*89c4ff92SAndroid Build Coastguard Worker group_write = 020,
540*89c4ff92SAndroid Build Coastguard Worker group_exec = 010,
541*89c4ff92SAndroid Build Coastguard Worker group_all = 070,
542*89c4ff92SAndroid Build Coastguard Worker
543*89c4ff92SAndroid Build Coastguard Worker others_read = 04,
544*89c4ff92SAndroid Build Coastguard Worker others_write = 02,
545*89c4ff92SAndroid Build Coastguard Worker others_exec = 01,
546*89c4ff92SAndroid Build Coastguard Worker others_all = 07,
547*89c4ff92SAndroid Build Coastguard Worker
548*89c4ff92SAndroid Build Coastguard Worker all = 0777,
549*89c4ff92SAndroid Build Coastguard Worker set_uid = 04000,
550*89c4ff92SAndroid Build Coastguard Worker set_gid = 02000,
551*89c4ff92SAndroid Build Coastguard Worker sticky_bit = 01000,
552*89c4ff92SAndroid Build Coastguard Worker
553*89c4ff92SAndroid Build Coastguard Worker mask = 07777,
554*89c4ff92SAndroid Build Coastguard Worker unknown = 0xffff
555*89c4ff92SAndroid Build Coastguard Worker };
556*89c4ff92SAndroid Build Coastguard Worker
557*89c4ff92SAndroid Build Coastguard Worker enum class perm_options : uint16_t {
558*89c4ff92SAndroid Build Coastguard Worker replace = 3,
559*89c4ff92SAndroid Build Coastguard Worker add = 1,
560*89c4ff92SAndroid Build Coastguard Worker remove = 2,
561*89c4ff92SAndroid Build Coastguard Worker nofollow = 4,
562*89c4ff92SAndroid Build Coastguard Worker };
563*89c4ff92SAndroid Build Coastguard Worker
564*89c4ff92SAndroid Build Coastguard Worker enum class copy_options : uint16_t {
565*89c4ff92SAndroid Build Coastguard Worker none = 0,
566*89c4ff92SAndroid Build Coastguard Worker
567*89c4ff92SAndroid Build Coastguard Worker skip_existing = 1,
568*89c4ff92SAndroid Build Coastguard Worker overwrite_existing = 2,
569*89c4ff92SAndroid Build Coastguard Worker update_existing = 4,
570*89c4ff92SAndroid Build Coastguard Worker
571*89c4ff92SAndroid Build Coastguard Worker recursive = 8,
572*89c4ff92SAndroid Build Coastguard Worker
573*89c4ff92SAndroid Build Coastguard Worker copy_symlinks = 0x10,
574*89c4ff92SAndroid Build Coastguard Worker skip_symlinks = 0x20,
575*89c4ff92SAndroid Build Coastguard Worker
576*89c4ff92SAndroid Build Coastguard Worker directories_only = 0x40,
577*89c4ff92SAndroid Build Coastguard Worker create_symlinks = 0x80,
578*89c4ff92SAndroid Build Coastguard Worker create_hard_links = 0x100
579*89c4ff92SAndroid Build Coastguard Worker };
580*89c4ff92SAndroid Build Coastguard Worker
581*89c4ff92SAndroid Build Coastguard Worker enum class directory_options : uint16_t {
582*89c4ff92SAndroid Build Coastguard Worker none = 0,
583*89c4ff92SAndroid Build Coastguard Worker follow_directory_symlink = 1,
584*89c4ff92SAndroid Build Coastguard Worker skip_permission_denied = 2,
585*89c4ff92SAndroid Build Coastguard Worker };
586*89c4ff92SAndroid Build Coastguard Worker
587*89c4ff92SAndroid Build Coastguard Worker // 30.10.11 class file_status
588*89c4ff92SAndroid Build Coastguard Worker class GHC_FS_API_CLASS file_status
589*89c4ff92SAndroid Build Coastguard Worker {
590*89c4ff92SAndroid Build Coastguard Worker public:
591*89c4ff92SAndroid Build Coastguard Worker // 30.10.11.1 constructors and destructor
592*89c4ff92SAndroid Build Coastguard Worker file_status() noexcept;
593*89c4ff92SAndroid Build Coastguard Worker explicit file_status(file_type ft, perms prms = perms::unknown) noexcept;
594*89c4ff92SAndroid Build Coastguard Worker file_status(const file_status&) noexcept;
595*89c4ff92SAndroid Build Coastguard Worker file_status(file_status&&) noexcept;
596*89c4ff92SAndroid Build Coastguard Worker ~file_status();
597*89c4ff92SAndroid Build Coastguard Worker // assignments:
598*89c4ff92SAndroid Build Coastguard Worker file_status& operator=(const file_status&) noexcept;
599*89c4ff92SAndroid Build Coastguard Worker file_status& operator=(file_status&&) noexcept;
600*89c4ff92SAndroid Build Coastguard Worker // 30.10.11.3 modifiers
601*89c4ff92SAndroid Build Coastguard Worker void type(file_type ft) noexcept;
602*89c4ff92SAndroid Build Coastguard Worker void permissions(perms prms) noexcept;
603*89c4ff92SAndroid Build Coastguard Worker // 30.10.11.2 observers
604*89c4ff92SAndroid Build Coastguard Worker file_type type() const noexcept;
605*89c4ff92SAndroid Build Coastguard Worker perms permissions() const noexcept;
606*89c4ff92SAndroid Build Coastguard Worker
607*89c4ff92SAndroid Build Coastguard Worker private:
608*89c4ff92SAndroid Build Coastguard Worker file_type _type;
609*89c4ff92SAndroid Build Coastguard Worker perms _perms;
610*89c4ff92SAndroid Build Coastguard Worker };
611*89c4ff92SAndroid Build Coastguard Worker
612*89c4ff92SAndroid Build Coastguard Worker using file_time_type = std::chrono::time_point<std::chrono::system_clock>;
613*89c4ff92SAndroid Build Coastguard Worker
614*89c4ff92SAndroid Build Coastguard Worker // 30.10.12 Class directory_entry
615*89c4ff92SAndroid Build Coastguard Worker class GHC_FS_API_CLASS directory_entry
616*89c4ff92SAndroid Build Coastguard Worker {
617*89c4ff92SAndroid Build Coastguard Worker public:
618*89c4ff92SAndroid Build Coastguard Worker // 30.10.12.1 constructors and destructor
619*89c4ff92SAndroid Build Coastguard Worker directory_entry() noexcept = default;
620*89c4ff92SAndroid Build Coastguard Worker directory_entry(const directory_entry&) = default;
621*89c4ff92SAndroid Build Coastguard Worker directory_entry(directory_entry&&) noexcept = default;
622*89c4ff92SAndroid Build Coastguard Worker explicit directory_entry(const path& p);
623*89c4ff92SAndroid Build Coastguard Worker directory_entry(const path& p, std::error_code& ec);
624*89c4ff92SAndroid Build Coastguard Worker ~directory_entry();
625*89c4ff92SAndroid Build Coastguard Worker
626*89c4ff92SAndroid Build Coastguard Worker // assignments:
627*89c4ff92SAndroid Build Coastguard Worker directory_entry& operator=(const directory_entry&) = default;
628*89c4ff92SAndroid Build Coastguard Worker directory_entry& operator=(directory_entry&&) noexcept = default;
629*89c4ff92SAndroid Build Coastguard Worker
630*89c4ff92SAndroid Build Coastguard Worker // 30.10.12.2 modifiers
631*89c4ff92SAndroid Build Coastguard Worker void assign(const path& p);
632*89c4ff92SAndroid Build Coastguard Worker void assign(const path& p, std::error_code& ec);
633*89c4ff92SAndroid Build Coastguard Worker void replace_filename(const path& p);
634*89c4ff92SAndroid Build Coastguard Worker void replace_filename(const path& p, std::error_code& ec);
635*89c4ff92SAndroid Build Coastguard Worker void refresh();
636*89c4ff92SAndroid Build Coastguard Worker void refresh(std::error_code& ec) noexcept;
637*89c4ff92SAndroid Build Coastguard Worker
638*89c4ff92SAndroid Build Coastguard Worker // 30.10.12.3 observers
639*89c4ff92SAndroid Build Coastguard Worker const filesystem::path& path() const noexcept;
640*89c4ff92SAndroid Build Coastguard Worker operator const filesystem::path&() const noexcept;
641*89c4ff92SAndroid Build Coastguard Worker bool exists() const;
642*89c4ff92SAndroid Build Coastguard Worker bool exists(std::error_code& ec) const noexcept;
643*89c4ff92SAndroid Build Coastguard Worker bool is_block_file() const;
644*89c4ff92SAndroid Build Coastguard Worker bool is_block_file(std::error_code& ec) const noexcept;
645*89c4ff92SAndroid Build Coastguard Worker bool is_character_file() const;
646*89c4ff92SAndroid Build Coastguard Worker bool is_character_file(std::error_code& ec) const noexcept;
647*89c4ff92SAndroid Build Coastguard Worker bool is_directory() const;
648*89c4ff92SAndroid Build Coastguard Worker bool is_directory(std::error_code& ec) const noexcept;
649*89c4ff92SAndroid Build Coastguard Worker bool is_fifo() const;
650*89c4ff92SAndroid Build Coastguard Worker bool is_fifo(std::error_code& ec) const noexcept;
651*89c4ff92SAndroid Build Coastguard Worker bool is_other() const;
652*89c4ff92SAndroid Build Coastguard Worker bool is_other(std::error_code& ec) const noexcept;
653*89c4ff92SAndroid Build Coastguard Worker bool is_regular_file() const;
654*89c4ff92SAndroid Build Coastguard Worker bool is_regular_file(std::error_code& ec) const noexcept;
655*89c4ff92SAndroid Build Coastguard Worker bool is_socket() const;
656*89c4ff92SAndroid Build Coastguard Worker bool is_socket(std::error_code& ec) const noexcept;
657*89c4ff92SAndroid Build Coastguard Worker bool is_symlink() const;
658*89c4ff92SAndroid Build Coastguard Worker bool is_symlink(std::error_code& ec) const noexcept;
659*89c4ff92SAndroid Build Coastguard Worker uintmax_t file_size() const;
660*89c4ff92SAndroid Build Coastguard Worker uintmax_t file_size(std::error_code& ec) const noexcept;
661*89c4ff92SAndroid Build Coastguard Worker uintmax_t hard_link_count() const;
662*89c4ff92SAndroid Build Coastguard Worker uintmax_t hard_link_count(std::error_code& ec) const noexcept;
663*89c4ff92SAndroid Build Coastguard Worker file_time_type last_write_time() const;
664*89c4ff92SAndroid Build Coastguard Worker file_time_type last_write_time(std::error_code& ec) const noexcept;
665*89c4ff92SAndroid Build Coastguard Worker
666*89c4ff92SAndroid Build Coastguard Worker file_status status() const;
667*89c4ff92SAndroid Build Coastguard Worker file_status status(std::error_code& ec) const noexcept;
668*89c4ff92SAndroid Build Coastguard Worker
669*89c4ff92SAndroid Build Coastguard Worker file_status symlink_status() const;
670*89c4ff92SAndroid Build Coastguard Worker file_status symlink_status(std::error_code& ec) const noexcept;
671*89c4ff92SAndroid Build Coastguard Worker bool operator<(const directory_entry& rhs) const noexcept;
672*89c4ff92SAndroid Build Coastguard Worker bool operator==(const directory_entry& rhs) const noexcept;
673*89c4ff92SAndroid Build Coastguard Worker bool operator!=(const directory_entry& rhs) const noexcept;
674*89c4ff92SAndroid Build Coastguard Worker bool operator<=(const directory_entry& rhs) const noexcept;
675*89c4ff92SAndroid Build Coastguard Worker bool operator>(const directory_entry& rhs) const noexcept;
676*89c4ff92SAndroid Build Coastguard Worker bool operator>=(const directory_entry& rhs) const noexcept;
677*89c4ff92SAndroid Build Coastguard Worker
678*89c4ff92SAndroid Build Coastguard Worker private:
679*89c4ff92SAndroid Build Coastguard Worker friend class directory_iterator;
680*89c4ff92SAndroid Build Coastguard Worker filesystem::path _path;
681*89c4ff92SAndroid Build Coastguard Worker file_status _status;
682*89c4ff92SAndroid Build Coastguard Worker file_status _symlink_status;
683*89c4ff92SAndroid Build Coastguard Worker uintmax_t _file_size = 0;
684*89c4ff92SAndroid Build Coastguard Worker #ifndef GHC_OS_WINDOWS
685*89c4ff92SAndroid Build Coastguard Worker uintmax_t _hard_link_count = 0;
686*89c4ff92SAndroid Build Coastguard Worker #endif
687*89c4ff92SAndroid Build Coastguard Worker time_t _last_write_time = 0;
688*89c4ff92SAndroid Build Coastguard Worker };
689*89c4ff92SAndroid Build Coastguard Worker
690*89c4ff92SAndroid Build Coastguard Worker // 30.10.13 Class directory_iterator
691*89c4ff92SAndroid Build Coastguard Worker class GHC_FS_API_CLASS directory_iterator
692*89c4ff92SAndroid Build Coastguard Worker {
693*89c4ff92SAndroid Build Coastguard Worker public:
694*89c4ff92SAndroid Build Coastguard Worker class GHC_FS_API_CLASS proxy
695*89c4ff92SAndroid Build Coastguard Worker {
696*89c4ff92SAndroid Build Coastguard Worker public:
operator *() const697*89c4ff92SAndroid Build Coastguard Worker const directory_entry& operator*() const& noexcept { return _dir_entry; }
operator *()698*89c4ff92SAndroid Build Coastguard Worker directory_entry operator*() && noexcept { return std::move(_dir_entry); }
699*89c4ff92SAndroid Build Coastguard Worker
700*89c4ff92SAndroid Build Coastguard Worker private:
proxy(const directory_entry & dir_entry)701*89c4ff92SAndroid Build Coastguard Worker explicit proxy(const directory_entry& dir_entry)
702*89c4ff92SAndroid Build Coastguard Worker : _dir_entry(dir_entry)
703*89c4ff92SAndroid Build Coastguard Worker {
704*89c4ff92SAndroid Build Coastguard Worker }
705*89c4ff92SAndroid Build Coastguard Worker friend class directory_iterator;
706*89c4ff92SAndroid Build Coastguard Worker friend class recursive_directory_iterator;
707*89c4ff92SAndroid Build Coastguard Worker directory_entry _dir_entry;
708*89c4ff92SAndroid Build Coastguard Worker };
709*89c4ff92SAndroid Build Coastguard Worker using iterator_category = std::input_iterator_tag;
710*89c4ff92SAndroid Build Coastguard Worker using value_type = directory_entry;
711*89c4ff92SAndroid Build Coastguard Worker using difference_type = std::ptrdiff_t;
712*89c4ff92SAndroid Build Coastguard Worker using pointer = const directory_entry*;
713*89c4ff92SAndroid Build Coastguard Worker using reference = const directory_entry&;
714*89c4ff92SAndroid Build Coastguard Worker
715*89c4ff92SAndroid Build Coastguard Worker // 30.10.13.1 member functions
716*89c4ff92SAndroid Build Coastguard Worker directory_iterator() noexcept;
717*89c4ff92SAndroid Build Coastguard Worker explicit directory_iterator(const path& p);
718*89c4ff92SAndroid Build Coastguard Worker directory_iterator(const path& p, directory_options options);
719*89c4ff92SAndroid Build Coastguard Worker directory_iterator(const path& p, std::error_code& ec) noexcept;
720*89c4ff92SAndroid Build Coastguard Worker directory_iterator(const path& p, directory_options options, std::error_code& ec) noexcept;
721*89c4ff92SAndroid Build Coastguard Worker directory_iterator(const directory_iterator& rhs);
722*89c4ff92SAndroid Build Coastguard Worker directory_iterator(directory_iterator&& rhs) noexcept;
723*89c4ff92SAndroid Build Coastguard Worker ~directory_iterator();
724*89c4ff92SAndroid Build Coastguard Worker directory_iterator& operator=(const directory_iterator& rhs);
725*89c4ff92SAndroid Build Coastguard Worker directory_iterator& operator=(directory_iterator&& rhs) noexcept;
726*89c4ff92SAndroid Build Coastguard Worker const directory_entry& operator*() const;
727*89c4ff92SAndroid Build Coastguard Worker const directory_entry* operator->() const;
728*89c4ff92SAndroid Build Coastguard Worker directory_iterator& operator++();
729*89c4ff92SAndroid Build Coastguard Worker directory_iterator& increment(std::error_code& ec) noexcept;
730*89c4ff92SAndroid Build Coastguard Worker
731*89c4ff92SAndroid Build Coastguard Worker // other members as required by 27.2.3, input iterators
operator ++(int)732*89c4ff92SAndroid Build Coastguard Worker proxy operator++(int)
733*89c4ff92SAndroid Build Coastguard Worker {
734*89c4ff92SAndroid Build Coastguard Worker proxy p{**this};
735*89c4ff92SAndroid Build Coastguard Worker ++*this;
736*89c4ff92SAndroid Build Coastguard Worker return p;
737*89c4ff92SAndroid Build Coastguard Worker }
738*89c4ff92SAndroid Build Coastguard Worker bool operator==(const directory_iterator& rhs) const;
739*89c4ff92SAndroid Build Coastguard Worker bool operator!=(const directory_iterator& rhs) const;
740*89c4ff92SAndroid Build Coastguard Worker
741*89c4ff92SAndroid Build Coastguard Worker private:
742*89c4ff92SAndroid Build Coastguard Worker friend class recursive_directory_iterator;
743*89c4ff92SAndroid Build Coastguard Worker class impl;
744*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<impl> _impl;
745*89c4ff92SAndroid Build Coastguard Worker };
746*89c4ff92SAndroid Build Coastguard Worker
747*89c4ff92SAndroid Build Coastguard Worker // 30.10.13.2 directory_iterator non-member functions
748*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API directory_iterator begin(directory_iterator iter) noexcept;
749*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API directory_iterator end(const directory_iterator&) noexcept;
750*89c4ff92SAndroid Build Coastguard Worker
751*89c4ff92SAndroid Build Coastguard Worker // 30.10.14 class recursive_directory_iterator
752*89c4ff92SAndroid Build Coastguard Worker class GHC_FS_API_CLASS recursive_directory_iterator
753*89c4ff92SAndroid Build Coastguard Worker {
754*89c4ff92SAndroid Build Coastguard Worker public:
755*89c4ff92SAndroid Build Coastguard Worker using iterator_category = std::input_iterator_tag;
756*89c4ff92SAndroid Build Coastguard Worker using value_type = directory_entry;
757*89c4ff92SAndroid Build Coastguard Worker using difference_type = std::ptrdiff_t;
758*89c4ff92SAndroid Build Coastguard Worker using pointer = const directory_entry*;
759*89c4ff92SAndroid Build Coastguard Worker using reference = const directory_entry&;
760*89c4ff92SAndroid Build Coastguard Worker
761*89c4ff92SAndroid Build Coastguard Worker // 30.10.14.1 constructors and destructor
762*89c4ff92SAndroid Build Coastguard Worker recursive_directory_iterator() noexcept;
763*89c4ff92SAndroid Build Coastguard Worker explicit recursive_directory_iterator(const path& p);
764*89c4ff92SAndroid Build Coastguard Worker recursive_directory_iterator(const path& p, directory_options options);
765*89c4ff92SAndroid Build Coastguard Worker recursive_directory_iterator(const path& p, directory_options options, std::error_code& ec) noexcept;
766*89c4ff92SAndroid Build Coastguard Worker recursive_directory_iterator(const path& p, std::error_code& ec) noexcept;
767*89c4ff92SAndroid Build Coastguard Worker recursive_directory_iterator(const recursive_directory_iterator& rhs);
768*89c4ff92SAndroid Build Coastguard Worker recursive_directory_iterator(recursive_directory_iterator&& rhs) noexcept;
769*89c4ff92SAndroid Build Coastguard Worker ~recursive_directory_iterator();
770*89c4ff92SAndroid Build Coastguard Worker
771*89c4ff92SAndroid Build Coastguard Worker // 30.10.14.1 observers
772*89c4ff92SAndroid Build Coastguard Worker directory_options options() const;
773*89c4ff92SAndroid Build Coastguard Worker int depth() const;
774*89c4ff92SAndroid Build Coastguard Worker bool recursion_pending() const;
775*89c4ff92SAndroid Build Coastguard Worker
776*89c4ff92SAndroid Build Coastguard Worker const directory_entry& operator*() const;
777*89c4ff92SAndroid Build Coastguard Worker const directory_entry* operator->() const;
778*89c4ff92SAndroid Build Coastguard Worker
779*89c4ff92SAndroid Build Coastguard Worker // 30.10.14.1 modifiers recursive_directory_iterator&
780*89c4ff92SAndroid Build Coastguard Worker recursive_directory_iterator& operator=(const recursive_directory_iterator& rhs);
781*89c4ff92SAndroid Build Coastguard Worker recursive_directory_iterator& operator=(recursive_directory_iterator&& rhs) noexcept;
782*89c4ff92SAndroid Build Coastguard Worker recursive_directory_iterator& operator++();
783*89c4ff92SAndroid Build Coastguard Worker recursive_directory_iterator& increment(std::error_code& ec) noexcept;
784*89c4ff92SAndroid Build Coastguard Worker
785*89c4ff92SAndroid Build Coastguard Worker void pop();
786*89c4ff92SAndroid Build Coastguard Worker void pop(std::error_code& ec);
787*89c4ff92SAndroid Build Coastguard Worker void disable_recursion_pending();
788*89c4ff92SAndroid Build Coastguard Worker
789*89c4ff92SAndroid Build Coastguard Worker // other members as required by 27.2.3, input iterators
operator ++(int)790*89c4ff92SAndroid Build Coastguard Worker directory_iterator::proxy operator++(int)
791*89c4ff92SAndroid Build Coastguard Worker {
792*89c4ff92SAndroid Build Coastguard Worker directory_iterator::proxy proxy{**this};
793*89c4ff92SAndroid Build Coastguard Worker ++*this;
794*89c4ff92SAndroid Build Coastguard Worker return proxy;
795*89c4ff92SAndroid Build Coastguard Worker }
796*89c4ff92SAndroid Build Coastguard Worker bool operator==(const recursive_directory_iterator& rhs) const;
797*89c4ff92SAndroid Build Coastguard Worker bool operator!=(const recursive_directory_iterator& rhs) const;
798*89c4ff92SAndroid Build Coastguard Worker
799*89c4ff92SAndroid Build Coastguard Worker private:
800*89c4ff92SAndroid Build Coastguard Worker struct recursive_directory_iterator_impl
801*89c4ff92SAndroid Build Coastguard Worker {
802*89c4ff92SAndroid Build Coastguard Worker directory_options _options;
803*89c4ff92SAndroid Build Coastguard Worker bool _recursion_pending;
804*89c4ff92SAndroid Build Coastguard Worker std::stack<directory_iterator> _dir_iter_stack;
recursive_directory_iterator_implghc::filesystem::recursive_directory_iterator::recursive_directory_iterator_impl805*89c4ff92SAndroid Build Coastguard Worker recursive_directory_iterator_impl(directory_options options, bool recursion_pending)
806*89c4ff92SAndroid Build Coastguard Worker : _options(options)
807*89c4ff92SAndroid Build Coastguard Worker , _recursion_pending(recursion_pending)
808*89c4ff92SAndroid Build Coastguard Worker {
809*89c4ff92SAndroid Build Coastguard Worker }
810*89c4ff92SAndroid Build Coastguard Worker };
811*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<recursive_directory_iterator_impl> _impl;
812*89c4ff92SAndroid Build Coastguard Worker };
813*89c4ff92SAndroid Build Coastguard Worker
814*89c4ff92SAndroid Build Coastguard Worker // 30.10.14.2 directory_iterator non-member functions
815*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;
816*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API recursive_directory_iterator end(const recursive_directory_iterator&) noexcept;
817*89c4ff92SAndroid Build Coastguard Worker
818*89c4ff92SAndroid Build Coastguard Worker // 30.10.15 filesystem operations
819*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API path absolute(const path& p);
820*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API path absolute(const path& p, std::error_code& ec);
821*89c4ff92SAndroid Build Coastguard Worker
822*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API path canonical(const path& p);
823*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API path canonical(const path& p, std::error_code& ec);
824*89c4ff92SAndroid Build Coastguard Worker
825*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void copy(const path& from, const path& to);
826*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void copy(const path& from, const path& to, std::error_code& ec) noexcept;
827*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void copy(const path& from, const path& to, copy_options options);
828*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void copy(const path& from, const path& to, copy_options options, std::error_code& ec) noexcept;
829*89c4ff92SAndroid Build Coastguard Worker
830*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool copy_file(const path& from, const path& to);
831*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool copy_file(const path& from, const path& to, std::error_code& ec) noexcept;
832*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool copy_file(const path& from, const path& to, copy_options option);
833*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool copy_file(const path& from, const path& to, copy_options option, std::error_code& ec) noexcept;
834*89c4ff92SAndroid Build Coastguard Worker
835*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void copy_symlink(const path& existing_symlink, const path& new_symlink);
836*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void copy_symlink(const path& existing_symlink, const path& new_symlink, std::error_code& ec) noexcept;
837*89c4ff92SAndroid Build Coastguard Worker
838*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool create_directories(const path& p);
839*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool create_directories(const path& p, std::error_code& ec) noexcept;
840*89c4ff92SAndroid Build Coastguard Worker
841*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool create_directory(const path& p);
842*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool create_directory(const path& p, std::error_code& ec) noexcept;
843*89c4ff92SAndroid Build Coastguard Worker
844*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool create_directory(const path& p, const path& attributes);
845*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool create_directory(const path& p, const path& attributes, std::error_code& ec) noexcept;
846*89c4ff92SAndroid Build Coastguard Worker
847*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void create_directory_symlink(const path& to, const path& new_symlink);
848*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void create_directory_symlink(const path& to, const path& new_symlink, std::error_code& ec) noexcept;
849*89c4ff92SAndroid Build Coastguard Worker
850*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void create_hard_link(const path& to, const path& new_hard_link);
851*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void create_hard_link(const path& to, const path& new_hard_link, std::error_code& ec) noexcept;
852*89c4ff92SAndroid Build Coastguard Worker
853*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void create_symlink(const path& to, const path& new_symlink);
854*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void create_symlink(const path& to, const path& new_symlink, std::error_code& ec) noexcept;
855*89c4ff92SAndroid Build Coastguard Worker
856*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API path current_path();
857*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API path current_path(std::error_code& ec);
858*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void current_path(const path& p);
859*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void current_path(const path& p, std::error_code& ec) noexcept;
860*89c4ff92SAndroid Build Coastguard Worker
861*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool exists(file_status s) noexcept;
862*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool exists(const path& p);
863*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool exists(const path& p, std::error_code& ec) noexcept;
864*89c4ff92SAndroid Build Coastguard Worker
865*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool equivalent(const path& p1, const path& p2);
866*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool equivalent(const path& p1, const path& p2, std::error_code& ec) noexcept;
867*89c4ff92SAndroid Build Coastguard Worker
868*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API uintmax_t file_size(const path& p);
869*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API uintmax_t file_size(const path& p, std::error_code& ec) noexcept;
870*89c4ff92SAndroid Build Coastguard Worker
871*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API uintmax_t hard_link_count(const path& p);
872*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcept;
873*89c4ff92SAndroid Build Coastguard Worker
874*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_block_file(file_status s) noexcept;
875*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_block_file(const path& p);
876*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_block_file(const path& p, std::error_code& ec) noexcept;
877*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_character_file(file_status s) noexcept;
878*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_character_file(const path& p);
879*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_character_file(const path& p, std::error_code& ec) noexcept;
880*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_directory(file_status s) noexcept;
881*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_directory(const path& p);
882*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_directory(const path& p, std::error_code& ec) noexcept;
883*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_empty(const path& p);
884*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_empty(const path& p, std::error_code& ec) noexcept;
885*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_fifo(file_status s) noexcept;
886*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_fifo(const path& p);
887*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_fifo(const path& p, std::error_code& ec) noexcept;
888*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_other(file_status s) noexcept;
889*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_other(const path& p);
890*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_other(const path& p, std::error_code& ec) noexcept;
891*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_regular_file(file_status s) noexcept;
892*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_regular_file(const path& p);
893*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_regular_file(const path& p, std::error_code& ec) noexcept;
894*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_socket(file_status s) noexcept;
895*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_socket(const path& p);
896*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_socket(const path& p, std::error_code& ec) noexcept;
897*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_symlink(file_status s) noexcept;
898*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_symlink(const path& p);
899*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_symlink(const path& p, std::error_code& ec) noexcept;
900*89c4ff92SAndroid Build Coastguard Worker
901*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API file_time_type last_write_time(const path& p);
902*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API file_time_type last_write_time(const path& p, std::error_code& ec) noexcept;
903*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void last_write_time(const path& p, file_time_type new_time);
904*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void last_write_time(const path& p, file_time_type new_time, std::error_code& ec) noexcept;
905*89c4ff92SAndroid Build Coastguard Worker
906*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void permissions(const path& p, perms prms, perm_options opts = perm_options::replace);
907*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void permissions(const path& p, perms prms, std::error_code& ec) noexcept;
908*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void permissions(const path& p, perms prms, perm_options opts, std::error_code& ec);
909*89c4ff92SAndroid Build Coastguard Worker
910*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API path proximate(const path& p, std::error_code& ec);
911*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API path proximate(const path& p, const path& base = current_path());
912*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API path proximate(const path& p, const path& base, std::error_code& ec);
913*89c4ff92SAndroid Build Coastguard Worker
914*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API path read_symlink(const path& p);
915*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API path read_symlink(const path& p, std::error_code& ec);
916*89c4ff92SAndroid Build Coastguard Worker
917*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API path relative(const path& p, std::error_code& ec);
918*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API path relative(const path& p, const path& base = current_path());
919*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API path relative(const path& p, const path& base, std::error_code& ec);
920*89c4ff92SAndroid Build Coastguard Worker
921*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool remove(const path& p);
922*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool remove(const path& p, std::error_code& ec) noexcept;
923*89c4ff92SAndroid Build Coastguard Worker
924*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API uintmax_t remove_all(const path& p);
925*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API uintmax_t remove_all(const path& p, std::error_code& ec) noexcept;
926*89c4ff92SAndroid Build Coastguard Worker
927*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void rename(const path& from, const path& to);
928*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void rename(const path& from, const path& to, std::error_code& ec) noexcept;
929*89c4ff92SAndroid Build Coastguard Worker
930*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void resize_file(const path& p, uintmax_t size);
931*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void resize_file(const path& p, uintmax_t size, std::error_code& ec) noexcept;
932*89c4ff92SAndroid Build Coastguard Worker
933*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API space_info space(const path& p);
934*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API space_info space(const path& p, std::error_code& ec) noexcept;
935*89c4ff92SAndroid Build Coastguard Worker
936*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API file_status status(const path& p);
937*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API file_status status(const path& p, std::error_code& ec) noexcept;
938*89c4ff92SAndroid Build Coastguard Worker
939*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool status_known(file_status s) noexcept;
940*89c4ff92SAndroid Build Coastguard Worker
941*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API file_status symlink_status(const path& p);
942*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API file_status symlink_status(const path& p, std::error_code& ec) noexcept;
943*89c4ff92SAndroid Build Coastguard Worker
944*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API path temp_directory_path();
945*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API path temp_directory_path(std::error_code& ec) noexcept;
946*89c4ff92SAndroid Build Coastguard Worker
947*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API path weakly_canonical(const path& p);
948*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API path weakly_canonical(const path& p, std::error_code& ec) noexcept;
949*89c4ff92SAndroid Build Coastguard Worker
950*89c4ff92SAndroid Build Coastguard Worker // Non-C++17 add-on std::fstream wrappers with path
951*89c4ff92SAndroid Build Coastguard Worker template <class charT, class traits = std::char_traits<charT>>
952*89c4ff92SAndroid Build Coastguard Worker class basic_filebuf : public std::basic_filebuf<charT, traits>
953*89c4ff92SAndroid Build Coastguard Worker {
954*89c4ff92SAndroid Build Coastguard Worker public:
basic_filebuf()955*89c4ff92SAndroid Build Coastguard Worker basic_filebuf() {}
~basic_filebuf()956*89c4ff92SAndroid Build Coastguard Worker ~basic_filebuf() override {}
957*89c4ff92SAndroid Build Coastguard Worker basic_filebuf(const basic_filebuf&) = delete;
958*89c4ff92SAndroid Build Coastguard Worker const basic_filebuf& operator=(const basic_filebuf&) = delete;
open(const path & p,std::ios_base::openmode mode)959*89c4ff92SAndroid Build Coastguard Worker basic_filebuf<charT, traits>* open(const path& p, std::ios_base::openmode mode)
960*89c4ff92SAndroid Build Coastguard Worker {
961*89c4ff92SAndroid Build Coastguard Worker #if defined(GHC_OS_WINDOWS) && !defined(__GNUC__)
962*89c4ff92SAndroid Build Coastguard Worker return std::basic_filebuf<charT, traits>::open(p.wstring().c_str(), mode) ? this : 0;
963*89c4ff92SAndroid Build Coastguard Worker #else
964*89c4ff92SAndroid Build Coastguard Worker return std::basic_filebuf<charT, traits>::open(p.string().c_str(), mode) ? this : 0;
965*89c4ff92SAndroid Build Coastguard Worker #endif
966*89c4ff92SAndroid Build Coastguard Worker }
967*89c4ff92SAndroid Build Coastguard Worker };
968*89c4ff92SAndroid Build Coastguard Worker
969*89c4ff92SAndroid Build Coastguard Worker template <class charT, class traits = std::char_traits<charT>>
970*89c4ff92SAndroid Build Coastguard Worker class basic_ifstream : public std::basic_ifstream<charT, traits>
971*89c4ff92SAndroid Build Coastguard Worker {
972*89c4ff92SAndroid Build Coastguard Worker public:
basic_ifstream()973*89c4ff92SAndroid Build Coastguard Worker basic_ifstream() {}
974*89c4ff92SAndroid Build Coastguard Worker #if defined(GHC_OS_WINDOWS) && !defined(__GNUC__)
basic_ifstream(const path & p,std::ios_base::openmode mode=std::ios_base::in)975*89c4ff92SAndroid Build Coastguard Worker explicit basic_ifstream(const path& p, std::ios_base::openmode mode = std::ios_base::in)
976*89c4ff92SAndroid Build Coastguard Worker : std::basic_ifstream<charT, traits>(p.wstring().c_str(), mode)
977*89c4ff92SAndroid Build Coastguard Worker {
978*89c4ff92SAndroid Build Coastguard Worker }
open(const path & p,std::ios_base::openmode mode=std::ios_base::in)979*89c4ff92SAndroid Build Coastguard Worker void open(const path& p, std::ios_base::openmode mode = std::ios_base::in) { std::basic_ifstream<charT, traits>::open(p.wstring().c_str(), mode); }
980*89c4ff92SAndroid Build Coastguard Worker #else
basic_ifstream(const path & p,std::ios_base::openmode mode=std::ios_base::in)981*89c4ff92SAndroid Build Coastguard Worker explicit basic_ifstream(const path& p, std::ios_base::openmode mode = std::ios_base::in)
982*89c4ff92SAndroid Build Coastguard Worker : std::basic_ifstream<charT, traits>(p.string().c_str(), mode)
983*89c4ff92SAndroid Build Coastguard Worker {
984*89c4ff92SAndroid Build Coastguard Worker }
open(const path & p,std::ios_base::openmode mode=std::ios_base::in)985*89c4ff92SAndroid Build Coastguard Worker void open(const path& p, std::ios_base::openmode mode = std::ios_base::in) { std::basic_ifstream<charT, traits>::open(p.string().c_str(), mode); }
986*89c4ff92SAndroid Build Coastguard Worker #endif
987*89c4ff92SAndroid Build Coastguard Worker basic_ifstream(const basic_ifstream&) = delete;
988*89c4ff92SAndroid Build Coastguard Worker const basic_ifstream& operator=(const basic_ifstream&) = delete;
~basic_ifstream()989*89c4ff92SAndroid Build Coastguard Worker ~basic_ifstream() override {}
990*89c4ff92SAndroid Build Coastguard Worker };
991*89c4ff92SAndroid Build Coastguard Worker
992*89c4ff92SAndroid Build Coastguard Worker template <class charT, class traits = std::char_traits<charT>>
993*89c4ff92SAndroid Build Coastguard Worker class basic_ofstream : public std::basic_ofstream<charT, traits>
994*89c4ff92SAndroid Build Coastguard Worker {
995*89c4ff92SAndroid Build Coastguard Worker public:
basic_ofstream()996*89c4ff92SAndroid Build Coastguard Worker basic_ofstream() {}
997*89c4ff92SAndroid Build Coastguard Worker #if defined(GHC_OS_WINDOWS) && !defined(__GNUC__)
basic_ofstream(const path & p,std::ios_base::openmode mode=std::ios_base::out)998*89c4ff92SAndroid Build Coastguard Worker explicit basic_ofstream(const path& p, std::ios_base::openmode mode = std::ios_base::out)
999*89c4ff92SAndroid Build Coastguard Worker : std::basic_ofstream<charT, traits>(p.wstring().c_str(), mode)
1000*89c4ff92SAndroid Build Coastguard Worker {
1001*89c4ff92SAndroid Build Coastguard Worker }
open(const path & p,std::ios_base::openmode mode=std::ios_base::out)1002*89c4ff92SAndroid Build Coastguard Worker void open(const path& p, std::ios_base::openmode mode = std::ios_base::out) { std::basic_ofstream<charT, traits>::open(p.wstring().c_str(), mode); }
1003*89c4ff92SAndroid Build Coastguard Worker #else
basic_ofstream(const path & p,std::ios_base::openmode mode=std::ios_base::out)1004*89c4ff92SAndroid Build Coastguard Worker explicit basic_ofstream(const path& p, std::ios_base::openmode mode = std::ios_base::out)
1005*89c4ff92SAndroid Build Coastguard Worker : std::basic_ofstream<charT, traits>(p.string().c_str(), mode)
1006*89c4ff92SAndroid Build Coastguard Worker {
1007*89c4ff92SAndroid Build Coastguard Worker }
open(const path & p,std::ios_base::openmode mode=std::ios_base::out)1008*89c4ff92SAndroid Build Coastguard Worker void open(const path& p, std::ios_base::openmode mode = std::ios_base::out) { std::basic_ofstream<charT, traits>::open(p.string().c_str(), mode); }
1009*89c4ff92SAndroid Build Coastguard Worker #endif
1010*89c4ff92SAndroid Build Coastguard Worker basic_ofstream(const basic_ofstream&) = delete;
1011*89c4ff92SAndroid Build Coastguard Worker const basic_ofstream& operator=(const basic_ofstream&) = delete;
~basic_ofstream()1012*89c4ff92SAndroid Build Coastguard Worker ~basic_ofstream() override {}
1013*89c4ff92SAndroid Build Coastguard Worker };
1014*89c4ff92SAndroid Build Coastguard Worker
1015*89c4ff92SAndroid Build Coastguard Worker template <class charT, class traits = std::char_traits<charT>>
1016*89c4ff92SAndroid Build Coastguard Worker class basic_fstream : public std::basic_fstream<charT, traits>
1017*89c4ff92SAndroid Build Coastguard Worker {
1018*89c4ff92SAndroid Build Coastguard Worker public:
basic_fstream()1019*89c4ff92SAndroid Build Coastguard Worker basic_fstream() {}
1020*89c4ff92SAndroid Build Coastguard Worker #if defined(GHC_OS_WINDOWS) && !defined(__GNUC__)
basic_fstream(const path & p,std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)1021*89c4ff92SAndroid Build Coastguard Worker explicit basic_fstream(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
1022*89c4ff92SAndroid Build Coastguard Worker : std::basic_fstream<charT, traits>(p.wstring().c_str(), mode)
1023*89c4ff92SAndroid Build Coastguard Worker {
1024*89c4ff92SAndroid Build Coastguard Worker }
open(const path & p,std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)1025*89c4ff92SAndroid Build Coastguard Worker void open(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) { std::basic_fstream<charT, traits>::open(p.wstring().c_str(), mode); }
1026*89c4ff92SAndroid Build Coastguard Worker #else
basic_fstream(const path & p,std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)1027*89c4ff92SAndroid Build Coastguard Worker explicit basic_fstream(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
1028*89c4ff92SAndroid Build Coastguard Worker : std::basic_fstream<charT, traits>(p.string().c_str(), mode)
1029*89c4ff92SAndroid Build Coastguard Worker {
1030*89c4ff92SAndroid Build Coastguard Worker }
open(const path & p,std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)1031*89c4ff92SAndroid Build Coastguard Worker void open(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) { std::basic_fstream<charT, traits>::open(p.string().c_str(), mode); }
1032*89c4ff92SAndroid Build Coastguard Worker #endif
1033*89c4ff92SAndroid Build Coastguard Worker basic_fstream(const basic_fstream&) = delete;
1034*89c4ff92SAndroid Build Coastguard Worker const basic_fstream& operator=(const basic_fstream&) = delete;
~basic_fstream()1035*89c4ff92SAndroid Build Coastguard Worker ~basic_fstream() override {}
1036*89c4ff92SAndroid Build Coastguard Worker };
1037*89c4ff92SAndroid Build Coastguard Worker
1038*89c4ff92SAndroid Build Coastguard Worker typedef basic_filebuf<char> filebuf;
1039*89c4ff92SAndroid Build Coastguard Worker typedef basic_filebuf<wchar_t> wfilebuf;
1040*89c4ff92SAndroid Build Coastguard Worker typedef basic_ifstream<char> ifstream;
1041*89c4ff92SAndroid Build Coastguard Worker typedef basic_ifstream<wchar_t> wifstream;
1042*89c4ff92SAndroid Build Coastguard Worker typedef basic_ofstream<char> ofstream;
1043*89c4ff92SAndroid Build Coastguard Worker typedef basic_ofstream<wchar_t> wofstream;
1044*89c4ff92SAndroid Build Coastguard Worker typedef basic_fstream<char> fstream;
1045*89c4ff92SAndroid Build Coastguard Worker typedef basic_fstream<wchar_t> wfstream;
1046*89c4ff92SAndroid Build Coastguard Worker
1047*89c4ff92SAndroid Build Coastguard Worker class GHC_FS_API_CLASS u8arguments
1048*89c4ff92SAndroid Build Coastguard Worker {
1049*89c4ff92SAndroid Build Coastguard Worker public:
1050*89c4ff92SAndroid Build Coastguard Worker u8arguments(int& argc, char**& argv);
~u8arguments()1051*89c4ff92SAndroid Build Coastguard Worker ~u8arguments()
1052*89c4ff92SAndroid Build Coastguard Worker {
1053*89c4ff92SAndroid Build Coastguard Worker _refargc = _argc;
1054*89c4ff92SAndroid Build Coastguard Worker _refargv = _argv;
1055*89c4ff92SAndroid Build Coastguard Worker }
1056*89c4ff92SAndroid Build Coastguard Worker
valid() const1057*89c4ff92SAndroid Build Coastguard Worker bool valid() const { return _isvalid; }
1058*89c4ff92SAndroid Build Coastguard Worker
1059*89c4ff92SAndroid Build Coastguard Worker private:
1060*89c4ff92SAndroid Build Coastguard Worker int _argc;
1061*89c4ff92SAndroid Build Coastguard Worker char** _argv;
1062*89c4ff92SAndroid Build Coastguard Worker int& _refargc;
1063*89c4ff92SAndroid Build Coastguard Worker char**& _refargv;
1064*89c4ff92SAndroid Build Coastguard Worker bool _isvalid;
1065*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
1066*89c4ff92SAndroid Build Coastguard Worker std::vector<std::string> _args;
1067*89c4ff92SAndroid Build Coastguard Worker std::vector<char*> _argp;
1068*89c4ff92SAndroid Build Coastguard Worker #endif
1069*89c4ff92SAndroid Build Coastguard Worker };
1070*89c4ff92SAndroid Build Coastguard Worker
1071*89c4ff92SAndroid Build Coastguard Worker //-------------------------------------------------------------------------------------------------
1072*89c4ff92SAndroid Build Coastguard Worker // Implementation
1073*89c4ff92SAndroid Build Coastguard Worker //-------------------------------------------------------------------------------------------------
1074*89c4ff92SAndroid Build Coastguard Worker
1075*89c4ff92SAndroid Build Coastguard Worker namespace detail {
1076*89c4ff92SAndroid Build Coastguard Worker // GHC_FS_API void postprocess_path_with_format(path::impl_string_type& p, path::format fmt);
1077*89c4ff92SAndroid Build Coastguard Worker enum utf8_states_t { S_STRT = 0, S_RJCT = 8 };
1078*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API void appendUTF8(std::string& str, uint32_t unicode);
1079*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_surrogate(uint32_t c);
1080*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_high_surrogate(uint32_t c);
1081*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API bool is_low_surrogate(uint32_t c);
1082*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API unsigned consumeUtf8Fragment(const unsigned state, const uint8_t fragment, uint32_t& codepoint);
1083*89c4ff92SAndroid Build Coastguard Worker enum class portable_error {
1084*89c4ff92SAndroid Build Coastguard Worker none = 0,
1085*89c4ff92SAndroid Build Coastguard Worker exists,
1086*89c4ff92SAndroid Build Coastguard Worker not_found,
1087*89c4ff92SAndroid Build Coastguard Worker not_supported,
1088*89c4ff92SAndroid Build Coastguard Worker not_implemented,
1089*89c4ff92SAndroid Build Coastguard Worker invalid_argument,
1090*89c4ff92SAndroid Build Coastguard Worker is_a_directory,
1091*89c4ff92SAndroid Build Coastguard Worker };
1092*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API std::error_code make_error_code(portable_error err);
1093*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
1094*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API std::error_code make_system_error(uint32_t err = 0);
1095*89c4ff92SAndroid Build Coastguard Worker #else
1096*89c4ff92SAndroid Build Coastguard Worker GHC_FS_API std::error_code make_system_error(int err = 0);
1097*89c4ff92SAndroid Build Coastguard Worker #endif
1098*89c4ff92SAndroid Build Coastguard Worker } // namespace detail
1099*89c4ff92SAndroid Build Coastguard Worker
1100*89c4ff92SAndroid Build Coastguard Worker namespace detail {
1101*89c4ff92SAndroid Build Coastguard Worker
1102*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_EXPAND_IMPL
1103*89c4ff92SAndroid Build Coastguard Worker
make_error_code(portable_error err)1104*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE std::error_code make_error_code(portable_error err)
1105*89c4ff92SAndroid Build Coastguard Worker {
1106*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
1107*89c4ff92SAndroid Build Coastguard Worker switch (err) {
1108*89c4ff92SAndroid Build Coastguard Worker case portable_error::none:
1109*89c4ff92SAndroid Build Coastguard Worker return std::error_code();
1110*89c4ff92SAndroid Build Coastguard Worker case portable_error::exists:
1111*89c4ff92SAndroid Build Coastguard Worker return std::error_code(ERROR_ALREADY_EXISTS, std::system_category());
1112*89c4ff92SAndroid Build Coastguard Worker case portable_error::not_found:
1113*89c4ff92SAndroid Build Coastguard Worker return std::error_code(ERROR_PATH_NOT_FOUND, std::system_category());
1114*89c4ff92SAndroid Build Coastguard Worker case portable_error::not_supported:
1115*89c4ff92SAndroid Build Coastguard Worker return std::error_code(ERROR_NOT_SUPPORTED, std::system_category());
1116*89c4ff92SAndroid Build Coastguard Worker case portable_error::not_implemented:
1117*89c4ff92SAndroid Build Coastguard Worker return std::error_code(ERROR_CALL_NOT_IMPLEMENTED, std::system_category());
1118*89c4ff92SAndroid Build Coastguard Worker case portable_error::invalid_argument:
1119*89c4ff92SAndroid Build Coastguard Worker return std::error_code(ERROR_INVALID_PARAMETER, std::system_category());
1120*89c4ff92SAndroid Build Coastguard Worker case portable_error::is_a_directory:
1121*89c4ff92SAndroid Build Coastguard Worker #ifdef ERROR_DIRECTORY_NOT_SUPPORTED
1122*89c4ff92SAndroid Build Coastguard Worker return std::error_code(ERROR_DIRECTORY_NOT_SUPPORTED, std::system_category());
1123*89c4ff92SAndroid Build Coastguard Worker #else
1124*89c4ff92SAndroid Build Coastguard Worker return std::error_code(ERROR_NOT_SUPPORTED, std::system_category());
1125*89c4ff92SAndroid Build Coastguard Worker #endif
1126*89c4ff92SAndroid Build Coastguard Worker }
1127*89c4ff92SAndroid Build Coastguard Worker #else
1128*89c4ff92SAndroid Build Coastguard Worker switch (err) {
1129*89c4ff92SAndroid Build Coastguard Worker case portable_error::none:
1130*89c4ff92SAndroid Build Coastguard Worker return std::error_code();
1131*89c4ff92SAndroid Build Coastguard Worker case portable_error::exists:
1132*89c4ff92SAndroid Build Coastguard Worker return std::error_code(EEXIST, std::system_category());
1133*89c4ff92SAndroid Build Coastguard Worker case portable_error::not_found:
1134*89c4ff92SAndroid Build Coastguard Worker return std::error_code(ENOENT, std::system_category());
1135*89c4ff92SAndroid Build Coastguard Worker case portable_error::not_supported:
1136*89c4ff92SAndroid Build Coastguard Worker return std::error_code(ENOTSUP, std::system_category());
1137*89c4ff92SAndroid Build Coastguard Worker case portable_error::not_implemented:
1138*89c4ff92SAndroid Build Coastguard Worker return std::error_code(ENOSYS, std::system_category());
1139*89c4ff92SAndroid Build Coastguard Worker case portable_error::invalid_argument:
1140*89c4ff92SAndroid Build Coastguard Worker return std::error_code(EINVAL, std::system_category());
1141*89c4ff92SAndroid Build Coastguard Worker case portable_error::is_a_directory:
1142*89c4ff92SAndroid Build Coastguard Worker return std::error_code(EISDIR, std::system_category());
1143*89c4ff92SAndroid Build Coastguard Worker }
1144*89c4ff92SAndroid Build Coastguard Worker #endif
1145*89c4ff92SAndroid Build Coastguard Worker return std::error_code();
1146*89c4ff92SAndroid Build Coastguard Worker }
1147*89c4ff92SAndroid Build Coastguard Worker
1148*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
make_system_error(uint32_t err)1149*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE std::error_code make_system_error(uint32_t err)
1150*89c4ff92SAndroid Build Coastguard Worker {
1151*89c4ff92SAndroid Build Coastguard Worker return std::error_code(err ? static_cast<int>(err) : static_cast<int>(::GetLastError()), std::system_category());
1152*89c4ff92SAndroid Build Coastguard Worker }
1153*89c4ff92SAndroid Build Coastguard Worker #else
make_system_error(int err)1154*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE std::error_code make_system_error(int err)
1155*89c4ff92SAndroid Build Coastguard Worker {
1156*89c4ff92SAndroid Build Coastguard Worker return std::error_code(err ? err : errno, std::system_category());
1157*89c4ff92SAndroid Build Coastguard Worker }
1158*89c4ff92SAndroid Build Coastguard Worker #endif
1159*89c4ff92SAndroid Build Coastguard Worker
1160*89c4ff92SAndroid Build Coastguard Worker #endif // GHC_EXPAND_IMPL
1161*89c4ff92SAndroid Build Coastguard Worker
1162*89c4ff92SAndroid Build Coastguard Worker template <typename Enum>
1163*89c4ff92SAndroid Build Coastguard Worker using EnableBitmask = typename std::enable_if<std::is_same<Enum, perms>::value || std::is_same<Enum, perm_options>::value || std::is_same<Enum, copy_options>::value || std::is_same<Enum, directory_options>::value, Enum>::type;
1164*89c4ff92SAndroid Build Coastguard Worker } // namespace detail
1165*89c4ff92SAndroid Build Coastguard Worker
1166*89c4ff92SAndroid Build Coastguard Worker template <typename Enum>
operator &(Enum X,Enum Y)1167*89c4ff92SAndroid Build Coastguard Worker detail::EnableBitmask<Enum> operator&(Enum X, Enum Y)
1168*89c4ff92SAndroid Build Coastguard Worker {
1169*89c4ff92SAndroid Build Coastguard Worker using underlying = typename std::underlying_type<Enum>::type;
1170*89c4ff92SAndroid Build Coastguard Worker return static_cast<Enum>(static_cast<underlying>(X) & static_cast<underlying>(Y));
1171*89c4ff92SAndroid Build Coastguard Worker }
1172*89c4ff92SAndroid Build Coastguard Worker
1173*89c4ff92SAndroid Build Coastguard Worker template <typename Enum>
operator |(Enum X,Enum Y)1174*89c4ff92SAndroid Build Coastguard Worker detail::EnableBitmask<Enum> operator|(Enum X, Enum Y)
1175*89c4ff92SAndroid Build Coastguard Worker {
1176*89c4ff92SAndroid Build Coastguard Worker using underlying = typename std::underlying_type<Enum>::type;
1177*89c4ff92SAndroid Build Coastguard Worker return static_cast<Enum>(static_cast<underlying>(X) | static_cast<underlying>(Y));
1178*89c4ff92SAndroid Build Coastguard Worker }
1179*89c4ff92SAndroid Build Coastguard Worker
1180*89c4ff92SAndroid Build Coastguard Worker template <typename Enum>
operator ^(Enum X,Enum Y)1181*89c4ff92SAndroid Build Coastguard Worker detail::EnableBitmask<Enum> operator^(Enum X, Enum Y)
1182*89c4ff92SAndroid Build Coastguard Worker {
1183*89c4ff92SAndroid Build Coastguard Worker using underlying = typename std::underlying_type<Enum>::type;
1184*89c4ff92SAndroid Build Coastguard Worker return static_cast<Enum>(static_cast<underlying>(X) ^ static_cast<underlying>(Y));
1185*89c4ff92SAndroid Build Coastguard Worker }
1186*89c4ff92SAndroid Build Coastguard Worker
1187*89c4ff92SAndroid Build Coastguard Worker template <typename Enum>
operator ~(Enum X)1188*89c4ff92SAndroid Build Coastguard Worker detail::EnableBitmask<Enum> operator~(Enum X)
1189*89c4ff92SAndroid Build Coastguard Worker {
1190*89c4ff92SAndroid Build Coastguard Worker using underlying = typename std::underlying_type<Enum>::type;
1191*89c4ff92SAndroid Build Coastguard Worker return static_cast<Enum>(~static_cast<underlying>(X));
1192*89c4ff92SAndroid Build Coastguard Worker }
1193*89c4ff92SAndroid Build Coastguard Worker
1194*89c4ff92SAndroid Build Coastguard Worker template <typename Enum>
operator &=(Enum & X,Enum Y)1195*89c4ff92SAndroid Build Coastguard Worker detail::EnableBitmask<Enum>& operator&=(Enum& X, Enum Y)
1196*89c4ff92SAndroid Build Coastguard Worker {
1197*89c4ff92SAndroid Build Coastguard Worker X = X & Y;
1198*89c4ff92SAndroid Build Coastguard Worker return X;
1199*89c4ff92SAndroid Build Coastguard Worker }
1200*89c4ff92SAndroid Build Coastguard Worker
1201*89c4ff92SAndroid Build Coastguard Worker template <typename Enum>
operator |=(Enum & X,Enum Y)1202*89c4ff92SAndroid Build Coastguard Worker detail::EnableBitmask<Enum>& operator|=(Enum& X, Enum Y)
1203*89c4ff92SAndroid Build Coastguard Worker {
1204*89c4ff92SAndroid Build Coastguard Worker X = X | Y;
1205*89c4ff92SAndroid Build Coastguard Worker return X;
1206*89c4ff92SAndroid Build Coastguard Worker }
1207*89c4ff92SAndroid Build Coastguard Worker
1208*89c4ff92SAndroid Build Coastguard Worker template <typename Enum>
operator ^=(Enum & X,Enum Y)1209*89c4ff92SAndroid Build Coastguard Worker detail::EnableBitmask<Enum>& operator^=(Enum& X, Enum Y)
1210*89c4ff92SAndroid Build Coastguard Worker {
1211*89c4ff92SAndroid Build Coastguard Worker X = X ^ Y;
1212*89c4ff92SAndroid Build Coastguard Worker return X;
1213*89c4ff92SAndroid Build Coastguard Worker }
1214*89c4ff92SAndroid Build Coastguard Worker
1215*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_EXPAND_IMPL
1216*89c4ff92SAndroid Build Coastguard Worker
1217*89c4ff92SAndroid Build Coastguard Worker namespace detail {
1218*89c4ff92SAndroid Build Coastguard Worker
in_range(uint32_t c,uint32_t lo,uint32_t hi)1219*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool in_range(uint32_t c, uint32_t lo, uint32_t hi)
1220*89c4ff92SAndroid Build Coastguard Worker {
1221*89c4ff92SAndroid Build Coastguard Worker return (static_cast<uint32_t>(c - lo) < (hi - lo + 1));
1222*89c4ff92SAndroid Build Coastguard Worker }
1223*89c4ff92SAndroid Build Coastguard Worker
is_surrogate(uint32_t c)1224*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_surrogate(uint32_t c)
1225*89c4ff92SAndroid Build Coastguard Worker {
1226*89c4ff92SAndroid Build Coastguard Worker return in_range(c, 0xd800, 0xdfff);
1227*89c4ff92SAndroid Build Coastguard Worker }
1228*89c4ff92SAndroid Build Coastguard Worker
is_high_surrogate(uint32_t c)1229*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_high_surrogate(uint32_t c)
1230*89c4ff92SAndroid Build Coastguard Worker {
1231*89c4ff92SAndroid Build Coastguard Worker return (c & 0xfffffc00) == 0xd800;
1232*89c4ff92SAndroid Build Coastguard Worker }
1233*89c4ff92SAndroid Build Coastguard Worker
is_low_surrogate(uint32_t c)1234*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_low_surrogate(uint32_t c)
1235*89c4ff92SAndroid Build Coastguard Worker {
1236*89c4ff92SAndroid Build Coastguard Worker return (c & 0xfffffc00) == 0xdc00;
1237*89c4ff92SAndroid Build Coastguard Worker }
1238*89c4ff92SAndroid Build Coastguard Worker
appendUTF8(std::string & str,uint32_t unicode)1239*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void appendUTF8(std::string& str, uint32_t unicode)
1240*89c4ff92SAndroid Build Coastguard Worker {
1241*89c4ff92SAndroid Build Coastguard Worker if (unicode <= 0x7f) {
1242*89c4ff92SAndroid Build Coastguard Worker str.push_back(static_cast<char>(unicode));
1243*89c4ff92SAndroid Build Coastguard Worker }
1244*89c4ff92SAndroid Build Coastguard Worker else if (unicode >= 0x80 && unicode <= 0x7ff) {
1245*89c4ff92SAndroid Build Coastguard Worker str.push_back(static_cast<char>((unicode >> 6) + 192));
1246*89c4ff92SAndroid Build Coastguard Worker str.push_back(static_cast<char>((unicode & 0x3f) + 128));
1247*89c4ff92SAndroid Build Coastguard Worker }
1248*89c4ff92SAndroid Build Coastguard Worker else if ((unicode >= 0x800 && unicode <= 0xd7ff) || (unicode >= 0xe000 && unicode <= 0xffff)) {
1249*89c4ff92SAndroid Build Coastguard Worker str.push_back(static_cast<char>((unicode >> 12) + 224));
1250*89c4ff92SAndroid Build Coastguard Worker str.push_back(static_cast<char>(((unicode & 0xfff) >> 6) + 128));
1251*89c4ff92SAndroid Build Coastguard Worker str.push_back(static_cast<char>((unicode & 0x3f) + 128));
1252*89c4ff92SAndroid Build Coastguard Worker }
1253*89c4ff92SAndroid Build Coastguard Worker else if (unicode >= 0x10000 && unicode <= 0x10ffff) {
1254*89c4ff92SAndroid Build Coastguard Worker str.push_back(static_cast<char>((unicode >> 18) + 240));
1255*89c4ff92SAndroid Build Coastguard Worker str.push_back(static_cast<char>(((unicode & 0x3ffff) >> 12) + 128));
1256*89c4ff92SAndroid Build Coastguard Worker str.push_back(static_cast<char>(((unicode & 0xfff) >> 6) + 128));
1257*89c4ff92SAndroid Build Coastguard Worker str.push_back(static_cast<char>((unicode & 0x3f) + 128));
1258*89c4ff92SAndroid Build Coastguard Worker }
1259*89c4ff92SAndroid Build Coastguard Worker else {
1260*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_RAISE_UNICODE_ERRORS
1261*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error("Illegal code point for unicode character.", str, std::make_error_code(std::errc::illegal_byte_sequence));
1262*89c4ff92SAndroid Build Coastguard Worker #else
1263*89c4ff92SAndroid Build Coastguard Worker appendUTF8(str, 0xfffd);
1264*89c4ff92SAndroid Build Coastguard Worker #endif
1265*89c4ff92SAndroid Build Coastguard Worker }
1266*89c4ff92SAndroid Build Coastguard Worker }
1267*89c4ff92SAndroid Build Coastguard Worker
1268*89c4ff92SAndroid Build Coastguard Worker // Thanks to Bjoern Hoehrmann (https://bjoern.hoehrmann.de/utf-8/decoder/dfa/)
1269*89c4ff92SAndroid Build Coastguard Worker // and Taylor R Campbell for the ideas to this DFA approach of UTF-8 decoding;
1270*89c4ff92SAndroid Build Coastguard Worker // Generating debugging and shrinking my own DFA from scratch was a day of fun!
consumeUtf8Fragment(const unsigned state,const uint8_t fragment,uint32_t & codepoint)1271*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE unsigned consumeUtf8Fragment(const unsigned state, const uint8_t fragment, uint32_t& codepoint)
1272*89c4ff92SAndroid Build Coastguard Worker {
1273*89c4ff92SAndroid Build Coastguard Worker static const uint32_t utf8_state_info[] = {
1274*89c4ff92SAndroid Build Coastguard Worker // encoded states
1275*89c4ff92SAndroid Build Coastguard Worker 0x11111111u, 0x11111111u, 0x77777777u, 0x77777777u, 0x88888888u, 0x88888888u, 0x88888888u, 0x88888888u, 0x22222299u, 0x22222222u, 0x22222222u, 0x22222222u, 0x3333333au, 0x33433333u, 0x9995666bu, 0x99999999u,
1276*89c4ff92SAndroid Build Coastguard Worker 0x88888880u, 0x22818108u, 0x88888881u, 0x88888882u, 0x88888884u, 0x88888887u, 0x88888886u, 0x82218108u, 0x82281108u, 0x88888888u, 0x88888883u, 0x88888885u, 0u, 0u, 0u, 0u,
1277*89c4ff92SAndroid Build Coastguard Worker };
1278*89c4ff92SAndroid Build Coastguard Worker uint8_t category = fragment < 128 ? 0 : (utf8_state_info[(fragment >> 3) & 0xf] >> ((fragment & 7) << 2)) & 0xf;
1279*89c4ff92SAndroid Build Coastguard Worker codepoint = (state ? (codepoint << 6) | (fragment & 0x3fu) : (0xffu >> category) & fragment);
1280*89c4ff92SAndroid Build Coastguard Worker return state == S_RJCT ? static_cast<unsigned>(S_RJCT) : static_cast<unsigned>((utf8_state_info[category + 16] >> (state << 2)) & 0xf);
1281*89c4ff92SAndroid Build Coastguard Worker }
1282*89c4ff92SAndroid Build Coastguard Worker
validUtf8(const std::string & utf8String)1283*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool validUtf8(const std::string& utf8String)
1284*89c4ff92SAndroid Build Coastguard Worker {
1285*89c4ff92SAndroid Build Coastguard Worker std::string::const_iterator iter = utf8String.begin();
1286*89c4ff92SAndroid Build Coastguard Worker unsigned utf8_state = S_STRT;
1287*89c4ff92SAndroid Build Coastguard Worker std::uint32_t codepoint = 0;
1288*89c4ff92SAndroid Build Coastguard Worker while (iter < utf8String.end()) {
1289*89c4ff92SAndroid Build Coastguard Worker if ((utf8_state = consumeUtf8Fragment(utf8_state, static_cast<uint8_t>(*iter++), codepoint)) == S_RJCT) {
1290*89c4ff92SAndroid Build Coastguard Worker return false;
1291*89c4ff92SAndroid Build Coastguard Worker }
1292*89c4ff92SAndroid Build Coastguard Worker }
1293*89c4ff92SAndroid Build Coastguard Worker if (utf8_state) {
1294*89c4ff92SAndroid Build Coastguard Worker return false;
1295*89c4ff92SAndroid Build Coastguard Worker }
1296*89c4ff92SAndroid Build Coastguard Worker return true;
1297*89c4ff92SAndroid Build Coastguard Worker }
1298*89c4ff92SAndroid Build Coastguard Worker
1299*89c4ff92SAndroid Build Coastguard Worker } // namespace detail
1300*89c4ff92SAndroid Build Coastguard Worker
1301*89c4ff92SAndroid Build Coastguard Worker #endif
1302*89c4ff92SAndroid Build Coastguard Worker
1303*89c4ff92SAndroid Build Coastguard Worker namespace detail {
1304*89c4ff92SAndroid Build Coastguard Worker
1305*89c4ff92SAndroid Build Coastguard Worker template <class StringType, typename std::enable_if<(sizeof(typename StringType::value_type) == 1)>::type* = nullptr>
fromUtf8(const std::string & utf8String,const typename StringType::allocator_type & alloc=typename StringType::allocator_type ())1306*89c4ff92SAndroid Build Coastguard Worker inline StringType fromUtf8(const std::string& utf8String, const typename StringType::allocator_type& alloc = typename StringType::allocator_type())
1307*89c4ff92SAndroid Build Coastguard Worker {
1308*89c4ff92SAndroid Build Coastguard Worker return StringType(utf8String.begin(), utf8String.end(), alloc);
1309*89c4ff92SAndroid Build Coastguard Worker }
1310*89c4ff92SAndroid Build Coastguard Worker
1311*89c4ff92SAndroid Build Coastguard Worker template <class StringType, typename std::enable_if<(sizeof(typename StringType::value_type) == 2)>::type* = nullptr>
fromUtf8(const std::string & utf8String,const typename StringType::allocator_type & alloc=typename StringType::allocator_type ())1312*89c4ff92SAndroid Build Coastguard Worker inline StringType fromUtf8(const std::string& utf8String, const typename StringType::allocator_type& alloc = typename StringType::allocator_type())
1313*89c4ff92SAndroid Build Coastguard Worker {
1314*89c4ff92SAndroid Build Coastguard Worker StringType result(alloc);
1315*89c4ff92SAndroid Build Coastguard Worker result.reserve(utf8String.length());
1316*89c4ff92SAndroid Build Coastguard Worker std::string::const_iterator iter = utf8String.begin();
1317*89c4ff92SAndroid Build Coastguard Worker unsigned utf8_state = S_STRT;
1318*89c4ff92SAndroid Build Coastguard Worker std::uint32_t codepoint = 0;
1319*89c4ff92SAndroid Build Coastguard Worker while (iter < utf8String.end()) {
1320*89c4ff92SAndroid Build Coastguard Worker if ((utf8_state = consumeUtf8Fragment(utf8_state, static_cast<uint8_t>(*iter++), codepoint)) == S_STRT) {
1321*89c4ff92SAndroid Build Coastguard Worker if (codepoint <= 0xffff) {
1322*89c4ff92SAndroid Build Coastguard Worker result += static_cast<typename StringType::value_type>(codepoint);
1323*89c4ff92SAndroid Build Coastguard Worker }
1324*89c4ff92SAndroid Build Coastguard Worker else {
1325*89c4ff92SAndroid Build Coastguard Worker codepoint -= 0x10000;
1326*89c4ff92SAndroid Build Coastguard Worker result += static_cast<typename StringType::value_type>((codepoint >> 10) + 0xd800);
1327*89c4ff92SAndroid Build Coastguard Worker result += static_cast<typename StringType::value_type>((codepoint & 0x3ff) + 0xdc00);
1328*89c4ff92SAndroid Build Coastguard Worker }
1329*89c4ff92SAndroid Build Coastguard Worker codepoint = 0;
1330*89c4ff92SAndroid Build Coastguard Worker }
1331*89c4ff92SAndroid Build Coastguard Worker else if (utf8_state == S_RJCT) {
1332*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_RAISE_UNICODE_ERRORS
1333*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error("Illegal byte sequence for unicode character.", utf8String, std::make_error_code(std::errc::illegal_byte_sequence));
1334*89c4ff92SAndroid Build Coastguard Worker #else
1335*89c4ff92SAndroid Build Coastguard Worker result += static_cast<typename StringType::value_type>(0xfffd);
1336*89c4ff92SAndroid Build Coastguard Worker utf8_state = S_STRT;
1337*89c4ff92SAndroid Build Coastguard Worker codepoint = 0;
1338*89c4ff92SAndroid Build Coastguard Worker #endif
1339*89c4ff92SAndroid Build Coastguard Worker }
1340*89c4ff92SAndroid Build Coastguard Worker }
1341*89c4ff92SAndroid Build Coastguard Worker if (utf8_state) {
1342*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_RAISE_UNICODE_ERRORS
1343*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error("Illegal byte sequence for unicode character.", utf8String, std::make_error_code(std::errc::illegal_byte_sequence));
1344*89c4ff92SAndroid Build Coastguard Worker #else
1345*89c4ff92SAndroid Build Coastguard Worker result += static_cast<typename StringType::value_type>(0xfffd);
1346*89c4ff92SAndroid Build Coastguard Worker #endif
1347*89c4ff92SAndroid Build Coastguard Worker }
1348*89c4ff92SAndroid Build Coastguard Worker return result;
1349*89c4ff92SAndroid Build Coastguard Worker }
1350*89c4ff92SAndroid Build Coastguard Worker
1351*89c4ff92SAndroid Build Coastguard Worker template <class StringType, typename std::enable_if<(sizeof(typename StringType::value_type) == 4)>::type* = nullptr>
fromUtf8(const std::string & utf8String,const typename StringType::allocator_type & alloc=typename StringType::allocator_type ())1352*89c4ff92SAndroid Build Coastguard Worker inline StringType fromUtf8(const std::string& utf8String, const typename StringType::allocator_type& alloc = typename StringType::allocator_type())
1353*89c4ff92SAndroid Build Coastguard Worker {
1354*89c4ff92SAndroid Build Coastguard Worker StringType result(alloc);
1355*89c4ff92SAndroid Build Coastguard Worker result.reserve(utf8String.length());
1356*89c4ff92SAndroid Build Coastguard Worker std::string::const_iterator iter = utf8String.begin();
1357*89c4ff92SAndroid Build Coastguard Worker unsigned utf8_state = S_STRT;
1358*89c4ff92SAndroid Build Coastguard Worker std::uint32_t codepoint = 0;
1359*89c4ff92SAndroid Build Coastguard Worker while (iter < utf8String.end()) {
1360*89c4ff92SAndroid Build Coastguard Worker if ((utf8_state = consumeUtf8Fragment(utf8_state, static_cast<uint8_t>(*iter++), codepoint)) == S_STRT) {
1361*89c4ff92SAndroid Build Coastguard Worker result += static_cast<typename StringType::value_type>(codepoint);
1362*89c4ff92SAndroid Build Coastguard Worker codepoint = 0;
1363*89c4ff92SAndroid Build Coastguard Worker }
1364*89c4ff92SAndroid Build Coastguard Worker else if (utf8_state == S_RJCT) {
1365*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_RAISE_UNICODE_ERRORS
1366*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error("Illegal byte sequence for unicode character.", utf8String, std::make_error_code(std::errc::illegal_byte_sequence));
1367*89c4ff92SAndroid Build Coastguard Worker #else
1368*89c4ff92SAndroid Build Coastguard Worker result += static_cast<typename StringType::value_type>(0xfffd);
1369*89c4ff92SAndroid Build Coastguard Worker utf8_state = S_STRT;
1370*89c4ff92SAndroid Build Coastguard Worker codepoint = 0;
1371*89c4ff92SAndroid Build Coastguard Worker #endif
1372*89c4ff92SAndroid Build Coastguard Worker }
1373*89c4ff92SAndroid Build Coastguard Worker }
1374*89c4ff92SAndroid Build Coastguard Worker if (utf8_state) {
1375*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_RAISE_UNICODE_ERRORS
1376*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error("Illegal byte sequence for unicode character.", utf8String, std::make_error_code(std::errc::illegal_byte_sequence));
1377*89c4ff92SAndroid Build Coastguard Worker #else
1378*89c4ff92SAndroid Build Coastguard Worker result += static_cast<typename StringType::value_type>(0xfffd);
1379*89c4ff92SAndroid Build Coastguard Worker #endif
1380*89c4ff92SAndroid Build Coastguard Worker }
1381*89c4ff92SAndroid Build Coastguard Worker return result;
1382*89c4ff92SAndroid Build Coastguard Worker }
1383*89c4ff92SAndroid Build Coastguard Worker
1384*89c4ff92SAndroid Build Coastguard Worker template <typename charT, typename traits, typename Alloc, typename std::enable_if<(sizeof(charT) == 1), int>::type size = 1>
toUtf8(const std::basic_string<charT,traits,Alloc> & unicodeString)1385*89c4ff92SAndroid Build Coastguard Worker inline std::string toUtf8(const std::basic_string<charT, traits, Alloc>& unicodeString)
1386*89c4ff92SAndroid Build Coastguard Worker {
1387*89c4ff92SAndroid Build Coastguard Worker return std::string(unicodeString.begin(), unicodeString.end());
1388*89c4ff92SAndroid Build Coastguard Worker }
1389*89c4ff92SAndroid Build Coastguard Worker
1390*89c4ff92SAndroid Build Coastguard Worker template <typename charT, typename traits, typename Alloc, typename std::enable_if<(sizeof(charT) == 2), int>::type size = 2>
toUtf8(const std::basic_string<charT,traits,Alloc> & unicodeString)1391*89c4ff92SAndroid Build Coastguard Worker inline std::string toUtf8(const std::basic_string<charT, traits, Alloc>& unicodeString)
1392*89c4ff92SAndroid Build Coastguard Worker {
1393*89c4ff92SAndroid Build Coastguard Worker std::string result;
1394*89c4ff92SAndroid Build Coastguard Worker for (auto iter = unicodeString.begin(); iter != unicodeString.end(); ++iter) {
1395*89c4ff92SAndroid Build Coastguard Worker char32_t c = *iter;
1396*89c4ff92SAndroid Build Coastguard Worker if (is_surrogate(c)) {
1397*89c4ff92SAndroid Build Coastguard Worker ++iter;
1398*89c4ff92SAndroid Build Coastguard Worker if (iter != unicodeString.end() && is_high_surrogate(c) && is_low_surrogate(*iter)) {
1399*89c4ff92SAndroid Build Coastguard Worker appendUTF8(result, (char32_t(c) << 10) + *iter - 0x35fdc00);
1400*89c4ff92SAndroid Build Coastguard Worker }
1401*89c4ff92SAndroid Build Coastguard Worker else {
1402*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_RAISE_UNICODE_ERRORS
1403*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error("Illegal code point for unicode character.", result, std::make_error_code(std::errc::illegal_byte_sequence));
1404*89c4ff92SAndroid Build Coastguard Worker #else
1405*89c4ff92SAndroid Build Coastguard Worker appendUTF8(result, 0xfffd);
1406*89c4ff92SAndroid Build Coastguard Worker if(iter == unicodeString.end()) {
1407*89c4ff92SAndroid Build Coastguard Worker break;
1408*89c4ff92SAndroid Build Coastguard Worker }
1409*89c4ff92SAndroid Build Coastguard Worker #endif
1410*89c4ff92SAndroid Build Coastguard Worker }
1411*89c4ff92SAndroid Build Coastguard Worker }
1412*89c4ff92SAndroid Build Coastguard Worker else {
1413*89c4ff92SAndroid Build Coastguard Worker appendUTF8(result, c);
1414*89c4ff92SAndroid Build Coastguard Worker }
1415*89c4ff92SAndroid Build Coastguard Worker }
1416*89c4ff92SAndroid Build Coastguard Worker return result;
1417*89c4ff92SAndroid Build Coastguard Worker }
1418*89c4ff92SAndroid Build Coastguard Worker
1419*89c4ff92SAndroid Build Coastguard Worker template <typename charT, typename traits, typename Alloc, typename std::enable_if<(sizeof(charT) == 4), int>::type size = 4>
toUtf8(const std::basic_string<charT,traits,Alloc> & unicodeString)1420*89c4ff92SAndroid Build Coastguard Worker inline std::string toUtf8(const std::basic_string<charT, traits, Alloc>& unicodeString)
1421*89c4ff92SAndroid Build Coastguard Worker {
1422*89c4ff92SAndroid Build Coastguard Worker std::string result;
1423*89c4ff92SAndroid Build Coastguard Worker for (auto c : unicodeString) {
1424*89c4ff92SAndroid Build Coastguard Worker appendUTF8(result, static_cast<uint32_t>(c));
1425*89c4ff92SAndroid Build Coastguard Worker }
1426*89c4ff92SAndroid Build Coastguard Worker return result;
1427*89c4ff92SAndroid Build Coastguard Worker }
1428*89c4ff92SAndroid Build Coastguard Worker
1429*89c4ff92SAndroid Build Coastguard Worker template <typename charT>
toUtf8(const charT * unicodeString)1430*89c4ff92SAndroid Build Coastguard Worker inline std::string toUtf8(const charT* unicodeString)
1431*89c4ff92SAndroid Build Coastguard Worker {
1432*89c4ff92SAndroid Build Coastguard Worker return toUtf8(std::basic_string<charT, std::char_traits<charT>>(unicodeString));
1433*89c4ff92SAndroid Build Coastguard Worker }
1434*89c4ff92SAndroid Build Coastguard Worker
1435*89c4ff92SAndroid Build Coastguard Worker } // namespace detail
1436*89c4ff92SAndroid Build Coastguard Worker
1437*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_EXPAND_IMPL
1438*89c4ff92SAndroid Build Coastguard Worker
1439*89c4ff92SAndroid Build Coastguard Worker namespace detail {
1440*89c4ff92SAndroid Build Coastguard Worker
startsWith(const std::string & what,const std::string & with)1441*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool startsWith(const std::string& what, const std::string& with)
1442*89c4ff92SAndroid Build Coastguard Worker {
1443*89c4ff92SAndroid Build Coastguard Worker return with.length() <= what.length() && equal(with.begin(), with.end(), what.begin());
1444*89c4ff92SAndroid Build Coastguard Worker }
1445*89c4ff92SAndroid Build Coastguard Worker
1446*89c4ff92SAndroid Build Coastguard Worker } // namespace detail
1447*89c4ff92SAndroid Build Coastguard Worker
postprocess_path_with_format(path::impl_string_type & p,path::format fmt)1448*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void path::postprocess_path_with_format(path::impl_string_type& p, path::format fmt)
1449*89c4ff92SAndroid Build Coastguard Worker {
1450*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_RAISE_UNICODE_ERRORS
1451*89c4ff92SAndroid Build Coastguard Worker if(!detail::validUtf8(p)) {
1452*89c4ff92SAndroid Build Coastguard Worker path t;
1453*89c4ff92SAndroid Build Coastguard Worker t._path = p;
1454*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error("Illegal byte sequence for unicode character.", t, std::make_error_code(std::errc::illegal_byte_sequence));
1455*89c4ff92SAndroid Build Coastguard Worker }
1456*89c4ff92SAndroid Build Coastguard Worker #endif
1457*89c4ff92SAndroid Build Coastguard Worker switch (fmt) {
1458*89c4ff92SAndroid Build Coastguard Worker #ifndef GHC_OS_WINDOWS
1459*89c4ff92SAndroid Build Coastguard Worker case path::auto_format:
1460*89c4ff92SAndroid Build Coastguard Worker case path::native_format:
1461*89c4ff92SAndroid Build Coastguard Worker #endif
1462*89c4ff92SAndroid Build Coastguard Worker case path::generic_format:
1463*89c4ff92SAndroid Build Coastguard Worker // nothing to do
1464*89c4ff92SAndroid Build Coastguard Worker break;
1465*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
1466*89c4ff92SAndroid Build Coastguard Worker case path::auto_format:
1467*89c4ff92SAndroid Build Coastguard Worker case path::native_format:
1468*89c4ff92SAndroid Build Coastguard Worker if (detail::startsWith(p, std::string("\\\\?\\"))) {
1469*89c4ff92SAndroid Build Coastguard Worker // remove Windows long filename marker
1470*89c4ff92SAndroid Build Coastguard Worker p.erase(0, 4);
1471*89c4ff92SAndroid Build Coastguard Worker if (detail::startsWith(p, std::string("UNC\\"))) {
1472*89c4ff92SAndroid Build Coastguard Worker p.erase(0, 2);
1473*89c4ff92SAndroid Build Coastguard Worker p[0] = '\\';
1474*89c4ff92SAndroid Build Coastguard Worker }
1475*89c4ff92SAndroid Build Coastguard Worker }
1476*89c4ff92SAndroid Build Coastguard Worker for (auto& c : p) {
1477*89c4ff92SAndroid Build Coastguard Worker if (c == '\\') {
1478*89c4ff92SAndroid Build Coastguard Worker c = '/';
1479*89c4ff92SAndroid Build Coastguard Worker }
1480*89c4ff92SAndroid Build Coastguard Worker }
1481*89c4ff92SAndroid Build Coastguard Worker break;
1482*89c4ff92SAndroid Build Coastguard Worker #endif
1483*89c4ff92SAndroid Build Coastguard Worker }
1484*89c4ff92SAndroid Build Coastguard Worker if (p.length() > 2 && p[0] == '/' && p[1] == '/' && p[2] != '/') {
1485*89c4ff92SAndroid Build Coastguard Worker std::string::iterator new_end = std::unique(p.begin() + 2, p.end(), [](path::value_type lhs, path::value_type rhs) { return lhs == rhs && lhs == '/'; });
1486*89c4ff92SAndroid Build Coastguard Worker p.erase(new_end, p.end());
1487*89c4ff92SAndroid Build Coastguard Worker }
1488*89c4ff92SAndroid Build Coastguard Worker else {
1489*89c4ff92SAndroid Build Coastguard Worker std::string::iterator new_end = std::unique(p.begin(), p.end(), [](path::value_type lhs, path::value_type rhs) { return lhs == rhs && lhs == '/'; });
1490*89c4ff92SAndroid Build Coastguard Worker p.erase(new_end, p.end());
1491*89c4ff92SAndroid Build Coastguard Worker }
1492*89c4ff92SAndroid Build Coastguard Worker }
1493*89c4ff92SAndroid Build Coastguard Worker
1494*89c4ff92SAndroid Build Coastguard Worker #endif // GHC_EXPAND_IMPL
1495*89c4ff92SAndroid Build Coastguard Worker
1496*89c4ff92SAndroid Build Coastguard Worker template <class Source, typename>
path(const Source & source,format fmt)1497*89c4ff92SAndroid Build Coastguard Worker inline path::path(const Source& source, format fmt)
1498*89c4ff92SAndroid Build Coastguard Worker : _path(detail::toUtf8(source))
1499*89c4ff92SAndroid Build Coastguard Worker {
1500*89c4ff92SAndroid Build Coastguard Worker postprocess_path_with_format(_path, fmt);
1501*89c4ff92SAndroid Build Coastguard Worker }
1502*89c4ff92SAndroid Build Coastguard Worker template <>
path(const std::wstring & source,format fmt)1503*89c4ff92SAndroid Build Coastguard Worker inline path::path(const std::wstring& source, format fmt)
1504*89c4ff92SAndroid Build Coastguard Worker {
1505*89c4ff92SAndroid Build Coastguard Worker _path = detail::toUtf8(source);
1506*89c4ff92SAndroid Build Coastguard Worker postprocess_path_with_format(_path, fmt);
1507*89c4ff92SAndroid Build Coastguard Worker }
1508*89c4ff92SAndroid Build Coastguard Worker template <>
path(const std::u16string & source,format fmt)1509*89c4ff92SAndroid Build Coastguard Worker inline path::path(const std::u16string& source, format fmt)
1510*89c4ff92SAndroid Build Coastguard Worker {
1511*89c4ff92SAndroid Build Coastguard Worker _path = detail::toUtf8(source);
1512*89c4ff92SAndroid Build Coastguard Worker postprocess_path_with_format(_path, fmt);
1513*89c4ff92SAndroid Build Coastguard Worker }
1514*89c4ff92SAndroid Build Coastguard Worker template <>
path(const std::u32string & source,format fmt)1515*89c4ff92SAndroid Build Coastguard Worker inline path::path(const std::u32string& source, format fmt)
1516*89c4ff92SAndroid Build Coastguard Worker {
1517*89c4ff92SAndroid Build Coastguard Worker _path = detail::toUtf8(source);
1518*89c4ff92SAndroid Build Coastguard Worker postprocess_path_with_format(_path, fmt);
1519*89c4ff92SAndroid Build Coastguard Worker }
1520*89c4ff92SAndroid Build Coastguard Worker
1521*89c4ff92SAndroid Build Coastguard Worker #ifdef __cpp_lib_string_view
1522*89c4ff92SAndroid Build Coastguard Worker template <>
path(const std::string_view & source,format fmt)1523*89c4ff92SAndroid Build Coastguard Worker inline path::path(const std::string_view& source, format fmt)
1524*89c4ff92SAndroid Build Coastguard Worker {
1525*89c4ff92SAndroid Build Coastguard Worker _path = detail::toUtf8(std::string(source));
1526*89c4ff92SAndroid Build Coastguard Worker postprocess_path_with_format(_path, fmt);
1527*89c4ff92SAndroid Build Coastguard Worker }
1528*89c4ff92SAndroid Build Coastguard Worker #endif
1529*89c4ff92SAndroid Build Coastguard Worker
1530*89c4ff92SAndroid Build Coastguard Worker template <class Source, typename>
u8path(const Source & source)1531*89c4ff92SAndroid Build Coastguard Worker inline path u8path(const Source& source)
1532*89c4ff92SAndroid Build Coastguard Worker {
1533*89c4ff92SAndroid Build Coastguard Worker return path(source);
1534*89c4ff92SAndroid Build Coastguard Worker }
1535*89c4ff92SAndroid Build Coastguard Worker template <class InputIterator>
u8path(InputIterator first,InputIterator last)1536*89c4ff92SAndroid Build Coastguard Worker inline path u8path(InputIterator first, InputIterator last)
1537*89c4ff92SAndroid Build Coastguard Worker {
1538*89c4ff92SAndroid Build Coastguard Worker return path(first, last);
1539*89c4ff92SAndroid Build Coastguard Worker }
1540*89c4ff92SAndroid Build Coastguard Worker
1541*89c4ff92SAndroid Build Coastguard Worker template <class InputIterator>
path(InputIterator first,InputIterator last,format fmt)1542*89c4ff92SAndroid Build Coastguard Worker inline path::path(InputIterator first, InputIterator last, format fmt)
1543*89c4ff92SAndroid Build Coastguard Worker : path(std::basic_string<typename std::iterator_traits<InputIterator>::value_type>(first, last), fmt)
1544*89c4ff92SAndroid Build Coastguard Worker {
1545*89c4ff92SAndroid Build Coastguard Worker // delegated
1546*89c4ff92SAndroid Build Coastguard Worker }
1547*89c4ff92SAndroid Build Coastguard Worker
1548*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_EXPAND_IMPL
1549*89c4ff92SAndroid Build Coastguard Worker
1550*89c4ff92SAndroid Build Coastguard Worker namespace detail {
1551*89c4ff92SAndroid Build Coastguard Worker
equals_simple_insensitive(const char * str1,const char * str2)1552*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool equals_simple_insensitive(const char* str1, const char* str2)
1553*89c4ff92SAndroid Build Coastguard Worker {
1554*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
1555*89c4ff92SAndroid Build Coastguard Worker #ifdef __GNUC__
1556*89c4ff92SAndroid Build Coastguard Worker while (::tolower((unsigned char)*str1) == ::tolower((unsigned char)*str2++)) {
1557*89c4ff92SAndroid Build Coastguard Worker if (*str1++ == 0)
1558*89c4ff92SAndroid Build Coastguard Worker return true;
1559*89c4ff92SAndroid Build Coastguard Worker }
1560*89c4ff92SAndroid Build Coastguard Worker return false;
1561*89c4ff92SAndroid Build Coastguard Worker #else
1562*89c4ff92SAndroid Build Coastguard Worker return 0 == ::_stricmp(str1, str2);
1563*89c4ff92SAndroid Build Coastguard Worker #endif
1564*89c4ff92SAndroid Build Coastguard Worker #else
1565*89c4ff92SAndroid Build Coastguard Worker return 0 == ::strcasecmp(str1, str2);
1566*89c4ff92SAndroid Build Coastguard Worker #endif
1567*89c4ff92SAndroid Build Coastguard Worker }
1568*89c4ff92SAndroid Build Coastguard Worker
strerror_adapter(char * gnu,char *)1569*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE const char* strerror_adapter(char* gnu, char*)
1570*89c4ff92SAndroid Build Coastguard Worker {
1571*89c4ff92SAndroid Build Coastguard Worker return gnu;
1572*89c4ff92SAndroid Build Coastguard Worker }
1573*89c4ff92SAndroid Build Coastguard Worker
strerror_adapter(int posix,char * buffer)1574*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE const char* strerror_adapter(int posix, char* buffer)
1575*89c4ff92SAndroid Build Coastguard Worker {
1576*89c4ff92SAndroid Build Coastguard Worker if(posix) {
1577*89c4ff92SAndroid Build Coastguard Worker return "Error in strerror_r!";
1578*89c4ff92SAndroid Build Coastguard Worker }
1579*89c4ff92SAndroid Build Coastguard Worker return buffer;
1580*89c4ff92SAndroid Build Coastguard Worker }
1581*89c4ff92SAndroid Build Coastguard Worker
1582*89c4ff92SAndroid Build Coastguard Worker template <typename ErrorNumber>
systemErrorText(ErrorNumber code=0)1583*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE std::string systemErrorText(ErrorNumber code = 0)
1584*89c4ff92SAndroid Build Coastguard Worker {
1585*89c4ff92SAndroid Build Coastguard Worker #if defined(GHC_OS_WINDOWS)
1586*89c4ff92SAndroid Build Coastguard Worker LPVOID msgBuf;
1587*89c4ff92SAndroid Build Coastguard Worker DWORD dw = code ? static_cast<DWORD>(code) : ::GetLastError();
1588*89c4ff92SAndroid Build Coastguard Worker FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&msgBuf, 0, NULL);
1589*89c4ff92SAndroid Build Coastguard Worker std::string msg = toUtf8(std::wstring((LPWSTR)msgBuf));
1590*89c4ff92SAndroid Build Coastguard Worker LocalFree(msgBuf);
1591*89c4ff92SAndroid Build Coastguard Worker return msg;
1592*89c4ff92SAndroid Build Coastguard Worker #else
1593*89c4ff92SAndroid Build Coastguard Worker char buffer[512];
1594*89c4ff92SAndroid Build Coastguard Worker return strerror_adapter(strerror_r(code ? code : errno, buffer, sizeof(buffer)), buffer);
1595*89c4ff92SAndroid Build Coastguard Worker #endif
1596*89c4ff92SAndroid Build Coastguard Worker }
1597*89c4ff92SAndroid Build Coastguard Worker
1598*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
1599*89c4ff92SAndroid Build Coastguard Worker using CreateSymbolicLinkW_fp = BOOLEAN(WINAPI*)(LPCWSTR, LPCWSTR, DWORD);
1600*89c4ff92SAndroid Build Coastguard Worker using CreateHardLinkW_fp = BOOLEAN(WINAPI*)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES);
1601*89c4ff92SAndroid Build Coastguard Worker
create_symlink(const path & target_name,const path & new_symlink,bool to_directory,std::error_code & ec)1602*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void create_symlink(const path& target_name, const path& new_symlink, bool to_directory, std::error_code& ec)
1603*89c4ff92SAndroid Build Coastguard Worker {
1604*89c4ff92SAndroid Build Coastguard Worker std::error_code tec;
1605*89c4ff92SAndroid Build Coastguard Worker auto fs = status(target_name, tec);
1606*89c4ff92SAndroid Build Coastguard Worker if ((fs.type() == file_type::directory && !to_directory) || (fs.type() == file_type::regular && to_directory)) {
1607*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_error_code(detail::portable_error::not_supported);
1608*89c4ff92SAndroid Build Coastguard Worker return;
1609*89c4ff92SAndroid Build Coastguard Worker }
1610*89c4ff92SAndroid Build Coastguard Worker #if defined(__GNUC__) && __GNUC__ >= 8
1611*89c4ff92SAndroid Build Coastguard Worker #pragma GCC diagnostic push
1612*89c4ff92SAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wcast-function-type"
1613*89c4ff92SAndroid Build Coastguard Worker #endif
1614*89c4ff92SAndroid Build Coastguard Worker static CreateSymbolicLinkW_fp api_call = reinterpret_cast<CreateSymbolicLinkW_fp>(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "CreateSymbolicLinkW"));
1615*89c4ff92SAndroid Build Coastguard Worker #if defined(__GNUC__) && __GNUC__ >= 8
1616*89c4ff92SAndroid Build Coastguard Worker #pragma GCC diagnostic pop
1617*89c4ff92SAndroid Build Coastguard Worker #endif
1618*89c4ff92SAndroid Build Coastguard Worker if (api_call) {
1619*89c4ff92SAndroid Build Coastguard Worker if (api_call(detail::fromUtf8<std::wstring>(new_symlink.u8string()).c_str(), detail::fromUtf8<std::wstring>(target_name.u8string()).c_str(), to_directory ? 1 : 0) == 0) {
1620*89c4ff92SAndroid Build Coastguard Worker auto result = ::GetLastError();
1621*89c4ff92SAndroid Build Coastguard Worker if (result == ERROR_PRIVILEGE_NOT_HELD && api_call(detail::fromUtf8<std::wstring>(new_symlink.u8string()).c_str(), detail::fromUtf8<std::wstring>(target_name.u8string()).c_str(), to_directory ? 3 : 2) != 0) {
1622*89c4ff92SAndroid Build Coastguard Worker return;
1623*89c4ff92SAndroid Build Coastguard Worker }
1624*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error(result);
1625*89c4ff92SAndroid Build Coastguard Worker }
1626*89c4ff92SAndroid Build Coastguard Worker }
1627*89c4ff92SAndroid Build Coastguard Worker else {
1628*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error(ERROR_NOT_SUPPORTED);
1629*89c4ff92SAndroid Build Coastguard Worker }
1630*89c4ff92SAndroid Build Coastguard Worker }
1631*89c4ff92SAndroid Build Coastguard Worker
create_hardlink(const path & target_name,const path & new_hardlink,std::error_code & ec)1632*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void create_hardlink(const path& target_name, const path& new_hardlink, std::error_code& ec)
1633*89c4ff92SAndroid Build Coastguard Worker {
1634*89c4ff92SAndroid Build Coastguard Worker #if defined(__GNUC__) && __GNUC__ >= 8
1635*89c4ff92SAndroid Build Coastguard Worker #pragma GCC diagnostic push
1636*89c4ff92SAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wcast-function-type"
1637*89c4ff92SAndroid Build Coastguard Worker #endif
1638*89c4ff92SAndroid Build Coastguard Worker static CreateHardLinkW_fp api_call = reinterpret_cast<CreateHardLinkW_fp>(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW"));
1639*89c4ff92SAndroid Build Coastguard Worker #if defined(__GNUC__) && __GNUC__ >= 8
1640*89c4ff92SAndroid Build Coastguard Worker #pragma GCC diagnostic pop
1641*89c4ff92SAndroid Build Coastguard Worker #endif
1642*89c4ff92SAndroid Build Coastguard Worker if (api_call) {
1643*89c4ff92SAndroid Build Coastguard Worker if (api_call(detail::fromUtf8<std::wstring>(new_hardlink.u8string()).c_str(), detail::fromUtf8<std::wstring>(target_name.u8string()).c_str(), NULL) == 0) {
1644*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
1645*89c4ff92SAndroid Build Coastguard Worker }
1646*89c4ff92SAndroid Build Coastguard Worker }
1647*89c4ff92SAndroid Build Coastguard Worker else {
1648*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error(ERROR_NOT_SUPPORTED);
1649*89c4ff92SAndroid Build Coastguard Worker }
1650*89c4ff92SAndroid Build Coastguard Worker }
1651*89c4ff92SAndroid Build Coastguard Worker #else
create_symlink(const path & target_name,const path & new_symlink,bool,std::error_code & ec)1652*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void create_symlink(const path& target_name, const path& new_symlink, bool, std::error_code& ec)
1653*89c4ff92SAndroid Build Coastguard Worker {
1654*89c4ff92SAndroid Build Coastguard Worker if (::symlink(target_name.c_str(), new_symlink.c_str()) != 0) {
1655*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
1656*89c4ff92SAndroid Build Coastguard Worker }
1657*89c4ff92SAndroid Build Coastguard Worker }
1658*89c4ff92SAndroid Build Coastguard Worker
create_hardlink(const path & target_name,const path & new_hardlink,std::error_code & ec)1659*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void create_hardlink(const path& target_name, const path& new_hardlink, std::error_code& ec)
1660*89c4ff92SAndroid Build Coastguard Worker {
1661*89c4ff92SAndroid Build Coastguard Worker if (::link(target_name.c_str(), new_hardlink.c_str()) != 0) {
1662*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
1663*89c4ff92SAndroid Build Coastguard Worker }
1664*89c4ff92SAndroid Build Coastguard Worker }
1665*89c4ff92SAndroid Build Coastguard Worker #endif
1666*89c4ff92SAndroid Build Coastguard Worker
1667*89c4ff92SAndroid Build Coastguard Worker template <typename T>
file_status_from_st_mode(T mode)1668*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_status file_status_from_st_mode(T mode)
1669*89c4ff92SAndroid Build Coastguard Worker {
1670*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
1671*89c4ff92SAndroid Build Coastguard Worker file_type ft = file_type::unknown;
1672*89c4ff92SAndroid Build Coastguard Worker if ((mode & _S_IFDIR) == _S_IFDIR) {
1673*89c4ff92SAndroid Build Coastguard Worker ft = file_type::directory;
1674*89c4ff92SAndroid Build Coastguard Worker }
1675*89c4ff92SAndroid Build Coastguard Worker else if ((mode & _S_IFREG) == _S_IFREG) {
1676*89c4ff92SAndroid Build Coastguard Worker ft = file_type::regular;
1677*89c4ff92SAndroid Build Coastguard Worker }
1678*89c4ff92SAndroid Build Coastguard Worker else if ((mode & _S_IFCHR) == _S_IFCHR) {
1679*89c4ff92SAndroid Build Coastguard Worker ft = file_type::character;
1680*89c4ff92SAndroid Build Coastguard Worker }
1681*89c4ff92SAndroid Build Coastguard Worker perms prms = static_cast<perms>(mode & 0xfff);
1682*89c4ff92SAndroid Build Coastguard Worker return file_status(ft, prms);
1683*89c4ff92SAndroid Build Coastguard Worker #else
1684*89c4ff92SAndroid Build Coastguard Worker file_type ft = file_type::unknown;
1685*89c4ff92SAndroid Build Coastguard Worker if (S_ISDIR(mode)) {
1686*89c4ff92SAndroid Build Coastguard Worker ft = file_type::directory;
1687*89c4ff92SAndroid Build Coastguard Worker }
1688*89c4ff92SAndroid Build Coastguard Worker else if (S_ISREG(mode)) {
1689*89c4ff92SAndroid Build Coastguard Worker ft = file_type::regular;
1690*89c4ff92SAndroid Build Coastguard Worker }
1691*89c4ff92SAndroid Build Coastguard Worker else if (S_ISCHR(mode)) {
1692*89c4ff92SAndroid Build Coastguard Worker ft = file_type::character;
1693*89c4ff92SAndroid Build Coastguard Worker }
1694*89c4ff92SAndroid Build Coastguard Worker else if (S_ISBLK(mode)) {
1695*89c4ff92SAndroid Build Coastguard Worker ft = file_type::block;
1696*89c4ff92SAndroid Build Coastguard Worker }
1697*89c4ff92SAndroid Build Coastguard Worker else if (S_ISFIFO(mode)) {
1698*89c4ff92SAndroid Build Coastguard Worker ft = file_type::fifo;
1699*89c4ff92SAndroid Build Coastguard Worker }
1700*89c4ff92SAndroid Build Coastguard Worker else if (S_ISLNK(mode)) {
1701*89c4ff92SAndroid Build Coastguard Worker ft = file_type::symlink;
1702*89c4ff92SAndroid Build Coastguard Worker }
1703*89c4ff92SAndroid Build Coastguard Worker else if (S_ISSOCK(mode)) {
1704*89c4ff92SAndroid Build Coastguard Worker ft = file_type::socket;
1705*89c4ff92SAndroid Build Coastguard Worker }
1706*89c4ff92SAndroid Build Coastguard Worker perms prms = static_cast<perms>(mode & 0xfff);
1707*89c4ff92SAndroid Build Coastguard Worker return file_status(ft, prms);
1708*89c4ff92SAndroid Build Coastguard Worker #endif
1709*89c4ff92SAndroid Build Coastguard Worker }
1710*89c4ff92SAndroid Build Coastguard Worker
resolveSymlink(const path & p,std::error_code & ec)1711*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path resolveSymlink(const path& p, std::error_code& ec)
1712*89c4ff92SAndroid Build Coastguard Worker {
1713*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
1714*89c4ff92SAndroid Build Coastguard Worker #ifndef REPARSE_DATA_BUFFER_HEADER_SIZE
1715*89c4ff92SAndroid Build Coastguard Worker typedef struct _REPARSE_DATA_BUFFER
1716*89c4ff92SAndroid Build Coastguard Worker {
1717*89c4ff92SAndroid Build Coastguard Worker ULONG ReparseTag;
1718*89c4ff92SAndroid Build Coastguard Worker USHORT ReparseDataLength;
1719*89c4ff92SAndroid Build Coastguard Worker USHORT Reserved;
1720*89c4ff92SAndroid Build Coastguard Worker union
1721*89c4ff92SAndroid Build Coastguard Worker {
1722*89c4ff92SAndroid Build Coastguard Worker struct
1723*89c4ff92SAndroid Build Coastguard Worker {
1724*89c4ff92SAndroid Build Coastguard Worker USHORT SubstituteNameOffset;
1725*89c4ff92SAndroid Build Coastguard Worker USHORT SubstituteNameLength;
1726*89c4ff92SAndroid Build Coastguard Worker USHORT PrintNameOffset;
1727*89c4ff92SAndroid Build Coastguard Worker USHORT PrintNameLength;
1728*89c4ff92SAndroid Build Coastguard Worker ULONG Flags;
1729*89c4ff92SAndroid Build Coastguard Worker WCHAR PathBuffer[1];
1730*89c4ff92SAndroid Build Coastguard Worker } SymbolicLinkReparseBuffer;
1731*89c4ff92SAndroid Build Coastguard Worker struct
1732*89c4ff92SAndroid Build Coastguard Worker {
1733*89c4ff92SAndroid Build Coastguard Worker USHORT SubstituteNameOffset;
1734*89c4ff92SAndroid Build Coastguard Worker USHORT SubstituteNameLength;
1735*89c4ff92SAndroid Build Coastguard Worker USHORT PrintNameOffset;
1736*89c4ff92SAndroid Build Coastguard Worker USHORT PrintNameLength;
1737*89c4ff92SAndroid Build Coastguard Worker WCHAR PathBuffer[1];
1738*89c4ff92SAndroid Build Coastguard Worker } MountPointReparseBuffer;
1739*89c4ff92SAndroid Build Coastguard Worker struct
1740*89c4ff92SAndroid Build Coastguard Worker {
1741*89c4ff92SAndroid Build Coastguard Worker UCHAR DataBuffer[1];
1742*89c4ff92SAndroid Build Coastguard Worker } GenericReparseBuffer;
1743*89c4ff92SAndroid Build Coastguard Worker } DUMMYUNIONNAME;
1744*89c4ff92SAndroid Build Coastguard Worker } REPARSE_DATA_BUFFER;
1745*89c4ff92SAndroid Build Coastguard Worker #ifndef MAXIMUM_REPARSE_DATA_BUFFER_SIZE
1746*89c4ff92SAndroid Build Coastguard Worker #define MAXIMUM_REPARSE_DATA_BUFFER_SIZE (16 * 1024)
1747*89c4ff92SAndroid Build Coastguard Worker #endif
1748*89c4ff92SAndroid Build Coastguard Worker #endif
1749*89c4ff92SAndroid Build Coastguard Worker
1750*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<void> file(CreateFileW(p.wstring().c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle);
1751*89c4ff92SAndroid Build Coastguard Worker if (file.get() == INVALID_HANDLE_VALUE) {
1752*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
1753*89c4ff92SAndroid Build Coastguard Worker return path();
1754*89c4ff92SAndroid Build Coastguard Worker }
1755*89c4ff92SAndroid Build Coastguard Worker
1756*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<REPARSE_DATA_BUFFER> reparseData((REPARSE_DATA_BUFFER*)std::calloc(1, MAXIMUM_REPARSE_DATA_BUFFER_SIZE), std::free);
1757*89c4ff92SAndroid Build Coastguard Worker ULONG bufferUsed;
1758*89c4ff92SAndroid Build Coastguard Worker path result;
1759*89c4ff92SAndroid Build Coastguard Worker if (DeviceIoControl(file.get(), FSCTL_GET_REPARSE_POINT, 0, 0, reparseData.get(), MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bufferUsed, 0)) {
1760*89c4ff92SAndroid Build Coastguard Worker if (IsReparseTagMicrosoft(reparseData->ReparseTag)) {
1761*89c4ff92SAndroid Build Coastguard Worker switch (reparseData->ReparseTag) {
1762*89c4ff92SAndroid Build Coastguard Worker case IO_REPARSE_TAG_SYMLINK:
1763*89c4ff92SAndroid Build Coastguard Worker result = std::wstring(&reparseData->SymbolicLinkReparseBuffer.PathBuffer[reparseData->SymbolicLinkReparseBuffer.PrintNameOffset / sizeof(WCHAR)], reparseData->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(WCHAR));
1764*89c4ff92SAndroid Build Coastguard Worker break;
1765*89c4ff92SAndroid Build Coastguard Worker case IO_REPARSE_TAG_MOUNT_POINT:
1766*89c4ff92SAndroid Build Coastguard Worker result = std::wstring(&reparseData->MountPointReparseBuffer.PathBuffer[reparseData->MountPointReparseBuffer.PrintNameOffset / sizeof(WCHAR)], reparseData->MountPointReparseBuffer.PrintNameLength / sizeof(WCHAR));
1767*89c4ff92SAndroid Build Coastguard Worker break;
1768*89c4ff92SAndroid Build Coastguard Worker default:
1769*89c4ff92SAndroid Build Coastguard Worker break;
1770*89c4ff92SAndroid Build Coastguard Worker }
1771*89c4ff92SAndroid Build Coastguard Worker }
1772*89c4ff92SAndroid Build Coastguard Worker }
1773*89c4ff92SAndroid Build Coastguard Worker else {
1774*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
1775*89c4ff92SAndroid Build Coastguard Worker }
1776*89c4ff92SAndroid Build Coastguard Worker return result;
1777*89c4ff92SAndroid Build Coastguard Worker #else
1778*89c4ff92SAndroid Build Coastguard Worker size_t bufferSize = 256;
1779*89c4ff92SAndroid Build Coastguard Worker while (true) {
1780*89c4ff92SAndroid Build Coastguard Worker std::vector<char> buffer(bufferSize, static_cast<char>(0));
1781*89c4ff92SAndroid Build Coastguard Worker auto rc = ::readlink(p.c_str(), buffer.data(), buffer.size());
1782*89c4ff92SAndroid Build Coastguard Worker if (rc < 0) {
1783*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
1784*89c4ff92SAndroid Build Coastguard Worker return path();
1785*89c4ff92SAndroid Build Coastguard Worker }
1786*89c4ff92SAndroid Build Coastguard Worker else if (rc < static_cast<int>(bufferSize)) {
1787*89c4ff92SAndroid Build Coastguard Worker return path(std::string(buffer.data(), static_cast<std::string::size_type>(rc)));
1788*89c4ff92SAndroid Build Coastguard Worker }
1789*89c4ff92SAndroid Build Coastguard Worker bufferSize *= 2;
1790*89c4ff92SAndroid Build Coastguard Worker }
1791*89c4ff92SAndroid Build Coastguard Worker return path();
1792*89c4ff92SAndroid Build Coastguard Worker #endif
1793*89c4ff92SAndroid Build Coastguard Worker }
1794*89c4ff92SAndroid Build Coastguard Worker
1795*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
timeFromFILETIME(const FILETIME & ft)1796*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE time_t timeFromFILETIME(const FILETIME& ft)
1797*89c4ff92SAndroid Build Coastguard Worker {
1798*89c4ff92SAndroid Build Coastguard Worker ULARGE_INTEGER ull;
1799*89c4ff92SAndroid Build Coastguard Worker ull.LowPart = ft.dwLowDateTime;
1800*89c4ff92SAndroid Build Coastguard Worker ull.HighPart = ft.dwHighDateTime;
1801*89c4ff92SAndroid Build Coastguard Worker return static_cast<time_t>(ull.QuadPart / 10000000ULL - 11644473600ULL);
1802*89c4ff92SAndroid Build Coastguard Worker }
1803*89c4ff92SAndroid Build Coastguard Worker
timeToFILETIME(time_t t,FILETIME & ft)1804*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void timeToFILETIME(time_t t, FILETIME& ft)
1805*89c4ff92SAndroid Build Coastguard Worker {
1806*89c4ff92SAndroid Build Coastguard Worker LONGLONG ll;
1807*89c4ff92SAndroid Build Coastguard Worker ll = Int32x32To64(t, 10000000) + 116444736000000000;
1808*89c4ff92SAndroid Build Coastguard Worker ft.dwLowDateTime = static_cast<DWORD>(ll);
1809*89c4ff92SAndroid Build Coastguard Worker ft.dwHighDateTime = static_cast<DWORD>(ll >> 32);
1810*89c4ff92SAndroid Build Coastguard Worker }
1811*89c4ff92SAndroid Build Coastguard Worker
1812*89c4ff92SAndroid Build Coastguard Worker template <typename INFO>
hard_links_from_INFO(const INFO * info)1813*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE uintmax_t hard_links_from_INFO(const INFO* info)
1814*89c4ff92SAndroid Build Coastguard Worker {
1815*89c4ff92SAndroid Build Coastguard Worker return static_cast<uintmax_t>(-1);
1816*89c4ff92SAndroid Build Coastguard Worker }
1817*89c4ff92SAndroid Build Coastguard Worker
1818*89c4ff92SAndroid Build Coastguard Worker template <>
hard_links_from_INFO(const BY_HANDLE_FILE_INFORMATION * info)1819*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE uintmax_t hard_links_from_INFO<BY_HANDLE_FILE_INFORMATION>(const BY_HANDLE_FILE_INFORMATION* info)
1820*89c4ff92SAndroid Build Coastguard Worker {
1821*89c4ff92SAndroid Build Coastguard Worker return info->nNumberOfLinks;
1822*89c4ff92SAndroid Build Coastguard Worker }
1823*89c4ff92SAndroid Build Coastguard Worker
1824*89c4ff92SAndroid Build Coastguard Worker template <typename INFO>
status_from_INFO(const path & p,const INFO * info,std::error_code &,uintmax_t * sz=nullptr,time_t * lwt=nullptr)1825*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_status status_from_INFO(const path& p, const INFO* info, std::error_code&, uintmax_t* sz = nullptr, time_t* lwt = nullptr) noexcept
1826*89c4ff92SAndroid Build Coastguard Worker {
1827*89c4ff92SAndroid Build Coastguard Worker file_type ft = file_type::unknown;
1828*89c4ff92SAndroid Build Coastguard Worker if ((info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
1829*89c4ff92SAndroid Build Coastguard Worker ft = file_type::symlink;
1830*89c4ff92SAndroid Build Coastguard Worker }
1831*89c4ff92SAndroid Build Coastguard Worker else {
1832*89c4ff92SAndroid Build Coastguard Worker if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
1833*89c4ff92SAndroid Build Coastguard Worker ft = file_type::directory;
1834*89c4ff92SAndroid Build Coastguard Worker }
1835*89c4ff92SAndroid Build Coastguard Worker else {
1836*89c4ff92SAndroid Build Coastguard Worker ft = file_type::regular;
1837*89c4ff92SAndroid Build Coastguard Worker }
1838*89c4ff92SAndroid Build Coastguard Worker }
1839*89c4ff92SAndroid Build Coastguard Worker perms prms = perms::owner_read | perms::group_read | perms::others_read;
1840*89c4ff92SAndroid Build Coastguard Worker if (!(info->dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
1841*89c4ff92SAndroid Build Coastguard Worker prms = prms | perms::owner_write | perms::group_write | perms::others_write;
1842*89c4ff92SAndroid Build Coastguard Worker }
1843*89c4ff92SAndroid Build Coastguard Worker std::string ext = p.extension().generic_string();
1844*89c4ff92SAndroid Build Coastguard Worker if (equals_simple_insensitive(ext.c_str(), ".exe") || equals_simple_insensitive(ext.c_str(), ".cmd") || equals_simple_insensitive(ext.c_str(), ".bat") || equals_simple_insensitive(ext.c_str(), ".com")) {
1845*89c4ff92SAndroid Build Coastguard Worker prms = prms | perms::owner_exec | perms::group_exec | perms::others_exec;
1846*89c4ff92SAndroid Build Coastguard Worker }
1847*89c4ff92SAndroid Build Coastguard Worker if (sz) {
1848*89c4ff92SAndroid Build Coastguard Worker *sz = static_cast<uintmax_t>(info->nFileSizeHigh) << (sizeof(info->nFileSizeHigh) * 8) | info->nFileSizeLow;
1849*89c4ff92SAndroid Build Coastguard Worker }
1850*89c4ff92SAndroid Build Coastguard Worker if (lwt) {
1851*89c4ff92SAndroid Build Coastguard Worker *lwt = detail::timeFromFILETIME(info->ftLastWriteTime);
1852*89c4ff92SAndroid Build Coastguard Worker }
1853*89c4ff92SAndroid Build Coastguard Worker return file_status(ft, prms);
1854*89c4ff92SAndroid Build Coastguard Worker }
1855*89c4ff92SAndroid Build Coastguard Worker
1856*89c4ff92SAndroid Build Coastguard Worker #endif
1857*89c4ff92SAndroid Build Coastguard Worker
is_not_found_error(std::error_code & ec)1858*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_not_found_error(std::error_code& ec)
1859*89c4ff92SAndroid Build Coastguard Worker {
1860*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
1861*89c4ff92SAndroid Build Coastguard Worker return ec.value() == ERROR_FILE_NOT_FOUND || ec.value() == ERROR_PATH_NOT_FOUND || ec.value() == ERROR_INVALID_NAME;
1862*89c4ff92SAndroid Build Coastguard Worker #else
1863*89c4ff92SAndroid Build Coastguard Worker return ec.value() == ENOENT || ec.value() == ENOTDIR;
1864*89c4ff92SAndroid Build Coastguard Worker #endif
1865*89c4ff92SAndroid Build Coastguard Worker }
1866*89c4ff92SAndroid Build Coastguard Worker
symlink_status_ex(const path & p,std::error_code & ec,uintmax_t * sz=nullptr,uintmax_t * nhl=nullptr,time_t * lwt=nullptr)1867*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_status symlink_status_ex(const path& p, std::error_code& ec, uintmax_t* sz = nullptr, uintmax_t* nhl = nullptr, time_t* lwt = nullptr) noexcept
1868*89c4ff92SAndroid Build Coastguard Worker {
1869*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
1870*89c4ff92SAndroid Build Coastguard Worker file_status fs;
1871*89c4ff92SAndroid Build Coastguard Worker WIN32_FILE_ATTRIBUTE_DATA attr;
1872*89c4ff92SAndroid Build Coastguard Worker if (!GetFileAttributesExW(detail::fromUtf8<std::wstring>(p.u8string()).c_str(), GetFileExInfoStandard, &attr)) {
1873*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
1874*89c4ff92SAndroid Build Coastguard Worker }
1875*89c4ff92SAndroid Build Coastguard Worker else {
1876*89c4ff92SAndroid Build Coastguard Worker ec.clear();
1877*89c4ff92SAndroid Build Coastguard Worker fs = detail::status_from_INFO(p, &attr, ec, sz, lwt);
1878*89c4ff92SAndroid Build Coastguard Worker if (nhl) {
1879*89c4ff92SAndroid Build Coastguard Worker *nhl = 0;
1880*89c4ff92SAndroid Build Coastguard Worker }
1881*89c4ff92SAndroid Build Coastguard Worker if (attr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1882*89c4ff92SAndroid Build Coastguard Worker fs.type(file_type::symlink);
1883*89c4ff92SAndroid Build Coastguard Worker }
1884*89c4ff92SAndroid Build Coastguard Worker }
1885*89c4ff92SAndroid Build Coastguard Worker if (detail::is_not_found_error(ec)) {
1886*89c4ff92SAndroid Build Coastguard Worker return file_status(file_type::not_found);
1887*89c4ff92SAndroid Build Coastguard Worker }
1888*89c4ff92SAndroid Build Coastguard Worker return ec ? file_status(file_type::none) : fs;
1889*89c4ff92SAndroid Build Coastguard Worker #else
1890*89c4ff92SAndroid Build Coastguard Worker (void)sz;
1891*89c4ff92SAndroid Build Coastguard Worker (void)nhl;
1892*89c4ff92SAndroid Build Coastguard Worker (void)lwt;
1893*89c4ff92SAndroid Build Coastguard Worker struct ::stat fs;
1894*89c4ff92SAndroid Build Coastguard Worker auto result = ::lstat(p.c_str(), &fs);
1895*89c4ff92SAndroid Build Coastguard Worker if (result == 0) {
1896*89c4ff92SAndroid Build Coastguard Worker ec.clear();
1897*89c4ff92SAndroid Build Coastguard Worker file_status f_s = detail::file_status_from_st_mode(fs.st_mode);
1898*89c4ff92SAndroid Build Coastguard Worker return f_s;
1899*89c4ff92SAndroid Build Coastguard Worker }
1900*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
1901*89c4ff92SAndroid Build Coastguard Worker if (detail::is_not_found_error(ec)) {
1902*89c4ff92SAndroid Build Coastguard Worker return file_status(file_type::not_found, perms::unknown);
1903*89c4ff92SAndroid Build Coastguard Worker }
1904*89c4ff92SAndroid Build Coastguard Worker return file_status(file_type::none);
1905*89c4ff92SAndroid Build Coastguard Worker #endif
1906*89c4ff92SAndroid Build Coastguard Worker }
1907*89c4ff92SAndroid Build Coastguard Worker
status_ex(const path & p,std::error_code & ec,file_status * sls=nullptr,uintmax_t * sz=nullptr,uintmax_t * nhl=nullptr,time_t * lwt=nullptr,int recurse_count=0)1908*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_status status_ex(const path& p, std::error_code& ec, file_status* sls = nullptr, uintmax_t* sz = nullptr, uintmax_t* nhl = nullptr, time_t* lwt = nullptr, int recurse_count = 0) noexcept
1909*89c4ff92SAndroid Build Coastguard Worker {
1910*89c4ff92SAndroid Build Coastguard Worker ec.clear();
1911*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
1912*89c4ff92SAndroid Build Coastguard Worker if (recurse_count > 16) {
1913*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error(0x2A9 /*ERROR_STOPPED_ON_SYMLINK*/);
1914*89c4ff92SAndroid Build Coastguard Worker return file_status(file_type::unknown);
1915*89c4ff92SAndroid Build Coastguard Worker }
1916*89c4ff92SAndroid Build Coastguard Worker WIN32_FILE_ATTRIBUTE_DATA attr;
1917*89c4ff92SAndroid Build Coastguard Worker if (!::GetFileAttributesExW(p.wstring().c_str(), GetFileExInfoStandard, &attr)) {
1918*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
1919*89c4ff92SAndroid Build Coastguard Worker }
1920*89c4ff92SAndroid Build Coastguard Worker else if (attr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1921*89c4ff92SAndroid Build Coastguard Worker path target = resolveSymlink(p, ec);
1922*89c4ff92SAndroid Build Coastguard Worker file_status result;
1923*89c4ff92SAndroid Build Coastguard Worker if (!ec && !target.empty()) {
1924*89c4ff92SAndroid Build Coastguard Worker if (sls) {
1925*89c4ff92SAndroid Build Coastguard Worker *sls = status_from_INFO(p, &attr, ec);
1926*89c4ff92SAndroid Build Coastguard Worker }
1927*89c4ff92SAndroid Build Coastguard Worker return detail::status_ex(target, ec, nullptr, sz, nhl, lwt, recurse_count + 1);
1928*89c4ff92SAndroid Build Coastguard Worker }
1929*89c4ff92SAndroid Build Coastguard Worker return file_status(file_type::unknown);
1930*89c4ff92SAndroid Build Coastguard Worker }
1931*89c4ff92SAndroid Build Coastguard Worker if (ec) {
1932*89c4ff92SAndroid Build Coastguard Worker if (detail::is_not_found_error(ec)) {
1933*89c4ff92SAndroid Build Coastguard Worker return file_status(file_type::not_found);
1934*89c4ff92SAndroid Build Coastguard Worker }
1935*89c4ff92SAndroid Build Coastguard Worker return file_status(file_type::none);
1936*89c4ff92SAndroid Build Coastguard Worker }
1937*89c4ff92SAndroid Build Coastguard Worker if (nhl) {
1938*89c4ff92SAndroid Build Coastguard Worker *nhl = 0;
1939*89c4ff92SAndroid Build Coastguard Worker }
1940*89c4ff92SAndroid Build Coastguard Worker return detail::status_from_INFO(p, &attr, ec, sz, lwt);
1941*89c4ff92SAndroid Build Coastguard Worker #else
1942*89c4ff92SAndroid Build Coastguard Worker (void)recurse_count;
1943*89c4ff92SAndroid Build Coastguard Worker struct ::stat st;
1944*89c4ff92SAndroid Build Coastguard Worker auto result = ::lstat(p.c_str(), &st);
1945*89c4ff92SAndroid Build Coastguard Worker if (result == 0) {
1946*89c4ff92SAndroid Build Coastguard Worker ec.clear();
1947*89c4ff92SAndroid Build Coastguard Worker file_status fs = detail::file_status_from_st_mode(st.st_mode);
1948*89c4ff92SAndroid Build Coastguard Worker if (fs.type() == file_type::symlink) {
1949*89c4ff92SAndroid Build Coastguard Worker result = ::stat(p.c_str(), &st);
1950*89c4ff92SAndroid Build Coastguard Worker if (result == 0) {
1951*89c4ff92SAndroid Build Coastguard Worker if (sls) {
1952*89c4ff92SAndroid Build Coastguard Worker *sls = fs;
1953*89c4ff92SAndroid Build Coastguard Worker }
1954*89c4ff92SAndroid Build Coastguard Worker fs = detail::file_status_from_st_mode(st.st_mode);
1955*89c4ff92SAndroid Build Coastguard Worker }
1956*89c4ff92SAndroid Build Coastguard Worker }
1957*89c4ff92SAndroid Build Coastguard Worker if (sz) {
1958*89c4ff92SAndroid Build Coastguard Worker *sz = static_cast<uintmax_t>(st.st_size);
1959*89c4ff92SAndroid Build Coastguard Worker }
1960*89c4ff92SAndroid Build Coastguard Worker if (nhl) {
1961*89c4ff92SAndroid Build Coastguard Worker *nhl = st.st_nlink;
1962*89c4ff92SAndroid Build Coastguard Worker }
1963*89c4ff92SAndroid Build Coastguard Worker if (lwt) {
1964*89c4ff92SAndroid Build Coastguard Worker *lwt = st.st_mtime;
1965*89c4ff92SAndroid Build Coastguard Worker }
1966*89c4ff92SAndroid Build Coastguard Worker return fs;
1967*89c4ff92SAndroid Build Coastguard Worker }
1968*89c4ff92SAndroid Build Coastguard Worker else {
1969*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
1970*89c4ff92SAndroid Build Coastguard Worker if (detail::is_not_found_error(ec)) {
1971*89c4ff92SAndroid Build Coastguard Worker return file_status(file_type::not_found, perms::unknown);
1972*89c4ff92SAndroid Build Coastguard Worker }
1973*89c4ff92SAndroid Build Coastguard Worker return file_status(file_type::none);
1974*89c4ff92SAndroid Build Coastguard Worker }
1975*89c4ff92SAndroid Build Coastguard Worker #endif
1976*89c4ff92SAndroid Build Coastguard Worker }
1977*89c4ff92SAndroid Build Coastguard Worker
1978*89c4ff92SAndroid Build Coastguard Worker } // namespace detail
1979*89c4ff92SAndroid Build Coastguard Worker
u8arguments(int & argc,char ** & argv)1980*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE u8arguments::u8arguments(int& argc, char**& argv)
1981*89c4ff92SAndroid Build Coastguard Worker : _argc(argc)
1982*89c4ff92SAndroid Build Coastguard Worker , _argv(argv)
1983*89c4ff92SAndroid Build Coastguard Worker , _refargc(argc)
1984*89c4ff92SAndroid Build Coastguard Worker , _refargv(argv)
1985*89c4ff92SAndroid Build Coastguard Worker , _isvalid(false)
1986*89c4ff92SAndroid Build Coastguard Worker {
1987*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
1988*89c4ff92SAndroid Build Coastguard Worker LPWSTR* p;
1989*89c4ff92SAndroid Build Coastguard Worker p = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
1990*89c4ff92SAndroid Build Coastguard Worker _args.reserve(static_cast<size_t>(argc));
1991*89c4ff92SAndroid Build Coastguard Worker _argp.reserve(static_cast<size_t>(argc));
1992*89c4ff92SAndroid Build Coastguard Worker for (size_t i = 0; i < static_cast<size_t>(argc); ++i) {
1993*89c4ff92SAndroid Build Coastguard Worker _args.push_back(detail::toUtf8(std::wstring(p[i])));
1994*89c4ff92SAndroid Build Coastguard Worker _argp.push_back((char*)_args[i].data());
1995*89c4ff92SAndroid Build Coastguard Worker }
1996*89c4ff92SAndroid Build Coastguard Worker argv = _argp.data();
1997*89c4ff92SAndroid Build Coastguard Worker ::LocalFree(p);
1998*89c4ff92SAndroid Build Coastguard Worker _isvalid = true;
1999*89c4ff92SAndroid Build Coastguard Worker #else
2000*89c4ff92SAndroid Build Coastguard Worker std::setlocale(LC_ALL, "");
2001*89c4ff92SAndroid Build Coastguard Worker #if defined(__ANDROID__) && __ANDROID_API__ < 26
2002*89c4ff92SAndroid Build Coastguard Worker _isvalid = true;
2003*89c4ff92SAndroid Build Coastguard Worker #else
2004*89c4ff92SAndroid Build Coastguard Worker if (detail::equals_simple_insensitive(::nl_langinfo(CODESET), "UTF-8")) {
2005*89c4ff92SAndroid Build Coastguard Worker _isvalid = true;
2006*89c4ff92SAndroid Build Coastguard Worker }
2007*89c4ff92SAndroid Build Coastguard Worker #endif
2008*89c4ff92SAndroid Build Coastguard Worker #endif
2009*89c4ff92SAndroid Build Coastguard Worker }
2010*89c4ff92SAndroid Build Coastguard Worker
2011*89c4ff92SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2012*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.4.1 constructors and destructor
2013*89c4ff92SAndroid Build Coastguard Worker
path()2014*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path::path() noexcept {}
2015*89c4ff92SAndroid Build Coastguard Worker
path(const path & p)2016*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path::path(const path& p)
2017*89c4ff92SAndroid Build Coastguard Worker : _path(p._path)
2018*89c4ff92SAndroid Build Coastguard Worker {
2019*89c4ff92SAndroid Build Coastguard Worker }
2020*89c4ff92SAndroid Build Coastguard Worker
path(path && p)2021*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path::path(path&& p) noexcept
2022*89c4ff92SAndroid Build Coastguard Worker : _path(std::move(p._path))
2023*89c4ff92SAndroid Build Coastguard Worker {
2024*89c4ff92SAndroid Build Coastguard Worker }
2025*89c4ff92SAndroid Build Coastguard Worker
path(string_type && source,format fmt)2026*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path::path(string_type&& source, format fmt)
2027*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_USE_WCHAR_T
2028*89c4ff92SAndroid Build Coastguard Worker : _path(detail::toUtf8(source))
2029*89c4ff92SAndroid Build Coastguard Worker #else
2030*89c4ff92SAndroid Build Coastguard Worker : _path(std::move(source))
2031*89c4ff92SAndroid Build Coastguard Worker #endif
2032*89c4ff92SAndroid Build Coastguard Worker {
2033*89c4ff92SAndroid Build Coastguard Worker postprocess_path_with_format(_path, fmt);
2034*89c4ff92SAndroid Build Coastguard Worker }
2035*89c4ff92SAndroid Build Coastguard Worker
2036*89c4ff92SAndroid Build Coastguard Worker #endif // GHC_EXPAND_IMPL
2037*89c4ff92SAndroid Build Coastguard Worker
2038*89c4ff92SAndroid Build Coastguard Worker template <class Source, typename>
path(const Source & source,const std::locale & loc,format fmt)2039*89c4ff92SAndroid Build Coastguard Worker inline path::path(const Source& source, const std::locale& loc, format fmt)
2040*89c4ff92SAndroid Build Coastguard Worker : path(source, fmt)
2041*89c4ff92SAndroid Build Coastguard Worker {
2042*89c4ff92SAndroid Build Coastguard Worker std::string locName = loc.name();
2043*89c4ff92SAndroid Build Coastguard Worker if (!(locName.length() >= 5 && (locName.substr(locName.length() - 5) == "UTF-8" || locName.substr(locName.length() - 5) == "utf-8"))) {
2044*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error("This implementation only supports UTF-8 locales!", path(_path), detail::make_error_code(detail::portable_error::not_supported));
2045*89c4ff92SAndroid Build Coastguard Worker }
2046*89c4ff92SAndroid Build Coastguard Worker }
2047*89c4ff92SAndroid Build Coastguard Worker
2048*89c4ff92SAndroid Build Coastguard Worker template <class InputIterator>
path(InputIterator first,InputIterator last,const std::locale & loc,format fmt)2049*89c4ff92SAndroid Build Coastguard Worker inline path::path(InputIterator first, InputIterator last, const std::locale& loc, format fmt)
2050*89c4ff92SAndroid Build Coastguard Worker : path(std::basic_string<typename std::iterator_traits<InputIterator>::value_type>(first, last), fmt)
2051*89c4ff92SAndroid Build Coastguard Worker {
2052*89c4ff92SAndroid Build Coastguard Worker std::string locName = loc.name();
2053*89c4ff92SAndroid Build Coastguard Worker if (!(locName.length() >= 5 && (locName.substr(locName.length() - 5) == "UTF-8" || locName.substr(locName.length() - 5) == "utf-8"))) {
2054*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error("This implementation only supports UTF-8 locales!", path(_path), detail::make_error_code(detail::portable_error::not_supported));
2055*89c4ff92SAndroid Build Coastguard Worker }
2056*89c4ff92SAndroid Build Coastguard Worker }
2057*89c4ff92SAndroid Build Coastguard Worker
2058*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_EXPAND_IMPL
2059*89c4ff92SAndroid Build Coastguard Worker
~path()2060*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path::~path() {}
2061*89c4ff92SAndroid Build Coastguard Worker
2062*89c4ff92SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2063*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.4.2 assignments
2064*89c4ff92SAndroid Build Coastguard Worker
operator =(const path & p)2065*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path& path::operator=(const path& p)
2066*89c4ff92SAndroid Build Coastguard Worker {
2067*89c4ff92SAndroid Build Coastguard Worker _path = p._path;
2068*89c4ff92SAndroid Build Coastguard Worker return *this;
2069*89c4ff92SAndroid Build Coastguard Worker }
2070*89c4ff92SAndroid Build Coastguard Worker
operator =(path && p)2071*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path& path::operator=(path&& p) noexcept
2072*89c4ff92SAndroid Build Coastguard Worker {
2073*89c4ff92SAndroid Build Coastguard Worker _path = std::move(p._path);
2074*89c4ff92SAndroid Build Coastguard Worker return *this;
2075*89c4ff92SAndroid Build Coastguard Worker }
2076*89c4ff92SAndroid Build Coastguard Worker
operator =(path::string_type && source)2077*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path& path::operator=(path::string_type&& source)
2078*89c4ff92SAndroid Build Coastguard Worker {
2079*89c4ff92SAndroid Build Coastguard Worker return assign(source);
2080*89c4ff92SAndroid Build Coastguard Worker }
2081*89c4ff92SAndroid Build Coastguard Worker
assign(path::string_type && source)2082*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path& path::assign(path::string_type&& source)
2083*89c4ff92SAndroid Build Coastguard Worker {
2084*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_USE_WCHAR_T
2085*89c4ff92SAndroid Build Coastguard Worker _path = detail::toUtf8(source);
2086*89c4ff92SAndroid Build Coastguard Worker #else
2087*89c4ff92SAndroid Build Coastguard Worker _path = std::move(source);
2088*89c4ff92SAndroid Build Coastguard Worker #endif
2089*89c4ff92SAndroid Build Coastguard Worker postprocess_path_with_format(_path, native_format);
2090*89c4ff92SAndroid Build Coastguard Worker return *this;
2091*89c4ff92SAndroid Build Coastguard Worker }
2092*89c4ff92SAndroid Build Coastguard Worker
2093*89c4ff92SAndroid Build Coastguard Worker #endif // GHC_EXPAND_IMPL
2094*89c4ff92SAndroid Build Coastguard Worker
2095*89c4ff92SAndroid Build Coastguard Worker template <class Source>
operator =(const Source & source)2096*89c4ff92SAndroid Build Coastguard Worker inline path& path::operator=(const Source& source)
2097*89c4ff92SAndroid Build Coastguard Worker {
2098*89c4ff92SAndroid Build Coastguard Worker return assign(source);
2099*89c4ff92SAndroid Build Coastguard Worker }
2100*89c4ff92SAndroid Build Coastguard Worker
2101*89c4ff92SAndroid Build Coastguard Worker template <class Source>
assign(const Source & source)2102*89c4ff92SAndroid Build Coastguard Worker inline path& path::assign(const Source& source)
2103*89c4ff92SAndroid Build Coastguard Worker {
2104*89c4ff92SAndroid Build Coastguard Worker _path.assign(detail::toUtf8(source));
2105*89c4ff92SAndroid Build Coastguard Worker postprocess_path_with_format(_path, native_format);
2106*89c4ff92SAndroid Build Coastguard Worker return *this;
2107*89c4ff92SAndroid Build Coastguard Worker }
2108*89c4ff92SAndroid Build Coastguard Worker
2109*89c4ff92SAndroid Build Coastguard Worker template <>
assign(const path & source)2110*89c4ff92SAndroid Build Coastguard Worker inline path& path::assign<path>(const path& source)
2111*89c4ff92SAndroid Build Coastguard Worker {
2112*89c4ff92SAndroid Build Coastguard Worker _path = source._path;
2113*89c4ff92SAndroid Build Coastguard Worker return *this;
2114*89c4ff92SAndroid Build Coastguard Worker }
2115*89c4ff92SAndroid Build Coastguard Worker
2116*89c4ff92SAndroid Build Coastguard Worker template <class InputIterator>
assign(InputIterator first,InputIterator last)2117*89c4ff92SAndroid Build Coastguard Worker inline path& path::assign(InputIterator first, InputIterator last)
2118*89c4ff92SAndroid Build Coastguard Worker {
2119*89c4ff92SAndroid Build Coastguard Worker _path.assign(first, last);
2120*89c4ff92SAndroid Build Coastguard Worker postprocess_path_with_format(_path, native_format);
2121*89c4ff92SAndroid Build Coastguard Worker return *this;
2122*89c4ff92SAndroid Build Coastguard Worker }
2123*89c4ff92SAndroid Build Coastguard Worker
2124*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_EXPAND_IMPL
2125*89c4ff92SAndroid Build Coastguard Worker
2126*89c4ff92SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2127*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.4.3 appends
2128*89c4ff92SAndroid Build Coastguard Worker
operator /=(const path & p)2129*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path& path::operator/=(const path& p)
2130*89c4ff92SAndroid Build Coastguard Worker {
2131*89c4ff92SAndroid Build Coastguard Worker if (p.empty()) {
2132*89c4ff92SAndroid Build Coastguard Worker // was: if ((!has_root_directory() && is_absolute()) || has_filename())
2133*89c4ff92SAndroid Build Coastguard Worker if (!_path.empty() && _path[_path.length() - 1] != '/' && _path[_path.length() - 1] != ':') {
2134*89c4ff92SAndroid Build Coastguard Worker _path += '/';
2135*89c4ff92SAndroid Build Coastguard Worker }
2136*89c4ff92SAndroid Build Coastguard Worker return *this;
2137*89c4ff92SAndroid Build Coastguard Worker }
2138*89c4ff92SAndroid Build Coastguard Worker if ((p.is_absolute() && (_path != root_name() || p._path != "/")) || (p.has_root_name() && p.root_name() != root_name())) {
2139*89c4ff92SAndroid Build Coastguard Worker assign(p);
2140*89c4ff92SAndroid Build Coastguard Worker return *this;
2141*89c4ff92SAndroid Build Coastguard Worker }
2142*89c4ff92SAndroid Build Coastguard Worker if (p.has_root_directory()) {
2143*89c4ff92SAndroid Build Coastguard Worker assign(root_name());
2144*89c4ff92SAndroid Build Coastguard Worker }
2145*89c4ff92SAndroid Build Coastguard Worker else if ((!has_root_directory() && is_absolute()) || has_filename()) {
2146*89c4ff92SAndroid Build Coastguard Worker _path += '/';
2147*89c4ff92SAndroid Build Coastguard Worker }
2148*89c4ff92SAndroid Build Coastguard Worker auto iter = p.begin();
2149*89c4ff92SAndroid Build Coastguard Worker bool first = true;
2150*89c4ff92SAndroid Build Coastguard Worker if (p.has_root_name()) {
2151*89c4ff92SAndroid Build Coastguard Worker ++iter;
2152*89c4ff92SAndroid Build Coastguard Worker }
2153*89c4ff92SAndroid Build Coastguard Worker while (iter != p.end()) {
2154*89c4ff92SAndroid Build Coastguard Worker if (!first && !(!_path.empty() && _path[_path.length() - 1] == '/')) {
2155*89c4ff92SAndroid Build Coastguard Worker _path += '/';
2156*89c4ff92SAndroid Build Coastguard Worker }
2157*89c4ff92SAndroid Build Coastguard Worker first = false;
2158*89c4ff92SAndroid Build Coastguard Worker _path += (*iter++).generic_string();
2159*89c4ff92SAndroid Build Coastguard Worker }
2160*89c4ff92SAndroid Build Coastguard Worker return *this;
2161*89c4ff92SAndroid Build Coastguard Worker }
2162*89c4ff92SAndroid Build Coastguard Worker
append_name(const char * name)2163*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void path::append_name(const char* name)
2164*89c4ff92SAndroid Build Coastguard Worker {
2165*89c4ff92SAndroid Build Coastguard Worker if (_path.empty()) {
2166*89c4ff92SAndroid Build Coastguard Worker this->operator/=(path(name));
2167*89c4ff92SAndroid Build Coastguard Worker }
2168*89c4ff92SAndroid Build Coastguard Worker else {
2169*89c4ff92SAndroid Build Coastguard Worker if (_path.back() != path::generic_separator) {
2170*89c4ff92SAndroid Build Coastguard Worker _path.push_back(path::generic_separator);
2171*89c4ff92SAndroid Build Coastguard Worker }
2172*89c4ff92SAndroid Build Coastguard Worker _path += name;
2173*89c4ff92SAndroid Build Coastguard Worker }
2174*89c4ff92SAndroid Build Coastguard Worker }
2175*89c4ff92SAndroid Build Coastguard Worker
2176*89c4ff92SAndroid Build Coastguard Worker #endif // GHC_EXPAND_IMPL
2177*89c4ff92SAndroid Build Coastguard Worker
2178*89c4ff92SAndroid Build Coastguard Worker template <class Source>
operator /=(const Source & source)2179*89c4ff92SAndroid Build Coastguard Worker inline path& path::operator/=(const Source& source)
2180*89c4ff92SAndroid Build Coastguard Worker {
2181*89c4ff92SAndroid Build Coastguard Worker return append(source);
2182*89c4ff92SAndroid Build Coastguard Worker }
2183*89c4ff92SAndroid Build Coastguard Worker
2184*89c4ff92SAndroid Build Coastguard Worker template <class Source>
append(const Source & source)2185*89c4ff92SAndroid Build Coastguard Worker inline path& path::append(const Source& source)
2186*89c4ff92SAndroid Build Coastguard Worker {
2187*89c4ff92SAndroid Build Coastguard Worker return this->operator/=(path(detail::toUtf8(source)));
2188*89c4ff92SAndroid Build Coastguard Worker }
2189*89c4ff92SAndroid Build Coastguard Worker
2190*89c4ff92SAndroid Build Coastguard Worker template <>
append(const path & p)2191*89c4ff92SAndroid Build Coastguard Worker inline path& path::append<path>(const path& p)
2192*89c4ff92SAndroid Build Coastguard Worker {
2193*89c4ff92SAndroid Build Coastguard Worker return this->operator/=(p);
2194*89c4ff92SAndroid Build Coastguard Worker }
2195*89c4ff92SAndroid Build Coastguard Worker
2196*89c4ff92SAndroid Build Coastguard Worker template <class InputIterator>
append(InputIterator first,InputIterator last)2197*89c4ff92SAndroid Build Coastguard Worker inline path& path::append(InputIterator first, InputIterator last)
2198*89c4ff92SAndroid Build Coastguard Worker {
2199*89c4ff92SAndroid Build Coastguard Worker std::basic_string<typename std::iterator_traits<InputIterator>::value_type> part(first, last);
2200*89c4ff92SAndroid Build Coastguard Worker return append(part);
2201*89c4ff92SAndroid Build Coastguard Worker }
2202*89c4ff92SAndroid Build Coastguard Worker
2203*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_EXPAND_IMPL
2204*89c4ff92SAndroid Build Coastguard Worker
2205*89c4ff92SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2206*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.4.4 concatenation
2207*89c4ff92SAndroid Build Coastguard Worker
operator +=(const path & x)2208*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path& path::operator+=(const path& x)
2209*89c4ff92SAndroid Build Coastguard Worker {
2210*89c4ff92SAndroid Build Coastguard Worker return concat(x._path);
2211*89c4ff92SAndroid Build Coastguard Worker }
2212*89c4ff92SAndroid Build Coastguard Worker
operator +=(const string_type & x)2213*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path& path::operator+=(const string_type& x)
2214*89c4ff92SAndroid Build Coastguard Worker {
2215*89c4ff92SAndroid Build Coastguard Worker return concat(x);
2216*89c4ff92SAndroid Build Coastguard Worker }
2217*89c4ff92SAndroid Build Coastguard Worker
2218*89c4ff92SAndroid Build Coastguard Worker #ifdef __cpp_lib_string_view
operator +=(std::basic_string_view<value_type> x)2219*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path& path::operator+=(std::basic_string_view<value_type> x)
2220*89c4ff92SAndroid Build Coastguard Worker {
2221*89c4ff92SAndroid Build Coastguard Worker return concat(x);
2222*89c4ff92SAndroid Build Coastguard Worker }
2223*89c4ff92SAndroid Build Coastguard Worker #endif
2224*89c4ff92SAndroid Build Coastguard Worker
operator +=(const value_type * x)2225*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path& path::operator+=(const value_type* x)
2226*89c4ff92SAndroid Build Coastguard Worker {
2227*89c4ff92SAndroid Build Coastguard Worker return concat(string_type(x));
2228*89c4ff92SAndroid Build Coastguard Worker }
2229*89c4ff92SAndroid Build Coastguard Worker
operator +=(value_type x)2230*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path& path::operator+=(value_type x)
2231*89c4ff92SAndroid Build Coastguard Worker {
2232*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
2233*89c4ff92SAndroid Build Coastguard Worker if (x == '\\') {
2234*89c4ff92SAndroid Build Coastguard Worker x = generic_separator;
2235*89c4ff92SAndroid Build Coastguard Worker }
2236*89c4ff92SAndroid Build Coastguard Worker #endif
2237*89c4ff92SAndroid Build Coastguard Worker if (_path.empty() || _path.back() != generic_separator) {
2238*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_USE_WCHAR_T
2239*89c4ff92SAndroid Build Coastguard Worker _path += detail::toUtf8(string_type(1, x));
2240*89c4ff92SAndroid Build Coastguard Worker #else
2241*89c4ff92SAndroid Build Coastguard Worker _path += x;
2242*89c4ff92SAndroid Build Coastguard Worker #endif
2243*89c4ff92SAndroid Build Coastguard Worker }
2244*89c4ff92SAndroid Build Coastguard Worker return *this;
2245*89c4ff92SAndroid Build Coastguard Worker }
2246*89c4ff92SAndroid Build Coastguard Worker
2247*89c4ff92SAndroid Build Coastguard Worker #endif // GHC_EXPAND_IMPL
2248*89c4ff92SAndroid Build Coastguard Worker
2249*89c4ff92SAndroid Build Coastguard Worker template <class Source>
operator +=(const Source & x)2250*89c4ff92SAndroid Build Coastguard Worker inline path::path_from_string<Source>& path::operator+=(const Source& x)
2251*89c4ff92SAndroid Build Coastguard Worker {
2252*89c4ff92SAndroid Build Coastguard Worker return concat(x);
2253*89c4ff92SAndroid Build Coastguard Worker }
2254*89c4ff92SAndroid Build Coastguard Worker
2255*89c4ff92SAndroid Build Coastguard Worker template <class EcharT>
operator +=(EcharT x)2256*89c4ff92SAndroid Build Coastguard Worker inline path::path_type_EcharT<EcharT>& path::operator+=(EcharT x)
2257*89c4ff92SAndroid Build Coastguard Worker {
2258*89c4ff92SAndroid Build Coastguard Worker std::basic_string<EcharT> part(1, x);
2259*89c4ff92SAndroid Build Coastguard Worker concat(detail::toUtf8(part));
2260*89c4ff92SAndroid Build Coastguard Worker return *this;
2261*89c4ff92SAndroid Build Coastguard Worker }
2262*89c4ff92SAndroid Build Coastguard Worker
2263*89c4ff92SAndroid Build Coastguard Worker template <class Source>
concat(const Source & x)2264*89c4ff92SAndroid Build Coastguard Worker inline path& path::concat(const Source& x)
2265*89c4ff92SAndroid Build Coastguard Worker {
2266*89c4ff92SAndroid Build Coastguard Worker path p(x);
2267*89c4ff92SAndroid Build Coastguard Worker postprocess_path_with_format(p._path, native_format);
2268*89c4ff92SAndroid Build Coastguard Worker _path += p._path;
2269*89c4ff92SAndroid Build Coastguard Worker return *this;
2270*89c4ff92SAndroid Build Coastguard Worker }
2271*89c4ff92SAndroid Build Coastguard Worker template <class InputIterator>
concat(InputIterator first,InputIterator last)2272*89c4ff92SAndroid Build Coastguard Worker inline path& path::concat(InputIterator first, InputIterator last)
2273*89c4ff92SAndroid Build Coastguard Worker {
2274*89c4ff92SAndroid Build Coastguard Worker _path.append(first, last);
2275*89c4ff92SAndroid Build Coastguard Worker postprocess_path_with_format(_path, native_format);
2276*89c4ff92SAndroid Build Coastguard Worker return *this;
2277*89c4ff92SAndroid Build Coastguard Worker }
2278*89c4ff92SAndroid Build Coastguard Worker
2279*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_EXPAND_IMPL
2280*89c4ff92SAndroid Build Coastguard Worker
2281*89c4ff92SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2282*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.4.5 modifiers
clear()2283*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void path::clear() noexcept
2284*89c4ff92SAndroid Build Coastguard Worker {
2285*89c4ff92SAndroid Build Coastguard Worker _path.clear();
2286*89c4ff92SAndroid Build Coastguard Worker }
2287*89c4ff92SAndroid Build Coastguard Worker
make_preferred()2288*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path& path::make_preferred()
2289*89c4ff92SAndroid Build Coastguard Worker {
2290*89c4ff92SAndroid Build Coastguard Worker // as this filesystem implementation only uses generic_format
2291*89c4ff92SAndroid Build Coastguard Worker // internally, this must be a no-op
2292*89c4ff92SAndroid Build Coastguard Worker return *this;
2293*89c4ff92SAndroid Build Coastguard Worker }
2294*89c4ff92SAndroid Build Coastguard Worker
remove_filename()2295*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path& path::remove_filename()
2296*89c4ff92SAndroid Build Coastguard Worker {
2297*89c4ff92SAndroid Build Coastguard Worker if (has_filename()) {
2298*89c4ff92SAndroid Build Coastguard Worker _path.erase(_path.size() - filename()._path.size());
2299*89c4ff92SAndroid Build Coastguard Worker }
2300*89c4ff92SAndroid Build Coastguard Worker return *this;
2301*89c4ff92SAndroid Build Coastguard Worker }
2302*89c4ff92SAndroid Build Coastguard Worker
replace_filename(const path & replacement)2303*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path& path::replace_filename(const path& replacement)
2304*89c4ff92SAndroid Build Coastguard Worker {
2305*89c4ff92SAndroid Build Coastguard Worker remove_filename();
2306*89c4ff92SAndroid Build Coastguard Worker return append(replacement);
2307*89c4ff92SAndroid Build Coastguard Worker }
2308*89c4ff92SAndroid Build Coastguard Worker
replace_extension(const path & replacement)2309*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path& path::replace_extension(const path& replacement)
2310*89c4ff92SAndroid Build Coastguard Worker {
2311*89c4ff92SAndroid Build Coastguard Worker if (has_extension()) {
2312*89c4ff92SAndroid Build Coastguard Worker _path.erase(_path.size() - extension()._path.size());
2313*89c4ff92SAndroid Build Coastguard Worker }
2314*89c4ff92SAndroid Build Coastguard Worker if (!replacement.empty() && replacement._path[0] != '.') {
2315*89c4ff92SAndroid Build Coastguard Worker _path += '.';
2316*89c4ff92SAndroid Build Coastguard Worker }
2317*89c4ff92SAndroid Build Coastguard Worker return concat(replacement);
2318*89c4ff92SAndroid Build Coastguard Worker }
2319*89c4ff92SAndroid Build Coastguard Worker
swap(path & rhs)2320*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void path::swap(path& rhs) noexcept
2321*89c4ff92SAndroid Build Coastguard Worker {
2322*89c4ff92SAndroid Build Coastguard Worker _path.swap(rhs._path);
2323*89c4ff92SAndroid Build Coastguard Worker }
2324*89c4ff92SAndroid Build Coastguard Worker
2325*89c4ff92SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2326*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.4.6, native format observers
2327*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
native_impl() const2328*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path::impl_string_type path::native_impl() const
2329*89c4ff92SAndroid Build Coastguard Worker {
2330*89c4ff92SAndroid Build Coastguard Worker impl_string_type result;
2331*89c4ff92SAndroid Build Coastguard Worker if (is_absolute() && _path.length() > MAX_PATH - 10) {
2332*89c4ff92SAndroid Build Coastguard Worker // expand long Windows filenames with marker
2333*89c4ff92SAndroid Build Coastguard Worker if (has_root_name() && _path[0] == '/') {
2334*89c4ff92SAndroid Build Coastguard Worker result = "\\\\?\\UNC" + _path.substr(1);
2335*89c4ff92SAndroid Build Coastguard Worker }
2336*89c4ff92SAndroid Build Coastguard Worker else {
2337*89c4ff92SAndroid Build Coastguard Worker result = "\\\\?\\" + _path;
2338*89c4ff92SAndroid Build Coastguard Worker }
2339*89c4ff92SAndroid Build Coastguard Worker }
2340*89c4ff92SAndroid Build Coastguard Worker else {
2341*89c4ff92SAndroid Build Coastguard Worker result = _path;
2342*89c4ff92SAndroid Build Coastguard Worker }
2343*89c4ff92SAndroid Build Coastguard Worker /*if (has_root_name() && root_name()._path[0] == '/') {
2344*89c4ff92SAndroid Build Coastguard Worker return _path;
2345*89c4ff92SAndroid Build Coastguard Worker }*/
2346*89c4ff92SAndroid Build Coastguard Worker for (auto& c : result) {
2347*89c4ff92SAndroid Build Coastguard Worker if (c == '/') {
2348*89c4ff92SAndroid Build Coastguard Worker c = '\\';
2349*89c4ff92SAndroid Build Coastguard Worker }
2350*89c4ff92SAndroid Build Coastguard Worker }
2351*89c4ff92SAndroid Build Coastguard Worker return result;
2352*89c4ff92SAndroid Build Coastguard Worker }
2353*89c4ff92SAndroid Build Coastguard Worker #else
native_impl() const2354*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE const path::impl_string_type& path::native_impl() const
2355*89c4ff92SAndroid Build Coastguard Worker {
2356*89c4ff92SAndroid Build Coastguard Worker return _path;
2357*89c4ff92SAndroid Build Coastguard Worker }
2358*89c4ff92SAndroid Build Coastguard Worker #endif
2359*89c4ff92SAndroid Build Coastguard Worker
native() const2360*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE const path::string_type& path::native() const
2361*89c4ff92SAndroid Build Coastguard Worker {
2362*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
2363*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_USE_WCHAR_T
2364*89c4ff92SAndroid Build Coastguard Worker _native_cache = detail::fromUtf8<string_type>(native_impl());
2365*89c4ff92SAndroid Build Coastguard Worker #else
2366*89c4ff92SAndroid Build Coastguard Worker _native_cache = native_impl();
2367*89c4ff92SAndroid Build Coastguard Worker #endif
2368*89c4ff92SAndroid Build Coastguard Worker return _native_cache;
2369*89c4ff92SAndroid Build Coastguard Worker #else
2370*89c4ff92SAndroid Build Coastguard Worker return _path;
2371*89c4ff92SAndroid Build Coastguard Worker #endif
2372*89c4ff92SAndroid Build Coastguard Worker }
2373*89c4ff92SAndroid Build Coastguard Worker
c_str() const2374*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE const path::value_type* path::c_str() const
2375*89c4ff92SAndroid Build Coastguard Worker {
2376*89c4ff92SAndroid Build Coastguard Worker return native().c_str();
2377*89c4ff92SAndroid Build Coastguard Worker }
2378*89c4ff92SAndroid Build Coastguard Worker
operator path::string_type() const2379*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path::operator path::string_type() const
2380*89c4ff92SAndroid Build Coastguard Worker {
2381*89c4ff92SAndroid Build Coastguard Worker return native();
2382*89c4ff92SAndroid Build Coastguard Worker }
2383*89c4ff92SAndroid Build Coastguard Worker
2384*89c4ff92SAndroid Build Coastguard Worker #endif // GHC_EXPAND_IMPL
2385*89c4ff92SAndroid Build Coastguard Worker
2386*89c4ff92SAndroid Build Coastguard Worker template <class EcharT, class traits, class Allocator>
string(const Allocator & a) const2387*89c4ff92SAndroid Build Coastguard Worker inline std::basic_string<EcharT, traits, Allocator> path::string(const Allocator& a) const
2388*89c4ff92SAndroid Build Coastguard Worker {
2389*89c4ff92SAndroid Build Coastguard Worker return detail::fromUtf8<std::basic_string<EcharT, traits, Allocator>>(native_impl(), a);
2390*89c4ff92SAndroid Build Coastguard Worker }
2391*89c4ff92SAndroid Build Coastguard Worker
2392*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_EXPAND_IMPL
2393*89c4ff92SAndroid Build Coastguard Worker
string() const2394*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE std::string path::string() const
2395*89c4ff92SAndroid Build Coastguard Worker {
2396*89c4ff92SAndroid Build Coastguard Worker return native_impl();
2397*89c4ff92SAndroid Build Coastguard Worker }
2398*89c4ff92SAndroid Build Coastguard Worker
wstring() const2399*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE std::wstring path::wstring() const
2400*89c4ff92SAndroid Build Coastguard Worker {
2401*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_USE_WCHAR_T
2402*89c4ff92SAndroid Build Coastguard Worker return native();
2403*89c4ff92SAndroid Build Coastguard Worker #else
2404*89c4ff92SAndroid Build Coastguard Worker return detail::fromUtf8<std::wstring>(native());
2405*89c4ff92SAndroid Build Coastguard Worker #endif
2406*89c4ff92SAndroid Build Coastguard Worker }
2407*89c4ff92SAndroid Build Coastguard Worker
u8string() const2408*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE std::string path::u8string() const
2409*89c4ff92SAndroid Build Coastguard Worker {
2410*89c4ff92SAndroid Build Coastguard Worker return native_impl();
2411*89c4ff92SAndroid Build Coastguard Worker }
2412*89c4ff92SAndroid Build Coastguard Worker
u16string() const2413*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE std::u16string path::u16string() const
2414*89c4ff92SAndroid Build Coastguard Worker {
2415*89c4ff92SAndroid Build Coastguard Worker return detail::fromUtf8<std::u16string>(native_impl());
2416*89c4ff92SAndroid Build Coastguard Worker }
2417*89c4ff92SAndroid Build Coastguard Worker
u32string() const2418*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE std::u32string path::u32string() const
2419*89c4ff92SAndroid Build Coastguard Worker {
2420*89c4ff92SAndroid Build Coastguard Worker return detail::fromUtf8<std::u32string>(native_impl());
2421*89c4ff92SAndroid Build Coastguard Worker }
2422*89c4ff92SAndroid Build Coastguard Worker
2423*89c4ff92SAndroid Build Coastguard Worker #endif // GHC_EXPAND_IMPL
2424*89c4ff92SAndroid Build Coastguard Worker
2425*89c4ff92SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2426*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.4.7, generic format observers
2427*89c4ff92SAndroid Build Coastguard Worker template <class EcharT, class traits, class Allocator>
generic_string(const Allocator & a) const2428*89c4ff92SAndroid Build Coastguard Worker inline std::basic_string<EcharT, traits, Allocator> path::generic_string(const Allocator& a) const
2429*89c4ff92SAndroid Build Coastguard Worker {
2430*89c4ff92SAndroid Build Coastguard Worker return detail::fromUtf8<std::basic_string<EcharT, traits, Allocator>>(_path, a);
2431*89c4ff92SAndroid Build Coastguard Worker }
2432*89c4ff92SAndroid Build Coastguard Worker
2433*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_EXPAND_IMPL
2434*89c4ff92SAndroid Build Coastguard Worker
generic_string() const2435*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE const std::string& path::generic_string() const
2436*89c4ff92SAndroid Build Coastguard Worker {
2437*89c4ff92SAndroid Build Coastguard Worker return _path;
2438*89c4ff92SAndroid Build Coastguard Worker }
2439*89c4ff92SAndroid Build Coastguard Worker
generic_wstring() const2440*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE std::wstring path::generic_wstring() const
2441*89c4ff92SAndroid Build Coastguard Worker {
2442*89c4ff92SAndroid Build Coastguard Worker return detail::fromUtf8<std::wstring>(_path);
2443*89c4ff92SAndroid Build Coastguard Worker }
2444*89c4ff92SAndroid Build Coastguard Worker
generic_u8string() const2445*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE std::string path::generic_u8string() const
2446*89c4ff92SAndroid Build Coastguard Worker {
2447*89c4ff92SAndroid Build Coastguard Worker return _path;
2448*89c4ff92SAndroid Build Coastguard Worker }
2449*89c4ff92SAndroid Build Coastguard Worker
generic_u16string() const2450*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE std::u16string path::generic_u16string() const
2451*89c4ff92SAndroid Build Coastguard Worker {
2452*89c4ff92SAndroid Build Coastguard Worker return detail::fromUtf8<std::u16string>(_path);
2453*89c4ff92SAndroid Build Coastguard Worker }
2454*89c4ff92SAndroid Build Coastguard Worker
generic_u32string() const2455*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE std::u32string path::generic_u32string() const
2456*89c4ff92SAndroid Build Coastguard Worker {
2457*89c4ff92SAndroid Build Coastguard Worker return detail::fromUtf8<std::u32string>(_path);
2458*89c4ff92SAndroid Build Coastguard Worker }
2459*89c4ff92SAndroid Build Coastguard Worker
2460*89c4ff92SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2461*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.4.8, compare
compare(const path & p) const2462*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE int path::compare(const path& p) const noexcept
2463*89c4ff92SAndroid Build Coastguard Worker {
2464*89c4ff92SAndroid Build Coastguard Worker return native().compare(p.native());
2465*89c4ff92SAndroid Build Coastguard Worker }
2466*89c4ff92SAndroid Build Coastguard Worker
compare(const string_type & s) const2467*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE int path::compare(const string_type& s) const
2468*89c4ff92SAndroid Build Coastguard Worker {
2469*89c4ff92SAndroid Build Coastguard Worker return native().compare(path(s).native());
2470*89c4ff92SAndroid Build Coastguard Worker }
2471*89c4ff92SAndroid Build Coastguard Worker
2472*89c4ff92SAndroid Build Coastguard Worker #ifdef __cpp_lib_string_view
compare(std::basic_string_view<value_type> s) const2473*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE int path::compare(std::basic_string_view<value_type> s) const
2474*89c4ff92SAndroid Build Coastguard Worker {
2475*89c4ff92SAndroid Build Coastguard Worker return native().compare(path(s).native());
2476*89c4ff92SAndroid Build Coastguard Worker }
2477*89c4ff92SAndroid Build Coastguard Worker #endif
2478*89c4ff92SAndroid Build Coastguard Worker
compare(const value_type * s) const2479*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE int path::compare(const value_type* s) const
2480*89c4ff92SAndroid Build Coastguard Worker {
2481*89c4ff92SAndroid Build Coastguard Worker return native().compare(path(s).native());
2482*89c4ff92SAndroid Build Coastguard Worker }
2483*89c4ff92SAndroid Build Coastguard Worker
2484*89c4ff92SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2485*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.4.9, decomposition
root_name() const2486*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path path::root_name() const
2487*89c4ff92SAndroid Build Coastguard Worker {
2488*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
2489*89c4ff92SAndroid Build Coastguard Worker if (_path.length() >= 2 && std::toupper(static_cast<unsigned char>(_path[0])) >= 'A' && std::toupper(static_cast<unsigned char>(_path[0])) <= 'Z' && _path[1] == ':') {
2490*89c4ff92SAndroid Build Coastguard Worker return path(_path.substr(0, 2));
2491*89c4ff92SAndroid Build Coastguard Worker }
2492*89c4ff92SAndroid Build Coastguard Worker #endif
2493*89c4ff92SAndroid Build Coastguard Worker if (_path.length() > 2 && _path[0] == '/' && _path[1] == '/' && _path[2] != '/' && std::isprint(_path[2])) {
2494*89c4ff92SAndroid Build Coastguard Worker impl_string_type::size_type pos = _path.find_first_of("/\\", 3);
2495*89c4ff92SAndroid Build Coastguard Worker if (pos == impl_string_type::npos) {
2496*89c4ff92SAndroid Build Coastguard Worker return path(_path);
2497*89c4ff92SAndroid Build Coastguard Worker }
2498*89c4ff92SAndroid Build Coastguard Worker else {
2499*89c4ff92SAndroid Build Coastguard Worker return path(_path.substr(0, pos));
2500*89c4ff92SAndroid Build Coastguard Worker }
2501*89c4ff92SAndroid Build Coastguard Worker }
2502*89c4ff92SAndroid Build Coastguard Worker return path();
2503*89c4ff92SAndroid Build Coastguard Worker }
2504*89c4ff92SAndroid Build Coastguard Worker
root_directory() const2505*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path path::root_directory() const
2506*89c4ff92SAndroid Build Coastguard Worker {
2507*89c4ff92SAndroid Build Coastguard Worker path root = root_name();
2508*89c4ff92SAndroid Build Coastguard Worker if (_path.length() > root._path.length() && _path[root._path.length()] == '/') {
2509*89c4ff92SAndroid Build Coastguard Worker return path("/");
2510*89c4ff92SAndroid Build Coastguard Worker }
2511*89c4ff92SAndroid Build Coastguard Worker return path();
2512*89c4ff92SAndroid Build Coastguard Worker }
2513*89c4ff92SAndroid Build Coastguard Worker
root_path() const2514*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path path::root_path() const
2515*89c4ff92SAndroid Build Coastguard Worker {
2516*89c4ff92SAndroid Build Coastguard Worker return root_name().generic_string() + root_directory().generic_string();
2517*89c4ff92SAndroid Build Coastguard Worker }
2518*89c4ff92SAndroid Build Coastguard Worker
relative_path() const2519*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path path::relative_path() const
2520*89c4ff92SAndroid Build Coastguard Worker {
2521*89c4ff92SAndroid Build Coastguard Worker std::string root = root_path()._path;
2522*89c4ff92SAndroid Build Coastguard Worker return path(_path.substr((std::min)(root.length(), _path.length())), generic_format);
2523*89c4ff92SAndroid Build Coastguard Worker }
2524*89c4ff92SAndroid Build Coastguard Worker
parent_path() const2525*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path path::parent_path() const
2526*89c4ff92SAndroid Build Coastguard Worker {
2527*89c4ff92SAndroid Build Coastguard Worker if (has_relative_path()) {
2528*89c4ff92SAndroid Build Coastguard Worker if (empty() || begin() == --end()) {
2529*89c4ff92SAndroid Build Coastguard Worker return path();
2530*89c4ff92SAndroid Build Coastguard Worker }
2531*89c4ff92SAndroid Build Coastguard Worker else {
2532*89c4ff92SAndroid Build Coastguard Worker path pp;
2533*89c4ff92SAndroid Build Coastguard Worker for (string_type s : input_iterator_range<iterator>(begin(), --end())) {
2534*89c4ff92SAndroid Build Coastguard Worker if (s == "/") {
2535*89c4ff92SAndroid Build Coastguard Worker // don't use append to join a path-
2536*89c4ff92SAndroid Build Coastguard Worker pp += s;
2537*89c4ff92SAndroid Build Coastguard Worker }
2538*89c4ff92SAndroid Build Coastguard Worker else {
2539*89c4ff92SAndroid Build Coastguard Worker pp /= s;
2540*89c4ff92SAndroid Build Coastguard Worker }
2541*89c4ff92SAndroid Build Coastguard Worker }
2542*89c4ff92SAndroid Build Coastguard Worker return pp;
2543*89c4ff92SAndroid Build Coastguard Worker }
2544*89c4ff92SAndroid Build Coastguard Worker }
2545*89c4ff92SAndroid Build Coastguard Worker else {
2546*89c4ff92SAndroid Build Coastguard Worker return *this;
2547*89c4ff92SAndroid Build Coastguard Worker }
2548*89c4ff92SAndroid Build Coastguard Worker }
2549*89c4ff92SAndroid Build Coastguard Worker
filename() const2550*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path path::filename() const
2551*89c4ff92SAndroid Build Coastguard Worker {
2552*89c4ff92SAndroid Build Coastguard Worker return relative_path().empty() ? path() : path(*--end());
2553*89c4ff92SAndroid Build Coastguard Worker }
2554*89c4ff92SAndroid Build Coastguard Worker
stem() const2555*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path path::stem() const
2556*89c4ff92SAndroid Build Coastguard Worker {
2557*89c4ff92SAndroid Build Coastguard Worker impl_string_type fn = filename().string();
2558*89c4ff92SAndroid Build Coastguard Worker if (fn != "." && fn != "..") {
2559*89c4ff92SAndroid Build Coastguard Worker impl_string_type::size_type n = fn.rfind('.');
2560*89c4ff92SAndroid Build Coastguard Worker if (n != impl_string_type::npos && n != 0) {
2561*89c4ff92SAndroid Build Coastguard Worker return path{fn.substr(0, n)};
2562*89c4ff92SAndroid Build Coastguard Worker }
2563*89c4ff92SAndroid Build Coastguard Worker }
2564*89c4ff92SAndroid Build Coastguard Worker return path{fn};
2565*89c4ff92SAndroid Build Coastguard Worker }
2566*89c4ff92SAndroid Build Coastguard Worker
extension() const2567*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path path::extension() const
2568*89c4ff92SAndroid Build Coastguard Worker {
2569*89c4ff92SAndroid Build Coastguard Worker impl_string_type fn = filename().string();
2570*89c4ff92SAndroid Build Coastguard Worker impl_string_type::size_type pos = fn.find_last_of('.');
2571*89c4ff92SAndroid Build Coastguard Worker if (pos == std::string::npos || pos == 0) {
2572*89c4ff92SAndroid Build Coastguard Worker return "";
2573*89c4ff92SAndroid Build Coastguard Worker }
2574*89c4ff92SAndroid Build Coastguard Worker return fn.substr(pos);
2575*89c4ff92SAndroid Build Coastguard Worker }
2576*89c4ff92SAndroid Build Coastguard Worker
2577*89c4ff92SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2578*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.4.10, query
empty() const2579*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool path::empty() const noexcept
2580*89c4ff92SAndroid Build Coastguard Worker {
2581*89c4ff92SAndroid Build Coastguard Worker return _path.empty();
2582*89c4ff92SAndroid Build Coastguard Worker }
2583*89c4ff92SAndroid Build Coastguard Worker
has_root_name() const2584*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool path::has_root_name() const
2585*89c4ff92SAndroid Build Coastguard Worker {
2586*89c4ff92SAndroid Build Coastguard Worker return !root_name().empty();
2587*89c4ff92SAndroid Build Coastguard Worker }
2588*89c4ff92SAndroid Build Coastguard Worker
has_root_directory() const2589*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool path::has_root_directory() const
2590*89c4ff92SAndroid Build Coastguard Worker {
2591*89c4ff92SAndroid Build Coastguard Worker return !root_directory().empty();
2592*89c4ff92SAndroid Build Coastguard Worker }
2593*89c4ff92SAndroid Build Coastguard Worker
has_root_path() const2594*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool path::has_root_path() const
2595*89c4ff92SAndroid Build Coastguard Worker {
2596*89c4ff92SAndroid Build Coastguard Worker return !root_path().empty();
2597*89c4ff92SAndroid Build Coastguard Worker }
2598*89c4ff92SAndroid Build Coastguard Worker
has_relative_path() const2599*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool path::has_relative_path() const
2600*89c4ff92SAndroid Build Coastguard Worker {
2601*89c4ff92SAndroid Build Coastguard Worker return !relative_path().empty();
2602*89c4ff92SAndroid Build Coastguard Worker }
2603*89c4ff92SAndroid Build Coastguard Worker
has_parent_path() const2604*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool path::has_parent_path() const
2605*89c4ff92SAndroid Build Coastguard Worker {
2606*89c4ff92SAndroid Build Coastguard Worker return !parent_path().empty();
2607*89c4ff92SAndroid Build Coastguard Worker }
2608*89c4ff92SAndroid Build Coastguard Worker
has_filename() const2609*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool path::has_filename() const
2610*89c4ff92SAndroid Build Coastguard Worker {
2611*89c4ff92SAndroid Build Coastguard Worker return !filename().empty();
2612*89c4ff92SAndroid Build Coastguard Worker }
2613*89c4ff92SAndroid Build Coastguard Worker
has_stem() const2614*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool path::has_stem() const
2615*89c4ff92SAndroid Build Coastguard Worker {
2616*89c4ff92SAndroid Build Coastguard Worker return !stem().empty();
2617*89c4ff92SAndroid Build Coastguard Worker }
2618*89c4ff92SAndroid Build Coastguard Worker
has_extension() const2619*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool path::has_extension() const
2620*89c4ff92SAndroid Build Coastguard Worker {
2621*89c4ff92SAndroid Build Coastguard Worker return !extension().empty();
2622*89c4ff92SAndroid Build Coastguard Worker }
2623*89c4ff92SAndroid Build Coastguard Worker
is_absolute() const2624*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool path::is_absolute() const
2625*89c4ff92SAndroid Build Coastguard Worker {
2626*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
2627*89c4ff92SAndroid Build Coastguard Worker return has_root_name() && has_root_directory();
2628*89c4ff92SAndroid Build Coastguard Worker #else
2629*89c4ff92SAndroid Build Coastguard Worker return has_root_directory();
2630*89c4ff92SAndroid Build Coastguard Worker #endif
2631*89c4ff92SAndroid Build Coastguard Worker }
2632*89c4ff92SAndroid Build Coastguard Worker
is_relative() const2633*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool path::is_relative() const
2634*89c4ff92SAndroid Build Coastguard Worker {
2635*89c4ff92SAndroid Build Coastguard Worker return !is_absolute();
2636*89c4ff92SAndroid Build Coastguard Worker }
2637*89c4ff92SAndroid Build Coastguard Worker
2638*89c4ff92SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2639*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.4.11, generation
lexically_normal() const2640*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path path::lexically_normal() const
2641*89c4ff92SAndroid Build Coastguard Worker {
2642*89c4ff92SAndroid Build Coastguard Worker path dest;
2643*89c4ff92SAndroid Build Coastguard Worker bool lastDotDot = false;
2644*89c4ff92SAndroid Build Coastguard Worker for (string_type s : *this) {
2645*89c4ff92SAndroid Build Coastguard Worker if (s == ".") {
2646*89c4ff92SAndroid Build Coastguard Worker dest /= "";
2647*89c4ff92SAndroid Build Coastguard Worker continue;
2648*89c4ff92SAndroid Build Coastguard Worker }
2649*89c4ff92SAndroid Build Coastguard Worker else if (s == ".." && !dest.empty()) {
2650*89c4ff92SAndroid Build Coastguard Worker auto root = root_path();
2651*89c4ff92SAndroid Build Coastguard Worker if (dest == root) {
2652*89c4ff92SAndroid Build Coastguard Worker continue;
2653*89c4ff92SAndroid Build Coastguard Worker }
2654*89c4ff92SAndroid Build Coastguard Worker else if (*(--dest.end()) != "..") {
2655*89c4ff92SAndroid Build Coastguard Worker if (dest._path.back() == generic_separator) {
2656*89c4ff92SAndroid Build Coastguard Worker dest._path.pop_back();
2657*89c4ff92SAndroid Build Coastguard Worker }
2658*89c4ff92SAndroid Build Coastguard Worker dest.remove_filename();
2659*89c4ff92SAndroid Build Coastguard Worker continue;
2660*89c4ff92SAndroid Build Coastguard Worker }
2661*89c4ff92SAndroid Build Coastguard Worker }
2662*89c4ff92SAndroid Build Coastguard Worker if (!(s.empty() && lastDotDot)) {
2663*89c4ff92SAndroid Build Coastguard Worker dest /= s;
2664*89c4ff92SAndroid Build Coastguard Worker }
2665*89c4ff92SAndroid Build Coastguard Worker lastDotDot = s == "..";
2666*89c4ff92SAndroid Build Coastguard Worker }
2667*89c4ff92SAndroid Build Coastguard Worker if (dest.empty()) {
2668*89c4ff92SAndroid Build Coastguard Worker dest = ".";
2669*89c4ff92SAndroid Build Coastguard Worker }
2670*89c4ff92SAndroid Build Coastguard Worker return dest;
2671*89c4ff92SAndroid Build Coastguard Worker }
2672*89c4ff92SAndroid Build Coastguard Worker
lexically_relative(const path & base) const2673*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path path::lexically_relative(const path& base) const
2674*89c4ff92SAndroid Build Coastguard Worker {
2675*89c4ff92SAndroid Build Coastguard Worker if (root_name() != base.root_name() || is_absolute() != base.is_absolute() || (!has_root_directory() && base.has_root_directory())) {
2676*89c4ff92SAndroid Build Coastguard Worker return path();
2677*89c4ff92SAndroid Build Coastguard Worker }
2678*89c4ff92SAndroid Build Coastguard Worker const_iterator a = begin(), b = base.begin();
2679*89c4ff92SAndroid Build Coastguard Worker while (a != end() && b != base.end() && *a == *b) {
2680*89c4ff92SAndroid Build Coastguard Worker ++a;
2681*89c4ff92SAndroid Build Coastguard Worker ++b;
2682*89c4ff92SAndroid Build Coastguard Worker }
2683*89c4ff92SAndroid Build Coastguard Worker if (a == end() && b == base.end()) {
2684*89c4ff92SAndroid Build Coastguard Worker return path(".");
2685*89c4ff92SAndroid Build Coastguard Worker }
2686*89c4ff92SAndroid Build Coastguard Worker int count = 0;
2687*89c4ff92SAndroid Build Coastguard Worker for (const auto& element : input_iterator_range<const_iterator>(b, base.end())) {
2688*89c4ff92SAndroid Build Coastguard Worker if (element != "." && element != "" && element != "..") {
2689*89c4ff92SAndroid Build Coastguard Worker ++count;
2690*89c4ff92SAndroid Build Coastguard Worker }
2691*89c4ff92SAndroid Build Coastguard Worker else if (element == "..") {
2692*89c4ff92SAndroid Build Coastguard Worker --count;
2693*89c4ff92SAndroid Build Coastguard Worker }
2694*89c4ff92SAndroid Build Coastguard Worker }
2695*89c4ff92SAndroid Build Coastguard Worker if (count < 0) {
2696*89c4ff92SAndroid Build Coastguard Worker return path();
2697*89c4ff92SAndroid Build Coastguard Worker }
2698*89c4ff92SAndroid Build Coastguard Worker path result;
2699*89c4ff92SAndroid Build Coastguard Worker for (int i = 0; i < count; ++i) {
2700*89c4ff92SAndroid Build Coastguard Worker result /= "..";
2701*89c4ff92SAndroid Build Coastguard Worker }
2702*89c4ff92SAndroid Build Coastguard Worker for (const auto& element : input_iterator_range<const_iterator>(a, end())) {
2703*89c4ff92SAndroid Build Coastguard Worker result /= element;
2704*89c4ff92SAndroid Build Coastguard Worker }
2705*89c4ff92SAndroid Build Coastguard Worker return result;
2706*89c4ff92SAndroid Build Coastguard Worker }
2707*89c4ff92SAndroid Build Coastguard Worker
lexically_proximate(const path & base) const2708*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path path::lexically_proximate(const path& base) const
2709*89c4ff92SAndroid Build Coastguard Worker {
2710*89c4ff92SAndroid Build Coastguard Worker path result = lexically_relative(base);
2711*89c4ff92SAndroid Build Coastguard Worker return result.empty() ? *this : result;
2712*89c4ff92SAndroid Build Coastguard Worker }
2713*89c4ff92SAndroid Build Coastguard Worker
2714*89c4ff92SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2715*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.5, iterators
iterator()2716*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path::iterator::iterator() {}
2717*89c4ff92SAndroid Build Coastguard Worker
iterator(const path::impl_string_type::const_iterator & first,const path::impl_string_type::const_iterator & last,const path::impl_string_type::const_iterator & pos)2718*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path::iterator::iterator(const path::impl_string_type::const_iterator& first, const path::impl_string_type::const_iterator& last, const path::impl_string_type::const_iterator& pos)
2719*89c4ff92SAndroid Build Coastguard Worker : _first(first)
2720*89c4ff92SAndroid Build Coastguard Worker , _last(last)
2721*89c4ff92SAndroid Build Coastguard Worker , _iter(pos)
2722*89c4ff92SAndroid Build Coastguard Worker {
2723*89c4ff92SAndroid Build Coastguard Worker updateCurrent();
2724*89c4ff92SAndroid Build Coastguard Worker // find the position of a potential root directory slash
2725*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
2726*89c4ff92SAndroid Build Coastguard Worker if (_last - _first >= 3 && std::toupper(static_cast<unsigned char>(*first)) >= 'A' && std::toupper(static_cast<unsigned char>(*first)) <= 'Z' && *(first + 1) == ':' && *(first + 2) == '/') {
2727*89c4ff92SAndroid Build Coastguard Worker _root = _first + 2;
2728*89c4ff92SAndroid Build Coastguard Worker }
2729*89c4ff92SAndroid Build Coastguard Worker else
2730*89c4ff92SAndroid Build Coastguard Worker #endif
2731*89c4ff92SAndroid Build Coastguard Worker {
2732*89c4ff92SAndroid Build Coastguard Worker if (_first != _last && *_first == '/') {
2733*89c4ff92SAndroid Build Coastguard Worker if (_last - _first >= 2 && *(_first + 1) == '/' && !(_last - _first >= 3 && *(_first + 2) == '/')) {
2734*89c4ff92SAndroid Build Coastguard Worker _root = increment(_first);
2735*89c4ff92SAndroid Build Coastguard Worker }
2736*89c4ff92SAndroid Build Coastguard Worker else {
2737*89c4ff92SAndroid Build Coastguard Worker _root = _first;
2738*89c4ff92SAndroid Build Coastguard Worker }
2739*89c4ff92SAndroid Build Coastguard Worker }
2740*89c4ff92SAndroid Build Coastguard Worker else {
2741*89c4ff92SAndroid Build Coastguard Worker _root = _last;
2742*89c4ff92SAndroid Build Coastguard Worker }
2743*89c4ff92SAndroid Build Coastguard Worker }
2744*89c4ff92SAndroid Build Coastguard Worker }
2745*89c4ff92SAndroid Build Coastguard Worker
increment(const path::impl_string_type::const_iterator & pos) const2746*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path::impl_string_type::const_iterator path::iterator::increment(const path::impl_string_type::const_iterator& pos) const
2747*89c4ff92SAndroid Build Coastguard Worker {
2748*89c4ff92SAndroid Build Coastguard Worker path::impl_string_type::const_iterator i = pos;
2749*89c4ff92SAndroid Build Coastguard Worker bool fromStart = i == _first;
2750*89c4ff92SAndroid Build Coastguard Worker if (i != _last) {
2751*89c4ff92SAndroid Build Coastguard Worker // we can only sit on a slash if it is a network name or a root
2752*89c4ff92SAndroid Build Coastguard Worker if (*i++ == '/') {
2753*89c4ff92SAndroid Build Coastguard Worker if (i != _last && *i == '/') {
2754*89c4ff92SAndroid Build Coastguard Worker if (fromStart && !(i + 1 != _last && *(i + 1) == '/')) {
2755*89c4ff92SAndroid Build Coastguard Worker // leadind double slashes detected, treat this and the
2756*89c4ff92SAndroid Build Coastguard Worker // following until a slash as one unit
2757*89c4ff92SAndroid Build Coastguard Worker i = std::find(++i, _last, '/');
2758*89c4ff92SAndroid Build Coastguard Worker }
2759*89c4ff92SAndroid Build Coastguard Worker else {
2760*89c4ff92SAndroid Build Coastguard Worker // skip redundant slashes
2761*89c4ff92SAndroid Build Coastguard Worker while (i != _last && *i == '/') {
2762*89c4ff92SAndroid Build Coastguard Worker ++i;
2763*89c4ff92SAndroid Build Coastguard Worker }
2764*89c4ff92SAndroid Build Coastguard Worker }
2765*89c4ff92SAndroid Build Coastguard Worker }
2766*89c4ff92SAndroid Build Coastguard Worker }
2767*89c4ff92SAndroid Build Coastguard Worker else {
2768*89c4ff92SAndroid Build Coastguard Worker if (fromStart && i != _last && *i == ':') {
2769*89c4ff92SAndroid Build Coastguard Worker ++i;
2770*89c4ff92SAndroid Build Coastguard Worker }
2771*89c4ff92SAndroid Build Coastguard Worker else {
2772*89c4ff92SAndroid Build Coastguard Worker i = std::find(i, _last, '/');
2773*89c4ff92SAndroid Build Coastguard Worker }
2774*89c4ff92SAndroid Build Coastguard Worker }
2775*89c4ff92SAndroid Build Coastguard Worker }
2776*89c4ff92SAndroid Build Coastguard Worker return i;
2777*89c4ff92SAndroid Build Coastguard Worker }
2778*89c4ff92SAndroid Build Coastguard Worker
decrement(const path::impl_string_type::const_iterator & pos) const2779*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path::impl_string_type::const_iterator path::iterator::decrement(const path::impl_string_type::const_iterator& pos) const
2780*89c4ff92SAndroid Build Coastguard Worker {
2781*89c4ff92SAndroid Build Coastguard Worker path::impl_string_type::const_iterator i = pos;
2782*89c4ff92SAndroid Build Coastguard Worker if (i != _first) {
2783*89c4ff92SAndroid Build Coastguard Worker --i;
2784*89c4ff92SAndroid Build Coastguard Worker // if this is now the root slash or the trailing slash, we are done,
2785*89c4ff92SAndroid Build Coastguard Worker // else check for network name
2786*89c4ff92SAndroid Build Coastguard Worker if (i != _root && (pos != _last || *i != '/')) {
2787*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
2788*89c4ff92SAndroid Build Coastguard Worker static const std::string seps = "/:";
2789*89c4ff92SAndroid Build Coastguard Worker i = std::find_first_of(std::reverse_iterator<path::impl_string_type::const_iterator>(i), std::reverse_iterator<path::impl_string_type::const_iterator>(_first), seps.begin(), seps.end()).base();
2790*89c4ff92SAndroid Build Coastguard Worker if (i > _first && *i == ':') {
2791*89c4ff92SAndroid Build Coastguard Worker i++;
2792*89c4ff92SAndroid Build Coastguard Worker }
2793*89c4ff92SAndroid Build Coastguard Worker #else
2794*89c4ff92SAndroid Build Coastguard Worker i = std::find(std::reverse_iterator<path::impl_string_type::const_iterator>(i), std::reverse_iterator<path::impl_string_type::const_iterator>(_first), '/').base();
2795*89c4ff92SAndroid Build Coastguard Worker #endif
2796*89c4ff92SAndroid Build Coastguard Worker // Now we have to check if this is a network name
2797*89c4ff92SAndroid Build Coastguard Worker if (i - _first == 2 && *_first == '/' && *(_first + 1) == '/') {
2798*89c4ff92SAndroid Build Coastguard Worker i -= 2;
2799*89c4ff92SAndroid Build Coastguard Worker }
2800*89c4ff92SAndroid Build Coastguard Worker }
2801*89c4ff92SAndroid Build Coastguard Worker }
2802*89c4ff92SAndroid Build Coastguard Worker return i;
2803*89c4ff92SAndroid Build Coastguard Worker }
2804*89c4ff92SAndroid Build Coastguard Worker
updateCurrent()2805*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void path::iterator::updateCurrent()
2806*89c4ff92SAndroid Build Coastguard Worker {
2807*89c4ff92SAndroid Build Coastguard Worker if (_iter != _first && _iter != _last && (*_iter == '/' && _iter != _root) && (_iter + 1 == _last)) {
2808*89c4ff92SAndroid Build Coastguard Worker _current = "";
2809*89c4ff92SAndroid Build Coastguard Worker }
2810*89c4ff92SAndroid Build Coastguard Worker else {
2811*89c4ff92SAndroid Build Coastguard Worker _current.assign(_iter, increment(_iter));
2812*89c4ff92SAndroid Build Coastguard Worker if (_current.generic_string().size() > 1 && _current.generic_string()[0] == '/' && _current.generic_string()[_current.generic_string().size() - 1] == '/') {
2813*89c4ff92SAndroid Build Coastguard Worker // shrink successive slashes to one
2814*89c4ff92SAndroid Build Coastguard Worker _current = "/";
2815*89c4ff92SAndroid Build Coastguard Worker }
2816*89c4ff92SAndroid Build Coastguard Worker }
2817*89c4ff92SAndroid Build Coastguard Worker }
2818*89c4ff92SAndroid Build Coastguard Worker
operator ++()2819*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path::iterator& path::iterator::operator++()
2820*89c4ff92SAndroid Build Coastguard Worker {
2821*89c4ff92SAndroid Build Coastguard Worker _iter = increment(_iter);
2822*89c4ff92SAndroid Build Coastguard Worker while (_iter != _last && // we didn't reach the end
2823*89c4ff92SAndroid Build Coastguard Worker _iter != _root && // this is not a root position
2824*89c4ff92SAndroid Build Coastguard Worker *_iter == '/' && // we are on a slash
2825*89c4ff92SAndroid Build Coastguard Worker (_iter + 1) != _last // the slash is not the last char
2826*89c4ff92SAndroid Build Coastguard Worker ) {
2827*89c4ff92SAndroid Build Coastguard Worker ++_iter;
2828*89c4ff92SAndroid Build Coastguard Worker }
2829*89c4ff92SAndroid Build Coastguard Worker updateCurrent();
2830*89c4ff92SAndroid Build Coastguard Worker return *this;
2831*89c4ff92SAndroid Build Coastguard Worker }
2832*89c4ff92SAndroid Build Coastguard Worker
operator ++(int)2833*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path::iterator path::iterator::operator++(int)
2834*89c4ff92SAndroid Build Coastguard Worker {
2835*89c4ff92SAndroid Build Coastguard Worker path::iterator i{*this};
2836*89c4ff92SAndroid Build Coastguard Worker ++(*this);
2837*89c4ff92SAndroid Build Coastguard Worker return i;
2838*89c4ff92SAndroid Build Coastguard Worker }
2839*89c4ff92SAndroid Build Coastguard Worker
operator --()2840*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path::iterator& path::iterator::operator--()
2841*89c4ff92SAndroid Build Coastguard Worker {
2842*89c4ff92SAndroid Build Coastguard Worker _iter = decrement(_iter);
2843*89c4ff92SAndroid Build Coastguard Worker updateCurrent();
2844*89c4ff92SAndroid Build Coastguard Worker return *this;
2845*89c4ff92SAndroid Build Coastguard Worker }
2846*89c4ff92SAndroid Build Coastguard Worker
operator --(int)2847*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path::iterator path::iterator::operator--(int)
2848*89c4ff92SAndroid Build Coastguard Worker {
2849*89c4ff92SAndroid Build Coastguard Worker auto i = *this;
2850*89c4ff92SAndroid Build Coastguard Worker --(*this);
2851*89c4ff92SAndroid Build Coastguard Worker return i;
2852*89c4ff92SAndroid Build Coastguard Worker }
2853*89c4ff92SAndroid Build Coastguard Worker
operator ==(const path::iterator & other) const2854*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool path::iterator::operator==(const path::iterator& other) const
2855*89c4ff92SAndroid Build Coastguard Worker {
2856*89c4ff92SAndroid Build Coastguard Worker return _iter == other._iter;
2857*89c4ff92SAndroid Build Coastguard Worker }
2858*89c4ff92SAndroid Build Coastguard Worker
operator !=(const path::iterator & other) const2859*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool path::iterator::operator!=(const path::iterator& other) const
2860*89c4ff92SAndroid Build Coastguard Worker {
2861*89c4ff92SAndroid Build Coastguard Worker return _iter != other._iter;
2862*89c4ff92SAndroid Build Coastguard Worker }
2863*89c4ff92SAndroid Build Coastguard Worker
operator *() const2864*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path::iterator::reference path::iterator::operator*() const
2865*89c4ff92SAndroid Build Coastguard Worker {
2866*89c4ff92SAndroid Build Coastguard Worker return _current;
2867*89c4ff92SAndroid Build Coastguard Worker }
2868*89c4ff92SAndroid Build Coastguard Worker
operator ->() const2869*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path::iterator::pointer path::iterator::operator->() const
2870*89c4ff92SAndroid Build Coastguard Worker {
2871*89c4ff92SAndroid Build Coastguard Worker return &_current;
2872*89c4ff92SAndroid Build Coastguard Worker }
2873*89c4ff92SAndroid Build Coastguard Worker
begin() const2874*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path::iterator path::begin() const
2875*89c4ff92SAndroid Build Coastguard Worker {
2876*89c4ff92SAndroid Build Coastguard Worker return iterator(_path.begin(), _path.end(), _path.begin());
2877*89c4ff92SAndroid Build Coastguard Worker }
2878*89c4ff92SAndroid Build Coastguard Worker
end() const2879*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path::iterator path::end() const
2880*89c4ff92SAndroid Build Coastguard Worker {
2881*89c4ff92SAndroid Build Coastguard Worker return iterator(_path.begin(), _path.end(), _path.end());
2882*89c4ff92SAndroid Build Coastguard Worker }
2883*89c4ff92SAndroid Build Coastguard Worker
2884*89c4ff92SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2885*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.6, path non-member functions
swap(path & lhs,path & rhs)2886*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void swap(path& lhs, path& rhs) noexcept
2887*89c4ff92SAndroid Build Coastguard Worker {
2888*89c4ff92SAndroid Build Coastguard Worker swap(lhs._path, rhs._path);
2889*89c4ff92SAndroid Build Coastguard Worker }
2890*89c4ff92SAndroid Build Coastguard Worker
hash_value(const path & p)2891*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE size_t hash_value(const path& p) noexcept
2892*89c4ff92SAndroid Build Coastguard Worker {
2893*89c4ff92SAndroid Build Coastguard Worker return std::hash<std::string>()(p.generic_string());
2894*89c4ff92SAndroid Build Coastguard Worker }
2895*89c4ff92SAndroid Build Coastguard Worker
operator ==(const path & lhs,const path & rhs)2896*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool operator==(const path& lhs, const path& rhs) noexcept
2897*89c4ff92SAndroid Build Coastguard Worker {
2898*89c4ff92SAndroid Build Coastguard Worker return lhs.generic_string() == rhs.generic_string();
2899*89c4ff92SAndroid Build Coastguard Worker }
2900*89c4ff92SAndroid Build Coastguard Worker
operator !=(const path & lhs,const path & rhs)2901*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool operator!=(const path& lhs, const path& rhs) noexcept
2902*89c4ff92SAndroid Build Coastguard Worker {
2903*89c4ff92SAndroid Build Coastguard Worker return lhs.generic_string() != rhs.generic_string();
2904*89c4ff92SAndroid Build Coastguard Worker }
2905*89c4ff92SAndroid Build Coastguard Worker
operator <(const path & lhs,const path & rhs)2906*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool operator<(const path& lhs, const path& rhs) noexcept
2907*89c4ff92SAndroid Build Coastguard Worker {
2908*89c4ff92SAndroid Build Coastguard Worker return lhs.generic_string() < rhs.generic_string();
2909*89c4ff92SAndroid Build Coastguard Worker }
2910*89c4ff92SAndroid Build Coastguard Worker
operator <=(const path & lhs,const path & rhs)2911*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool operator<=(const path& lhs, const path& rhs) noexcept
2912*89c4ff92SAndroid Build Coastguard Worker {
2913*89c4ff92SAndroid Build Coastguard Worker return lhs.generic_string() <= rhs.generic_string();
2914*89c4ff92SAndroid Build Coastguard Worker }
2915*89c4ff92SAndroid Build Coastguard Worker
operator >(const path & lhs,const path & rhs)2916*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool operator>(const path& lhs, const path& rhs) noexcept
2917*89c4ff92SAndroid Build Coastguard Worker {
2918*89c4ff92SAndroid Build Coastguard Worker return lhs.generic_string() > rhs.generic_string();
2919*89c4ff92SAndroid Build Coastguard Worker }
2920*89c4ff92SAndroid Build Coastguard Worker
operator >=(const path & lhs,const path & rhs)2921*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool operator>=(const path& lhs, const path& rhs) noexcept
2922*89c4ff92SAndroid Build Coastguard Worker {
2923*89c4ff92SAndroid Build Coastguard Worker return lhs.generic_string() >= rhs.generic_string();
2924*89c4ff92SAndroid Build Coastguard Worker }
2925*89c4ff92SAndroid Build Coastguard Worker
operator /(const path & lhs,const path & rhs)2926*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path operator/(const path& lhs, const path& rhs)
2927*89c4ff92SAndroid Build Coastguard Worker {
2928*89c4ff92SAndroid Build Coastguard Worker path result(lhs);
2929*89c4ff92SAndroid Build Coastguard Worker result /= rhs;
2930*89c4ff92SAndroid Build Coastguard Worker return result;
2931*89c4ff92SAndroid Build Coastguard Worker }
2932*89c4ff92SAndroid Build Coastguard Worker
2933*89c4ff92SAndroid Build Coastguard Worker #endif // GHC_EXPAND_IMPL
2934*89c4ff92SAndroid Build Coastguard Worker
2935*89c4ff92SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2936*89c4ff92SAndroid Build Coastguard Worker // 30.10.8.6.1 path inserter and extractor
2937*89c4ff92SAndroid Build Coastguard Worker template <class charT, class traits>
operator <<(std::basic_ostream<charT,traits> & os,const path & p)2938*89c4ff92SAndroid Build Coastguard Worker inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const path& p)
2939*89c4ff92SAndroid Build Coastguard Worker {
2940*89c4ff92SAndroid Build Coastguard Worker os << "\"";
2941*89c4ff92SAndroid Build Coastguard Worker auto ps = p.string<charT, traits>();
2942*89c4ff92SAndroid Build Coastguard Worker for (auto c : ps) {
2943*89c4ff92SAndroid Build Coastguard Worker if (c == '"' || c == '\\') {
2944*89c4ff92SAndroid Build Coastguard Worker os << '\\';
2945*89c4ff92SAndroid Build Coastguard Worker }
2946*89c4ff92SAndroid Build Coastguard Worker os << c;
2947*89c4ff92SAndroid Build Coastguard Worker }
2948*89c4ff92SAndroid Build Coastguard Worker os << "\"";
2949*89c4ff92SAndroid Build Coastguard Worker return os;
2950*89c4ff92SAndroid Build Coastguard Worker }
2951*89c4ff92SAndroid Build Coastguard Worker
2952*89c4ff92SAndroid Build Coastguard Worker template <class charT, class traits>
operator >>(std::basic_istream<charT,traits> & is,path & p)2953*89c4ff92SAndroid Build Coastguard Worker inline std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>& is, path& p)
2954*89c4ff92SAndroid Build Coastguard Worker {
2955*89c4ff92SAndroid Build Coastguard Worker std::basic_string<charT, traits> tmp;
2956*89c4ff92SAndroid Build Coastguard Worker charT c;
2957*89c4ff92SAndroid Build Coastguard Worker is >> c;
2958*89c4ff92SAndroid Build Coastguard Worker if (c == '"') {
2959*89c4ff92SAndroid Build Coastguard Worker auto sf = is.flags();
2960*89c4ff92SAndroid Build Coastguard Worker is >> std::noskipws;
2961*89c4ff92SAndroid Build Coastguard Worker while (is) {
2962*89c4ff92SAndroid Build Coastguard Worker auto c2 = is.get();
2963*89c4ff92SAndroid Build Coastguard Worker if (is) {
2964*89c4ff92SAndroid Build Coastguard Worker if (c2 == '\\') {
2965*89c4ff92SAndroid Build Coastguard Worker c2 = is.get();
2966*89c4ff92SAndroid Build Coastguard Worker if (is) {
2967*89c4ff92SAndroid Build Coastguard Worker tmp += static_cast<charT>(c2);
2968*89c4ff92SAndroid Build Coastguard Worker }
2969*89c4ff92SAndroid Build Coastguard Worker }
2970*89c4ff92SAndroid Build Coastguard Worker else if (c2 == '"') {
2971*89c4ff92SAndroid Build Coastguard Worker break;
2972*89c4ff92SAndroid Build Coastguard Worker }
2973*89c4ff92SAndroid Build Coastguard Worker else {
2974*89c4ff92SAndroid Build Coastguard Worker tmp += static_cast<charT>(c2);
2975*89c4ff92SAndroid Build Coastguard Worker }
2976*89c4ff92SAndroid Build Coastguard Worker }
2977*89c4ff92SAndroid Build Coastguard Worker }
2978*89c4ff92SAndroid Build Coastguard Worker if ((sf & std::ios_base::skipws) == std::ios_base::skipws) {
2979*89c4ff92SAndroid Build Coastguard Worker is >> std::skipws;
2980*89c4ff92SAndroid Build Coastguard Worker }
2981*89c4ff92SAndroid Build Coastguard Worker p = path(tmp);
2982*89c4ff92SAndroid Build Coastguard Worker }
2983*89c4ff92SAndroid Build Coastguard Worker else {
2984*89c4ff92SAndroid Build Coastguard Worker is >> tmp;
2985*89c4ff92SAndroid Build Coastguard Worker p = path(static_cast<charT>(c) + tmp);
2986*89c4ff92SAndroid Build Coastguard Worker }
2987*89c4ff92SAndroid Build Coastguard Worker return is;
2988*89c4ff92SAndroid Build Coastguard Worker }
2989*89c4ff92SAndroid Build Coastguard Worker
2990*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_EXPAND_IMPL
2991*89c4ff92SAndroid Build Coastguard Worker
2992*89c4ff92SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2993*89c4ff92SAndroid Build Coastguard Worker // 30.10.9 Class filesystem_error
filesystem_error(const std::string & what_arg,std::error_code ec)2994*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE filesystem_error::filesystem_error(const std::string& what_arg, std::error_code ec)
2995*89c4ff92SAndroid Build Coastguard Worker : std::system_error(ec, what_arg)
2996*89c4ff92SAndroid Build Coastguard Worker , _what_arg(what_arg)
2997*89c4ff92SAndroid Build Coastguard Worker , _ec(ec)
2998*89c4ff92SAndroid Build Coastguard Worker {
2999*89c4ff92SAndroid Build Coastguard Worker }
3000*89c4ff92SAndroid Build Coastguard Worker
filesystem_error(const std::string & what_arg,const path & p1,std::error_code ec)3001*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE filesystem_error::filesystem_error(const std::string& what_arg, const path& p1, std::error_code ec)
3002*89c4ff92SAndroid Build Coastguard Worker : std::system_error(ec, what_arg)
3003*89c4ff92SAndroid Build Coastguard Worker , _what_arg(what_arg)
3004*89c4ff92SAndroid Build Coastguard Worker , _ec(ec)
3005*89c4ff92SAndroid Build Coastguard Worker , _p1(p1)
3006*89c4ff92SAndroid Build Coastguard Worker {
3007*89c4ff92SAndroid Build Coastguard Worker if (!_p1.empty()) {
3008*89c4ff92SAndroid Build Coastguard Worker _what_arg += ": '" + _p1.u8string() + "'";
3009*89c4ff92SAndroid Build Coastguard Worker }
3010*89c4ff92SAndroid Build Coastguard Worker }
3011*89c4ff92SAndroid Build Coastguard Worker
filesystem_error(const std::string & what_arg,const path & p1,const path & p2,std::error_code ec)3012*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE filesystem_error::filesystem_error(const std::string& what_arg, const path& p1, const path& p2, std::error_code ec)
3013*89c4ff92SAndroid Build Coastguard Worker : std::system_error(ec, what_arg)
3014*89c4ff92SAndroid Build Coastguard Worker , _what_arg(what_arg)
3015*89c4ff92SAndroid Build Coastguard Worker , _ec(ec)
3016*89c4ff92SAndroid Build Coastguard Worker , _p1(p1)
3017*89c4ff92SAndroid Build Coastguard Worker , _p2(p2)
3018*89c4ff92SAndroid Build Coastguard Worker {
3019*89c4ff92SAndroid Build Coastguard Worker if (!_p1.empty()) {
3020*89c4ff92SAndroid Build Coastguard Worker _what_arg += ": '" + _p1.u8string() + "'";
3021*89c4ff92SAndroid Build Coastguard Worker }
3022*89c4ff92SAndroid Build Coastguard Worker if (!_p2.empty()) {
3023*89c4ff92SAndroid Build Coastguard Worker _what_arg += ", '" + _p2.u8string() + "'";
3024*89c4ff92SAndroid Build Coastguard Worker }
3025*89c4ff92SAndroid Build Coastguard Worker }
3026*89c4ff92SAndroid Build Coastguard Worker
path1() const3027*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE const path& filesystem_error::path1() const noexcept
3028*89c4ff92SAndroid Build Coastguard Worker {
3029*89c4ff92SAndroid Build Coastguard Worker return _p1;
3030*89c4ff92SAndroid Build Coastguard Worker }
3031*89c4ff92SAndroid Build Coastguard Worker
path2() const3032*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE const path& filesystem_error::path2() const noexcept
3033*89c4ff92SAndroid Build Coastguard Worker {
3034*89c4ff92SAndroid Build Coastguard Worker return _p2;
3035*89c4ff92SAndroid Build Coastguard Worker }
3036*89c4ff92SAndroid Build Coastguard Worker
what() const3037*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE const char* filesystem_error::what() const noexcept
3038*89c4ff92SAndroid Build Coastguard Worker {
3039*89c4ff92SAndroid Build Coastguard Worker return _what_arg.c_str();
3040*89c4ff92SAndroid Build Coastguard Worker }
3041*89c4ff92SAndroid Build Coastguard Worker
3042*89c4ff92SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
3043*89c4ff92SAndroid Build Coastguard Worker // 30.10.15, filesystem operations
absolute(const path & p)3044*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path absolute(const path& p)
3045*89c4ff92SAndroid Build Coastguard Worker {
3046*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
3047*89c4ff92SAndroid Build Coastguard Worker path result = absolute(p, ec);
3048*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3049*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3050*89c4ff92SAndroid Build Coastguard Worker }
3051*89c4ff92SAndroid Build Coastguard Worker return result;
3052*89c4ff92SAndroid Build Coastguard Worker }
3053*89c4ff92SAndroid Build Coastguard Worker
absolute(const path & p,std::error_code & ec)3054*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path absolute(const path& p, std::error_code& ec)
3055*89c4ff92SAndroid Build Coastguard Worker {
3056*89c4ff92SAndroid Build Coastguard Worker ec.clear();
3057*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
3058*89c4ff92SAndroid Build Coastguard Worker if (p.empty()) {
3059*89c4ff92SAndroid Build Coastguard Worker return absolute(current_path(ec), ec) / "";
3060*89c4ff92SAndroid Build Coastguard Worker }
3061*89c4ff92SAndroid Build Coastguard Worker ULONG size = ::GetFullPathNameW(p.wstring().c_str(), 0, 0, 0);
3062*89c4ff92SAndroid Build Coastguard Worker if (size) {
3063*89c4ff92SAndroid Build Coastguard Worker std::vector<wchar_t> buf(size, 0);
3064*89c4ff92SAndroid Build Coastguard Worker ULONG s2 = GetFullPathNameW(p.wstring().c_str(), size, buf.data(), nullptr);
3065*89c4ff92SAndroid Build Coastguard Worker if (s2 && s2 < size) {
3066*89c4ff92SAndroid Build Coastguard Worker path result = path(std::wstring(buf.data(), s2));
3067*89c4ff92SAndroid Build Coastguard Worker if (p.filename() == ".") {
3068*89c4ff92SAndroid Build Coastguard Worker result /= ".";
3069*89c4ff92SAndroid Build Coastguard Worker }
3070*89c4ff92SAndroid Build Coastguard Worker return result;
3071*89c4ff92SAndroid Build Coastguard Worker }
3072*89c4ff92SAndroid Build Coastguard Worker }
3073*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3074*89c4ff92SAndroid Build Coastguard Worker return path();
3075*89c4ff92SAndroid Build Coastguard Worker #else
3076*89c4ff92SAndroid Build Coastguard Worker path base = current_path(ec);
3077*89c4ff92SAndroid Build Coastguard Worker if (!ec) {
3078*89c4ff92SAndroid Build Coastguard Worker if (p.empty()) {
3079*89c4ff92SAndroid Build Coastguard Worker return base / p;
3080*89c4ff92SAndroid Build Coastguard Worker }
3081*89c4ff92SAndroid Build Coastguard Worker if (p.has_root_name()) {
3082*89c4ff92SAndroid Build Coastguard Worker if (p.has_root_directory()) {
3083*89c4ff92SAndroid Build Coastguard Worker return p;
3084*89c4ff92SAndroid Build Coastguard Worker }
3085*89c4ff92SAndroid Build Coastguard Worker else {
3086*89c4ff92SAndroid Build Coastguard Worker return p.root_name() / base.root_directory() / base.relative_path() / p.relative_path();
3087*89c4ff92SAndroid Build Coastguard Worker }
3088*89c4ff92SAndroid Build Coastguard Worker }
3089*89c4ff92SAndroid Build Coastguard Worker else {
3090*89c4ff92SAndroid Build Coastguard Worker if (p.has_root_directory()) {
3091*89c4ff92SAndroid Build Coastguard Worker return base.root_name() / p;
3092*89c4ff92SAndroid Build Coastguard Worker }
3093*89c4ff92SAndroid Build Coastguard Worker else {
3094*89c4ff92SAndroid Build Coastguard Worker return base / p;
3095*89c4ff92SAndroid Build Coastguard Worker }
3096*89c4ff92SAndroid Build Coastguard Worker }
3097*89c4ff92SAndroid Build Coastguard Worker }
3098*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3099*89c4ff92SAndroid Build Coastguard Worker return path();
3100*89c4ff92SAndroid Build Coastguard Worker #endif
3101*89c4ff92SAndroid Build Coastguard Worker }
3102*89c4ff92SAndroid Build Coastguard Worker
canonical(const path & p)3103*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path canonical(const path& p)
3104*89c4ff92SAndroid Build Coastguard Worker {
3105*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
3106*89c4ff92SAndroid Build Coastguard Worker auto result = canonical(p, ec);
3107*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3108*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3109*89c4ff92SAndroid Build Coastguard Worker }
3110*89c4ff92SAndroid Build Coastguard Worker return result;
3111*89c4ff92SAndroid Build Coastguard Worker }
3112*89c4ff92SAndroid Build Coastguard Worker
canonical(const path & p,std::error_code & ec)3113*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path canonical(const path& p, std::error_code& ec)
3114*89c4ff92SAndroid Build Coastguard Worker {
3115*89c4ff92SAndroid Build Coastguard Worker if (p.empty()) {
3116*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_error_code(detail::portable_error::not_found);
3117*89c4ff92SAndroid Build Coastguard Worker return path();
3118*89c4ff92SAndroid Build Coastguard Worker }
3119*89c4ff92SAndroid Build Coastguard Worker path work = p.is_absolute() ? p : absolute(p, ec);
3120*89c4ff92SAndroid Build Coastguard Worker path root = work.root_path();
3121*89c4ff92SAndroid Build Coastguard Worker path result;
3122*89c4ff92SAndroid Build Coastguard Worker
3123*89c4ff92SAndroid Build Coastguard Worker auto fs = status(work, ec);
3124*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3125*89c4ff92SAndroid Build Coastguard Worker return path();
3126*89c4ff92SAndroid Build Coastguard Worker }
3127*89c4ff92SAndroid Build Coastguard Worker if (fs.type() == file_type::not_found) {
3128*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_error_code(detail::portable_error::not_found);
3129*89c4ff92SAndroid Build Coastguard Worker return path();
3130*89c4ff92SAndroid Build Coastguard Worker }
3131*89c4ff92SAndroid Build Coastguard Worker bool redo;
3132*89c4ff92SAndroid Build Coastguard Worker do {
3133*89c4ff92SAndroid Build Coastguard Worker redo = false;
3134*89c4ff92SAndroid Build Coastguard Worker result.clear();
3135*89c4ff92SAndroid Build Coastguard Worker for (auto pe : work) {
3136*89c4ff92SAndroid Build Coastguard Worker if (pe.empty() || pe == ".") {
3137*89c4ff92SAndroid Build Coastguard Worker continue;
3138*89c4ff92SAndroid Build Coastguard Worker }
3139*89c4ff92SAndroid Build Coastguard Worker else if (pe == "..") {
3140*89c4ff92SAndroid Build Coastguard Worker result = result.parent_path();
3141*89c4ff92SAndroid Build Coastguard Worker continue;
3142*89c4ff92SAndroid Build Coastguard Worker }
3143*89c4ff92SAndroid Build Coastguard Worker else if ((result / pe).string().length() <= root.string().length()) {
3144*89c4ff92SAndroid Build Coastguard Worker result /= pe;
3145*89c4ff92SAndroid Build Coastguard Worker continue;
3146*89c4ff92SAndroid Build Coastguard Worker }
3147*89c4ff92SAndroid Build Coastguard Worker auto sls = symlink_status(result / pe, ec);
3148*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3149*89c4ff92SAndroid Build Coastguard Worker return path();
3150*89c4ff92SAndroid Build Coastguard Worker }
3151*89c4ff92SAndroid Build Coastguard Worker if (is_symlink(sls)) {
3152*89c4ff92SAndroid Build Coastguard Worker redo = true;
3153*89c4ff92SAndroid Build Coastguard Worker auto target = read_symlink(result / pe, ec);
3154*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3155*89c4ff92SAndroid Build Coastguard Worker return path();
3156*89c4ff92SAndroid Build Coastguard Worker }
3157*89c4ff92SAndroid Build Coastguard Worker if (target.is_absolute()) {
3158*89c4ff92SAndroid Build Coastguard Worker result = target;
3159*89c4ff92SAndroid Build Coastguard Worker continue;
3160*89c4ff92SAndroid Build Coastguard Worker }
3161*89c4ff92SAndroid Build Coastguard Worker else {
3162*89c4ff92SAndroid Build Coastguard Worker result /= target;
3163*89c4ff92SAndroid Build Coastguard Worker continue;
3164*89c4ff92SAndroid Build Coastguard Worker }
3165*89c4ff92SAndroid Build Coastguard Worker }
3166*89c4ff92SAndroid Build Coastguard Worker else {
3167*89c4ff92SAndroid Build Coastguard Worker result /= pe;
3168*89c4ff92SAndroid Build Coastguard Worker }
3169*89c4ff92SAndroid Build Coastguard Worker }
3170*89c4ff92SAndroid Build Coastguard Worker work = result;
3171*89c4ff92SAndroid Build Coastguard Worker } while (redo);
3172*89c4ff92SAndroid Build Coastguard Worker ec.clear();
3173*89c4ff92SAndroid Build Coastguard Worker return result;
3174*89c4ff92SAndroid Build Coastguard Worker }
3175*89c4ff92SAndroid Build Coastguard Worker
copy(const path & from,const path & to)3176*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void copy(const path& from, const path& to)
3177*89c4ff92SAndroid Build Coastguard Worker {
3178*89c4ff92SAndroid Build Coastguard Worker copy(from, to, copy_options::none);
3179*89c4ff92SAndroid Build Coastguard Worker }
3180*89c4ff92SAndroid Build Coastguard Worker
copy(const path & from,const path & to,std::error_code & ec)3181*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void copy(const path& from, const path& to, std::error_code& ec) noexcept
3182*89c4ff92SAndroid Build Coastguard Worker {
3183*89c4ff92SAndroid Build Coastguard Worker copy(from, to, copy_options::none, ec);
3184*89c4ff92SAndroid Build Coastguard Worker }
3185*89c4ff92SAndroid Build Coastguard Worker
copy(const path & from,const path & to,copy_options options)3186*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void copy(const path& from, const path& to, copy_options options)
3187*89c4ff92SAndroid Build Coastguard Worker {
3188*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
3189*89c4ff92SAndroid Build Coastguard Worker copy(from, to, options, ec);
3190*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3191*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), from, to, ec);
3192*89c4ff92SAndroid Build Coastguard Worker }
3193*89c4ff92SAndroid Build Coastguard Worker }
3194*89c4ff92SAndroid Build Coastguard Worker
copy(const path & from,const path & to,copy_options options,std::error_code & ec)3195*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void copy(const path& from, const path& to, copy_options options, std::error_code& ec) noexcept
3196*89c4ff92SAndroid Build Coastguard Worker {
3197*89c4ff92SAndroid Build Coastguard Worker std::error_code tec;
3198*89c4ff92SAndroid Build Coastguard Worker file_status fs_from, fs_to;
3199*89c4ff92SAndroid Build Coastguard Worker ec.clear();
3200*89c4ff92SAndroid Build Coastguard Worker if ((options & (copy_options::skip_symlinks | copy_options::copy_symlinks | copy_options::create_symlinks)) != copy_options::none) {
3201*89c4ff92SAndroid Build Coastguard Worker fs_from = symlink_status(from, ec);
3202*89c4ff92SAndroid Build Coastguard Worker }
3203*89c4ff92SAndroid Build Coastguard Worker else {
3204*89c4ff92SAndroid Build Coastguard Worker fs_from = status(from, ec);
3205*89c4ff92SAndroid Build Coastguard Worker }
3206*89c4ff92SAndroid Build Coastguard Worker if (!exists(fs_from)) {
3207*89c4ff92SAndroid Build Coastguard Worker if (!ec) {
3208*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_error_code(detail::portable_error::not_found);
3209*89c4ff92SAndroid Build Coastguard Worker }
3210*89c4ff92SAndroid Build Coastguard Worker return;
3211*89c4ff92SAndroid Build Coastguard Worker }
3212*89c4ff92SAndroid Build Coastguard Worker if ((options & (copy_options::skip_symlinks | copy_options::create_symlinks)) != copy_options::none) {
3213*89c4ff92SAndroid Build Coastguard Worker fs_to = symlink_status(to, tec);
3214*89c4ff92SAndroid Build Coastguard Worker }
3215*89c4ff92SAndroid Build Coastguard Worker else {
3216*89c4ff92SAndroid Build Coastguard Worker fs_to = status(to, tec);
3217*89c4ff92SAndroid Build Coastguard Worker }
3218*89c4ff92SAndroid Build Coastguard Worker if (is_other(fs_from) || is_other(fs_to) || (is_directory(fs_from) && is_regular_file(fs_to)) || (exists(fs_to) && equivalent(from, to, ec))) {
3219*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_error_code(detail::portable_error::invalid_argument);
3220*89c4ff92SAndroid Build Coastguard Worker }
3221*89c4ff92SAndroid Build Coastguard Worker else if (is_symlink(fs_from)) {
3222*89c4ff92SAndroid Build Coastguard Worker if ((options & copy_options::skip_symlinks) == copy_options::none) {
3223*89c4ff92SAndroid Build Coastguard Worker if (!exists(fs_to) && (options & copy_options::copy_symlinks) != copy_options::none) {
3224*89c4ff92SAndroid Build Coastguard Worker copy_symlink(from, to, ec);
3225*89c4ff92SAndroid Build Coastguard Worker }
3226*89c4ff92SAndroid Build Coastguard Worker else {
3227*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_error_code(detail::portable_error::invalid_argument);
3228*89c4ff92SAndroid Build Coastguard Worker }
3229*89c4ff92SAndroid Build Coastguard Worker }
3230*89c4ff92SAndroid Build Coastguard Worker }
3231*89c4ff92SAndroid Build Coastguard Worker else if (is_regular_file(fs_from)) {
3232*89c4ff92SAndroid Build Coastguard Worker if ((options & copy_options::directories_only) == copy_options::none) {
3233*89c4ff92SAndroid Build Coastguard Worker if ((options & copy_options::create_symlinks) != copy_options::none) {
3234*89c4ff92SAndroid Build Coastguard Worker create_symlink(from.is_absolute() ? from : canonical(from, ec), to, ec);
3235*89c4ff92SAndroid Build Coastguard Worker }
3236*89c4ff92SAndroid Build Coastguard Worker else if ((options & copy_options::create_hard_links) != copy_options::none) {
3237*89c4ff92SAndroid Build Coastguard Worker create_hard_link(from, to, ec);
3238*89c4ff92SAndroid Build Coastguard Worker }
3239*89c4ff92SAndroid Build Coastguard Worker else if (is_directory(fs_to)) {
3240*89c4ff92SAndroid Build Coastguard Worker copy_file(from, to / from.filename(), options, ec);
3241*89c4ff92SAndroid Build Coastguard Worker }
3242*89c4ff92SAndroid Build Coastguard Worker else {
3243*89c4ff92SAndroid Build Coastguard Worker copy_file(from, to, options, ec);
3244*89c4ff92SAndroid Build Coastguard Worker }
3245*89c4ff92SAndroid Build Coastguard Worker }
3246*89c4ff92SAndroid Build Coastguard Worker }
3247*89c4ff92SAndroid Build Coastguard Worker #ifdef LWG_2682_BEHAVIOUR
3248*89c4ff92SAndroid Build Coastguard Worker else if (is_directory(fs_from) && (options & copy_options::create_symlinks) != copy_options::none) {
3249*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_error_code(detail::portable_error::is_a_directory);
3250*89c4ff92SAndroid Build Coastguard Worker }
3251*89c4ff92SAndroid Build Coastguard Worker #endif
3252*89c4ff92SAndroid Build Coastguard Worker else if (is_directory(fs_from) && (options == copy_options::none || (options & copy_options::recursive) != copy_options::none)) {
3253*89c4ff92SAndroid Build Coastguard Worker if (!exists(fs_to)) {
3254*89c4ff92SAndroid Build Coastguard Worker create_directory(to, from, ec);
3255*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3256*89c4ff92SAndroid Build Coastguard Worker return;
3257*89c4ff92SAndroid Build Coastguard Worker }
3258*89c4ff92SAndroid Build Coastguard Worker }
3259*89c4ff92SAndroid Build Coastguard Worker for (auto iter = directory_iterator(from, ec); iter != directory_iterator(); iter.increment(ec)) {
3260*89c4ff92SAndroid Build Coastguard Worker if (!ec) {
3261*89c4ff92SAndroid Build Coastguard Worker copy(iter->path(), to / iter->path().filename(), options | static_cast<copy_options>(0x8000), ec);
3262*89c4ff92SAndroid Build Coastguard Worker }
3263*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3264*89c4ff92SAndroid Build Coastguard Worker return;
3265*89c4ff92SAndroid Build Coastguard Worker }
3266*89c4ff92SAndroid Build Coastguard Worker }
3267*89c4ff92SAndroid Build Coastguard Worker }
3268*89c4ff92SAndroid Build Coastguard Worker return;
3269*89c4ff92SAndroid Build Coastguard Worker }
3270*89c4ff92SAndroid Build Coastguard Worker
copy_file(const path & from,const path & to)3271*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool copy_file(const path& from, const path& to)
3272*89c4ff92SAndroid Build Coastguard Worker {
3273*89c4ff92SAndroid Build Coastguard Worker return copy_file(from, to, copy_options::none);
3274*89c4ff92SAndroid Build Coastguard Worker }
3275*89c4ff92SAndroid Build Coastguard Worker
copy_file(const path & from,const path & to,std::error_code & ec)3276*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool copy_file(const path& from, const path& to, std::error_code& ec) noexcept
3277*89c4ff92SAndroid Build Coastguard Worker {
3278*89c4ff92SAndroid Build Coastguard Worker return copy_file(from, to, copy_options::none, ec);
3279*89c4ff92SAndroid Build Coastguard Worker }
3280*89c4ff92SAndroid Build Coastguard Worker
copy_file(const path & from,const path & to,copy_options option)3281*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool copy_file(const path& from, const path& to, copy_options option)
3282*89c4ff92SAndroid Build Coastguard Worker {
3283*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
3284*89c4ff92SAndroid Build Coastguard Worker auto result = copy_file(from, to, option, ec);
3285*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3286*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), from, to, ec);
3287*89c4ff92SAndroid Build Coastguard Worker }
3288*89c4ff92SAndroid Build Coastguard Worker return result;
3289*89c4ff92SAndroid Build Coastguard Worker }
3290*89c4ff92SAndroid Build Coastguard Worker
copy_file(const path & from,const path & to,copy_options options,std::error_code & ec)3291*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool copy_file(const path& from, const path& to, copy_options options, std::error_code& ec) noexcept
3292*89c4ff92SAndroid Build Coastguard Worker {
3293*89c4ff92SAndroid Build Coastguard Worker std::error_code tecf, tect;
3294*89c4ff92SAndroid Build Coastguard Worker auto sf = status(from, tecf);
3295*89c4ff92SAndroid Build Coastguard Worker auto st = status(to, tect);
3296*89c4ff92SAndroid Build Coastguard Worker bool overwrite = false;
3297*89c4ff92SAndroid Build Coastguard Worker ec.clear();
3298*89c4ff92SAndroid Build Coastguard Worker if (!is_regular_file(sf)) {
3299*89c4ff92SAndroid Build Coastguard Worker ec = tecf;
3300*89c4ff92SAndroid Build Coastguard Worker return false;
3301*89c4ff92SAndroid Build Coastguard Worker }
3302*89c4ff92SAndroid Build Coastguard Worker 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)) {
3303*89c4ff92SAndroid Build Coastguard Worker ec = tect ? tect : detail::make_error_code(detail::portable_error::exists);
3304*89c4ff92SAndroid Build Coastguard Worker return false;
3305*89c4ff92SAndroid Build Coastguard Worker }
3306*89c4ff92SAndroid Build Coastguard Worker if (exists(st)) {
3307*89c4ff92SAndroid Build Coastguard Worker if ((options & copy_options::update_existing) == copy_options::update_existing) {
3308*89c4ff92SAndroid Build Coastguard Worker auto from_time = last_write_time(from, ec);
3309*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3310*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3311*89c4ff92SAndroid Build Coastguard Worker return false;
3312*89c4ff92SAndroid Build Coastguard Worker }
3313*89c4ff92SAndroid Build Coastguard Worker auto to_time = last_write_time(to, ec);
3314*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3315*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3316*89c4ff92SAndroid Build Coastguard Worker return false;
3317*89c4ff92SAndroid Build Coastguard Worker }
3318*89c4ff92SAndroid Build Coastguard Worker if (from_time <= to_time) {
3319*89c4ff92SAndroid Build Coastguard Worker return false;
3320*89c4ff92SAndroid Build Coastguard Worker }
3321*89c4ff92SAndroid Build Coastguard Worker }
3322*89c4ff92SAndroid Build Coastguard Worker overwrite = true;
3323*89c4ff92SAndroid Build Coastguard Worker }
3324*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
3325*89c4ff92SAndroid Build Coastguard Worker if (!::CopyFileW(detail::fromUtf8<std::wstring>(from.u8string()).c_str(), detail::fromUtf8<std::wstring>(to.u8string()).c_str(), !overwrite)) {
3326*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3327*89c4ff92SAndroid Build Coastguard Worker return false;
3328*89c4ff92SAndroid Build Coastguard Worker }
3329*89c4ff92SAndroid Build Coastguard Worker return true;
3330*89c4ff92SAndroid Build Coastguard Worker #else
3331*89c4ff92SAndroid Build Coastguard Worker std::vector<char> buffer(16384, '\0');
3332*89c4ff92SAndroid Build Coastguard Worker int in = -1, out = -1;
3333*89c4ff92SAndroid Build Coastguard Worker if ((in = ::open(from.c_str(), O_RDONLY)) < 0) {
3334*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3335*89c4ff92SAndroid Build Coastguard Worker return false;
3336*89c4ff92SAndroid Build Coastguard Worker }
3337*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<void> guard_in(nullptr, [in](void*) { ::close(in); });
3338*89c4ff92SAndroid Build Coastguard Worker int mode = O_CREAT | O_WRONLY | O_TRUNC;
3339*89c4ff92SAndroid Build Coastguard Worker if (!overwrite) {
3340*89c4ff92SAndroid Build Coastguard Worker mode |= O_EXCL;
3341*89c4ff92SAndroid Build Coastguard Worker }
3342*89c4ff92SAndroid Build Coastguard Worker if ((out = ::open(to.c_str(), mode, static_cast<int>(sf.permissions() & perms::all))) < 0) {
3343*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3344*89c4ff92SAndroid Build Coastguard Worker return false;
3345*89c4ff92SAndroid Build Coastguard Worker }
3346*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<void> guard_out(nullptr, [out](void*) { ::close(out); });
3347*89c4ff92SAndroid Build Coastguard Worker ssize_t br, bw;
3348*89c4ff92SAndroid Build Coastguard Worker while ((br = ::read(in, buffer.data(), buffer.size())) > 0) {
3349*89c4ff92SAndroid Build Coastguard Worker ssize_t offset = 0;
3350*89c4ff92SAndroid Build Coastguard Worker do {
3351*89c4ff92SAndroid Build Coastguard Worker if ((bw = ::write(out, buffer.data() + offset, static_cast<size_t>(br))) > 0) {
3352*89c4ff92SAndroid Build Coastguard Worker br -= bw;
3353*89c4ff92SAndroid Build Coastguard Worker offset += bw;
3354*89c4ff92SAndroid Build Coastguard Worker }
3355*89c4ff92SAndroid Build Coastguard Worker else if (bw < 0) {
3356*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3357*89c4ff92SAndroid Build Coastguard Worker return false;
3358*89c4ff92SAndroid Build Coastguard Worker }
3359*89c4ff92SAndroid Build Coastguard Worker } while (br);
3360*89c4ff92SAndroid Build Coastguard Worker }
3361*89c4ff92SAndroid Build Coastguard Worker return true;
3362*89c4ff92SAndroid Build Coastguard Worker #endif
3363*89c4ff92SAndroid Build Coastguard Worker }
3364*89c4ff92SAndroid Build Coastguard Worker
copy_symlink(const path & existing_symlink,const path & new_symlink)3365*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void copy_symlink(const path& existing_symlink, const path& new_symlink)
3366*89c4ff92SAndroid Build Coastguard Worker {
3367*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
3368*89c4ff92SAndroid Build Coastguard Worker copy_symlink(existing_symlink, new_symlink, ec);
3369*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3370*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), existing_symlink, new_symlink, ec);
3371*89c4ff92SAndroid Build Coastguard Worker }
3372*89c4ff92SAndroid Build Coastguard Worker }
3373*89c4ff92SAndroid Build Coastguard Worker
copy_symlink(const path & existing_symlink,const path & new_symlink,std::error_code & ec)3374*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void copy_symlink(const path& existing_symlink, const path& new_symlink, std::error_code& ec) noexcept
3375*89c4ff92SAndroid Build Coastguard Worker {
3376*89c4ff92SAndroid Build Coastguard Worker ec.clear();
3377*89c4ff92SAndroid Build Coastguard Worker auto to = read_symlink(existing_symlink, ec);
3378*89c4ff92SAndroid Build Coastguard Worker if (!ec) {
3379*89c4ff92SAndroid Build Coastguard Worker if (exists(to, ec) && is_directory(to, ec)) {
3380*89c4ff92SAndroid Build Coastguard Worker create_directory_symlink(to, new_symlink, ec);
3381*89c4ff92SAndroid Build Coastguard Worker }
3382*89c4ff92SAndroid Build Coastguard Worker else {
3383*89c4ff92SAndroid Build Coastguard Worker create_symlink(to, new_symlink, ec);
3384*89c4ff92SAndroid Build Coastguard Worker }
3385*89c4ff92SAndroid Build Coastguard Worker }
3386*89c4ff92SAndroid Build Coastguard Worker }
3387*89c4ff92SAndroid Build Coastguard Worker
create_directories(const path & p)3388*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool create_directories(const path& p)
3389*89c4ff92SAndroid Build Coastguard Worker {
3390*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
3391*89c4ff92SAndroid Build Coastguard Worker auto result = create_directories(p, ec);
3392*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3393*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3394*89c4ff92SAndroid Build Coastguard Worker }
3395*89c4ff92SAndroid Build Coastguard Worker return result;
3396*89c4ff92SAndroid Build Coastguard Worker }
3397*89c4ff92SAndroid Build Coastguard Worker
create_directories(const path & p,std::error_code & ec)3398*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool create_directories(const path& p, std::error_code& ec) noexcept
3399*89c4ff92SAndroid Build Coastguard Worker {
3400*89c4ff92SAndroid Build Coastguard Worker path current;
3401*89c4ff92SAndroid Build Coastguard Worker ec.clear();
3402*89c4ff92SAndroid Build Coastguard Worker bool didCreate = false;
3403*89c4ff92SAndroid Build Coastguard Worker for (path::string_type part : p) {
3404*89c4ff92SAndroid Build Coastguard Worker current /= part;
3405*89c4ff92SAndroid Build Coastguard Worker if (current != p.root_name() && current != p.root_path()) {
3406*89c4ff92SAndroid Build Coastguard Worker std::error_code tec;
3407*89c4ff92SAndroid Build Coastguard Worker auto fs = status(current, tec);
3408*89c4ff92SAndroid Build Coastguard Worker if (tec && fs.type() != file_type::not_found) {
3409*89c4ff92SAndroid Build Coastguard Worker ec = tec;
3410*89c4ff92SAndroid Build Coastguard Worker return false;
3411*89c4ff92SAndroid Build Coastguard Worker }
3412*89c4ff92SAndroid Build Coastguard Worker if (!exists(fs)) {
3413*89c4ff92SAndroid Build Coastguard Worker create_directory(current, ec);
3414*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3415*89c4ff92SAndroid Build Coastguard Worker std::error_code tmp_ec;
3416*89c4ff92SAndroid Build Coastguard Worker if (is_directory(current, tmp_ec)) {
3417*89c4ff92SAndroid Build Coastguard Worker ec.clear();
3418*89c4ff92SAndroid Build Coastguard Worker } else {
3419*89c4ff92SAndroid Build Coastguard Worker return false;
3420*89c4ff92SAndroid Build Coastguard Worker }
3421*89c4ff92SAndroid Build Coastguard Worker }
3422*89c4ff92SAndroid Build Coastguard Worker didCreate = true;
3423*89c4ff92SAndroid Build Coastguard Worker }
3424*89c4ff92SAndroid Build Coastguard Worker #ifndef LWG_2935_BEHAVIOUR
3425*89c4ff92SAndroid Build Coastguard Worker else if (!is_directory(fs)) {
3426*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_error_code(detail::portable_error::exists);
3427*89c4ff92SAndroid Build Coastguard Worker return false;
3428*89c4ff92SAndroid Build Coastguard Worker }
3429*89c4ff92SAndroid Build Coastguard Worker #endif
3430*89c4ff92SAndroid Build Coastguard Worker }
3431*89c4ff92SAndroid Build Coastguard Worker }
3432*89c4ff92SAndroid Build Coastguard Worker return didCreate;
3433*89c4ff92SAndroid Build Coastguard Worker }
3434*89c4ff92SAndroid Build Coastguard Worker
create_directory(const path & p)3435*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool create_directory(const path& p)
3436*89c4ff92SAndroid Build Coastguard Worker {
3437*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
3438*89c4ff92SAndroid Build Coastguard Worker auto result = create_directory(p, path(), ec);
3439*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3440*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3441*89c4ff92SAndroid Build Coastguard Worker }
3442*89c4ff92SAndroid Build Coastguard Worker return result;
3443*89c4ff92SAndroid Build Coastguard Worker }
3444*89c4ff92SAndroid Build Coastguard Worker
create_directory(const path & p,std::error_code & ec)3445*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool create_directory(const path& p, std::error_code& ec) noexcept
3446*89c4ff92SAndroid Build Coastguard Worker {
3447*89c4ff92SAndroid Build Coastguard Worker return create_directory(p, path(), ec);
3448*89c4ff92SAndroid Build Coastguard Worker }
3449*89c4ff92SAndroid Build Coastguard Worker
create_directory(const path & p,const path & attributes)3450*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool create_directory(const path& p, const path& attributes)
3451*89c4ff92SAndroid Build Coastguard Worker {
3452*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
3453*89c4ff92SAndroid Build Coastguard Worker auto result = create_directory(p, attributes, ec);
3454*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3455*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3456*89c4ff92SAndroid Build Coastguard Worker }
3457*89c4ff92SAndroid Build Coastguard Worker return result;
3458*89c4ff92SAndroid Build Coastguard Worker }
3459*89c4ff92SAndroid Build Coastguard Worker
create_directory(const path & p,const path & attributes,std::error_code & ec)3460*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool create_directory(const path& p, const path& attributes, std::error_code& ec) noexcept
3461*89c4ff92SAndroid Build Coastguard Worker {
3462*89c4ff92SAndroid Build Coastguard Worker std::error_code tec;
3463*89c4ff92SAndroid Build Coastguard Worker ec.clear();
3464*89c4ff92SAndroid Build Coastguard Worker auto fs = status(p, tec);
3465*89c4ff92SAndroid Build Coastguard Worker #ifdef LWG_2935_BEHAVIOUR
3466*89c4ff92SAndroid Build Coastguard Worker if (status_known(fs) && exists(fs)) {
3467*89c4ff92SAndroid Build Coastguard Worker return false;
3468*89c4ff92SAndroid Build Coastguard Worker }
3469*89c4ff92SAndroid Build Coastguard Worker #else
3470*89c4ff92SAndroid Build Coastguard Worker if (status_known(fs) && exists(fs) && is_directory(fs)) {
3471*89c4ff92SAndroid Build Coastguard Worker return false;
3472*89c4ff92SAndroid Build Coastguard Worker }
3473*89c4ff92SAndroid Build Coastguard Worker #endif
3474*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
3475*89c4ff92SAndroid Build Coastguard Worker if (!attributes.empty()) {
3476*89c4ff92SAndroid Build Coastguard Worker if (!::CreateDirectoryExW(detail::fromUtf8<std::wstring>(attributes.u8string()).c_str(), detail::fromUtf8<std::wstring>(p.u8string()).c_str(), NULL)) {
3477*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3478*89c4ff92SAndroid Build Coastguard Worker return false;
3479*89c4ff92SAndroid Build Coastguard Worker }
3480*89c4ff92SAndroid Build Coastguard Worker }
3481*89c4ff92SAndroid Build Coastguard Worker else if (!::CreateDirectoryW(detail::fromUtf8<std::wstring>(p.u8string()).c_str(), NULL)) {
3482*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3483*89c4ff92SAndroid Build Coastguard Worker return false;
3484*89c4ff92SAndroid Build Coastguard Worker }
3485*89c4ff92SAndroid Build Coastguard Worker #else
3486*89c4ff92SAndroid Build Coastguard Worker ::mode_t attribs = static_cast<mode_t>(perms::all);
3487*89c4ff92SAndroid Build Coastguard Worker if (!attributes.empty()) {
3488*89c4ff92SAndroid Build Coastguard Worker struct ::stat fileStat;
3489*89c4ff92SAndroid Build Coastguard Worker if (::stat(attributes.c_str(), &fileStat) != 0) {
3490*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3491*89c4ff92SAndroid Build Coastguard Worker return false;
3492*89c4ff92SAndroid Build Coastguard Worker }
3493*89c4ff92SAndroid Build Coastguard Worker attribs = fileStat.st_mode;
3494*89c4ff92SAndroid Build Coastguard Worker }
3495*89c4ff92SAndroid Build Coastguard Worker if (::mkdir(p.c_str(), attribs) != 0) {
3496*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3497*89c4ff92SAndroid Build Coastguard Worker return false;
3498*89c4ff92SAndroid Build Coastguard Worker }
3499*89c4ff92SAndroid Build Coastguard Worker #endif
3500*89c4ff92SAndroid Build Coastguard Worker return true;
3501*89c4ff92SAndroid Build Coastguard Worker }
3502*89c4ff92SAndroid Build Coastguard Worker
create_directory_symlink(const path & to,const path & new_symlink)3503*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void create_directory_symlink(const path& to, const path& new_symlink)
3504*89c4ff92SAndroid Build Coastguard Worker {
3505*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
3506*89c4ff92SAndroid Build Coastguard Worker create_directory_symlink(to, new_symlink, ec);
3507*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3508*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), to, new_symlink, ec);
3509*89c4ff92SAndroid Build Coastguard Worker }
3510*89c4ff92SAndroid Build Coastguard Worker }
3511*89c4ff92SAndroid Build Coastguard Worker
create_directory_symlink(const path & to,const path & new_symlink,std::error_code & ec)3512*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void create_directory_symlink(const path& to, const path& new_symlink, std::error_code& ec) noexcept
3513*89c4ff92SAndroid Build Coastguard Worker {
3514*89c4ff92SAndroid Build Coastguard Worker detail::create_symlink(to, new_symlink, true, ec);
3515*89c4ff92SAndroid Build Coastguard Worker }
3516*89c4ff92SAndroid Build Coastguard Worker
create_hard_link(const path & to,const path & new_hard_link)3517*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void create_hard_link(const path& to, const path& new_hard_link)
3518*89c4ff92SAndroid Build Coastguard Worker {
3519*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
3520*89c4ff92SAndroid Build Coastguard Worker create_hard_link(to, new_hard_link, ec);
3521*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3522*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), to, new_hard_link, ec);
3523*89c4ff92SAndroid Build Coastguard Worker }
3524*89c4ff92SAndroid Build Coastguard Worker }
3525*89c4ff92SAndroid Build Coastguard Worker
create_hard_link(const path & to,const path & new_hard_link,std::error_code & ec)3526*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void create_hard_link(const path& to, const path& new_hard_link, std::error_code& ec) noexcept
3527*89c4ff92SAndroid Build Coastguard Worker {
3528*89c4ff92SAndroid Build Coastguard Worker detail::create_hardlink(to, new_hard_link, ec);
3529*89c4ff92SAndroid Build Coastguard Worker }
3530*89c4ff92SAndroid Build Coastguard Worker
create_symlink(const path & to,const path & new_symlink)3531*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void create_symlink(const path& to, const path& new_symlink)
3532*89c4ff92SAndroid Build Coastguard Worker {
3533*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
3534*89c4ff92SAndroid Build Coastguard Worker create_symlink(to, new_symlink, ec);
3535*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3536*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), to, new_symlink, ec);
3537*89c4ff92SAndroid Build Coastguard Worker }
3538*89c4ff92SAndroid Build Coastguard Worker }
3539*89c4ff92SAndroid Build Coastguard Worker
create_symlink(const path & to,const path & new_symlink,std::error_code & ec)3540*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void create_symlink(const path& to, const path& new_symlink, std::error_code& ec) noexcept
3541*89c4ff92SAndroid Build Coastguard Worker {
3542*89c4ff92SAndroid Build Coastguard Worker detail::create_symlink(to, new_symlink, false, ec);
3543*89c4ff92SAndroid Build Coastguard Worker }
3544*89c4ff92SAndroid Build Coastguard Worker
current_path()3545*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path current_path()
3546*89c4ff92SAndroid Build Coastguard Worker {
3547*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
3548*89c4ff92SAndroid Build Coastguard Worker auto result = current_path(ec);
3549*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3550*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), ec);
3551*89c4ff92SAndroid Build Coastguard Worker }
3552*89c4ff92SAndroid Build Coastguard Worker return result;
3553*89c4ff92SAndroid Build Coastguard Worker }
3554*89c4ff92SAndroid Build Coastguard Worker
current_path(std::error_code & ec)3555*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path current_path(std::error_code& ec)
3556*89c4ff92SAndroid Build Coastguard Worker {
3557*89c4ff92SAndroid Build Coastguard Worker ec.clear();
3558*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
3559*89c4ff92SAndroid Build Coastguard Worker DWORD pathlen = ::GetCurrentDirectoryW(0, 0);
3560*89c4ff92SAndroid Build Coastguard Worker std::unique_ptr<wchar_t[]> buffer(new wchar_t[size_t(pathlen) + 1]);
3561*89c4ff92SAndroid Build Coastguard Worker if (::GetCurrentDirectoryW(pathlen, buffer.get()) == 0) {
3562*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3563*89c4ff92SAndroid Build Coastguard Worker return path();
3564*89c4ff92SAndroid Build Coastguard Worker }
3565*89c4ff92SAndroid Build Coastguard Worker return path(std::wstring(buffer.get()), path::native_format);
3566*89c4ff92SAndroid Build Coastguard Worker #else
3567*89c4ff92SAndroid Build Coastguard Worker size_t pathlen = static_cast<size_t>(std::max(int(::pathconf(".", _PC_PATH_MAX)), int(PATH_MAX)));
3568*89c4ff92SAndroid Build Coastguard Worker std::unique_ptr<char[]> buffer(new char[pathlen + 1]);
3569*89c4ff92SAndroid Build Coastguard Worker if (::getcwd(buffer.get(), pathlen) == nullptr) {
3570*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3571*89c4ff92SAndroid Build Coastguard Worker return path();
3572*89c4ff92SAndroid Build Coastguard Worker }
3573*89c4ff92SAndroid Build Coastguard Worker return path(buffer.get());
3574*89c4ff92SAndroid Build Coastguard Worker #endif
3575*89c4ff92SAndroid Build Coastguard Worker }
3576*89c4ff92SAndroid Build Coastguard Worker
current_path(const path & p)3577*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void current_path(const path& p)
3578*89c4ff92SAndroid Build Coastguard Worker {
3579*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
3580*89c4ff92SAndroid Build Coastguard Worker current_path(p, ec);
3581*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3582*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3583*89c4ff92SAndroid Build Coastguard Worker }
3584*89c4ff92SAndroid Build Coastguard Worker }
3585*89c4ff92SAndroid Build Coastguard Worker
current_path(const path & p,std::error_code & ec)3586*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void current_path(const path& p, std::error_code& ec) noexcept
3587*89c4ff92SAndroid Build Coastguard Worker {
3588*89c4ff92SAndroid Build Coastguard Worker ec.clear();
3589*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
3590*89c4ff92SAndroid Build Coastguard Worker if (!::SetCurrentDirectoryW(detail::fromUtf8<std::wstring>(p.u8string()).c_str())) {
3591*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3592*89c4ff92SAndroid Build Coastguard Worker }
3593*89c4ff92SAndroid Build Coastguard Worker #else
3594*89c4ff92SAndroid Build Coastguard Worker if (::chdir(p.string().c_str()) == -1) {
3595*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3596*89c4ff92SAndroid Build Coastguard Worker }
3597*89c4ff92SAndroid Build Coastguard Worker #endif
3598*89c4ff92SAndroid Build Coastguard Worker }
3599*89c4ff92SAndroid Build Coastguard Worker
exists(file_status s)3600*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool exists(file_status s) noexcept
3601*89c4ff92SAndroid Build Coastguard Worker {
3602*89c4ff92SAndroid Build Coastguard Worker return status_known(s) && s.type() != file_type::not_found;
3603*89c4ff92SAndroid Build Coastguard Worker }
3604*89c4ff92SAndroid Build Coastguard Worker
exists(const path & p)3605*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool exists(const path& p)
3606*89c4ff92SAndroid Build Coastguard Worker {
3607*89c4ff92SAndroid Build Coastguard Worker return exists(status(p));
3608*89c4ff92SAndroid Build Coastguard Worker }
3609*89c4ff92SAndroid Build Coastguard Worker
exists(const path & p,std::error_code & ec)3610*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool exists(const path& p, std::error_code& ec) noexcept
3611*89c4ff92SAndroid Build Coastguard Worker {
3612*89c4ff92SAndroid Build Coastguard Worker file_status s = status(p, ec);
3613*89c4ff92SAndroid Build Coastguard Worker if (status_known(s)) {
3614*89c4ff92SAndroid Build Coastguard Worker ec.clear();
3615*89c4ff92SAndroid Build Coastguard Worker }
3616*89c4ff92SAndroid Build Coastguard Worker return exists(s);
3617*89c4ff92SAndroid Build Coastguard Worker }
3618*89c4ff92SAndroid Build Coastguard Worker
equivalent(const path & p1,const path & p2)3619*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool equivalent(const path& p1, const path& p2)
3620*89c4ff92SAndroid Build Coastguard Worker {
3621*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
3622*89c4ff92SAndroid Build Coastguard Worker bool result = equivalent(p1, p2, ec);
3623*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3624*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), p1, p2, ec);
3625*89c4ff92SAndroid Build Coastguard Worker }
3626*89c4ff92SAndroid Build Coastguard Worker return result;
3627*89c4ff92SAndroid Build Coastguard Worker }
3628*89c4ff92SAndroid Build Coastguard Worker
equivalent(const path & p1,const path & p2,std::error_code & ec)3629*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool equivalent(const path& p1, const path& p2, std::error_code& ec) noexcept
3630*89c4ff92SAndroid Build Coastguard Worker {
3631*89c4ff92SAndroid Build Coastguard Worker ec.clear();
3632*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
3633*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<void> file1(::CreateFileW(p1.wstring().c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle);
3634*89c4ff92SAndroid Build Coastguard Worker auto e1 = ::GetLastError();
3635*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<void> file2(::CreateFileW(p2.wstring().c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle);
3636*89c4ff92SAndroid Build Coastguard Worker if (file1.get() == INVALID_HANDLE_VALUE || file2.get() == INVALID_HANDLE_VALUE) {
3637*89c4ff92SAndroid Build Coastguard Worker #ifdef LWG_2937_BEHAVIOUR
3638*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error(e1 ? e1 : ::GetLastError());
3639*89c4ff92SAndroid Build Coastguard Worker #else
3640*89c4ff92SAndroid Build Coastguard Worker if (file1 == file2) {
3641*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error(e1 ? e1 : ::GetLastError());
3642*89c4ff92SAndroid Build Coastguard Worker }
3643*89c4ff92SAndroid Build Coastguard Worker #endif
3644*89c4ff92SAndroid Build Coastguard Worker return false;
3645*89c4ff92SAndroid Build Coastguard Worker }
3646*89c4ff92SAndroid Build Coastguard Worker BY_HANDLE_FILE_INFORMATION inf1, inf2;
3647*89c4ff92SAndroid Build Coastguard Worker if (!::GetFileInformationByHandle(file1.get(), &inf1)) {
3648*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3649*89c4ff92SAndroid Build Coastguard Worker return false;
3650*89c4ff92SAndroid Build Coastguard Worker }
3651*89c4ff92SAndroid Build Coastguard Worker if (!::GetFileInformationByHandle(file2.get(), &inf2)) {
3652*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3653*89c4ff92SAndroid Build Coastguard Worker return false;
3654*89c4ff92SAndroid Build Coastguard Worker }
3655*89c4ff92SAndroid Build Coastguard Worker return inf1.ftLastWriteTime.dwLowDateTime == inf2.ftLastWriteTime.dwLowDateTime && inf1.ftLastWriteTime.dwHighDateTime == inf2.ftLastWriteTime.dwHighDateTime && inf1.nFileIndexHigh == inf2.nFileIndexHigh && inf1.nFileIndexLow == inf2.nFileIndexLow &&
3656*89c4ff92SAndroid Build Coastguard Worker inf1.nFileSizeHigh == inf2.nFileSizeHigh && inf1.nFileSizeLow == inf2.nFileSizeLow && inf1.dwVolumeSerialNumber == inf2.dwVolumeSerialNumber;
3657*89c4ff92SAndroid Build Coastguard Worker #else
3658*89c4ff92SAndroid Build Coastguard Worker struct ::stat s1, s2;
3659*89c4ff92SAndroid Build Coastguard Worker auto rc1 = ::stat(p1.c_str(), &s1);
3660*89c4ff92SAndroid Build Coastguard Worker auto e1 = errno;
3661*89c4ff92SAndroid Build Coastguard Worker auto rc2 = ::stat(p2.c_str(), &s2);
3662*89c4ff92SAndroid Build Coastguard Worker if (rc1 || rc2) {
3663*89c4ff92SAndroid Build Coastguard Worker #ifdef LWG_2937_BEHAVIOUR
3664*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error(e1 ? e1 : errno);
3665*89c4ff92SAndroid Build Coastguard Worker #else
3666*89c4ff92SAndroid Build Coastguard Worker if (rc1 && rc2) {
3667*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error(e1 ? e1 : errno);
3668*89c4ff92SAndroid Build Coastguard Worker }
3669*89c4ff92SAndroid Build Coastguard Worker #endif
3670*89c4ff92SAndroid Build Coastguard Worker return false;
3671*89c4ff92SAndroid Build Coastguard Worker }
3672*89c4ff92SAndroid Build Coastguard Worker return s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino && s1.st_size == s2.st_size && s1.st_mtime == s2.st_mtime;
3673*89c4ff92SAndroid Build Coastguard Worker #endif
3674*89c4ff92SAndroid Build Coastguard Worker }
3675*89c4ff92SAndroid Build Coastguard Worker
file_size(const path & p)3676*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE uintmax_t file_size(const path& p)
3677*89c4ff92SAndroid Build Coastguard Worker {
3678*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
3679*89c4ff92SAndroid Build Coastguard Worker auto result = file_size(p, ec);
3680*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3681*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3682*89c4ff92SAndroid Build Coastguard Worker }
3683*89c4ff92SAndroid Build Coastguard Worker return result;
3684*89c4ff92SAndroid Build Coastguard Worker }
3685*89c4ff92SAndroid Build Coastguard Worker
file_size(const path & p,std::error_code & ec)3686*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE uintmax_t file_size(const path& p, std::error_code& ec) noexcept
3687*89c4ff92SAndroid Build Coastguard Worker {
3688*89c4ff92SAndroid Build Coastguard Worker ec.clear();
3689*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
3690*89c4ff92SAndroid Build Coastguard Worker WIN32_FILE_ATTRIBUTE_DATA attr;
3691*89c4ff92SAndroid Build Coastguard Worker if (!GetFileAttributesExW(detail::fromUtf8<std::wstring>(p.u8string()).c_str(), GetFileExInfoStandard, &attr)) {
3692*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3693*89c4ff92SAndroid Build Coastguard Worker return static_cast<uintmax_t>(-1);
3694*89c4ff92SAndroid Build Coastguard Worker }
3695*89c4ff92SAndroid Build Coastguard Worker return static_cast<uintmax_t>(attr.nFileSizeHigh) << (sizeof(attr.nFileSizeHigh) * 8) | attr.nFileSizeLow;
3696*89c4ff92SAndroid Build Coastguard Worker #else
3697*89c4ff92SAndroid Build Coastguard Worker struct ::stat fileStat;
3698*89c4ff92SAndroid Build Coastguard Worker if (::stat(p.c_str(), &fileStat) == -1) {
3699*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3700*89c4ff92SAndroid Build Coastguard Worker return static_cast<uintmax_t>(-1);
3701*89c4ff92SAndroid Build Coastguard Worker }
3702*89c4ff92SAndroid Build Coastguard Worker return static_cast<uintmax_t>(fileStat.st_size);
3703*89c4ff92SAndroid Build Coastguard Worker #endif
3704*89c4ff92SAndroid Build Coastguard Worker }
3705*89c4ff92SAndroid Build Coastguard Worker
hard_link_count(const path & p)3706*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE uintmax_t hard_link_count(const path& p)
3707*89c4ff92SAndroid Build Coastguard Worker {
3708*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
3709*89c4ff92SAndroid Build Coastguard Worker auto result = hard_link_count(p, ec);
3710*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3711*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3712*89c4ff92SAndroid Build Coastguard Worker }
3713*89c4ff92SAndroid Build Coastguard Worker return result;
3714*89c4ff92SAndroid Build Coastguard Worker }
3715*89c4ff92SAndroid Build Coastguard Worker
hard_link_count(const path & p,std::error_code & ec)3716*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcept
3717*89c4ff92SAndroid Build Coastguard Worker {
3718*89c4ff92SAndroid Build Coastguard Worker ec.clear();
3719*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
3720*89c4ff92SAndroid Build Coastguard Worker uintmax_t result = static_cast<uintmax_t>(-1);
3721*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<void> file(::CreateFileW(p.wstring().c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle);
3722*89c4ff92SAndroid Build Coastguard Worker BY_HANDLE_FILE_INFORMATION inf;
3723*89c4ff92SAndroid Build Coastguard Worker if (file.get() == INVALID_HANDLE_VALUE) {
3724*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3725*89c4ff92SAndroid Build Coastguard Worker }
3726*89c4ff92SAndroid Build Coastguard Worker else {
3727*89c4ff92SAndroid Build Coastguard Worker if (!::GetFileInformationByHandle(file.get(), &inf)) {
3728*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3729*89c4ff92SAndroid Build Coastguard Worker }
3730*89c4ff92SAndroid Build Coastguard Worker else {
3731*89c4ff92SAndroid Build Coastguard Worker result = inf.nNumberOfLinks;
3732*89c4ff92SAndroid Build Coastguard Worker }
3733*89c4ff92SAndroid Build Coastguard Worker }
3734*89c4ff92SAndroid Build Coastguard Worker return result;
3735*89c4ff92SAndroid Build Coastguard Worker #else
3736*89c4ff92SAndroid Build Coastguard Worker uintmax_t result = 0;
3737*89c4ff92SAndroid Build Coastguard Worker file_status fs = detail::status_ex(p, ec, nullptr, nullptr, &result, nullptr);
3738*89c4ff92SAndroid Build Coastguard Worker if (fs.type() == file_type::not_found) {
3739*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_error_code(detail::portable_error::not_found);
3740*89c4ff92SAndroid Build Coastguard Worker }
3741*89c4ff92SAndroid Build Coastguard Worker return ec ? static_cast<uintmax_t>(-1) : result;
3742*89c4ff92SAndroid Build Coastguard Worker #endif
3743*89c4ff92SAndroid Build Coastguard Worker }
3744*89c4ff92SAndroid Build Coastguard Worker
is_block_file(file_status s)3745*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_block_file(file_status s) noexcept
3746*89c4ff92SAndroid Build Coastguard Worker {
3747*89c4ff92SAndroid Build Coastguard Worker return s.type() == file_type::block;
3748*89c4ff92SAndroid Build Coastguard Worker }
3749*89c4ff92SAndroid Build Coastguard Worker
is_block_file(const path & p)3750*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_block_file(const path& p)
3751*89c4ff92SAndroid Build Coastguard Worker {
3752*89c4ff92SAndroid Build Coastguard Worker return is_block_file(status(p));
3753*89c4ff92SAndroid Build Coastguard Worker }
3754*89c4ff92SAndroid Build Coastguard Worker
is_block_file(const path & p,std::error_code & ec)3755*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_block_file(const path& p, std::error_code& ec) noexcept
3756*89c4ff92SAndroid Build Coastguard Worker {
3757*89c4ff92SAndroid Build Coastguard Worker return is_block_file(status(p, ec));
3758*89c4ff92SAndroid Build Coastguard Worker }
3759*89c4ff92SAndroid Build Coastguard Worker
is_character_file(file_status s)3760*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_character_file(file_status s) noexcept
3761*89c4ff92SAndroid Build Coastguard Worker {
3762*89c4ff92SAndroid Build Coastguard Worker return s.type() == file_type::character;
3763*89c4ff92SAndroid Build Coastguard Worker }
3764*89c4ff92SAndroid Build Coastguard Worker
is_character_file(const path & p)3765*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_character_file(const path& p)
3766*89c4ff92SAndroid Build Coastguard Worker {
3767*89c4ff92SAndroid Build Coastguard Worker return is_character_file(status(p));
3768*89c4ff92SAndroid Build Coastguard Worker }
3769*89c4ff92SAndroid Build Coastguard Worker
is_character_file(const path & p,std::error_code & ec)3770*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_character_file(const path& p, std::error_code& ec) noexcept
3771*89c4ff92SAndroid Build Coastguard Worker {
3772*89c4ff92SAndroid Build Coastguard Worker return is_character_file(status(p, ec));
3773*89c4ff92SAndroid Build Coastguard Worker }
3774*89c4ff92SAndroid Build Coastguard Worker
is_directory(file_status s)3775*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_directory(file_status s) noexcept
3776*89c4ff92SAndroid Build Coastguard Worker {
3777*89c4ff92SAndroid Build Coastguard Worker return s.type() == file_type::directory;
3778*89c4ff92SAndroid Build Coastguard Worker }
3779*89c4ff92SAndroid Build Coastguard Worker
is_directory(const path & p)3780*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_directory(const path& p)
3781*89c4ff92SAndroid Build Coastguard Worker {
3782*89c4ff92SAndroid Build Coastguard Worker return is_directory(status(p));
3783*89c4ff92SAndroid Build Coastguard Worker }
3784*89c4ff92SAndroid Build Coastguard Worker
is_directory(const path & p,std::error_code & ec)3785*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_directory(const path& p, std::error_code& ec) noexcept
3786*89c4ff92SAndroid Build Coastguard Worker {
3787*89c4ff92SAndroid Build Coastguard Worker return is_directory(status(p, ec));
3788*89c4ff92SAndroid Build Coastguard Worker }
3789*89c4ff92SAndroid Build Coastguard Worker
is_empty(const path & p)3790*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_empty(const path& p)
3791*89c4ff92SAndroid Build Coastguard Worker {
3792*89c4ff92SAndroid Build Coastguard Worker if (is_directory(p)) {
3793*89c4ff92SAndroid Build Coastguard Worker return directory_iterator(p) == directory_iterator();
3794*89c4ff92SAndroid Build Coastguard Worker }
3795*89c4ff92SAndroid Build Coastguard Worker else {
3796*89c4ff92SAndroid Build Coastguard Worker return file_size(p) == 0;
3797*89c4ff92SAndroid Build Coastguard Worker }
3798*89c4ff92SAndroid Build Coastguard Worker }
3799*89c4ff92SAndroid Build Coastguard Worker
is_empty(const path & p,std::error_code & ec)3800*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_empty(const path& p, std::error_code& ec) noexcept
3801*89c4ff92SAndroid Build Coastguard Worker {
3802*89c4ff92SAndroid Build Coastguard Worker auto fs = status(p, ec);
3803*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3804*89c4ff92SAndroid Build Coastguard Worker return false;
3805*89c4ff92SAndroid Build Coastguard Worker }
3806*89c4ff92SAndroid Build Coastguard Worker if (is_directory(fs)) {
3807*89c4ff92SAndroid Build Coastguard Worker directory_iterator iter(p, ec);
3808*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3809*89c4ff92SAndroid Build Coastguard Worker return false;
3810*89c4ff92SAndroid Build Coastguard Worker }
3811*89c4ff92SAndroid Build Coastguard Worker return iter == directory_iterator();
3812*89c4ff92SAndroid Build Coastguard Worker }
3813*89c4ff92SAndroid Build Coastguard Worker else {
3814*89c4ff92SAndroid Build Coastguard Worker auto sz = file_size(p, ec);
3815*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3816*89c4ff92SAndroid Build Coastguard Worker return false;
3817*89c4ff92SAndroid Build Coastguard Worker }
3818*89c4ff92SAndroid Build Coastguard Worker return sz == 0;
3819*89c4ff92SAndroid Build Coastguard Worker }
3820*89c4ff92SAndroid Build Coastguard Worker }
3821*89c4ff92SAndroid Build Coastguard Worker
is_fifo(file_status s)3822*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_fifo(file_status s) noexcept
3823*89c4ff92SAndroid Build Coastguard Worker {
3824*89c4ff92SAndroid Build Coastguard Worker return s.type() == file_type::fifo;
3825*89c4ff92SAndroid Build Coastguard Worker }
3826*89c4ff92SAndroid Build Coastguard Worker
is_fifo(const path & p)3827*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_fifo(const path& p)
3828*89c4ff92SAndroid Build Coastguard Worker {
3829*89c4ff92SAndroid Build Coastguard Worker return is_fifo(status(p));
3830*89c4ff92SAndroid Build Coastguard Worker }
3831*89c4ff92SAndroid Build Coastguard Worker
is_fifo(const path & p,std::error_code & ec)3832*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_fifo(const path& p, std::error_code& ec) noexcept
3833*89c4ff92SAndroid Build Coastguard Worker {
3834*89c4ff92SAndroid Build Coastguard Worker return is_fifo(status(p, ec));
3835*89c4ff92SAndroid Build Coastguard Worker }
3836*89c4ff92SAndroid Build Coastguard Worker
is_other(file_status s)3837*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_other(file_status s) noexcept
3838*89c4ff92SAndroid Build Coastguard Worker {
3839*89c4ff92SAndroid Build Coastguard Worker return exists(s) && !is_regular_file(s) && !is_directory(s) && !is_symlink(s);
3840*89c4ff92SAndroid Build Coastguard Worker }
3841*89c4ff92SAndroid Build Coastguard Worker
is_other(const path & p)3842*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_other(const path& p)
3843*89c4ff92SAndroid Build Coastguard Worker {
3844*89c4ff92SAndroid Build Coastguard Worker return is_other(status(p));
3845*89c4ff92SAndroid Build Coastguard Worker }
3846*89c4ff92SAndroid Build Coastguard Worker
is_other(const path & p,std::error_code & ec)3847*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_other(const path& p, std::error_code& ec) noexcept
3848*89c4ff92SAndroid Build Coastguard Worker {
3849*89c4ff92SAndroid Build Coastguard Worker return is_other(status(p, ec));
3850*89c4ff92SAndroid Build Coastguard Worker }
3851*89c4ff92SAndroid Build Coastguard Worker
is_regular_file(file_status s)3852*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_regular_file(file_status s) noexcept
3853*89c4ff92SAndroid Build Coastguard Worker {
3854*89c4ff92SAndroid Build Coastguard Worker return s.type() == file_type::regular;
3855*89c4ff92SAndroid Build Coastguard Worker }
3856*89c4ff92SAndroid Build Coastguard Worker
is_regular_file(const path & p)3857*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_regular_file(const path& p)
3858*89c4ff92SAndroid Build Coastguard Worker {
3859*89c4ff92SAndroid Build Coastguard Worker return is_regular_file(status(p));
3860*89c4ff92SAndroid Build Coastguard Worker }
3861*89c4ff92SAndroid Build Coastguard Worker
is_regular_file(const path & p,std::error_code & ec)3862*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_regular_file(const path& p, std::error_code& ec) noexcept
3863*89c4ff92SAndroid Build Coastguard Worker {
3864*89c4ff92SAndroid Build Coastguard Worker return is_regular_file(status(p, ec));
3865*89c4ff92SAndroid Build Coastguard Worker }
3866*89c4ff92SAndroid Build Coastguard Worker
is_socket(file_status s)3867*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_socket(file_status s) noexcept
3868*89c4ff92SAndroid Build Coastguard Worker {
3869*89c4ff92SAndroid Build Coastguard Worker return s.type() == file_type::socket;
3870*89c4ff92SAndroid Build Coastguard Worker }
3871*89c4ff92SAndroid Build Coastguard Worker
is_socket(const path & p)3872*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_socket(const path& p)
3873*89c4ff92SAndroid Build Coastguard Worker {
3874*89c4ff92SAndroid Build Coastguard Worker return is_socket(status(p));
3875*89c4ff92SAndroid Build Coastguard Worker }
3876*89c4ff92SAndroid Build Coastguard Worker
is_socket(const path & p,std::error_code & ec)3877*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_socket(const path& p, std::error_code& ec) noexcept
3878*89c4ff92SAndroid Build Coastguard Worker {
3879*89c4ff92SAndroid Build Coastguard Worker return is_socket(status(p, ec));
3880*89c4ff92SAndroid Build Coastguard Worker }
3881*89c4ff92SAndroid Build Coastguard Worker
is_symlink(file_status s)3882*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_symlink(file_status s) noexcept
3883*89c4ff92SAndroid Build Coastguard Worker {
3884*89c4ff92SAndroid Build Coastguard Worker return s.type() == file_type::symlink;
3885*89c4ff92SAndroid Build Coastguard Worker }
3886*89c4ff92SAndroid Build Coastguard Worker
is_symlink(const path & p)3887*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_symlink(const path& p)
3888*89c4ff92SAndroid Build Coastguard Worker {
3889*89c4ff92SAndroid Build Coastguard Worker return is_symlink(symlink_status(p));
3890*89c4ff92SAndroid Build Coastguard Worker }
3891*89c4ff92SAndroid Build Coastguard Worker
is_symlink(const path & p,std::error_code & ec)3892*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool is_symlink(const path& p, std::error_code& ec) noexcept
3893*89c4ff92SAndroid Build Coastguard Worker {
3894*89c4ff92SAndroid Build Coastguard Worker return is_symlink(symlink_status(p, ec));
3895*89c4ff92SAndroid Build Coastguard Worker }
3896*89c4ff92SAndroid Build Coastguard Worker
last_write_time(const path & p)3897*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_time_type last_write_time(const path& p)
3898*89c4ff92SAndroid Build Coastguard Worker {
3899*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
3900*89c4ff92SAndroid Build Coastguard Worker auto result = last_write_time(p, ec);
3901*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3902*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3903*89c4ff92SAndroid Build Coastguard Worker }
3904*89c4ff92SAndroid Build Coastguard Worker return result;
3905*89c4ff92SAndroid Build Coastguard Worker }
3906*89c4ff92SAndroid Build Coastguard Worker
last_write_time(const path & p,std::error_code & ec)3907*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_time_type last_write_time(const path& p, std::error_code& ec) noexcept
3908*89c4ff92SAndroid Build Coastguard Worker {
3909*89c4ff92SAndroid Build Coastguard Worker time_t result = 0;
3910*89c4ff92SAndroid Build Coastguard Worker ec.clear();
3911*89c4ff92SAndroid Build Coastguard Worker file_status fs = detail::status_ex(p, ec, nullptr, nullptr, nullptr, &result);
3912*89c4ff92SAndroid Build Coastguard Worker return ec ? (file_time_type::min)() : std::chrono::system_clock::from_time_t(result);
3913*89c4ff92SAndroid Build Coastguard Worker }
3914*89c4ff92SAndroid Build Coastguard Worker
last_write_time(const path & p,file_time_type new_time)3915*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void last_write_time(const path& p, file_time_type new_time)
3916*89c4ff92SAndroid Build Coastguard Worker {
3917*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
3918*89c4ff92SAndroid Build Coastguard Worker last_write_time(p, new_time, ec);
3919*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3920*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3921*89c4ff92SAndroid Build Coastguard Worker }
3922*89c4ff92SAndroid Build Coastguard Worker }
3923*89c4ff92SAndroid Build Coastguard Worker
last_write_time(const path & p,file_time_type new_time,std::error_code & ec)3924*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void last_write_time(const path& p, file_time_type new_time, std::error_code& ec) noexcept
3925*89c4ff92SAndroid Build Coastguard Worker {
3926*89c4ff92SAndroid Build Coastguard Worker ec.clear();
3927*89c4ff92SAndroid Build Coastguard Worker auto d = new_time.time_since_epoch();
3928*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
3929*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<void> file(::CreateFileW(p.wstring().c_str(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL), ::CloseHandle);
3930*89c4ff92SAndroid Build Coastguard Worker FILETIME ft;
3931*89c4ff92SAndroid Build Coastguard Worker auto tt = std::chrono::duration_cast<std::chrono::microseconds>(d).count() * 10 + 116444736000000000;
3932*89c4ff92SAndroid Build Coastguard Worker ft.dwLowDateTime = static_cast<DWORD>(tt);
3933*89c4ff92SAndroid Build Coastguard Worker ft.dwHighDateTime = static_cast<DWORD>(tt >> 32);
3934*89c4ff92SAndroid Build Coastguard Worker if (!::SetFileTime(file.get(), 0, 0, &ft)) {
3935*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3936*89c4ff92SAndroid Build Coastguard Worker }
3937*89c4ff92SAndroid Build Coastguard Worker #elif defined(GHC_OS_MACOS)
3938*89c4ff92SAndroid Build Coastguard Worker #ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
3939*89c4ff92SAndroid Build Coastguard Worker #if __MAC_OS_X_VERSION_MIN_REQUIRED < 101300
3940*89c4ff92SAndroid Build Coastguard Worker struct ::stat fs;
3941*89c4ff92SAndroid Build Coastguard Worker if (::stat(p.c_str(), &fs) == 0) {
3942*89c4ff92SAndroid Build Coastguard Worker struct ::timeval tv[2];
3943*89c4ff92SAndroid Build Coastguard Worker tv[0].tv_sec = fs.st_atimespec.tv_sec;
3944*89c4ff92SAndroid Build Coastguard Worker tv[0].tv_usec = static_cast<int>(fs.st_atimespec.tv_nsec / 1000);
3945*89c4ff92SAndroid Build Coastguard Worker tv[1].tv_sec = std::chrono::duration_cast<std::chrono::seconds>(d).count();
3946*89c4ff92SAndroid Build Coastguard Worker tv[1].tv_usec = static_cast<int>(std::chrono::duration_cast<std::chrono::microseconds>(d).count() % 1000000);
3947*89c4ff92SAndroid Build Coastguard Worker if (::utimes(p.c_str(), tv) == 0) {
3948*89c4ff92SAndroid Build Coastguard Worker return;
3949*89c4ff92SAndroid Build Coastguard Worker }
3950*89c4ff92SAndroid Build Coastguard Worker }
3951*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3952*89c4ff92SAndroid Build Coastguard Worker return;
3953*89c4ff92SAndroid Build Coastguard Worker #else
3954*89c4ff92SAndroid Build Coastguard Worker struct ::timespec times[2];
3955*89c4ff92SAndroid Build Coastguard Worker times[0].tv_sec = 0;
3956*89c4ff92SAndroid Build Coastguard Worker times[0].tv_nsec = UTIME_OMIT;
3957*89c4ff92SAndroid Build Coastguard Worker times[1].tv_sec = std::chrono::duration_cast<std::chrono::seconds>(d).count();
3958*89c4ff92SAndroid Build Coastguard Worker times[1].tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(d).count() % 1000000000;
3959*89c4ff92SAndroid Build Coastguard Worker if (::utimensat(AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) {
3960*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3961*89c4ff92SAndroid Build Coastguard Worker }
3962*89c4ff92SAndroid Build Coastguard Worker return;
3963*89c4ff92SAndroid Build Coastguard Worker #endif
3964*89c4ff92SAndroid Build Coastguard Worker #endif
3965*89c4ff92SAndroid Build Coastguard Worker #else
3966*89c4ff92SAndroid Build Coastguard Worker struct ::timespec times[2];
3967*89c4ff92SAndroid Build Coastguard Worker times[0].tv_sec = 0;
3968*89c4ff92SAndroid Build Coastguard Worker times[0].tv_nsec = UTIME_OMIT;
3969*89c4ff92SAndroid Build Coastguard Worker times[1].tv_sec = static_cast<decltype(times[1].tv_sec)>(std::chrono::duration_cast<std::chrono::seconds>(d).count());
3970*89c4ff92SAndroid Build Coastguard Worker times[1].tv_nsec = static_cast<decltype(times[1].tv_nsec)>(std::chrono::duration_cast<std::chrono::nanoseconds>(d).count() % 1000000000);
3971*89c4ff92SAndroid Build Coastguard Worker if (::utimensat(AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) {
3972*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
3973*89c4ff92SAndroid Build Coastguard Worker }
3974*89c4ff92SAndroid Build Coastguard Worker return;
3975*89c4ff92SAndroid Build Coastguard Worker #endif
3976*89c4ff92SAndroid Build Coastguard Worker }
3977*89c4ff92SAndroid Build Coastguard Worker
permissions(const path & p,perms prms,perm_options opts)3978*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void permissions(const path& p, perms prms, perm_options opts)
3979*89c4ff92SAndroid Build Coastguard Worker {
3980*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
3981*89c4ff92SAndroid Build Coastguard Worker permissions(p, prms, opts, ec);
3982*89c4ff92SAndroid Build Coastguard Worker if (ec) {
3983*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3984*89c4ff92SAndroid Build Coastguard Worker }
3985*89c4ff92SAndroid Build Coastguard Worker }
3986*89c4ff92SAndroid Build Coastguard Worker
permissions(const path & p,perms prms,std::error_code & ec)3987*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void permissions(const path& p, perms prms, std::error_code& ec) noexcept
3988*89c4ff92SAndroid Build Coastguard Worker {
3989*89c4ff92SAndroid Build Coastguard Worker permissions(p, prms, perm_options::replace, ec);
3990*89c4ff92SAndroid Build Coastguard Worker }
3991*89c4ff92SAndroid Build Coastguard Worker
permissions(const path & p,perms prms,perm_options opts,std::error_code & ec)3992*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void permissions(const path& p, perms prms, perm_options opts, std::error_code& ec)
3993*89c4ff92SAndroid Build Coastguard Worker {
3994*89c4ff92SAndroid Build Coastguard Worker if (static_cast<int>(opts & (perm_options::replace | perm_options::add | perm_options::remove)) == 0) {
3995*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_error_code(detail::portable_error::invalid_argument);
3996*89c4ff92SAndroid Build Coastguard Worker return;
3997*89c4ff92SAndroid Build Coastguard Worker }
3998*89c4ff92SAndroid Build Coastguard Worker auto fs = symlink_status(p, ec);
3999*89c4ff92SAndroid Build Coastguard Worker if ((opts & perm_options::replace) != perm_options::replace) {
4000*89c4ff92SAndroid Build Coastguard Worker if ((opts & perm_options::add) == perm_options::add) {
4001*89c4ff92SAndroid Build Coastguard Worker prms = fs.permissions() | prms;
4002*89c4ff92SAndroid Build Coastguard Worker }
4003*89c4ff92SAndroid Build Coastguard Worker else {
4004*89c4ff92SAndroid Build Coastguard Worker prms = fs.permissions() & ~prms;
4005*89c4ff92SAndroid Build Coastguard Worker }
4006*89c4ff92SAndroid Build Coastguard Worker }
4007*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
4008*89c4ff92SAndroid Build Coastguard Worker #ifdef __GNUC__
4009*89c4ff92SAndroid Build Coastguard Worker auto oldAttr = GetFileAttributesW(p.wstring().c_str());
4010*89c4ff92SAndroid Build Coastguard Worker if (oldAttr != INVALID_FILE_ATTRIBUTES) {
4011*89c4ff92SAndroid Build Coastguard Worker DWORD newAttr = ((prms & perms::owner_write) == perms::owner_write) ? oldAttr & ~(static_cast<DWORD>(FILE_ATTRIBUTE_READONLY)) : oldAttr | FILE_ATTRIBUTE_READONLY;
4012*89c4ff92SAndroid Build Coastguard Worker if (oldAttr == newAttr || SetFileAttributesW(p.wstring().c_str(), newAttr)) {
4013*89c4ff92SAndroid Build Coastguard Worker return;
4014*89c4ff92SAndroid Build Coastguard Worker }
4015*89c4ff92SAndroid Build Coastguard Worker }
4016*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
4017*89c4ff92SAndroid Build Coastguard Worker #else
4018*89c4ff92SAndroid Build Coastguard Worker int mode = 0;
4019*89c4ff92SAndroid Build Coastguard Worker if ((prms & perms::owner_read) == perms::owner_read) {
4020*89c4ff92SAndroid Build Coastguard Worker mode |= _S_IREAD;
4021*89c4ff92SAndroid Build Coastguard Worker }
4022*89c4ff92SAndroid Build Coastguard Worker if ((prms & perms::owner_write) == perms::owner_write) {
4023*89c4ff92SAndroid Build Coastguard Worker mode |= _S_IWRITE;
4024*89c4ff92SAndroid Build Coastguard Worker }
4025*89c4ff92SAndroid Build Coastguard Worker if (::_wchmod(p.wstring().c_str(), mode) != 0) {
4026*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
4027*89c4ff92SAndroid Build Coastguard Worker }
4028*89c4ff92SAndroid Build Coastguard Worker #endif
4029*89c4ff92SAndroid Build Coastguard Worker #else
4030*89c4ff92SAndroid Build Coastguard Worker if ((opts & perm_options::nofollow) != perm_options::nofollow) {
4031*89c4ff92SAndroid Build Coastguard Worker if (::chmod(p.c_str(), static_cast<mode_t>(prms)) != 0) {
4032*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
4033*89c4ff92SAndroid Build Coastguard Worker }
4034*89c4ff92SAndroid Build Coastguard Worker }
4035*89c4ff92SAndroid Build Coastguard Worker #endif
4036*89c4ff92SAndroid Build Coastguard Worker }
4037*89c4ff92SAndroid Build Coastguard Worker
proximate(const path & p,std::error_code & ec)4038*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path proximate(const path& p, std::error_code& ec)
4039*89c4ff92SAndroid Build Coastguard Worker {
4040*89c4ff92SAndroid Build Coastguard Worker return proximate(p, current_path(), ec);
4041*89c4ff92SAndroid Build Coastguard Worker }
4042*89c4ff92SAndroid Build Coastguard Worker
proximate(const path & p,const path & base)4043*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path proximate(const path& p, const path& base)
4044*89c4ff92SAndroid Build Coastguard Worker {
4045*89c4ff92SAndroid Build Coastguard Worker return weakly_canonical(p).lexically_proximate(weakly_canonical(base));
4046*89c4ff92SAndroid Build Coastguard Worker }
4047*89c4ff92SAndroid Build Coastguard Worker
proximate(const path & p,const path & base,std::error_code & ec)4048*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path proximate(const path& p, const path& base, std::error_code& ec)
4049*89c4ff92SAndroid Build Coastguard Worker {
4050*89c4ff92SAndroid Build Coastguard Worker return weakly_canonical(p, ec).lexically_proximate(weakly_canonical(base, ec));
4051*89c4ff92SAndroid Build Coastguard Worker }
4052*89c4ff92SAndroid Build Coastguard Worker
read_symlink(const path & p)4053*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path read_symlink(const path& p)
4054*89c4ff92SAndroid Build Coastguard Worker {
4055*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
4056*89c4ff92SAndroid Build Coastguard Worker auto result = read_symlink(p, ec);
4057*89c4ff92SAndroid Build Coastguard Worker if (ec) {
4058*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4059*89c4ff92SAndroid Build Coastguard Worker }
4060*89c4ff92SAndroid Build Coastguard Worker return result;
4061*89c4ff92SAndroid Build Coastguard Worker }
4062*89c4ff92SAndroid Build Coastguard Worker
read_symlink(const path & p,std::error_code & ec)4063*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path read_symlink(const path& p, std::error_code& ec)
4064*89c4ff92SAndroid Build Coastguard Worker {
4065*89c4ff92SAndroid Build Coastguard Worker file_status fs = symlink_status(p, ec);
4066*89c4ff92SAndroid Build Coastguard Worker if (fs.type() != file_type::symlink) {
4067*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_error_code(detail::portable_error::invalid_argument);
4068*89c4ff92SAndroid Build Coastguard Worker return path();
4069*89c4ff92SAndroid Build Coastguard Worker }
4070*89c4ff92SAndroid Build Coastguard Worker auto result = detail::resolveSymlink(p, ec);
4071*89c4ff92SAndroid Build Coastguard Worker return ec ? path() : result;
4072*89c4ff92SAndroid Build Coastguard Worker }
4073*89c4ff92SAndroid Build Coastguard Worker
relative(const path & p,std::error_code & ec)4074*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path relative(const path& p, std::error_code& ec)
4075*89c4ff92SAndroid Build Coastguard Worker {
4076*89c4ff92SAndroid Build Coastguard Worker return relative(p, current_path(ec), ec);
4077*89c4ff92SAndroid Build Coastguard Worker }
4078*89c4ff92SAndroid Build Coastguard Worker
relative(const path & p,const path & base)4079*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path relative(const path& p, const path& base)
4080*89c4ff92SAndroid Build Coastguard Worker {
4081*89c4ff92SAndroid Build Coastguard Worker return weakly_canonical(p).lexically_relative(weakly_canonical(base));
4082*89c4ff92SAndroid Build Coastguard Worker }
4083*89c4ff92SAndroid Build Coastguard Worker
relative(const path & p,const path & base,std::error_code & ec)4084*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path relative(const path& p, const path& base, std::error_code& ec)
4085*89c4ff92SAndroid Build Coastguard Worker {
4086*89c4ff92SAndroid Build Coastguard Worker return weakly_canonical(p, ec).lexically_relative(weakly_canonical(base, ec));
4087*89c4ff92SAndroid Build Coastguard Worker }
4088*89c4ff92SAndroid Build Coastguard Worker
remove(const path & p)4089*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool remove(const path& p)
4090*89c4ff92SAndroid Build Coastguard Worker {
4091*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
4092*89c4ff92SAndroid Build Coastguard Worker auto result = remove(p, ec);
4093*89c4ff92SAndroid Build Coastguard Worker if (ec) {
4094*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4095*89c4ff92SAndroid Build Coastguard Worker }
4096*89c4ff92SAndroid Build Coastguard Worker return result;
4097*89c4ff92SAndroid Build Coastguard Worker }
4098*89c4ff92SAndroid Build Coastguard Worker
remove(const path & p,std::error_code & ec)4099*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool remove(const path& p, std::error_code& ec) noexcept
4100*89c4ff92SAndroid Build Coastguard Worker {
4101*89c4ff92SAndroid Build Coastguard Worker ec.clear();
4102*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
4103*89c4ff92SAndroid Build Coastguard Worker std::wstring np = detail::fromUtf8<std::wstring>(p.u8string());
4104*89c4ff92SAndroid Build Coastguard Worker DWORD attr = GetFileAttributesW(np.c_str());
4105*89c4ff92SAndroid Build Coastguard Worker if (attr == INVALID_FILE_ATTRIBUTES) {
4106*89c4ff92SAndroid Build Coastguard Worker auto error = ::GetLastError();
4107*89c4ff92SAndroid Build Coastguard Worker if (error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND) {
4108*89c4ff92SAndroid Build Coastguard Worker return false;
4109*89c4ff92SAndroid Build Coastguard Worker }
4110*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error(error);
4111*89c4ff92SAndroid Build Coastguard Worker }
4112*89c4ff92SAndroid Build Coastguard Worker if (!ec) {
4113*89c4ff92SAndroid Build Coastguard Worker if (attr & FILE_ATTRIBUTE_DIRECTORY) {
4114*89c4ff92SAndroid Build Coastguard Worker if (!RemoveDirectoryW(np.c_str())) {
4115*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
4116*89c4ff92SAndroid Build Coastguard Worker }
4117*89c4ff92SAndroid Build Coastguard Worker }
4118*89c4ff92SAndroid Build Coastguard Worker else {
4119*89c4ff92SAndroid Build Coastguard Worker if (!DeleteFileW(np.c_str())) {
4120*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
4121*89c4ff92SAndroid Build Coastguard Worker }
4122*89c4ff92SAndroid Build Coastguard Worker }
4123*89c4ff92SAndroid Build Coastguard Worker }
4124*89c4ff92SAndroid Build Coastguard Worker #else
4125*89c4ff92SAndroid Build Coastguard Worker if (::remove(p.c_str()) == -1) {
4126*89c4ff92SAndroid Build Coastguard Worker auto error = errno;
4127*89c4ff92SAndroid Build Coastguard Worker if (error == ENOENT) {
4128*89c4ff92SAndroid Build Coastguard Worker return false;
4129*89c4ff92SAndroid Build Coastguard Worker }
4130*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
4131*89c4ff92SAndroid Build Coastguard Worker }
4132*89c4ff92SAndroid Build Coastguard Worker #endif
4133*89c4ff92SAndroid Build Coastguard Worker return ec ? false : true;
4134*89c4ff92SAndroid Build Coastguard Worker }
4135*89c4ff92SAndroid Build Coastguard Worker
remove_all(const path & p)4136*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE uintmax_t remove_all(const path& p)
4137*89c4ff92SAndroid Build Coastguard Worker {
4138*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
4139*89c4ff92SAndroid Build Coastguard Worker auto result = remove_all(p, ec);
4140*89c4ff92SAndroid Build Coastguard Worker if (ec) {
4141*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4142*89c4ff92SAndroid Build Coastguard Worker }
4143*89c4ff92SAndroid Build Coastguard Worker return result;
4144*89c4ff92SAndroid Build Coastguard Worker }
4145*89c4ff92SAndroid Build Coastguard Worker
remove_all(const path & p,std::error_code & ec)4146*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE uintmax_t remove_all(const path& p, std::error_code& ec) noexcept
4147*89c4ff92SAndroid Build Coastguard Worker {
4148*89c4ff92SAndroid Build Coastguard Worker ec.clear();
4149*89c4ff92SAndroid Build Coastguard Worker uintmax_t count = 0;
4150*89c4ff92SAndroid Build Coastguard Worker if (p == "/") {
4151*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_error_code(detail::portable_error::not_supported);
4152*89c4ff92SAndroid Build Coastguard Worker return static_cast<uintmax_t>(-1);
4153*89c4ff92SAndroid Build Coastguard Worker }
4154*89c4ff92SAndroid Build Coastguard Worker std::error_code tec;
4155*89c4ff92SAndroid Build Coastguard Worker auto fs = status(p, tec);
4156*89c4ff92SAndroid Build Coastguard Worker if (exists(fs) && is_directory(fs)) {
4157*89c4ff92SAndroid Build Coastguard Worker for (auto iter = directory_iterator(p, ec); iter != directory_iterator(); iter.increment(ec)) {
4158*89c4ff92SAndroid Build Coastguard Worker if (ec) {
4159*89c4ff92SAndroid Build Coastguard Worker break;
4160*89c4ff92SAndroid Build Coastguard Worker }
4161*89c4ff92SAndroid Build Coastguard Worker if (!iter->is_symlink() && iter->is_directory()) {
4162*89c4ff92SAndroid Build Coastguard Worker count += remove_all(iter->path(), ec);
4163*89c4ff92SAndroid Build Coastguard Worker if (ec) {
4164*89c4ff92SAndroid Build Coastguard Worker return static_cast<uintmax_t>(-1);
4165*89c4ff92SAndroid Build Coastguard Worker }
4166*89c4ff92SAndroid Build Coastguard Worker }
4167*89c4ff92SAndroid Build Coastguard Worker else {
4168*89c4ff92SAndroid Build Coastguard Worker remove(iter->path(), ec);
4169*89c4ff92SAndroid Build Coastguard Worker if (ec) {
4170*89c4ff92SAndroid Build Coastguard Worker return static_cast<uintmax_t>(-1);
4171*89c4ff92SAndroid Build Coastguard Worker }
4172*89c4ff92SAndroid Build Coastguard Worker ++count;
4173*89c4ff92SAndroid Build Coastguard Worker }
4174*89c4ff92SAndroid Build Coastguard Worker }
4175*89c4ff92SAndroid Build Coastguard Worker }
4176*89c4ff92SAndroid Build Coastguard Worker if (!ec) {
4177*89c4ff92SAndroid Build Coastguard Worker if (remove(p, ec)) {
4178*89c4ff92SAndroid Build Coastguard Worker ++count;
4179*89c4ff92SAndroid Build Coastguard Worker }
4180*89c4ff92SAndroid Build Coastguard Worker }
4181*89c4ff92SAndroid Build Coastguard Worker if (ec) {
4182*89c4ff92SAndroid Build Coastguard Worker return static_cast<uintmax_t>(-1);
4183*89c4ff92SAndroid Build Coastguard Worker }
4184*89c4ff92SAndroid Build Coastguard Worker return count;
4185*89c4ff92SAndroid Build Coastguard Worker }
4186*89c4ff92SAndroid Build Coastguard Worker
rename(const path & from,const path & to)4187*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void rename(const path& from, const path& to)
4188*89c4ff92SAndroid Build Coastguard Worker {
4189*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
4190*89c4ff92SAndroid Build Coastguard Worker rename(from, to, ec);
4191*89c4ff92SAndroid Build Coastguard Worker if (ec) {
4192*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), from, to, ec);
4193*89c4ff92SAndroid Build Coastguard Worker }
4194*89c4ff92SAndroid Build Coastguard Worker }
4195*89c4ff92SAndroid Build Coastguard Worker
rename(const path & from,const path & to,std::error_code & ec)4196*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void rename(const path& from, const path& to, std::error_code& ec) noexcept
4197*89c4ff92SAndroid Build Coastguard Worker {
4198*89c4ff92SAndroid Build Coastguard Worker ec.clear();
4199*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
4200*89c4ff92SAndroid Build Coastguard Worker if (from != to) {
4201*89c4ff92SAndroid Build Coastguard Worker if (!MoveFileExW(detail::fromUtf8<std::wstring>(from.u8string()).c_str(), detail::fromUtf8<std::wstring>(to.u8string()).c_str(), (DWORD)MOVEFILE_REPLACE_EXISTING)) {
4202*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
4203*89c4ff92SAndroid Build Coastguard Worker }
4204*89c4ff92SAndroid Build Coastguard Worker }
4205*89c4ff92SAndroid Build Coastguard Worker #else
4206*89c4ff92SAndroid Build Coastguard Worker if (from != to) {
4207*89c4ff92SAndroid Build Coastguard Worker if (::rename(from.c_str(), to.c_str()) != 0) {
4208*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
4209*89c4ff92SAndroid Build Coastguard Worker }
4210*89c4ff92SAndroid Build Coastguard Worker }
4211*89c4ff92SAndroid Build Coastguard Worker #endif
4212*89c4ff92SAndroid Build Coastguard Worker }
4213*89c4ff92SAndroid Build Coastguard Worker
resize_file(const path & p,uintmax_t size)4214*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void resize_file(const path& p, uintmax_t size)
4215*89c4ff92SAndroid Build Coastguard Worker {
4216*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
4217*89c4ff92SAndroid Build Coastguard Worker resize_file(p, size, ec);
4218*89c4ff92SAndroid Build Coastguard Worker if (ec) {
4219*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4220*89c4ff92SAndroid Build Coastguard Worker }
4221*89c4ff92SAndroid Build Coastguard Worker }
4222*89c4ff92SAndroid Build Coastguard Worker
resize_file(const path & p,uintmax_t size,std::error_code & ec)4223*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void resize_file(const path& p, uintmax_t size, std::error_code& ec) noexcept
4224*89c4ff92SAndroid Build Coastguard Worker {
4225*89c4ff92SAndroid Build Coastguard Worker ec.clear();
4226*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
4227*89c4ff92SAndroid Build Coastguard Worker LARGE_INTEGER lisize;
4228*89c4ff92SAndroid Build Coastguard Worker lisize.QuadPart = static_cast<LONGLONG>(size);
4229*89c4ff92SAndroid Build Coastguard Worker if(lisize.QuadPart < 0) {
4230*89c4ff92SAndroid Build Coastguard Worker #ifdef ERROR_FILE_TOO_LARGE
4231*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error(ERROR_FILE_TOO_LARGE);
4232*89c4ff92SAndroid Build Coastguard Worker #else
4233*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error(223);
4234*89c4ff92SAndroid Build Coastguard Worker #endif
4235*89c4ff92SAndroid Build Coastguard Worker return;
4236*89c4ff92SAndroid Build Coastguard Worker }
4237*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<void> file(CreateFileW(detail::fromUtf8<std::wstring>(p.u8string()).c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL), CloseHandle);
4238*89c4ff92SAndroid Build Coastguard Worker if (file.get() == INVALID_HANDLE_VALUE) {
4239*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
4240*89c4ff92SAndroid Build Coastguard Worker }
4241*89c4ff92SAndroid Build Coastguard Worker else if (SetFilePointerEx(file.get(), lisize, NULL, FILE_BEGIN) == 0 || SetEndOfFile(file.get()) == 0) {
4242*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
4243*89c4ff92SAndroid Build Coastguard Worker }
4244*89c4ff92SAndroid Build Coastguard Worker #else
4245*89c4ff92SAndroid Build Coastguard Worker if (::truncate(p.c_str(), static_cast<off_t>(size)) != 0) {
4246*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
4247*89c4ff92SAndroid Build Coastguard Worker }
4248*89c4ff92SAndroid Build Coastguard Worker #endif
4249*89c4ff92SAndroid Build Coastguard Worker }
4250*89c4ff92SAndroid Build Coastguard Worker
space(const path & p)4251*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE space_info space(const path& p)
4252*89c4ff92SAndroid Build Coastguard Worker {
4253*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
4254*89c4ff92SAndroid Build Coastguard Worker auto result = space(p, ec);
4255*89c4ff92SAndroid Build Coastguard Worker if (ec) {
4256*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4257*89c4ff92SAndroid Build Coastguard Worker }
4258*89c4ff92SAndroid Build Coastguard Worker return result;
4259*89c4ff92SAndroid Build Coastguard Worker }
4260*89c4ff92SAndroid Build Coastguard Worker
space(const path & p,std::error_code & ec)4261*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE space_info space(const path& p, std::error_code& ec) noexcept
4262*89c4ff92SAndroid Build Coastguard Worker {
4263*89c4ff92SAndroid Build Coastguard Worker ec.clear();
4264*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
4265*89c4ff92SAndroid Build Coastguard Worker ULARGE_INTEGER freeBytesAvailableToCaller = {0, 0};
4266*89c4ff92SAndroid Build Coastguard Worker ULARGE_INTEGER totalNumberOfBytes = {0, 0};
4267*89c4ff92SAndroid Build Coastguard Worker ULARGE_INTEGER totalNumberOfFreeBytes = {0, 0};
4268*89c4ff92SAndroid Build Coastguard Worker if (!GetDiskFreeSpaceExW(detail::fromUtf8<std::wstring>(p.u8string()).c_str(), &freeBytesAvailableToCaller, &totalNumberOfBytes, &totalNumberOfFreeBytes)) {
4269*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
4270*89c4ff92SAndroid Build Coastguard Worker return {static_cast<uintmax_t>(-1), static_cast<uintmax_t>(-1), static_cast<uintmax_t>(-1)};
4271*89c4ff92SAndroid Build Coastguard Worker }
4272*89c4ff92SAndroid Build Coastguard Worker return {static_cast<uintmax_t>(totalNumberOfBytes.QuadPart), static_cast<uintmax_t>(totalNumberOfFreeBytes.QuadPart), static_cast<uintmax_t>(freeBytesAvailableToCaller.QuadPart)};
4273*89c4ff92SAndroid Build Coastguard Worker #elif !defined(__ANDROID__) || __ANDROID_API__ >= 19
4274*89c4ff92SAndroid Build Coastguard Worker struct ::statvfs sfs;
4275*89c4ff92SAndroid Build Coastguard Worker if (::statvfs(p.c_str(), &sfs) != 0) {
4276*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
4277*89c4ff92SAndroid Build Coastguard Worker return {static_cast<uintmax_t>(-1), static_cast<uintmax_t>(-1), static_cast<uintmax_t>(-1)};
4278*89c4ff92SAndroid Build Coastguard Worker }
4279*89c4ff92SAndroid Build Coastguard Worker return {static_cast<uintmax_t>(sfs.f_blocks * sfs.f_frsize), static_cast<uintmax_t>(sfs.f_bfree * sfs.f_frsize), static_cast<uintmax_t>(sfs.f_bavail * sfs.f_frsize)};
4280*89c4ff92SAndroid Build Coastguard Worker #else
4281*89c4ff92SAndroid Build Coastguard Worker (void)p;
4282*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_error_code(detail::portable_error::not_supported);
4283*89c4ff92SAndroid Build Coastguard Worker return {static_cast<uintmax_t>(-1), static_cast<uintmax_t>(-1), static_cast<uintmax_t>(-1)};
4284*89c4ff92SAndroid Build Coastguard Worker #endif
4285*89c4ff92SAndroid Build Coastguard Worker }
4286*89c4ff92SAndroid Build Coastguard Worker
status(const path & p)4287*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_status status(const path& p)
4288*89c4ff92SAndroid Build Coastguard Worker {
4289*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
4290*89c4ff92SAndroid Build Coastguard Worker auto result = status(p, ec);
4291*89c4ff92SAndroid Build Coastguard Worker if (result.type() == file_type::none) {
4292*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4293*89c4ff92SAndroid Build Coastguard Worker }
4294*89c4ff92SAndroid Build Coastguard Worker return result;
4295*89c4ff92SAndroid Build Coastguard Worker }
4296*89c4ff92SAndroid Build Coastguard Worker
status(const path & p,std::error_code & ec)4297*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_status status(const path& p, std::error_code& ec) noexcept
4298*89c4ff92SAndroid Build Coastguard Worker {
4299*89c4ff92SAndroid Build Coastguard Worker return detail::status_ex(p, ec);
4300*89c4ff92SAndroid Build Coastguard Worker }
4301*89c4ff92SAndroid Build Coastguard Worker
status_known(file_status s)4302*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool status_known(file_status s) noexcept
4303*89c4ff92SAndroid Build Coastguard Worker {
4304*89c4ff92SAndroid Build Coastguard Worker return s.type() != file_type::none;
4305*89c4ff92SAndroid Build Coastguard Worker }
4306*89c4ff92SAndroid Build Coastguard Worker
symlink_status(const path & p)4307*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_status symlink_status(const path& p)
4308*89c4ff92SAndroid Build Coastguard Worker {
4309*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
4310*89c4ff92SAndroid Build Coastguard Worker auto result = symlink_status(p, ec);
4311*89c4ff92SAndroid Build Coastguard Worker if (result.type() == file_type::none) {
4312*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), ec);
4313*89c4ff92SAndroid Build Coastguard Worker }
4314*89c4ff92SAndroid Build Coastguard Worker return result;
4315*89c4ff92SAndroid Build Coastguard Worker }
4316*89c4ff92SAndroid Build Coastguard Worker
symlink_status(const path & p,std::error_code & ec)4317*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_status symlink_status(const path& p, std::error_code& ec) noexcept
4318*89c4ff92SAndroid Build Coastguard Worker {
4319*89c4ff92SAndroid Build Coastguard Worker return detail::symlink_status_ex(p, ec);
4320*89c4ff92SAndroid Build Coastguard Worker }
4321*89c4ff92SAndroid Build Coastguard Worker
temp_directory_path()4322*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path temp_directory_path()
4323*89c4ff92SAndroid Build Coastguard Worker {
4324*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
4325*89c4ff92SAndroid Build Coastguard Worker path result = temp_directory_path(ec);
4326*89c4ff92SAndroid Build Coastguard Worker if (ec) {
4327*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), ec);
4328*89c4ff92SAndroid Build Coastguard Worker }
4329*89c4ff92SAndroid Build Coastguard Worker return result;
4330*89c4ff92SAndroid Build Coastguard Worker }
4331*89c4ff92SAndroid Build Coastguard Worker
temp_directory_path(std::error_code & ec)4332*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path temp_directory_path(std::error_code& ec) noexcept
4333*89c4ff92SAndroid Build Coastguard Worker {
4334*89c4ff92SAndroid Build Coastguard Worker ec.clear();
4335*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
4336*89c4ff92SAndroid Build Coastguard Worker wchar_t buffer[512];
4337*89c4ff92SAndroid Build Coastguard Worker auto rc = GetTempPathW(511, buffer);
4338*89c4ff92SAndroid Build Coastguard Worker if (!rc || rc > 511) {
4339*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
4340*89c4ff92SAndroid Build Coastguard Worker return path();
4341*89c4ff92SAndroid Build Coastguard Worker }
4342*89c4ff92SAndroid Build Coastguard Worker return path(std::wstring(buffer));
4343*89c4ff92SAndroid Build Coastguard Worker #else
4344*89c4ff92SAndroid Build Coastguard Worker static const char* temp_vars[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR", nullptr};
4345*89c4ff92SAndroid Build Coastguard Worker const char* temp_path = nullptr;
4346*89c4ff92SAndroid Build Coastguard Worker for (auto temp_name = temp_vars; *temp_name != nullptr; ++temp_name) {
4347*89c4ff92SAndroid Build Coastguard Worker temp_path = std::getenv(*temp_name);
4348*89c4ff92SAndroid Build Coastguard Worker if (temp_path) {
4349*89c4ff92SAndroid Build Coastguard Worker return path(temp_path);
4350*89c4ff92SAndroid Build Coastguard Worker }
4351*89c4ff92SAndroid Build Coastguard Worker }
4352*89c4ff92SAndroid Build Coastguard Worker return path("/tmp");
4353*89c4ff92SAndroid Build Coastguard Worker #endif
4354*89c4ff92SAndroid Build Coastguard Worker }
4355*89c4ff92SAndroid Build Coastguard Worker
weakly_canonical(const path & p)4356*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path weakly_canonical(const path& p)
4357*89c4ff92SAndroid Build Coastguard Worker {
4358*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
4359*89c4ff92SAndroid Build Coastguard Worker auto result = weakly_canonical(p, ec);
4360*89c4ff92SAndroid Build Coastguard Worker if (ec) {
4361*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4362*89c4ff92SAndroid Build Coastguard Worker }
4363*89c4ff92SAndroid Build Coastguard Worker return result;
4364*89c4ff92SAndroid Build Coastguard Worker }
4365*89c4ff92SAndroid Build Coastguard Worker
weakly_canonical(const path & p,std::error_code & ec)4366*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE path weakly_canonical(const path& p, std::error_code& ec) noexcept
4367*89c4ff92SAndroid Build Coastguard Worker {
4368*89c4ff92SAndroid Build Coastguard Worker path result;
4369*89c4ff92SAndroid Build Coastguard Worker ec.clear();
4370*89c4ff92SAndroid Build Coastguard Worker bool scan = true;
4371*89c4ff92SAndroid Build Coastguard Worker for (auto pe : p) {
4372*89c4ff92SAndroid Build Coastguard Worker if (scan) {
4373*89c4ff92SAndroid Build Coastguard Worker std::error_code tec;
4374*89c4ff92SAndroid Build Coastguard Worker if (exists(result / pe, tec)) {
4375*89c4ff92SAndroid Build Coastguard Worker result /= pe;
4376*89c4ff92SAndroid Build Coastguard Worker }
4377*89c4ff92SAndroid Build Coastguard Worker else {
4378*89c4ff92SAndroid Build Coastguard Worker if (ec) {
4379*89c4ff92SAndroid Build Coastguard Worker return path();
4380*89c4ff92SAndroid Build Coastguard Worker }
4381*89c4ff92SAndroid Build Coastguard Worker scan = false;
4382*89c4ff92SAndroid Build Coastguard Worker if (!result.empty()) {
4383*89c4ff92SAndroid Build Coastguard Worker result = canonical(result, ec) / pe;
4384*89c4ff92SAndroid Build Coastguard Worker if (ec) {
4385*89c4ff92SAndroid Build Coastguard Worker break;
4386*89c4ff92SAndroid Build Coastguard Worker }
4387*89c4ff92SAndroid Build Coastguard Worker }
4388*89c4ff92SAndroid Build Coastguard Worker else {
4389*89c4ff92SAndroid Build Coastguard Worker result /= pe;
4390*89c4ff92SAndroid Build Coastguard Worker }
4391*89c4ff92SAndroid Build Coastguard Worker }
4392*89c4ff92SAndroid Build Coastguard Worker }
4393*89c4ff92SAndroid Build Coastguard Worker else {
4394*89c4ff92SAndroid Build Coastguard Worker result /= pe;
4395*89c4ff92SAndroid Build Coastguard Worker }
4396*89c4ff92SAndroid Build Coastguard Worker }
4397*89c4ff92SAndroid Build Coastguard Worker if (scan) {
4398*89c4ff92SAndroid Build Coastguard Worker if (!result.empty()) {
4399*89c4ff92SAndroid Build Coastguard Worker result = canonical(result, ec);
4400*89c4ff92SAndroid Build Coastguard Worker }
4401*89c4ff92SAndroid Build Coastguard Worker }
4402*89c4ff92SAndroid Build Coastguard Worker return ec ? path() : result.lexically_normal();
4403*89c4ff92SAndroid Build Coastguard Worker }
4404*89c4ff92SAndroid Build Coastguard Worker
4405*89c4ff92SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
4406*89c4ff92SAndroid Build Coastguard Worker // 30.10.11 class file_status
4407*89c4ff92SAndroid Build Coastguard Worker // 30.10.11.1 constructors and destructor
file_status()4408*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_status::file_status() noexcept
4409*89c4ff92SAndroid Build Coastguard Worker : file_status(file_type::none)
4410*89c4ff92SAndroid Build Coastguard Worker {
4411*89c4ff92SAndroid Build Coastguard Worker }
4412*89c4ff92SAndroid Build Coastguard Worker
file_status(file_type ft,perms prms)4413*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_status::file_status(file_type ft, perms prms) noexcept
4414*89c4ff92SAndroid Build Coastguard Worker : _type(ft)
4415*89c4ff92SAndroid Build Coastguard Worker , _perms(prms)
4416*89c4ff92SAndroid Build Coastguard Worker {
4417*89c4ff92SAndroid Build Coastguard Worker }
4418*89c4ff92SAndroid Build Coastguard Worker
file_status(const file_status & other)4419*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_status::file_status(const file_status& other) noexcept
4420*89c4ff92SAndroid Build Coastguard Worker : _type(other._type)
4421*89c4ff92SAndroid Build Coastguard Worker , _perms(other._perms)
4422*89c4ff92SAndroid Build Coastguard Worker {
4423*89c4ff92SAndroid Build Coastguard Worker }
4424*89c4ff92SAndroid Build Coastguard Worker
file_status(file_status && other)4425*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_status::file_status(file_status&& other) noexcept
4426*89c4ff92SAndroid Build Coastguard Worker : _type(other._type)
4427*89c4ff92SAndroid Build Coastguard Worker , _perms(other._perms)
4428*89c4ff92SAndroid Build Coastguard Worker {
4429*89c4ff92SAndroid Build Coastguard Worker }
4430*89c4ff92SAndroid Build Coastguard Worker
~file_status()4431*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_status::~file_status() {}
4432*89c4ff92SAndroid Build Coastguard Worker
4433*89c4ff92SAndroid Build Coastguard Worker // assignments:
operator =(const file_status & rhs)4434*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_status& file_status::operator=(const file_status& rhs) noexcept
4435*89c4ff92SAndroid Build Coastguard Worker {
4436*89c4ff92SAndroid Build Coastguard Worker _type = rhs._type;
4437*89c4ff92SAndroid Build Coastguard Worker _perms = rhs._perms;
4438*89c4ff92SAndroid Build Coastguard Worker return *this;
4439*89c4ff92SAndroid Build Coastguard Worker }
4440*89c4ff92SAndroid Build Coastguard Worker
operator =(file_status && rhs)4441*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_status& file_status::operator=(file_status&& rhs) noexcept
4442*89c4ff92SAndroid Build Coastguard Worker {
4443*89c4ff92SAndroid Build Coastguard Worker _type = rhs._type;
4444*89c4ff92SAndroid Build Coastguard Worker _perms = rhs._perms;
4445*89c4ff92SAndroid Build Coastguard Worker return *this;
4446*89c4ff92SAndroid Build Coastguard Worker }
4447*89c4ff92SAndroid Build Coastguard Worker
4448*89c4ff92SAndroid Build Coastguard Worker // 30.10.11.3 modifiers
type(file_type ft)4449*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void file_status::type(file_type ft) noexcept
4450*89c4ff92SAndroid Build Coastguard Worker {
4451*89c4ff92SAndroid Build Coastguard Worker _type = ft;
4452*89c4ff92SAndroid Build Coastguard Worker }
4453*89c4ff92SAndroid Build Coastguard Worker
permissions(perms prms)4454*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void file_status::permissions(perms prms) noexcept
4455*89c4ff92SAndroid Build Coastguard Worker {
4456*89c4ff92SAndroid Build Coastguard Worker _perms = prms;
4457*89c4ff92SAndroid Build Coastguard Worker }
4458*89c4ff92SAndroid Build Coastguard Worker
4459*89c4ff92SAndroid Build Coastguard Worker // 30.10.11.2 observers
type() const4460*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_type file_status::type() const noexcept
4461*89c4ff92SAndroid Build Coastguard Worker {
4462*89c4ff92SAndroid Build Coastguard Worker return _type;
4463*89c4ff92SAndroid Build Coastguard Worker }
4464*89c4ff92SAndroid Build Coastguard Worker
permissions() const4465*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE perms file_status::permissions() const noexcept
4466*89c4ff92SAndroid Build Coastguard Worker {
4467*89c4ff92SAndroid Build Coastguard Worker return _perms;
4468*89c4ff92SAndroid Build Coastguard Worker }
4469*89c4ff92SAndroid Build Coastguard Worker
4470*89c4ff92SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
4471*89c4ff92SAndroid Build Coastguard Worker // 30.10.12 class directory_entry
4472*89c4ff92SAndroid Build Coastguard Worker // 30.10.12.1 constructors and destructor
4473*89c4ff92SAndroid Build Coastguard Worker // directory_entry::directory_entry() noexcept = default;
4474*89c4ff92SAndroid Build Coastguard Worker // directory_entry::directory_entry(const directory_entry&) = default;
4475*89c4ff92SAndroid Build Coastguard Worker // directory_entry::directory_entry(directory_entry&&) noexcept = default;
directory_entry(const filesystem::path & p)4476*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE directory_entry::directory_entry(const filesystem::path& p)
4477*89c4ff92SAndroid Build Coastguard Worker : _path(p)
4478*89c4ff92SAndroid Build Coastguard Worker , _file_size(0)
4479*89c4ff92SAndroid Build Coastguard Worker #ifndef GHC_OS_WINDOWS
4480*89c4ff92SAndroid Build Coastguard Worker , _hard_link_count(0)
4481*89c4ff92SAndroid Build Coastguard Worker #endif
4482*89c4ff92SAndroid Build Coastguard Worker , _last_write_time(0)
4483*89c4ff92SAndroid Build Coastguard Worker {
4484*89c4ff92SAndroid Build Coastguard Worker refresh();
4485*89c4ff92SAndroid Build Coastguard Worker }
4486*89c4ff92SAndroid Build Coastguard Worker
directory_entry(const filesystem::path & p,std::error_code & ec)4487*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE directory_entry::directory_entry(const filesystem::path& p, std::error_code& ec)
4488*89c4ff92SAndroid Build Coastguard Worker : _path(p)
4489*89c4ff92SAndroid Build Coastguard Worker , _file_size(0)
4490*89c4ff92SAndroid Build Coastguard Worker #ifndef GHC_OS_WINDOWS
4491*89c4ff92SAndroid Build Coastguard Worker , _hard_link_count(0)
4492*89c4ff92SAndroid Build Coastguard Worker #endif
4493*89c4ff92SAndroid Build Coastguard Worker , _last_write_time(0)
4494*89c4ff92SAndroid Build Coastguard Worker {
4495*89c4ff92SAndroid Build Coastguard Worker refresh(ec);
4496*89c4ff92SAndroid Build Coastguard Worker }
4497*89c4ff92SAndroid Build Coastguard Worker
~directory_entry()4498*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE directory_entry::~directory_entry() {}
4499*89c4ff92SAndroid Build Coastguard Worker
4500*89c4ff92SAndroid Build Coastguard Worker // assignments:
4501*89c4ff92SAndroid Build Coastguard Worker // directory_entry& directory_entry::operator=(const directory_entry&) = default;
4502*89c4ff92SAndroid Build Coastguard Worker // directory_entry& directory_entry::operator=(directory_entry&&) noexcept = default;
4503*89c4ff92SAndroid Build Coastguard Worker
4504*89c4ff92SAndroid Build Coastguard Worker // 30.10.12.2 directory_entry modifiers
assign(const filesystem::path & p)4505*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void directory_entry::assign(const filesystem::path& p)
4506*89c4ff92SAndroid Build Coastguard Worker {
4507*89c4ff92SAndroid Build Coastguard Worker _path = p;
4508*89c4ff92SAndroid Build Coastguard Worker refresh();
4509*89c4ff92SAndroid Build Coastguard Worker }
4510*89c4ff92SAndroid Build Coastguard Worker
assign(const filesystem::path & p,std::error_code & ec)4511*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void directory_entry::assign(const filesystem::path& p, std::error_code& ec)
4512*89c4ff92SAndroid Build Coastguard Worker {
4513*89c4ff92SAndroid Build Coastguard Worker _path = p;
4514*89c4ff92SAndroid Build Coastguard Worker refresh(ec);
4515*89c4ff92SAndroid Build Coastguard Worker }
4516*89c4ff92SAndroid Build Coastguard Worker
replace_filename(const filesystem::path & p)4517*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void directory_entry::replace_filename(const filesystem::path& p)
4518*89c4ff92SAndroid Build Coastguard Worker {
4519*89c4ff92SAndroid Build Coastguard Worker _path.replace_filename(p);
4520*89c4ff92SAndroid Build Coastguard Worker refresh();
4521*89c4ff92SAndroid Build Coastguard Worker }
4522*89c4ff92SAndroid Build Coastguard Worker
replace_filename(const filesystem::path & p,std::error_code & ec)4523*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void directory_entry::replace_filename(const filesystem::path& p, std::error_code& ec)
4524*89c4ff92SAndroid Build Coastguard Worker {
4525*89c4ff92SAndroid Build Coastguard Worker _path.replace_filename(p);
4526*89c4ff92SAndroid Build Coastguard Worker refresh(ec);
4527*89c4ff92SAndroid Build Coastguard Worker }
4528*89c4ff92SAndroid Build Coastguard Worker
refresh()4529*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void directory_entry::refresh()
4530*89c4ff92SAndroid Build Coastguard Worker {
4531*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
4532*89c4ff92SAndroid Build Coastguard Worker refresh(ec);
4533*89c4ff92SAndroid Build Coastguard Worker if (ec) {
4534*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), _path, ec);
4535*89c4ff92SAndroid Build Coastguard Worker }
4536*89c4ff92SAndroid Build Coastguard Worker }
4537*89c4ff92SAndroid Build Coastguard Worker
refresh(std::error_code & ec)4538*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void directory_entry::refresh(std::error_code& ec) noexcept
4539*89c4ff92SAndroid Build Coastguard Worker {
4540*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
4541*89c4ff92SAndroid Build Coastguard Worker _status = detail::status_ex(_path, ec, &_symlink_status, &_file_size, nullptr, &_last_write_time);
4542*89c4ff92SAndroid Build Coastguard Worker #else
4543*89c4ff92SAndroid Build Coastguard Worker _status = detail::status_ex(_path, ec, &_symlink_status, &_file_size, &_hard_link_count, &_last_write_time);
4544*89c4ff92SAndroid Build Coastguard Worker #endif
4545*89c4ff92SAndroid Build Coastguard Worker }
4546*89c4ff92SAndroid Build Coastguard Worker
4547*89c4ff92SAndroid Build Coastguard Worker // 30.10.12.3 directory_entry observers
path() const4548*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE const filesystem::path& directory_entry::path() const noexcept
4549*89c4ff92SAndroid Build Coastguard Worker {
4550*89c4ff92SAndroid Build Coastguard Worker return _path;
4551*89c4ff92SAndroid Build Coastguard Worker }
4552*89c4ff92SAndroid Build Coastguard Worker
operator const filesystem::path&() const4553*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE directory_entry::operator const filesystem::path&() const noexcept
4554*89c4ff92SAndroid Build Coastguard Worker {
4555*89c4ff92SAndroid Build Coastguard Worker return _path;
4556*89c4ff92SAndroid Build Coastguard Worker }
4557*89c4ff92SAndroid Build Coastguard Worker
exists() const4558*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::exists() const
4559*89c4ff92SAndroid Build Coastguard Worker {
4560*89c4ff92SAndroid Build Coastguard Worker return filesystem::exists(status());
4561*89c4ff92SAndroid Build Coastguard Worker }
4562*89c4ff92SAndroid Build Coastguard Worker
exists(std::error_code & ec) const4563*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::exists(std::error_code& ec) const noexcept
4564*89c4ff92SAndroid Build Coastguard Worker {
4565*89c4ff92SAndroid Build Coastguard Worker return filesystem::exists(status(ec));
4566*89c4ff92SAndroid Build Coastguard Worker }
4567*89c4ff92SAndroid Build Coastguard Worker
is_block_file() const4568*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::is_block_file() const
4569*89c4ff92SAndroid Build Coastguard Worker {
4570*89c4ff92SAndroid Build Coastguard Worker return filesystem::is_block_file(status());
4571*89c4ff92SAndroid Build Coastguard Worker }
is_block_file(std::error_code & ec) const4572*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::is_block_file(std::error_code& ec) const noexcept
4573*89c4ff92SAndroid Build Coastguard Worker {
4574*89c4ff92SAndroid Build Coastguard Worker return filesystem::is_block_file(status(ec));
4575*89c4ff92SAndroid Build Coastguard Worker }
4576*89c4ff92SAndroid Build Coastguard Worker
is_character_file() const4577*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::is_character_file() const
4578*89c4ff92SAndroid Build Coastguard Worker {
4579*89c4ff92SAndroid Build Coastguard Worker return filesystem::is_character_file(status());
4580*89c4ff92SAndroid Build Coastguard Worker }
4581*89c4ff92SAndroid Build Coastguard Worker
is_character_file(std::error_code & ec) const4582*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::is_character_file(std::error_code& ec) const noexcept
4583*89c4ff92SAndroid Build Coastguard Worker {
4584*89c4ff92SAndroid Build Coastguard Worker return filesystem::is_character_file(status(ec));
4585*89c4ff92SAndroid Build Coastguard Worker }
4586*89c4ff92SAndroid Build Coastguard Worker
is_directory() const4587*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::is_directory() const
4588*89c4ff92SAndroid Build Coastguard Worker {
4589*89c4ff92SAndroid Build Coastguard Worker return filesystem::is_directory(status());
4590*89c4ff92SAndroid Build Coastguard Worker }
4591*89c4ff92SAndroid Build Coastguard Worker
is_directory(std::error_code & ec) const4592*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::is_directory(std::error_code& ec) const noexcept
4593*89c4ff92SAndroid Build Coastguard Worker {
4594*89c4ff92SAndroid Build Coastguard Worker return filesystem::is_directory(status(ec));
4595*89c4ff92SAndroid Build Coastguard Worker }
4596*89c4ff92SAndroid Build Coastguard Worker
is_fifo() const4597*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::is_fifo() const
4598*89c4ff92SAndroid Build Coastguard Worker {
4599*89c4ff92SAndroid Build Coastguard Worker return filesystem::is_fifo(status());
4600*89c4ff92SAndroid Build Coastguard Worker }
4601*89c4ff92SAndroid Build Coastguard Worker
is_fifo(std::error_code & ec) const4602*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::is_fifo(std::error_code& ec) const noexcept
4603*89c4ff92SAndroid Build Coastguard Worker {
4604*89c4ff92SAndroid Build Coastguard Worker return filesystem::is_fifo(status(ec));
4605*89c4ff92SAndroid Build Coastguard Worker }
4606*89c4ff92SAndroid Build Coastguard Worker
is_other() const4607*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::is_other() const
4608*89c4ff92SAndroid Build Coastguard Worker {
4609*89c4ff92SAndroid Build Coastguard Worker return filesystem::is_other(status());
4610*89c4ff92SAndroid Build Coastguard Worker }
4611*89c4ff92SAndroid Build Coastguard Worker
is_other(std::error_code & ec) const4612*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::is_other(std::error_code& ec) const noexcept
4613*89c4ff92SAndroid Build Coastguard Worker {
4614*89c4ff92SAndroid Build Coastguard Worker return filesystem::is_other(status(ec));
4615*89c4ff92SAndroid Build Coastguard Worker }
4616*89c4ff92SAndroid Build Coastguard Worker
is_regular_file() const4617*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::is_regular_file() const
4618*89c4ff92SAndroid Build Coastguard Worker {
4619*89c4ff92SAndroid Build Coastguard Worker return filesystem::is_regular_file(status());
4620*89c4ff92SAndroid Build Coastguard Worker }
4621*89c4ff92SAndroid Build Coastguard Worker
is_regular_file(std::error_code & ec) const4622*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::is_regular_file(std::error_code& ec) const noexcept
4623*89c4ff92SAndroid Build Coastguard Worker {
4624*89c4ff92SAndroid Build Coastguard Worker return filesystem::is_regular_file(status(ec));
4625*89c4ff92SAndroid Build Coastguard Worker }
4626*89c4ff92SAndroid Build Coastguard Worker
is_socket() const4627*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::is_socket() const
4628*89c4ff92SAndroid Build Coastguard Worker {
4629*89c4ff92SAndroid Build Coastguard Worker return filesystem::is_socket(status());
4630*89c4ff92SAndroid Build Coastguard Worker }
4631*89c4ff92SAndroid Build Coastguard Worker
is_socket(std::error_code & ec) const4632*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::is_socket(std::error_code& ec) const noexcept
4633*89c4ff92SAndroid Build Coastguard Worker {
4634*89c4ff92SAndroid Build Coastguard Worker return filesystem::is_socket(status(ec));
4635*89c4ff92SAndroid Build Coastguard Worker }
4636*89c4ff92SAndroid Build Coastguard Worker
is_symlink() const4637*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::is_symlink() const
4638*89c4ff92SAndroid Build Coastguard Worker {
4639*89c4ff92SAndroid Build Coastguard Worker return filesystem::is_symlink(symlink_status());
4640*89c4ff92SAndroid Build Coastguard Worker }
4641*89c4ff92SAndroid Build Coastguard Worker
is_symlink(std::error_code & ec) const4642*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::is_symlink(std::error_code& ec) const noexcept
4643*89c4ff92SAndroid Build Coastguard Worker {
4644*89c4ff92SAndroid Build Coastguard Worker return filesystem::is_symlink(symlink_status(ec));
4645*89c4ff92SAndroid Build Coastguard Worker }
4646*89c4ff92SAndroid Build Coastguard Worker
file_size() const4647*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE uintmax_t directory_entry::file_size() const
4648*89c4ff92SAndroid Build Coastguard Worker {
4649*89c4ff92SAndroid Build Coastguard Worker if (_status.type() != file_type::none) {
4650*89c4ff92SAndroid Build Coastguard Worker return _file_size;
4651*89c4ff92SAndroid Build Coastguard Worker }
4652*89c4ff92SAndroid Build Coastguard Worker return filesystem::file_size(path());
4653*89c4ff92SAndroid Build Coastguard Worker }
4654*89c4ff92SAndroid Build Coastguard Worker
file_size(std::error_code & ec) const4655*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE uintmax_t directory_entry::file_size(std::error_code& ec) const noexcept
4656*89c4ff92SAndroid Build Coastguard Worker {
4657*89c4ff92SAndroid Build Coastguard Worker if (_status.type() != file_type::none) {
4658*89c4ff92SAndroid Build Coastguard Worker ec.clear();
4659*89c4ff92SAndroid Build Coastguard Worker return _file_size;
4660*89c4ff92SAndroid Build Coastguard Worker }
4661*89c4ff92SAndroid Build Coastguard Worker return filesystem::file_size(path(), ec);
4662*89c4ff92SAndroid Build Coastguard Worker }
4663*89c4ff92SAndroid Build Coastguard Worker
hard_link_count() const4664*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE uintmax_t directory_entry::hard_link_count() const
4665*89c4ff92SAndroid Build Coastguard Worker {
4666*89c4ff92SAndroid Build Coastguard Worker #ifndef GHC_OS_WINDOWS
4667*89c4ff92SAndroid Build Coastguard Worker if (_status.type() != file_type::none) {
4668*89c4ff92SAndroid Build Coastguard Worker return _hard_link_count;
4669*89c4ff92SAndroid Build Coastguard Worker }
4670*89c4ff92SAndroid Build Coastguard Worker #endif
4671*89c4ff92SAndroid Build Coastguard Worker return filesystem::hard_link_count(path());
4672*89c4ff92SAndroid Build Coastguard Worker }
4673*89c4ff92SAndroid Build Coastguard Worker
hard_link_count(std::error_code & ec) const4674*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE uintmax_t directory_entry::hard_link_count(std::error_code& ec) const noexcept
4675*89c4ff92SAndroid Build Coastguard Worker {
4676*89c4ff92SAndroid Build Coastguard Worker #ifndef GHC_OS_WINDOWS
4677*89c4ff92SAndroid Build Coastguard Worker if (_status.type() != file_type::none) {
4678*89c4ff92SAndroid Build Coastguard Worker ec.clear();
4679*89c4ff92SAndroid Build Coastguard Worker return _hard_link_count;
4680*89c4ff92SAndroid Build Coastguard Worker }
4681*89c4ff92SAndroid Build Coastguard Worker #endif
4682*89c4ff92SAndroid Build Coastguard Worker return filesystem::hard_link_count(path(), ec);
4683*89c4ff92SAndroid Build Coastguard Worker }
4684*89c4ff92SAndroid Build Coastguard Worker
last_write_time() const4685*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_time_type directory_entry::last_write_time() const
4686*89c4ff92SAndroid Build Coastguard Worker {
4687*89c4ff92SAndroid Build Coastguard Worker if (_status.type() != file_type::none) {
4688*89c4ff92SAndroid Build Coastguard Worker return std::chrono::system_clock::from_time_t(_last_write_time);
4689*89c4ff92SAndroid Build Coastguard Worker }
4690*89c4ff92SAndroid Build Coastguard Worker return filesystem::last_write_time(path());
4691*89c4ff92SAndroid Build Coastguard Worker }
4692*89c4ff92SAndroid Build Coastguard Worker
last_write_time(std::error_code & ec) const4693*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_time_type directory_entry::last_write_time(std::error_code& ec) const noexcept
4694*89c4ff92SAndroid Build Coastguard Worker {
4695*89c4ff92SAndroid Build Coastguard Worker if (_status.type() != file_type::none) {
4696*89c4ff92SAndroid Build Coastguard Worker ec.clear();
4697*89c4ff92SAndroid Build Coastguard Worker return std::chrono::system_clock::from_time_t(_last_write_time);
4698*89c4ff92SAndroid Build Coastguard Worker }
4699*89c4ff92SAndroid Build Coastguard Worker return filesystem::last_write_time(path(), ec);
4700*89c4ff92SAndroid Build Coastguard Worker }
4701*89c4ff92SAndroid Build Coastguard Worker
status() const4702*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_status directory_entry::status() const
4703*89c4ff92SAndroid Build Coastguard Worker {
4704*89c4ff92SAndroid Build Coastguard Worker if (_status.type() != file_type::none) {
4705*89c4ff92SAndroid Build Coastguard Worker return _status;
4706*89c4ff92SAndroid Build Coastguard Worker }
4707*89c4ff92SAndroid Build Coastguard Worker return filesystem::status(path());
4708*89c4ff92SAndroid Build Coastguard Worker }
4709*89c4ff92SAndroid Build Coastguard Worker
status(std::error_code & ec) const4710*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_status directory_entry::status(std::error_code& ec) const noexcept
4711*89c4ff92SAndroid Build Coastguard Worker {
4712*89c4ff92SAndroid Build Coastguard Worker if (_status.type() != file_type::none) {
4713*89c4ff92SAndroid Build Coastguard Worker ec.clear();
4714*89c4ff92SAndroid Build Coastguard Worker return _status;
4715*89c4ff92SAndroid Build Coastguard Worker }
4716*89c4ff92SAndroid Build Coastguard Worker return filesystem::status(path(), ec);
4717*89c4ff92SAndroid Build Coastguard Worker }
4718*89c4ff92SAndroid Build Coastguard Worker
symlink_status() const4719*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_status directory_entry::symlink_status() const
4720*89c4ff92SAndroid Build Coastguard Worker {
4721*89c4ff92SAndroid Build Coastguard Worker if (_symlink_status.type() != file_type::none) {
4722*89c4ff92SAndroid Build Coastguard Worker return _symlink_status;
4723*89c4ff92SAndroid Build Coastguard Worker }
4724*89c4ff92SAndroid Build Coastguard Worker return filesystem::symlink_status(path());
4725*89c4ff92SAndroid Build Coastguard Worker }
4726*89c4ff92SAndroid Build Coastguard Worker
symlink_status(std::error_code & ec) const4727*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE file_status directory_entry::symlink_status(std::error_code& ec) const noexcept
4728*89c4ff92SAndroid Build Coastguard Worker {
4729*89c4ff92SAndroid Build Coastguard Worker if (_symlink_status.type() != file_type::none) {
4730*89c4ff92SAndroid Build Coastguard Worker ec.clear();
4731*89c4ff92SAndroid Build Coastguard Worker return _symlink_status;
4732*89c4ff92SAndroid Build Coastguard Worker }
4733*89c4ff92SAndroid Build Coastguard Worker return filesystem::symlink_status(path(), ec);
4734*89c4ff92SAndroid Build Coastguard Worker }
4735*89c4ff92SAndroid Build Coastguard Worker
operator <(const directory_entry & rhs) const4736*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::operator<(const directory_entry& rhs) const noexcept
4737*89c4ff92SAndroid Build Coastguard Worker {
4738*89c4ff92SAndroid Build Coastguard Worker return _path < rhs._path;
4739*89c4ff92SAndroid Build Coastguard Worker }
4740*89c4ff92SAndroid Build Coastguard Worker
operator ==(const directory_entry & rhs) const4741*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::operator==(const directory_entry& rhs) const noexcept
4742*89c4ff92SAndroid Build Coastguard Worker {
4743*89c4ff92SAndroid Build Coastguard Worker return _path == rhs._path;
4744*89c4ff92SAndroid Build Coastguard Worker }
4745*89c4ff92SAndroid Build Coastguard Worker
operator !=(const directory_entry & rhs) const4746*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::operator!=(const directory_entry& rhs) const noexcept
4747*89c4ff92SAndroid Build Coastguard Worker {
4748*89c4ff92SAndroid Build Coastguard Worker return _path != rhs._path;
4749*89c4ff92SAndroid Build Coastguard Worker }
4750*89c4ff92SAndroid Build Coastguard Worker
operator <=(const directory_entry & rhs) const4751*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::operator<=(const directory_entry& rhs) const noexcept
4752*89c4ff92SAndroid Build Coastguard Worker {
4753*89c4ff92SAndroid Build Coastguard Worker return _path <= rhs._path;
4754*89c4ff92SAndroid Build Coastguard Worker }
4755*89c4ff92SAndroid Build Coastguard Worker
operator >(const directory_entry & rhs) const4756*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::operator>(const directory_entry& rhs) const noexcept
4757*89c4ff92SAndroid Build Coastguard Worker {
4758*89c4ff92SAndroid Build Coastguard Worker return _path > rhs._path;
4759*89c4ff92SAndroid Build Coastguard Worker }
4760*89c4ff92SAndroid Build Coastguard Worker
operator >=(const directory_entry & rhs) const4761*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_entry::operator>=(const directory_entry& rhs) const noexcept
4762*89c4ff92SAndroid Build Coastguard Worker {
4763*89c4ff92SAndroid Build Coastguard Worker return _path >= rhs._path;
4764*89c4ff92SAndroid Build Coastguard Worker }
4765*89c4ff92SAndroid Build Coastguard Worker
4766*89c4ff92SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
4767*89c4ff92SAndroid Build Coastguard Worker // 30.10.13 class directory_iterator
4768*89c4ff92SAndroid Build Coastguard Worker
4769*89c4ff92SAndroid Build Coastguard Worker #ifdef GHC_OS_WINDOWS
4770*89c4ff92SAndroid Build Coastguard Worker class directory_iterator::impl
4771*89c4ff92SAndroid Build Coastguard Worker {
4772*89c4ff92SAndroid Build Coastguard Worker public:
impl(const path & p,directory_options options)4773*89c4ff92SAndroid Build Coastguard Worker impl(const path& p, directory_options options)
4774*89c4ff92SAndroid Build Coastguard Worker : _base(p)
4775*89c4ff92SAndroid Build Coastguard Worker , _options(options)
4776*89c4ff92SAndroid Build Coastguard Worker , _dirHandle(INVALID_HANDLE_VALUE)
4777*89c4ff92SAndroid Build Coastguard Worker {
4778*89c4ff92SAndroid Build Coastguard Worker if (!_base.empty()) {
4779*89c4ff92SAndroid Build Coastguard Worker ZeroMemory(&_findData, sizeof(WIN32_FIND_DATAW));
4780*89c4ff92SAndroid Build Coastguard Worker if ((_dirHandle = FindFirstFileW(detail::fromUtf8<std::wstring>((_base / "*").u8string()).c_str(), &_findData)) != INVALID_HANDLE_VALUE) {
4781*89c4ff92SAndroid Build Coastguard Worker if (std::wstring(_findData.cFileName) == L"." || std::wstring(_findData.cFileName) == L"..") {
4782*89c4ff92SAndroid Build Coastguard Worker increment(_ec);
4783*89c4ff92SAndroid Build Coastguard Worker }
4784*89c4ff92SAndroid Build Coastguard Worker else {
4785*89c4ff92SAndroid Build Coastguard Worker _current = _base / std::wstring(_findData.cFileName);
4786*89c4ff92SAndroid Build Coastguard Worker copyToDirEntry(_ec);
4787*89c4ff92SAndroid Build Coastguard Worker }
4788*89c4ff92SAndroid Build Coastguard Worker }
4789*89c4ff92SAndroid Build Coastguard Worker else {
4790*89c4ff92SAndroid Build Coastguard Worker auto error = ::GetLastError();
4791*89c4ff92SAndroid Build Coastguard Worker _base = filesystem::path();
4792*89c4ff92SAndroid Build Coastguard Worker if (error != ERROR_ACCESS_DENIED || (options & directory_options::skip_permission_denied) == directory_options::none) {
4793*89c4ff92SAndroid Build Coastguard Worker _ec = detail::make_system_error();
4794*89c4ff92SAndroid Build Coastguard Worker }
4795*89c4ff92SAndroid Build Coastguard Worker }
4796*89c4ff92SAndroid Build Coastguard Worker }
4797*89c4ff92SAndroid Build Coastguard Worker }
4798*89c4ff92SAndroid Build Coastguard Worker impl(const impl& other) = delete;
~impl()4799*89c4ff92SAndroid Build Coastguard Worker ~impl()
4800*89c4ff92SAndroid Build Coastguard Worker {
4801*89c4ff92SAndroid Build Coastguard Worker if (_dirHandle != INVALID_HANDLE_VALUE) {
4802*89c4ff92SAndroid Build Coastguard Worker FindClose(_dirHandle);
4803*89c4ff92SAndroid Build Coastguard Worker _dirHandle = INVALID_HANDLE_VALUE;
4804*89c4ff92SAndroid Build Coastguard Worker }
4805*89c4ff92SAndroid Build Coastguard Worker }
increment(std::error_code & ec)4806*89c4ff92SAndroid Build Coastguard Worker void increment(std::error_code& ec)
4807*89c4ff92SAndroid Build Coastguard Worker {
4808*89c4ff92SAndroid Build Coastguard Worker if (_dirHandle != INVALID_HANDLE_VALUE) {
4809*89c4ff92SAndroid Build Coastguard Worker do {
4810*89c4ff92SAndroid Build Coastguard Worker if (FindNextFileW(_dirHandle, &_findData)) {
4811*89c4ff92SAndroid Build Coastguard Worker _current = _base;
4812*89c4ff92SAndroid Build Coastguard Worker try {
4813*89c4ff92SAndroid Build Coastguard Worker _current.append_name(detail::toUtf8(_findData.cFileName).c_str());
4814*89c4ff92SAndroid Build Coastguard Worker }
4815*89c4ff92SAndroid Build Coastguard Worker catch(filesystem_error& fe) {
4816*89c4ff92SAndroid Build Coastguard Worker ec = fe.code();
4817*89c4ff92SAndroid Build Coastguard Worker return;
4818*89c4ff92SAndroid Build Coastguard Worker }
4819*89c4ff92SAndroid Build Coastguard Worker copyToDirEntry(ec);
4820*89c4ff92SAndroid Build Coastguard Worker }
4821*89c4ff92SAndroid Build Coastguard Worker else {
4822*89c4ff92SAndroid Build Coastguard Worker auto err = ::GetLastError();
4823*89c4ff92SAndroid Build Coastguard Worker if(err != ERROR_NO_MORE_FILES) {
4824*89c4ff92SAndroid Build Coastguard Worker _ec = ec = detail::make_system_error(err);
4825*89c4ff92SAndroid Build Coastguard Worker }
4826*89c4ff92SAndroid Build Coastguard Worker FindClose(_dirHandle);
4827*89c4ff92SAndroid Build Coastguard Worker _dirHandle = INVALID_HANDLE_VALUE;
4828*89c4ff92SAndroid Build Coastguard Worker _current = filesystem::path();
4829*89c4ff92SAndroid Build Coastguard Worker break;
4830*89c4ff92SAndroid Build Coastguard Worker }
4831*89c4ff92SAndroid Build Coastguard Worker } while (std::wstring(_findData.cFileName) == L"." || std::wstring(_findData.cFileName) == L"..");
4832*89c4ff92SAndroid Build Coastguard Worker }
4833*89c4ff92SAndroid Build Coastguard Worker else {
4834*89c4ff92SAndroid Build Coastguard Worker ec = _ec;
4835*89c4ff92SAndroid Build Coastguard Worker }
4836*89c4ff92SAndroid Build Coastguard Worker }
copyToDirEntry(std::error_code & ec)4837*89c4ff92SAndroid Build Coastguard Worker void copyToDirEntry(std::error_code& ec)
4838*89c4ff92SAndroid Build Coastguard Worker {
4839*89c4ff92SAndroid Build Coastguard Worker _dir_entry._path = _current;
4840*89c4ff92SAndroid Build Coastguard Worker if (_findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
4841*89c4ff92SAndroid Build Coastguard Worker _dir_entry._status = detail::status_ex(_current, ec, &_dir_entry._symlink_status, &_dir_entry._file_size, nullptr, &_dir_entry._last_write_time);
4842*89c4ff92SAndroid Build Coastguard Worker }
4843*89c4ff92SAndroid Build Coastguard Worker else {
4844*89c4ff92SAndroid Build Coastguard Worker _dir_entry._status = detail::status_from_INFO(_current, &_findData, ec, &_dir_entry._file_size, &_dir_entry._last_write_time);
4845*89c4ff92SAndroid Build Coastguard Worker _dir_entry._symlink_status = _dir_entry._status;
4846*89c4ff92SAndroid Build Coastguard Worker }
4847*89c4ff92SAndroid Build Coastguard Worker if (ec) {
4848*89c4ff92SAndroid Build Coastguard Worker if (_dir_entry._status.type() != file_type::none && _dir_entry._symlink_status.type() != file_type::none) {
4849*89c4ff92SAndroid Build Coastguard Worker ec.clear();
4850*89c4ff92SAndroid Build Coastguard Worker }
4851*89c4ff92SAndroid Build Coastguard Worker else {
4852*89c4ff92SAndroid Build Coastguard Worker _dir_entry._file_size = static_cast<uintmax_t>(-1);
4853*89c4ff92SAndroid Build Coastguard Worker _dir_entry._last_write_time = 0;
4854*89c4ff92SAndroid Build Coastguard Worker }
4855*89c4ff92SAndroid Build Coastguard Worker }
4856*89c4ff92SAndroid Build Coastguard Worker }
4857*89c4ff92SAndroid Build Coastguard Worker path _base;
4858*89c4ff92SAndroid Build Coastguard Worker directory_options _options;
4859*89c4ff92SAndroid Build Coastguard Worker WIN32_FIND_DATAW _findData;
4860*89c4ff92SAndroid Build Coastguard Worker HANDLE _dirHandle;
4861*89c4ff92SAndroid Build Coastguard Worker path _current;
4862*89c4ff92SAndroid Build Coastguard Worker directory_entry _dir_entry;
4863*89c4ff92SAndroid Build Coastguard Worker std::error_code _ec;
4864*89c4ff92SAndroid Build Coastguard Worker };
4865*89c4ff92SAndroid Build Coastguard Worker #else
4866*89c4ff92SAndroid Build Coastguard Worker // POSIX implementation
4867*89c4ff92SAndroid Build Coastguard Worker class directory_iterator::impl
4868*89c4ff92SAndroid Build Coastguard Worker {
4869*89c4ff92SAndroid Build Coastguard Worker public:
impl(const path & path,directory_options options)4870*89c4ff92SAndroid Build Coastguard Worker impl(const path& path, directory_options options)
4871*89c4ff92SAndroid Build Coastguard Worker : _base(path)
4872*89c4ff92SAndroid Build Coastguard Worker , _options(options)
4873*89c4ff92SAndroid Build Coastguard Worker , _dir(nullptr)
4874*89c4ff92SAndroid Build Coastguard Worker , _entry(nullptr)
4875*89c4ff92SAndroid Build Coastguard Worker {
4876*89c4ff92SAndroid Build Coastguard Worker if (!path.empty()) {
4877*89c4ff92SAndroid Build Coastguard Worker _dir = ::opendir(path.native().c_str());
4878*89c4ff92SAndroid Build Coastguard Worker }
4879*89c4ff92SAndroid Build Coastguard Worker if (!path.empty()) {
4880*89c4ff92SAndroid Build Coastguard Worker if (!_dir) {
4881*89c4ff92SAndroid Build Coastguard Worker auto error = errno;
4882*89c4ff92SAndroid Build Coastguard Worker _base = filesystem::path();
4883*89c4ff92SAndroid Build Coastguard Worker if (error != EACCES || (options & directory_options::skip_permission_denied) == directory_options::none) {
4884*89c4ff92SAndroid Build Coastguard Worker _ec = detail::make_system_error();
4885*89c4ff92SAndroid Build Coastguard Worker }
4886*89c4ff92SAndroid Build Coastguard Worker }
4887*89c4ff92SAndroid Build Coastguard Worker else {
4888*89c4ff92SAndroid Build Coastguard Worker increment(_ec);
4889*89c4ff92SAndroid Build Coastguard Worker }
4890*89c4ff92SAndroid Build Coastguard Worker }
4891*89c4ff92SAndroid Build Coastguard Worker }
4892*89c4ff92SAndroid Build Coastguard Worker impl(const impl& other) = delete;
~impl()4893*89c4ff92SAndroid Build Coastguard Worker ~impl()
4894*89c4ff92SAndroid Build Coastguard Worker {
4895*89c4ff92SAndroid Build Coastguard Worker if (_dir) {
4896*89c4ff92SAndroid Build Coastguard Worker ::closedir(_dir);
4897*89c4ff92SAndroid Build Coastguard Worker }
4898*89c4ff92SAndroid Build Coastguard Worker }
increment(std::error_code & ec)4899*89c4ff92SAndroid Build Coastguard Worker void increment(std::error_code& ec)
4900*89c4ff92SAndroid Build Coastguard Worker {
4901*89c4ff92SAndroid Build Coastguard Worker if (_dir) {
4902*89c4ff92SAndroid Build Coastguard Worker do {
4903*89c4ff92SAndroid Build Coastguard Worker errno = 0;
4904*89c4ff92SAndroid Build Coastguard Worker _entry = readdir(_dir);
4905*89c4ff92SAndroid Build Coastguard Worker if (_entry) {
4906*89c4ff92SAndroid Build Coastguard Worker _current = _base;
4907*89c4ff92SAndroid Build Coastguard Worker _current.append_name(_entry->d_name);
4908*89c4ff92SAndroid Build Coastguard Worker _dir_entry = directory_entry(_current, ec);
4909*89c4ff92SAndroid Build Coastguard Worker }
4910*89c4ff92SAndroid Build Coastguard Worker else {
4911*89c4ff92SAndroid Build Coastguard Worker ::closedir(_dir);
4912*89c4ff92SAndroid Build Coastguard Worker _dir = nullptr;
4913*89c4ff92SAndroid Build Coastguard Worker _current = path();
4914*89c4ff92SAndroid Build Coastguard Worker if (errno) {
4915*89c4ff92SAndroid Build Coastguard Worker ec = detail::make_system_error();
4916*89c4ff92SAndroid Build Coastguard Worker }
4917*89c4ff92SAndroid Build Coastguard Worker break;
4918*89c4ff92SAndroid Build Coastguard Worker }
4919*89c4ff92SAndroid Build Coastguard Worker } while (std::strcmp(_entry->d_name, ".") == 0 || std::strcmp(_entry->d_name, "..") == 0);
4920*89c4ff92SAndroid Build Coastguard Worker }
4921*89c4ff92SAndroid Build Coastguard Worker }
4922*89c4ff92SAndroid Build Coastguard Worker path _base;
4923*89c4ff92SAndroid Build Coastguard Worker directory_options _options;
4924*89c4ff92SAndroid Build Coastguard Worker path _current;
4925*89c4ff92SAndroid Build Coastguard Worker DIR* _dir;
4926*89c4ff92SAndroid Build Coastguard Worker struct ::dirent* _entry;
4927*89c4ff92SAndroid Build Coastguard Worker directory_entry _dir_entry;
4928*89c4ff92SAndroid Build Coastguard Worker std::error_code _ec;
4929*89c4ff92SAndroid Build Coastguard Worker };
4930*89c4ff92SAndroid Build Coastguard Worker #endif
4931*89c4ff92SAndroid Build Coastguard Worker
4932*89c4ff92SAndroid Build Coastguard Worker // 30.10.13.1 member functions
directory_iterator()4933*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE directory_iterator::directory_iterator() noexcept
4934*89c4ff92SAndroid Build Coastguard Worker : _impl(new impl(path(), directory_options::none))
4935*89c4ff92SAndroid Build Coastguard Worker {
4936*89c4ff92SAndroid Build Coastguard Worker }
4937*89c4ff92SAndroid Build Coastguard Worker
directory_iterator(const path & p)4938*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE directory_iterator::directory_iterator(const path& p)
4939*89c4ff92SAndroid Build Coastguard Worker : _impl(new impl(p, directory_options::none))
4940*89c4ff92SAndroid Build Coastguard Worker {
4941*89c4ff92SAndroid Build Coastguard Worker if (_impl->_ec) {
4942*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(_impl->_ec.value()), p, _impl->_ec);
4943*89c4ff92SAndroid Build Coastguard Worker }
4944*89c4ff92SAndroid Build Coastguard Worker _impl->_ec.clear();
4945*89c4ff92SAndroid Build Coastguard Worker }
4946*89c4ff92SAndroid Build Coastguard Worker
directory_iterator(const path & p,directory_options options)4947*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE directory_iterator::directory_iterator(const path& p, directory_options options)
4948*89c4ff92SAndroid Build Coastguard Worker : _impl(new impl(p, options))
4949*89c4ff92SAndroid Build Coastguard Worker {
4950*89c4ff92SAndroid Build Coastguard Worker if (_impl->_ec) {
4951*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(_impl->_ec.value()), p, _impl->_ec);
4952*89c4ff92SAndroid Build Coastguard Worker }
4953*89c4ff92SAndroid Build Coastguard Worker }
4954*89c4ff92SAndroid Build Coastguard Worker
directory_iterator(const path & p,std::error_code & ec)4955*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE directory_iterator::directory_iterator(const path& p, std::error_code& ec) noexcept
4956*89c4ff92SAndroid Build Coastguard Worker : _impl(new impl(p, directory_options::none))
4957*89c4ff92SAndroid Build Coastguard Worker {
4958*89c4ff92SAndroid Build Coastguard Worker if (_impl->_ec) {
4959*89c4ff92SAndroid Build Coastguard Worker ec = _impl->_ec;
4960*89c4ff92SAndroid Build Coastguard Worker }
4961*89c4ff92SAndroid Build Coastguard Worker }
4962*89c4ff92SAndroid Build Coastguard Worker
directory_iterator(const path & p,directory_options options,std::error_code & ec)4963*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE directory_iterator::directory_iterator(const path& p, directory_options options, std::error_code& ec) noexcept
4964*89c4ff92SAndroid Build Coastguard Worker : _impl(new impl(p, options))
4965*89c4ff92SAndroid Build Coastguard Worker {
4966*89c4ff92SAndroid Build Coastguard Worker if (_impl->_ec) {
4967*89c4ff92SAndroid Build Coastguard Worker ec = _impl->_ec;
4968*89c4ff92SAndroid Build Coastguard Worker }
4969*89c4ff92SAndroid Build Coastguard Worker }
4970*89c4ff92SAndroid Build Coastguard Worker
directory_iterator(const directory_iterator & rhs)4971*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE directory_iterator::directory_iterator(const directory_iterator& rhs)
4972*89c4ff92SAndroid Build Coastguard Worker : _impl(rhs._impl)
4973*89c4ff92SAndroid Build Coastguard Worker {
4974*89c4ff92SAndroid Build Coastguard Worker }
4975*89c4ff92SAndroid Build Coastguard Worker
directory_iterator(directory_iterator && rhs)4976*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE directory_iterator::directory_iterator(directory_iterator&& rhs) noexcept
4977*89c4ff92SAndroid Build Coastguard Worker : _impl(std::move(rhs._impl))
4978*89c4ff92SAndroid Build Coastguard Worker {
4979*89c4ff92SAndroid Build Coastguard Worker }
4980*89c4ff92SAndroid Build Coastguard Worker
~directory_iterator()4981*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE directory_iterator::~directory_iterator() {}
4982*89c4ff92SAndroid Build Coastguard Worker
operator =(const directory_iterator & rhs)4983*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE directory_iterator& directory_iterator::operator=(const directory_iterator& rhs)
4984*89c4ff92SAndroid Build Coastguard Worker {
4985*89c4ff92SAndroid Build Coastguard Worker _impl = rhs._impl;
4986*89c4ff92SAndroid Build Coastguard Worker return *this;
4987*89c4ff92SAndroid Build Coastguard Worker }
4988*89c4ff92SAndroid Build Coastguard Worker
operator =(directory_iterator && rhs)4989*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE directory_iterator& directory_iterator::operator=(directory_iterator&& rhs) noexcept
4990*89c4ff92SAndroid Build Coastguard Worker {
4991*89c4ff92SAndroid Build Coastguard Worker _impl = std::move(rhs._impl);
4992*89c4ff92SAndroid Build Coastguard Worker return *this;
4993*89c4ff92SAndroid Build Coastguard Worker }
4994*89c4ff92SAndroid Build Coastguard Worker
operator *() const4995*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE const directory_entry& directory_iterator::operator*() const
4996*89c4ff92SAndroid Build Coastguard Worker {
4997*89c4ff92SAndroid Build Coastguard Worker return _impl->_dir_entry;
4998*89c4ff92SAndroid Build Coastguard Worker }
4999*89c4ff92SAndroid Build Coastguard Worker
operator ->() const5000*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE const directory_entry* directory_iterator::operator->() const
5001*89c4ff92SAndroid Build Coastguard Worker {
5002*89c4ff92SAndroid Build Coastguard Worker return &_impl->_dir_entry;
5003*89c4ff92SAndroid Build Coastguard Worker }
5004*89c4ff92SAndroid Build Coastguard Worker
operator ++()5005*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE directory_iterator& directory_iterator::operator++()
5006*89c4ff92SAndroid Build Coastguard Worker {
5007*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
5008*89c4ff92SAndroid Build Coastguard Worker _impl->increment(ec);
5009*89c4ff92SAndroid Build Coastguard Worker if (ec) {
5010*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), _impl->_current, ec);
5011*89c4ff92SAndroid Build Coastguard Worker }
5012*89c4ff92SAndroid Build Coastguard Worker return *this;
5013*89c4ff92SAndroid Build Coastguard Worker }
5014*89c4ff92SAndroid Build Coastguard Worker
increment(std::error_code & ec)5015*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE directory_iterator& directory_iterator::increment(std::error_code& ec) noexcept
5016*89c4ff92SAndroid Build Coastguard Worker {
5017*89c4ff92SAndroid Build Coastguard Worker _impl->increment(ec);
5018*89c4ff92SAndroid Build Coastguard Worker return *this;
5019*89c4ff92SAndroid Build Coastguard Worker }
5020*89c4ff92SAndroid Build Coastguard Worker
operator ==(const directory_iterator & rhs) const5021*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_iterator::operator==(const directory_iterator& rhs) const
5022*89c4ff92SAndroid Build Coastguard Worker {
5023*89c4ff92SAndroid Build Coastguard Worker return _impl->_current == rhs._impl->_current;
5024*89c4ff92SAndroid Build Coastguard Worker }
5025*89c4ff92SAndroid Build Coastguard Worker
operator !=(const directory_iterator & rhs) const5026*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool directory_iterator::operator!=(const directory_iterator& rhs) const
5027*89c4ff92SAndroid Build Coastguard Worker {
5028*89c4ff92SAndroid Build Coastguard Worker return _impl->_current != rhs._impl->_current;
5029*89c4ff92SAndroid Build Coastguard Worker }
5030*89c4ff92SAndroid Build Coastguard Worker
5031*89c4ff92SAndroid Build Coastguard Worker // 30.10.13.2 directory_iterator non-member functions
5032*89c4ff92SAndroid Build Coastguard Worker
begin(directory_iterator iter)5033*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE directory_iterator begin(directory_iterator iter) noexcept
5034*89c4ff92SAndroid Build Coastguard Worker {
5035*89c4ff92SAndroid Build Coastguard Worker return iter;
5036*89c4ff92SAndroid Build Coastguard Worker }
5037*89c4ff92SAndroid Build Coastguard Worker
end(const directory_iterator &)5038*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE directory_iterator end(const directory_iterator&) noexcept
5039*89c4ff92SAndroid Build Coastguard Worker {
5040*89c4ff92SAndroid Build Coastguard Worker return directory_iterator();
5041*89c4ff92SAndroid Build Coastguard Worker }
5042*89c4ff92SAndroid Build Coastguard Worker
5043*89c4ff92SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
5044*89c4ff92SAndroid Build Coastguard Worker // 30.10.14 class recursive_directory_iterator
5045*89c4ff92SAndroid Build Coastguard Worker
recursive_directory_iterator()5046*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE recursive_directory_iterator::recursive_directory_iterator() noexcept
5047*89c4ff92SAndroid Build Coastguard Worker : _impl(new recursive_directory_iterator_impl(directory_options::none, true))
5048*89c4ff92SAndroid Build Coastguard Worker {
5049*89c4ff92SAndroid Build Coastguard Worker _impl->_dir_iter_stack.push(directory_iterator());
5050*89c4ff92SAndroid Build Coastguard Worker }
5051*89c4ff92SAndroid Build Coastguard Worker
recursive_directory_iterator(const path & p)5052*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(const path& p)
5053*89c4ff92SAndroid Build Coastguard Worker : _impl(new recursive_directory_iterator_impl(directory_options::none, true))
5054*89c4ff92SAndroid Build Coastguard Worker {
5055*89c4ff92SAndroid Build Coastguard Worker _impl->_dir_iter_stack.push(directory_iterator(p));
5056*89c4ff92SAndroid Build Coastguard Worker }
5057*89c4ff92SAndroid Build Coastguard Worker
recursive_directory_iterator(const path & p,directory_options options)5058*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(const path& p, directory_options options)
5059*89c4ff92SAndroid Build Coastguard Worker : _impl(new recursive_directory_iterator_impl(options, true))
5060*89c4ff92SAndroid Build Coastguard Worker {
5061*89c4ff92SAndroid Build Coastguard Worker _impl->_dir_iter_stack.push(directory_iterator(p, options));
5062*89c4ff92SAndroid Build Coastguard Worker }
5063*89c4ff92SAndroid Build Coastguard Worker
recursive_directory_iterator(const path & p,directory_options options,std::error_code & ec)5064*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(const path& p, directory_options options, std::error_code& ec) noexcept
5065*89c4ff92SAndroid Build Coastguard Worker : _impl(new recursive_directory_iterator_impl(options, true))
5066*89c4ff92SAndroid Build Coastguard Worker {
5067*89c4ff92SAndroid Build Coastguard Worker _impl->_dir_iter_stack.push(directory_iterator(p, options, ec));
5068*89c4ff92SAndroid Build Coastguard Worker }
5069*89c4ff92SAndroid Build Coastguard Worker
recursive_directory_iterator(const path & p,std::error_code & ec)5070*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(const path& p, std::error_code& ec) noexcept
5071*89c4ff92SAndroid Build Coastguard Worker : _impl(new recursive_directory_iterator_impl(directory_options::none, true))
5072*89c4ff92SAndroid Build Coastguard Worker {
5073*89c4ff92SAndroid Build Coastguard Worker _impl->_dir_iter_stack.push(directory_iterator(p, ec));
5074*89c4ff92SAndroid Build Coastguard Worker }
5075*89c4ff92SAndroid Build Coastguard Worker
recursive_directory_iterator(const recursive_directory_iterator & rhs)5076*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(const recursive_directory_iterator& rhs)
5077*89c4ff92SAndroid Build Coastguard Worker : _impl(rhs._impl)
5078*89c4ff92SAndroid Build Coastguard Worker {
5079*89c4ff92SAndroid Build Coastguard Worker }
5080*89c4ff92SAndroid Build Coastguard Worker
recursive_directory_iterator(recursive_directory_iterator && rhs)5081*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(recursive_directory_iterator&& rhs) noexcept
5082*89c4ff92SAndroid Build Coastguard Worker : _impl(std::move(rhs._impl))
5083*89c4ff92SAndroid Build Coastguard Worker {
5084*89c4ff92SAndroid Build Coastguard Worker }
5085*89c4ff92SAndroid Build Coastguard Worker
~recursive_directory_iterator()5086*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE recursive_directory_iterator::~recursive_directory_iterator() {}
5087*89c4ff92SAndroid Build Coastguard Worker
5088*89c4ff92SAndroid Build Coastguard Worker // 30.10.14.1 observers
options() const5089*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE directory_options recursive_directory_iterator::options() const
5090*89c4ff92SAndroid Build Coastguard Worker {
5091*89c4ff92SAndroid Build Coastguard Worker return _impl->_options;
5092*89c4ff92SAndroid Build Coastguard Worker }
5093*89c4ff92SAndroid Build Coastguard Worker
depth() const5094*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE int recursive_directory_iterator::depth() const
5095*89c4ff92SAndroid Build Coastguard Worker {
5096*89c4ff92SAndroid Build Coastguard Worker return static_cast<int>(_impl->_dir_iter_stack.size() - 1);
5097*89c4ff92SAndroid Build Coastguard Worker }
5098*89c4ff92SAndroid Build Coastguard Worker
recursion_pending() const5099*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool recursive_directory_iterator::recursion_pending() const
5100*89c4ff92SAndroid Build Coastguard Worker {
5101*89c4ff92SAndroid Build Coastguard Worker return _impl->_recursion_pending;
5102*89c4ff92SAndroid Build Coastguard Worker }
5103*89c4ff92SAndroid Build Coastguard Worker
operator *() const5104*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE const directory_entry& recursive_directory_iterator::operator*() const
5105*89c4ff92SAndroid Build Coastguard Worker {
5106*89c4ff92SAndroid Build Coastguard Worker return *(_impl->_dir_iter_stack.top());
5107*89c4ff92SAndroid Build Coastguard Worker }
5108*89c4ff92SAndroid Build Coastguard Worker
operator ->() const5109*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE const directory_entry* recursive_directory_iterator::operator->() const
5110*89c4ff92SAndroid Build Coastguard Worker {
5111*89c4ff92SAndroid Build Coastguard Worker return &(*(_impl->_dir_iter_stack.top()));
5112*89c4ff92SAndroid Build Coastguard Worker }
5113*89c4ff92SAndroid Build Coastguard Worker
5114*89c4ff92SAndroid Build Coastguard Worker // 30.10.14.1 modifiers recursive_directory_iterator&
operator =(const recursive_directory_iterator & rhs)5115*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::operator=(const recursive_directory_iterator& rhs)
5116*89c4ff92SAndroid Build Coastguard Worker {
5117*89c4ff92SAndroid Build Coastguard Worker _impl = rhs._impl;
5118*89c4ff92SAndroid Build Coastguard Worker return *this;
5119*89c4ff92SAndroid Build Coastguard Worker }
5120*89c4ff92SAndroid Build Coastguard Worker
operator =(recursive_directory_iterator && rhs)5121*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::operator=(recursive_directory_iterator&& rhs) noexcept
5122*89c4ff92SAndroid Build Coastguard Worker {
5123*89c4ff92SAndroid Build Coastguard Worker _impl = std::move(rhs._impl);
5124*89c4ff92SAndroid Build Coastguard Worker return *this;
5125*89c4ff92SAndroid Build Coastguard Worker }
5126*89c4ff92SAndroid Build Coastguard Worker
operator ++()5127*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::operator++()
5128*89c4ff92SAndroid Build Coastguard Worker {
5129*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
5130*89c4ff92SAndroid Build Coastguard Worker increment(ec);
5131*89c4ff92SAndroid Build Coastguard Worker if (ec) {
5132*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), _impl->_dir_iter_stack.empty() ? path() : _impl->_dir_iter_stack.top()->path(), ec);
5133*89c4ff92SAndroid Build Coastguard Worker }
5134*89c4ff92SAndroid Build Coastguard Worker return *this;
5135*89c4ff92SAndroid Build Coastguard Worker }
5136*89c4ff92SAndroid Build Coastguard Worker
increment(std::error_code & ec)5137*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::increment(std::error_code& ec) noexcept
5138*89c4ff92SAndroid Build Coastguard Worker {
5139*89c4ff92SAndroid Build Coastguard Worker if (recursion_pending() && is_directory((*this)->status()) && (!is_symlink((*this)->symlink_status()) || (options() & directory_options::follow_directory_symlink) != directory_options::none)) {
5140*89c4ff92SAndroid Build Coastguard Worker _impl->_dir_iter_stack.push(directory_iterator((*this)->path(), _impl->_options, ec));
5141*89c4ff92SAndroid Build Coastguard Worker }
5142*89c4ff92SAndroid Build Coastguard Worker else {
5143*89c4ff92SAndroid Build Coastguard Worker _impl->_dir_iter_stack.top().increment(ec);
5144*89c4ff92SAndroid Build Coastguard Worker }
5145*89c4ff92SAndroid Build Coastguard Worker if (!ec) {
5146*89c4ff92SAndroid Build Coastguard Worker while (depth() && _impl->_dir_iter_stack.top() == directory_iterator()) {
5147*89c4ff92SAndroid Build Coastguard Worker _impl->_dir_iter_stack.pop();
5148*89c4ff92SAndroid Build Coastguard Worker _impl->_dir_iter_stack.top().increment(ec);
5149*89c4ff92SAndroid Build Coastguard Worker }
5150*89c4ff92SAndroid Build Coastguard Worker }
5151*89c4ff92SAndroid Build Coastguard Worker else if (!_impl->_dir_iter_stack.empty()) {
5152*89c4ff92SAndroid Build Coastguard Worker _impl->_dir_iter_stack.pop();
5153*89c4ff92SAndroid Build Coastguard Worker }
5154*89c4ff92SAndroid Build Coastguard Worker _impl->_recursion_pending = true;
5155*89c4ff92SAndroid Build Coastguard Worker return *this;
5156*89c4ff92SAndroid Build Coastguard Worker }
5157*89c4ff92SAndroid Build Coastguard Worker
pop()5158*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void recursive_directory_iterator::pop()
5159*89c4ff92SAndroid Build Coastguard Worker {
5160*89c4ff92SAndroid Build Coastguard Worker std::error_code ec;
5161*89c4ff92SAndroid Build Coastguard Worker pop(ec);
5162*89c4ff92SAndroid Build Coastguard Worker if (ec) {
5163*89c4ff92SAndroid Build Coastguard Worker throw filesystem_error(detail::systemErrorText(ec.value()), _impl->_dir_iter_stack.empty() ? path() : _impl->_dir_iter_stack.top()->path(), ec);
5164*89c4ff92SAndroid Build Coastguard Worker }
5165*89c4ff92SAndroid Build Coastguard Worker }
5166*89c4ff92SAndroid Build Coastguard Worker
pop(std::error_code & ec)5167*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void recursive_directory_iterator::pop(std::error_code& ec)
5168*89c4ff92SAndroid Build Coastguard Worker {
5169*89c4ff92SAndroid Build Coastguard Worker if (depth() == 0) {
5170*89c4ff92SAndroid Build Coastguard Worker *this = recursive_directory_iterator();
5171*89c4ff92SAndroid Build Coastguard Worker }
5172*89c4ff92SAndroid Build Coastguard Worker else {
5173*89c4ff92SAndroid Build Coastguard Worker do {
5174*89c4ff92SAndroid Build Coastguard Worker _impl->_dir_iter_stack.pop();
5175*89c4ff92SAndroid Build Coastguard Worker _impl->_dir_iter_stack.top().increment(ec);
5176*89c4ff92SAndroid Build Coastguard Worker } while (depth() && _impl->_dir_iter_stack.top() == directory_iterator());
5177*89c4ff92SAndroid Build Coastguard Worker }
5178*89c4ff92SAndroid Build Coastguard Worker }
5179*89c4ff92SAndroid Build Coastguard Worker
disable_recursion_pending()5180*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE void recursive_directory_iterator::disable_recursion_pending()
5181*89c4ff92SAndroid Build Coastguard Worker {
5182*89c4ff92SAndroid Build Coastguard Worker _impl->_recursion_pending = false;
5183*89c4ff92SAndroid Build Coastguard Worker }
5184*89c4ff92SAndroid Build Coastguard Worker
5185*89c4ff92SAndroid Build Coastguard Worker // other members as required by 27.2.3, input iterators
operator ==(const recursive_directory_iterator & rhs) const5186*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool recursive_directory_iterator::operator==(const recursive_directory_iterator& rhs) const
5187*89c4ff92SAndroid Build Coastguard Worker {
5188*89c4ff92SAndroid Build Coastguard Worker return _impl->_dir_iter_stack.top() == rhs._impl->_dir_iter_stack.top();
5189*89c4ff92SAndroid Build Coastguard Worker }
5190*89c4ff92SAndroid Build Coastguard Worker
operator !=(const recursive_directory_iterator & rhs) const5191*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE bool recursive_directory_iterator::operator!=(const recursive_directory_iterator& rhs) const
5192*89c4ff92SAndroid Build Coastguard Worker {
5193*89c4ff92SAndroid Build Coastguard Worker return _impl->_dir_iter_stack.top() != rhs._impl->_dir_iter_stack.top();
5194*89c4ff92SAndroid Build Coastguard Worker }
5195*89c4ff92SAndroid Build Coastguard Worker
5196*89c4ff92SAndroid Build Coastguard Worker // 30.10.14.2 directory_iterator non-member functions
begin(recursive_directory_iterator iter)5197*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept
5198*89c4ff92SAndroid Build Coastguard Worker {
5199*89c4ff92SAndroid Build Coastguard Worker return iter;
5200*89c4ff92SAndroid Build Coastguard Worker }
5201*89c4ff92SAndroid Build Coastguard Worker
end(const recursive_directory_iterator &)5202*89c4ff92SAndroid Build Coastguard Worker GHC_INLINE recursive_directory_iterator end(const recursive_directory_iterator&) noexcept
5203*89c4ff92SAndroid Build Coastguard Worker {
5204*89c4ff92SAndroid Build Coastguard Worker return recursive_directory_iterator();
5205*89c4ff92SAndroid Build Coastguard Worker }
5206*89c4ff92SAndroid Build Coastguard Worker
5207*89c4ff92SAndroid Build Coastguard Worker #endif // GHC_EXPAND_IMPL
5208*89c4ff92SAndroid Build Coastguard Worker
5209*89c4ff92SAndroid Build Coastguard Worker } // namespace filesystem
5210*89c4ff92SAndroid Build Coastguard Worker } // namespace ghc
5211*89c4ff92SAndroid Build Coastguard Worker
5212*89c4ff92SAndroid Build Coastguard Worker // cleanup some macros
5213*89c4ff92SAndroid Build Coastguard Worker #undef GHC_INLINE
5214*89c4ff92SAndroid Build Coastguard Worker #undef GHC_EXPAND_IMPL
5215*89c4ff92SAndroid Build Coastguard Worker
5216*89c4ff92SAndroid Build Coastguard Worker #endif // GHC_FILESYSTEM_H
5217