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
277class 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
524template <>
525inline constexpr bool std::ranges::enable_borrowed_range<std::filesystem::directory_iterator> = true;
526template <>
527inline constexpr bool std::ranges::enable_borrowed_range<std::filesystem::recursive_directory_iterator> = true;
528
529template <>
530inline constexpr bool std::ranges::enable_view<std::filesystem::directory_iterator> = true;
531template <>
532inline 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