libstdc++
|
00001 // Filesystem directory utilities -*- C++ -*- 00002 00003 // Copyright (C) 2014-2019 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 3, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // Under Section 7 of GPL version 3, you are granted additional 00017 // permissions described in the GCC Runtime Library Exception, version 00018 // 3.1, as published by the Free Software Foundation. 00019 00020 // You should have received a copy of the GNU General Public License and 00021 // a copy of the GCC Runtime Library Exception along with this program; 00022 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 // <http://www.gnu.org/licenses/>. 00024 00025 /** @file include/bits/fs_dir.h 00026 * This is an internal header file, included by other library headers. 00027 * Do not attempt to use it directly. @headername{filesystem} 00028 */ 00029 00030 #ifndef _GLIBCXX_FS_DIR_H 00031 #define _GLIBCXX_FS_DIR_H 1 00032 00033 #if __cplusplus >= 201703L 00034 # include <typeinfo> 00035 # include <ext/concurrence.h> 00036 # include <bits/unique_ptr.h> 00037 # include <bits/shared_ptr.h> 00038 00039 namespace std _GLIBCXX_VISIBILITY(default) 00040 { 00041 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00042 00043 namespace filesystem 00044 { 00045 /** 00046 * @ingroup filesystem 00047 * @{ 00048 */ 00049 00050 class file_status 00051 { 00052 public: 00053 // constructors and destructor 00054 file_status() noexcept : file_status(file_type::none) {} 00055 00056 explicit 00057 file_status(file_type __ft, perms __prms = perms::unknown) noexcept 00058 : _M_type(__ft), _M_perms(__prms) { } 00059 00060 file_status(const file_status&) noexcept = default; 00061 file_status(file_status&&) noexcept = default; 00062 ~file_status() = default; 00063 00064 file_status& operator=(const file_status&) noexcept = default; 00065 file_status& operator=(file_status&&) noexcept = default; 00066 00067 // observers 00068 file_type type() const noexcept { return _M_type; } 00069 perms permissions() const noexcept { return _M_perms; } 00070 00071 // modifiers 00072 void type(file_type __ft) noexcept { _M_type = __ft; } 00073 void permissions(perms __prms) noexcept { _M_perms = __prms; } 00074 00075 private: 00076 file_type _M_type; 00077 perms _M_perms; 00078 }; 00079 00080 _GLIBCXX_BEGIN_NAMESPACE_CXX11 00081 00082 struct _Dir; 00083 class directory_iterator; 00084 class recursive_directory_iterator; 00085 00086 class directory_entry 00087 { 00088 public: 00089 // constructors and destructor 00090 directory_entry() noexcept = default; 00091 directory_entry(const directory_entry&) = default; 00092 directory_entry(directory_entry&&) noexcept = default; 00093 00094 explicit 00095 directory_entry(const filesystem::path& __p) 00096 : _M_path(__p) 00097 { refresh(); } 00098 00099 directory_entry(const filesystem::path& __p, error_code& __ec) 00100 : _M_path(__p) 00101 { 00102 refresh(__ec); 00103 if (__ec) 00104 _M_path.clear(); 00105 } 00106 00107 ~directory_entry() = default; 00108 00109 // modifiers 00110 directory_entry& operator=(const directory_entry&) = default; 00111 directory_entry& operator=(directory_entry&&) noexcept = default; 00112 00113 void 00114 assign(const filesystem::path& __p) 00115 { 00116 _M_path = __p; 00117 refresh(); 00118 } 00119 00120 void 00121 assign(const filesystem::path& __p, error_code& __ec) 00122 { 00123 _M_path = __p; 00124 refresh(__ec); 00125 } 00126 00127 void 00128 replace_filename(const filesystem::path& __p) 00129 { 00130 _M_path.replace_filename(__p); 00131 refresh(); 00132 } 00133 00134 void 00135 replace_filename(const filesystem::path& __p, error_code& __ec) 00136 { 00137 _M_path.replace_filename(__p); 00138 refresh(__ec); 00139 } 00140 00141 void 00142 refresh() 00143 { _M_type = symlink_status().type(); } 00144 00145 void 00146 refresh(error_code& __ec) noexcept 00147 { _M_type = symlink_status(__ec).type(); } 00148 00149 // observers 00150 const filesystem::path& path() const noexcept { return _M_path; } 00151 operator const filesystem::path& () const noexcept { return _M_path; } 00152 00153 bool 00154 exists() const 00155 { return filesystem::exists(file_status{_M_file_type()}); } 00156 00157 bool 00158 exists(error_code& __ec) const noexcept 00159 { return filesystem::exists(file_status{_M_file_type(__ec)}); } 00160 00161 bool 00162 is_block_file() const 00163 { return _M_file_type() == file_type::block; } 00164 00165 bool 00166 is_block_file(error_code& __ec) const noexcept 00167 { return _M_file_type(__ec) == file_type::block; } 00168 00169 bool 00170 is_character_file() const 00171 { return _M_file_type() == file_type::character; } 00172 00173 bool 00174 is_character_file(error_code& __ec) const noexcept 00175 { return _M_file_type(__ec) == file_type::character; } 00176 00177 bool 00178 is_directory() const 00179 { return _M_file_type() == file_type::directory; } 00180 00181 bool 00182 is_directory(error_code& __ec) const noexcept 00183 { return _M_file_type(__ec) == file_type::directory; } 00184 00185 bool 00186 is_fifo() const 00187 { return _M_file_type() == file_type::fifo; } 00188 00189 bool 00190 is_fifo(error_code& __ec) const noexcept 00191 { return _M_file_type(__ec) == file_type::fifo; } 00192 00193 bool 00194 is_other() const 00195 { return filesystem::is_other(file_status{_M_file_type()}); } 00196 00197 bool 00198 is_other(error_code& __ec) const noexcept 00199 { return filesystem::is_other(file_status{_M_file_type(__ec)}); } 00200 00201 bool 00202 is_regular_file() const 00203 { return _M_file_type() == file_type::regular; } 00204 00205 bool 00206 is_regular_file(error_code& __ec) const noexcept 00207 { return _M_file_type(__ec) == file_type::regular; } 00208 00209 bool 00210 is_socket() const 00211 { return _M_file_type() == file_type::socket; } 00212 00213 bool 00214 is_socket(error_code& __ec) const noexcept 00215 { return _M_file_type(__ec) == file_type::socket; } 00216 00217 bool 00218 is_symlink() const 00219 { 00220 if (_M_type != file_type::none) 00221 return _M_type == file_type::symlink; 00222 return symlink_status().type() == file_type::symlink; 00223 } 00224 00225 bool 00226 is_symlink(error_code& __ec) const noexcept 00227 { 00228 if (_M_type != file_type::none) 00229 return _M_type == file_type::symlink; 00230 return symlink_status(__ec).type() == file_type::symlink; 00231 } 00232 00233 uintmax_t 00234 file_size() const 00235 { return filesystem::file_size(_M_path); } 00236 00237 uintmax_t 00238 file_size(error_code& __ec) const noexcept 00239 { return filesystem::file_size(_M_path, __ec); } 00240 00241 uintmax_t 00242 hard_link_count() const 00243 { return filesystem::hard_link_count(_M_path); } 00244 00245 uintmax_t 00246 hard_link_count(error_code& __ec) const noexcept 00247 { return filesystem::hard_link_count(_M_path, __ec); } 00248 00249 file_time_type 00250 last_write_time() const 00251 { return filesystem::last_write_time(_M_path); } 00252 00253 00254 file_time_type 00255 last_write_time(error_code& __ec) const noexcept 00256 { return filesystem::last_write_time(_M_path, __ec); } 00257 00258 file_status 00259 status() const 00260 { return filesystem::status(_M_path); } 00261 00262 file_status 00263 status(error_code& __ec) const noexcept 00264 { return filesystem::status(_M_path, __ec); } 00265 00266 file_status 00267 symlink_status() const 00268 { return filesystem::symlink_status(_M_path); } 00269 00270 file_status 00271 symlink_status(error_code& __ec) const noexcept 00272 { return filesystem::symlink_status(_M_path, __ec); } 00273 00274 bool 00275 operator< (const directory_entry& __rhs) const noexcept 00276 { return _M_path < __rhs._M_path; } 00277 00278 bool 00279 operator==(const directory_entry& __rhs) const noexcept 00280 { return _M_path == __rhs._M_path; } 00281 00282 bool 00283 operator!=(const directory_entry& __rhs) const noexcept 00284 { return _M_path != __rhs._M_path; } 00285 00286 bool 00287 operator<=(const directory_entry& __rhs) const noexcept 00288 { return _M_path <= __rhs._M_path; } 00289 00290 bool 00291 operator> (const directory_entry& __rhs) const noexcept 00292 { return _M_path > __rhs._M_path; } 00293 00294 bool 00295 operator>=(const directory_entry& __rhs) const noexcept 00296 { return _M_path >= __rhs._M_path; } 00297 00298 private: 00299 friend class _Dir; 00300 friend class directory_iterator; 00301 friend class recursive_directory_iterator; 00302 00303 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00304 // 3171. LWG 2989 breaks directory_entry stream insertion 00305 template<typename _CharT, typename _Traits> 00306 friend basic_ostream<_CharT, _Traits>& 00307 operator<<(basic_ostream<_CharT, _Traits>& __os, 00308 const directory_entry& __d) 00309 { return __os << __d.path(); } 00310 00311 directory_entry(const filesystem::path& __p, file_type __t) 00312 : _M_path(__p), _M_type(__t) 00313 { } 00314 00315 // Equivalent to status().type() but uses cached value, if any. 00316 file_type 00317 _M_file_type() const 00318 { 00319 if (_M_type != file_type::none && _M_type != file_type::symlink) 00320 return _M_type; 00321 return status().type(); 00322 } 00323 00324 // Equivalent to status(__ec).type() but uses cached value, if any. 00325 file_type 00326 _M_file_type(error_code& __ec) const noexcept 00327 { 00328 if (_M_type != file_type::none && _M_type != file_type::symlink) 00329 { 00330 __ec.clear(); 00331 return _M_type; 00332 } 00333 return status(__ec).type(); 00334 } 00335 00336 filesystem::path _M_path; 00337 file_type _M_type = file_type::none; 00338 }; 00339 00340 struct __directory_iterator_proxy 00341 { 00342 const directory_entry& operator*() const& noexcept { return _M_entry; } 00343 00344 directory_entry operator*() && noexcept { return std::move(_M_entry); } 00345 00346 private: 00347 friend class directory_iterator; 00348 friend class recursive_directory_iterator; 00349 00350 explicit 00351 __directory_iterator_proxy(const directory_entry& __e) : _M_entry(__e) { } 00352 00353 directory_entry _M_entry; 00354 }; 00355 00356 class directory_iterator 00357 { 00358 public: 00359 typedef directory_entry value_type; 00360 typedef ptrdiff_t difference_type; 00361 typedef const directory_entry* pointer; 00362 typedef const directory_entry& reference; 00363 typedef input_iterator_tag iterator_category; 00364 00365 directory_iterator() = default; 00366 00367 explicit 00368 directory_iterator(const path& __p) 00369 : directory_iterator(__p, directory_options::none, nullptr) { } 00370 00371 directory_iterator(const path& __p, directory_options __options) 00372 : directory_iterator(__p, __options, nullptr) { } 00373 00374 directory_iterator(const path& __p, error_code& __ec) 00375 : directory_iterator(__p, directory_options::none, __ec) { } 00376 00377 directory_iterator(const path& __p, directory_options __options, 00378 error_code& __ec) 00379 : directory_iterator(__p, __options, &__ec) { } 00380 00381 directory_iterator(const directory_iterator& __rhs) = default; 00382 00383 directory_iterator(directory_iterator&& __rhs) noexcept = default; 00384 00385 ~directory_iterator() = default; 00386 00387 directory_iterator& 00388 operator=(const directory_iterator& __rhs) = default; 00389 00390 directory_iterator& 00391 operator=(directory_iterator&& __rhs) noexcept = default; 00392 00393 const directory_entry& operator*() const noexcept; 00394 const directory_entry* operator->() const noexcept { return &**this; } 00395 directory_iterator& operator++(); 00396 directory_iterator& increment(error_code& __ec); 00397 00398 __directory_iterator_proxy operator++(int) 00399 { 00400 __directory_iterator_proxy __pr{**this}; 00401 ++*this; 00402 return __pr; 00403 } 00404 00405 private: 00406 directory_iterator(const path&, directory_options, error_code*); 00407 00408 friend bool 00409 operator==(const directory_iterator& __lhs, 00410 const directory_iterator& __rhs) noexcept 00411 { 00412 return !__rhs._M_dir.owner_before(__lhs._M_dir) 00413 && !__lhs._M_dir.owner_before(__rhs._M_dir); 00414 } 00415 00416 friend bool 00417 operator!=(const directory_iterator& __lhs, 00418 const directory_iterator& __rhs) noexcept 00419 { return !(__lhs == __rhs); } 00420 00421 friend class recursive_directory_iterator; 00422 00423 std::__shared_ptr<_Dir> _M_dir; 00424 }; 00425 00426 inline directory_iterator 00427 begin(directory_iterator __iter) noexcept 00428 { return __iter; } 00429 00430 inline directory_iterator 00431 end(directory_iterator) noexcept 00432 { return directory_iterator(); } 00433 00434 class recursive_directory_iterator 00435 { 00436 public: 00437 typedef directory_entry value_type; 00438 typedef ptrdiff_t difference_type; 00439 typedef const directory_entry* pointer; 00440 typedef const directory_entry& reference; 00441 typedef input_iterator_tag iterator_category; 00442 00443 recursive_directory_iterator() = default; 00444 00445 explicit 00446 recursive_directory_iterator(const path& __p) 00447 : recursive_directory_iterator(__p, directory_options::none, nullptr) { } 00448 00449 recursive_directory_iterator(const path& __p, directory_options __options) 00450 : recursive_directory_iterator(__p, __options, nullptr) { } 00451 00452 recursive_directory_iterator(const path& __p, directory_options __options, 00453 error_code& __ec) 00454 : recursive_directory_iterator(__p, __options, &__ec) { } 00455 00456 recursive_directory_iterator(const path& __p, error_code& __ec) 00457 : recursive_directory_iterator(__p, directory_options::none, &__ec) { } 00458 00459 recursive_directory_iterator( 00460 const recursive_directory_iterator&) = default; 00461 00462 recursive_directory_iterator(recursive_directory_iterator&&) = default; 00463 00464 ~recursive_directory_iterator(); 00465 00466 // observers 00467 directory_options options() const noexcept; 00468 int depth() const noexcept; 00469 bool recursion_pending() const noexcept; 00470 00471 const directory_entry& operator*() const noexcept; 00472 const directory_entry* operator->() const noexcept { return &**this; } 00473 00474 // modifiers 00475 recursive_directory_iterator& 00476 operator=(const recursive_directory_iterator& __rhs) noexcept; 00477 recursive_directory_iterator& 00478 operator=(recursive_directory_iterator&& __rhs) noexcept; 00479 00480 recursive_directory_iterator& operator++(); 00481 recursive_directory_iterator& increment(error_code& __ec); 00482 00483 __directory_iterator_proxy operator++(int) 00484 { 00485 __directory_iterator_proxy __pr{**this}; 00486 ++*this; 00487 return __pr; 00488 } 00489 00490 void pop(); 00491 void pop(error_code&); 00492 00493 void disable_recursion_pending() noexcept; 00494 00495 private: 00496 recursive_directory_iterator(const path&, directory_options, error_code*); 00497 00498 friend bool 00499 operator==(const recursive_directory_iterator& __lhs, 00500 const recursive_directory_iterator& __rhs) noexcept 00501 { 00502 return !__rhs._M_dirs.owner_before(__lhs._M_dirs) 00503 && !__lhs._M_dirs.owner_before(__rhs._M_dirs); 00504 } 00505 00506 friend bool 00507 operator!=(const recursive_directory_iterator& __lhs, 00508 const recursive_directory_iterator& __rhs) noexcept 00509 { return !(__lhs == __rhs); } 00510 00511 struct _Dir_stack; 00512 std::__shared_ptr<_Dir_stack> _M_dirs; 00513 }; 00514 00515 inline recursive_directory_iterator 00516 begin(recursive_directory_iterator __iter) noexcept 00517 { return __iter; } 00518 00519 inline recursive_directory_iterator 00520 end(recursive_directory_iterator) noexcept 00521 { return recursive_directory_iterator(); } 00522 00523 _GLIBCXX_END_NAMESPACE_CXX11 00524 00525 // @} group filesystem 00526 } // namespace filesystem 00527 00528 // Use explicit instantiations of these types. Any inconsistency in the 00529 // value of __default_lock_policy between code including this header and 00530 // the library will cause a linker error. 00531 extern template class 00532 __shared_ptr<filesystem::_Dir>; 00533 extern template class 00534 __shared_ptr<filesystem::recursive_directory_iterator::_Dir_stack>; 00535 00536 _GLIBCXX_END_NAMESPACE_VERSION 00537 } // namespace std 00538 00539 #endif // C++17 00540 00541 #endif // _GLIBCXX_FS_DIR_H