Boost logo

Boost-Commit :

From: bdawes_at_[hidden]
Date: 2008-07-02 17:05:55


Author: bemandawes
Date: 2008-07-02 17:05:54 EDT (Wed, 02 Jul 2008)
New Revision: 47006
URL: http://svn.boost.org/trac/boost/changeset/47006

Log:
Partial resolution of ticket #1972; remove() issues for POSIX are cleared. Added regression test cases covering self-reference and cyclic symlinks.
Text files modified:
   trunk/boost/filesystem/operations.hpp | 30 +++-----
   trunk/libs/filesystem/doc/reference.html | 54 ++++++++++------
   trunk/libs/filesystem/src/operations.cpp | 131 ++++++++++++++++++++++-----------------
   trunk/libs/filesystem/test/operations_test.cpp | 106 +++++++++++++++++++------------
   4 files changed, 184 insertions(+), 137 deletions(-)

Modified: trunk/boost/filesystem/operations.hpp
==============================================================================
--- trunk/boost/filesystem/operations.hpp (original)
+++ trunk/boost/filesystem/operations.hpp 2008-07-02 17:05:54 EDT (Wed, 02 Jul 2008)
@@ -117,6 +117,10 @@
 
     namespace detail
     {
+ // singular object used only as a tag; thus initialization and
+ // thread-safety are not issues
+ BOOST_FILESYSTEM_DECL extern system::error_code throws;
+
       typedef std::pair< system::error_code, bool >
         query_pair;
 
@@ -454,21 +458,13 @@
       return ec;
     }
 
- BOOST_FS_FUNC(bool) remove( const Path & ph )
+ BOOST_FS_FUNC(void) remove( const Path & ph, system::error_code & ec = detail::throws )
     {
- if ( exists( ph )
- || is_symlink( ph ) ) // handle dangling symbolic links
- // note that the POSIX behavior for symbolic links is what we want;
- // the link rather than what it points to is deleted. Windows behavior
- // doesn't matter; is_symlink() is always false on Windows.
- {
- system::error_code ec( detail::remove_api( ph.external_file_string() ) );
- if ( ec )
- boost::throw_exception( basic_filesystem_error<Path>(
- "boost::filesystem::remove", ph, ec ) );
- return true;
- }
- return false;
+ system::error_code error( detail::remove_api(ph.external_file_string()) );
+ if ( error && &ec == &detail::throws )
+ boost::throw_exception( basic_filesystem_error<Path>(
+ "boost::filesystem::remove", ph, error ) );
+ ec = error;
     }
 
     BOOST_FS_FUNC(unsigned long) remove_all( const Path & ph )
@@ -693,10 +689,8 @@
       const wpath & from_ph, system::error_code & ec )
       { return create_symlink<wpath>( to_ph, from_ph, ec ); }
 
- inline bool remove( const path & ph )
- { return remove<path>( ph ); }
- inline bool remove( const wpath & ph )
- { return remove<wpath>( ph ); }
+ inline void remove( const path & ph ) { remove<path>( ph ); }
+ inline void remove( const wpath & ph ) { remove<wpath>( ph ); }
 
     inline unsigned long remove_all( const path & ph )
       { return remove_all<path>( ph ); }

Modified: trunk/libs/filesystem/doc/reference.html
==============================================================================
--- trunk/libs/filesystem/doc/reference.html (original)
+++ trunk/libs/filesystem/doc/reference.html 2008-07-02 17:05:54 EDT (Wed, 02 Jul 2008)
@@ -1807,11 +1807,11 @@
 <blockquote>
   <p><i>Returns:</i></p>
   <blockquote>
- For <code>status,</code> determine the attributes
+ For <code>status</code>, determine the attributes
     of
     <code>p</code> as if by<i> POSIX </i> <code>
   <a href="http://www.opengroup.org/onlinepubs/000095399/functions/stat.html">stat()</a></code>,
