Boost C++ Libraries: Ticket #2866: boost::filesystem::rename throw exception when target file exists, but documentation tell us that it must be replaced https://svn.boost.org/trac10/ticket/2866 <p> [Note: If from_p and to_p resolve to the same file, no action is taken. '''Otherwise, if to_p resolves to an existing file, it is removed'''. A symbolic link is itself renamed, rather than the file it resolves to being renamed. -- end note] </p> <p> A part from libs/filesystem/operations.cpp </p> <pre class="wiki">BOOST_FILESYSTEM_DECL error_code rename_api( const std::string &amp; from, const std::string &amp; to ) { return error_code( ::MoveFileA( from.c_str(), to.c_str() ) ? 0 : ::GetLastError(), system_category ); } </pre><pre class="wiki">BOOST_FILESYSTEM_DECL error_code rename_api( const std::string &amp; from, const std::string &amp; to ) { // POSIX is too permissive so must check error_code dummy; if ( fs::exists( status_api( to, dummy ) ) ) return error_code( EEXIST, system_category ); return error_code( std::rename( from.c_str(), to.c_str() ) != 0 ? errno : 0, system_category ); } </pre><p> And boost/filesystem/operation.hpp </p> <pre class="wiki">BOOST_FS_FUNC(void) rename( const Path &amp; from_path, const Path &amp; to_path ) { system::error_code ec( detail::rename_api( from_path.external_directory_string(), to_path.external_directory_string() ) ); if ( ec ) boost::throw_exception( basic_filesystem_error&lt;Path&gt;( "boost::filesystem::rename", from_path, to_path, ec ) ); } </pre> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/2866 Trac 1.4.3 csapuntz@… Fri, 05 Jun 2009 05:45:05 GMT severity changed https://svn.boost.org/trac10/ticket/2866#comment:1 https://svn.boost.org/trac10/ticket/2866#comment:1 <ul> <li><strong>severity</strong> <span class="trac-field-old">Cosmetic</span> → <span class="trac-field-new">Problem</span> </li> </ul> <p> MoveFileA/W error out if destination exists. The posix rename_api is written to error out if destination exists (though there is a race of course). </p> <p> Recommend using <a class="missing wiki">MoveFileEx</a>(<sub>MOVEFILE_REPLACE_EXISTING) on Windows </sub></p> Ticket sean@… Tue, 17 Nov 2009 22:46:39 GMT version, milestone changed; cc set https://svn.boost.org/trac10/ticket/2866#comment:2 https://svn.boost.org/trac10/ticket/2866#comment:2 <ul> <li><strong>cc</strong> <span class="trac-author">sean@…</span> added </li> <li><strong>version</strong> <span class="trac-field-old">Boost 1.38.0</span> → <span class="trac-field-new">Boost 1.40.0</span> </li> <li><strong>milestone</strong> <span class="trac-field-old">Boost 1.39.0</span> → <span class="trac-field-new">Boost 1.41.0</span> </li> </ul> <p> Passing the call back to POSIX's rename(2) call should result in the desired outcome that matches the semantics of both POSIX's rename(2) call and boost::filesystem's documentation. The attached patch fixes this problem and changes the behavior of boost::filesystem::rename() to match that of rename(2). I believe that the Win32 API is doing the correct thing. The extra exists() checks should be removed from the POSIX versions according to the posix specification. POSIX rename(2) guarantees rename(2) to be atomic and the extra check creates a race condition that prevents boost's rename() from being used. </p> <p> Thanks in advance. </p> <p> <a class="ext-link" href="http://www.opengroup.org/onlinepubs/000095399/functions/rename.html"><span class="icon">​</span>http://www.opengroup.org/onlinepubs/000095399/functions/rename.html</a> </p> <p> --- /tmp/operations.cpp 2009-11-17 14:40:39.000000000 -0800 +++ contrib-Darwin-i386/boost-1.41.0.beta1.cmake1/libs/filesystem/src/operations.cpp 2009-11-17 14:41:00.000000000 -0800 @@ -1186,10 +1186,6 @@ </p> <blockquote> <p> BOOST_FILESYSTEM_DECL error_code rename_api( const std::string &amp; from, const std::string &amp; to ) { </p> </blockquote> <ul><li> <em> POSIX is too permissive so must check </em></li><li> error_code dummy; </li><li> if ( fs::exists( status_api( to, dummy ) ) ) </li><li> return error_code( EEXIST, system_category ); </li></ul><blockquote> <p> return error_code( std::rename( from.c_str(), to.c_str() ) != 0 </p> <blockquote> <p> ? errno : 0, system_category ); </p> </blockquote> </blockquote> <blockquote> <p> } </p> </blockquote> Ticket Beman Dawes Mon, 07 Dec 2009 19:52:19 GMT status changed; resolution set https://svn.boost.org/trac10/ticket/2866#comment:3 https://svn.boost.org/trac10/ticket/2866#comment:3 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> </ul> <p> (In <a class="changeset" href="https://svn.boost.org/trac10/changeset/58226" title="rename() specs now same as POSIX; fix #2866, but for V3 only">[58226]</a>) rename() specs now same as POSIX; fix <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/2866" title="#2866: Bugs: boost::filesystem::rename throw exception when target file exists, but ... (closed: fixed)">#2866</a>, but for V3 only </p> Ticket