1 | // -*- C++ -*- |
2 | //===----------------------------------------------------------------------===// |
3 | // |
4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
5 | // See https://llvm.org/LICENSE.txt for license information. |
6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | #ifndef _LIBCPP_FILESYSTEM |
11 | #define _LIBCPP_FILESYSTEM |
12 | |
13 | /* |
14 | filesystem synopsis |
15 | |
16 | namespace std::filesystem { |
17 | |
18 | // `class path` from http://eel.is/c++draft/fs.class.path.general#6 |
19 | class path { |
20 | public: |
21 | using value_type = see below; |
22 | using string_type = basic_string<value_type>; |
23 | static constexpr value_type preferred_separator = see below; |
24 | |
25 | enum format; |
26 | |
27 | path() noexcept; |
28 | path(const path& p); |
29 | path(path&& p) noexcept; |
30 | path(string_type&& source, format fmt = auto_format); |
31 | template<class Source> |
32 | path(const Source& source, format fmt = auto_format); |
33 | template<class InputIterator> |
34 | path(InputIterator first, InputIterator last, format fmt = auto_format); |
35 | template<class Source> |
36 | path(const Source& source, const locale& loc, format fmt = auto_format); |
37 | template<class InputIterator> |
38 | path(InputIterator first, InputIterator last, const locale& loc, format fmt = auto_format); |
39 | ~path(); |
40 | |
41 | path& operator=(const path& p); |
42 | path& operator=(path&& p) noexcept; |
43 | path& operator=(string_type&& source); |
44 | path& assign(string_type&& source); |
45 | template<class Source> |
46 | path& operator=(const Source& source); |
47 | template<class Source> |
48 | path& assign(const Source& source); |
49 | template<class InputIterator> |
50 | path& assign(InputIterator first, InputIterator last); |
51 | |
52 | path& operator/=(const path& p); |
53 | template<class Source> |
54 | path& operator/=(const Source& source); |
55 | template<class Source> |
56 | path& append(const Source& source); |
57 | template<class InputIterator> |
58 | path& append(InputIterator first, InputIterator last); |
59 | |
60 | path& operator+=(const path& x); |
61 | path& operator+=(const string_type& x); |
62 | path& operator+=(basic_string_view<value_type> x); |
63 | path& operator+=(const value_type* x); |
64 | path& operator+=(value_type x); |
65 | template<class Source> |
66 | path& operator+=(const Source& x); |
67 | template<class EcharT> |
68 | path& operator+=(EcharT x); |
69 | template<class Source> |
70 | path& concat(const Source& x); |
71 | template<class InputIterator> |
72 | path& concat(InputIterator first, InputIterator last); |
73 | |
74 | void clear() noexcept; |
75 | path& make_preferred(); |
76 | path& remove_filename(); |
77 | path& replace_filename(const path& replacement); |
78 | path& replace_extension(const path& replacement = path()); |
79 | void swap(path& rhs) noexcept; |
80 | |
81 | friend bool operator==(const path& lhs, const path& rhs) noexcept; |
82 | friend bool operator!=(const path& lhs, const path& rhs) noexcept; // removed in C++20 |
83 | friend bool operator< (const path& lhs, const path& rhs) noexcept; // removed in C++20 |
84 | friend bool operator<=(const path& lhs, const path& rhs) noexcept; // removed in C++20 |
85 | friend bool operator> (const path& lhs, const path& rhs) noexcept; // removed in C++20 |
86 | friend bool operator>=(const path& lhs, const path& rhs) noexcept; // removed in C++20 |
87 | friend strong_ordering operator<=>(const path& lhs, const path& rhs) noexcept; // C++20 |
88 | |
89 | friend path operator/(const path& lhs, const path& rhs); |
90 | |
91 | const string_type& native() const noexcept; |
92 | const value_type* c_str() const noexcept; |
93 | operator string_type() const; |
94 | |
95 | template<class EcharT, class traits = char_traits<EcharT>, |
96 | class Allocator = allocator<EcharT>> |
97 | basic_string<EcharT, traits, Allocator> |
98 | string(const Allocator& a = Allocator()) const; |
99 | std::string string() const; |
100 | std::wstring wstring() const; |
101 | std::u8string u8string() const; |
102 | std::u16string u16string() const; |
103 | std::u32string u32string() const; |
104 | |
105 | template<class EcharT, class traits = char_traits<EcharT>, |
106 | class Allocator = allocator<EcharT>> |
107 | basic_string<EcharT, traits, Allocator> |
108 | generic_string(const Allocator& a = Allocator()) const; |
109 | std::string generic_string() const; |
110 | std::wstring generic_wstring() const; |
111 | std::u8string generic_u8string() const; |
112 | std::u16string generic_u16string() const; |
113 | std::u32string generic_u32string() const; |
114 | |
115 | int compare(const path& p) const noexcept; |
116 | int compare(const string_type& s) const; |
117 | int compare(basic_string_view<value_type> s) const; |
118 | int compare(const value_type* s) const; |
119 | |
120 | path root_name() const; |
121 | path root_directory() const; |
122 | path root_path() const; |
123 | path relative_path() const; |
124 | path parent_path() const; |
125 | path filename() const; |
126 | path stem() const; |
127 | path extension() const; |
128 | |
129 | [[nodiscard]] bool empty() const noexcept; |
130 | bool has_root_name() const; |
131 | bool has_root_directory() const; |
132 | bool has_root_path() const; |
133 | bool has_relative_path() const; |
134 | bool has_parent_path() const; |
135 | bool has_filename() const; |
136 | bool has_stem() const; |
137 | bool has_extension() const; |
138 | bool is_absolute() const; |
139 | bool is_relative() const; |
140 | |
141 | path lexically_normal() const; |
142 | path lexically_relative(const path& base) const; |
143 | path lexically_proximate(const path& base) const; |
144 | |
145 | class iterator; |
146 | using const_iterator = iterator; |
147 | |
148 | iterator begin() const; |
149 | iterator end() const; |
150 | |
151 | template<class charT, class traits> |
152 | friend basic_ostream<charT, traits>& |
153 | operator<<(basic_ostream<charT, traits>& os, const path& p); |
154 | template<class charT, class traits> |
155 | friend basic_istream<charT, traits>& |
156 | operator>>(basic_istream<charT, traits>& is, path& p); |
157 | }; |
158 | |
159 | void swap(path& lhs, path& rhs) noexcept; |
160 | size_t hash_value(const path& p) noexcept; |
161 | |
162 | // [fs.path.hash], hash support |
163 | template<> struct hash<filesystem::path>; |
164 | |
165 | template <class Source> |
166 | path u8path(const Source& source); |
167 | template <class InputIterator> |
168 | path u8path(InputIterator first, InputIterator last); |
169 | |
170 | class filesystem_error; |
171 | |
172 | class directory_entry { |
173 | public: |
174 | directory_entry() noexcept = default; |
175 | directory_entry(const directory_entry&) = default; |
176 | directory_entry(directory_entry&&) noexcept = default; |
177 | explicit directory_entry(const filesystem::path& p); |
178 | directory_entry(const filesystem::path& p, error_code& ec); |
179 | ~directory_entry(); |
180 | |
181 | directory_entry& operator=(const directory_entry&) = default; |
182 | directory_entry& operator=(directory_entry&&) noexcept = default; |
183 | |
184 | void assign(const filesystem::path& p); |
185 | void assign(const filesystem::path& p, error_code& ec); |
186 | void replace_filename(const filesystem::path& p); |
187 | void replace_filename(const filesystem::path& p, error_code& ec); |
188 | void refresh(); |
189 | void refresh(error_code& ec) noexcept; |
190 | |
191 | const filesystem::path& path() const noexcept; |
192 | operator const filesystem::path&() const noexcept; |
193 | bool exists() const; |
194 | bool exists(error_code& ec) const noexcept; |
195 | bool is_block_file() const; |
196 | bool is_block_file(error_code& ec) const noexcept; |
197 | bool is_character_file() const; |
198 | bool is_character_file(error_code& ec) const noexcept; |
199 | bool is_directory() const; |
200 | bool is_directory(error_code& ec) const noexcept; |
201 | bool is_fifo() const; |
202 | bool is_fifo(error_code& ec) const noexcept; |
203 | bool is_other() const; |
204 | bool is_other(error_code& ec) const noexcept; |
205 | bool is_regular_file() const; |
206 | bool is_regular_file(error_code& ec) const noexcept; |
207 | bool is_socket() const; |
208 | bool is_socket(error_code& ec) const noexcept; |
209 | bool is_symlink() const; |
210 | bool is_symlink(error_code& ec) const noexcept; |
211 | uintmax_t file_size() const; |
212 | uintmax_t file_size(error_code& ec) const noexcept; |
213 | uintmax_t hard_link_count() const; |
214 | uintmax_t hard_link_count(error_code& ec) const noexcept; |
215 | file_time_type last_write_time() const; |
216 | file_time_type last_write_time(error_code& ec) const noexcept; |
217 | file_status status() const; |
218 | file_status status(error_code& ec) const noexcept; |
219 | file_status symlink_status() const; |
220 | file_status symlink_status(error_code& ec) const noexcept; |
221 | |
222 | bool operator==(const directory_entry& rhs) const noexcept; |
223 | bool operator!=(const directory_entry& rhs) const noexcept; // removed in C++20 |
224 | bool operator< (const directory_entry& rhs) const noexcept; // removed in C++20 |
225 | bool operator<=(const directory_entry& rhs) const noexcept; // removed in C++20 |
226 | bool operator> (const directory_entry& rhs) const noexcept; // removed in C++20 |
227 | bool operator>=(const directory_entry& rhs) const noexcept; // removed in C++20 |
228 | strong_ordering operator<=>(const directory_entry& rhs) const noexcept; // since C++20 |
229 | |
230 | template<class charT, class traits> |
231 | friend basic_ostream<charT, traits>& |
232 | operator<<(basic_ostream<charT, traits>& os, const directory_entry& d); |
233 | |
234 | private: |
235 | filesystem::path pathobject; // exposition only |
236 | friend class directory_iterator; // exposition only |
237 | }; |
238 | |
239 | class directory_iterator { |
240 | public: |
241 | using iterator_category = input_iterator_tag; |
242 | using value_type = directory_entry; |
243 | using difference_type = ptrdiff_t; |
244 | using pointer = const directory_entry*; |
245 | using reference = const directory_entry&; |
246 | |
247 | // [fs.dir.itr.members], member functions |
248 | directory_iterator() noexcept; |
249 | explicit directory_iterator(const path& p); |
250 | directory_iterator(const path& p, directory_options options); |
251 | directory_iterator(const path& p, error_code& ec); |
252 | directory_iterator(const path& p, directory_options options, |
253 | error_code& ec); |
254 | directory_iterator(const directory_iterator& rhs); |
255 | directory_iterator(directory_iterator&& rhs) noexcept; |
256 | ~directory_iterator(); |
257 | |
258 | directory_iterator& operator=(const directory_iterator& rhs); |
259 | directory_iterator& operator=(directory_iterator&& rhs) noexcept; |
260 | |
261 | const directory_entry& operator*() const; |
262 | const directory_entry* operator->() const; |
263 | directory_iterator& operator++(); |
264 | directory_iterator& increment(error_code& ec); |
265 | |
266 | bool operator==(default_sentinel_t) const noexcept { // since C++20 |
267 | return *this == directory_iterator(); |
268 | } |
269 | |
270 | // other members as required by [input.iterators], input iterators |
271 | }; |
272 | |
273 | // enable directory_iterator range-based for statements |
274 | directory_iterator begin(directory_iterator iter) noexcept; |
275 | directory_iterator end(directory_iterator) noexcept; |
276 | |
277 | class recursive_directory_iterator { |
278 | public: |
279 | using iterator_category = input_iterator_tag; |
280 | using value_type = directory_entry; |
281 | using difference_type = ptrdiff_t; |
282 | using pointer = const directory_entry*; |
283 | using reference = const directory_entry&; |
284 | |
285 | // [fs.rec.dir.itr.members], constructors and destructor |
286 | recursive_directory_iterator() noexcept; |
287 | explicit recursive_directory_iterator(const path& p); |
288 | recursive_directory_iterator(const path& p, directory_options options); |
289 | recursive_directory_iterator(const path& p, directory_options options, |
290 | error_code& ec); |
291 | recursive_directory_iterator(const path& p, error_code& ec); |
292 | recursive_directory_iterator(const recursive_directory_iterator& rhs); |
293 | recursive_directory_iterator(recursive_directory_iterator&& rhs) noexcept; |
294 | ~recursive_directory_iterator(); |
295 | |
296 | // [fs.rec.dir.itr.members], observers |
297 | directory_options options() const; |
298 | int depth() const; |
299 | bool recursion_pending() const; |
300 | |
301 | const directory_entry& operator*() const; |
302 | const directory_entry* operator->() const; |
303 | |
304 | // [fs.rec.dir.itr.members], modifiers |
305 | recursive_directory_iterator& |
306 | operator=(const recursive_directory_iterator& rhs); |
307 | recursive_directory_iterator& |
308 | operator=(recursive_directory_iterator&& rhs) noexcept; |
309 | |
310 | recursive_directory_iterator& operator++(); |
311 | recursive_directory_iterator& increment(error_code& ec); |
312 | |
313 | void pop(); |
314 | void pop(error_code& ec); |
315 | void disable_recursion_pending(); |
316 | |
317 | bool operator==(default_sentinel_t) const noexcept { // since C++20 |
318 | return *this == recursive_directory_iterator(); |
319 | } |
320 | |
321 | // other members as required by [input.iterators], input iterators |
322 | }; |
323 | |
324 | // enable recursive_directory_iterator range-based for statements |
325 | recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept; |
326 | recursive_directory_iterator end(recursive_directory_iterator) noexcept; |
327 | |
328 | class file_status { |
329 | public: |
330 | // [fs.file.status.cons], constructors and destructor |
331 | file_status() noexcept : file_status(file_type::none) {} |
332 | explicit file_status(file_type ft, |
333 | perms prms = perms::unknown) noexcept; |
334 | file_status(const file_status&) noexcept = default; |
335 | file_status(file_status&&) noexcept = default; |
336 | ~file_status(); |
337 | |
338 | // assignments |
339 | file_status& operator=(const file_status&) noexcept = default; |
340 | file_status& operator=(file_status&&) noexcept = default; |
341 | |
342 | // [fs.file.status.mods], modifiers |
343 | void type(file_type ft) noexcept; |
344 | void permissions(perms prms) noexcept; |
345 | |
346 | // [fs.file.status.obs], observers |
347 | file_type type() const noexcept; |
348 | perms permissions() const noexcept; |
349 | |
350 | friend bool operator==(const file_status& lhs, const file_status& rhs) noexcept |
351 | { return lhs.type() == rhs.type() && lhs.permissions() == rhs.permissions(); } // C++20 |
352 | }; |
353 | |
354 | struct space_info |
355 | { |
356 | uintmax_t capacity; |
357 | uintmax_t free; |
358 | uintmax_t available; |
359 | |
360 | friend bool operator==(const space_info&, const space_info&) = default; // C++20 |
361 | }; |
362 | |
363 | enum class file_type; |
364 | enum class perms; |
365 | enum class perm_options; |
366 | enum class copy_options; |
367 | enum class directory_options; |
368 | |
369 | typedef chrono::time_point<trivial-clock> file_time_type; |
370 | |
371 | // operational functions |
372 | |
373 | path absolute(const path& p); |
374 | path absolute(const path& p, error_code &ec); |
375 | |
376 | path canonical(const path& p); |
377 | path canonical(const path& p, error_code& ec); |
378 | |
379 | void copy(const path& from, const path& to); |
380 | void copy(const path& from, const path& to, error_code& ec); |
381 | void copy(const path& from, const path& to, copy_options options); |
382 | void copy(const path& from, const path& to, copy_options options, |
383 | error_code& ec); |
384 | |
385 | bool copy_file(const path& from, const path& to); |
386 | bool copy_file(const path& from, const path& to, error_code& ec); |
387 | bool copy_file(const path& from, const path& to, copy_options option); |
388 | bool copy_file(const path& from, const path& to, copy_options option, |
389 | error_code& ec); |
390 | |
391 | void copy_symlink(const path& existing_symlink, const path& new_symlink); |
392 | void copy_symlink(const path& existing_symlink, const path& new_symlink, |
393 | error_code& ec) noexcept; |
394 | |
395 | bool create_directories(const path& p); |
396 | bool create_directories(const path& p, error_code& ec); |
397 | |
398 | bool create_directory(const path& p); |
399 | bool create_directory(const path& p, error_code& ec) noexcept; |
400 | |
401 | bool create_directory(const path& p, const path& attributes); |
402 | bool create_directory(const path& p, const path& attributes, |
403 | error_code& ec) noexcept; |
404 | |
405 | void create_directory_symlink(const path& to, const path& new_symlink); |
406 | void create_directory_symlink(const path& to, const path& new_symlink, |
407 | error_code& ec) noexcept; |
408 | |
409 | void create_hard_link(const path& to, const path& new_hard_link); |
410 | void create_hard_link(const path& to, const path& new_hard_link, |
411 | error_code& ec) noexcept; |
412 | |
413 | void create_symlink(const path& to, const path& new_symlink); |
414 | void create_symlink(const path& to, const path& new_symlink, |
415 | error_code& ec) noexcept; |
416 | |
417 | path current_path(); |
418 | path current_path(error_code& ec); |
419 | void current_path(const path& p); |
420 | void current_path(const path& p, error_code& ec) noexcept; |
421 | |
422 | bool exists(file_status s) noexcept; |
423 | bool exists(const path& p); |
424 | bool exists(const path& p, error_code& ec) noexcept; |
425 | |
426 | bool equivalent(const path& p1, const path& p2); |
427 | bool equivalent(const path& p1, const path& p2, error_code& ec) noexcept; |
428 | |
429 | uintmax_t file_size(const path& p); |
430 | uintmax_t file_size(const path& p, error_code& ec) noexcept; |
431 | |
432 | uintmax_t hard_link_count(const path& p); |
433 | uintmax_t hard_link_count(const path& p, error_code& ec) noexcept; |
434 | |
435 | bool is_block_file(file_status s) noexcept; |
436 | bool is_block_file(const path& p); |
437 | bool is_block_file(const path& p, error_code& ec) noexcept; |
438 | |
439 | bool is_character_file(file_status s) noexcept; |
440 | bool is_character_file(const path& p); |
441 | bool is_character_file(const path& p, error_code& ec) noexcept; |
442 | |
443 | bool is_directory(file_status s) noexcept; |
444 | bool is_directory(const path& p); |
445 | bool is_directory(const path& p, error_code& ec) noexcept; |
446 | |
447 | bool is_empty(const path& p); |
448 | bool is_empty(const path& p, error_code& ec) noexcept; |
449 | |
450 | bool is_fifo(file_status s) noexcept; |
451 | bool is_fifo(const path& p); |
452 | bool is_fifo(const path& p, error_code& ec) noexcept; |
453 | |
454 | bool is_other(file_status s) noexcept; |
455 | bool is_other(const path& p); |
456 | bool is_other(const path& p, error_code& ec) noexcept; |
457 | |
458 | bool is_regular_file(file_status s) noexcept; |
459 | bool is_regular_file(const path& p); |
460 | bool is_regular_file(const path& p, error_code& ec) noexcept; |
461 | |
462 | bool is_socket(file_status s) noexcept; |
463 | bool is_socket(const path& p); |
464 | bool is_socket(const path& p, error_code& ec) noexcept; |
465 | |
466 | bool is_symlink(file_status s) noexcept; |
467 | bool is_symlink(const path& p); |
468 | bool is_symlink(const path& p, error_code& ec) noexcept; |
469 | |
470 | file_time_type last_write_time(const path& p); |
471 | file_time_type last_write_time(const path& p, error_code& ec) noexcept; |
472 | void last_write_time(const path& p, file_time_type new_time); |
473 | void last_write_time(const path& p, file_time_type new_time, |
474 | error_code& ec) noexcept; |
475 | |
476 | void permissions(const path& p, perms prms, |
477 | perm_options opts=perm_options::replace); |
478 | void permissions(const path& p, perms prms, error_code& ec) noexcept; |
479 | void permissions(const path& p, perms prms, perm_options opts, |
480 | error_code& ec); |
481 | |
482 | path proximate(const path& p, error_code& ec); |
483 | path proximate(const path& p, const path& base = current_path()); |
484 | path proximate(const path& p, const path& base, error_code &ec); |
485 | |
486 | path read_symlink(const path& p); |
487 | path read_symlink(const path& p, error_code& ec); |
488 | |
489 | path relative(const path& p, error_code& ec); |
490 | path relative(const path& p, const path& base=current_path()); |
491 | path relative(const path& p, const path& base, error_code& ec); |
492 | |
493 | bool remove(const path& p); |
494 | bool remove(const path& p, error_code& ec) noexcept; |
495 | |
496 | uintmax_t remove_all(const path& p); |
497 | uintmax_t remove_all(const path& p, error_code& ec); |
498 | |
499 | void rename(const path& from, const path& to); |
500 | void rename(const path& from, const path& to, error_code& ec) noexcept; |
501 | |
502 | void resize_file(const path& p, uintmax_t size); |
503 | void resize_file(const path& p, uintmax_t size, error_code& ec) noexcept; |
504 | |
505 | space_info space(const path& p); |
506 | space_info space(const path& p, error_code& ec) noexcept; |
507 | |
508 | file_status status(const path& p); |
509 | file_status status(const path& p, error_code& ec) noexcept; |
510 | |
511 | bool status_known(file_status s) noexcept; |
512 | |
513 | file_status symlink_status(const path& p); |
514 | file_status symlink_status(const path& p, error_code& ec) noexcept; |
515 | |
516 | path temp_directory_path(); |
517 | path temp_directory_path(error_code& ec); |
518 | |
519 | path weakly_canonical(path const& p); |
520 | path weakly_canonical(path const& p, error_code& ec); |
521 | |
522 | } // namespace std::filesystem |
523 | |
524 | template <> |
525 | inline constexpr bool std::ranges::enable_borrowed_range<std::filesystem::directory_iterator> = true; |
526 | template <> |
527 | inline constexpr bool std::ranges::enable_borrowed_range<std::filesystem::recursive_directory_iterator> = true; |
528 | |
529 | template <> |
530 | inline constexpr bool std::ranges::enable_view<std::filesystem::directory_iterator> = true; |
531 | template <> |
532 | inline constexpr bool std::ranges::enable_view<std::filesystem::recursive_directory_iterator> = true; |
533 | |
534 | */ |
535 | |
536 | #include <__config> |
537 | |
538 | #if _LIBCPP_STD_VER >= 17 |
539 | # include <__filesystem/copy_options.h> |
540 | # include <__filesystem/directory_entry.h> |
541 | # include <__filesystem/directory_iterator.h> |
542 | # include <__filesystem/directory_options.h> |
543 | # include <__filesystem/file_status.h> |
544 | # include <__filesystem/file_time_type.h> |
545 | # include <__filesystem/file_type.h> |
546 | # include <__filesystem/filesystem_error.h> |
547 | # include <__filesystem/operations.h> |
548 | # include <__filesystem/path.h> |
549 | # include <__filesystem/path_iterator.h> |
550 | # include <__filesystem/perm_options.h> |
551 | # include <__filesystem/perms.h> |
552 | # include <__filesystem/recursive_directory_iterator.h> |
553 | # include <__filesystem/space_info.h> |
554 | # include <__filesystem/u8path.h> |
555 | #endif |
556 | |
557 | #include <version> |
558 | |
559 | // standard-mandated includes |
560 | |
561 | // [fs.filesystem.syn] |
562 | #include <compare> |
563 | |
564 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
565 | # pragma GCC system_header |
566 | #endif |
567 | |
568 | #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 |
569 | # include <concepts> |
570 | # include <cstdlib> |
571 | # include <cstring> |
572 | # include <iosfwd> |
573 | # include <new> |
574 | # include <system_error> |
575 | #endif |
576 | |
577 | #endif // _LIBCPP_FILESYSTEM |
578 | |