- for <code>symlink_status</code> determine the attributes as if by <i>POSIX </i> <code>
+ for <code>symlink_status</code>, determine the attributes as if by <i>POSIX </i> <code>
     <a href="http://www.opengroup.org/onlinepubs/000095399/functions/lstat.html">
     lstat()</a></code>.<blockquote>
       <p>[<i>Note:</i> For symbolic links, <code>stat()</code> continues
@@ -1819,14 +1819,23 @@
       does not. <i>--
     end note</i>]</p>
     </blockquote>
- <p>If the operating system reports an error during attribute determination:</p>
+ <p>If the underlying file system reports an error during attribute determination:</p>
     <ul>
- <li>If the error indicating that <code>p</code> could not
- be resolved, as if by POSIX error codes ENOENT or ENOTDIR, set ec to 0 and return <code>
+ <li>If the error indicating that <code>p</code> could not be resolved, as
+ if by POSIX errors ENOENT or ENOTDIR, call <code>ec.clear()</code> and return <code>
       file_status(not_found_flag)</code>.</li>
     </ul>
+ <blockquote>
+ <blockquote>
+ <p>[<i>Note:</i> The effect of this behavior is to distinguish between
+ knowing that p
+ does not exist, and not being able to determine the status of p. This
+ distinction is important to users.&nbsp; <i>--end note</i>]</p>
+ </blockquote>
+ </blockquote>
     <ul>
- <li>Otherwise, set ec to the error code reported by the operating system
+ <li>Otherwise, set ec to the error number reported by the underlying
+ implementation API
       and return <code>
       file_status(status_unknown)</code>.</li>
     </ul>
@@ -2154,22 +2163,26 @@
   </span> <code>basic_filesystem_error&lt;Path1, Path2&gt;</code><span style="background-color: #FFFFFF">
   if <code>ec</code> is not zero.</span></p>
   </blockquote>
-<pre>template &lt;class Path&gt; bool remove(const Path&amp; p);</pre>
+<pre>template &lt;class Path&gt; void remove(const Path&amp; p, system::error_code &amp; ec = <i>singular</i> );</pre>
 <blockquote>
- <p><i>Effects:</i>&nbsp; Deletes the file <code>p</code> resolves
- to if it exists,
+ <p><i>Effects:</i>&nbsp; Removes the file <code>p</code>,
   as if by<i> POSIX </i><code>
- <a href="http://www.opengroup.org/onlinepubs/000095399/functions/link.html">
- remove()</a></code>.</p>
- <p><i>Returns:</i> The value of <code>exists(p)</code> prior to the
- establishment of the postcondition.</p>
- <p><i>Postcondition:</i> <code>!exists(p)</code></p>
- <p><i>Throws:</i> <code>basic_filesystem_error&lt;Path&gt;</code> if:</p>
+ remove()</code>.
+ If no error is reported by the underlying removal implementation or if <code>
+ status(p).type() == file_not_found</code>, then:</p>
   <ul>
- <li><code>exists(p) &amp;&amp; is_directory(p) &amp;&amp; !empty(p)</code>.</li>
- <li><i>Effects</i> fails for any reason other than because <code>p</code>
- does not resolve to an existing file.</li>
+ <li>if <code>ec != </code><i><code>singular</code></i>, then <code>ec.clear()</code>.</li>
   </ul>
+ <p>Otherwise,</p>
+ <ul>
+ <li>if <code>ec != </code><i><code>singular</code></i>, then set <code>ec</code>
+ to represent the error.</li>
+ <li>otherwise, throw <code>basic_filesystem_error&lt;Path&gt;</code> to represent
+ the error.if <code>ec != </code><i><code>singular</code></i>, then <code>
+ ec.clear()</code></li>
+ </ul>
+ <p><i>Postcondition:</i> <code>!exists(p)</code></p>
+ <p><i>Throws:</i> See <i>Effects</i>.</p>
   <p>[<i>Note:</i> A symbolic link is itself removed, rather than the file it
   resolves to being removed. <i>-- end note</i>]</p>
 </blockquote>
@@ -2178,8 +2191,7 @@
   <p><i>Effects:</i>&nbsp; Recursively deletes the contents of p if it exists,
   then deletes file <code>p</code> itself,
   as if by<i> POSIX </i><code>
