8 #ifndef CVMFS_UTIL_FS_TRAVERSAL_H_
9 #define CVMFS_UTIL_FS_TRAVERSAL_H_
24 #ifdef CVMFS_NAMESPACE_GUARD
25 namespace CVMFS_NAMESPACE_GUARD {
39 typedef void (T::*VoidCallback)(
const std::string &relative_path,
40 const std::string &dir_name);
41 typedef bool (T::*BoolCallback)(
const std::string &relative_path,
42 const std::string &dir_name);
88 const std::string &relative_to_directory,
95 fn_new_block_dev(NULL),
96 fn_new_character_dev(NULL),
99 fn_new_dir_prefix(NULL),
100 fn_new_dir_postfix(NULL),
102 relative_to_directory_(relative_to_directory),
112 void Recurse(
const std::string &dir_path)
const {
113 assert(fn_enter_dir != NULL ||
114 fn_leave_dir != NULL ||
115 fn_new_file != NULL ||
116 fn_new_symlink != NULL ||
117 fn_new_dir_prefix != NULL ||
118 fn_new_block_dev != NULL ||
119 fn_new_character_dev != NULL ||
120 fn_new_fifo != NULL ||
121 fn_new_socket != NULL);
123 assert(relative_to_directory_.length() == 0 ||
124 dir_path.substr(0, relative_to_directory_.length()) ==
125 relative_to_directory_);
127 DoRecursion(dir_path,
"");
142 void DoRecursion(
const std::string &parent_path,
const std::string &dir_name)
147 const std::string path = parent_path + ((!dir_name.empty()) ?
148 (
"/" + dir_name) :
"");
152 path.c_str(), parent_path.c_str(), dir_name.c_str());
153 dip = opendir(path.c_str());
156 "Failed to open %s (%d).\n"
157 "Please check directory permissions.",
158 path.c_str(), errno);
160 Notify(fn_enter_dir, parent_path, dir_name);
165 if (std::string(dit->d_name) ==
"." || std::string(dit->d_name) ==
"..") {
167 }
else if (fn_ignore_file != NULL) {
168 if (Notify(fn_ignore_file, path, dit->d_name)) {
170 path.c_str(), dit->d_name);
175 "not ignoring %s/%s (fn_ignore_file not set)",
176 path.c_str(), dit->d_name);
181 int retval =
platform_lstat((path +
"/" + dit->d_name).c_str(), &info);
184 (path +
"/" + dit->d_name).c_str(), errno);
186 if (S_ISDIR(info.st_mode)) {
188 path.c_str(), dit->d_name);
189 if (Notify(fn_new_dir_prefix, path, dit->d_name) && recurse_) {
190 DoRecursion(path, dit->d_name);
192 Notify(fn_new_dir_postfix, path, dit->d_name);
193 }
else if (S_ISREG(info.st_mode)) {
195 path.c_str(), dit->d_name);
196 Notify(fn_new_file, path, dit->d_name);
197 }
else if (S_ISLNK(info.st_mode)) {
199 path.c_str(), dit->d_name);
200 Notify(fn_new_symlink, path, dit->d_name);
201 }
else if (S_ISSOCK(info.st_mode)) {
203 path.c_str(), dit->d_name);
204 Notify(fn_new_socket, path, dit->d_name);
205 }
else if (S_ISBLK(info.st_mode)) {
207 path.c_str(), dit->d_name);
208 Notify(fn_new_block_dev, path, dit->d_name);
209 }
else if (S_ISCHR(info.st_mode)) {
212 path.c_str(), dit->d_name);
213 Notify(fn_new_character_dev, path, dit->d_name);
214 }
else if (S_ISFIFO(info.st_mode)) {
216 path.c_str(), dit->d_name);
217 Notify(fn_new_fifo, path, dit->d_name);
220 path.c_str(), dit->d_name);
227 Notify(fn_leave_dir, parent_path, dir_name);
230 inline bool Notify(
const BoolCallback callback,
231 const std::string &parent_path,
232 const std::string &entry_name)
const
234 return (callback == NULL) ?
true :
235 (delegate_->*callback)(GetRelativePath(parent_path),
239 inline void Notify(
const VoidCallback callback,
240 const std::string &parent_path,
241 const std::string &entry_name)
const
243 if (callback != NULL) {
244 (delegate_->*callback)(GetRelativePath(parent_path),
250 const unsigned int rel_dir_len = relative_to_directory_.length();
251 if (rel_dir_len >= absolute_path.length()) {
253 }
else if (rel_dir_len > 1) {
254 return absolute_path.substr(rel_dir_len + 1);
255 }
else if (rel_dir_len == 0) {
256 return absolute_path;
257 }
else if (relative_to_directory_ ==
"/") {
258 return absolute_path.substr(1);
265 #ifdef CVMFS_NAMESPACE_GUARD
269 #endif // CVMFS_UTIL_FS_TRAVERSAL_H_
VoidCallback fn_new_symlink
VoidCallback fn_new_character_dev
void Recurse(const std::string &dir_path) const
void DoRecursion(const std::string &parent_path, const std::string &dir_name) const
A simple recursion engine to abstract the recursion of directories. It provides several callback hook...
assert((mem||(size==0))&&"Out Of Memory")
VoidCallback fn_leave_dir
std::string relative_to_directory_
BoolCallback fn_ignore_file
FileSystemTraversal(T *delegate, const std::string &relative_to_directory, const bool recurse)
VoidCallback fn_enter_dir
std::string GetRelativePath(const std::string &absolute_path) const
bool Notify(const BoolCallback callback, const std::string &parent_path, const std::string &entry_name) const
VoidCallback fn_new_block_dev
static int Init(const loader::LoaderExports *loader_exports)
VoidCallback fn_new_dir_postfix
void Notify(const VoidCallback callback, const std::string &parent_path, const std::string &entry_name) const
VoidCallback fn_new_socket
BoolCallback fn_new_dir_prefix
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)