8 #ifndef CVMFS_UTIL_FS_TRAVERSAL_H_
9 #define CVMFS_UTIL_FS_TRAVERSAL_H_
23 #ifdef CVMFS_NAMESPACE_GUARD
24 namespace CVMFS_NAMESPACE_GUARD {
38 typedef void (T::*VoidCallback)(
const std::string &relative_path,
39 const std::string &dir_name);
40 typedef bool (T::*BoolCallback)(
const std::string &relative_path,
41 const std::string &dir_name);
87 const std::string &relative_to_directory,
92 , fn_new_symlink(NULL)
94 , fn_new_block_dev(NULL)
95 , fn_new_character_dev(NULL)
97 , fn_ignore_file(NULL)
98 , fn_new_dir_prefix(NULL)
99 , fn_new_dir_postfix(NULL)
100 , delegate_(delegate)
101 , relative_to_directory_(relative_to_directory)
102 , recurse_(recurse) {
110 void Recurse(
const std::string &dir_path)
const {
111 assert(fn_enter_dir != NULL || fn_leave_dir != NULL || fn_new_file != NULL
112 || fn_new_symlink != NULL || fn_new_dir_prefix != NULL
113 || fn_new_block_dev != NULL || fn_new_character_dev != NULL
114 || fn_new_fifo != NULL || fn_new_socket != NULL);
116 assert(relative_to_directory_.length() == 0
117 || dir_path.substr(0, relative_to_directory_.length())
118 == relative_to_directory_);
120 DoRecursion(dir_path,
"");
135 const std::string &dir_name)
const {
138 const std::string path = parent_path
139 + ((!dir_name.empty()) ? (
"/" + dir_name) :
"");
143 path.c_str(), parent_path.c_str(), dir_name.c_str());
144 dip = opendir(path.c_str());
147 "Failed to open %s (%d).\n"
148 "Please check directory permissions.",
149 path.c_str(), errno);
151 Notify(fn_enter_dir, parent_path, dir_name);
156 if (std::string(dit->d_name) ==
"." || std::string(dit->d_name) ==
"..") {
158 }
else if (fn_ignore_file != NULL) {
159 if (Notify(fn_ignore_file, path, dit->d_name)) {
161 path.c_str(), dit->d_name);
166 "not ignoring %s/%s (fn_ignore_file not set)", path.c_str(),
176 (path +
"/" + dit->d_name).c_str(), errno);
178 if (S_ISDIR(info.st_mode)) {
180 path.c_str(), dit->d_name);
181 if (Notify(fn_new_dir_prefix, path, dit->d_name) && recurse_) {
182 DoRecursion(path, dit->d_name);
184 Notify(fn_new_dir_postfix, path, dit->d_name);
185 }
else if (S_ISREG(info.st_mode)) {
187 path.c_str(), dit->d_name);
188 Notify(fn_new_file, path, dit->d_name);
189 }
else if (S_ISLNK(info.st_mode)) {
191 path.c_str(), dit->d_name);
192 Notify(fn_new_symlink, path, dit->d_name);
193 }
else if (S_ISSOCK(info.st_mode)) {
195 path.c_str(), dit->d_name);
196 Notify(fn_new_socket, path, dit->d_name);
197 }
else if (S_ISBLK(info.st_mode)) {
199 path.c_str(), dit->d_name);
200 Notify(fn_new_block_dev, path, dit->d_name);
201 }
else if (S_ISCHR(info.st_mode)) {
203 "passing character-device "
205 path.c_str(), dit->d_name);
206 Notify(fn_new_character_dev, path, dit->d_name);
207 }
else if (S_ISFIFO(info.st_mode)) {
209 path.c_str(), dit->d_name);
210 Notify(fn_new_fifo, path, dit->d_name);
213 path.c_str(), dit->d_name);
220 Notify(fn_leave_dir, parent_path, dir_name);
223 inline bool Notify(
const BoolCallback callback,
224 const std::string &parent_path,
225 const std::string &entry_name)
const {
226 return (callback == NULL) ?
true
227 : (delegate_->*callback)(
228 GetRelativePath(parent_path), entry_name);
231 inline void Notify(
const VoidCallback callback,
232 const std::string &parent_path,
233 const std::string &entry_name)
const {
234 if (callback != NULL) {
235 (delegate_->*callback)(GetRelativePath(parent_path), entry_name);
240 const unsigned int rel_dir_len = relative_to_directory_.length();
241 if (rel_dir_len >= absolute_path.length()) {
243 }
else if (rel_dir_len > 1) {
244 return absolute_path.substr(rel_dir_len + 1);
245 }
else if (rel_dir_len == 0) {
246 return absolute_path;
247 }
else if (relative_to_directory_ ==
"/") {
248 return absolute_path.substr(1);
255 #ifdef CVMFS_NAMESPACE_GUARD
259 #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,...)