- <a href="http://www.opengroup.org/onlinepubs/000095399/functions/link.html">
- remove()</a></code>.</p>
+ remove()</code>.</p>
   <p><i>Returns:</i> The number of files removed.</p>
   <p><i>Postcondition:</i> <code>!exists(p)</code></p>
   <p>[<i>Note:</i> A symbolic link is itself removed, rather than the file it
@@ -3068,7 +3080,7 @@
 <p>Distributed under the Boost Software License, Version 1.0. See
 <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a></p>
 <p>Revised
-<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->29 June 2008<!--webbot bot="Timestamp" endspan i-checksum="17622" --></p>
+<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->02 July 2008<!--webbot bot="Timestamp" endspan i-checksum="18822" --></p>
 
 </body>
 

Modified: trunk/libs/filesystem/src/operations.cpp
==============================================================================
--- trunk/libs/filesystem/src/operations.cpp (original)
+++ trunk/libs/filesystem/src/operations.cpp 2008-07-02 17:05:54 EDT (Wed, 02 Jul 2008)
@@ -110,6 +110,8 @@
 
 namespace
 {
+ const error_code ok;
+
   const fs::directory_iterator end_itr;
   bool is_empty_directory( const std::string & dir_path )
   {
@@ -200,19 +202,19 @@
         || (ec.value() == ERROR_BAD_PATHNAME) // "//nosuch" on Win64
         || (ec.value() == ERROR_BAD_NETPATH)) // "//nosuch" on Win32
       {
- ec = error_code(); // these are not considered errors;
+ 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 = error_code(); // these are not considered errors;
+ 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 = error_code();;
+ ec = ok;;
     return (attr & FILE_ATTRIBUTE_DIRECTORY)
       ? fs::file_status( fs::directory_file )
       : fs::file_status( fs::regular_file );
@@ -229,7 +231,7 @@
     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( error_code(),
+ return std::make_pair( ok,
       ( fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
         ? is_empty_directory( ph )
         :( !fad.nFileSizeHigh && !fad.nFileSizeLow ) );
@@ -295,7 +297,7 @@
     {
       if ( p1.handle != INVALID_HANDLE_VALUE
         || p2.handle != INVALID_HANDLE_VALUE )
- { return std::make_pair( error_code(), false ); }
+ { 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 ); }
@@ -309,7 +311,7 @@
     // 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( error_code(),
+ return std::make_pair( ok,
         info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber
         && info1.nFileIndexHigh == info2.nFileIndexHigh
         && info1.nFileIndexLow == info2.nFileIndexLow
@@ -331,7 +333,7 @@
       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( error_code(),
+ return std::make_pair( ok,
       (static_cast<boost::uintmax_t>(fad.nFileSizeHigh)
         << (sizeof(fad.nFileSizeLow)*8))
       + fad.nFileSizeLow );
@@ -349,7 +351,7 @@
     boost::filesystem::detail::space_pair result;
     if ( get_free_disk_space( ph, &avail, &total, &free ) )
     {
- result.first = error_code();
+ result.first = ok;
       result.second.capacity
         = (static_cast<boost::uintmax_t>(total.HighPart) << 32)
           + total.LowPart;
@@ -385,7 +387,7 @@
     if ( get_current_directory( sz, buf.get() ) == 0 )
       return error_code( ::GetLastError(), system_category );
     ph = buf.get();
- return error_code();
+ return ok;
   }
 
   inline bool set_current_directory( const char * buf )
@@ -426,11 +428,11 @@
         == 0 ) return error_code( ::GetLastError(), system_category );
       big_buf[len] = '\0';
       target = big_buf.get();
- return error_code();
+ return ok;
     }
     buf[len] = '\0';
     target = buf;
- return error_code();
+ return ok;
   }
 
   template<class String>
@@ -517,9 +519,14 @@
   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 ( ec )
+ return ec;
+ if ( sf.type() == fs::file_not_found )
+ return ok;
     if ( fs::is_directory( sf ) )
     {
       if ( !remove_directory( ph ) )
@@ -529,7 +536,7 @@
     {
       if ( !delete_file( ph ) ) return error_code(::GetLastError(), system_category);
     }
- return error_code();
+ return ok;
   }
 
   inline bool create_directory( const std::string & dir )
@@ -545,7 +552,7 @@
     // 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( error_code(), false );
+ return std::make_pair( ok, false );
     return std::make_pair( error, false );
   }
 
@@ -566,6 +573,24 @@
   }
 #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 != EPERM )
+ return err;
+ return ::rmdir( p )
+# else
+ std::remove( p );
+# endif
+ }
+
 #endif
 } // unnamed namespace
 
