Boost C++ Libraries: Ticket #6821: recursive_directory_iterator: increment fails with 'access denied' https://svn.boost.org/trac10/ticket/6821 <p> This issue is found on Windows 7 x64, Win32 binary built with Visual Studio 2010. See attachment for sample program. </p> <p> Recursive iteration fails when iterating a directory that contains a child directory for which the user does not have permission to access. The attached program illustrates this issue, assuming that the user has at least one directory that the current users does not have permission to access: </p> <pre class="wiki">boost::filesystem::directory_iterator::construct: Access is denied: "c:\$Recycle.Bin\S-1-5-20" </pre><p> The exception is caused by FindFirstFileW() returning ERROR_ACCESS_DENIED. This function is located in dir_itr_first(), filesystem/v3/src/operations.cpp, line 2000. </p> <p> Intuitively this iteration should work and any directories for which the user does not have permission to access should be ignored. Though, perhaps there are at least two use cases for this behaviour when encountering a directory for which the user does not have permission to access: </p> <ul><li>Iteration is not expected to fail with an 'access denied' error, so if it encounters this situation throw an error. (The current behaviour.) </li><li>It is unknown if the directory being recursively iterated contains one or more directories for which the user does not have access. Therefore, these directories should be ignored and processing allowed to continue. </li></ul><p> One solution might be to allow a flag to be passed in the constructor that would define which of the two behaviours to invoke. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/6821 Trac 1.4.3 Gary Sanders <lex21@…> Sun, 22 Apr 2012 18:54:37 GMT attachment set https://svn.boost.org/trac10/ticket/6821 https://svn.boost.org/trac10/ticket/6821 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">fs_bug.cpp</span> </li> </ul> <p> source code </p> Ticket Gary Sanders <lex21@…> Fri, 27 Apr 2012 15:29:52 GMT attachment set https://svn.boost.org/trac10/ticket/6821 https://svn.boost.org/trac10/ticket/6821 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">diff.txt</span> </li> </ul> Ticket Gary Sanders <lex21@…> Fri, 27 Apr 2012 15:31:42 GMT <link>https://svn.boost.org/trac10/ticket/6821#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6821#comment:1</guid> <description> <p> Attached is a proposed one line code change that will fix the issue described without changing or introducing functionality. </p> <p> The diff is created from operations.cpp, trunk rev 78220. </p> </description> <category>Ticket</category> </item> <item> <author>Gary Sanders <lex21@…></author> <pubDate>Wed, 02 May 2012 17:52:31 GMT</pubDate> <title>attachment set https://svn.boost.org/trac10/ticket/6821 https://svn.boost.org/trac10/ticket/6821 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">access_denied.patch</span> </li> </ul> <p> svn patch file </p> Ticket Beman Dawes Mon, 28 May 2012 12:44:13 GMT status changed https://svn.boost.org/trac10/ticket/6821#comment:2 https://svn.boost.org/trac10/ticket/6821#comment:2 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">assigned</span> </li> </ul> <p> You suggestion of adding an option to treat permission denied as an empty directory seems to me to be the best resolution, since the desired behavior is very application dependent. </p> <p> I've implemented and tested that for Windows, and am satisfied with the results. This work has been stashed until 1.50.0 is out the door, when I'll resume work on it. </p> <p> Thanks, </p> <p> --Beman </p> Ticket Jesse Jarrell <jjarrell@…> Wed, 29 Aug 2012 03:11:42 GMT <link>https://svn.boost.org/trac10/ticket/6821#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6821#comment:3</guid> <description> <p> The proposed fix only addresses when the first entry is a directory and returns an access denied code. The POSIX code handles this situation nicely with the iterator being set to EOF. However, if there are more entries you get an internal error. </p> <p> Here is the test directory structure I used to reproduce this as user anonymous: </p> <pre class="wiki"> drwxrwxr-x 5 anonymous anonymous 4096 Aug 28 20:45 ./ drwxrwxr-x 8 anonymous anonymous 4096 Aug 28 20:14 ../ drwx------ 2 root root 4096 Aug 28 15:30 root_noaccess/ drwxrwxr-x 2 root anonymous 4096 Aug 28 15:28 root_subdir/ drwxrwxr-x 2 anonymous anonymous 4096 Aug 28 20:14 xfiles/ </pre><pre class="wiki">#include &lt;boost/config/warning_disable.hpp&gt; #include &lt;boost/filesystem.hpp&gt; #include &lt;iostream&gt; #include &lt;iterator&gt; using namespace std; int main(int argc, char* argv[]) { boost::system::error_code dir_error; for ( boost::filesystem::recursive_directory_iterator end, dir(".", dir_error); dir != end; dir.increment(dir_error) ) { if (dir_error.value()) { cerr &lt;&lt; "Error accessing file: " &lt;&lt; dir_error.message() &lt;&lt; endl; }else{ cout &lt;&lt; dir-&gt;path() &lt;&lt; endl; } } return 0; } </pre><p> Output: </p> <pre class="wiki">anonymous@ubuntu:~/perm_test$ ./test_perms "./root_noaccess" Error accessing file: Permission denied ***** Internal Program Error - assertion (m_imp.get()) failed in boost::filesystem::directory_entry&amp; boost::filesystem::directory_iterator::dereference() const: /usr/local/include/boost/filesystem/operations.hpp(714): attempt to dereference end iterator Aborted (core dumped) </pre><p> The expected outcome would be for the iterator to continue on to root_subdir since the program has no access to the directory "./root_noaccess". </p> </description> <category>Ticket</category> </item> <item> <author>Jesse Jarrell <jjarrell@…></author> <pubDate>Wed, 29 Aug 2012 13:05:38 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6821#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6821#comment:4</guid> <description> <p> Found ticket <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/5403" title="#5403: Bugs: filesystem3::recursive_directory_iterator::increment(system::error_code ... (closed: fixed)">#5403</a> that has more details and a workaround for the problems with increment. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Claudio Bley</dc:creator> <pubDate>Mon, 25 Mar 2013 16:27:14 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6821#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6821#comment:5</guid> <description> <p> Actually, this is a regression in regard to v2. </p> <p> In v2 you could use no_push() in order to skip a directory after an error occurred. </p> <p> With v3, the directory_iterator at the top of the stack is invalid (ie. an end iterator) if an error occurs. So, you cannot dereference it, and you cannot use any other method (e.g. no_push) on it, otherwise std::abort will be called. </p> <p> Simple fix: just don't push an end iterator to m_stack. </p> <pre class="wiki">--- C:\Users\Claudio\src\boost.svn\boost\filesystem\operations.hpp 2012-07-24 08:43:28 +0200 +++ boost\filesystem\operations.hpp 2013-03-25 17:21:39 +0100 @@ -791,9 +791,11 @@ m_stack.push(directory_iterator(m_stack.top()-&gt;path())); else { - m_stack.push(directory_iterator(m_stack.top()-&gt;path(), *ec)); + directory_iterator next = directory_iterator(m_stack.top()-&gt;path(), *ec); if (*ec) return; + else + m_stack.push(next); } if (m_stack.top() != directory_iterator()) { </pre> </description> <category>Ticket</category> </item> <item> <author>rose.branston@…</author> <pubDate>Wed, 21 May 2014 12:00:08 GMT</pubDate> <title>version, severity changed https://svn.boost.org/trac10/ticket/6821#comment:6 https://svn.boost.org/trac10/ticket/6821#comment:6 <ul> <li><strong>version</strong> <span class="trac-field-old">Boost 1.49.0</span> → <span class="trac-field-new">Boost 1.55.0</span> </li> <li><strong>severity</strong> <span class="trac-field-old">Problem</span> → <span class="trac-field-new">Showstopper</span> </li> </ul> <p> I have encountered the same problem on ubuntu except I don't get the "Permission Denied" message or an exception thrown, it just aborts. </p> Ticket Beman Dawes Tue, 22 Jul 2014 15:49:16 GMT status changed; resolution set https://svn.boost.org/trac10/ticket/6821#comment:7 https://svn.boost.org/trac10/ticket/6821#comment:7 <ul> <li><strong>status</strong> <span class="trac-field-old">assigned</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> </ul> <p> <code>recursive_directory_iterator::increment</code> implementation code has been reorganized, adding an invariant that progress is always made even if an error is reported by exception or error_code. Thanks to Claudio Bley for his pull request, which was incorporated into the reorganized code. </p> <p> Tickets <a class="ext-link" href="https://svn.boost.org/trac/boost/ticket/5403"><span class="icon">​</span>5403</a> and <a class="ext-link" href="https://svn.boost.org/trac/boost/ticket/6821"><span class="icon">​</span>6821</a> have been closed. Please open a new issue and supply test cases if you continue to experience problems. </p> Ticket