diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index 08da764..a8610d8 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -21,8 +21,8 @@ lib boost_filesystem $(SOURCES).cpp ../../system/build//boost_system : - shared:BOOST_FILESYSTEM_DYN_LINK=1 # tell source we're building dll's - static:BOOST_FILESYSTEM_STATIC_LINK=1 # tell source we're building static lib's + shared:BOOST_ALL_DYN_LINK=1 # tell source we're building dll's + static:BOOST_All_STATIC_LINK=1 # tell source we're building static lib's ; install dist-lib diff --git a/include/boost/filesystem/cerrno.hpp b/include/boost/filesystem/cerrno.hpp deleted file mode 100644 index 9f5391a..0000000 --- a/include/boost/filesystem/cerrno.hpp +++ /dev/null @@ -1,23 +0,0 @@ -// Boost Filesystem cerrno.hpp header --------------------------------------// - -// Copyright Beman Dawes 2005. -// 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 - -#ifndef BOOST_FILESYSTEM_CERRNO_HPP -#define BOOST_FILESYSTEM_CERRNO_HPP - -#include - -#if defined __BORLANDC__ -#define ENOSYS 9997 -#endif - -#define EBADHANDLE 9998 // bad handle -#define EOTHER 9999 // Other error not translatable - // to a POSIX errno value - -#endif // include guard diff --git a/include/boost/filesystem/convenience.hpp b/include/boost/filesystem/convenience.hpp index affa38a..66708c5 100644 --- a/include/boost/filesystem/convenience.hpp +++ b/include/boost/filesystem/convenience.hpp @@ -1,7 +1,7 @@ // boost/filesystem/convenience.hpp ----------------------------------------// -// © Copyright Beman Dawes, 2002-2005 -// © Copyright Vladimir Prus, 2002 +// Copyright Beman Dawes, 2002-2005 +// Copyright Vladimir Prus, 2002 // 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) @@ -14,7 +14,7 @@ #define BOOST_FILESYSTEM_CONVENIENCE_HPP #include -#include +#include #include #include @@ -45,7 +45,8 @@ namespace boost if ( !ph.empty() && !is_directory(ph) ) boost::throw_exception( basic_filesystem_error( "boost::filesystem::create_directories", ph, - boost::system::error_code(EEXIST, boost::system::errno_ecat) ) ); + boost::system::make_error_code( + boost::system::posix::file_exists ) ) ); return false; } @@ -188,6 +189,7 @@ namespace boost bool equal( const basic_recursive_directory_iterator & rhs ) const { return m_imp == rhs.m_imp; } + }; typedef basic_recursive_directory_iterator recursive_directory_iterator; @@ -204,6 +206,8 @@ namespace boost : m_imp( new detail::recur_dir_itr_imp ) { m_imp->m_stack.push( basic_directory_iterator( dir_path ) ); + if ( m_imp->m_stack.top () == basic_directory_iterator() ) + { m_imp.reset (); } } template @@ -212,8 +216,10 @@ namespace boost system::error_code & ec ) : m_imp( new detail::recur_dir_itr_imp ) { - m_imp->m_stack.push( basic_directory_iterator( dir_path, std::nothrow ) ); m_imp->m_no_throw = true; + m_imp->m_stack.push( basic_directory_iterator( dir_path, ec ) ); + if ( m_imp->m_stack.top () == basic_directory_iterator() ) + { m_imp.reset (); } } // increment @@ -224,15 +230,15 @@ namespace boost static const basic_directory_iterator end_itr; - if ( m_imp->m_no_push ) m_imp->m_no_push = false; + if ( m_imp->m_no_push ) + { m_imp->m_no_push = false; } else if ( is_directory( m_imp->m_stack.top()->status() ) ) { system::error_code ec; m_imp->m_stack.push( m_imp->m_no_throw ? basic_directory_iterator( *m_imp->m_stack.top(), ec ) - : basic_directory_iterator( *m_imp->m_stack.top() ) - ); + : basic_directory_iterator( *m_imp->m_stack.top() ) ); if ( m_imp->m_stack.top() != end_itr ) { ++m_imp->m_level; @@ -258,8 +264,17 @@ namespace boost BOOST_ASSERT( m_imp.get() && "pop on end iterator" ); BOOST_ASSERT( m_imp->m_level > 0 && "pop with level < 1" ); - m_imp->m_stack.pop(); - --m_imp->m_level; + static const basic_directory_iterator end_itr; + + do + { + m_imp->m_stack.pop(); + --m_imp->m_level; + } + while ( !m_imp->m_stack.empty() + && ++m_imp->m_stack.top() == end_itr ); + + if ( m_imp->m_stack.empty() ) m_imp.reset(); // done, so make end iterator } } // namespace filesystem diff --git a/include/boost/filesystem/operations.hpp b/include/boost/filesystem/operations.hpp index fe393c3..682c276 100644 --- a/include/boost/filesystem/operations.hpp +++ b/include/boost/filesystem/operations.hpp @@ -160,6 +160,8 @@ namespace boost last_write_time_api( const std::string & ph, std::time_t new_value ); BOOST_FILESYSTEM_DECL system::error_code get_current_path_api( std::string & ph ); + BOOST_FILESYSTEM_DECL system::error_code + set_current_path_api( const std::string & ph ); BOOST_FILESYSTEM_DECL query_pair create_directory_api( const std::string & ph ); BOOST_FILESYSTEM_DECL system::error_code @@ -200,6 +202,8 @@ namespace boost last_write_time_api( const std::wstring & ph, std::time_t new_value ); BOOST_FILESYSTEM_DECL system::error_code get_current_path_api( std::wstring & ph ); + BOOST_FILESYSTEM_DECL system::error_code + set_current_path_api( const std::wstring & ph ); BOOST_FILESYSTEM_DECL query_pair create_directory_api( const std::wstring & ph ); # ifdef BOOST_FS_HARD_LINK @@ -505,6 +509,15 @@ namespace boost return Path( Path::traits_type::to_internal( ph ) ); } + template< class Path > + void current_path( const Path & ph ) + { + system::error_code ec( detail::set_current_path_api( ph.string() ) ); + if ( ec ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::current_path", ph, ec ) ); + } + template< class Path > const Path & initial_path() { @@ -991,7 +1004,7 @@ namespace boost m_symlink_status = symlink_st; } - const Path & path() const { return m_path; } + const Path & path() const { return m_path; } file_status status() const; file_status status( system::error_code & ec ) const; file_status symlink_status() const; diff --git a/include/boost/filesystem/path.hpp b/include/boost/filesystem/path.hpp index 5a74828..cbf1a9a 100644 --- a/include/boost/filesystem/path.hpp +++ b/include/boost/filesystem/path.hpp @@ -1,6 +1,6 @@ // boost/filesystem/path.hpp -----------------------------------------------// -// Copyright Beman Dawes 2002-2005 +// Copyright Beman Dawes 2002-2005 // Distributed under 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) @@ -566,6 +566,53 @@ namespace boost } # endif + // basic_filesystem_error helpers --------------------------------------// + + // Originally choice of implementation was done via specialization of + // basic_filesystem_error::what(). Several compilers (GCC, aCC, etc.) + // couldn't handle that, so the choice is now accomplished by overloading. + + namespace detail + { + // BOOST_FILESYSTEM_DECL version works for VC++ but not GCC. Go figure! + inline + const char * what( const char * sys_err_what, + const path & path1, const path & path2, std::string & target ) + { + try + { + if ( target.empty() ) + { + target = sys_err_what; + if ( !path1.empty() ) + { + target += ": \""; + target += path1.file_string(); + target += "\""; + } + if ( !path2.empty() ) + { + target += ", \""; + target += path2.file_string(); + target += "\""; + } + } + return target.c_str(); + } + catch (...) + { + return sys_err_what; + } + } + + template + const char * what( const char * sys_err_what, + const Path & path1, const Path & path2, std::string & target ) + { + return sys_err_what; + } + } + // basic_filesystem_error ----------------------------------------------// template @@ -599,7 +646,13 @@ namespace boost return m_imp_ptr.get() ? m_imp_ptr->m_path2 : empty_path ; } - const char * what() const throw() { return system_error::what(); } + const char * what() const throw() + { + if ( !m_imp_ptr.get() ) + return system_error::what(); + return detail::what( system_error::what(), m_imp_ptr->m_path1, + m_imp_ptr->m_path2, m_imp_ptr->m_what ); + } private: struct m_imp @@ -611,33 +664,6 @@ namespace boost boost::shared_ptr m_imp_ptr; }; -// This specialization is causing problems with GCC, aCC (HP-UX) -// and cxx on Alpha platforms. -#if !(defined(__GNUC__) || defined(__HP_aCC) || \ - (defined(__DECCXX) && defined(__alpha))) - template<> const char * basic_filesystem_error::what() const throw() - { - if ( !m_imp_ptr.get() ) return system_error::what(); - if ( m_imp_ptr->m_what.empty() ) - { - m_imp_ptr->m_what = system_error::what(); - if ( !path1().empty() ) - { - m_imp_ptr->m_what += ": \""; - m_imp_ptr->m_what += path1().file_string(); - m_imp_ptr->m_what += "\""; - } - if ( !path2().empty() ) - { - m_imp_ptr->m_what += ", \""; - m_imp_ptr->m_what += path2().file_string(); - m_imp_ptr->m_what += "\""; - } - } - return m_imp_ptr->m_what.c_str(); - } -#endif - typedef basic_filesystem_error filesystem_error; # ifndef BOOST_FILESYSTEM_NARROW_ONLY diff --git a/src/operations.cpp b/src/operations.cpp index 14c830f..8af89f6 100644 --- a/src/operations.cpp +++ b/src/operations.cpp @@ -16,7 +16,10 @@ #define _POSIX_PTHREAD_SEMANTICS // Sun readdir_r() needs this +#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. @@ -42,35 +45,38 @@ namespace fs = boost::filesystem; using boost::system::error_code; -using boost::system::errno_ecat; -using boost::system::native_ecat; +using boost::system::system_category; # if defined(BOOST_WINDOWS_API) -# include "windows.h" +# include # if defined(__BORLANDC__) || defined(__MWERKS__) # if defined(__BORLANDC__) using std::time_t; # endif -# include "utime.h" +# include # else -# include "sys/utime.h" +# include # endif # else // BOOST_POSIX_API # include -# ifndef __APPLE__ +# if !defined(__APPLE__) && !defined(__OpenBSD__) # include # define BOOST_STATVFS statvfs # define BOOST_STATVFS_F_FRSIZE vfs.f_frsize # else +#ifdef __OpenBSD__ +# include +#endif # include # define BOOST_STATVFS statfs # define BOOST_STATVFS_F_FRSIZE static_cast( vfs.f_bsize ) # endif -# include "dirent.h" -# include "unistd.h" -# include "fcntl.h" -# include "utime.h" +# include +# include +# include +# include +# include "limits.h" # endif // BOOST_FILESYSTEM_STATUS_CACHE enables file_status cache in @@ -99,7 +105,7 @@ namespace std { using ::strcmp; using ::remove; using ::rename; } namespace { - static const fs::directory_iterator end_itr; + const fs::directory_iterator end_itr; bool is_empty_directory( const std::string & dir_path ) { return fs::directory_iterator(fs::path(dir_path)) == end_itr; @@ -120,7 +126,7 @@ namespace inline DWORD get_file_attributes( const wchar_t * ph ) { return ::GetFileAttributesW( ph ); } - static const fs::wdirectory_iterator wend_itr; + const fs::wdirectory_iterator wend_itr; bool is_empty_directory( const std::wstring & dir_path ) { return fs::wdirectory_iterator(fs::wpath(dir_path)) == wend_itr; @@ -143,6 +149,9 @@ namespace 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; } @@ -178,7 +187,7 @@ namespace DWORD attr( get_file_attributes( ph.c_str() ) ); if ( attr == 0xFFFFFFFF ) { - ec = error_code( ::GetLastError(), native_ecat ); + 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" @@ -206,7 +215,7 @@ namespace { WIN32_FILE_ATTRIBUTE_DATA fad; if ( get_file_attributes_ex( ph.c_str(), fad ) == 0 ) - return std::make_pair( error_code( ::GetLastError(), native_ecat ), false ); + return std::make_pair( error_code( ::GetLastError(), system_category ), false ); return std::make_pair( error_code(), ( fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) ? is_empty_directory( ph ) @@ -276,14 +285,14 @@ namespace { return std::make_pair( error_code(), false ); } assert( p1.handle == INVALID_HANDLE_VALUE && p2.handle == INVALID_HANDLE_VALUE ); - { return std::make_pair( error_code( error1, errno_ecat), false ); } + { 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(), native_ecat ), false ); } + { return std::make_pair( error_code( ::GetLastError(), system_category ), false ); } if ( !::GetFileInformationByHandle( p2.handle, &info2 ) ) - { return std::make_pair( error_code( ::GetLastError(), native_ecat ), false ); } + { 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. @@ -306,9 +315,9 @@ namespace 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(), native_ecat ), 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, native_ecat), 0 ); + return std::make_pair( error_code( ERROR_FILE_NOT_FOUND, system_category), 0 ); return std::make_pair( error_code(), (static_cast(fad.nFileSizeHigh) << (sizeof(fad.nFileSizeLow)*8)) @@ -340,7 +349,7 @@ namespace } else { - result.first = error_code( ::GetLastError(), native_ecat ); + result.first = error_code( ::GetLastError(), system_category ); result.second.capacity = result.second.free = result.second.available = 0; } @@ -361,11 +370,22 @@ namespace typedef typename String::value_type value_type; boost::scoped_array buf( new value_type[sz] ); if ( get_current_directory( sz, buf.get() ) == 0 ) - return error_code( ::GetLastError(), native_ecat ); + return error_code( ::GetLastError(), system_category ); ph = buf.get(); return error_code(); } + 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 ) { @@ -384,13 +404,13 @@ namespace 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(), native_ecat ); + if ( len == 0 ) return error_code( ::GetLastError(), system_category ); if ( len > buf_size ) { typedef typename String::value_type value_type; boost::scoped_array big_buf( new value_type[len] ); if ( (len=get_full_path_name( ph, len , big_buf.get(), &pfn )) - == 0 ) return error_code( ::GetLastError(), native_ecat ); + == 0 ) return error_code( ::GetLastError(), system_category ); big_buf[len] = '\0'; target = big_buf.get(); return error_code(); @@ -409,9 +429,9 @@ namespace 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(), native_ecat ); + return error_code( ::GetLastError(), system_category ); return error_code( ::GetFileTime( hw.handle, 0, 0, &last_write_time ) != 0 - ? 0 : ::GetLastError(), native_ecat ); + ? 0 : ::GetLastError(), system_category ); } template @@ -423,9 +443,9 @@ namespace 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(), native_ecat ); + return error_code( ::GetLastError(), system_category ); return error_code( ::SetFileTime( hw.handle, 0, 0, &last_write_time ) != 0 - ? 0 : ::GetLastError(), native_ecat ); + ? 0 : ::GetLastError(), system_category ); } // these constants come from inspecting some Microsoft sample code @@ -490,11 +510,11 @@ namespace if ( fs::is_directory( sf ) ) { if ( !remove_directory( ph ) ) - return error_code(::GetLastError(), native_ecat); + return error_code(::GetLastError(), system_category); } else { - if ( !delete_file( ph ) ) return error_code(::GetLastError(), native_ecat); + if ( !delete_file( ph ) ) return error_code(::GetLastError(), system_category); } return error_code(); } @@ -508,7 +528,7 @@ namespace { error_code error, dummy; if ( create_directory( dir_ph ) ) return std::make_pair( error, true ); - error = error_code( ::GetLastError(), native_ecat ); + 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 ) ) ) @@ -529,7 +549,7 @@ namespace const String & from_ph ) { return error_code( create_hard_link( to_ph.c_str(), from_ph.c_str() ) - ? 0 : ::GetLastError(), native_ecat ); + ? 0 : ::GetLastError(), system_category ); } #endif @@ -548,9 +568,9 @@ namespace boost BOOST_FILESYSTEM_DECL error_code not_found_error() { # ifdef BOOST_WINDOWS_API - return error_code(ERROR_PATH_NOT_FOUND, native_ecat); + return error_code(ERROR_PATH_NOT_FOUND, system_category); # else - return error_code(ENOENT, errno_ecat); + return error_code(ENOENT, system_category); # endif } @@ -601,6 +621,11 @@ namespace boost 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 ); } @@ -627,7 +652,7 @@ namespace boost BOOST_FILESYSTEM_DECL error_code create_symlink_api( const std::wstring & to_ph, const std::wstring & from_ph ) - { return error_code( ERROR_NOT_SUPPORTED, native_ecat ); } + { return error_code( ERROR_NOT_SUPPORTED, system_category ); } BOOST_FILESYSTEM_DECL error_code remove_api( const std::wstring & ph ) { return remove_template( ph ); } @@ -636,14 +661,14 @@ namespace boost rename_api( const std::wstring & from, const std::wstring & to ) { return error_code( ::MoveFileW( from.c_str(), to.c_str() ) - ? 0 : ::GetLastError(), native_ecat ); + ? 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(), native_ecat ); + ? 0 : ::GetLastError(), system_category ); } BOOST_FILESYSTEM_DECL bool create_file_api( const std::wstring & ph, @@ -719,7 +744,7 @@ namespace boost { handle = 0; return error_code( ::GetLastError() == ERROR_FILE_NOT_FOUND - ? 0 : ::GetLastError(), native_ecat ); + ? 0 : ::GetLastError(), system_category ); } target = data.cFileName; if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) @@ -737,7 +762,7 @@ namespace boost { int error = ::GetLastError(); dir_itr_close( handle ); - return error_code( error == ERROR_NO_MORE_FILES ? 0 : error, native_ecat ); + return error_code( error == ERROR_NO_MORE_FILES ? 0 : error, system_category ); } target = data.cFileName; if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) @@ -774,6 +799,11 @@ namespace boost 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 ); } @@ -802,7 +832,7 @@ namespace boost BOOST_FILESYSTEM_DECL error_code create_symlink_api( const std::string & to_ph, const std::string & from_ph ) - { return error_code( ERROR_NOT_SUPPORTED, native_ecat ); } + { return error_code( ERROR_NOT_SUPPORTED, system_category ); } BOOST_FILESYSTEM_DECL error_code remove_api( const std::string & ph ) { return remove_template( ph ); } @@ -811,14 +841,14 @@ namespace boost rename_api( const std::string & from, const std::string & to ) { return error_code( ::MoveFileA( from.c_str(), to.c_str() ) - ? 0 : ::GetLastError(), native_ecat ); + ? 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(), native_ecat ); + ? 0 : ::GetLastError(), system_category ); } BOOST_FILESYSTEM_DECL error_code @@ -840,7 +870,7 @@ namespace boost { handle = 0; return error_code( ::GetLastError() == ERROR_FILE_NOT_FOUND - ? 0 : ::GetLastError(), native_ecat ); + ? 0 : ::GetLastError(), system_category ); } target = data.cFileName; if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) @@ -856,7 +886,7 @@ namespace boost { bool ok = ::FindClose( handle ) != 0; handle = 0; - return error_code( ok ? 0 : ::GetLastError(), native_ecat ); + return error_code( ok ? 0 : ::GetLastError(), system_category ); } return error_code(); } @@ -870,7 +900,7 @@ namespace boost { int error = ::GetLastError(); dir_itr_close( handle ); - return error_code( error == ERROR_NO_MORE_FILES ? 0 : error, native_ecat ); + return error_code( error == ERROR_NO_MORE_FILES ? 0 : error, system_category ); } target = data.cFileName; if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) @@ -892,7 +922,7 @@ namespace boost ec = error_code(); return fs::file_status( fs::file_not_found ); } - ec = error_code( errno, errno_ecat ); + ec = error_code( errno, system_category ); return fs::file_status( fs::status_unknown ); } ec = error_code(); @@ -922,7 +952,7 @@ namespace boost ec = error_code(); return fs::file_status( fs::file_not_found ); } - ec = error_code( errno, errno_ecat ); + ec = error_code( errno, system_category ); return fs::file_status( fs::status_unknown ); } ec = error_code(); @@ -957,7 +987,7 @@ namespace boost { struct stat path_stat; if ( (::stat( ph.c_str(), &path_stat )) != 0 ) - return std::make_pair( error_code( errno, errno_ecat ), false ); + return std::make_pair( error_code( errno, system_category ), false ); return std::make_pair( error_code(), S_ISDIR( path_stat.st_mode ) ? is_empty_directory( ph ) : path_stat.st_size == 0 ); @@ -971,7 +1001,7 @@ namespace boost 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, errno_ecat ), false ); + 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( error_code(), s1.st_dev == s2.st_dev @@ -988,9 +1018,9 @@ namespace boost { struct stat path_stat; if ( ::stat( ph.c_str(), &path_stat ) != 0 ) - return std::make_pair( error_code( errno, errno_ecat ), 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, errno_ecat ), 0 ); + return std::make_pair( error_code( EPERM, system_category ), 0 ); return std::make_pair( error_code(), static_cast(path_stat.st_size) ); } @@ -1002,7 +1032,7 @@ namespace boost space_pair result; if ( ::BOOST_STATVFS( ph.c_str(), &vfs ) != 0 ) { - result.first = error_code( errno, errno_ecat ); + result.first = error_code( errno, system_category ); result.second.capacity = result.second.free = result.second.available = 0; } @@ -1024,7 +1054,7 @@ namespace boost { struct stat path_stat; if ( ::stat( ph.c_str(), &path_stat ) != 0 ) - return std::make_pair( error_code( errno, errno_ecat ), 0 ); + return std::make_pair( error_code( errno, system_category ), 0 ); return std::make_pair( error_code(), path_stat.st_mtime ); } @@ -1033,11 +1063,11 @@ namespace boost { struct stat path_stat; if ( ::stat( ph.c_str(), &path_stat ) != 0 ) - return error_code( errno, errno_ecat ); + 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, errno_ecat ); + return error_code( ::utime( ph.c_str(), &buf ) != 0 ? errno : 0, system_category ); } BOOST_FILESYSTEM_DECL error_code @@ -1054,7 +1084,7 @@ namespace boost # if defined(__MSL__) && (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) && errno != 0 # endif - ) return error_code( errno, errno_ecat ); + ) return error_code( errno, system_category ); } else { @@ -1065,6 +1095,13 @@ namespace boost return error_code(); } + BOOST_FILESYSTEM_DECL error_code + set_current_path_api( 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 ) { @@ -1074,7 +1111,7 @@ namespace boost error_code dummy; if ( ec != EEXIST || !fs::is_directory( status_api( ph, dummy ) ) ) - { return std::make_pair( error_code( ec, errno_ecat ), false ); } + { return std::make_pair( error_code( ec, system_category ), false ); } return std::make_pair( error_code(), false ); } @@ -1083,7 +1120,7 @@ namespace boost const std::string & from_ph ) { return error_code( ::link( to_ph.c_str(), from_ph.c_str() ) == 0 - ? 0 : errno, errno_ecat ); + ? 0 : errno, system_category ); } BOOST_FILESYSTEM_DECL error_code @@ -1091,7 +1128,7 @@ namespace boost const std::string & from_ph ) { return error_code( ::symlink( to_ph.c_str(), from_ph.c_str() ) == 0 - ? 0 : errno, errno_ecat ); + ? 0 : errno, system_category ); } BOOST_FILESYSTEM_DECL error_code @@ -1116,7 +1153,7 @@ namespace boost // shall fail and set errno to EEXIST or ENOTEMPTY." // Linux uses ENOTEMPTY, Solaris uses EEXIST. if ( error == EEXIST ) error = ENOTEMPTY; - return error_code( error, errno_ecat ); + return error_code( error, system_category ); } return error_code(); } @@ -1127,9 +1164,9 @@ namespace boost // POSIX is too permissive so must check error_code dummy; if ( fs::exists( status_api( to, dummy ) ) ) - return error_code( EEXIST, errno_ecat ); + return error_code( EEXIST, system_category ); return error_code( std::rename( from.c_str(), to.c_str() ) != 0 - ? errno : 0, errno_ecat ); + ? errno : 0, system_category ); } BOOST_FILESYSTEM_DECL error_code @@ -1149,7 +1186,7 @@ namespace boost from_stat.st_mode )) < 0 ) { if ( infile >= 0 ) ::close( infile ); - return error_code( errno, errno_ecat ); + return error_code( errno, system_category ); } ssize_t sz, sz_read=1, sz_write; @@ -1174,7 +1211,32 @@ namespace boost if ( ::close( infile) < 0 ) sz_read = -1; if ( ::close( outfile) < 0 ) sz_read = -1; - return error_code( sz_read < 0 ? errno : 0, errno_ecat ); + 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( tmp + 1 ); // relative root + } + result = max; + return error_code(); } BOOST_FILESYSTEM_DECL error_code @@ -1182,15 +1244,17 @@ namespace boost const std::string & dir, std::string & target, file_status &, file_status & ) { - static const std::string dummy_first_name( "." ); if ( (handle = ::opendir( dir.c_str() )) == 0 ) - return error_code( errno, errno_ecat ); - target = dummy_first_name; - long pc_name_max( ::pathconf( dir.c_str(), _PC_NAME_MAX ) ); - if ( pc_name_max == -1L ) return error_code( errno, errno_ecat ); + 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)) - + static_cast( pc_name_max ) + 1 ); + + path_size + 1 ); // + 1 for "/0" return error_code(); } @@ -1202,7 +1266,7 @@ namespace boost if ( handle == 0 ) return error_code(); DIR * h( static_cast(handle) ); handle = 0; - return error_code( ::closedir( h ) == 0 ? 0 : errno, errno_ecat ); + return error_code( ::closedir( h ) == 0 ? 0 : errno, system_category ); } // warning: the only dirent member updated is d_name @@ -1215,7 +1279,7 @@ namespace boost && defined(_POSIX_THREAD_SAFE_FUNCTIONS) \ && defined(_SC_THREAD_SAFE_FUNCTIONS) \ && (_POSIX_THREAD_SAFE_FUNCTIONS+0 >= 0) \ - && (!defined(__hpux) || (defined(__hpux) && defined(_REENTRANT))) + && (!defined(__HP_aCC) || (defined(__HP_aCC) && defined(_REENTRANT))) if ( ::sysconf( _SC_THREAD_SAFE_FUNCTIONS ) >= 0 ) { return ::readdir_r( dirp, entry, result ); } # endif @@ -1238,7 +1302,7 @@ namespace boost dirent * result; int return_code; if ( (return_code = readdir_r_simulator( static_cast(handle), - entry, &result )) != 0 ) return error_code( errno, errno_ecat ); + 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 diff --git a/src/path.cpp b/src/path.cpp index 9044239..b3e3b2d 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -36,10 +36,16 @@ namespace return lc; } - const std::codecvt * - converter( + const std::codecvt *& + converter() + { + static const std::codecvt * + cvtr( &std::use_facet > ( loc() ) ); + return cvtr; + } + bool locked(false); } // unnamed namespace @@ -52,7 +58,7 @@ namespace boost if ( locked ) return false; locked = true; loc() = new_loc; - converter = &std::use_facet + converter() = &std::use_facet >( loc() ); return true; } @@ -62,9 +68,42 @@ namespace boost if ( locked ) boost::throw_exception( wfilesystem_error( "boost::filesystem::wpath_traits::imbue() after lockdown", - system::error_code(EOTHER, system::errno_ecat) ) ); + system::make_error_code( system::posix::not_supported ) ) ); imbue( new_loc, std::nothrow ); } + + //namespace detail + //{ + // BOOST_FILESYSTEM_DECL + // const char * what( const char * sys_err_what, + // const path & path1, const path & path2, std::string & target) + // { + // try + // { + // if ( target.empty() ) + // { + // target = sys_err_what; + // if ( !path1.empty() ) + // { + // target += ": \""; + // target += path1.file_string(); + // target += "\""; + // } + // if ( !path2.empty() ) + // { + // target += ", \""; + // target += path2.file_string(); + // target += "\""; + // } + // } + // return target.c_str(); + // } + // catch (...) + // { + // return sys_err_what; + // } + // } + //} # ifdef BOOST_POSIX_API @@ -81,12 +120,12 @@ namespace boost std::mbstate_t state; const internal_string_type::value_type * from_next; external_string_type::value_type * to_next; - if ( converter->out( + if ( converter()->out( state, src.c_str(), src.c_str()+src.size(), from_next, work.get(), work.get()+work_size, to_next ) != std::codecvt_base::ok ) boost::throw_exception( boost::filesystem::wfilesystem_error( "boost::filesystem::wpath::to_external conversion error", - ph, system::error_code( EINVAL, system::errno_ecat ) ) ); + ph, system::posix::invalid_argument ) ); *to_next = '\0'; return external_string_type( work.get() ); } @@ -100,12 +139,12 @@ namespace boost std::mbstate_t state; const external_string_type::value_type * from_next; internal_string_type::value_type * to_next; - if ( converter->in( + if ( converter()->in( state, src.c_str(), src.c_str()+src.size(), from_next, work.get(), work.get()+work_size, to_next ) != std::codecvt_base::ok ) boost::throw_exception( boost::filesystem::wfilesystem_error( "boost::filesystem::wpath::to_internal conversion error", - system::error_code( EINVAL, system::errno_ecat ) ) ); + system::posix::invalid_argument ) ); *to_next = L'\0'; return internal_string_type( work.get() ); } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 8926e15..8f5cc57 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -16,7 +16,7 @@ project static static ] [ run path_test.cpp ../../system/build - : : : BOOST_FILESYSTEM_DYN_LINK + : : : BOOST_FILESYSTEM_DYN_LINK BOOST_SYSTEM_DYN_LINK : path_test_dll ] [ run operations_test.cpp @@ -24,7 +24,7 @@ project static static ] [ run operations_test.cpp ../../system/build - : : : BOOST_FILESYSTEM_DYN_LINK + : : : BOOST_FILESYSTEM_DYN_LINK BOOST_SYSTEM_DYN_LINK : operations_test_dll ] [ run fstream_test.cpp diff --git a/test/convenience_test.cpp b/test/convenience_test.cpp index e5821a7..fd552f8 100644 --- a/test/convenience_test.cpp +++ b/test/convenience_test.cpp @@ -18,6 +18,7 @@ #include namespace fs = boost::filesystem; using fs::path; +namespace sys = boost::system; #include #include @@ -45,7 +46,15 @@ namespace } return false; } + + void create_recursive_iterator( const fs::path & ph ) + { + fs::recursive_directory_iterator it( ph ); + } } + +// --------------------------------------------------------------------------// + int test_main( int, char*[] ) { path::default_name_check( fs::no_check ); // names below not valid on all O/S's @@ -63,13 +72,13 @@ int test_main( int, char*[] ) BOOST_CHECK( fs::exists( "xx" ) ); BOOST_CHECK( fs::is_directory( "xx" ) ); - BOOST_CHECK( fs::create_directories( "xx/ww/zz" ) ); + BOOST_CHECK( fs::create_directories( "xx/yy/zz" ) ); BOOST_CHECK( fs::exists( "xx" ) ); - BOOST_CHECK( fs::exists( "xx/ww" ) ); - BOOST_CHECK( fs::exists( "xx/ww/zz" ) ); + BOOST_CHECK( fs::exists( "xx/yy" ) ); + BOOST_CHECK( fs::exists( "xx/yy/zz" ) ); BOOST_CHECK( fs::is_directory( "xx" ) ); - BOOST_CHECK( fs::is_directory( "xx/ww" ) ); - BOOST_CHECK( fs::is_directory( "xx/ww/zz" ) ); + BOOST_CHECK( fs::is_directory( "xx/yy" ) ); + BOOST_CHECK( fs::is_directory( "xx/yy/zz" ) ); path is_a_file( "xx/uu" ); { @@ -109,5 +118,82 @@ int test_main( int, char*[] ) // see the rationale in html docs for explanation why this works BOOST_CHECK( fs::change_extension("", ".png").string() == ".png" ); +// recursive_directory_iterator tests ----------------------------------------// + + sys::error_code ec; + fs::recursive_directory_iterator it( "/no-such-path", ec ); + BOOST_CHECK( ec ); + BOOST_CHECK( throws_fs_error( + boost::bind( create_recursive_iterator, "/no-such-path" ) ) ); + + fs::remove( "xx/uu" ); + +#ifdef BOOST_WINDOWS_API + // These tests depends on ordering of directory entries, and that's guaranteed + // on Windows but not necessarily on other operating systems + { + std::ofstream f( "xx/yya" ); + BOOST_CHECK( !!f ); + } + + for ( it = fs::recursive_directory_iterator( "xx" ); + it != fs::recursive_directory_iterator(); ++it ) + { std::cout << *it << '\n'; } + + it = fs::recursive_directory_iterator( "xx" ); + BOOST_CHECK( it->path() == "xx/yy" ); + BOOST_CHECK( it.level() == 0 ); + ++it; + BOOST_CHECK( it->path() == "xx/yy/zz" ); + BOOST_CHECK( it.level() == 1 ); + it.pop(); + BOOST_CHECK( it->path() == "xx/yya" ); + BOOST_CHECK( it.level() == 0 ); + it++; + BOOST_CHECK( it == fs::recursive_directory_iterator() ); + + it = fs::recursive_directory_iterator( "xx" ); + BOOST_CHECK( it->path() == "xx/yy" ); + it.no_push(); + ++it; + BOOST_CHECK( it->path() == "xx/yya" ); + ++it; + BOOST_CHECK( it == fs::recursive_directory_iterator() ); + + fs::remove( "xx/yya" ); +#endif + + it = fs::recursive_directory_iterator( "xx/yy/zz" ); + BOOST_CHECK( it == fs::recursive_directory_iterator() ); + + it = fs::recursive_directory_iterator( "xx" ); + BOOST_CHECK( it->path() == "xx/yy" ); + BOOST_CHECK( it.level() == 0 ); + ++it; + BOOST_CHECK( it->path() == "xx/yy/zz" ); + BOOST_CHECK( it.level() == 1 ); + it++; + BOOST_CHECK( it == fs::recursive_directory_iterator() ); + + it = fs::recursive_directory_iterator( "xx" ); + BOOST_CHECK( it->path() == "xx/yy" ); + it.no_push(); + ++it; + BOOST_CHECK( it == fs::recursive_directory_iterator() ); + + it = fs::recursive_directory_iterator( "xx" ); + BOOST_CHECK( it->path() == "xx/yy" ); + ++it; + it.pop(); + BOOST_CHECK( it == fs::recursive_directory_iterator() ); + + + + // nothrow wrong. see imp. Make sure failed basic_directory_iterator + // ctor creates the end iterator. + + + + return 0; } diff --git a/test/operations_test.cpp b/test/operations_test.cpp index 2bfcc30..e50bb26 100644 --- a/test/operations_test.cpp +++ b/test/operations_test.cpp @@ -16,7 +16,7 @@ #include #include -#include +#include namespace fs = boost::filesystem; #include @@ -26,7 +26,7 @@ namespace fs = boost::filesystem; using boost::bind; using boost::system::error_code; -using boost::system::errno_ecat; +using boost::system::system_category; using boost::system::system_error; #include @@ -71,7 +71,7 @@ namespace std::ofstream f( ph.file_string().c_str() ); if ( !f ) throw fs::filesystem_error( "operations_test create_file", - ph, error_code(errno, errno_ecat) ); + ph, error_code(errno, system_category) ); if ( !contents.empty() ) f << contents; } @@ -80,7 +80,7 @@ namespace std::ifstream f( ph.file_string().c_str() ); if ( !f ) throw fs::filesystem_error( "operations_test verify_file", - ph, error_code(errno, errno_ecat) ); + ph, error_code(errno, system_category) ); std::string contents; f >> contents; if ( contents != expected ) @@ -101,10 +101,10 @@ namespace std::cout << "\n" << ex.what() << "\n"; } if ( en == 0 - || en == ex.code().to_errno() ) return true; + || en == ex.code().default_error_condition().value() ) return true; std::cout << "\nWarning: line " << line - << " exception reports iso() " << ex.code().to_errno() + << " exception reports default_error_condition().value() " << ex.code().default_error_condition().value() << ", should be " << en << "\n value() is " << ex.code().value() << std::endl; @@ -160,7 +160,7 @@ namespace if ( report_throws ) std::cout << x.what() << std::endl; if ( platform == "Windows" ) BOOST_CHECK( std::strcmp( x.what(), - "boost::filesystem::create_directory: The system cannot find the path specified." ) == 0 ); + "boost::filesystem::create_directory: The system cannot find the path specified" ) == 0 ); } BOOST_CHECK( exception_thrown ); @@ -176,8 +176,12 @@ namespace if ( platform == "Windows" ) { bool ok ( std::strcmp( x.what(), - "boost::filesystem::create_directory: The system cannot find the path specified.: \"no-such-dir\\foo\\bar\"" ) == 0 ); + "boost::filesystem::create_directory: The system cannot find the path specified: \"no-such-dir\\foo\\bar\"" ) == 0 ); BOOST_CHECK( ok ); + if ( !ok ) + { + std::cout << "what returns \"" << x.what() << "\"" << std::endl; + } } } BOOST_CHECK( exception_thrown ); @@ -194,8 +198,12 @@ namespace if ( platform == "Windows" ) { bool ok ( std::strcmp( x.what(), - "boost::filesystem::create_directory: The system cannot find the path specified.: \"no-such-dir\\foo\\bar\"" ) == 0 ); + "boost::filesystem::create_directory: The system cannot find the path specified: \"no-such-dir\\foo\\bar\"" ) == 0 ); BOOST_CHECK( ok ); + if ( !ok ) + { + std::cout << "what returns \"" << x.what() << "\"" << std::endl; + } } } BOOST_CHECK( exception_thrown ); @@ -222,7 +230,7 @@ int test_main( int argc, char * argv[] ) ? "Windows" : "POSIX"; # endif - std::cout << "API is " << platform << '\n'; + std::cout << "API is " << platform << std::endl; exception_tests(); @@ -325,13 +333,36 @@ int test_main( int argc, char * argv[] ) { BOOST_CHECK( ex.path1().string() == " no-way, Jose" ); } - - BOOST_CHECK( fs::create_directory( dir ) ); - // several functions give unreasonable results if uintmax_t isn't 64-bits std::cout << "sizeof(boost::uintmax_t) = " << sizeof(boost::uintmax_t) << '\n'; BOOST_CHECK( sizeof( boost::uintmax_t ) >= 8 ); + // create a directory, then check it for consistency + BOOST_CHECK( fs::create_directory( dir ) ); + + BOOST_CHECK( fs::exists( dir ) ); + BOOST_CHECK( BOOST_FS_IS_EMPTY( dir ) ); + BOOST_CHECK( fs::is_directory( dir ) ); + BOOST_CHECK( !fs::is_regular( dir ) ); + BOOST_CHECK( !fs::is_other( dir ) ); + BOOST_CHECK( !fs::is_symlink( dir ) ); + stat = fs::status( dir ); + BOOST_CHECK( fs::exists( stat ) ); + BOOST_CHECK( fs::is_directory( stat ) ); + BOOST_CHECK( !fs::is_regular( stat ) ); + BOOST_CHECK( !fs::is_other( stat ) ); + BOOST_CHECK( !fs::is_symlink( stat ) ); + + // set the current directory, then check it for consistency + fs::path original_dir = fs::current_path(); + BOOST_CHECK( dir != original_dir ); + fs::current_path( dir ); + BOOST_CHECK( fs::current_path() == dir ); + BOOST_CHECK( fs::current_path() != original_dir ); + fs::current_path( original_dir ); + BOOST_CHECK( fs::current_path() == original_dir ); + BOOST_CHECK( fs::current_path() != dir ); + // make some reasonable assuptions for testing purposes fs::space_info spi( fs::space( dir ) ); BOOST_CHECK( spi.capacity > 1000000 ); @@ -346,19 +377,6 @@ int test_main( int argc, char * argv[] ) std::cout << "available = " << spi.available << '\n'; # endif - BOOST_CHECK( fs::exists( dir ) ); - BOOST_CHECK( BOOST_FS_IS_EMPTY( dir ) ); - BOOST_CHECK( fs::is_directory( dir ) ); - BOOST_CHECK( !fs::is_regular( dir ) ); - BOOST_CHECK( !fs::is_other( dir ) ); - BOOST_CHECK( !fs::is_symlink( dir ) ); - stat = fs::status( dir ); - BOOST_CHECK( fs::exists( stat ) ); - BOOST_CHECK( fs::is_directory( stat ) ); - BOOST_CHECK( !fs::is_regular( stat ) ); - BOOST_CHECK( !fs::is_other( stat ) ); - BOOST_CHECK( !fs::is_symlink( stat ) ); - if ( platform == "Windows" ) BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::file_size), dir ), ENOENT ) ); diff --git a/test/path_test.cpp b/test/path_test.cpp index 8118555..8d85a57 100644 --- a/test/path_test.cpp +++ b/test/path_test.cpp @@ -180,7 +180,7 @@ namespace void exception_tests() { const std::string str_1("string-1"); - boost::system::error_code ec( 12345, boost::system::errno_ecat); + boost::system::error_code ec( 12345, boost::system::system_category); try { throw fs::filesystem_error( str_1, ec ); } catch ( const fs::filesystem_error & ex ) {