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(),
172 int retval =
platform_lstat((path +
"/" + dit->d_name).c_str(), &info);
175 (path +
"/" + dit->d_name).c_str(), errno);
177 if (S_ISDIR(info.st_mode)) {
179 path.c_str(), dit->d_name);
180 if (Notify(fn_new_dir_prefix, path, dit->d_name) && recurse_) {
181 DoRecursion(path, dit->d_name);
183 Notify(fn_new_dir_postfix, path, dit->d_name);
184 }
else if (S_ISREG(info.st_mode)) {
186 path.c_str(), dit->d_name);
187 Notify(fn_new_file, path, dit->d_name);
188 }
else if (S_ISLNK(info.st_mode)) {
190 path.c_str(), dit->d_name);
191 Notify(fn_new_symlink, path, dit->d_name);
192 }
else if (S_ISSOCK(info.st_mode)) {
194 path.c_str(), dit->d_name);
195 Notify(fn_new_socket, path, dit->d_name);
196 }
else if (S_ISBLK(info.st_mode)) {
198 path.c_str(), dit->d_name);
199 Notify(fn_new_block_dev, path, dit->d_name);
200 }
else if (S_ISCHR(info.st_mode)) {
202 "passing character-device "
204 path.c_str(), dit->d_name);
205 Notify(fn_new_character_dev, path, dit->d_name);
206 }
else if (S_ISFIFO(info.st_mode)) {
208 path.c_str(), dit->d_name);
209 Notify(fn_new_fifo, path, dit->d_name);
212 path.c_str(), dit->d_name);
219 Notify(fn_leave_dir, parent_path, dir_name);
222 inline bool Notify(
const BoolCallback callback,
223 const std::string &parent_path,
224 const std::string &entry_name)
const {
225 return (callback == NULL) ?
true
226 : (delegate_->*callback)(
227 GetRelativePath(parent_path), entry_name);
230 inline void Notify(
const VoidCallback callback,
231 const std::string &parent_path,
232 const std::string &entry_name)
const {
233 if (callback != NULL) {
234 (delegate_->*callback)(GetRelativePath(parent_path), entry_name);
239 const unsigned int rel_dir_len = relative_to_directory_.length();
240 if (rel_dir_len >= absolute_path.length()) {
242 }
else if (rel_dir_len > 1) {
243 return absolute_path.substr(rel_dir_len + 1);
244 }
else if (rel_dir_len == 0) {
245 return absolute_path;
246 }
else if (relative_to_directory_ ==
"/") {
247 return absolute_path.substr(1);
254 #ifdef CVMFS_NAMESPACE_GUARD
258 #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,...)