@@ -575,6 +600,7 @@
   {
     namespace detail
     {
+ BOOST_FILESYSTEM_DECL system::error_code throws;
 
 // free functions ----------------------------------------------------------//
 
@@ -763,7 +789,7 @@
         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 error_code();
+ return ok;
       }
 
       BOOST_FILESYSTEM_DECL error_code
@@ -781,7 +807,7 @@
         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 error_code();
+ return ok;
       }
 
 # endif // ifndef BOOST_FILESYSTEM_NARROW_ONLY
@@ -889,7 +915,7 @@
         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 error_code();
+ return ok;
       }
 
       BOOST_FILESYSTEM_DECL error_code
@@ -901,7 +927,7 @@
           handle = 0;
           return error_code( ok ? 0 : ::GetLastError(), system_category );
         }
- return error_code();
+ return ok;
       }
 
       BOOST_FILESYSTEM_DECL error_code
@@ -919,7 +945,7 @@
         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 error_code();
+ return ok;
       }
 
 # else // BOOST_POSIX_API
@@ -932,13 +958,13 @@
         {
           if ( errno == ENOENT || errno == ENOTDIR )
           {
- ec = error_code();
+ ec = ok;
             return fs::file_status( fs::file_not_found );
           }
           ec = error_code( errno, system_category );
           return fs::file_status( fs::status_unknown );
         }
- ec = error_code();
+ ec = ok;
         if ( S_ISDIR( path_stat.st_mode ) )
           return fs::file_status( fs::directory_file );
         if ( S_ISREG( path_stat.st_mode ) )
@@ -962,13 +988,13 @@
         {
           if ( errno == ENOENT || errno == ENOTDIR )
           {
- ec = error_code();
+ ec = ok;
             return fs::file_status( fs::file_not_found );
           }
           ec = error_code( errno, system_category );
           return fs::file_status( fs::status_unknown );
         }
- ec = error_code();
+ ec = ok;
         if ( S_ISREG( path_stat.st_mode ) )
           return fs::file_status( fs::regular_file );
         if ( S_ISDIR( path_stat.st_mode ) )
@@ -1001,7 +1027,7 @@
         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( error_code(), S_ISDIR( path_stat.st_mode )
+ return std::make_pair( ok, S_ISDIR( path_stat.st_mode )
           ? is_empty_directory( ph )
           : path_stat.st_size == 0 );
       }
@@ -1016,7 +1042,7 @@
         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( error_code(),
+ 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
@@ -1034,7 +1060,7 @@
           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( error_code(),
+ return std::make_pair( ok,
           static_cast<boost::uintmax_t>(path_stat.st_size) );
       }
 
@@ -1051,7 +1077,7 @@
         }
         else
         {
- result.first = error_code();
+ result.first = ok;
           result.second.capacity
             = static_cast<boost::uintmax_t>(vfs.f_blocks) * BOOST_STATVFS_F_FRSIZE;
           result.second.free
@@ -1068,7 +1094,7 @@
         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( error_code(), path_stat.st_mtime );
+ return std::make_pair( ok, path_stat.st_mtime );
       }
 
       BOOST_FILESYSTEM_DECL error_code
@@ -1105,7 +1131,7 @@
             break;
           }
         }
- return error_code();
+ return ok;
       }
 
       BOOST_FILESYSTEM_DECL error_code
