Re: [Boost-bugs] [Boost C++ Libraries] #5403: filesystem3::recursive_directory_iterator::increment(system::error_code& ec) unexpected behaviour

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