Line data Source code
1 : // boost/filesystem/operations.hpp ---------------------------------------------------//
2 :
3 : // Copyright Beman Dawes 2002-2009
4 : // Copyright Jan Langer 2002
5 : // Copyright Dietmar Kuehl 2001
6 : // Copyright Vladimir Prus 2002
7 :
8 : // Distributed under the Boost Software License, Version 1.0.
9 : // See http://www.boost.org/LICENSE_1_0.txt
10 :
11 : // Library home page: http://www.boost.org/libs/filesystem
12 :
13 : //--------------------------------------------------------------------------------------//
14 :
15 : #ifndef BOOST_FILESYSTEM3_OPERATIONS_HPP
16 : #define BOOST_FILESYSTEM3_OPERATIONS_HPP
17 :
18 : #include <boost/config.hpp>
19 :
20 : # if defined( BOOST_NO_STD_WSTRING )
21 : # error Configuration not supported: Boost.Filesystem V3 and later requires std::wstring support
22 : # endif
23 :
24 : #include <boost/filesystem/config.hpp>
25 : #include <boost/filesystem/path.hpp>
26 :
27 : #include <boost/core/scoped_enum.hpp>
28 : #include <boost/detail/bitmask.hpp>
29 : #include <boost/system/error_code.hpp>
30 : #include <boost/system/system_error.hpp>
31 : #include <boost/smart_ptr/intrusive_ptr.hpp>
32 : #include <boost/smart_ptr/intrusive_ref_counter.hpp>
33 : #include <boost/type_traits/is_same.hpp>
34 : #include <boost/cstdint.hpp>
35 : #include <boost/assert.hpp>
36 : #include <string>
37 : #include <utility> // std::move
38 : #include <ctime>
39 : #include <vector>
40 : #include <stack>
41 : #include <new> // std::nothrow, std::bad_alloc
42 :
43 : #ifdef BOOST_WINDOWS_API
44 : # include <fstream>
45 : #endif
46 :
47 : #include <boost/config/abi_prefix.hpp> // must be the last #include
48 :
49 : //--------------------------------------------------------------------------------------//
50 :
51 : namespace boost
52 : {
53 : namespace filesystem
54 : {
55 :
56 : //--------------------------------------------------------------------------------------//
57 : // //
58 : // class filesystem_error //
59 : // //
60 : //--------------------------------------------------------------------------------------//
61 :
62 : class BOOST_SYMBOL_VISIBLE filesystem_error :
63 : public system::system_error
64 : {
65 : // see http://www.boost.org/more/error_handling.html for design rationale
66 :
67 : // all functions are inline to avoid issues with crossing dll boundaries
68 :
69 : // functions previously throw() are now BOOST_NOEXCEPT_OR_NOTHROW
70 : // functions previously without throw() are now BOOST_NOEXCEPT
71 :
72 : public:
73 : // compiler generates copy constructor and copy assignment
74 :
75 : filesystem_error(
76 : const std::string & what_arg, system::error_code ec) BOOST_NOEXCEPT :
77 : system::system_error(ec, what_arg)
78 : {
79 : try
80 : {
81 : m_imp_ptr.reset(new impl());
82 : }
83 : catch (...) { m_imp_ptr.reset(); }
84 : }
85 :
86 0 : filesystem_error(
87 : const std::string & what_arg, const path& path1_arg,
88 0 : system::error_code ec) BOOST_NOEXCEPT :
89 0 : system::system_error(ec, what_arg)
90 : {
91 0 : try
92 : {
93 0 : m_imp_ptr.reset(new impl(path1_arg));
94 : }
95 0 : catch (...) { m_imp_ptr.reset(); }
96 0 : }
97 :
98 : filesystem_error(
99 : const std::string & what_arg, const path& path1_arg,
100 : const path& path2_arg, system::error_code ec) BOOST_NOEXCEPT :
101 : system::system_error(ec, what_arg)
102 : {
103 : try
104 : {
105 : m_imp_ptr.reset(new impl(path1_arg, path2_arg));
106 : }
107 : catch (...) { m_imp_ptr.reset(); }
108 : }
109 :
110 0 : ~filesystem_error() BOOST_NOEXCEPT_OR_NOTHROW {}
111 :
112 : const path& path1() const BOOST_NOEXCEPT
113 : {
114 : static const path empty_path;
115 : return m_imp_ptr.get() ? m_imp_ptr->m_path1 : empty_path;
116 : }
117 : const path& path2() const BOOST_NOEXCEPT
118 : {
119 : static const path empty_path;
120 : return m_imp_ptr.get() ? m_imp_ptr->m_path2 : empty_path;
121 : }
122 :
123 0 : const char* what() const BOOST_NOEXCEPT_OR_NOTHROW
124 : {
125 0 : if (!m_imp_ptr.get())
126 0 : return system::system_error::what();
127 :
128 0 : try
129 : {
130 0 : if (m_imp_ptr->m_what.empty())
131 : {
132 0 : m_imp_ptr->m_what = system::system_error::what();
133 0 : if (!m_imp_ptr->m_path1.empty())
134 : {
135 0 : m_imp_ptr->m_what += ": \"";
136 0 : m_imp_ptr->m_what += m_imp_ptr->m_path1.string();
137 0 : m_imp_ptr->m_what += "\"";
138 : }
139 0 : if (!m_imp_ptr->m_path2.empty())
140 : {
141 0 : m_imp_ptr->m_what += ", \"";
142 0 : m_imp_ptr->m_what += m_imp_ptr->m_path2.string();
143 0 : m_imp_ptr->m_what += "\"";
144 : }
145 : }
146 0 : return m_imp_ptr->m_what.c_str();
147 : }
148 0 : catch (...)
149 : {
150 0 : return system::system_error::what();
151 : }
152 : }
153 :
154 : private:
155 : struct impl :
156 : public boost::intrusive_ref_counter< impl >
157 : {
158 : path m_path1; // may be empty()
159 : path m_path2; // may be empty()
160 : std::string m_what; // not built until needed
161 :
162 : BOOST_DEFAULTED_FUNCTION(impl(), {})
163 0 : explicit impl(path const& path1) : m_path1(path1) {}
164 : impl(path const& path1, path const& path2) : m_path1(path1), m_path2(path2) {}
165 : };
166 : boost::intrusive_ptr< impl > m_imp_ptr;
167 : };
168 :
169 : //--------------------------------------------------------------------------------------//
170 : // file_type //
171 : //--------------------------------------------------------------------------------------//
172 :
173 : enum file_type
174 : {
175 : status_error,
176 : # ifndef BOOST_FILESYSTEM_NO_DEPRECATED
177 : status_unknown = status_error,
178 : # endif
179 : file_not_found,
180 : regular_file,
181 : directory_file,
182 : // the following may not apply to some operating systems or file systems
183 : symlink_file,
184 : block_file,
185 : character_file,
186 : fifo_file,
187 : socket_file,
188 : reparse_file, // Windows: FILE_ATTRIBUTE_REPARSE_POINT that is not a symlink
189 : type_unknown, // file does exist, but isn't one of the above types or
190 : // we don't have strong enough permission to find its type
191 :
192 : _detail_directory_symlink // internal use only; never exposed to users
193 : };
194 :
195 : //--------------------------------------------------------------------------------------//
196 : // perms //
197 : //--------------------------------------------------------------------------------------//
198 :
199 : enum perms
200 : {
201 : no_perms = 0, // file_not_found is no_perms rather than perms_not_known
202 :
203 : // POSIX equivalent macros given in comments.
204 : // Values are from POSIX and are given in octal per the POSIX standard.
205 :
206 : // permission bits
207 :
208 : owner_read = 0400, // S_IRUSR, Read permission, owner
209 : owner_write = 0200, // S_IWUSR, Write permission, owner
210 : owner_exe = 0100, // S_IXUSR, Execute/search permission, owner
211 : owner_all = 0700, // S_IRWXU, Read, write, execute/search by owner
212 :
213 : group_read = 040, // S_IRGRP, Read permission, group
214 : group_write = 020, // S_IWGRP, Write permission, group
215 : group_exe = 010, // S_IXGRP, Execute/search permission, group
216 : group_all = 070, // S_IRWXG, Read, write, execute/search by group
217 :
218 : others_read = 04, // S_IROTH, Read permission, others
219 : others_write = 02, // S_IWOTH, Write permission, others
220 : others_exe = 01, // S_IXOTH, Execute/search permission, others
221 : others_all = 07, // S_IRWXO, Read, write, execute/search by others
222 :
223 : all_all = 0777, // owner_all|group_all|others_all
224 :
225 : // other POSIX bits
226 :
227 : set_uid_on_exe = 04000, // S_ISUID, Set-user-ID on execution
228 : set_gid_on_exe = 02000, // S_ISGID, Set-group-ID on execution
229 : sticky_bit = 01000, // S_ISVTX,
230 : // (POSIX XSI) On directories, restricted deletion flag
231 : // (V7) 'sticky bit': save swapped text even after use
232 : // (SunOS) On non-directories: don't cache this file
233 : // (SVID-v4.2) On directories: restricted deletion flag
234 : // Also see http://en.wikipedia.org/wiki/Sticky_bit
235 :
236 : perms_mask = 07777, // all_all|set_uid_on_exe|set_gid_on_exe|sticky_bit
237 :
238 : perms_not_known = 0xFFFF, // present when directory_entry cache not loaded
239 :
240 : // options for permissions() function
241 :
242 : add_perms = 0x1000, // adds the given permission bits to the current bits
243 : remove_perms = 0x2000, // removes the given permission bits from the current bits;
244 : // choose add_perms or remove_perms, not both; if neither add_perms
245 : // nor remove_perms is given, replace the current bits with
246 : // the given bits.
247 :
248 : symlink_perms = 0x4000, // on POSIX, don't resolve symlinks; implied on Windows
249 :
250 : // BOOST_BITMASK op~ casts to int32_least_t, producing invalid enum values
251 : _detail_extend_perms_32_1 = 0x7fffffff,
252 : _detail_extend_perms_32_2 = -0x7fffffff-1
253 : };
254 :
255 : BOOST_BITMASK(perms)
256 :
257 : //--------------------------------------------------------------------------------------//
258 : // file_status //
259 : //--------------------------------------------------------------------------------------//
260 :
261 : class file_status
262 : {
263 : public:
264 0 : BOOST_CONSTEXPR file_status() BOOST_NOEXCEPT :
265 0 : m_value(status_error), m_perms(perms_not_known)
266 : {
267 : }
268 : explicit BOOST_CONSTEXPR file_status(file_type v) BOOST_NOEXCEPT :
269 : m_value(v), m_perms(perms_not_known)
270 : {
271 : }
272 : BOOST_CONSTEXPR file_status(file_type v, perms prms) BOOST_NOEXCEPT :
273 : m_value(v), m_perms(prms)
274 : {
275 : }
276 :
277 : // As of October 2015 the interaction between noexcept and =default is so troublesome
278 : // for VC++, GCC, and probably other compilers, that =default is not used with noexcept
279 : // functions. GCC is not even consistent for the same release on different platforms.
280 :
281 : BOOST_CONSTEXPR file_status(const file_status& rhs) BOOST_NOEXCEPT :
282 : m_value(rhs.m_value), m_perms(rhs.m_perms)
283 : {
284 : }
285 : BOOST_CXX14_CONSTEXPR file_status& operator=(const file_status& rhs) BOOST_NOEXCEPT
286 : {
287 : m_value = rhs.m_value;
288 : m_perms = rhs.m_perms;
289 : return *this;
290 : }
291 :
292 : # if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
293 : // Note: std::move is not constexpr in C++11, that's why we're not using it here
294 : BOOST_CONSTEXPR file_status(file_status&& rhs) BOOST_NOEXCEPT :
295 : m_value(static_cast< file_type&& >(rhs.m_value)), m_perms(static_cast< enum perms&& >(rhs.m_perms))
296 : {
297 : }
298 : BOOST_CXX14_CONSTEXPR file_status& operator=(file_status&& rhs) BOOST_NOEXCEPT
299 : {
300 : m_value = std::move(rhs.m_value);
301 : m_perms = std::move(rhs.m_perms);
302 : return *this;
303 : }
304 : # endif
305 :
306 : // observers
307 1555 : BOOST_CONSTEXPR file_type type() const BOOST_NOEXCEPT { return m_value; }
308 : BOOST_CONSTEXPR perms permissions() const BOOST_NOEXCEPT { return m_perms; }
309 :
310 : // modifiers
311 : BOOST_CXX14_CONSTEXPR void type(file_type v) BOOST_NOEXCEPT { m_value = v; }
312 : BOOST_CXX14_CONSTEXPR void permissions(perms prms) BOOST_NOEXCEPT { m_perms = prms; }
313 :
314 : BOOST_CONSTEXPR bool operator==(const file_status& rhs) const BOOST_NOEXCEPT
315 : {
316 : return type() == rhs.type() &&
317 : permissions() == rhs.permissions();
318 : }
319 : BOOST_CONSTEXPR bool operator!=(const file_status& rhs) const BOOST_NOEXCEPT
320 : {
321 : return !(*this == rhs);
322 : }
323 :
324 : private:
325 : file_type m_value;
326 : enum perms m_perms;
327 : };
328 :
329 : inline BOOST_CONSTEXPR bool type_present(file_status f) BOOST_NOEXCEPT
330 : { return f.type() != status_error; }
331 : inline BOOST_CONSTEXPR bool permissions_present(file_status f) BOOST_NOEXCEPT
332 : {return f.permissions() != perms_not_known;}
333 : inline BOOST_CONSTEXPR bool status_known(file_status f) BOOST_NOEXCEPT
334 : { return filesystem::type_present(f) && filesystem::permissions_present(f); }
335 637 : inline BOOST_CONSTEXPR bool exists(file_status f) BOOST_NOEXCEPT
336 637 : { return f.type() != status_error
337 637 : && f.type() != file_not_found; }
338 0 : inline BOOST_CONSTEXPR bool is_regular_file(file_status f) BOOST_NOEXCEPT
339 0 : { return f.type() == regular_file; }
340 281 : inline BOOST_CONSTEXPR bool is_directory(file_status f) BOOST_NOEXCEPT
341 281 : { return f.type() == directory_file; }
342 0 : inline BOOST_CONSTEXPR bool is_symlink(file_status f) BOOST_NOEXCEPT
343 0 : { return f.type() == symlink_file; }
344 : inline BOOST_CONSTEXPR bool is_other(file_status f) BOOST_NOEXCEPT
345 : { return filesystem::exists(f) && !filesystem::is_regular_file(f)
346 : && !filesystem::is_directory(f) && !filesystem::is_symlink(f); }
347 :
348 : # ifndef BOOST_FILESYSTEM_NO_DEPRECATED
349 : inline bool is_regular(file_status f) BOOST_NOEXCEPT { return f.type() == regular_file; }
350 : # endif
351 :
352 : struct space_info
353 : {
354 : // all values are byte counts
355 : boost::uintmax_t capacity;
356 : boost::uintmax_t free; // <= capacity
357 : boost::uintmax_t available; // <= free
358 : };
359 :
360 : BOOST_SCOPED_ENUM_DECLARE_BEGIN(copy_option)
361 : {none=0, fail_if_exists = none, overwrite_if_exists}
362 : BOOST_SCOPED_ENUM_DECLARE_END(copy_option)
363 :
364 : //--------------------------------------------------------------------------------------//
365 : // implementation details //
366 : //--------------------------------------------------------------------------------------//
367 :
368 : namespace detail
369 : {
370 : // We cannot pass a BOOST_SCOPED_ENUM to a compled function because it will result
371 : // in an undefined reference if the library is compled with -std=c++0x but the use
372 : // is compiled in C++03 mode, or vice versa. See tickets 6124, 6779, 10038.
373 : enum copy_option {none=0, fail_if_exists = none, overwrite_if_exists};
374 :
375 : BOOST_FILESYSTEM_DECL
376 : file_status status(const path&p, system::error_code* ec=0);
377 : BOOST_FILESYSTEM_DECL
378 : file_status symlink_status(const path& p, system::error_code* ec=0);
379 : BOOST_FILESYSTEM_DECL
380 : bool is_empty(const path& p, system::error_code* ec=0);
381 : BOOST_FILESYSTEM_DECL
382 : path initial_path(system::error_code* ec=0);
383 : BOOST_FILESYSTEM_DECL
384 : path canonical(const path& p, const path& base, system::error_code* ec=0);
385 : BOOST_FILESYSTEM_DECL
386 : void copy(const path& from, const path& to, system::error_code* ec=0);
387 : BOOST_FILESYSTEM_DECL
388 : void copy_directory(const path& from, const path& to, system::error_code* ec=0);
389 : BOOST_FILESYSTEM_DECL
390 : void copy_file(const path& from, const path& to, // See ticket #2925
391 : detail::copy_option option, system::error_code* ec=0);
392 : BOOST_FILESYSTEM_DECL
393 : void copy_symlink(const path& existing_symlink, const path& new_symlink, system::error_code* ec=0);
394 : BOOST_FILESYSTEM_DECL
395 : bool create_directories(const path& p, system::error_code* ec=0);
396 : BOOST_FILESYSTEM_DECL
397 : bool create_directory(const path& p, system::error_code* ec=0);
398 : BOOST_FILESYSTEM_DECL
399 : void create_directory_symlink(const path& to, const path& from,
400 : system::error_code* ec=0);
401 : BOOST_FILESYSTEM_DECL
402 : void create_hard_link(const path& to, const path& from, system::error_code* ec=0);
403 : BOOST_FILESYSTEM_DECL
404 : void create_symlink(const path& to, const path& from, system::error_code* ec=0);
405 : BOOST_FILESYSTEM_DECL
406 : path current_path(system::error_code* ec=0);
407 : BOOST_FILESYSTEM_DECL
408 : void current_path(const path& p, system::error_code* ec=0);
409 : BOOST_FILESYSTEM_DECL
410 : bool equivalent(const path& p1, const path& p2, system::error_code* ec=0);
411 : BOOST_FILESYSTEM_DECL
412 : boost::uintmax_t file_size(const path& p, system::error_code* ec=0);
413 : BOOST_FILESYSTEM_DECL
414 : boost::uintmax_t hard_link_count(const path& p, system::error_code* ec=0);
415 : BOOST_FILESYSTEM_DECL
416 : std::time_t last_write_time(const path& p, system::error_code* ec=0);
417 : BOOST_FILESYSTEM_DECL
418 : void last_write_time(const path& p, const std::time_t new_time,
419 : system::error_code* ec=0);
420 : BOOST_FILESYSTEM_DECL
421 : void permissions(const path& p, perms prms, system::error_code* ec=0);
422 : BOOST_FILESYSTEM_DECL
423 : path read_symlink(const path& p, system::error_code* ec=0);
424 : BOOST_FILESYSTEM_DECL
425 : path relative(const path& p, const path& base, system::error_code* ec = 0);
426 : BOOST_FILESYSTEM_DECL
427 : bool remove(const path& p, system::error_code* ec=0);
428 : BOOST_FILESYSTEM_DECL
429 : boost::uintmax_t remove_all(const path& p, system::error_code* ec=0);
430 : BOOST_FILESYSTEM_DECL
431 : void rename(const path& old_p, const path& new_p, system::error_code* ec=0);
432 : BOOST_FILESYSTEM_DECL
433 : void resize_file(const path& p, uintmax_t size, system::error_code* ec=0);
434 : BOOST_FILESYSTEM_DECL
435 : space_info space(const path& p, system::error_code* ec=0);
436 : BOOST_FILESYSTEM_DECL
437 : path system_complete(const path& p, system::error_code* ec=0);
438 : BOOST_FILESYSTEM_DECL
439 : path temp_directory_path(system::error_code* ec=0);
440 : BOOST_FILESYSTEM_DECL
441 : path unique_path(const path& p, system::error_code* ec=0);
442 : BOOST_FILESYSTEM_DECL
443 : path weakly_canonical(const path& p, system::error_code* ec = 0);
444 : } // namespace detail
445 :
446 : //--------------------------------------------------------------------------------------//
447 : // //
448 : // status query functions //
449 : // //
450 : //--------------------------------------------------------------------------------------//
451 :
452 : inline
453 : file_status status(const path& p) {return detail::status(p);}
454 : inline
455 : file_status status(const path& p, system::error_code& ec)
456 : {return detail::status(p, &ec);}
457 : inline
458 : file_status symlink_status(const path& p) {return detail::symlink_status(p);}
459 : inline
460 : file_status symlink_status(const path& p, system::error_code& ec)
461 : {return detail::symlink_status(p, &ec);}
462 : inline
463 1274 : bool exists(const path& p) {return exists(detail::status(p));}
464 : inline
465 : bool exists(const path& p, system::error_code& ec)
466 : {return exists(detail::status(p, &ec));}
467 : inline
468 281 : bool is_directory(const path& p) {return is_directory(detail::status(p));}
469 : inline
470 : bool is_directory(const path& p, system::error_code& ec)
471 : {return is_directory(detail::status(p, &ec));}
472 : inline
473 0 : bool is_regular_file(const path& p) {return is_regular_file(detail::status(p));}
474 : inline
475 : bool is_regular_file(const path& p, system::error_code& ec)
476 : {return is_regular_file(detail::status(p, &ec));}
477 : inline
478 : bool is_other(const path& p) {return is_other(detail::status(p));}
479 : inline
480 : bool is_other(const path& p, system::error_code& ec)
481 : {return is_other(detail::status(p, &ec));}
482 : inline
483 0 : bool is_symlink(const path& p) {return is_symlink(detail::symlink_status(p));}
484 : inline
485 : bool is_symlink(const path& p, system::error_code& ec)
486 : {return is_symlink(detail::symlink_status(p, &ec));}
487 : # ifndef BOOST_FILESYSTEM_NO_DEPRECATED
488 : inline
489 : bool is_regular(const path& p) {return is_regular(detail::status(p));}
490 : inline
491 : bool is_regular(const path& p, system::error_code& ec)
492 : {return is_regular(detail::status(p, &ec));}
493 : # endif
494 :
495 : inline
496 0 : bool is_empty(const path& p) {return detail::is_empty(p);}
497 : inline
498 : bool is_empty(const path& p, system::error_code& ec)
499 : {return detail::is_empty(p, &ec);}
500 :
501 : //--------------------------------------------------------------------------------------//
502 : // //
503 : // operational functions //
504 : // in alphabetical order, unless otherwise noted //
505 : // //
506 : //--------------------------------------------------------------------------------------//
507 :
508 : // forward declarations
509 : path current_path(); // fwd declaration
510 : path initial_path();
511 :
512 : BOOST_FILESYSTEM_DECL
513 : path absolute(const path& p, const path& base=current_path());
514 : // If base.is_absolute(), throws nothing. Thus no need for ec argument
515 :
516 : inline
517 : path canonical(const path& p, const path& base=current_path())
518 : {return detail::canonical(p, base);}
519 : inline
520 : path canonical(const path& p, system::error_code& ec)
521 : {return detail::canonical(p, current_path(), &ec);}
522 : inline
523 : path canonical(const path& p, const path& base, system::error_code& ec)
524 : {return detail::canonical(p, base, &ec);}
525 :
526 : # ifndef BOOST_FILESYSTEM_NO_DEPRECATED
527 : inline
528 : path complete(const path& p)
529 : {
530 : return absolute(p, initial_path());
531 : }
532 :
533 : inline
534 0 : path complete(const path& p, const path& base)
535 : {
536 0 : return absolute(p, base);
537 : }
538 : # endif
539 :
540 : inline
541 : void copy(const path& from, const path& to) {detail::copy(from, to);}
542 :
543 : inline
544 : void copy(const path& from, const path& to, system::error_code& ec) BOOST_NOEXCEPT
545 : {detail::copy(from, to, &ec);}
546 : inline
547 : void copy_directory(const path& from, const path& to)
548 : {detail::copy_directory(from, to);}
549 : inline
550 : void copy_directory(const path& from, const path& to, system::error_code& ec) BOOST_NOEXCEPT
551 : {detail::copy_directory(from, to, &ec);}
552 : inline
553 0 : void copy_file(const path& from, const path& to, // See ticket #2925
554 : BOOST_SCOPED_ENUM_NATIVE(copy_option) option)
555 : {
556 0 : detail::copy_file(from, to, static_cast<detail::copy_option>(option));
557 0 : }
558 : inline
559 : void copy_file(const path& from, const path& to)
560 : {
561 : detail::copy_file(from, to, detail::fail_if_exists);
562 : }
563 : inline
564 : void copy_file(const path& from, const path& to, // See ticket #2925
565 : BOOST_SCOPED_ENUM_NATIVE(copy_option) option, system::error_code& ec) BOOST_NOEXCEPT
566 : {
567 : detail::copy_file(from, to, static_cast<detail::copy_option>(option), &ec);
568 : }
569 : inline
570 : void copy_file(const path& from, const path& to, system::error_code& ec) BOOST_NOEXCEPT
571 : {
572 : detail::copy_file(from, to, detail::fail_if_exists, &ec);
573 : }
574 : inline
575 : void copy_symlink(const path& existing_symlink,
576 : const path& new_symlink) {detail::copy_symlink(existing_symlink, new_symlink);}
577 :
578 : inline
579 : void copy_symlink(const path& existing_symlink, const path& new_symlink,
580 : system::error_code& ec) BOOST_NOEXCEPT
581 : {detail::copy_symlink(existing_symlink, new_symlink, &ec);}
582 : inline
583 0 : bool create_directories(const path& p) {return detail::create_directories(p);}
584 :
585 : inline
586 : bool create_directories(const path& p, system::error_code& ec) BOOST_NOEXCEPT
587 : {return detail::create_directories(p, &ec);}
588 : inline
589 0 : bool create_directory(const path& p) {return detail::create_directory(p);}
590 :
591 : inline
592 0 : bool create_directory(const path& p, system::error_code& ec) BOOST_NOEXCEPT
593 0 : {return detail::create_directory(p, &ec);}
594 : inline
595 : void create_directory_symlink(const path& to, const path& from)
596 : {detail::create_directory_symlink(to, from);}
597 : inline
598 : void create_directory_symlink(const path& to, const path& from, system::error_code& ec) BOOST_NOEXCEPT
599 : {detail::create_directory_symlink(to, from, &ec);}
600 : inline
601 : void create_hard_link(const path& to, const path& new_hard_link) {detail::create_hard_link(to, new_hard_link);}
602 :
603 : inline
604 : void create_hard_link(const path& to, const path& new_hard_link, system::error_code& ec) BOOST_NOEXCEPT
605 : {detail::create_hard_link(to, new_hard_link, &ec);}
606 : inline
607 : void create_symlink(const path& to, const path& new_symlink) {detail::create_symlink(to, new_symlink);}
608 :
609 : inline
610 : void create_symlink(const path& to, const path& new_symlink, system::error_code& ec) BOOST_NOEXCEPT
611 : {detail::create_symlink(to, new_symlink, &ec);}
612 : inline
613 0 : path current_path() {return detail::current_path();}
614 :
615 : inline
616 : path current_path(system::error_code& ec) BOOST_NOEXCEPT {return detail::current_path(&ec);}
617 :
618 : inline
619 : void current_path(const path& p) {detail::current_path(p);}
620 :
621 : inline
622 : void current_path(const path& p, system::error_code& ec) BOOST_NOEXCEPT {detail::current_path(p, &ec);}
623 :
624 : inline
625 0 : bool equivalent(const path& p1, const path& p2) {return detail::equivalent(p1, p2);}
626 :
627 : inline
628 : bool equivalent(const path& p1, const path& p2, system::error_code& ec) BOOST_NOEXCEPT
629 : {return detail::equivalent(p1, p2, &ec);}
630 : inline
631 0 : boost::uintmax_t file_size(const path& p) {return detail::file_size(p);}
632 :
633 : inline
634 : boost::uintmax_t file_size(const path& p, system::error_code& ec) BOOST_NOEXCEPT
635 : {return detail::file_size(p, &ec);}
636 : inline
637 : boost::uintmax_t hard_link_count(const path& p) {return detail::hard_link_count(p);}
638 :
639 : inline
640 : boost::uintmax_t hard_link_count(const path& p, system::error_code& ec) BOOST_NOEXCEPT
641 : {return detail::hard_link_count(p, &ec);}
642 : inline
643 0 : path initial_path() {return detail::initial_path();}
644 :
645 : inline
646 : path initial_path(system::error_code& ec) {return detail::initial_path(&ec);}
647 :
648 : template <class Path>
649 : path initial_path() {return initial_path();}
650 : template <class Path>
651 : path initial_path(system::error_code& ec) {return detail::initial_path(&ec);}
652 :
653 : inline
654 : std::time_t last_write_time(const path& p) {return detail::last_write_time(p);}
655 :
656 : inline
657 : std::time_t last_write_time(const path& p, system::error_code& ec) BOOST_NOEXCEPT
658 : {return detail::last_write_time(p, &ec);}
659 : inline
660 : void last_write_time(const path& p, const std::time_t new_time)
661 : {detail::last_write_time(p, new_time);}
662 : inline
663 : void last_write_time(const path& p, const std::time_t new_time,
664 : system::error_code& ec) BOOST_NOEXCEPT
665 : {detail::last_write_time(p, new_time, &ec);}
666 : inline
667 : void permissions(const path& p, perms prms)
668 : {detail::permissions(p, prms);}
669 : inline
670 : void permissions(const path& p, perms prms, system::error_code& ec) BOOST_NOEXCEPT
671 : {detail::permissions(p, prms, &ec);}
672 :
673 : inline
674 : path read_symlink(const path& p) {return detail::read_symlink(p);}
675 :
676 : inline
677 : path read_symlink(const path& p, system::error_code& ec)
678 : {return detail::read_symlink(p, &ec);}
679 : inline
680 : // For standardization, if the committee doesn't like "remove", consider "eliminate"
681 0 : bool remove(const path& p) {return detail::remove(p);}
682 :
683 : inline
684 : bool remove(const path& p, system::error_code& ec) BOOST_NOEXCEPT
685 : {return detail::remove(p, &ec);}
686 :
687 : inline
688 0 : boost::uintmax_t remove_all(const path& p) {return detail::remove_all(p);}
689 :
690 : inline
691 : boost::uintmax_t remove_all(const path& p, system::error_code& ec) BOOST_NOEXCEPT
692 : {return detail::remove_all(p, &ec);}
693 : inline
694 : void rename(const path& old_p, const path& new_p) {detail::rename(old_p, new_p);}
695 :
696 : inline
697 : void rename(const path& old_p, const path& new_p, system::error_code& ec) BOOST_NOEXCEPT
698 : {detail::rename(old_p, new_p, &ec);}
699 : inline // name suggested by Scott McMurray
700 : void resize_file(const path& p, uintmax_t size) {detail::resize_file(p, size);}
701 :
702 : inline
703 : void resize_file(const path& p, uintmax_t size, system::error_code& ec) BOOST_NOEXCEPT
704 : {detail::resize_file(p, size, &ec);}
705 : inline
706 : path relative(const path& p, const path& base=current_path())
707 : {return detail::relative(p, base);}
708 : inline
709 : path relative(const path& p, system::error_code& ec)
710 : {return detail::relative(p, current_path(), &ec);}
711 : inline
712 : path relative(const path& p, const path& base, system::error_code& ec)
713 : {return detail::relative(p, base, &ec);}
714 : inline
715 : space_info space(const path& p) {return detail::space(p);}
716 :
717 : inline
718 : space_info space(const path& p, system::error_code& ec) BOOST_NOEXCEPT
719 : {return detail::space(p, &ec);}
720 :
721 : # ifndef BOOST_FILESYSTEM_NO_DEPRECATED
722 : inline bool symbolic_link_exists(const path& p)
723 : { return is_symlink(filesystem::symlink_status(p)); }
724 : # endif
725 :
726 : inline
727 : path system_complete(const path& p) {return detail::system_complete(p);}
728 :
729 : inline
730 : path system_complete(const path& p, system::error_code& ec)
731 : {return detail::system_complete(p, &ec);}
732 : inline
733 0 : path temp_directory_path() {return detail::temp_directory_path();}
734 :
735 : inline
736 : path temp_directory_path(system::error_code& ec)
737 : {return detail::temp_directory_path(&ec);}
738 : inline
739 0 : path unique_path(const path& p="%%%%-%%%%-%%%%-%%%%")
740 0 : {return detail::unique_path(p);}
741 : inline
742 : path unique_path(const path& p, system::error_code& ec)
743 : {return detail::unique_path(p, &ec);}
744 : inline
745 : path weakly_canonical(const path& p) {return detail::weakly_canonical(p);}
746 :
747 : inline
748 : path weakly_canonical(const path& p, system::error_code& ec)
749 : {return detail::weakly_canonical(p, &ec);}
750 :
751 : //--------------------------------------------------------------------------------------//
752 : // //
753 : // directory_entry //
754 : // //
755 : //--------------------------------------------------------------------------------------//
756 :
757 : // GCC has a problem with a member function named path within a namespace or
758 : // sub-namespace that also has a class named path. The workaround is to always
759 : // fully qualify the name path when it refers to the class name.
760 :
761 0 : class directory_entry
762 : {
763 : public:
764 : typedef boost::filesystem::path::value_type value_type; // enables class path ctor taking directory_entry
765 :
766 0 : directory_entry() BOOST_NOEXCEPT {}
767 : explicit directory_entry(const boost::filesystem::path& p) :
768 : m_path(p), m_status(file_status()), m_symlink_status(file_status())
769 : {
770 : }
771 : directory_entry(const boost::filesystem::path& p,
772 : file_status st, file_status symlink_st = file_status()) :
773 : m_path(p), m_status(st), m_symlink_status(symlink_st)
774 : {
775 : }
776 :
777 : directory_entry(const directory_entry& rhs) :
778 : m_path(rhs.m_path), m_status(rhs.m_status), m_symlink_status(rhs.m_symlink_status)
779 : {
780 : }
781 :
782 : directory_entry& operator=(const directory_entry& rhs)
783 : {
784 : m_path = rhs.m_path;
785 : m_status = rhs.m_status;
786 : m_symlink_status = rhs.m_symlink_status;
787 : return *this;
788 : }
789 :
790 : // As of October 2015 the interaction between noexcept and =default is so troublesome
791 : // for VC++, GCC, and probably other compilers, that =default is not used with noexcept
792 : // functions. GCC is not even consistent for the same release on different platforms.
793 :
794 : #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
795 : directory_entry(directory_entry&& rhs) BOOST_NOEXCEPT :
796 : m_path(std::move(rhs.m_path)), m_status(std::move(rhs.m_status)), m_symlink_status(std::move(rhs.m_symlink_status))
797 : {
798 : }
799 : directory_entry& operator=(directory_entry&& rhs) BOOST_NOEXCEPT
800 : {
801 : m_path = std::move(rhs.m_path);
802 : m_status = std::move(rhs.m_status);
803 : m_symlink_status = std::move(rhs.m_symlink_status);
804 : return *this;
805 : }
806 : #endif
807 :
808 : void assign(const boost::filesystem::path& p,
809 : file_status st = file_status(), file_status symlink_st = file_status())
810 : {
811 : m_path = p;
812 : m_status = st;
813 : m_symlink_status = symlink_st;
814 : }
815 :
816 : void replace_filename(const boost::filesystem::path& p,
817 : file_status st = file_status(), file_status symlink_st = file_status())
818 : {
819 : m_path.remove_filename();
820 : m_path /= p;
821 : m_status = st;
822 : m_symlink_status = symlink_st;
823 : }
824 :
825 : # ifndef BOOST_FILESYSTEM_NO_DEPRECATED
826 : void replace_leaf(const boost::filesystem::path& p,
827 : file_status st, file_status symlink_st)
828 : { replace_filename(p, st, symlink_st); }
829 : # endif
830 :
831 0 : const boost::filesystem::path& path() const BOOST_NOEXCEPT {return m_path;}
832 : operator const boost::filesystem::path&() const BOOST_NOEXCEPT
833 : {return m_path;}
834 : file_status status() const {return m_get_status();}
835 : file_status status(system::error_code& ec) const BOOST_NOEXCEPT
836 : {return m_get_status(&ec); }
837 : file_status symlink_status() const {return m_get_symlink_status();}
838 : file_status symlink_status(system::error_code& ec) const BOOST_NOEXCEPT
839 : {return m_get_symlink_status(&ec); }
840 :
841 : bool operator==(const directory_entry& rhs) const BOOST_NOEXCEPT {return m_path == rhs.m_path; }
842 : bool operator!=(const directory_entry& rhs) const BOOST_NOEXCEPT {return m_path != rhs.m_path;}
843 : bool operator< (const directory_entry& rhs) const BOOST_NOEXCEPT {return m_path < rhs.m_path;}
844 : bool operator<=(const directory_entry& rhs) const BOOST_NOEXCEPT {return m_path <= rhs.m_path;}
845 : bool operator> (const directory_entry& rhs) const BOOST_NOEXCEPT {return m_path > rhs.m_path;}
846 : bool operator>=(const directory_entry& rhs) const BOOST_NOEXCEPT {return m_path >= rhs.m_path;}
847 :
848 : private:
849 : BOOST_FILESYSTEM_DECL file_status m_get_status(system::error_code* ec=0) const;
850 : BOOST_FILESYSTEM_DECL file_status m_get_symlink_status(system::error_code* ec=0) const;
851 :
852 : private:
853 : boost::filesystem::path m_path;
854 : mutable file_status m_status; // stat()-like
855 : mutable file_status m_symlink_status; // lstat()-like
856 : }; // directory_entry
857 :
858 :
859 : //--------------------------------------------------------------------------------------//
860 : // //
861 : // directory_entry overloads //
862 : // //
863 : //--------------------------------------------------------------------------------------//
864 :
865 : // Without these functions, calling (for example) 'is_directory' with a 'directory_entry' results in:
866 : // - a conversion to 'path' using 'operator const boost::filesystem::path&()',
867 : // - then a call to 'is_directory(const path& p)' which recomputes the status with 'detail::status(p)'.
868 : //
869 : // These functions avoid a costly recomputation of the status if one calls 'is_directory(e)' instead of 'is_directory(e.status)'
870 :
871 : inline file_status status (const directory_entry& e) BOOST_NOEXCEPT { return e.status(); }
872 : inline bool type_present (const directory_entry& e) BOOST_NOEXCEPT { return filesystem::type_present(e.status()); }
873 : inline bool status_known (const directory_entry& e) BOOST_NOEXCEPT { return filesystem::status_known(e.status()); }
874 : inline bool exists (const directory_entry& e) BOOST_NOEXCEPT { return filesystem::exists(e.status()); }
875 : inline bool is_regular_file(const directory_entry& e) BOOST_NOEXCEPT { return filesystem::is_regular_file(e.status()); }
876 : inline bool is_directory (const directory_entry& e) BOOST_NOEXCEPT { return filesystem::is_directory(e.status()); }
877 : inline bool is_symlink (const directory_entry& e) BOOST_NOEXCEPT { return filesystem::is_symlink(e.status()); }
878 : inline bool is_other (const directory_entry& e) BOOST_NOEXCEPT { return filesystem::is_other(e.status()); }
879 : #ifndef BOOST_FILESYSTEM_NO_DEPRECATED
880 : inline bool is_regular (const directory_entry& e) BOOST_NOEXCEPT { return filesystem::is_regular(e.status()); }
881 : #endif
882 :
883 : //--------------------------------------------------------------------------------------//
884 : // //
885 : // directory_iterator helpers //
886 : // //
887 : //--------------------------------------------------------------------------------------//
888 :
889 : class directory_iterator;
890 :
891 : namespace detail
892 : {
893 : BOOST_FILESYSTEM_DECL
894 : system::error_code dir_itr_close(// never throws()
895 : void *& handle
896 : # if defined(BOOST_POSIX_API)
897 : , void *& buffer
898 : # endif
899 : );
900 :
901 : struct dir_itr_imp :
902 : public boost::intrusive_ref_counter< dir_itr_imp >
903 : {
904 : directory_entry dir_entry;
905 : void* handle;
906 :
907 : # ifdef BOOST_POSIX_API
908 : void* buffer; // see dir_itr_increment implementation
909 : # endif
910 :
911 0 : dir_itr_imp() BOOST_NOEXCEPT : handle(0)
912 : # ifdef BOOST_POSIX_API
913 0 : , buffer(0)
914 : # endif
915 : {}
916 :
917 0 : ~dir_itr_imp() BOOST_NOEXCEPT
918 0 : {
919 0 : dir_itr_close(handle
920 : # if defined(BOOST_POSIX_API)
921 0 : , buffer
922 : # endif
923 0 : );
924 0 : }
925 : };
926 :
927 : // see path::iterator: comment below
928 : BOOST_FILESYSTEM_DECL void directory_iterator_construct(directory_iterator& it,
929 : const path& p, system::error_code* ec);
930 : BOOST_FILESYSTEM_DECL void directory_iterator_increment(directory_iterator& it,
931 : system::error_code* ec);
932 :
933 : } // namespace detail
934 :
935 : //--------------------------------------------------------------------------------------//
936 : // //
937 : // directory_iterator //
938 : // //
939 : //--------------------------------------------------------------------------------------//
940 :
941 0 : class directory_iterator :
942 : public boost::iterator_facade<
943 : directory_iterator,
944 : directory_entry,
945 : boost::single_pass_traversal_tag
946 : >
947 : {
948 : public:
949 :
950 0 : directory_iterator() BOOST_NOEXCEPT {} // creates the "end" iterator
951 :
952 : // iterator_facade derived classes don't seem to like implementations in
953 : // separate translation unit dll's, so forward to detail functions
954 0 : explicit directory_iterator(const path& p) :
955 0 : m_imp(new detail::dir_itr_imp())
956 : {
957 0 : detail::directory_iterator_construct(*this, p, 0);
958 0 : }
959 :
960 : directory_iterator(const path& p, system::error_code& ec) BOOST_NOEXCEPT :
961 : m_imp(new (std::nothrow) detail::dir_itr_imp())
962 : {
963 : if (BOOST_UNLIKELY(!m_imp))
964 : {
965 : ec = make_error_code(system::errc::not_enough_memory);
966 : return;
967 : }
968 :
969 : detail::directory_iterator_construct(*this, p, &ec);
970 : }
971 :
972 : BOOST_DEFAULTED_FUNCTION(directory_iterator(directory_iterator const& that), : m_imp(that.m_imp) {})
973 : BOOST_DEFAULTED_FUNCTION(directory_iterator& operator= (directory_iterator const& that), { m_imp = that.m_imp; return *this; })
974 :
975 : #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
976 0 : directory_iterator(directory_iterator&& that) BOOST_NOEXCEPT :
977 0 : m_imp(std::move(that.m_imp))
978 : {
979 : }
980 :
981 : directory_iterator& operator= (directory_iterator&& that) BOOST_NOEXCEPT
982 : {
983 : m_imp = std::move(that.m_imp);
984 : return *this;
985 : }
986 : #endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
987 :
988 : directory_iterator& increment(system::error_code& ec) BOOST_NOEXCEPT
989 : {
990 : detail::directory_iterator_increment(*this, &ec);
991 : return *this;
992 : }
993 :
994 : private:
995 : friend struct detail::dir_itr_imp;
996 : friend BOOST_FILESYSTEM_DECL void detail::directory_iterator_construct(directory_iterator& it,
997 : const path& p, system::error_code* ec);
998 : friend BOOST_FILESYSTEM_DECL void detail::directory_iterator_increment(directory_iterator& it,
999 : system::error_code* ec);
1000 :
1001 : // intrusive_ptr provides the shallow-copy semantics required for single pass iterators
1002 : // (i.e. InputIterators). The end iterator is indicated by !m_imp || !m_imp->handle
1003 : boost::intrusive_ptr< detail::dir_itr_imp > m_imp;
1004 :
1005 : friend class boost::iterator_core_access;
1006 :
1007 : boost::iterator_facade<
1008 : directory_iterator,
1009 : directory_entry,
1010 : boost::single_pass_traversal_tag
1011 0 : >::reference dereference() const
1012 : {
1013 0 : BOOST_ASSERT_MSG(m_imp.get(), "attempt to dereference end iterator");
1014 0 : return m_imp->dir_entry;
1015 : }
1016 :
1017 0 : void increment() { detail::directory_iterator_increment(*this, 0); }
1018 :
1019 0 : bool equal(const directory_iterator& rhs) const
1020 : {
1021 0 : return m_imp == rhs.m_imp
1022 0 : || (!m_imp && rhs.m_imp && !rhs.m_imp->handle)
1023 0 : || (!rhs.m_imp && m_imp && !m_imp->handle);
1024 : }
1025 : }; // directory_iterator
1026 :
1027 : // enable directory_iterator C++11 range-based for statement use --------------------//
1028 :
1029 : // begin() and end() are only used by a range-based for statement in the context of
1030 : // auto - thus the top-level const is stripped - so returning const is harmless and
1031 : // emphasizes begin() is just a pass through.
1032 : inline
1033 : const directory_iterator& begin(const directory_iterator& iter) BOOST_NOEXCEPT
1034 : {return iter;}
1035 : inline
1036 : directory_iterator end(const directory_iterator&) BOOST_NOEXCEPT
1037 : {return directory_iterator();}
1038 :
1039 : // enable C++14 generic accessors for range const iterators
1040 : inline
1041 : const directory_iterator& cbegin(const directory_iterator& iter) BOOST_NOEXCEPT
1042 : {return iter;}
1043 : inline
1044 : directory_iterator cend(const directory_iterator&) BOOST_NOEXCEPT
1045 : {return directory_iterator();}
1046 :
1047 : // enable directory_iterator BOOST_FOREACH -----------------------------------------//
1048 :
1049 : inline
1050 : directory_iterator& range_begin(directory_iterator& iter) BOOST_NOEXCEPT
1051 : {return iter;}
1052 : inline
1053 : directory_iterator range_begin(const directory_iterator& iter) BOOST_NOEXCEPT
1054 : {return iter;}
1055 : inline
1056 : directory_iterator range_end(directory_iterator&) BOOST_NOEXCEPT
1057 : {return directory_iterator();}
1058 : inline
1059 : directory_iterator range_end(const directory_iterator&) BOOST_NOEXCEPT
1060 : {return directory_iterator();}
1061 : } // namespace filesystem
1062 :
1063 : // namespace boost template specializations
1064 : template<typename C, typename Enabler>
1065 : struct range_mutable_iterator;
1066 :
1067 : template<>
1068 : struct range_mutable_iterator<boost::filesystem::directory_iterator, void>
1069 : { typedef boost::filesystem::directory_iterator type; };
1070 :
1071 : template<typename C, typename Enabler>
1072 : struct range_const_iterator;
1073 :
1074 : template<>
1075 : struct range_const_iterator<boost::filesystem::directory_iterator, void>
1076 : { typedef boost::filesystem::directory_iterator type; };
1077 :
1078 : namespace filesystem
1079 : {
1080 :
1081 : //--------------------------------------------------------------------------------------//
1082 : // //
1083 : // recursive_directory_iterator helpers //
1084 : // //
1085 : //--------------------------------------------------------------------------------------//
1086 :
1087 : BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(symlink_option, unsigned int)
1088 : {
1089 : none,
1090 : no_recurse = none, // don't follow directory symlinks (default behavior)
1091 : recurse, // follow directory symlinks
1092 : _detail_no_push = recurse << 1 // internal use only
1093 : }
1094 : BOOST_SCOPED_ENUM_DECLARE_END(symlink_option)
1095 :
1096 : BOOST_BITMASK(BOOST_SCOPED_ENUM_NATIVE(symlink_option))
1097 :
1098 : namespace detail
1099 : {
1100 0 : struct recur_dir_itr_imp :
1101 : public boost::intrusive_ref_counter< recur_dir_itr_imp >
1102 : {
1103 : typedef directory_iterator element_type;
1104 : std::stack< element_type, std::vector< element_type > > m_stack;
1105 : int m_level;
1106 : // symlink_option values, declared as unsigned int for ABI compatibility
1107 : unsigned int m_options;
1108 :
1109 0 : recur_dir_itr_imp() BOOST_NOEXCEPT : m_level(0), m_options(static_cast< unsigned int >(symlink_option::none)) {}
1110 : explicit recur_dir_itr_imp(BOOST_SCOPED_ENUM_NATIVE(symlink_option) opt) BOOST_NOEXCEPT : m_level(0), m_options(static_cast< unsigned int >(opt)) {}
1111 :
1112 : // ec == 0 means throw on error
1113 : //
1114 : // Invariant: On return, the top of the iterator stack is the next valid (possibly
1115 : // end) iterator, regardless of whether or not an error is reported, and regardless of
1116 : // whether any error is reported by exception or error code. In other words, progress
1117 : // is always made so a loop on the iterator will always eventually terminate
1118 : // regardless of errors.
1119 : BOOST_FILESYSTEM_DECL void increment(system::error_code* ec);
1120 :
1121 : // Returns: true if push occurs, otherwise false. Always returns false on error.
1122 : BOOST_FILESYSTEM_DECL bool push_directory(system::error_code& ec) BOOST_NOEXCEPT;
1123 :
1124 : // ec == 0 means throw on error
1125 : BOOST_FILESYSTEM_DECL void pop(system::error_code* ec);
1126 : };
1127 :
1128 : } // namespace detail
1129 :
1130 : //--------------------------------------------------------------------------------------//
1131 : // //
1132 : // recursive_directory_iterator //
1133 : // //
1134 : //--------------------------------------------------------------------------------------//
1135 :
1136 0 : class recursive_directory_iterator :
1137 : public boost::iterator_facade<
1138 : recursive_directory_iterator,
1139 : directory_entry,
1140 : boost::single_pass_traversal_tag
1141 : >
1142 : {
1143 : public:
1144 :
1145 0 : recursive_directory_iterator() BOOST_NOEXCEPT {} // creates the "end" iterator
1146 :
1147 0 : explicit recursive_directory_iterator(const path& dir_path) : // throws if !exists()
1148 0 : m_imp(new detail::recur_dir_itr_imp())
1149 : {
1150 0 : m_imp->m_stack.push(directory_iterator(dir_path));
1151 0 : if (m_imp->m_stack.top() == directory_iterator())
1152 0 : { m_imp.reset(); }
1153 0 : }
1154 :
1155 : recursive_directory_iterator(const path& dir_path,
1156 : BOOST_SCOPED_ENUM_NATIVE(symlink_option) opt) : // throws if !exists()
1157 : m_imp(new detail::recur_dir_itr_imp(opt))
1158 : {
1159 : m_imp->m_stack.push(directory_iterator(dir_path));
1160 : if (m_imp->m_stack.top() == directory_iterator())
1161 : { m_imp.reset (); }
1162 : }
1163 :
1164 : recursive_directory_iterator(const path& dir_path,
1165 : BOOST_SCOPED_ENUM_NATIVE(symlink_option) opt,
1166 : system::error_code & ec) BOOST_NOEXCEPT :
1167 : m_imp(new (std::nothrow) detail::recur_dir_itr_imp(opt))
1168 : {
1169 : if (BOOST_UNLIKELY(!m_imp))
1170 : {
1171 : ec = make_error_code(system::errc::not_enough_memory);
1172 : return;
1173 : }
1174 :
1175 : directory_iterator it(dir_path, ec);
1176 : if (ec || it == directory_iterator())
1177 : {
1178 : m_imp.reset();
1179 : return;
1180 : }
1181 :
1182 : try
1183 : {
1184 : #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
1185 : m_imp->m_stack.push(std::move(it));
1186 : #else
1187 : m_imp->m_stack.push(it);
1188 : #endif
1189 : }
1190 : catch (std::bad_alloc&)
1191 : {
1192 : ec = make_error_code(system::errc::not_enough_memory);
1193 : m_imp.reset();
1194 : }
1195 : }
1196 :
1197 : recursive_directory_iterator(const path& dir_path,
1198 : system::error_code & ec) BOOST_NOEXCEPT :
1199 : m_imp(new (std::nothrow) detail::recur_dir_itr_imp())
1200 : {
1201 : if (BOOST_UNLIKELY(!m_imp))
1202 : {
1203 : ec = make_error_code(system::errc::not_enough_memory);
1204 : return;
1205 : }
1206 :
1207 : directory_iterator it(dir_path, ec);
1208 : if (ec || it == directory_iterator())
1209 : {
1210 : m_imp.reset();
1211 : return;
1212 : }
1213 :
1214 : try
1215 : {
1216 : #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
1217 : m_imp->m_stack.push(std::move(it));
1218 : #else
1219 : m_imp->m_stack.push(it);
1220 : #endif
1221 : }
1222 : catch (std::bad_alloc&)
1223 : {
1224 : ec = make_error_code(system::errc::not_enough_memory);
1225 : m_imp.reset();
1226 : }
1227 : }
1228 :
1229 : BOOST_DEFAULTED_FUNCTION(recursive_directory_iterator(recursive_directory_iterator const& that), : m_imp(that.m_imp) {})
1230 : BOOST_DEFAULTED_FUNCTION(recursive_directory_iterator& operator= (recursive_directory_iterator const& that), { m_imp = that.m_imp; return *this; })
1231 :
1232 : #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
1233 : recursive_directory_iterator(recursive_directory_iterator&& that) BOOST_NOEXCEPT :
1234 : m_imp(std::move(that.m_imp))
1235 : {
1236 : }
1237 :
1238 : recursive_directory_iterator& operator= (recursive_directory_iterator&& that) BOOST_NOEXCEPT
1239 : {
1240 : m_imp = std::move(that.m_imp);
1241 : return *this;
1242 : }
1243 : #endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
1244 :
1245 : recursive_directory_iterator& increment(system::error_code& ec) BOOST_NOEXCEPT
1246 : {
1247 : BOOST_ASSERT_MSG(m_imp.get(),
1248 : "increment() on end recursive_directory_iterator");
1249 : m_imp->increment(&ec);
1250 : if (m_imp->m_stack.empty())
1251 : m_imp.reset(); // done, so make end iterator
1252 : return *this;
1253 : }
1254 :
1255 : int depth() const BOOST_NOEXCEPT
1256 : {
1257 : BOOST_ASSERT_MSG(m_imp.get(),
1258 : "depth() on end recursive_directory_iterator");
1259 : return m_imp->m_level;
1260 : }
1261 :
1262 : int level() const BOOST_NOEXCEPT { return depth(); }
1263 :
1264 : bool recursion_pending() const BOOST_NOEXCEPT
1265 : {
1266 : BOOST_ASSERT_MSG(m_imp.get(),
1267 : "is_no_push_requested() on end recursive_directory_iterator");
1268 : return (m_imp->m_options & static_cast< unsigned int >(symlink_option::_detail_no_push))
1269 : == static_cast< unsigned int >(symlink_option::_detail_no_push);
1270 : }
1271 :
1272 : bool no_push_pending() const BOOST_NOEXCEPT { return recursion_pending(); }
1273 :
1274 : # ifndef BOOST_FILESYSTEM_NO_DEPRECATED
1275 : bool no_push_request() const BOOST_NOEXCEPT { return no_push_pending(); }
1276 : # endif
1277 :
1278 : void pop()
1279 : {
1280 : BOOST_ASSERT_MSG(m_imp.get(),
1281 : "pop() on end recursive_directory_iterator");
1282 : m_imp->pop(0);
1283 : if (m_imp->m_stack.empty()) m_imp.reset(); // done, so make end iterator
1284 : }
1285 :
1286 : void pop(system::error_code& ec) BOOST_NOEXCEPT
1287 : {
1288 : BOOST_ASSERT_MSG(m_imp.get(),
1289 : "pop() on end recursive_directory_iterator");
1290 : m_imp->pop(&ec);
1291 : if (m_imp->m_stack.empty()) m_imp.reset(); // done, so make end iterator
1292 : }
1293 :
1294 0 : void disable_recursion_pending(bool value=true) BOOST_NOEXCEPT
1295 : {
1296 0 : BOOST_ASSERT_MSG(m_imp.get(),
1297 : "no_push() on end recursive_directory_iterator");
1298 0 : if (value)
1299 0 : m_imp->m_options |= static_cast< unsigned int >(symlink_option::_detail_no_push);
1300 : else
1301 0 : m_imp->m_options &= ~static_cast< unsigned int >(symlink_option::_detail_no_push);
1302 0 : }
1303 :
1304 0 : void no_push(bool value=true) BOOST_NOEXCEPT { disable_recursion_pending(value); }
1305 :
1306 : file_status status() const
1307 : {
1308 : BOOST_ASSERT_MSG(m_imp.get(),
1309 : "status() on end recursive_directory_iterator");
1310 : return m_imp->m_stack.top()->status();
1311 : }
1312 :
1313 : file_status symlink_status() const
1314 : {
1315 : BOOST_ASSERT_MSG(m_imp.get(),
1316 : "symlink_status() on end recursive_directory_iterator");
1317 : return m_imp->m_stack.top()->symlink_status();
1318 : }
1319 :
1320 : private:
1321 :
1322 : // intrusive_ptr provides the shallow-copy semantics required for single pass iterators
1323 : // (i.e. InputIterators).
1324 : // The end iterator is indicated by !m_imp || m_imp->m_stack.empty()
1325 : boost::intrusive_ptr< detail::recur_dir_itr_imp > m_imp;
1326 :
1327 : friend class boost::iterator_core_access;
1328 :
1329 : boost::iterator_facade<
1330 : recursive_directory_iterator,
1331 : directory_entry,
1332 : boost::single_pass_traversal_tag >::reference
1333 0 : dereference() const
1334 : {
1335 0 : BOOST_ASSERT_MSG(m_imp.get(),
1336 : "dereference of end recursive_directory_iterator");
1337 0 : return *m_imp->m_stack.top();
1338 : }
1339 :
1340 0 : void increment()
1341 : {
1342 0 : BOOST_ASSERT_MSG(m_imp.get(),
1343 : "increment of end recursive_directory_iterator");
1344 0 : m_imp->increment(0);
1345 0 : if (m_imp->m_stack.empty())
1346 0 : m_imp.reset(); // done, so make end iterator
1347 0 : }
1348 :
1349 0 : bool equal(const recursive_directory_iterator& rhs) const
1350 : {
1351 0 : return m_imp == rhs.m_imp
1352 0 : || (!m_imp && rhs.m_imp && rhs.m_imp->m_stack.empty())
1353 0 : || (!rhs.m_imp && m_imp && m_imp->m_stack.empty()) ;
1354 : }
1355 : }; // recursive directory iterator
1356 :
1357 : // enable recursive directory iterator C++11 range-base for statement use ----------//
1358 :
1359 : // begin() and end() are only used by a range-based for statement in the context of
1360 : // auto - thus the top-level const is stripped - so returning const is harmless and
1361 : // emphasizes begin() is just a pass through.
1362 : inline
1363 : const recursive_directory_iterator&
1364 : begin(const recursive_directory_iterator& iter) BOOST_NOEXCEPT
1365 : {return iter;}
1366 : inline
1367 : recursive_directory_iterator end(const recursive_directory_iterator&) BOOST_NOEXCEPT
1368 : {return recursive_directory_iterator();}
1369 :
1370 : // enable C++14 generic accessors for range const iterators
1371 : inline
1372 : const recursive_directory_iterator& cbegin(const recursive_directory_iterator& iter) BOOST_NOEXCEPT
1373 : {return iter;}
1374 : inline
1375 : recursive_directory_iterator cend(const recursive_directory_iterator&) BOOST_NOEXCEPT
1376 : {return recursive_directory_iterator();}
1377 :
1378 : // enable recursive directory iterator BOOST_FOREACH -------------------------------//
1379 :
1380 : inline
1381 : recursive_directory_iterator&
1382 : range_begin(recursive_directory_iterator& iter) BOOST_NOEXCEPT
1383 : {return iter;}
1384 : inline
1385 : recursive_directory_iterator
1386 : range_begin(const recursive_directory_iterator& iter) BOOST_NOEXCEPT
1387 : {return iter;}
1388 : inline
1389 : recursive_directory_iterator range_end(recursive_directory_iterator&) BOOST_NOEXCEPT
1390 : {return recursive_directory_iterator();}
1391 : inline
1392 : recursive_directory_iterator range_end(const recursive_directory_iterator&) BOOST_NOEXCEPT
1393 : {return recursive_directory_iterator();}
1394 : } // namespace filesystem
1395 :
1396 : // namespace boost template specializations
1397 : template<>
1398 : struct range_mutable_iterator<boost::filesystem::recursive_directory_iterator, void>
1399 : { typedef boost::filesystem::recursive_directory_iterator type; };
1400 : template<>
1401 : struct range_const_iterator<boost::filesystem::recursive_directory_iterator, void>
1402 : { typedef boost::filesystem::recursive_directory_iterator type; };
1403 :
1404 : namespace filesystem
1405 : {
1406 :
1407 : # if !defined(BOOST_FILESYSTEM_NO_DEPRECATED)
1408 : typedef recursive_directory_iterator wrecursive_directory_iterator;
1409 : # endif
1410 :
1411 : // test helper -----------------------------------------------------------------------//
1412 :
1413 : // Not part of the documented interface since false positives are possible;
1414 : // there is no law that says that an OS that has large stat.st_size
1415 : // actually supports large file sizes.
1416 :
1417 : namespace detail
1418 : {
1419 : BOOST_FILESYSTEM_DECL bool possible_large_file_size_support();
1420 : }
1421 :
1422 : } // namespace filesystem
1423 : } // namespace boost
1424 :
1425 : #include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
1426 : #endif // BOOST_FILESYSTEM3_OPERATIONS_HPP
|