@@ -1119,13 +1145,13 @@
       create_directory_api( const std::string & ph )
       {
         if ( ::mkdir( ph.c_str(), S_IRWXU|S_IRWXG|S_IRWXO ) == 0 )
- { return std::make_pair( error_code(), true ); }
+ { 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( error_code(), false );
+ return std::make_pair( ok, false );
       }
 
       BOOST_FILESYSTEM_DECL error_code
@@ -1147,28 +1173,19 @@
       BOOST_FILESYSTEM_DECL error_code
       remove_api( const std::string & ph )
       {
-# 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.
- if ( (is_directory( ph )
- ? ::rmdir( ph.c_str() )
- : ::unlink( ph.c_str() )) != 0 )
-# else
- // note that the POSIX behavior for symbolic links is what we want;
- // the link rather than what it points to is deleted
- if ( std::remove( ph.c_str() ) != 0 )
-# endif
- {
- 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;
- return error_code( error, system_category );
- }
- return error_code();
+ 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
@@ -1249,7 +1266,7 @@
           else max = static_cast<std::size_t>( tmp + 1 ); // relative root
         }
         result = max;
- return error_code();
+ return ok;
       }
 
       BOOST_FILESYSTEM_DECL error_code
@@ -1268,7 +1285,7 @@
         dirent de;
         buffer = std::malloc( (sizeof(dirent) - sizeof(de.d_name))
           + path_size + 1 ); // + 1 for "/0"
- return error_code();
+ return ok;
       }
 
       BOOST_FILESYSTEM_DECL error_code
@@ -1276,7 +1293,7 @@
       {
         std::free( buffer );
         buffer = 0;
- if ( handle == 0 ) return error_code();
+ if ( handle == 0 ) return ok;
         DIR * h( static_cast<DIR*>(handle) );
         handle = 0;
         return error_code( ::closedir( h ) == 0 ? 0 : errno, system_category );
@@ -1339,7 +1356,7 @@
 # else
         sf = symlink_sf = fs::file_status( fs::status_unknown );
 # endif
- return error_code();
+ return ok;
       }
 
 # endif

Modified: trunk/libs/filesystem/test/operations_test.cpp
==============================================================================
--- trunk/libs/filesystem/test/operations_test.cpp (original)
+++ trunk/libs/filesystem/test/operations_test.cpp 2008-07-02 17:05:54 EDT (Wed, 02 Jul 2008)
@@ -769,18 +769,18 @@
   BOOST_CHECK( !fs::exists( d2 / "d20" ) );
   BOOST_CHECK( fs::exists( d1 / "f2" ) );
 
- // remove() tests on file
+ // remove() file
   file_ph = dir / "shortlife";
   BOOST_CHECK( !fs::exists( file_ph ) );
   create_file( file_ph, "" );
   BOOST_CHECK( fs::exists( file_ph ) );
   BOOST_CHECK( !fs::is_directory( file_ph ) );
- BOOST_CHECK( fs::remove( file_ph ) );
+ fs::remove( file_ph );
   BOOST_CHECK( !fs::exists( file_ph ) );
- BOOST_CHECK( !fs::remove( "no-such-file" ) );
- BOOST_CHECK( !fs::remove( "no-such-directory/no-such-file" ) );
+ fs::remove( "no-such-file" );
+ fs::remove( "no-such-directory/no-such-file" );
 
- // remove() test on directory
+ // remove() directory
   d1 = dir / "shortlife_dir";
   BOOST_CHECK( !fs::exists( d1 ) );
   fs::create_directory( d1 );
@@ -789,44 +789,68 @@
   BOOST_CHECK( BOOST_FS_IS_EMPTY( d1 ) );
   bad_remove_dir = dir;
   BOOST_CHECK( CHECK_EXCEPTION( bad_remove, ENOTEMPTY ) );
- BOOST_CHECK( fs::remove( d1 ) );
+ fs::remove( d1 );
   BOOST_CHECK( !fs::exists( d1 ) );
 
-// STLport is allergic to std::system, so don't use runtime platform test
-# ifdef BOOST_POSIX
-
- // remove() test on dangling symbolic link
- fs::path link( "dangling_link" );
- fs::remove( link );
- BOOST_CHECK( !fs::is_symlink( link ) );
- BOOST_CHECK( !fs::exists( link ) );
- std::system("ln -s nowhere dangling_link");
- BOOST_CHECK( !fs::exists( link ) );
- BOOST_CHECK( fs::is_symlink( link ) );
- BOOST_CHECK( fs::remove( link ) );
- BOOST_CHECK( !fs::is_symlink( link ) );
-
- // remove() test on symbolic link to a file
- file_ph = "link_target";
- fs::remove( file_ph );
- BOOST_CHECK( !fs::exists( file_ph ) );
- create_file( file_ph, "" );
- BOOST_CHECK( fs::exists( file_ph ) );
- BOOST_CHECK( !fs::is_directory( file_ph ) );
- BOOST_CHECK( fs::is_regular( file_ph ) );
- std::system("ln -s link_target non_dangling_link");
- link = "non_dangling_link";
- BOOST_CHECK( fs::exists( link ) );
- BOOST_CHECK( !fs::is_directory( link ) );
- BOOST_CHECK( fs::is_regular( link ) );
- BOOST_CHECK( fs::is_symlink( link ) );
- BOOST_CHECK( fs::remove( link ) );
- BOOST_CHECK( fs::exists( file_ph ) );
- BOOST_CHECK( !fs::exists( link ) );
- BOOST_CHECK( !fs::is_symlink( link ) );
- BOOST_CHECK( fs::remove( file_ph ) );
- BOOST_CHECK( !fs::exists( file_ph ) );
-# endif
+ if ( create_symlink_ok ) // only if symlinks supported
+ {
+ // remove() dangling symbolic link
+ fs::path link( "dangling_link" );
+ fs::remove( link );
+ BOOST_CHECK( !fs::is_symlink( link ) );
+ BOOST_CHECK( !fs::exists( link ) );
+ fs::create_symlink( "nowhere", link );
+ BOOST_CHECK( !fs::exists( link ) );
+ BOOST_CHECK( fs::is_symlink( link ) );
+ fs::remove( link );
+ BOOST_CHECK( !fs::is_symlink( link ) );
+
+ // remove() self-refering symbolic link
+ link = "link_to_self";
+ fs::remove( link );
+ BOOST_CHECK( !fs::is_symlink( link ) );
+ BOOST_CHECK( !fs::exists( link ) );
+ fs::create_symlink( link, link );
+ fs::remove( link );
+ BOOST_CHECK( !fs::exists( link ) );
+ BOOST_CHECK( !fs::is_symlink( link ) );
+
+ // remove() cyclic symbolic link
+ link = "link_to_a";
+ fs::path link2( "link_to_b" );
+ fs::remove( link );
+ fs::remove( link2 );
+ BOOST_CHECK( !fs::is_symlink( link ) );
+ BOOST_CHECK( !fs::exists( link ) );
+ fs::create_symlink( link, link2 );
+ fs::create_symlink( link2, link );
+ fs::remove( link );
+ fs::remove( link2 );
+ BOOST_CHECK( !fs::exists( link ) );
+ BOOST_CHECK( !fs::exists( link2 ) );
+ BOOST_CHECK( !fs::is_symlink( link ) );
+
+ // remove() symbolic link to file
+ file_ph = "link_target";
+ fs::remove( file_ph );
+ BOOST_CHECK( !fs::exists( file_ph ) );
+ create_file( file_ph, "" );
+ BOOST_CHECK( fs::exists( file_ph ) );
+ BOOST_CHECK( !fs::is_directory( file_ph ) );
+ BOOST_CHECK( fs::is_regular( file_ph ) );
+ link = "non_dangling_link";
+ fs::create_symlink( file_ph, link );
+ BOOST_CHECK( fs::exists( link ) );
+ BOOST_CHECK( !fs::is_directory( link ) );
+ BOOST_CHECK( fs::is_regular( link ) );
+ BOOST_CHECK( fs::is_symlink( link ) );
+ fs::remove( link );
+ BOOST_CHECK( fs::exists( file_ph ) );
+ BOOST_CHECK( !fs::exists( link ) );
+ BOOST_CHECK( !fs::is_symlink( link ) );
+ fs::remove( file_ph );
+ BOOST_CHECK( !fs::exists( file_ph ) );
+ }
 
   // write time tests
 


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk