diff options
Diffstat (limited to '3rdParty/Boost/libs/filesystem/src/operations.cpp')
| -rw-r--r-- | 3rdParty/Boost/libs/filesystem/src/operations.cpp | 1367 | 
1 files changed, 1367 insertions, 0 deletions
| diff --git a/3rdParty/Boost/libs/filesystem/src/operations.cpp b/3rdParty/Boost/libs/filesystem/src/operations.cpp new file mode 100644 index 0000000..0c74504 --- /dev/null +++ b/3rdParty/Boost/libs/filesystem/src/operations.cpp @@ -0,0 +1,1367 @@ +//  operations.cpp  ----------------------------------------------------------// + +//  Copyright 2002-2005 Beman Dawes +//  Copyright 2001 Dietmar Kuehl +//  Use, modification, and distribution is subject to the Boost Software +//  License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +//  at http://www.boost.org/LICENSE_1_0.txt) + +//  See library home page at http://www.boost.org/libs/filesystem + +//----------------------------------------------------------------------------//  + +// define BOOST_FILESYSTEM_SOURCE so that <boost/filesystem/config.hpp> knows +// the library is being built (possibly exporting rather than importing code) +#define BOOST_FILESYSTEM_SOURCE  + +#define _POSIX_PTHREAD_SEMANTICS  // Sun readdir_r() needs this + +// enable the XPG-compliant version of readdir_r() on AIX +#if defined(_AIX) +# define _LINUX_SOURCE_COMPAT +#endif + +#if !(defined(__HP_aCC) && defined(_ILP32) && \ +      !defined(_STATVFS_ACPP_PROBLEMS_FIXED)) +#define _FILE_OFFSET_BITS 64 // at worst, these defines may have no effect, +#endif +#define __USE_FILE_OFFSET64 // but that is harmless on Windows and on POSIX +      // 64-bit systems or on 32-bit systems which don't have files larger  +      // than can be represented by a traditional POSIX/UNIX off_t type.  +      // OTOH, defining them should kick in 64-bit off_t's (and thus  +      // st_size) on 32-bit systems that provide the Large File +      // Support (LFS) interface, such as Linux, Solaris, and IRIX. +      // The defines are given before any headers are included to +      // ensure that they are available to all included headers. +      // That is required at least on Solaris, and possibly on other +      // systems as well. + +// for some compilers (CodeWarrior, for example), windows.h +// is getting included by some other boost header, so do this early: +#if !defined(_WIN32_WINNT) +#define _WIN32_WINNT 0x0500 // Default to Windows 2K or later +#endif + + +#include <boost/filesystem/operations.hpp> +#include <boost/scoped_array.hpp> +#include <boost/throw_exception.hpp> +#include <boost/detail/workaround.hpp> + +namespace fs = boost::filesystem; +using boost::system::error_code; +using boost::system::system_category; + +# if defined(BOOST_WINDOWS_API) +#   include <windows.h> +#   if defined(__BORLANDC__) || defined(__MWERKS__) +#     if defined(__BORLANDC__) +        using std::time_t; +#     endif +#     include <utime.h> +#   else +#     include <sys/utime.h> +#   endif + +# else // BOOST_POSIX_API +#   include <sys/types.h> +#   if !defined(__APPLE__) && !defined(__OpenBSD__) +#     include <sys/statvfs.h> +#     define BOOST_STATVFS statvfs +#     define BOOST_STATVFS_F_FRSIZE vfs.f_frsize +#   else +#ifdef __OpenBSD__ +#     include <sys/param.h> +#endif +#     include <sys/mount.h> +#     define BOOST_STATVFS statfs +#     define BOOST_STATVFS_F_FRSIZE static_cast<boost::uintmax_t>( vfs.f_bsize ) +#   endif +#   include <dirent.h> +#   include <unistd.h> +#   include <fcntl.h> +#   include <utime.h> +#   include "limits.h" +# endif + +//  BOOST_FILESYSTEM_STATUS_CACHE enables file_status cache in +//  dir_itr_increment. The config tests are placed here because some of the +//  macros being tested come from dirent.h. +// +// TODO: find out what macros indicate dirent::d_type present in more libraries +# if defined(BOOST_WINDOWS_API) \ +  || (defined(_DIRENT_HAVE_D_TYPE) /* defined by GNU C library if d_type present */ \ +    && !(defined(__SUNPRO_CC) && !defined(__sun)))  // _DIRENT_HAVE_D_TYPE wrong for Sun compiler on Linux +#   define BOOST_FILESYSTEM_STATUS_CACHE +# endif + +#include <sys/stat.h>  // even on Windows some functions use stat() +#include <string> +#include <cstring> +#include <cstdio>      // for remove, rename +#include <cerrno> +#include <cassert> +// #include <iostream>    // for debugging only; comment out when not in use + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std { using ::strcmp; using ::remove; using ::rename; } +#endif + +//  helpers  -----------------------------------------------------------------// + +namespace +{ +  const error_code ok; + +  bool is_empty_directory( const std::string & dir_path ) +  { +    static const fs::directory_iterator end_itr; +    return fs::directory_iterator(fs::path(dir_path)) == end_itr; +  } + +#ifdef BOOST_WINDOWS_API +   +// For Windows, the xxxA form of various function names is used to avoid +// inadvertently getting wide forms of the functions. (The undecorated +// forms are actually macros, so can misfire if the user has various +// other macros defined. There was a bug report of this happening.) + +  inline DWORD get_file_attributes( const char * ph ) +    { return ::GetFileAttributesA( ph ); } + +# ifndef BOOST_FILESYSTEM_NARROW_ONLY + +  inline DWORD get_file_attributes( const wchar_t * ph ) +    { return ::GetFileAttributesW( ph ); } + +  bool is_empty_directory( const std::wstring & dir_path ) +  { +    static const fs::wdirectory_iterator wend_itr; +    return fs::wdirectory_iterator(fs::wpath(dir_path)) == wend_itr; +  } + +  inline BOOL get_file_attributes_ex( const wchar_t * ph, +    WIN32_FILE_ATTRIBUTE_DATA & fad ) +  { return ::GetFileAttributesExW( ph, ::GetFileExInfoStandard, &fad ); } +       +  HANDLE create_file( const wchar_t * ph, DWORD dwDesiredAccess, +    DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, +    DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, +    HANDLE hTemplateFile ) +  { +    return ::CreateFileW( ph, dwDesiredAccess, dwShareMode, +      lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, +      hTemplateFile ); +  } + +  inline DWORD get_current_directory( DWORD sz, wchar_t * buf ) +    { return ::GetCurrentDirectoryW( sz, buf ); }  + +  inline bool set_current_directory( const wchar_t * buf ) +    { return ::SetCurrentDirectoryW( buf ) != 0 ; }  + +  inline bool get_free_disk_space( const std::wstring & ph, +    PULARGE_INTEGER avail, PULARGE_INTEGER total, PULARGE_INTEGER free ) +    { return ::GetDiskFreeSpaceExW( ph.c_str(), avail, total, free ) != 0; } + +  inline std::size_t get_full_path_name( +    const std::wstring & ph, std::size_t len, wchar_t * buf, wchar_t ** p ) +  { +    return static_cast<std::size_t>( +      ::GetFullPathNameW( ph.c_str(), +        static_cast<DWORD>(len), buf, p )); +  }  + +  inline bool remove_directory( const std::wstring & ph ) +    { return ::RemoveDirectoryW( ph.c_str() ) != 0; } + +  inline bool delete_file( const std::wstring & ph ) +    { return ::DeleteFileW( ph.c_str() ) != 0; } + +  inline bool create_directory( const std::wstring & dir ) +    {  return ::CreateDirectoryW( dir.c_str(), 0 ) != 0; } + +#if _WIN32_WINNT >= 0x500 +  inline bool create_hard_link( const std::wstring & to_ph, +    const std::wstring & from_ph ) +    {  return ::CreateHardLinkW( from_ph.c_str(), to_ph.c_str(), 0 ) != 0; } +#endif +   +# endif // ifndef BOOST_FILESYSTEM_NARROW_ONLY + +  template< class String > +  fs::file_status status_template( const String & ph, error_code & ec ) +  { +    DWORD attr( get_file_attributes( ph.c_str() ) ); +    if ( attr == 0xFFFFFFFF ) +    { +      ec = error_code( ::GetLastError(), system_category ); +      if ((ec.value() == ERROR_FILE_NOT_FOUND) +        || (ec.value() == ERROR_PATH_NOT_FOUND) +        || (ec.value() == ERROR_INVALID_NAME) // "tools/jam/src/:sys:stat.h", "//foo" +        || (ec.value() == ERROR_INVALID_DRIVE) // USB card reader with no card inserted +        || (ec.value() == ERROR_INVALID_PARAMETER) // ":sys:stat.h" +        || (ec.value() == ERROR_BAD_PATHNAME) // "//nosuch" on Win64 +        || (ec.value() == ERROR_BAD_NETPATH)) // "//nosuch" on Win32 +      { +        ec = ok; // these are not considered errors; +                           // the status is considered not found +        return fs::file_status( fs::file_not_found ); +      } +      else if ((ec.value() == ERROR_SHARING_VIOLATION)) +      { +        ec = ok; // these are not considered errors; +                           // the file exists but the type is not known  +        return fs::file_status( fs::type_unknown ); +      } +      return fs::file_status( fs::status_unknown ); +    } +    ec = ok;; +    return (attr & FILE_ATTRIBUTE_DIRECTORY) +      ? fs::file_status( fs::directory_file ) +      : fs::file_status( fs::regular_file ); +  } + +  BOOL get_file_attributes_ex( const char * ph, +    WIN32_FILE_ATTRIBUTE_DATA & fad ) +  { return ::GetFileAttributesExA( ph, ::GetFileExInfoStandard, &fad ); } + +  template< class String > +  boost::filesystem::detail::query_pair +  is_empty_template( const String & ph ) +  { +    WIN32_FILE_ATTRIBUTE_DATA fad; +    if ( get_file_attributes_ex( ph.c_str(), fad ) == 0 ) +      return std::make_pair( error_code( ::GetLastError(), system_category ), false );     +    return std::make_pair( ok, +      ( fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) +        ? is_empty_directory( ph ) +        :( !fad.nFileSizeHigh && !fad.nFileSizeLow ) ); +  } + +  HANDLE create_file( const char * ph, DWORD dwDesiredAccess, +    DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, +    DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, +    HANDLE hTemplateFile ) +  { +    return ::CreateFileA( ph, dwDesiredAccess, dwShareMode, +      lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, +      hTemplateFile ); +  } + +  // Thanks to Jeremy Maitin-Shepard for much help and for permission to +  // base the equivalent() implementation on portions of his  +  // file-equivalence-win32.cpp experimental code. +  struct handle_wrapper +  { +    HANDLE handle; +    handle_wrapper( HANDLE h ) +      : handle(h) {} +    ~handle_wrapper() +    { +      if ( handle != INVALID_HANDLE_VALUE ) +        ::CloseHandle(handle); +    } +  }; + +  template< class String > +  boost::filesystem::detail::query_pair +  equivalent_template( const String & ph1, const String & ph2 ) +  { +    // Note well: Physical location on external media is part of the +    // equivalence criteria. If there are no open handles, physical location +    // can change due to defragmentation or other relocations. Thus handles +    // must be held open until location information for both paths has +    // been retrieved. +    handle_wrapper p1( +      create_file( +          ph1.c_str(), +          0, +          FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, +          0, +          OPEN_EXISTING, +          FILE_FLAG_BACKUP_SEMANTICS, +          0 ) ); +    int error1(0); // save error code in case we have to throw +    if ( p1.handle == INVALID_HANDLE_VALUE ) +      error1 = ::GetLastError(); +    handle_wrapper p2( +      create_file( +          ph2.c_str(), +          0, +          FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, +          0, +          OPEN_EXISTING, +          FILE_FLAG_BACKUP_SEMANTICS, +          0 ) ); +    if ( p1.handle == INVALID_HANDLE_VALUE +      || p2.handle == INVALID_HANDLE_VALUE ) +    { +      if ( p1.handle != INVALID_HANDLE_VALUE +        || p2.handle != INVALID_HANDLE_VALUE ) +        { return std::make_pair( ok, false ); } +      assert( p1.handle == INVALID_HANDLE_VALUE +        && p2.handle == INVALID_HANDLE_VALUE ); +        { return std::make_pair( error_code( error1, system_category), false ); } +    } +    // at this point, both handles are known to be valid +    BY_HANDLE_FILE_INFORMATION info1, info2; +    if ( !::GetFileInformationByHandle( p1.handle, &info1 ) ) +      { return std::make_pair( error_code( ::GetLastError(), system_category ), false ); } +    if ( !::GetFileInformationByHandle( p2.handle, &info2 ) ) +      { return std::make_pair( error_code( ::GetLastError(), system_category ), false ); } +    // In theory, volume serial numbers are sufficient to distinguish between +    // devices, but in practice VSN's are sometimes duplicated, so last write +    // time and file size are also checked. +      return std::make_pair( ok, +        info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber +        && info1.nFileIndexHigh == info2.nFileIndexHigh +        && info1.nFileIndexLow == info2.nFileIndexLow +        && info1.nFileSizeHigh == info2.nFileSizeHigh +        && info1.nFileSizeLow == info2.nFileSizeLow +        && info1.ftLastWriteTime.dwLowDateTime +          == info2.ftLastWriteTime.dwLowDateTime +        && info1.ftLastWriteTime.dwHighDateTime +          == info2.ftLastWriteTime.dwHighDateTime ); +  } + +  template< class String > +  boost::filesystem::detail::uintmax_pair +  file_size_template( const String & ph ) +  { +    WIN32_FILE_ATTRIBUTE_DATA fad; +    // by now, intmax_t is 64-bits on all Windows compilers +    if ( get_file_attributes_ex( ph.c_str(), fad ) == 0 ) +      return std::make_pair( error_code( ::GetLastError(), system_category ), 0 );     +    if ( (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) !=0 ) +      return std::make_pair( error_code( ERROR_FILE_NOT_FOUND, system_category), 0 ); +    return std::make_pair( ok, +      (static_cast<boost::uintmax_t>(fad.nFileSizeHigh) +        << (sizeof(fad.nFileSizeLow)*8)) +      + fad.nFileSizeLow ); +  } + +  inline bool get_free_disk_space( const std::string & ph, +    PULARGE_INTEGER avail, PULARGE_INTEGER total, PULARGE_INTEGER free ) +    { return ::GetDiskFreeSpaceExA( ph.c_str(), avail, total, free ) != 0; } + +  template< class String > +  boost::filesystem::detail::space_pair +  space_template( String & ph ) +  { +    ULARGE_INTEGER avail, total, free; +    boost::filesystem::detail::space_pair result; +    if ( get_free_disk_space( ph, &avail, &total, &free ) ) +    { +      result.first = ok; +      result.second.capacity +        = (static_cast<boost::uintmax_t>(total.HighPart) << 32) +          + total.LowPart; +      result.second.free +        = (static_cast<boost::uintmax_t>(free.HighPart) << 32) +          + free.LowPart; +      result.second.available +        = (static_cast<boost::uintmax_t>(avail.HighPart) << 32) +          + avail.LowPart; +    } +    else +    { +      result.first = error_code( ::GetLastError(), system_category ); +      result.second.capacity = result.second.free +        = result.second.available = 0; +    } +    return result; +  } + +  inline DWORD get_current_directory( DWORD sz, char * buf ) +    { return ::GetCurrentDirectoryA( sz, buf ); }  + +  template< class String > +  error_code +  get_current_path_template( String & ph ) +  { +    DWORD sz; +    if ( (sz = get_current_directory( 0, +      static_cast<typename String::value_type*>(0) )) == 0 ) +      { sz = 1; } +    typedef typename String::value_type value_type; +    boost::scoped_array<value_type> buf( new value_type[sz] ); +    if ( get_current_directory( sz, buf.get() ) == 0 ) +      return error_code( ::GetLastError(), system_category ); +    ph = buf.get(); +    return ok; +  } + +  inline bool set_current_directory( const char * buf ) +    { return ::SetCurrentDirectoryA( buf ) != 0; }  + +  template< class String > +  error_code +  set_current_path_template( const String & ph ) +  { +    return error_code( set_current_directory( ph.c_str() ) +      ? 0 : ::GetLastError(), system_category ); +  } + +  inline std::size_t get_full_path_name( +    const std::string & ph, std::size_t len, char * buf, char ** p ) +  { +    return static_cast<std::size_t>( +      ::GetFullPathNameA( ph.c_str(), +        static_cast<DWORD>(len), buf, p )); +  }  + +  const std::size_t buf_size( 128 ); + +  template<class String> +  error_code +  get_full_path_name_template( const String & ph, String & target ) +  { +    typename String::value_type buf[buf_size]; +    typename String::value_type * pfn; +    std::size_t len = get_full_path_name( ph, +      buf_size , buf, &pfn ); +    if ( len == 0 ) return error_code( ::GetLastError(), system_category ); +    if ( len > buf_size ) +    { +      typedef typename String::value_type value_type; +      boost::scoped_array<value_type> big_buf( new value_type[len] ); +      if ( (len=get_full_path_name( ph, len , big_buf.get(), &pfn )) +        == 0 ) return error_code( ::GetLastError(), system_category ); +      big_buf[len] = '\0'; +      target = big_buf.get(); +      return ok; +    } +    buf[len] = '\0'; +    target = buf; +    return ok; +  } + +  template<class String> +  error_code +  get_file_write_time( const String & ph, FILETIME & last_write_time ) +  { +    handle_wrapper hw( +      create_file( ph.c_str(), 0, +        FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, +        OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 ) ); +    if ( hw.handle == INVALID_HANDLE_VALUE ) +      return error_code( ::GetLastError(), system_category ); +    return error_code( ::GetFileTime( hw.handle, 0, 0, &last_write_time ) != 0 +      ? 0 : ::GetLastError(), system_category ); +  } + +  template<class String> +  error_code +  set_file_write_time( const String & ph, const FILETIME & last_write_time ) +  { +    handle_wrapper hw( +      create_file( ph.c_str(), FILE_WRITE_ATTRIBUTES, +        FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, +        OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 ) ); +    if ( hw.handle == INVALID_HANDLE_VALUE ) +      return error_code( ::GetLastError(), system_category ); +    return error_code( ::SetFileTime( hw.handle, 0, 0, &last_write_time ) != 0 +      ? 0 : ::GetLastError(), system_category ); +  } + +  // these constants come from inspecting some Microsoft sample code +  std::time_t to_time_t( const FILETIME & ft ) +  { +    __int64 t = (static_cast<__int64>( ft.dwHighDateTime ) << 32) +      + ft.dwLowDateTime; +# if !defined( BOOST_MSVC ) || BOOST_MSVC > 1300 // > VC++ 7.0 +    t -= 116444736000000000LL; +# else +    t -= 116444736000000000; +# endif +    t /= 10000000; +    return static_cast<std::time_t>( t ); +  } + +  void to_FILETIME( std::time_t t, FILETIME & ft ) +  { +    __int64 temp = t; +    temp *= 10000000; +# if !defined( BOOST_MSVC ) || BOOST_MSVC > 1300 // > VC++ 7.0 +    temp += 116444736000000000LL; +# else +    temp += 116444736000000000; +# endif +    ft.dwLowDateTime = static_cast<DWORD>( temp ); +    ft.dwHighDateTime = static_cast<DWORD>( temp >> 32 ); +  } + +  template<class String> +  boost::filesystem::detail::time_pair +  last_write_time_template( const String & ph ) +  { +    FILETIME lwt; +    error_code ec( +      get_file_write_time( ph, lwt ) ); +    return std::make_pair( ec, to_time_t( lwt ) ); +  } + +  template<class String> +  error_code +  last_write_time_template( const String & ph, const std::time_t new_time ) +  { +    FILETIME lwt; +    to_FILETIME( new_time, lwt ); +    return set_file_write_time( ph, lwt ); +  } + +  bool remove_directory( const std::string & ph ) +    { return ::RemoveDirectoryA( ph.c_str() ) != 0; } +   +  bool delete_file( const std::string & ph ) +    { return ::DeleteFileA( ph.c_str() ) != 0; } +   +  template<class String> +  error_code +  remove_template( const String & ph ) +  { +    // TODO: test this code in the presence of Vista symlinks, +    // including dangling, self-referal, and cyclic symlinks +    error_code ec; +    fs::file_status sf( fs::detail::status_api( ph, ec ) ); +    if ( ec )  +      return ec; +    if ( sf.type() == fs::file_not_found ) +      return ok; +    if ( fs::is_directory( sf ) ) +    { +      if ( !remove_directory( ph ) ) +        return error_code(::GetLastError(), system_category); +    } +    else +    { +      if ( !delete_file( ph ) ) return error_code(::GetLastError(), system_category); +    } +    return ok; +  } + +  inline bool create_directory( const std::string & dir ) +    {  return ::CreateDirectoryA( dir.c_str(), 0 ) != 0; } +          +  template<class String> +  boost::filesystem::detail::query_pair +  create_directory_template( const String & dir_ph ) +  { +    error_code error, dummy; +    if ( create_directory( dir_ph ) ) return std::make_pair( error, true ); +    error = error_code( ::GetLastError(), system_category ); +    // an error here may simply mean the postcondition is already met +    if ( error.value() == ERROR_ALREADY_EXISTS +      && fs::is_directory( fs::detail::status_api( dir_ph, dummy ) ) ) +      return std::make_pair( ok, false ); +    return std::make_pair( error, false ); +  } + +#if _WIN32_WINNT >= 0x500 +  inline bool create_hard_link( const std::string & to_ph, +    const std::string & from_ph ) +    {  return ::CreateHardLinkA( from_ph.c_str(), to_ph.c_str(), 0 ) != 0; } +#endif +   +#if _WIN32_WINNT >= 0x500 +  template<class String> +  error_code +  create_hard_link_template( const String & to_ph, +    const String & from_ph ) +  { +    return error_code( create_hard_link( to_ph.c_str(), from_ph.c_str() ) +      ? 0 : ::GetLastError(), system_category ); +  } +#endif + +#else // BOOST_POSIX_API + +  int posix_remove( const char * p ) +  { +#     if defined(__QNXNTO__) || (defined(__MSL__) && (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))) +        // Some Metrowerks C library versions fail on directories because of a +        // known Metrowerks coding error in ::remove. Workaround is to call +        // rmdir() or unlink() as indicated. +        // Same bug also reported for QNX, with the same fix. +        int err = ::unlink( p ); +        if ( err == 0 || errno != EPERM ) +          return err; +        return ::rmdir( p ); +#     else +        return std::remove( p ); +#     endif +  } + +#endif +} // unnamed namespace + +namespace boost +{ +  namespace filesystem +  { +    namespace detail +    { +      BOOST_FILESYSTEM_DECL system::error_code throws; + +//  free functions  ----------------------------------------------------------// + +      BOOST_FILESYSTEM_DECL error_code not_found_error() +      { +#     ifdef BOOST_WINDOWS_API +        return error_code(ERROR_PATH_NOT_FOUND, system_category); +#     else +        return error_code(ENOENT, system_category);  +#     endif +      } + +      BOOST_FILESYSTEM_DECL bool possible_large_file_size_support() +      { +#   ifdef BOOST_POSIX_API +        struct stat lcl_stat; +        return sizeof( lcl_stat.st_size ) > 4; +#   else +        return true; +#   endif +      } + +#   ifdef BOOST_WINDOWS_API + +      BOOST_FILESYSTEM_DECL fs::file_status +        status_api( const std::string & ph, error_code & ec ) +        { return status_template( ph, ec ); } + +#     ifndef BOOST_FILESYSTEM_NARROW_ONLY + +      BOOST_FILESYSTEM_DECL fs::file_status +      status_api( const std::wstring & ph, error_code & ec ) +        { return status_template( ph, ec ); } + +      BOOST_FILESYSTEM_DECL bool symbolic_link_exists_api( const std::wstring & ) +        { return false; } + +      BOOST_FILESYSTEM_DECL +      fs::detail::query_pair is_empty_api( const std::wstring & ph ) +        { return is_empty_template( ph ); } + +      BOOST_FILESYSTEM_DECL +      fs::detail::query_pair +      equivalent_api( const std::wstring & ph1, const std::wstring & ph2 ) +        { return equivalent_template( ph1, ph2 ); } + +      BOOST_FILESYSTEM_DECL +      fs::detail::uintmax_pair file_size_api( const std::wstring & ph ) +        { return file_size_template( ph ); } + +      BOOST_FILESYSTEM_DECL +      fs::detail::space_pair space_api( const std::wstring & ph ) +        { return space_template( ph ); } + +      BOOST_FILESYSTEM_DECL +      error_code  +      get_current_path_api( std::wstring & ph ) +        { return get_current_path_template( ph ); } + +      BOOST_FILESYSTEM_DECL +      error_code  +      set_current_path_api( const std::wstring & ph ) +        { return set_current_path_template( ph ); } + +      BOOST_FILESYSTEM_DECL error_code +        get_full_path_name_api( const std::wstring & ph, std::wstring & target ) +         { return get_full_path_name_template( ph, target ); } + +      BOOST_FILESYSTEM_DECL time_pair +        last_write_time_api( const std::wstring & ph ) +          { return last_write_time_template( ph ); } +  +      BOOST_FILESYSTEM_DECL error_code +        last_write_time_api( const std::wstring & ph, std::time_t new_value ) +          { return last_write_time_template( ph, new_value ); } + +      BOOST_FILESYSTEM_DECL fs::detail::query_pair +      create_directory_api( const std::wstring & ph ) +        { return create_directory_template( ph ); } + +#if _WIN32_WINNT >= 0x500 +      BOOST_FILESYSTEM_DECL error_code +      create_hard_link_api( const std::wstring & to_ph, +        const std::wstring & from_ph ) +        { return create_hard_link_template( to_ph, from_ph ); } +#endif +       +      BOOST_FILESYSTEM_DECL error_code +      create_symlink_api( const std::wstring & /*to_ph*/, +        const std::wstring & /*from_ph*/ ) +        { return error_code( ERROR_NOT_SUPPORTED, system_category ); } + +      BOOST_FILESYSTEM_DECL error_code +      remove_api( const std::wstring & ph ) { return remove_template( ph ); } + +      BOOST_FILESYSTEM_DECL error_code +      rename_api( const std::wstring & from, const std::wstring & to ) +      { +        return error_code( ::MoveFileW( from.c_str(), to.c_str() ) +          ? 0 : ::GetLastError(), system_category ); +      } + +      BOOST_FILESYSTEM_DECL error_code +      copy_file_api( const std::wstring & from, const std::wstring & to ) +      { +        return error_code( ::CopyFileW( from.c_str(), to.c_str(), /*fail_if_exists=*/true ) +          ? 0 : ::GetLastError(), system_category ); +      } + +      BOOST_FILESYSTEM_DECL bool create_file_api( const std::wstring & ph, +        std::ios_base::openmode mode ) // true if succeeds +      { +        DWORD access( +          ((mode & std::ios_base::in) == 0 ? 0 : GENERIC_READ) +          | ((mode & std::ios_base::out) == 0 ? 0 : GENERIC_WRITE) ); + +        DWORD disposition(0); // see 27.8.1.3 Table 92 +        if ( (mode&~std::ios_base::binary) +          == (std::ios_base::out|std::ios_base::app) ) +          disposition = OPEN_ALWAYS; +        else if ( (mode&~(std::ios_base::binary|std::ios_base::out)) +          == std::ios_base::in ) disposition = OPEN_EXISTING; +        else if ( ((mode&~(std::ios_base::binary|std::ios_base::trunc)) +          == std::ios_base::out ) +          || ((mode&~std::ios_base::binary) +          == (std::ios_base::in|std::ios_base::out|std::ios_base::trunc)) ) +          disposition = CREATE_ALWAYS; +        else assert( 0 && "invalid mode argument" ); + +        HANDLE handle ( ::CreateFileW( ph.c_str(), access, +          FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, +          disposition, (mode &std::ios_base::out) != 0 +          ? FILE_ATTRIBUTE_ARCHIVE : FILE_ATTRIBUTE_NORMAL, 0 ) ); +        if ( handle == INVALID_HANDLE_VALUE ) return false; +        ::CloseHandle( handle ); +        return true; +      } + +      BOOST_FILESYSTEM_DECL std::string narrow_path_api( +        const std::wstring & ph ) // return is empty if fails +      { +        std::string narrow_short_form; +        std::wstring short_form; +        for ( DWORD buf_sz( static_cast<DWORD>( ph.size()+1 ));; ) +        { +          boost::scoped_array<wchar_t> buf( new wchar_t[buf_sz] ); +          DWORD sz( ::GetShortPathNameW( ph.c_str(), buf.get(), buf_sz ) ); +          if ( sz == 0 ) return narrow_short_form; +          if ( sz <= buf_sz ) +          { +            short_form += buf.get(); +            break; +          } +          buf_sz = sz + 1; +        } +        // contributed by Takeshi Mouri: +        int narrow_sz( ::WideCharToMultiByte( CP_ACP, 0, +          short_form.c_str(), static_cast<int>(short_form.size()), 0, 0, 0, 0 ) ); +        boost::scoped_array<char> narrow_buf( new char[narrow_sz] ); +        ::WideCharToMultiByte( CP_ACP, 0, +          short_form.c_str(), static_cast<int>(short_form.size()), +          narrow_buf.get(), narrow_sz, 0, 0 ); +        narrow_short_form.assign(narrow_buf.get(), narrow_sz); + +        return narrow_short_form; +      } + +      BOOST_FILESYSTEM_DECL error_code +      dir_itr_first( void *& handle, const std::wstring & dir, +        std::wstring & target, file_status & sf, file_status & symlink_sf ) +      { +        // use a form of search Sebastian Martel reports will work with Win98 +        std::wstring dirpath( dir ); +        dirpath += (dirpath.empty() +          || dirpath[dirpath.size()-1] != L'\\') ? L"\\*" : L"*"; + +        WIN32_FIND_DATAW data; +        if ( (handle = ::FindFirstFileW( dirpath.c_str(), &data )) +          == INVALID_HANDLE_VALUE ) +        {  +          handle = 0; +          return error_code( ::GetLastError() == ERROR_FILE_NOT_FOUND +            ? 0 : ::GetLastError(), system_category ); +        } +        target = data.cFileName; +        if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) +          { sf.type( directory_file ); symlink_sf.type( directory_file ); } +        else { sf.type( regular_file ); symlink_sf.type( regular_file ); } +        return ok; +      }   + +      BOOST_FILESYSTEM_DECL error_code +      dir_itr_increment( void *& handle, std::wstring & target, +        file_status & sf, file_status & symlink_sf ) +      { +        WIN32_FIND_DATAW data; +        if ( ::FindNextFileW( handle, &data ) == 0 ) // fails +        { +          int error = ::GetLastError(); +          dir_itr_close( handle ); +          return error_code( error == ERROR_NO_MORE_FILES ? 0 : error, system_category ); +        } +        target = data.cFileName; +        if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) +          { sf.type( directory_file ); symlink_sf.type( directory_file ); } +        else { sf.type( regular_file ); symlink_sf.type( regular_file ); } +        return ok; +      } + +#     endif // ifndef BOOST_FILESYSTEM_NARROW_ONLY + +      // suggested by Walter Landry +      BOOST_FILESYSTEM_DECL bool symbolic_link_exists_api( const std::string & ) +        { return false; } + +      BOOST_FILESYSTEM_DECL +      fs::detail::query_pair is_empty_api( const std::string & ph ) +        { return is_empty_template( ph ); } + +      BOOST_FILESYSTEM_DECL +      fs::detail::query_pair +      equivalent_api( const std::string & ph1, const std::string & ph2 ) +        { return equivalent_template( ph1, ph2 ); } + +      BOOST_FILESYSTEM_DECL +      fs::detail::uintmax_pair file_size_api( const std::string & ph ) +        { return file_size_template( ph ); } + +      BOOST_FILESYSTEM_DECL +      fs::detail::space_pair space_api( const std::string & ph ) +        { return space_template( ph ); } + +      BOOST_FILESYSTEM_DECL +      error_code  +      get_current_path_api( std::string & ph ) +        { return get_current_path_template( ph ); } + +      BOOST_FILESYSTEM_DECL +      error_code  +      set_current_path_api( const std::string & ph ) +        { return set_current_path_template( ph ); } + +      BOOST_FILESYSTEM_DECL error_code +        get_full_path_name_api( const std::string & ph, std::string & target ) +         { return get_full_path_name_template( ph, target ); } + +      BOOST_FILESYSTEM_DECL time_pair +        last_write_time_api( const std::string & ph ) +          { return last_write_time_template( ph ); } +  +      BOOST_FILESYSTEM_DECL error_code +        last_write_time_api( const std::string & ph, std::time_t new_value ) +          { return last_write_time_template( ph, new_value ); } + +      BOOST_FILESYSTEM_DECL fs::detail::query_pair +      create_directory_api( const std::string & ph ) +        { return create_directory_template( ph ); } + +#if _WIN32_WINNT >= 0x500 +      BOOST_FILESYSTEM_DECL error_code +      create_hard_link_api( const std::string & to_ph, +        const std::string & from_ph ) +      {  +        return create_hard_link_template( to_ph, from_ph ); +      } +#endif + +      BOOST_FILESYSTEM_DECL error_code +      create_symlink_api( const std::string & /*to_ph*/, +        const std::string & /*from_ph*/ ) +        { return error_code( ERROR_NOT_SUPPORTED, system_category ); } + +      BOOST_FILESYSTEM_DECL error_code +      remove_api( const std::string & ph ) { return remove_template( ph ); } + +      BOOST_FILESYSTEM_DECL error_code +      rename_api( const std::string & from, const std::string & to ) +      { +        return error_code( ::MoveFileA( from.c_str(), to.c_str() ) +          ? 0 : ::GetLastError(), system_category ); +      } + +      BOOST_FILESYSTEM_DECL error_code +      copy_file_api( const std::string & from, const std::string & to ) +      { +        return error_code( ::CopyFileA( from.c_str(), to.c_str(), /*fail_if_exists=*/true ) +          ? 0 : ::GetLastError(), system_category ); +      } + +      BOOST_FILESYSTEM_DECL error_code +      dir_itr_first( void *& handle, const std::string & dir, +        std::string & target, file_status & sf, file_status & symlink_sf ) +      // Note: an empty root directory has no "." or ".." entries, so this +      // causes a ERROR_FILE_NOT_FOUND error which we do not considered an +      // error. It is treated as eof instead. +      { +        // use a form of search Sebastian Martel reports will work with Win98 +        std::string dirpath( dir ); +        dirpath += (dirpath.empty() +          || (dirpath[dirpath.size()-1] != '\\' +            && dirpath[dirpath.size()-1] != ':')) ? "\\*" : "*"; + +        WIN32_FIND_DATAA data; +        if ( (handle = ::FindFirstFileA( dirpath.c_str(), &data )) +          == INVALID_HANDLE_VALUE ) +        {  +          handle = 0; +          return error_code( ::GetLastError() == ERROR_FILE_NOT_FOUND +            ? 0 : ::GetLastError(), system_category ); +        } +        target = data.cFileName; +        if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) +          { sf.type( directory_file ); symlink_sf.type( directory_file ); } +        else { sf.type( regular_file ); symlink_sf.type( regular_file ); } +        return ok; +      } + +      BOOST_FILESYSTEM_DECL error_code +      dir_itr_close( void *& handle ) +      { +        if ( handle != 0 ) +        { +          bool ok = ::FindClose( handle ) != 0; +          handle = 0; +          return error_code( ok ? 0 : ::GetLastError(), system_category ); +        } +        return ok; +      } + +      BOOST_FILESYSTEM_DECL error_code +      dir_itr_increment( void *& handle, std::string & target, +        file_status & sf, file_status & symlink_sf ) +      { +        WIN32_FIND_DATAA data; +        if ( ::FindNextFileA( handle, &data ) == 0 ) // fails +        { +          int error = ::GetLastError(); +          dir_itr_close( handle ); +          return error_code( error == ERROR_NO_MORE_FILES ? 0 : error, system_category ); +        } +        target = data.cFileName; +        if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) +          { sf.type( directory_file ); symlink_sf.type( directory_file ); } +        else { sf.type( regular_file ); symlink_sf.type( regular_file ); } +        return ok; +      } + +#   else // BOOST_POSIX_API + +      BOOST_FILESYSTEM_DECL fs::file_status +      status_api( const std::string & ph, error_code & ec ) +      { +        struct stat path_stat; +        if ( ::stat( ph.c_str(), &path_stat ) != 0 ) +        { +          if ( errno == ENOENT || errno == ENOTDIR ) +          { +            ec = ok; +            return fs::file_status( fs::file_not_found ); +          } +          ec = error_code( errno, system_category ); +          return fs::file_status( fs::status_unknown ); +        } +        ec = ok; +        if ( S_ISDIR( path_stat.st_mode ) ) +          return fs::file_status( fs::directory_file ); +        if ( S_ISREG( path_stat.st_mode ) ) +          return fs::file_status( fs::regular_file ); +        if ( S_ISBLK( path_stat.st_mode ) ) +          return fs::file_status( fs::block_file ); +        if ( S_ISCHR( path_stat.st_mode ) ) +          return fs::file_status( fs::character_file ); +        if ( S_ISFIFO( path_stat.st_mode ) ) +          return fs::file_status( fs::fifo_file ); +        if ( S_ISSOCK( path_stat.st_mode ) ) +          return fs::file_status( fs::socket_file ); +        return fs::file_status( fs::type_unknown ); +      } + +      BOOST_FILESYSTEM_DECL fs::file_status +      symlink_status_api( const std::string & ph, error_code & ec ) +      { +        struct stat path_stat; +        if ( ::lstat( ph.c_str(), &path_stat ) != 0 ) +        { +          if ( errno == ENOENT || errno == ENOTDIR ) +          { +            ec = ok; +            return fs::file_status( fs::file_not_found ); +          } +          ec = error_code( errno, system_category ); +          return fs::file_status( fs::status_unknown ); +        } +        ec = ok; +        if ( S_ISREG( path_stat.st_mode ) ) +          return fs::file_status( fs::regular_file ); +        if ( S_ISDIR( path_stat.st_mode ) ) +          return fs::file_status( fs::directory_file ); +        if ( S_ISLNK( path_stat.st_mode ) ) +          return fs::file_status( fs::symlink_file ); +        if ( S_ISBLK( path_stat.st_mode ) ) +          return fs::file_status( fs::block_file ); +        if ( S_ISCHR( path_stat.st_mode ) ) +          return fs::file_status( fs::character_file ); +        if ( S_ISFIFO( path_stat.st_mode ) ) +          return fs::file_status( fs::fifo_file ); +        if ( S_ISSOCK( path_stat.st_mode ) ) +          return fs::file_status( fs::socket_file ); +        return fs::file_status( fs::type_unknown ); +      } + +      // suggested by Walter Landry +      BOOST_FILESYSTEM_DECL bool +      symbolic_link_exists_api( const std::string & ph ) +      { +        struct stat path_stat; +        return ::lstat( ph.c_str(), &path_stat ) == 0 +          && S_ISLNK( path_stat.st_mode ); +      } + +      BOOST_FILESYSTEM_DECL query_pair +      is_empty_api( const std::string & ph ) +      { +        struct stat path_stat; +        if ( (::stat( ph.c_str(), &path_stat )) != 0 ) +          return std::make_pair( error_code( errno, system_category ), false );         +        return std::make_pair( ok, S_ISDIR( path_stat.st_mode ) +          ? is_empty_directory( ph ) +          : path_stat.st_size == 0 ); +      } + +      BOOST_FILESYSTEM_DECL query_pair +      equivalent_api( const std::string & ph1, const std::string & ph2 ) +      { +        struct stat s2; +        int e2( ::stat( ph2.c_str(), &s2 ) ); +        struct stat s1; +        int e1( ::stat( ph1.c_str(), &s1 ) ); +        if ( e1 != 0 || e2 != 0 ) +          return std::make_pair( error_code( e1 != 0 && e2 != 0 ? errno : 0, system_category ), false ); +        // at this point, both stats are known to be valid +        return std::make_pair( ok, +            s1.st_dev == s2.st_dev +            && s1.st_ino == s2.st_ino +            // According to the POSIX stat specs, "The st_ino and st_dev fields +            // taken together uniquely identify the file within the system." +            // Just to be sure, size and mod time are also checked. +            && s1.st_size == s2.st_size +            && s1.st_mtime == s2.st_mtime ); +      } +  +      BOOST_FILESYSTEM_DECL uintmax_pair +      file_size_api( const std::string & ph ) +      { +        struct stat path_stat; +        if ( ::stat( ph.c_str(), &path_stat ) != 0 ) +          return std::make_pair( error_code( errno, system_category ), 0 ); +        if ( !S_ISREG( path_stat.st_mode ) ) +          return std::make_pair( error_code( EPERM, system_category ), 0 );  +        return std::make_pair( ok, +          static_cast<boost::uintmax_t>(path_stat.st_size) ); +      } + +      BOOST_FILESYSTEM_DECL space_pair +      space_api( const std::string & ph ) +      { +        struct BOOST_STATVFS vfs; +        space_pair result; +        if ( ::BOOST_STATVFS( ph.c_str(), &vfs ) != 0 ) +        { +          result.first = error_code( errno, system_category ); +          result.second.capacity = result.second.free +            = result.second.available = 0; +        } +        else +        { +          result.first = ok; +          result.second.capacity  +            = static_cast<boost::uintmax_t>(vfs.f_blocks) * BOOST_STATVFS_F_FRSIZE; +          result.second.free  +            = static_cast<boost::uintmax_t>(vfs.f_bfree) * BOOST_STATVFS_F_FRSIZE; +          result.second.available +            = static_cast<boost::uintmax_t>(vfs.f_bavail) * BOOST_STATVFS_F_FRSIZE; +        } +        return result; +      } + +      BOOST_FILESYSTEM_DECL time_pair  +      last_write_time_api( const std::string & ph ) +      { +        struct stat path_stat; +        if ( ::stat( ph.c_str(), &path_stat ) != 0 ) +          return std::make_pair( error_code( errno, system_category ), 0 ); +        return std::make_pair( ok, path_stat.st_mtime ); +      } + +      BOOST_FILESYSTEM_DECL error_code +      last_write_time_api( const std::string & ph, std::time_t new_value ) +      { +        struct stat path_stat; +        if ( ::stat( ph.c_str(), &path_stat ) != 0 ) +          return error_code( errno, system_category ); +        ::utimbuf buf; +        buf.actime = path_stat.st_atime; // utime() updates access time too:-( +        buf.modtime = new_value; +        return error_code( ::utime( ph.c_str(), &buf ) != 0 ? errno : 0, system_category ); +      } + +      BOOST_FILESYSTEM_DECL error_code  +      get_current_path_api( std::string & ph ) +      { +        for ( long path_max = 32;; path_max *=2 ) // loop 'til buffer large enough +        { +          boost::scoped_array<char> +            buf( new char[static_cast<std::size_t>(path_max)] ); +          if ( ::getcwd( buf.get(), static_cast<std::size_t>(path_max) ) == 0 ) +          { +            if ( errno != ERANGE +          // bug in some versions of the Metrowerks C lib on the Mac: wrong errno set  +#         if defined(__MSL__) && (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) +              && errno != 0 +#         endif +              ) return error_code( errno, system_category ); +          } +          else +          { +            ph = buf.get(); +            break; +          } +        } +        return ok; +      } + +      BOOST_FILESYSTEM_DECL error_code +      set_current_path_api( const std::string & ph ) +      { +        return error_code( ::chdir( ph.c_str() ) +          ? errno : 0, system_category ); +      } + +      BOOST_FILESYSTEM_DECL fs::detail::query_pair +      create_directory_api( const std::string & ph ) +      { +        if ( ::mkdir( ph.c_str(), S_IRWXU|S_IRWXG|S_IRWXO ) == 0 ) +          { return std::make_pair( ok, true ); } +        int ec=errno; +        error_code dummy; +        if ( ec != EEXIST  +          || !fs::is_directory( status_api( ph, dummy ) ) ) +          { return std::make_pair( error_code( ec, system_category ), false ); } +        return std::make_pair( ok, false ); +      } + +      BOOST_FILESYSTEM_DECL error_code +      create_hard_link_api( const std::string & to_ph, +          const std::string & from_ph ) +      { +        return error_code( ::link( to_ph.c_str(), from_ph.c_str() ) == 0 +          ? 0 : errno, system_category ); +      } + +      BOOST_FILESYSTEM_DECL error_code +      create_symlink_api( const std::string & to_ph, +          const std::string & from_ph ) +      { +        return error_code( ::symlink( to_ph.c_str(), from_ph.c_str() ) == 0 +          ? 0 : errno, system_category );  +      } + +      BOOST_FILESYSTEM_DECL error_code +      remove_api( const std::string & ph ) +      { +        if ( posix_remove( ph.c_str() ) == 0 ) +          return ok; +        int error = errno; +        // POSIX says "If the directory is not an empty directory, rmdir() +        // shall fail and set errno to EEXIST or ENOTEMPTY." +        // Linux uses ENOTEMPTY, Solaris uses EEXIST. +        if ( error == EEXIST ) error = ENOTEMPTY; + +        error_code ec; + +        // ignore errors if post-condition satisfied +        return status_api(ph, ec).type() == file_not_found +          ? ok : error_code( error, system_category ) ; +      } + +      BOOST_FILESYSTEM_DECL error_code +      rename_api( const std::string & from, const std::string & to ) +      { +        // POSIX is too permissive so must check +        error_code dummy; +        if ( fs::exists( status_api( to, dummy ) ) )  +          return error_code( EEXIST, system_category ); +        return error_code( std::rename( from.c_str(), to.c_str() ) != 0  +          ? errno : 0, system_category ); +      } + +      BOOST_FILESYSTEM_DECL error_code +      copy_file_api( const std::string & from_file_ph, +        const std::string & to_file_ph ) +      { +        const std::size_t buf_sz = 32768; +        boost::scoped_array<char> buf( new char [buf_sz] ); +        int infile=-1, outfile=-1;  // -1 means not open +        struct stat from_stat; + +        if ( ::stat( from_file_ph.c_str(), &from_stat ) != 0 +          || (infile = ::open( from_file_ph.c_str(), +                              O_RDONLY )) < 0 +          || (outfile = ::open( to_file_ph.c_str(), +                                O_WRONLY | O_CREAT | O_EXCL, +                                from_stat.st_mode )) < 0 ) +        { +          if ( infile >= 0 ) ::close( infile ); +          return error_code( errno, system_category ); +        } + +        ssize_t sz, sz_read=1, sz_write; +        while ( sz_read > 0 +          && (sz_read = ::read( infile, buf.get(), buf_sz )) > 0 ) +        { +          // Allow for partial writes - see Advanced Unix Programming (2nd Ed.), +          // Marc Rochkind, Addison-Wesley, 2004, page 94 +          sz_write = 0; +          do +          { +            if ( (sz = ::write( outfile, buf.get() + sz_write, +              sz_read - sz_write )) < 0 ) +            {  +              sz_read = sz; // cause read loop termination +              break;        //  and error to be thrown after closes +            } +            sz_write += sz; +          } while ( sz_write < sz_read ); +        } + +        if ( ::close( infile) < 0 ) sz_read = -1; +        if ( ::close( outfile) < 0 ) sz_read = -1; + +        return error_code( sz_read < 0 ? errno : 0, system_category ); +      } + +      // this code is based on Stevens and Rago, Advanced Programming in the +      // UNIX envirnment, 2nd Ed., ISBN 0-201-43307-9, page 49 +      error_code path_max( std::size_t & result ) +      { +#     ifdef PATH_MAX +        static std::size_t max = PATH_MAX; +#     else +        static std::size_t max = 0; +#     endif +        if ( max == 0 ) +        { +          errno = 0; +          long tmp = ::pathconf( "/", _PC_NAME_MAX ); +          if ( tmp < 0 ) +          { +            if ( errno == 0 ) // indeterminate +              max = 4096; // guess +            else return error_code( errno, system_category ); +          } +          else max = static_cast<std::size_t>( tmp + 1 ); // relative root +        } +        result = max; +        return ok; +      } + +      BOOST_FILESYSTEM_DECL error_code +      dir_itr_first( void *& handle, void *& buffer, +        const std::string & dir, std::string & target, +        file_status &, file_status & ) +      { +        if ( (handle = ::opendir( dir.c_str() )) == 0 ) +          return error_code( errno, system_category ); +        target = std::string( "." ); // string was static but caused trouble +                                     // when iteration called from dtor, after +                                     // static had already been destroyed +        std::size_t path_size; +        error_code ec = path_max( path_size ); +        if ( ec ) return ec; +        dirent de; +        buffer = std::malloc( (sizeof(dirent) - sizeof(de.d_name)) +          +  path_size + 1 ); // + 1 for "/0" +        return ok; +      }   + +      BOOST_FILESYSTEM_DECL error_code +      dir_itr_close( void *& handle, void*& buffer ) +      { +        std::free( buffer ); +        buffer = 0; +        if ( handle == 0 ) return ok; +        DIR * h( static_cast<DIR*>(handle) ); +        handle = 0; +        return error_code( ::closedir( h ) == 0 ? 0 : errno, system_category ); +      } + +      // warning: the only dirent member updated is d_name +      inline int readdir_r_simulator( DIR * dirp, struct dirent * entry, +        struct dirent ** result ) // *result set to 0 on end of directory +        { +          errno = 0; + +    #     if !defined(__CYGWIN__) \ +          && defined(_POSIX_THREAD_SAFE_FUNCTIONS) \ +          && defined(_SC_THREAD_SAFE_FUNCTIONS) \ +          && (_POSIX_THREAD_SAFE_FUNCTIONS+0 >= 0) \ +          && (!defined(__hpux) || (defined(__hpux) && defined(_REENTRANT))) +          if ( ::sysconf( _SC_THREAD_SAFE_FUNCTIONS ) >= 0 ) +            { return ::readdir_r( dirp, entry, result ); } +    #     endif + +          struct dirent * p; +          *result = 0; +          if ( (p = ::readdir( dirp )) == 0 ) +            return errno; +          std::strcpy( entry->d_name, p->d_name ); +          *result = entry; +          return 0; +        } + +      BOOST_FILESYSTEM_DECL error_code +      dir_itr_increment( void *& handle, void *& buffer, +        std::string & target, file_status & sf, file_status & symlink_sf ) +      { +        BOOST_ASSERT( buffer != 0 ); +        dirent * entry( static_cast<dirent *>(buffer) ); +        dirent * result; +        int return_code; +        if ( (return_code = readdir_r_simulator( static_cast<DIR*>(handle), +          entry, &result )) != 0 ) return error_code( errno, system_category ); +        if ( result == 0 ) return dir_itr_close( handle, buffer ); +        target = entry->d_name; +#     ifdef BOOST_FILESYSTEM_STATUS_CACHE +        if ( entry->d_type == DT_UNKNOWN )  // filesystem does not supply d_type value +        { +          sf = symlink_sf = fs::file_status(fs::status_unknown); +        } +        else  // filesystem supplies d_type value +        { +          if ( entry->d_type == DT_DIR ) +            sf = symlink_sf = fs::file_status( fs::directory_file ); +          else if ( entry->d_type == DT_REG ) +            sf = symlink_sf = fs::file_status( fs::regular_file ); +          else if ( entry->d_type == DT_LNK ) +          { +            sf = fs::file_status( fs::status_unknown ); +            symlink_sf = fs::file_status( fs::symlink_file ); +          } +          else sf = symlink_sf = fs::file_status( fs::status_unknown ); +        } +#     else +        sf = symlink_sf = fs::file_status( fs::status_unknown ); +#     endif +        return ok; +      } + +#   endif +    } // namespace detail +  } // namespace filesystem +} // namespace boost | 
 Swift
 Swift