add checking file types to directory entry
parent
4c0c4e8f41
commit
64a529254c
|
@ -12,7 +12,7 @@ using namespace ostd;
|
||||||
inline void list_dirs(path const &path, int off = 0) {
|
inline void list_dirs(path const &path, int off = 0) {
|
||||||
fs::directory_range ds{path};
|
fs::directory_range ds{path};
|
||||||
for (auto &v: ds) {
|
for (auto &v: ds) {
|
||||||
if (!fs::is_directory(v.path())) {
|
if (!v.is_directory()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for_each(range(off), [](int) { write(' '); });
|
for_each(range(off), [](int) { write(' '); });
|
||||||
|
|
81
ostd/path.hh
81
ostd/path.hh
|
@ -795,7 +795,7 @@ public:
|
||||||
OSTD_EXPORT file_mode mode(path const &p);
|
OSTD_EXPORT file_mode mode(path const &p);
|
||||||
OSTD_EXPORT file_mode symlink_mode(path const &p);
|
OSTD_EXPORT file_mode symlink_mode(path const &p);
|
||||||
|
|
||||||
inline bool is_block_file(file_mode st) {
|
inline bool is_block_file(file_mode st) noexcept {
|
||||||
return st.type() == file_type::block;
|
return st.type() == file_type::block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -803,7 +803,7 @@ inline bool is_block_file(path const &p) {
|
||||||
return is_block_file(mode(p));
|
return is_block_file(mode(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_character_file(file_mode st) {
|
inline bool is_character_file(file_mode st) noexcept {
|
||||||
return st.type() == file_type::character;
|
return st.type() == file_type::character;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -811,7 +811,7 @@ inline bool is_character_file(path const &p) {
|
||||||
return is_character_file(mode(p));
|
return is_character_file(mode(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_directory(file_mode st) {
|
inline bool is_directory(file_mode st) noexcept {
|
||||||
return st.type() == file_type::directory;
|
return st.type() == file_type::directory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -819,7 +819,7 @@ inline bool is_directory(path const &p) {
|
||||||
return is_directory(mode(p));
|
return is_directory(mode(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_regular_file(file_mode st) {
|
inline bool is_regular_file(file_mode st) noexcept {
|
||||||
return st.type() == file_type::regular;
|
return st.type() == file_type::regular;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -827,7 +827,7 @@ inline bool is_regular_file(path const &p) {
|
||||||
return is_regular_file(mode(p));
|
return is_regular_file(mode(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_fifo(file_mode st) {
|
inline bool is_fifo(file_mode st) noexcept {
|
||||||
return st.type() == file_type::fifo;
|
return st.type() == file_type::fifo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -835,7 +835,7 @@ inline bool is_fifo(path const &p) {
|
||||||
return is_fifo(mode(p));
|
return is_fifo(mode(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_symlink(file_mode st) {
|
inline bool is_symlink(file_mode st) noexcept {
|
||||||
return st.type() == file_type::symlink;
|
return st.type() == file_type::symlink;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -843,7 +843,7 @@ inline bool is_symlink(path const &p) {
|
||||||
return is_symlink(mode(p));
|
return is_symlink(mode(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_socket(file_mode st) {
|
inline bool is_socket(file_mode st) noexcept {
|
||||||
return st.type() == file_type::socket;
|
return st.type() == file_type::socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -851,7 +851,7 @@ inline bool is_socket(path const &p) {
|
||||||
return is_socket(mode(p));
|
return is_socket(mode(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_other(file_mode st) {
|
inline bool is_other(file_mode st) noexcept {
|
||||||
return st.type() == file_type::unknown;
|
return st.type() == file_type::unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -859,7 +859,7 @@ inline bool is_other(path const &p) {
|
||||||
return is_other(mode(p));
|
return is_other(mode(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool mode_known(file_mode st) {
|
inline bool mode_known(file_mode st) noexcept {
|
||||||
return st.type() != file_type::none;
|
return st.type() != file_type::none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -867,9 +867,9 @@ inline bool mode_known(path const &p) {
|
||||||
return mode_known(mode(p));
|
return mode_known(mode(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct file_info {
|
struct file_status {
|
||||||
file_info() {}
|
file_status() {}
|
||||||
file_info(ostd::path const &p): p_path(p) {}
|
file_status(ostd::path const &p): p_path(p) {}
|
||||||
|
|
||||||
ostd::path const &path() const noexcept {
|
ostd::path const &path() const noexcept {
|
||||||
return p_path;
|
return p_path;
|
||||||
|
@ -895,9 +895,16 @@ private:
|
||||||
ostd::path p_path{};
|
ostd::path p_path{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
struct dir_range_impl;
|
||||||
|
struct rdir_range_impl;
|
||||||
|
} /* namespace detail */
|
||||||
|
|
||||||
struct directory_entry {
|
struct directory_entry {
|
||||||
directory_entry() {}
|
directory_entry() {}
|
||||||
directory_entry(ostd::path const &p): p_path(p) {}
|
directory_entry(ostd::path const &p): p_path(p) {
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
ostd::path const &path() const noexcept {
|
ostd::path const &path() const noexcept {
|
||||||
return p_path;
|
return p_path;
|
||||||
|
@ -907,8 +914,56 @@ struct directory_entry {
|
||||||
return p_path;
|
return p_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void refresh() {
|
||||||
|
p_type = symlink_mode(p_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_block_file() const noexcept {
|
||||||
|
return fs::is_block_file(p_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_character_file() const noexcept {
|
||||||
|
return fs::is_character_file(p_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_directory() const noexcept {
|
||||||
|
return fs::is_directory(p_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_fifo() const noexcept {
|
||||||
|
return fs::is_fifo(p_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_other() const noexcept {
|
||||||
|
return fs::is_other(p_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_regular_file() const noexcept {
|
||||||
|
return fs::is_regular_file(p_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_socket() const noexcept {
|
||||||
|
return fs::is_socket(p_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_symlink() const noexcept {
|
||||||
|
return fs::is_symlink(p_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool exists() const noexcept {
|
||||||
|
return (mode_known(p_type) && (p_type.type() != file_type::not_found));
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend struct detail::dir_range_impl;
|
||||||
|
friend struct detail::rdir_range_impl;
|
||||||
|
|
||||||
|
directory_entry(ostd::path &&p, file_mode tp):
|
||||||
|
p_path(p), p_type(tp)
|
||||||
|
{}
|
||||||
|
|
||||||
ostd::path p_path{};
|
ostd::path p_path{};
|
||||||
|
file_mode p_type{};
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
|
@ -93,7 +93,9 @@ namespace ostd {
|
||||||
namespace fs {
|
namespace fs {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
static void dir_read_next(DIR *dh, directory_entry &cur, path const &base) {
|
static void dir_read_next(
|
||||||
|
DIR *dh, path &cur, file_mode &tp, path const &base
|
||||||
|
) {
|
||||||
struct dirent d;
|
struct dirent d;
|
||||||
struct dirent *o;
|
struct dirent *o;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -102,7 +104,7 @@ static void dir_read_next(DIR *dh, directory_entry &cur, path const &base) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
if (!o) {
|
if (!o) {
|
||||||
cur = directory_entry{};
|
cur = path{};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
string_range nm{static_cast<char const *>(o->d_name)};
|
string_range nm{static_cast<char const *>(o->d_name)};
|
||||||
|
@ -111,6 +113,14 @@ static void dir_read_next(DIR *dh, directory_entry &cur, path const &base) {
|
||||||
}
|
}
|
||||||
path p{base};
|
path p{base};
|
||||||
p.append(nm);
|
p.append(nm);
|
||||||
|
#ifdef DT_UNKNOWN
|
||||||
|
/* most systems have d_type */
|
||||||
|
file_mode md{mode_to_type(DTTOIF(o->d_type))};
|
||||||
|
#else
|
||||||
|
/* fallback mainly for legacy */
|
||||||
|
file_mode md = symlink_mode(p);
|
||||||
|
#endif
|
||||||
|
tp = md;
|
||||||
cur = std::move(p);
|
cur = std::move(p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -134,7 +144,10 @@ OSTD_EXPORT void dir_range_impl::close() noexcept {
|
||||||
}
|
}
|
||||||
|
|
||||||
OSTD_EXPORT void dir_range_impl::read_next() {
|
OSTD_EXPORT void dir_range_impl::read_next() {
|
||||||
dir_read_next(static_cast<DIR *>(p_handle), p_current, p_dir);
|
path cur;
|
||||||
|
file_mode tp;
|
||||||
|
dir_read_next(static_cast<DIR *>(p_handle), cur, tp, p_dir);
|
||||||
|
p_current = directory_entry{std::move(cur), tp};
|
||||||
}
|
}
|
||||||
|
|
||||||
/* recursive dir range */
|
/* recursive dir range */
|
||||||
|
@ -161,26 +174,29 @@ OSTD_EXPORT void rdir_range_impl::read_next() {
|
||||||
if (p_handles.empty()) {
|
if (p_handles.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
path curd;
|
||||||
|
file_mode tp;
|
||||||
/* can't reuse info from dirent because we need to expand symlinks */
|
/* can't reuse info from dirent because we need to expand symlinks */
|
||||||
if (is_directory(p_current.path())) {
|
if (p_current.is_directory()) {
|
||||||
/* directory, recurse into it and if it contains stuff, return */
|
/* directory, recurse into it and if it contains stuff, return */
|
||||||
DIR *nd = opendir(p_current.path().string().data());
|
DIR *nd = opendir(p_current.path().string().data());
|
||||||
if (!nd) {
|
if (!nd) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
directory_entry based = p_current, curd;
|
directory_entry based = p_current;
|
||||||
dir_read_next(nd, curd, based);
|
dir_read_next(nd, curd, tp, based);
|
||||||
if (!curd.path().empty()) {
|
if (!curd.empty()) {
|
||||||
p_dir = based;
|
p_dir = based;
|
||||||
p_handles.push(nd);
|
p_handles.push(nd);
|
||||||
p_current = curd;
|
p_current = directory_entry{std::move(curd), tp};
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
closedir(nd);
|
closedir(nd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* didn't recurse into a directory, go to next file */
|
/* didn't recurse into a directory, go to next file */
|
||||||
dir_read_next(static_cast<DIR *>(p_handles.top()), p_current, p_dir);
|
dir_read_next(static_cast<DIR *>(p_handles.top()), curd, tp, p_dir);
|
||||||
|
p_current = directory_entry{std::move(curd), tp};
|
||||||
/* end of dir, pop while at it */
|
/* end of dir, pop while at it */
|
||||||
if (p_current.path().empty()) {
|
if (p_current.path().empty()) {
|
||||||
closedir(static_cast<DIR *>(p_handles.top()));
|
closedir(static_cast<DIR *>(p_handles.top()));
|
||||||
|
@ -188,9 +204,8 @@ OSTD_EXPORT void rdir_range_impl::read_next() {
|
||||||
if (!p_handles.empty()) {
|
if (!p_handles.empty()) {
|
||||||
/* got back to another dir, read next so it's valid */
|
/* got back to another dir, read next so it's valid */
|
||||||
p_dir.remove_name();
|
p_dir.remove_name();
|
||||||
dir_read_next(static_cast<DIR *>(p_handles.top()), p_current, p_dir);
|
dir_read_next(static_cast<DIR *>(p_handles.top()), curd, tp, p_dir);
|
||||||
} else {
|
p_current = directory_entry{std::move(curd), tp};
|
||||||
p_current = directory_entry{};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue