1// Filesystem directory utilities -*- C++ -*- 
2 
3// Copyright (C) 2014-2019 Free Software Foundation, Inc. 
4// 
5// This file is part of the GNU ISO C++ Library. This library is free 
6// software; you can redistribute it and/or modify it under the 
7// terms of the GNU General Public License as published by the 
8// Free Software Foundation; either version 3, or (at your option) 
9// any later version. 
10 
11// This library is distributed in the hope that it will be useful, 
12// but WITHOUT ANY WARRANTY; without even the implied warranty of 
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
14// GNU General Public License for more details. 
15 
16// Under Section 7 of GPL version 3, you are granted additional 
17// permissions described in the GCC Runtime Library Exception, version 
18// 3.1, as published by the Free Software Foundation. 
19 
20// You should have received a copy of the GNU General Public License and 
21// a copy of the GCC Runtime Library Exception along with this program; 
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 
23// <http://www.gnu.org/licenses/>. 
24 
25/** @file include/bits/fs_dir.h 
26 * This is an internal header file, included by other library headers. 
27 * Do not attempt to use it directly. @headername{filesystem} 
28 */ 
29 
30#ifndef _GLIBCXX_FS_DIR_H 
31#define _GLIBCXX_FS_DIR_H 1 
32 
33#if __cplusplus >= 201703L 
34# include <typeinfo> 
35# include <ext/concurrence.h> 
36# include <bits/unique_ptr.h> 
37# include <bits/shared_ptr.h> 
38 
39namespace std _GLIBCXX_VISIBILITY(default
40
41_GLIBCXX_BEGIN_NAMESPACE_VERSION 
42 
43namespace filesystem 
44
45 /** 
46 * @ingroup filesystem 
47 * @{ 
48 */ 
49 
50 class file_status 
51
52 public
53 // constructors and destructor 
54 file_status() noexcept : file_status(file_type::none) {} 
55 
56 explicit 
57 file_status(file_type __ft, perms __prms = perms::unknown) noexcept 
58 : _M_type(__ft), _M_perms(__prms) { } 
59 
60 file_status(const file_status&) noexcept = default
61 file_status(file_status&&) noexcept = default
62 ~file_status() = default
63 
64 file_status& operator=(const file_status&) noexcept = default
65 file_status& operator=(file_status&&) noexcept = default
66 
67 // observers 
68 file_type type() const noexcept { return _M_type; } 
69 perms permissions() const noexcept { return _M_perms; } 
70 
71 // modifiers 
72 void type(file_type __ft) noexcept { _M_type = __ft; } 
73 void permissions(perms __prms) noexcept { _M_perms = __prms; } 
74 
75 private
76 file_type _M_type
77 perms _M_perms
78 }; 
79 
80_GLIBCXX_BEGIN_NAMESPACE_CXX11 
81 
82 struct _Dir
83 class directory_iterator
84 class recursive_directory_iterator
85 
86 class directory_entry 
87
88 public
89 // constructors and destructor 
90 directory_entry() noexcept = default
91 directory_entry(const directory_entry&) = default
92 directory_entry(directory_entry&&) noexcept = default
93 
94 explicit 
95 directory_entry(const filesystem::path& __p
96 : _M_path(__p
97 { refresh(); } 
98 
99 directory_entry(const filesystem::path& __p, error_code& __ec
100 : _M_path(__p
101
102 refresh(__ec); 
103 if (__ec
104 _M_path.clear(); 
105
106 
107 ~directory_entry() = default
108 
109 // modifiers 
110 directory_entry& operator=(const directory_entry&) = default
111 directory_entry& operator=(directory_entry&&) noexcept = default
112 
113 void 
114 assign(const filesystem::path& __p
115
116 _M_path = __p
117 refresh(); 
118
119 
120 void 
121 assign(const filesystem::path& __p, error_code& __ec
122
123 _M_path = __p
124 refresh(__ec); 
125
126 
127 void 
128 replace_filename(const filesystem::path& __p
129
130 _M_path.replace_filename(__p); 
131 refresh(); 
132
133 
134 void 
135 replace_filename(const filesystem::path& __p, error_code& __ec
136
137 _M_path.replace_filename(__p); 
138 refresh(__ec); 
139
140 
141 void 
142 refresh() 
143 { _M_type = symlink_status().type(); } 
144 
145 void 
146 refresh(error_code& __ec) noexcept 
147 { _M_type = symlink_status(__ec).type(); } 
148 
149 // observers 
150 const filesystem::path& path() const noexcept { return _M_path; } 
151 operator const filesystem::path& () const noexcept { return _M_path; } 
152 
153 bool 
154 exists() const 
155 { return filesystem::exists(file_status{_M_file_type()}); } 
156 
157 bool 
158 exists(error_code& __ec) const noexcept 
159 { return filesystem::exists(file_status{_M_file_type(__ec)}); } 
160 
161 bool 
162 is_block_file() const 
163 { return _M_file_type() == file_type::block; } 
164 
165 bool 
166 is_block_file(error_code& __ec) const noexcept 
167 { return _M_file_type(__ec) == file_type::block; } 
168 
169 bool 
170 is_character_file() const 
171 { return _M_file_type() == file_type::character; } 
172 
173 bool 
174 is_character_file(error_code& __ec) const noexcept 
175 { return _M_file_type(__ec) == file_type::character; } 
176 
177 bool 
178 is_directory() const 
179 { return _M_file_type() == file_type::directory; } 
180 
181 bool 
182 is_directory(error_code& __ec) const noexcept 
183 { return _M_file_type(__ec) == file_type::directory; } 
184 
185 bool 
186 is_fifo() const 
187 { return _M_file_type() == file_type::fifo; } 
188 
189 bool 
190 is_fifo(error_code& __ec) const noexcept 
191 { return _M_file_type(__ec) == file_type::fifo; } 
192 
193 bool 
194 is_other() const 
195 { return filesystem::is_other(file_status{_M_file_type()}); } 
196 
197 bool 
198 is_other(error_code& __ec) const noexcept 
199 { return filesystem::is_other(file_status{_M_file_type(__ec)}); } 
200 
201 bool 
202 is_regular_file() const 
203 { return _M_file_type() == file_type::regular; } 
204 
205 bool 
206 is_regular_file(error_code& __ec) const noexcept 
207 { return _M_file_type(__ec) == file_type::regular; } 
208 
209 bool 
210 is_socket() const 
211 { return _M_file_type() == file_type::socket; } 
212 
213 bool 
214 is_socket(error_code& __ec) const noexcept 
215 { return _M_file_type(__ec) == file_type::socket; } 
216 
217 bool 
218 is_symlink() const 
219
220 if (_M_type != file_type::none
221 return _M_type == file_type::symlink
222 return symlink_status().type() == file_type::symlink
223
224 
225 bool 
226 is_symlink(error_code& __ec) const noexcept 
227
228 if (_M_type != file_type::none
229 return _M_type == file_type::symlink
230 return symlink_status(__ec).type() == file_type::symlink
231
232 
233 uintmax_t 
234 file_size() const 
235 { return filesystem::file_size(_M_path); } 
236 
237 uintmax_t 
238 file_size(error_code& __ec) const noexcept 
239 { return filesystem::file_size(_M_path, __ec); } 
240 
241 uintmax_t 
242 hard_link_count() const 
243 { return filesystem::hard_link_count(_M_path); } 
244 
245 uintmax_t 
246 hard_link_count(error_code& __ec) const noexcept 
247 { return filesystem::hard_link_count(_M_path, __ec); } 
248 
249 file_time_type 
250 last_write_time() const 
251 { return filesystem::last_write_time(_M_path); } 
252 
253 
254 file_time_type 
255 last_write_time(error_code& __ec) const noexcept 
256 { return filesystem::last_write_time(_M_path, __ec); } 
257 
258 file_status 
259 status() const 
260 { return filesystem::status(_M_path); } 
261 
262 file_status 
263 status(error_code& __ec) const noexcept 
264 { return filesystem::status(_M_path, __ec); } 
265 
266 file_status 
267 symlink_status() const 
268 { return filesystem::symlink_status(_M_path); } 
269 
270 file_status 
271 symlink_status(error_code& __ec) const noexcept 
272 { return filesystem::symlink_status(_M_path, __ec); } 
273 
274 bool 
275 operator< (const directory_entry& __rhs) const noexcept 
276 { return _M_path < __rhs._M_path; } 
277 
278 bool 
279 operator==(const directory_entry& __rhs) const noexcept 
280 { return _M_path == __rhs._M_path; } 
281 
282 bool 
283 operator!=(const directory_entry& __rhs) const noexcept 
284 { return _M_path != __rhs._M_path; } 
285 
286 bool 
287 operator<=(const directory_entry& __rhs) const noexcept 
288 { return _M_path <= __rhs._M_path; } 
289 
290 bool 
291 operator> (const directory_entry& __rhs) const noexcept 
292 { return _M_path > __rhs._M_path; } 
293 
294 bool 
295 operator>=(const directory_entry& __rhs) const noexcept 
296 { return _M_path >= __rhs._M_path; } 
297 
298 private
299 friend class _Dir
300 friend class directory_iterator
301 friend class recursive_directory_iterator
302 
303 // _GLIBCXX_RESOLVE_LIB_DEFECTS 
304 // 3171. LWG 2989 breaks directory_entry stream insertion 
305 template<typename _CharT, typename _Traits> 
306 friend basic_ostream<_CharT, _Traits>& 
307 operator<<(basic_ostream<_CharT, _Traits>& __os
308 const directory_entry& __d
309 { return __os << __d.path(); } 
310 
311 directory_entry(const filesystem::path& __p, file_type __t
312 : _M_path(__p), _M_type(__t
313 { } 
314 
315 // Equivalent to status().type() but uses cached value, if any. 
316 file_type 
317 _M_file_type() const 
318
319 if (_M_type != file_type::none && _M_type != file_type::symlink
320 return _M_type
321 return status().type(); 
322
323 
324 // Equivalent to status(__ec).type() but uses cached value, if any. 
325 file_type 
326 _M_file_type(error_code& __ec) const noexcept 
327
328 if (_M_type != file_type::none && _M_type != file_type::symlink
329
330 __ec.clear(); 
331 return _M_type
332
333 return status(__ec).type(); 
334
335 
336 filesystem::path _M_path
337 file_type _M_type = file_type::none
338 }; 
339 
340 struct __directory_iterator_proxy 
341
342 const directory_entry& operator*() const& noexcept { return _M_entry; } 
343 
344 directory_entry operator*() && noexcept { return std::move(_M_entry); } 
345 
346 private
347 friend class directory_iterator
348 friend class recursive_directory_iterator
349 
350 explicit 
351 __directory_iterator_proxy(const directory_entry& __e) : _M_entry(__e) { } 
352 
353 directory_entry _M_entry
354 }; 
355 
356 class directory_iterator 
357
358 public
359 typedef directory_entry value_type
360 typedef ptrdiff_t difference_type
361 typedef const directory_entry* pointer
362 typedef const directory_entry& reference
363 typedef input_iterator_tag iterator_category
364 
365 directory_iterator() = default
366 
367 explicit 
368 directory_iterator(const path& __p
369 : directory_iterator(__p, directory_options::none, nullptr) { } 
370 
371 directory_iterator(const path& __p, directory_options __options
372 : directory_iterator(__p, __options, nullptr) { } 
373 
374 directory_iterator(const path& __p, error_code& __ec
375 : directory_iterator(__p, directory_options::none, __ec) { } 
376 
377 directory_iterator(const path& __p, directory_options __options
378 error_code& __ec
379 : directory_iterator(__p, __options, &__ec) { } 
380 
381 directory_iterator(const directory_iterator& __rhs) = default
382 
383 directory_iterator(directory_iterator&& __rhs) noexcept = default
384 
385 ~directory_iterator() = default
386 
387 directory_iterator
388 operator=(const directory_iterator& __rhs) = default
389 
390 directory_iterator
391 operator=(directory_iterator&& __rhs) noexcept = default
392 
393 const directory_entry& operator*() const noexcept
394 const directory_entry* operator->() const noexcept { return &**this; } 
395 directory_iterator& operator++(); 
396 directory_iterator& increment(error_code& __ec); 
397 
398 __directory_iterator_proxy operator++(int
399
400 __directory_iterator_proxy __pr{**this}; 
401 ++*this
402 return __pr
403
404 
405 private
406 directory_iterator(const path&, directory_options, error_code*); 
407 
408 friend bool 
409 operator==(const directory_iterator& __lhs
410 const directory_iterator& __rhs) noexcept 
411
412 return !__rhs._M_dir.owner_before(__lhs._M_dir
413 && !__lhs._M_dir.owner_before(__rhs._M_dir); 
414
415 
416 friend bool 
417 operator!=(const directory_iterator& __lhs
418 const directory_iterator& __rhs) noexcept 
419 { return !(__lhs == __rhs); } 
420 
421 friend class recursive_directory_iterator
422 
423 std::__shared_ptr<_Dir> _M_dir
424 }; 
425 
426 inline directory_iterator 
427 begin(directory_iterator __iter) noexcept 
428 { return __iter; } 
429 
430 inline directory_iterator 
431 end(directory_iterator) noexcept 
432 { return directory_iterator(); } 
433 
434 class recursive_directory_iterator 
435
436 public
437 typedef directory_entry value_type
438 typedef ptrdiff_t difference_type
439 typedef const directory_entry* pointer
440 typedef const directory_entry& reference
441 typedef input_iterator_tag iterator_category
442 
443 recursive_directory_iterator() = default
444 
445 explicit 
446 recursive_directory_iterator(const path& __p
447 : recursive_directory_iterator(__p, directory_options::none, nullptr) { } 
448 
449 recursive_directory_iterator(const path& __p, directory_options __options
450 : recursive_directory_iterator(__p, __options, nullptr) { } 
451 
452 recursive_directory_iterator(const path& __p, directory_options __options
453 error_code& __ec
454 : recursive_directory_iterator(__p, __options, &__ec) { } 
455 
456 recursive_directory_iterator(const path& __p, error_code& __ec
457 : recursive_directory_iterator(__p, directory_options::none, &__ec) { } 
458 
459 recursive_directory_iterator
460 const recursive_directory_iterator&) = default
461 
462 recursive_directory_iterator(recursive_directory_iterator&&) = default
463 
464 ~recursive_directory_iterator(); 
465 
466 // observers 
467 directory_options options() const noexcept
468 int depth() const noexcept
469 bool recursion_pending() const noexcept
470 
471 const directory_entry& operator*() const noexcept
472 const directory_entry* operator->() const noexcept { return &**this; } 
473 
474 // modifiers 
475 recursive_directory_iterator
476 operator=(const recursive_directory_iterator& __rhs) noexcept
477 recursive_directory_iterator
478 operator=(recursive_directory_iterator&& __rhs) noexcept
479 
480 recursive_directory_iterator& operator++(); 
481 recursive_directory_iterator& increment(error_code& __ec); 
482 
483 __directory_iterator_proxy operator++(int
484
485 __directory_iterator_proxy __pr{**this}; 
486 ++*this
487 return __pr
488
489 
490 void pop(); 
491 void pop(error_code&); 
492 
493 void disable_recursion_pending() noexcept
494 
495 private
496 recursive_directory_iterator(const path&, directory_options, error_code*); 
497 
498 friend bool 
499 operator==(const recursive_directory_iterator& __lhs
500 const recursive_directory_iterator& __rhs) noexcept 
501
502 return !__rhs._M_dirs.owner_before(__lhs._M_dirs
503 && !__lhs._M_dirs.owner_before(__rhs._M_dirs); 
504
505 
506 friend bool 
507 operator!=(const recursive_directory_iterator& __lhs
508 const recursive_directory_iterator& __rhs) noexcept 
509 { return !(__lhs == __rhs); } 
510 
511 struct _Dir_stack
512 std::__shared_ptr<_Dir_stack> _M_dirs
513 }; 
514 
515 inline recursive_directory_iterator 
516 begin(recursive_directory_iterator __iter) noexcept 
517 { return __iter; } 
518 
519 inline recursive_directory_iterator 
520 end(recursive_directory_iterator) noexcept 
521 { return recursive_directory_iterator(); } 
522 
523_GLIBCXX_END_NAMESPACE_CXX11 
524 
525 // @} group filesystem 
526} // namespace filesystem 
527 
528 // Use explicit instantiations of these types. Any inconsistency in the 
529 // value of __default_lock_policy between code including this header and 
530 // the library will cause a linker error. 
531 extern template class 
532 __shared_ptr<filesystem::_Dir>; 
533 extern template class 
534 __shared_ptr<filesystem::recursive_directory_iterator::_Dir_stack>; 
535 
536_GLIBCXX_END_NAMESPACE_VERSION 
537} // namespace std 
538 
539#endif // C++17 
540 
541#endif // _GLIBCXX_FS_DIR_H 
542