Files
wlan-cloud-lib-poco/Foundation/include/Poco/RecursiveDirectoryIteratorImpl.h
Aleksandar Fabijanic e1018881ba Harden RecursiveDirectoryIterator when walking the filesystem. (#2001)
* In the implementation for the *Traverse strategies the next method performs an unguarded list directory.  If the directory is not accessible an unrecoverable error is raised thus ruining the walk.  This changeset adopts and adapts the error handling protocol as defined in Python's os.walk function where errors from listdir are ignored or are reported to an optional on error callback function.

* Expand DirectoryIteratorsTest testsuite to confirm the hardened iterator behaviour over unreadable directories.

* Expand DirectoryIteratorsTest testsuite to confirm the hardened iterator behaviour over
  unreadable directories.  Correct bad formatting

* fix clang compile
2017-11-15 10:47:44 -06:00

120 lines
2.2 KiB
C++

//
// RecursiveDirectoryIteratorImpl.h
//
// Library: Foundation
// Package: Filesystem
// Module: RecursiveDirectoryIterator
//
// Definition of the RecursiveDirectoryIteratorImpl class.
//
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Foundation_RecursiveDirectoryIteratorImpl_INCLUDED
#define Foundation_RecursiveDirectoryIteratorImpl_INCLUDED
#include "Poco/Foundation.h"
#include "Poco/DirectoryIteratorStrategy.h"
#include "Poco/Delegate.h"
#include <stack>
#include <functional>
namespace Poco {
class ChildrenFirstTraverse;
class SiblingsFirstTraverse;
template<class TTraverseStrategy = ChildrenFirstTraverse>
class RecursiveDirectoryIteratorImpl
{
public:
enum
{
D_INFINITE = 0 /// Special value for infinite traverse depth.
};
RecursiveDirectoryIteratorImpl(const std::string& path, UInt16 maxDepth = D_INFINITE)
: _maxDepth(maxDepth), _traverseStrategy(std::ptr_fun(depthFun), _maxDepth), _isFinished(false), _rc(1)
{
_itStack.push(DirectoryIterator(path));
_current = _itStack.top()->path();
}
~RecursiveDirectoryIteratorImpl()
{
}
inline void duplicate()
{
++_rc;
}
inline void release()
{
if (--_rc == 0)
delete this;
}
inline UInt16 depth() const
{
return depthFun(_itStack);
}
inline UInt16 maxDepth() const
{
return _maxDepth;
}
inline const std::string& get() const
{
return _current;
}
template <typename T>
void onError(T& obj, void (T::*pCB)(const void*, const std::string&))
{
_traverseStrategy.traverseError += delegate(&obj, pCB);
}
const std::string& next()
{
if (_isFinished)
return _current;
_current = _traverseStrategy.next(&_itStack, &_isFinished);
return _current;
}
private:
typedef std::stack<DirectoryIterator> Stack;
static UInt16 depthFun(const Stack& stack)
/// Function which implements the logic of determining
/// recursion depth.
{
return static_cast<Poco::UInt16>(stack.size());
}
UInt16 _maxDepth;
TTraverseStrategy _traverseStrategy;
bool _isFinished;
Stack _itStack;
std::string _current;
int _rc;
};
} // namespace Poco
#endif // Foundation_RecursiveDirectoryIteratorImpl_INCLUDED