]> git.lyx.org Git - lyx.git/blob - boost/boost/filesystem/operations.hpp
* lib/doc/Makefile.am:
[lyx.git] / boost / boost / filesystem / operations.hpp
1 //  boost/filesystem/operations.hpp  -----------------------------------------//
2
3 //  Copyright 2002-2005 Beman Dawes
4 //  Copyright 2002 Jan Langer
5 //  Copyright 2001 Dietmar Kuehl                                        
6 //  
7 //  Use, modification, and distribution is subject to the Boost Software
8 //  License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
9 //  at http://www.boost.org/LICENSE_1_0.txt)                             
10
11 //  See library home page at http://www.boost.org/libs/filesystem
12
13 //----------------------------------------------------------------------------// 
14
15 #ifndef BOOST_FILESYSTEM_OPERATIONS_HPP
16 #define BOOST_FILESYSTEM_OPERATIONS_HPP
17
18 #include <boost/filesystem/path.hpp>  // includes <boost/filesystem/config.hpp>
19
20 #include <boost/shared_ptr.hpp>
21 #include <boost/utility/enable_if.hpp>
22 #include <boost/type_traits/is_same.hpp>
23 #include <boost/iterator.hpp>
24 #include <boost/cstdint.hpp>
25 #include <boost/assert.hpp>
26
27 #include <string>
28 #include <utility> // for pair
29 #include <ctime>
30
31 #ifdef BOOST_WINDOWS_API
32 #  include <fstream>
33 #  if !defined(_WIN32_WINNT) || _WIN32_WINNT >= 0x0500
34 #    define BOOST_FS_HARD_LINK // Default for Windows 2K or later 
35 #  endif
36 #endif
37
38 #include <boost/config/abi_prefix.hpp> // must be the last #include
39
40 # ifdef BOOST_NO_STDC_NAMESPACE
41     namespace std { using ::time_t; }
42 # endif
43
44 # ifndef BOOST_FILESYSTEM_NARROW_ONLY
45 #   define BOOST_FS_FUNC(BOOST_FS_TYPE) \
46       template<class Path> typename boost::enable_if<is_basic_path<Path>, \
47       BOOST_FS_TYPE>::type
48 #   define BOOST_INLINE_FS_FUNC(BOOST_FS_TYPE) \
49       template<class Path> inline typename boost::enable_if<is_basic_path<Path>, \
50       BOOST_FS_TYPE>::type
51 #   define BOOST_FS_TYPENAME typename
52 # else
53 #   define BOOST_FS_FUNC(BOOST_FS_TYPE) inline BOOST_FS_TYPE
54 #   define BOOST_INLINE_FS_FUNC(BOOST_FS_TYPE) inline BOOST_FS_TYPE
55     typedef boost::filesystem::path Path;
56 #   define BOOST_FS_TYPENAME
57 # endif
58
59 //----------------------------------------------------------------------------//
60
61 namespace boost
62 {
63   namespace filesystem
64   {
65     template<class Path> class basic_directory_iterator;
66
67     // BOOST_FILESYSTEM_NARROW_ONLY needs this:
68     typedef basic_directory_iterator<path> directory_iterator;
69
70     template<class Path> class basic_directory_entry;
71
72     enum file_type
73     { 
74       status_unknown,
75       file_not_found,
76       regular_file,
77       directory_file,
78       // the following will never be reported by some operating or file systems
79       symlink_file,
80       block_file,
81       character_file,
82       fifo_file,
83       socket_file,
84       type_unknown // file does exist, but isn't one of the above types
85     };
86
87     class file_status
88     {
89     public:
90       explicit file_status( file_type v = status_unknown ) : m_value(v) {}
91
92       void type( file_type v )  { m_value = v; }
93       file_type type() const    { return m_value; }
94
95     private:
96       // the internal representation is unspecified so that additional state
97       // information such as permissions can be added in the future; this
98       // implementation just uses status_type as the internal representation
99
100       file_type m_value;
101     };
102
103     inline bool status_known( file_status f ) { return f.type() != status_unknown; }
104     inline bool exists( file_status f )       { return f.type() != status_unknown && f.type() != file_not_found; }
105     inline bool is_regular( file_status f )   { return f.type() == regular_file; }
106     inline bool is_directory( file_status f ) { return f.type() == directory_file; }
107     inline bool is_symlink( file_status f )   { return f.type() == symlink_file; }
108     inline bool is_other( file_status f )     { return exists(f) && !is_regular(f) && !is_directory(f) && !is_symlink(f); }
109
110     struct space_info
111     {
112       // all values are byte counts
113       boost::uintmax_t capacity;
114       boost::uintmax_t free;      // <= capacity
115       boost::uintmax_t available; // <= free
116     };
117
118     namespace detail
119     {
120       typedef std::pair< boost::filesystem::system_error_type, bool >
121         query_pair;
122
123       typedef std::pair< boost::filesystem::system_error_type, boost::uintmax_t >
124         uintmax_pair;
125
126       typedef std::pair< boost::filesystem::system_error_type, std::time_t >
127         time_pair;
128
129       typedef std::pair< boost::filesystem::system_error_type, space_info >
130         space_pair;
131
132       template< class Path >
133       struct directory_pair
134       {
135         typedef std::pair< boost::filesystem::system_error_type,
136           typename Path::external_string_type > type;
137       };
138
139 #   ifndef BOOST_FILESYSTEM_NO_DEPRECATED
140       BOOST_FILESYSTEM_DECL bool
141         symbolic_link_exists_api( const std::string & ); // deprecated
142 #   endif
143
144       BOOST_FILESYSTEM_DECL file_status
145         status_api( const std::string & ph, system_error_type & ec );
146 #   ifndef BOOST_WINDOWS_API
147       BOOST_FILESYSTEM_DECL file_status
148         symlink_status_api( const std::string & ph, system_error_type & ec );
149 #   endif
150       BOOST_FILESYSTEM_DECL query_pair
151         is_empty_api( const std::string & ph );
152       BOOST_FILESYSTEM_DECL query_pair
153         equivalent_api( const std::string & ph1, const std::string & ph2 );
154       BOOST_FILESYSTEM_DECL uintmax_pair
155         file_size_api( const std::string & ph );
156       BOOST_FILESYSTEM_DECL space_pair
157         space_api( const std::string & ph );
158       BOOST_FILESYSTEM_DECL time_pair 
159         last_write_time_api( const std::string & ph );
160       BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
161         last_write_time_api( const std::string & ph, std::time_t new_value );
162       BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
163         get_current_path_api( std::string & ph );
164       BOOST_FILESYSTEM_DECL query_pair
165         create_directory_api( const std::string & ph );
166       BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
167         create_hard_link_api( const std::string & to_ph,
168           const std::string & from_ph );
169       BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
170         create_symlink_api( const std::string & to_ph,
171           const std::string & from_ph );
172       BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
173         remove_api( const std::string & ph );
174       BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
175         rename_api( const std::string & from, const std::string & to );
176       BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
177         copy_file_api( const std::string & from, const std::string & to );
178
179 #   if defined(BOOST_WINDOWS_API)
180       
181       BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
182         get_full_path_name_api( const std::string & ph, std::string & target );
183
184 #     if !defined(BOOST_FILESYSTEM_NARROW_ONLY)
185
186       BOOST_FILESYSTEM_DECL  boost::filesystem::file_status
187         status_api( const std::wstring & ph, system_error_type & ec );
188       BOOST_FILESYSTEM_DECL query_pair 
189         is_empty_api( const std::wstring & ph );
190       BOOST_FILESYSTEM_DECL query_pair
191         equivalent_api( const std::wstring & ph1, const std::wstring & ph2 );
192       BOOST_FILESYSTEM_DECL uintmax_pair 
193         file_size_api( const std::wstring & ph );
194       BOOST_FILESYSTEM_DECL space_pair 
195         space_api( const std::wstring & ph );
196       BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
197         get_full_path_name_api( const std::wstring & ph, std::wstring & target );
198       BOOST_FILESYSTEM_DECL time_pair 
199         last_write_time_api( const std::wstring & ph );
200       BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
201         last_write_time_api( const std::wstring & ph, std::time_t new_value );
202       BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type 
203         get_current_path_api( std::wstring & ph );
204       BOOST_FILESYSTEM_DECL query_pair
205         create_directory_api( const std::wstring & ph );
206 # ifdef BOOST_FS_HARD_LINK
207       BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
208         create_hard_link_api( const std::wstring & existing_ph,
209           const std::wstring & new_ph );
210 # endif
211       BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
212         create_symlink_api( const std::wstring & to_ph,
213           const std::wstring & from_ph );
214       BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
215         remove_api( const std::wstring & ph );
216       BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
217         rename_api( const std::wstring & from, const std::wstring & to );
218       BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
219         copy_file_api( const std::wstring & from, const std::wstring & to );
220
221 #     endif
222 #   endif
223
224       template<class Path>
225       unsigned long remove_all_aux( const Path & ph );
226
227     } // namespace detail
228
229 //  operations functions  ----------------------------------------------------//
230
231     //  The non-template overloads enable automatic conversion from std and
232     //  C-style strings. See basic_path constructors. The enable_if for the
233     //  templates implements the famous "do-the-right-thing" rule.
234
235 //  query functions  ---------------------------------------------------------//
236
237     BOOST_INLINE_FS_FUNC(file_status)
238     status( const Path & ph, system_error_type & ec )
239       { return detail::status_api( ph.external_file_string(), ec ); }
240
241     BOOST_FS_FUNC(file_status)
242     status( const Path & ph )
243     { 
244       system_error_type ec;
245       file_status result( detail::status_api( ph.external_file_string(), ec ) );
246       if ( ec )
247         boost::throw_exception( basic_filesystem_error<Path>(
248         "boost::filesystem::status", ph, ec ) );
249       return result;
250     }
251
252     BOOST_INLINE_FS_FUNC(file_status)
253     symlink_status( const Path & ph, system_error_type & ec )
254 #   ifdef BOOST_WINDOWS_API
255       { return detail::status_api( ph.external_file_string(), ec ); }
256 #   else
257       { return detail::symlink_status_api( ph.external_file_string(), ec ); }
258 #   endif
259
260     BOOST_FS_FUNC(file_status)
261     symlink_status( const Path & ph )
262     { 
263       system_error_type ec;
264       file_status result( symlink_status( ph, ec ) );
265       if ( ec )
266         boost::throw_exception( basic_filesystem_error<Path>(
267         "boost::filesystem::symlink_status", ph, ec ) );
268       return result;
269     }
270
271 # ifndef BOOST_FILESYSTEM_NO_DEPRECATED
272     inline bool symbolic_link_exists( const path & ph )
273       { return is_symlink( symlink_status(ph) ); }
274 #endif
275
276     BOOST_FS_FUNC(bool) exists( const Path & ph )
277     { 
278       system_error_type ec;
279       file_status result( detail::status_api( ph.external_file_string(), ec ) );
280       if ( ec )
281         boost::throw_exception( basic_filesystem_error<Path>(
282           "boost::filesystem::exists", ph, ec ) );
283       return exists( result );
284     }
285
286     BOOST_FS_FUNC(bool) is_directory( const Path & ph )
287     { 
288       system_error_type ec;
289       file_status result( detail::status_api( ph.external_file_string(), ec ) );
290       if ( ec )
291         boost::throw_exception( basic_filesystem_error<Path>(
292           "boost::filesystem::is_directory", ph, ec ) );
293       return is_directory( result );
294     }
295
296     BOOST_FS_FUNC(bool) is_regular( const Path & ph )
297     { 
298       system_error_type ec;
299       file_status result( detail::status_api( ph.external_file_string(), ec ) );
300       if ( ec )
301         boost::throw_exception( basic_filesystem_error<Path>(
302           "boost::filesystem::is_regular", ph, ec ) );
303       return is_regular( result );
304     }
305
306     BOOST_FS_FUNC(bool) is_other( const Path & ph )
307     { 
308       system_error_type ec;
309       file_status result( detail::status_api( ph.external_file_string(), ec ) );
310       if ( ec )
311         boost::throw_exception( basic_filesystem_error<Path>(
312           "boost::filesystem::is_other", ph, ec ) );
313       return is_other( result );
314     }
315
316     BOOST_FS_FUNC(bool) is_symlink(
317 #   ifdef BOOST_WINDOWS_API
318       const Path & )
319     {
320       return false;
321 #   else
322       const Path & ph)
323     {
324       system_error_type ec;
325       file_status result( detail::symlink_status_api( ph.external_file_string(), ec ) );
326       if ( ec )
327         boost::throw_exception( basic_filesystem_error<Path>(
328           "boost::filesystem::is_symlink", ph, ec ) );
329       return is_symlink( result );
330 #   endif
331     }
332
333     // VC++ 7.0 and earlier has a serious namespace bug that causes a clash
334     // between boost::filesystem::is_empty and the unrelated type trait
335     // boost::is_empty.
336
337 # if !defined( BOOST_MSVC ) || BOOST_MSVC > 1300
338     BOOST_FS_FUNC(bool) is_empty( const Path & ph )
339 # else
340     BOOST_FS_FUNC(bool) _is_empty( const Path & ph )
341 # endif
342     {
343       detail::query_pair result = detail::is_empty_api( ph.external_file_string() );
344       if ( result.first != 0 )
345         boost::throw_exception( basic_filesystem_error<Path>(
346           "boost::filesystem::is_empty", ph, result.first ) );
347       return result.second;
348     }
349
350     BOOST_FS_FUNC(bool) equivalent( const Path & ph1, const Path & ph2 )
351     {
352       detail::query_pair result = detail::equivalent_api(
353         ph1.external_file_string(), ph2.external_file_string() );
354       if ( result.first != 0 )
355         boost::throw_exception( basic_filesystem_error<Path>(
356           "boost::filesystem::equivalent", ph1, ph2, result.first ) );
357       return result.second;
358     }
359
360     BOOST_FS_FUNC(boost::uintmax_t) file_size( const Path & ph )
361     {
362       detail::uintmax_pair result
363         = detail::file_size_api( ph.external_file_string() );
364       if ( result.first != 0 )
365         boost::throw_exception( basic_filesystem_error<Path>(
366           "boost::filesystem::file_size", ph, result.first ) );
367       return result.second;
368     }
369
370     BOOST_FS_FUNC(space_info) space( const Path & ph )
371     {
372       detail::space_pair result
373         = detail::space_api( ph.external_file_string() );
374       if ( result.first != 0 )
375         boost::throw_exception( basic_filesystem_error<Path>(
376           "boost::filesystem::space", ph, result.first ) );
377       return result.second;
378     }
379
380     BOOST_FS_FUNC(std::time_t) last_write_time( const Path & ph )
381     {
382       detail::time_pair result
383         = detail::last_write_time_api( ph.external_file_string() );
384       if ( result.first != 0 )
385         boost::throw_exception( basic_filesystem_error<Path>(
386           "boost::filesystem::last_write_time", ph, result.first ) );
387       return result.second;
388     }
389
390
391 //  operations  --------------------------------------------------------------//
392
393     BOOST_FS_FUNC(bool) create_directory( const Path & dir_ph )
394     {
395       detail::query_pair result(
396         detail::create_directory_api( dir_ph.external_directory_string() ) );
397       if ( result.first != 0 )
398         boost::throw_exception( basic_filesystem_error<Path>(
399           "boost::filesystem::create_directory",
400           dir_ph, result.first ) );
401       return result.second;
402     }
403
404 #if !defined(BOOST_WINDOWS_API) || defined(BOOST_FS_HARD_LINK)
405     BOOST_FS_FUNC(void)
406     create_hard_link( const Path & to_ph, const Path & from_ph )
407     {
408       system_error_type result( 
409         detail::create_hard_link_api(
410           to_ph.external_file_string(),
411           from_ph.external_file_string() ) );
412       if ( result != 0 )
413         boost::throw_exception( basic_filesystem_error<Path>(
414           "boost::filesystem::create_hard_link",
415           to_ph, from_ph, result ) );
416     }
417
418     BOOST_FS_FUNC(system_error_type)
419     create_hard_link( const Path & to_ph, const Path & from_ph,
420       system_error_type & ec )
421     {
422       ec = detail::create_hard_link_api(
423             to_ph.external_file_string(),
424             from_ph.external_file_string() );
425       return ec;
426     }
427 #endif
428
429     BOOST_FS_FUNC(void)
430     create_symlink( const Path & to_ph, const Path & from_ph )
431     {
432       system_error_type result( 
433         detail::create_symlink_api(
434           to_ph.external_file_string(),
435           from_ph.external_file_string() ) );
436       if ( result )
437         boost::throw_exception( basic_filesystem_error<Path>(
438           "boost::filesystem::create_symlink",
439           to_ph, from_ph, result ) );
440     }
441
442     BOOST_FS_FUNC(system_error_type)
443     create_symlink( const Path & to_ph, const Path & from_ph,
444       system_error_type & ec )
445     {
446       ec = detail::create_symlink_api(
447              to_ph.external_file_string(),
448              from_ph.external_file_string() );
449       return ec;
450     }
451
452     BOOST_FS_FUNC(bool) remove( const Path & ph )
453     {
454       if ( exists( ph )
455         || is_symlink( ph ) ) // handle dangling symbolic links
456         // note that the POSIX behavior for symbolic links is what we want;
457         // the link rather than what it points to is deleted. Windows behavior
458         // doesn't matter; is_symlink() is always false on Windows.
459       {
460         system_error_type result = detail::remove_api( ph.external_file_string() );
461         if ( result != 0 )
462           boost::throw_exception( basic_filesystem_error<Path>(
463             "boost::filesystem::remove",
464             ph, result ) );
465         return true;
466       }
467       return false;
468     }
469
470     BOOST_FS_FUNC(unsigned long) remove_all( const Path & ph )
471     {
472       return exists( ph )|| is_symlink( ph )
473         ? detail::remove_all_aux( ph ) : 0;
474     }
475
476     BOOST_FS_FUNC(void) rename( const Path & from_path, const Path & to_path )
477     {
478       system_error_type result = detail::rename_api(
479         from_path.external_directory_string(),
480         to_path.external_directory_string() );
481       if ( result != 0 )
482         boost::throw_exception( basic_filesystem_error<Path>(
483           "boost::filesystem::rename",
484           from_path, to_path, result ) );
485     }
486
487     BOOST_FS_FUNC(void) copy_file( const Path & from_path, const Path & to_path )
488     {
489       system_error_type result = detail::copy_file_api(
490         from_path.external_directory_string(),
491         to_path.external_directory_string() );
492       if ( result != 0 )
493         boost::throw_exception( basic_filesystem_error<Path>(
494           "boost::filesystem::copy_file",
495           from_path, to_path, result ) );
496     }
497
498     template< class Path >
499     Path current_path()
500     {
501       typename Path::external_string_type ph;
502       boost::filesystem::system_error_type result;
503       if ( (result = detail::get_current_path_api( ph )) != 0 )
504           boost::throw_exception( basic_filesystem_error<Path>(
505             "boost::filesystem::current_path", result ) );
506       return Path( Path::traits_type::to_internal( ph ) );
507     }
508
509     template< class Path >
510     const Path & initial_path()
511     {
512       static Path init_path;
513       if ( init_path.empty() ) init_path = current_path<Path>();
514       return init_path;
515     }
516
517 # ifndef BOOST_FILESYSTEM_NO_DEPRECATED
518     // legacy support
519     inline path current_path()  // overload supports pre-i18n apps
520       { return current_path<boost::filesystem::path>(); }
521     inline const path & initial_path() // overload supports pre-i18n apps
522       { return initial_path<boost::filesystem::path>(); }
523 # endif
524
525     BOOST_FS_FUNC(Path) system_complete( const Path & ph )
526     {
527 # ifdef BOOST_WINDOWS_API
528       if ( ph.empty() ) return ph;
529       BOOST_FS_TYPENAME Path::external_string_type sys_ph;
530       boost::filesystem::system_error_type result;
531       if ( (result = detail::get_full_path_name_api( ph.external_file_string(),
532               sys_ph )) != 0 )
533           boost::throw_exception( basic_filesystem_error<Path>(
534             "boost::filesystem::system_complete", ph, result ) );
535       return Path( Path::traits_type::to_internal( sys_ph ) );
536 # else
537       return (ph.empty() || ph.is_complete())
538         ? ph : current_path<Path>() / ph;
539 # endif
540     }
541
542     BOOST_FS_FUNC(Path)
543     complete( const Path & ph,
544       const Path & base/* = initial_path<Path>() */)
545     {
546       BOOST_ASSERT( base.is_complete()
547         && (ph.is_complete() || !ph.has_root_name())
548         && "boost::filesystem::complete() precondition not met" );
549 #   ifdef BOOST_WINDOWS_PATH
550       if (ph.empty() || ph.is_complete()) return ph;
551       if ( !ph.has_root_name() )
552         return ph.has_root_directory()
553           ? Path( base.root_name() ) / ph
554           : base / ph;
555       return base / ph;
556 #   else
557       return (ph.empty() || ph.is_complete()) ? ph : base / ph;
558 #   endif
559     }
560
561     // VC++ 7.1 had trouble with default arguments, so separate one argument
562     // signatures are provided as workarounds; the effect is the same.
563     BOOST_FS_FUNC(Path) complete( const Path & ph )
564       { return complete( ph, initial_path<Path>() ); }
565
566     BOOST_FS_FUNC(void)
567     last_write_time( const Path & ph, const std::time_t new_time )
568     {
569       boost::filesystem::system_error_type result;
570       if ( (result = detail::last_write_time_api( ph.external_file_string(),
571           new_time )) != 0 )
572         boost::throw_exception( basic_filesystem_error<Path>(
573           "boost::filesystem::last_write_time", ph, result ) );
574     }
575
576 # ifndef BOOST_FILESYSTEM_NARROW_ONLY
577
578     // "do-the-right-thing" overloads  ---------------------------------------//
579
580     inline file_status status( const path & ph )
581       { return status<path>( ph ); }
582     inline file_status status( const wpath & ph )
583       { return status<wpath>( ph ); }
584
585     inline file_status status( const path & ph, system_error_type & ec )
586       { return status<path>( ph, ec ); }
587     inline file_status status( const wpath & ph, system_error_type & ec )
588       { return status<wpath>( ph, ec ); }
589
590     inline file_status symlink_status( const path & ph )
591       { return symlink_status<path>( ph ); }
592     inline file_status symlink_status( const wpath & ph )
593       { return symlink_status<wpath>( ph ); }
594
595     inline file_status symlink_status( const path & ph, system_error_type & ec )
596       { return symlink_status<path>( ph, ec ); }
597     inline file_status symlink_status( const wpath & ph, system_error_type & ec )
598       { return symlink_status<wpath>( ph, ec ); }
599
600     inline bool exists( const path & ph ) { return exists<path>( ph ); }
601     inline bool exists( const wpath & ph ) { return exists<wpath>( ph ); }
602
603     inline bool is_directory( const path & ph )
604       { return is_directory<path>( ph ); }
605     inline bool is_directory( const wpath & ph )
606       { return is_directory<wpath>( ph ); }
607  
608     inline bool is_regular( const path & ph )
609       { return is_regular<path>( ph ); }
610     inline bool is_regular( const wpath & ph )
611       { return is_regular<wpath>( ph ); }
612
613     inline bool is_other( const path & ph )
614       { return is_other<path>( ph ); }
615     inline bool is_other( const wpath & ph )
616       { return is_other<wpath>( ph ); }
617
618     inline bool is_symlink( const path & ph )
619       { return is_symlink<path>( ph ); }
620     inline bool is_symlink( const wpath & ph )
621       { return is_symlink<wpath>( ph ); }
622
623     inline bool is_empty( const path & ph )
624       { return is_empty<path>( ph ); }
625     inline bool is_empty( const wpath & ph )
626       { return is_empty<wpath>( ph ); }
627
628     inline bool equivalent( const path & ph1, const path & ph2 )
629       { return equivalent<path>( ph1, ph2 ); }
630     inline bool equivalent( const wpath & ph1, const wpath & ph2 )
631       { return equivalent<wpath>( ph1, ph2 ); }
632
633     inline boost::uintmax_t file_size( const path & ph )
634       { return file_size<path>( ph ); }
635     inline boost::uintmax_t file_size( const wpath & ph )
636       { return file_size<wpath>( ph ); }
637
638     inline space_info space( const path & ph )
639       { return space<path>( ph ); }
640     inline space_info space( const wpath & ph )
641       { return space<wpath>( ph ); }
642
643     inline std::time_t last_write_time( const path & ph )
644       { return last_write_time<path>( ph ); }
645     inline std::time_t last_write_time( const wpath & ph )
646       { return last_write_time<wpath>( ph ); }
647
648     inline bool create_directory( const path & dir_ph )
649       { return create_directory<path>( dir_ph ); }
650     inline bool create_directory( const wpath & dir_ph )
651       { return create_directory<wpath>( dir_ph ); }
652
653 #if !defined(BOOST_WINDOWS_API) || defined(BOOST_FS_HARD_LINK)
654     inline void create_hard_link( const path & to_ph,
655       const path & from_ph )
656       { return create_hard_link<path>( to_ph, from_ph ); }
657     inline void create_hard_link( const wpath & to_ph,
658       const wpath & from_ph )
659       { return create_hard_link<wpath>( to_ph, from_ph ); }
660
661     inline system_error_type create_hard_link( const path & to_ph,
662       const path & from_ph, system_error_type & ec )
663       { return create_hard_link<path>( to_ph, from_ph, ec ); }
664     inline system_error_type create_hard_link( const wpath & to_ph,
665       const wpath & from_ph, system_error_type & ec )
666       { return create_hard_link<wpath>( to_ph, from_ph, ec ); }
667 #endif
668     
669     inline void create_symlink( const path & to_ph,
670       const path & from_ph )
671       { return create_symlink<path>( to_ph, from_ph ); }
672     inline void create_symlink( const wpath & to_ph,
673       const wpath & from_ph )
674       { return create_symlink<wpath>( to_ph, from_ph ); }
675
676     inline system_error_type create_symlink( const path & to_ph,
677       const path & from_ph, system_error_type & ec )
678       { return create_symlink<path>( to_ph, from_ph, ec ); }
679     inline system_error_type create_symlink( const wpath & to_ph,
680       const wpath & from_ph, system_error_type & ec )
681       { return create_symlink<wpath>( to_ph, from_ph, ec ); }
682
683     inline bool remove( const path & ph )
684       { return remove<path>( ph ); }
685     inline bool remove( const wpath & ph )
686       { return remove<wpath>( ph ); }
687
688     inline unsigned long remove_all( const path & ph )
689       { return remove_all<path>( ph ); }
690     inline unsigned long remove_all( const wpath & ph )
691       { return remove_all<wpath>( ph ); }
692
693     inline void rename( const path & from_path, const path & to_path )
694       { return rename<path>( from_path, to_path ); }
695     inline void rename( const wpath & from_path, const wpath & to_path )
696       { return rename<wpath>( from_path, to_path ); }
697
698     inline void copy_file( const path & from_path, const path & to_path )
699       { return copy_file<path>( from_path, to_path ); }
700     inline void copy_file( const wpath & from_path, const wpath & to_path )
701       { return copy_file<wpath>( from_path, to_path ); }
702
703     inline path system_complete( const path & ph )
704       { return system_complete<path>( ph ); }
705     inline wpath system_complete( const wpath & ph )
706       { return system_complete<wpath>( ph ); }
707
708     inline path complete( const path & ph,
709       const path & base/* = initial_path<path>()*/ )
710       { return complete<path>( ph, base ); }
711     inline wpath complete( const wpath & ph,
712       const wpath & base/* = initial_path<wpath>()*/ )
713       { return complete<wpath>( ph, base ); }
714
715     inline path complete( const path & ph )
716       { return complete<path>( ph, initial_path<path>() ); }
717     inline wpath complete( const wpath & ph )
718       { return complete<wpath>( ph, initial_path<wpath>() ); }
719
720     inline void last_write_time( const path & ph, const std::time_t new_time )
721       { last_write_time<path>( ph, new_time ); }
722     inline void last_write_time( const wpath & ph, const std::time_t new_time )
723       { last_write_time<wpath>( ph, new_time ); }
724
725 # endif // BOOST_FILESYSTEM_NARROW_ONLY
726
727     namespace detail
728     {
729       template<class Path>
730       unsigned long remove_all_aux( const Path & ph )
731       {
732         static const boost::filesystem::basic_directory_iterator<Path> end_itr;
733         unsigned long count = 1;
734         if ( !boost::filesystem::is_symlink( ph ) // don't recurse symbolic links
735           && boost::filesystem::is_directory( ph ) )
736         {
737           for ( boost::filesystem::basic_directory_iterator<Path> itr( ph );
738                 itr != end_itr; ++itr )
739           {
740             count += remove_all_aux( itr->path() );
741           }
742         }
743         boost::filesystem::remove( ph );
744         return count;
745       }
746
747 //  test helper  -------------------------------------------------------------//
748
749     // not part of the documented interface because false positives are possible;
750     // there is no law that says that an OS that has large stat.st_size
751     // actually supports large file sizes.
752       BOOST_FILESYSTEM_DECL bool possible_large_file_size_support();
753
754 //  directory_iterator helpers  ----------------------------------------------//
755
756 //    forwarding functions avoid need for BOOST_FILESYSTEM_DECL for class
757 //    basic_directory_iterator, and so avoid iterator_facade DLL template
758 //    problems. They also overload to the proper external path character type.
759
760       BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
761         dir_itr_first( void *& handle,
762 #if       defined(BOOST_POSIX_API)
763             void *& buffer,
764 #endif
765           const std::string & dir_path,
766           std::string & target, file_status & fs, file_status & symlink_fs );
767       // eof: return==0 && handle==0
768
769       BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
770         dir_itr_increment( void *& handle,
771 #if       defined(BOOST_POSIX_API)
772             void *& buffer,
773 #endif
774           std::string & target, file_status & fs, file_status & symlink_fs );
775       // eof: return==0 && handle==0
776
777       BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
778         dir_itr_close( void *& handle
779 #if       defined(BOOST_POSIX_API)
780             , void *& buffer
781 #endif
782           );
783       // Effects: none if handle==0, otherwise close handle, set handle=0
784
785 #     if defined(BOOST_WINDOWS_API) && !defined(BOOST_FILESYSTEM_NARROW_ONLY)
786       BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
787         dir_itr_first( void *& handle, const std::wstring & ph,
788           std::wstring & target, file_status & fs, file_status & symlink_fs );
789       BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
790         dir_itr_increment( void *& handle, std::wstring & target,
791           file_status & fs, file_status & symlink_fs );
792 #     endif
793
794       template< class Path >
795       class dir_itr_imp
796       {
797       public:  
798         basic_directory_entry<Path> m_directory_entry;
799         void *        m_handle;
800 #       ifdef BOOST_POSIX_API
801           void *      m_buffer;  // see dir_itr_increment implementation
802 #       endif
803         dir_itr_imp() : m_handle(0)
804 #       ifdef BOOST_POSIX_API
805           , m_buffer(0)
806 #       endif
807         {}
808
809         ~dir_itr_imp() { dir_itr_close( m_handle
810 #if       defined(BOOST_POSIX_API)
811             , m_buffer
812 #endif
813           ); }
814       };
815
816     BOOST_FILESYSTEM_DECL extern system_error_type not_found_error;
817     } // namespace detail
818
819 //  basic_directory_iterator  ------------------------------------------------//
820
821     template< class Path >
822     class basic_directory_iterator
823       : public boost::iterator_facade<
824           basic_directory_iterator<Path>,
825           basic_directory_entry<Path>,
826           boost::single_pass_traversal_tag >
827     {
828     public:
829       typedef Path path_type;
830
831       basic_directory_iterator(){}  // creates the "end" iterator
832
833       explicit basic_directory_iterator( const Path & dir_path );
834       basic_directory_iterator( const Path & dir_path, system_error_type & ec );
835
836     private:
837
838       // shared_ptr provides shallow-copy semantics required for InputIterators.
839       // m_imp.get()==0 indicates the end iterator.
840       boost::shared_ptr< detail::dir_itr_imp< Path > >  m_imp;
841
842       friend class boost::iterator_core_access;
843
844       typename boost::iterator_facade<
845         basic_directory_iterator<Path>,
846         basic_directory_entry<Path>,
847         boost::single_pass_traversal_tag >::reference dereference() const 
848       {
849         BOOST_ASSERT( m_imp.get() && "attempt to dereference end iterator" );
850         return m_imp->m_directory_entry;
851       }
852
853       void increment();
854
855       bool equal( const basic_directory_iterator & rhs ) const
856         { return m_imp == rhs.m_imp; }
857
858       system_error_type m_init( const Path & dir_path );
859     };
860
861     typedef basic_directory_iterator< path > directory_iterator;
862 # ifndef BOOST_FILESYSTEM_NARROW_ONLY
863     typedef basic_directory_iterator< wpath > wdirectory_iterator;
864 # endif
865
866     //  basic_directory_iterator implementation  ---------------------------//
867
868     template<class Path>
869     system_error_type basic_directory_iterator<Path>::m_init(
870       const Path & dir_path )
871     {
872       if ( dir_path.empty() )
873       {
874         m_imp.reset();
875         return detail::not_found_error;
876       }
877       system_error_type sys_err;
878       typename Path::external_string_type name;
879       file_status fs, symlink_fs;
880
881       if ( (sys_err = detail::dir_itr_first( m_imp->m_handle,
882 #if   defined(BOOST_POSIX_API)
883         m_imp->m_buffer,
884 #endif
885         dir_path.external_directory_string(),
886         name, fs, symlink_fs )) != 0 )
887       {
888         m_imp.reset();
889         return sys_err;
890       }
891       
892       if ( m_imp->m_handle == 0 ) m_imp.reset(); // eof, so make end iterator
893       else // not eof
894       {
895         m_imp->m_directory_entry.assign( dir_path
896           / Path::traits_type::to_internal( name ), fs, symlink_fs );
897         if ( name[0] == dot<Path>::value // dot or dot-dot
898           && (name.size() == 1
899             || (name[1] == dot<Path>::value
900               && name.size() == 2)) )
901           {  increment(); }
902       }
903       return 0;
904     }
905
906     template<class Path>
907     basic_directory_iterator<Path>::basic_directory_iterator(
908       const Path & dir_path )
909       : m_imp( new detail::dir_itr_imp<Path> )
910     {
911       system_error_type ec( m_init(dir_path) );
912       if ( ec != 0 )
913       {
914         boost::throw_exception( basic_filesystem_error<Path>(  
915           "boost::filesystem::basic_directory_iterator constructor",
916           dir_path, ec ) );
917       }
918     }
919
920     template<class Path>
921     basic_directory_iterator<Path>::basic_directory_iterator(
922       const Path & dir_path, system_error_type & ec )
923       : m_imp( new detail::dir_itr_imp<Path> )
924     {
925       ec = m_init(dir_path);
926     }
927
928     template<class Path>
929     void basic_directory_iterator<Path>::increment()
930     {
931       BOOST_ASSERT( m_imp.get() && "attempt to increment end iterator" );
932       BOOST_ASSERT( m_imp->m_handle != 0 && "internal program error" );
933       
934       system_error_type sys_err(0);
935       typename Path::external_string_type name;
936       file_status fs, symlink_fs;
937
938       for (;;)
939       {
940         if ( (sys_err = detail::dir_itr_increment( m_imp->m_handle,
941 #if     defined(BOOST_POSIX_API)
942           m_imp->m_buffer,
943 #endif
944           name, fs, symlink_fs )) != 0 )
945         {
946           boost::throw_exception( basic_filesystem_error<Path>(  
947             "boost::filesystem::basic_directory_iterator increment",
948             m_imp->m_directory_entry.path().branch_path(), sys_err ) );
949         }
950         if ( m_imp->m_handle == 0 ) { m_imp.reset(); return; } // eof, make end
951         if ( !(name[0] == dot<Path>::value // !(dot or dot-dot)
952           && (name.size() == 1
953             || (name[1] == dot<Path>::value
954               && name.size() == 2))) )
955         {
956           m_imp->m_directory_entry.replace_leaf(
957             Path::traits_type::to_internal( name ), fs, symlink_fs );
958           return;
959         }
960       }
961     }
962
963     //  basic_directory_entry  -----------------------------------------------//
964     
965     template<class Path>
966     class basic_directory_entry
967     {
968     public:
969       typedef Path path_type;
970       typedef typename Path::string_type string_type;
971
972       // compiler generated copy-ctor, copy assignment, and destructor apply
973
974       basic_directory_entry() {}
975       explicit basic_directory_entry( const path_type & p,
976         file_status st = file_status(), file_status symlink_st=file_status() )
977         : m_path(p), m_status(st), m_symlink_status(symlink_st)
978         {}
979
980       void assign( const path_type & p,
981         file_status st, file_status symlink_st )
982         { m_path = p; m_status = st; m_symlink_status = symlink_st; }
983
984       void replace_leaf( const string_type & s,
985         file_status st, file_status symlink_st )
986      {
987        m_path.remove_leaf();
988        m_path /= s;
989        m_status = st;
990        m_symlink_status = symlink_st;
991      }
992
993       const Path &   path() const { return m_path; }
994       file_status   status() const;
995       file_status   status( system_error_type & ec ) const;
996       file_status   symlink_status() const;
997       file_status   symlink_status( system_error_type & ec ) const;
998
999       // conversion simplifies the most common use of basic_directory_entry
1000       operator const path_type &() const { return m_path; }
1001
1002 #   ifndef BOOST_FILESYSTEM_NO_DEPRECATED
1003       // deprecated functions preserve common use cases in legacy code
1004       typename Path::string_type leaf() const
1005       {
1006         return path().leaf();
1007       }
1008       typename Path::string_type string() const
1009       {
1010         return path().string();
1011       }
1012 #   endif
1013
1014     private:
1015       path_type             m_path;
1016       mutable file_status  m_status;           // stat()-like
1017       mutable file_status  m_symlink_status;   // lstat()-like
1018         // note: m_symlink_status is not used by Windows implementation
1019
1020     }; // basic_directory_status
1021
1022     typedef basic_directory_entry<path> directory_entry;
1023 # ifndef BOOST_FILESYSTEM_NARROW_ONLY
1024     typedef basic_directory_entry<wpath> wdirectory_entry;
1025 # endif
1026
1027     //  basic_directory_entry implementation  --------------------------------//
1028
1029     template<class Path>
1030     file_status
1031     basic_directory_entry<Path>::status() const
1032     {
1033       if ( !status_known( m_status ) )
1034       {
1035 #     ifndef BOOST_WINDOWS_API
1036         if ( status_known( m_symlink_status )
1037           && !is_symlink( m_symlink_status ) )
1038           { m_status = m_symlink_status; }
1039         else { m_status = boost::filesystem::status( m_path ); }
1040 #     else
1041         m_status = boost::filesystem::status( m_path );
1042 #     endif
1043       }
1044       return m_status;
1045     }
1046
1047     template<class Path>
1048     file_status
1049     basic_directory_entry<Path>::status( system_error_type & ec ) const
1050     {
1051       if ( !status_known( m_status ) )
1052       {
1053 #     ifndef BOOST_WINDOWS_API
1054         if ( status_known( m_symlink_status )
1055           && !is_symlink( m_symlink_status ) )
1056           { ec = 0; m_status = m_symlink_status; }
1057         else { m_status = boost::filesystem::status( m_path, ec ); }
1058 #     else
1059         m_status = boost::filesystem::status( m_path, ec );
1060 #     endif
1061       }
1062       else ec = 0;
1063       return m_status;
1064     }
1065
1066     template<class Path>
1067     file_status
1068     basic_directory_entry<Path>::symlink_status() const
1069     {
1070 #   ifndef BOOST_WINDOWS_API
1071       if ( !status_known( m_symlink_status ) )
1072         { m_symlink_status = boost::filesystem::symlink_status( m_path ); }
1073       return m_symlink_status;
1074 #   else
1075       return status();
1076 #   endif
1077     }
1078
1079     template<class Path>
1080     file_status
1081     basic_directory_entry<Path>::symlink_status( system_error_type & ec ) const
1082     {
1083 #   ifndef BOOST_WINDOWS_API
1084       if ( !status_known( m_symlink_status ) )
1085         { m_symlink_status = boost::filesystem::symlink_status( m_path, ec ); }
1086       else ec = 0;
1087       return m_symlink_status;
1088 #   else
1089       return status( ec );
1090 #   endif
1091     }
1092   } // namespace filesystem
1093 } // namespace boost
1094
1095 #undef BOOST_FS_FUNC
1096
1097
1098 #include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
1099 #endif // BOOST_FILESYSTEM_OPERATIONS_HPP