summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemko Tronçon <git@el-tramo.be>2009-06-01 08:48:42 (GMT)
committerRemko Tronçon <git@el-tramo.be>2009-06-01 09:24:28 (GMT)
commit2812bddd81f8a1b804c7460f4e14cd0aa393d129 (patch)
treed46294f35150c4f0f43deaf2d31fceaf945ae715 /3rdParty/Boost/libs/filesystem/src/operations.cpp
downloadswift-2812bddd81f8a1b804c7460f4e14cd0aa393d129.zip
swift-2812bddd81f8a1b804c7460f4e14cd0aa393d129.tar.bz2
Import.
Diffstat (limited to '3rdParty/Boost/libs/filesystem/src/operations.cpp')
-rw-r--r--3rdParty/Boost/libs/filesystem/src/operations.cpp1367
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