Boost C++ Libraries: Ticket #1972: boost::filesystem::remove() throws on self referenced symlinks https://svn.boost.org/trac10/ticket/1972 <p> If one creates a symlink like this "ln -s sym sym" (to itself symlink), bfs::exists("sym") will throw because the documentation defines it to do so (and I have nothing against it doing so, although in my programs because of this I am forced to just use "lstat()" and I can't replace using "lstat()" to check if something exists with bfs::exists). </p> <p> However, I do think that bfs::remove("sym") throwing for the same reason (because it calls upon bfs::exists()) is the wrong thing to do. The source around bfs::remove() implementation even try to solve the issue of "dangling symlinks" as they call it by having an exception in case bfs::exists returns false and the target path points to a dangling symlink and still tries to remove it. Unfortunetly, exists will throw in my example of a symlink (not even dangling technically speaking :) ) even tho a remove on that kind of symlink should work just fine (it does work in shell or just doing std::remove()). </p> <p> If boost::exists is going to be left in place to throw for those "valid" symlinks (because exists is suposed to try to dereference symlinks and dereferencing such a recursive symlink is always an error) then the only solution I see is to not use exists at all. Because I also found that remove and remove_all are fairly inefficient regarding repetitive calls fo stat/lstat on the same path I've created the attached patch that fixes the reported problem and would be more efficient "system call" wise. </p> <p> I am using Linux and ext3 filesystem tho in theory it should perform the same on any symlink supporting platform (since symlinks are just containers of strings as defined by POSIX and if you try to dereference a self referencing symlink you should always get an error different than ENOENT and others for which exists() does not throw). </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/1972 Trac 1.4.3 dizzy@… Fri, 30 May 2008 12:24:51 GMT attachment set https://svn.boost.org/trac10/ticket/1972 https://svn.boost.org/trac10/ticket/1972 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">remove-selfsym-fix.diff</span> </li> </ul> <p> Reworks remove/remove_all so they do not error on self referencing symlinks and are more efficient "system call" wise </p> Ticket Beman Dawes Mon, 25 Aug 2008 15:46:04 GMT status changed; resolution set https://svn.boost.org/trac10/ticket/1972#comment:1 https://svn.boost.org/trac10/ticket/1972#comment:1 <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> Thanks for the patch! </p> <p> It has been applied. </p> <p> --Beman </p> Ticket anonymous Tue, 26 Aug 2008 08:39:34 GMT <link>https://svn.boost.org/trac10/ticket/1972#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/1972#comment:2</guid> <description> <p> Thanks for applying the patch. While looking for it I noticed it's not in 1.36 release but it is in the boost trunk. This way I also noticed that the trunk code seems a sort of 1.35 code with my patch instead of being a 1.36 version with some sort of adapted version of my patch. In 1.36: </p> <ul><li>remove(): <ul><li>has a default argument for error code thus allows to be called in a nothrow way </li><li>does not return bool but void and thus no need for any stat/exists() I/O call (errors based on the result of the system dependent remove API error) </li></ul></li><li>remove_all() <ul><li>has a default argument for error code thus allows to be called in a nothrow way </li></ul></li></ul><p> I will adapt my patch for the 1.36 code since I think the current version in boost trunk reverses on good changes that were in 1.36 (unless you think otherwise of course :) ). </p> </description> <category>Ticket</category> </item> <item> <author>dizzy@…</author> <pubDate>Tue, 26 Aug 2008 08:49:17 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/1972#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/1972#comment:3</guid> <description> <p> Err, remove_all() had no no changes in 1.36 so I was wrong above about the remove_all() default argument. </p> <p> Only remove() had some changes in 1.36 that seem to be reversed by application of my patch. All that's needed to fix this actually is to get remove() back to the version from 1.36. This also fixes what my patch intended to do because 1.36 remove() does not calle exists() or status() on the parameter thus no reason to throw on self referenced symlinks. </p> </description> <category>Ticket</category> </item> </channel> </rss>