Align error codes to be based on POSIX

[SVN r29485]
This commit is contained in:
Beman Dawes
2005-06-08 21:03:07 +00:00
parent 8afe37cdbd
commit 07de4dccc5
9 changed files with 176 additions and 142 deletions

View File

@@ -162,10 +162,11 @@ processing.</p>
<h2><a name="Acknowledgements">Acknowledgements</a></h2>
<p>Peter Dimov patiently identified requirements for portability and
internationalization of error messages. </p>
internationalization of error messages. He also suggested basing the portable
error codes on POSIX.</p>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->09 May, 2005<!--webbot bot="Timestamp" endspan i-checksum="14004" --></p>
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->08 June, 2005<!--webbot bot="Timestamp" endspan i-checksum="19924" --></p>
<p>© Copyright Beman Dawes, 2002</p>
<p> Use, modification, and distribution are subject to the Boost Software

View File

@@ -24,6 +24,8 @@ Filesystem Library</h1>
&nbsp;&nbsp;&nbsp; <a href="#Common_Specifications">Common Specifications</a><br>
&nbsp;&nbsp;&nbsp; <a href="#Race-condition">Race-condition danger</a><br>
&nbsp;&nbsp;&nbsp; <a href="#Implementation">Implementation</a><br>
&nbsp;&nbsp;&nbsp; <a href="#narrow-only">Restricting library to narrow
character paths</a><br>
&nbsp;&nbsp;&nbsp; <a href="#Building">Building the object-library</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#Cgywin">Notes for Cygwin users</a><br>
&nbsp;&nbsp;&nbsp; <a href="#Acknowledgements">Acknowledgements</a><br>
@@ -403,6 +405,13 @@ either the POSIX or Windows API.</p>
<p>The library is in regular use on Apple OS X, HP-UX, IBM AIX, Linux,
Microsoft Windows, SGI IRIX, and Sun Solaris operating systems using a variety
of compilers.</p>
<h2><a name="narrow-only">Restricting library to narrow character paths</a></h2>
<p>Compilers or standard libraries which do not support wide characters (wchar_t)
or wide character strings (std::wstring) are detected automatically, and cause
the library to compile code that is restricted to narrow character paths
(boost::filesystem::path). Users can force this restriction by defining the
macro BOOST_FILESYSTEM_NARROW_ONLY. That may be useful for dealing with legacy
compilers or operating systems.</p>
<h2><a name="Building">Building</a> the object-library</h2>
<p>The object-library will normally be built automatically. See
<a href="../../../more/getting_started.html">Getting Started</a>. It can also be
@@ -619,7 +628,7 @@ version 1.31.0.</p>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->29 May, 2005<!--webbot bot="Timestamp" endspan i-checksum="14006" --></p>
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->08 June, 2005<!--webbot bot="Timestamp" endspan i-checksum="19924" --></p>
<p>© Copyright Beman Dawes, 2002-2005</p>
<p> Use, modification, and distribution are subject to the Boost Software

View File

@@ -0,0 +1,23 @@
// 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 <cerrno>
#if defined __BORLANDC__
#define ENOSYS 9997
#endif
#define EBADHANDLE 9998 // bad handle
#define EOTHERERR 9999 // Other operating system error not translatable
// to a POSIX errno value
#endif // include guard

View File

