Subject: Re: [Boost-bugs] [Boost C++ Libraries] #5403: filesystem3::recursive_directory_iterator::increment(system::error_code& ec) unexpected behaviour
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2012-09-03 01:18:21
#5403: filesystem3::recursive_directory_iterator::increment(system::error_code&
ec) unexpected behaviour
--------------------------------------+-------------------------------------
Reporter: ttan@⦠| Owner: bemandawes
Type: Bugs | Status: new
Milestone: To Be Determined | Component: filesystem
Version: Boost Development Trunk | Severity: Showstopper
Resolution: | Keywords: recursive_directory_iterator increment
--------------------------------------+-------------------------------------
Comment (by schmurtz_boost@â¦):
Imagine we are listing "dir1", and we are at element "node2" in this
listing. iter->path() is "dir1/node2".
There're several reasons for recur_dir_itr_imp::increment() to fail:
- at the beginning if "m_stack.top()->symlink_status(*ec)" or
"m_stack.top()->status(*ec)" fails (stat or lstat on "dir1/node2" fails :
we can't know if it is a directory). In this case, to continue, one need
to call no_push() (using pop(), we would miss other files/folders after
"node2" in "dir1").
- during the sublisting of "dir1/node2", in
"m_stack.push(directory_iterator(m_stack.top()->path(),*ec))". At this
time, one need to call pop() to continue, but, as said ttan, there's a bug
is incrementing m_level. However, like Benjamin Herr, I think it's better
not to push the bad directory_iterator: therefore, one just needs to call
no_push() to continue listing.
- during the listing of "dir1" after "node2", in "++m_stack.top()". Note
that this will always throw, even if ec is not null. Imagine this is
corrected (using "m_stack.top().increment(*ec)"), one need to call pop()
to continue listing. As far as I know, failing in the middle of a
directory listing is really uncommon.
So, the first two cases are errors for going deeper in the hierarchy: to
continue, one needs to no_push(). In the last case, error is when
continuing listing at the same level: pop() is required to continue. As
it's not possible to know what kind of error we have (without analysing
exact error code, which may be difficult and implementation specific), I
propose the following strategy:
{{{
iter.increment(ec);
while(ec) {
path cur_path = iter->path();
iter.no_push(); // if it an error of the third case, no_push() won't
help, but is harmless as we'll get exactly the same error.
error_code saved_ec = ec;
iter.increment(ec);
if(!ec) {
cerr << "can't go inside " << cur_path << " " << saved_ec;
break;
} else {
cerr << "can't go inside and/or can't list after " << cur_path << " "
<< saved_ec;
iter.pop(ec);
}
}
}}}
Note that there's currently no iter.pop(error_code&) function, just a
iter.pop() that will throw in case of an error.
Furthermore, in my understanding of the concept, pop() should work even at
level 0 and return the end iterator. For me, pop() is just a way to pass
all remaining filesystem nodes at the current level, and MUST NOT be
followed by another increment (otherwise you'll miss one item, pop() being
somehow an increment).
I think also that the first item returned by
recursive_directory_iterator("/test") should be "/test", as in all POSIX
recursive commands. But this last point may be disputed ;). Note that in
this case, /test is level 0 and then calling pop() at this level become
again a non-sense.
-- Ticket URL: <https://svn.boost.org/trac/boost/ticket/5403#comment:6> Boost C++ Libraries <http://www.boost.org/> Boost provides free peer-reviewed portable C++ source libraries.
This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:10 UTC