Fix walk_path. Test works

GitOrigin-RevId: c09c177e1e6a85efce931c0eb1e59d2aab3a4042
This commit is contained in:
Arseny Smirnov 2018-09-12 15:24:21 +03:00
parent f72bcd230f
commit 16b2c5969d

View File

@ -50,23 +50,23 @@ Result<std::pair<FileFd, string>> mkstemp(CSlice dir) TD_WARN_UNUSED_RESULT;
Result<string> mkdtemp(CSlice dir, Slice prefix) TD_WARN_UNUSED_RESULT;
template <class Func>
Status walk_path(CSlice path, const Func &func) TD_WARN_UNUSED_RESULT;
Status walk_path(CSlice path, Func &&func) TD_WARN_UNUSED_RESULT;
#if TD_PORT_POSIX
// TODO move details somewhere else
namespace detail {
template <class Func>
Status walk_path_dir(string &path, FileFd fd, const Func &func) TD_WARN_UNUSED_RESULT;
Status walk_path_dir(string &path, FileFd fd, Func &&func) TD_WARN_UNUSED_RESULT;
template <class Func>
Status walk_path_dir(string &path, const Func &func) TD_WARN_UNUSED_RESULT;
Status walk_path_dir(string &path, Func &&func) TD_WARN_UNUSED_RESULT;
template <class Func>
Status walk_path_file(string &path, const Func &func) TD_WARN_UNUSED_RESULT;
Status walk_path_file(string &path, Func &&func) TD_WARN_UNUSED_RESULT;
template <class Func>
Status walk_path(string &path, const Func &func) TD_WARN_UNUSED_RESULT;
Status walk_path(string &path, Func &&func) TD_WARN_UNUSED_RESULT;
template <class Func>
Status walk_path_subdir(string &path, DIR *dir, const Func &func) {
Status walk_path_subdir(string &path, DIR *dir, Func &&func) {
while (true) {
errno = 0;
auto *entry = readdir(dir);
@ -92,15 +92,15 @@ Status walk_path_subdir(string &path, DIR *dir, const Func &func) {
Status status;
#ifdef DT_DIR
if (entry->d_type == DT_UNKNOWN) {
status = walk_path(path, func);
status = walk_path(path, std::forward<Func>(func));
} else if (entry->d_type == DT_DIR) {
status = walk_path_dir(path, func);
status = walk_path_dir(path, std::forward<Func>(func));
} else if (entry->d_type == DT_REG) {
status = walk_path_file(path, func);
status = walk_path_file(path, std::forward<Func>(func));
}
#else
#warning "Slow walk_path"
status = walk_path(path, func);
status = walk_path(path, std::forward<Func>(func));
#endif
if (status.is_error()) {
return status;
@ -109,49 +109,49 @@ Status walk_path_subdir(string &path, DIR *dir, const Func &func) {
}
template <class Func>
Status walk_path_dir(string &path, DIR *subdir, const Func &func) {
Status walk_path_dir(string &path, DIR *subdir, Func &&func) {
SCOPE_EXIT {
closedir(subdir);
};
TRY_STATUS(walk_path_subdir(path, subdir, func));
TRY_STATUS(walk_path_subdir(path, subdir, std::forward<Func>(func)));
func(path, true);
return Status::OK();
}
template <class Func>
Status walk_path_dir(string &path, FileFd fd, const Func &func) {
Status walk_path_dir(string &path, FileFd fd, Func &&func) {
auto native_fd = fd.move_as_native_fd();
auto *subdir = fdopendir(native_fd.fd());
if (subdir == nullptr) {
return OS_ERROR("fdopendir");
}
native_fd.release();
return walk_path_dir(path, subdir, func);
return walk_path_dir(path, subdir, std::forward<Func>(func));
}
template <class Func>
Status walk_path_dir(string &path, const Func &func) {
Status walk_path_dir(string &path, Func &&func) {
auto *subdir = opendir(path.c_str());
if (subdir == nullptr) {
return OS_ERROR(PSLICE() << tag("opendir", path));
}
return walk_path_dir(path, subdir, func);
return walk_path_dir(path, subdir, std::forward<Func>(func));
}
template <class Func>
Status walk_path_file(string &path, const Func &func) {
Status walk_path_file(string &path, Func &&func) {
func(path, false);
return Status::OK();
}
template <class Func>
Status walk_path(string &path, const Func &func) {
Status walk_path(string &path, Func &&func) {
TRY_RESULT(fd, FileFd::open(path, FileFd::Read));
auto stat = fd.stat();
bool is_dir = stat.is_dir_;
bool is_reg = stat.is_reg_;
if (is_dir) {
return walk_path_dir(path, std::move(fd), func);
return walk_path_dir(path, std::move(fd), std::forward<Func>(func));
}
fd.close();
@ -164,11 +164,11 @@ Status walk_path(string &path, const Func &func) {
} // namespace detail
template <class Func>
Status walk_path(CSlice path, const Func &func) {
Status walk_path(CSlice path, Func &&func) {
string curr_path;
curr_path.reserve(PATH_MAX + 10);
curr_path = path.c_str();
return detail::walk_path(curr_path, func);
return detail::walk_path(curr_path, std::forward<Func>(func));
}
#endif
@ -177,7 +177,7 @@ Status walk_path(CSlice path, const Func &func) {
namespace detail {
template <class Func>
Status walk_path_dir(const std::wstring &dir_name, const Func &func) {
Status walk_path_dir(const std::wstring &dir_name, Func &&func) {
std::wstring name = dir_name + L"\\*";
WIN32_FIND_DATA file_data;
@ -194,7 +194,7 @@ Status walk_path_dir(const std::wstring &dir_name, const Func &func) {
TRY_RESULT(entry_name, from_wstring(full_name));
if (file_data.cFileName[0] != '.') {
if ((file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
TRY_STATUS(walk_path_dir(full_name, func));
TRY_STATUS(walk_path_dir(full_name, std::forward<Func>(func)));
} else {
func(entry_name, false);
}
@ -215,14 +215,14 @@ Status walk_path_dir(const std::wstring &dir_name, const Func &func) {
} // namespace detail
template <class Func>
Status walk_path(CSlice path, const Func &func) {
Status walk_path(CSlice path, Func &&func) {
TRY_RESULT(wpath, to_wstring(path));
Slice path_slice = path;
while (!path_slice.empty() && (path_slice.back() == '/' || path_slice.back() == '\\')) {
path_slice.remove_suffix(1);
wpath.pop_back();
}
return detail::walk_path_dir(wpath.c_str(), func);
return detail::walk_path_dir(wpath.c_str(), std::forward<Func>(func));
}
#endif