@@ -79,35 +79,23 @@ namespace boost
};
# endif // ifndef BOOST_FILESYSTEM_NARROW_ONLY
enum error_code
{
no_error = 0,
system_error, // system generated error; if possible, is translated
// to one of the more specific errors below.
other_error, // library generated error
security_error, // includes access rights, permissions failures
read_only_error,
io_error,
path_error, // such as bad syntax
not_found_error,
not_directory_error,
busy_error, // implies trying again might succeed
not_ready_error, // ditto
already_exists_error,
not_empty_error,
is_directory_error,
out_of_space_error,
out_of_memory_error,
out_of_resource_error
};
typedef int errno_type; // determined by C standard
typedef int system_error_type; // both POSIX and Windows use int
typedef int system_error_type;
# ifdef BOOST_WINDOWS_API
BOOST_FILESYSTEM_DECL
errno_type lookup_errno( system_error_type sys_err_code );
# else
inline errno_type lookup_errno( system_error_type sys_err_code )
{ return sys_err_code; }
# endif
BOOST_FILESYSTEM_DECL error_code
lookup_error_code( system_error_type sys_err_code );
BOOST_FILESYSTEM_DECL void
system_message( system_error_type sys_err_code, std::string & target );
// deprecated support for legacy function name
inline errno_type lookup_error_code( system_error_type sys_err_code )
{ return lookup_errno( sys_err_code ); }
BOOST_FILESYSTEM_DECL
void system_message( system_error_type sys_err_code, std::string & target );
// Effects: appends error message to target
# if defined(BOOST_WINDOWS_API) && !defined(BOOST_FILESYSTEM_NARROW_ONLY)
@@ -475,7 +463,7 @@ namespace boost
typename String::size_type size = -1
)
{
if ( size == -1 ) size = src.size();
if ( size == String::npos ) size = src.size();
element_pos = 0;
element_size = 0;
if ( src.empty() ) return;
@@ -592,7 +580,7 @@ namespace boost
&& m_path[end_pos] == path_separator<path_type>::value );
// skip separators unless root directory
string_type::size_type root_dir_pos( detail::root_directory_start
typename string_type::size_type root_dir_pos( detail::root_directory_start
<string_type, traits_type>( m_path, end_pos ) );
for ( ;
end_pos > 0
@@ -644,7 +632,7 @@ namespace boost
template<class String, class Traits>
String basic_path<String, Traits>::root_directory() const
{
string_type::size_type start(
typename string_type::size_type start(
detail::root_directory_start<String, Traits>( m_path, m_path.size() ) );
return start == string_type::npos
@@ -730,7 +718,7 @@ namespace boost
template<class String, class Traits>
basic_path<String, Traits> & basic_path<String, Traits>::canonize()
{
static const string_type::value_type dot[]
static const typename string_type::value_type dot[]
= { path_relative<path_type>::value, 0 };
if ( m_path.empty() ) return *this;
@@ -752,7 +740,7 @@ namespace boost
template<class String, class Traits>
basic_path<String, Traits> & basic_path<String, Traits>::normalize()
{
static const string_type::value_type dot[]
static const typename string_type::value_type dot[]
= { path_relative<path_type>::value, 0 };
if ( m_path.empty() ) return *this;
@@ -796,7 +784,7 @@ namespace boost
&& temp.m_path[temp.m_path.size()-1]
== path_separator<path_type>::value )
{
string_type::size_type rds(
typename string_type::size_type rds(
detail::root_directory_start<String,Traits>( temp.m_path,
temp.m_path.size() ) );
if ( rds == string_type::npos
@@ -839,11 +827,11 @@ namespace boost
// for Windows, use the alternate separator, and bypass extra
// root separators
string_type::size_type root_dir_start(
typename string_type::size_type root_dir_start(
detail::root_directory_start<String, Traits>( m_path, m_path.size() ) );
bool in_root( root_dir_start != string_type::npos );
String s;
for ( string_type::size_type pos( 0 );
for ( typename string_type::size_type pos( 0 );
pos != m_path.size(); ++pos )
{
// special case // [net]
@@ -891,7 +879,7 @@ namespace boost
{
iterator itr;
itr.m_path_ptr = this;
string_type::size_type element_size;
typename string_type::size_type element_size;
detail::first_element<String, Traits>( m_path, itr.m_pos, element_size );
itr.m_name = m_path.substr( itr.m_pos, element_size );
return itr;
@@ -954,7 +942,7 @@ namespace boost
}
typedef typename Path::string_type string_type;
string_type::size_type end_pos(
typename string_type::size_type end_pos(
ph.m_path_ptr->m_path.find( path_separator<Path>::value, ph.m_pos ) );
# ifdef BOOST_WINDOWS_PATH
if ( end_pos == string_type::npos )
@@ -973,17 +961,17 @@ namespace boost
typedef typename Path::string_type string_type;
static const string_type::value_type separators[] = {
static const typename string_type::value_type separators[] = {
path_separator<Path>::value,
# ifdef BOOST_WINDOWS_PATH
path_alt_separator<Path>::value,
# endif
0 };
string_type::size_type end_pos( ph.m_pos );
typename string_type::size_type end_pos( ph.m_pos );
string_type::size_type root_dir_pos( detail::root_directory_start
<string_type, typename Path::traits_type>(
typename string_type::size_type root_dir_pos(
detail::root_directory_start<string_type, typename Path::traits_type>(
ph.m_path_ptr->m_path, end_pos ) );
// if at end and there was a trailing non-root '/', return "."

View File

@@ -16,6 +16,7 @@
#include <boost/filesystem/config.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/cerrno.hpp>
namespace fs = boost::filesystem;
@@ -25,10 +26,9 @@ namespace fs = boost::filesystem;
namespace std { using ::strerror; }
# endif
# if defined( BOOST_WINDOWS_API )
# include "windows.h"
# else
# include <errno.h> // for POSIX error codes
# endif
#include <boost/config/abi_prefix.hpp> // must be the last header
@@ -37,62 +37,59 @@ namespace fs = boost::filesystem;
namespace
{
struct ec_xlate { int sys_ec; fs::error_code ec; };
#ifdef BOOST_WINDOWS_API
struct ec_xlate { fs::system_error_type sys_ec; fs::errno_type ec; };
const ec_xlate ec_table[] =
{
# ifdef BOOST_WINDOWS_API
{ 0, fs::other_error },
{ ERROR_ACCESS_DENIED, fs::security_error },
{ ERROR_INVALID_ACCESS, fs::security_error },
{ ERROR_SHARING_VIOLATION, fs::security_error },
{ ERROR_LOCK_VIOLATION, fs::security_error },
{ ERROR_LOCKED, fs::security_error },
{ ERROR_NOACCESS, fs::security_error },
{ ERROR_WRITE_PROTECT, fs::read_only_error },
{ ERROR_NOT_READY, fs::not_ready_error },
{ ERROR_SEEK, fs::io_error },
{ ERROR_READ_FAULT, fs::io_error },
{ ERROR_WRITE_FAULT, fs::io_error },
{ ERROR_CANTOPEN, fs::io_error },
{ ERROR_CANTREAD, fs::io_error },
{ ERROR_CANTWRITE, fs::io_error },
{ ERROR_DIRECTORY, fs::path_error },
{ ERROR_INVALID_NAME, fs::path_error },
{ ERROR_FILE_NOT_FOUND, fs::not_found_error },
{ ERROR_PATH_NOT_FOUND, fs::not_found_error },
{ ERROR_DEV_NOT_EXIST, fs::not_found_error },
{ ERROR_DEVICE_IN_USE, fs::busy_error },
{ ERROR_OPEN_FILES, fs::busy_error },
{ ERROR_BUSY_DRIVE, fs::busy_error },
{ ERROR_BUSY, fs::busy_error },
{ ERROR_FILE_EXISTS, fs::already_exists_error },
{ ERROR_ALREADY_EXISTS, fs::already_exists_error },
{ ERROR_DIR_NOT_EMPTY, fs::not_empty_error },
{ ERROR_HANDLE_DISK_FULL, fs::out_of_space_error },
{ ERROR_DISK_FULL, fs::out_of_space_error },
{ ERROR_OUTOFMEMORY, fs::out_of_memory_error },
{ ERROR_NOT_ENOUGH_MEMORY, fs::out_of_memory_error },
{ ERROR_TOO_MANY_OPEN_FILES, fs::out_of_resource_error }
# else
{ 0, fs::other_error },
{ EACCES, fs::security_error },
{ EROFS, fs::read_only_error },
{ EIO, fs::io_error },
{ EINVAL, fs::path_error },
{ ENAMETOOLONG, fs::path_error },
{ ENOENT, fs::not_found_error },
{ ENOTDIR, fs::not_directory_error },
{ EAGAIN, fs::busy_error },
{ EBUSY, fs::busy_error },
{ ETXTBSY, fs::busy_error },
{ EEXIST, fs::already_exists_error },
{ ENOTEMPTY, fs::not_empty_error },
{ EISDIR, fs::is_directory_error },
{ ENOSPC, fs::out_of_space_error },
{ ENOMEM, fs::out_of_memory_error },
{ EMFILE, fs::out_of_resource_error }
# endif
// see WinError.h comments for descriptions of errors
// most common errors first to speed sequential search
{ ERROR_FILE_NOT_FOUND, ENOENT },
{ ERROR_PATH_NOT_FOUND, ENOENT },
// alphabetical for easy maintenance
{ 0, 0 }, // no error
{ ERROR_ACCESS_DENIED, EACCES },
{ ERROR_ALREADY_EXISTS, EEXIST },
{ ERROR_BAD_UNIT, ENODEV },
{ ERROR_BUFFER_OVERFLOW, ENAMETOOLONG },
{ ERROR_BUSY, EBUSY },
{ ERROR_BUSY_DRIVE, EBUSY },
{ ERROR_CANNOT_MAKE, EACCES },
{ ERROR_CANTOPEN, EIO },
{ ERROR_CANTREAD, EIO },
{ ERROR_CANTWRITE, EIO },
{ ERROR_CURRENT_DIRECTORY, EACCES },
{ ERROR_DEV_NOT_EXIST, ENODEV },
{ ERROR_DEVICE_IN_USE, EBUSY },
{ ERROR_DIR_NOT_EMPTY, ENOTEMPTY },
{ ERROR_DIRECTORY, EINVAL }, // WinError.h: "The directory name is invalid"
{ ERROR_DISK_FULL, ENOSPC },
{ ERROR_FILE_EXISTS, EEXIST },
{ ERROR_HANDLE_DISK_FULL, ENOSPC },
{ ERROR_INVALID_ACCESS, EACCES },
{ ERROR_INVALID_DRIVE, ENODEV },
{ ERROR_INVALID_FUNCTION, ENOSYS },
{ ERROR_INVALID_HANDLE, EBADHANDLE },
{ ERROR_INVALID_NAME, EINVAL },
{ ERROR_LOCK_VIOLATION, EACCES },
{ ERROR_LOCKED, EACCES },
{ ERROR_NOACCESS, EACCES },
{ ERROR_NOT_ENOUGH_MEMORY, ENOMEM },
{ ERROR_NOT_READY, EAGAIN },
{ ERROR_NOT_SAME_DEVICE, EXDEV },
{ ERROR_OPEN_FAILED, EIO },
{ ERROR_OPEN_FILES, EBUSY },
{ ERROR_OUTOFMEMORY, ENOMEM },
{ ERROR_READ_FAULT, EIO },
{ ERROR_SEEK, EIO },
{ ERROR_SHARING_VIOLATION, EACCES },
{ ERROR_TOO_MANY_OPEN_FILES, ENFILE },
{ ERROR_WRITE_FAULT, EIO },
{ ERROR_WRITE_PROTECT, EROFS },
{ 0,EOTHERERR }
};
#endif
} // unnamed namespace
@@ -100,8 +97,10 @@ namespace boost
{
namespace filesystem
{
BOOST_FILESYSTEM_DECL error_code
lookup_error_code( system_error_type sys_err_code )
# ifdef BOOST_WINDOWS_API
BOOST_FILESYSTEM_DECL
errno_type lookup_errno( system_error_type sys_err_code )
{
for ( const ec_xlate * cur = &ec_table[0];
cur != ec_table
@@ -109,10 +108,9 @@ namespace boost
{
if ( sys_err_code == cur->sys_ec ) return cur->ec;
}
return system_error; // general system error code
return EOTHERERR;
}
# ifdef BOOST_WINDOWS_API
BOOST_FILESYSTEM_DECL void
system_message( system_error_type sys_err_code, std::string & target )
{

View File

@@ -622,7 +622,11 @@ namespace boost
dir_itr_first(
void *& handle, const std::wstring & dir, std::wstring & target )
{
std::wstring dirpath( dir + L"/*" );
// 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 )
@@ -718,7 +722,11 @@ namespace boost
// causes a ERROR_FILE_NOT_FOUND error which we do not considered an
// error. It is treated as eof instead.
{
std::string dirpath( dir + "/*" );
// use a form of search Sebastian Martel reports will work with Win98
std::string dirpath( dir );
dirpath += (dirpath.empty()
|| dirpath[dirpath.size()-1] != '\\') ? "\\*" : "*";
WIN32_FIND_DATAA data;
if ( (handle = ::FindFirstFileA( dirpath.c_str(), &data ))
== INVALID_HANDLE_VALUE )

View File

@@ -28,21 +28,20 @@ using fs::path;
namespace
{
template< typename F >
bool throws_fs_error( F func, fs::error_code ec =
::boost::filesystem::no_error ) // VC++ 7.1 build 2292 won't accept fs::
bool throws_fs_error( F func, fs::errno_type ec = 0 )
{
try { func(); }
catch ( const fs::filesystem_error & ex )
{
if ( ec == fs::no_error
if ( ec == 0
|| ec == fs::lookup_error_code(ex.system_error()) ) return true;
std::cout
<< "exception reports " << fs::lookup_error_code(ex.system_error())
<< ", should be " << ec
<< "\n system_error() is " << ex.system_error()
<< std::endl;
return true;
return false;
}
return false;
}

View File

@@ -32,7 +32,7 @@ namespace std
return s1 == e ? 0 : (*s1<*s2 ? -1 : 1);
}
static size_t length(const char_type* s)
{ const char_type* b=s; for(;*s!=0L;++s); return s-b; }
{ const char_type* b=s; for(;*s!=0L;++s){} return s-b; }
static const char_type* find(const char_type* s, size_t n, const char_type& a)
{ return 0; }

View File

@@ -8,6 +8,7 @@
// See library home page at http://www.boost.org/libs/filesystem
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/cerrno.hpp>
namespace fs = boost::filesystem;
#include <boost/config.hpp>
@@ -19,7 +20,6 @@ using boost::bind;
#include <fstream>
#include <iostream>
#include <string>
#include <cerrno>
#include <ctime>
#ifndef BOOST_FILESYSTEM_NARROW_ONLY
@@ -42,6 +42,8 @@ using boost::bind;
using ::difftime; using ::time; using ::tm; using ::mktime; }
# endif
#define CHECK_EXCEPTION(b,e) throws_fs_error(b,e,__LINE__)
namespace
{
bool report_throws;
@@ -70,22 +72,21 @@ namespace
}
template< typename F >
bool throws_fs_error( F func, fs::error_code ec =
::boost::filesystem::no_error ) // VC++ 7.1 build 2292 won't accept fs::
bool throws_fs_error( F func, fs::errno_type ec, int line )
{
try { func(); }
catch ( const fs::filesystem_error & ex )
{
if ( report_throws ) std::cout << ex.what() << "\n";
if ( ec == fs::no_error
if ( ec == 0
|| ec == fs::lookup_error_code(ex.system_error()) ) return true;
std::cout
<< "exception reports " << fs::lookup_error_code(ex.system_error())
<< "\nline " << line
<< " exception reports " << fs::lookup_error_code(ex.system_error())
<< ", should be " << ec
<< "\n system_error() is " << ex.system_error()
<< std::endl;
return true;
}
return false;
}
@@ -132,10 +133,10 @@ int test_main( int argc, char * argv[] )
# endif
std::cout << "API is " << platform << '\n';
std::cout << "initial_path<path>().string() is\n \""
std::cout << "\ninitial_path<path>().string() is\n \""
<< fs::initial_path<fs::path>().string()
<< "\"\n";
std::cout << "initial_path<fs::path>().file_string() is\n \""
std::cout << "\ninitial_path<fs::path>().file_string() is\n \""
<< fs::initial_path<fs::path>().file_string()
<< "\"\n";
BOOST_CHECK( fs::initial_path<fs::path>().is_complete() );
@@ -147,6 +148,8 @@ int test_main( int argc, char * argv[] )
BOOST_CHECK( fs::complete( "/" ).string() == fs::initial_path<fs::path>().root_path().string() );
BOOST_CHECK( fs::complete( "foo" ).string() == fs::initial_path<fs::path>().string()+"/foo" );
BOOST_CHECK( fs::complete( "/foo" ).string() == fs::initial_path<fs::path>().root_path().string()+"foo" );
BOOST_CHECK( fs::complete( "foo", fs::path( "//net/bar" ) ).string()
== "//net/bar/foo" );
// predicate and status tests
fs::path ng( " no-way, Jose" );
@@ -177,8 +180,6 @@ int test_main( int argc, char * argv[] )
== "c:/" );
BOOST_CHECK( fs::complete( fs::path( "c:/foo" ) ).string()
== "c:/foo" );
BOOST_CHECK( fs::complete( fs::path( "//share" ) ).string()
== "//share" );
BOOST_CHECK( fs::system_complete( fs::path( fs::initial_path<fs::path>().root_name() ) ).string() == fs::initial_path<fs::path>().string() );
BOOST_CHECK( fs::system_complete( fs::path( fs::initial_path<fs::path>().root_name()
@@ -205,8 +206,8 @@ int test_main( int argc, char * argv[] )
fs::remove_all( dir ); // in case residue from prior failed tests
BOOST_CHECK( !fs::exists( dir ) );
// the bound functions should throw, so throws_fs_error() should return true
BOOST_CHECK( throws_fs_error( bind( BOOST_BND(fs::file_size), ng ), fs::not_found_error ) );
// the bound functions should throw, so CHECK_EXCEPTION() should return true
BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::file_size), ng ), ENOENT ) );
// test path::exception members
try { fs::file_size( ng ); } // will throw
@@ -221,8 +222,12 @@ int test_main( int argc, char * argv[] )
BOOST_CHECK( fs::exists( dir ) );
BOOST_CHECK( BOOST_FS_IS_EMPTY( dir ) );
BOOST_CHECK( fs::is_directory( dir ) );
BOOST_CHECK( throws_fs_error( bind( BOOST_BND(fs::file_size), dir ),
fs::is_directory_error ) );
if ( platform == "Windows" )
BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::file_size), dir ),
ENOENT ) );
else
BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::file_size), dir ),
EISDIR ) );
BOOST_CHECK( !fs::create_directory( dir ) );
BOOST_CHECK( !fs::is_symlink( dir ) );
@@ -302,8 +307,8 @@ int test_main( int argc, char * argv[] )
BOOST_CHECK( fs::is_file( file_ph ) );
BOOST_CHECK( BOOST_FS_IS_EMPTY( file_ph ) );
BOOST_CHECK( fs::file_size( file_ph ) == 0 );
BOOST_CHECK( throws_fs_error( bind( BOOST_BND(fs::create_directory),
file_ph ), fs::not_directory_error ) );
BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::create_directory),
file_ph ), EEXIST ) );
// create a file named "f1"
file_ph = dir / "f1";
create_file( file_ph, "foobar1" );
@@ -316,7 +321,8 @@ int test_main( int argc, char * argv[] )
// equivalence tests
fs::path ng2("does_not_exist2");
BOOST_CHECK( throws_fs_error( bind( BOOST_BND(fs::equivalent), ng, ng2 ) ) );
BOOST_CHECK( CHECK_EXCEPTION(
bind( BOOST_BND(fs::equivalent), ng, ng2 ), ENOENT ) );
BOOST_CHECK( fs::equivalent( file_ph, dir / "f1" ) );
BOOST_CHECK( fs::equivalent( dir, d1 / ".." ) );
BOOST_CHECK( !fs::equivalent( file_ph, dir ) );
@@ -348,8 +354,9 @@ int test_main( int argc, char * argv[] )
BOOST_CHECK( fs::exists( link_ph ) );
BOOST_CHECK( fs::exists( file_ph ) );
BOOST_CHECK( fs::equivalent( link_ph, file_ph ) );
BOOST_CHECK( throws_fs_error(
bind( BOOST_BND(fs::create_hard_link), dir, dir/"shouldnotwork" ), fs::not_found_error ) );
BOOST_CHECK( CHECK_EXCEPTION(
bind( BOOST_BND(fs::create_hard_link), dir, dir/"shouldnotwork" ),
0 ) );
}
// there was an inital bug in directory_iterator that caused premature
// close of an OS handle. This block will detect regression.
@@ -374,28 +381,29 @@ int test_main( int argc, char * argv[] )
// [case 1] make sure can't rename() a non-existent file
BOOST_CHECK( !fs::exists( d1 / "f99" ) );
BOOST_CHECK( !fs::exists( d1 / "f98" ) );
BOOST_CHECK( throws_fs_error( bind( BOOST_BND(fs::rename), d1 / "f99", d1 / "f98" ),
fs::not_found_error ) );
BOOST_CHECK( throws_fs_error( bind( BOOST_BND(fs::rename), fs::path(""), d1 / "f98" ),
fs::not_found_error ) );
BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::rename), d1 / "f99", d1 / "f98" ),
ENOENT ) );
BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::rename), fs::path(""), d1 / "f98" ),
ENOENT ) );
// [case 2] rename() target.empty()
BOOST_CHECK( throws_fs_error( bind( BOOST_BND(fs::rename), file_ph, "" ),
fs::not_found_error ) );
BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::rename), file_ph, "" ),
ENOENT ) );
// [case 3] make sure can't rename() to an existent file or directory
BOOST_CHECK( fs::exists( dir / "f1" ) );
BOOST_CHECK( fs::exists( d1 / "f2" ) );
BOOST_CHECK( throws_fs_error( bind( BOOST_BND(fs::rename), dir / "f1", d1 / "f2" ) ) );
BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::rename),
dir / "f1", d1 / "f2" ), EEXIST ) );
// several POSIX implementations (cygwin, openBSD) report ENOENT instead of EEXIST,
// so we don't verify error type on the above test.
BOOST_CHECK( throws_fs_error( bind( BOOST_BND(fs::rename), dir, d1 ) ) );
BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::rename), dir, d1 ), 0 ) );
// [case 4A] can't rename() file to a nonexistent parent directory
BOOST_CHECK( !fs::is_directory( dir / "f1" ) );
BOOST_CHECK( !fs::exists( dir / "d3/f3" ) );
BOOST_CHECK( throws_fs_error( bind( BOOST_BND(fs::rename), dir / "f1", dir / "d3/f3" ),
fs::not_found_error ) );
BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::rename), dir / "f1", dir / "d3/f3" ),
ENOENT ) );
// [case 4B] rename() file in same directory
BOOST_CHECK( fs::exists( d1 / "f2" ) );
@@ -421,8 +429,8 @@ int test_main( int argc, char * argv[] )
BOOST_CHECK( fs::exists( d1 ) );
BOOST_CHECK( !fs::exists( dir / "d3/d5" ) );
BOOST_CHECK( !fs::exists( dir / "d3" ) );
BOOST_CHECK( throws_fs_error( bind( BOOST_BND(fs::rename), d1, dir / "d3/d5" ),
fs::not_found_error ) );
BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::rename), d1, dir / "d3/d5" ),
ENOENT ) );
// [case 5B] rename() on directory
fs::path d3( dir / "d3" );
@@ -471,7 +479,7 @@ int test_main( int argc, char * argv[] )
BOOST_CHECK( fs::exists( d1 ) );
BOOST_CHECK( fs::is_directory( d1 ) );
BOOST_CHECK( BOOST_FS_IS_EMPTY( d1 ) );
BOOST_CHECK( throws_fs_error( bind( BOOST_BND(fs::remove), dir ), fs::not_empty_error ) );
BOOST_CHECK( CHECK_EXCEPTION( bind( BOOST_BND(fs::remove), dir ), ENOTEMPTY ) );
BOOST_CHECK( fs::remove( d1 ) );
BOOST_CHECK( !fs::exists( d1 ) );