Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/filesystem/operations.hpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 38.2 KB
Line 
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
61namespace 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
Note: See TracBrowser for help on using the repository browser.