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) {
|
||||
fs::directory_range ds{path};
|
||||
for (auto &v: ds) {
|
||||
if (!fs::is_directory(v.path())) {
|
||||
if (!v.is_directory()) {
|
||||
continue;
|
||||
}
|
||||
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 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;
|
||||
}
|
||||
|
||||
|
@ -803,7 +803,7 @@ inline bool is_block_file(path const &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;
|
||||
}
|
||||
|
||||
|
@ -811,7 +811,7 @@ inline bool is_character_file(path const &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;
|
||||
}
|
||||
|
||||
|
@ -819,7 +819,7 @@ inline bool is_directory(path const &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;
|
||||
}
|
||||
|
||||
|
@ -827,7 +827,7 @@ inline bool is_regular_file(path const &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;
|
||||
}
|
||||
|
||||
|
@ -835,7 +835,7 @@ inline bool is_fifo(path const &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;
|
||||
}
|
||||
|
||||
|
@ -843,7 +843,7 @@ inline bool is_symlink(path const &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;
|
||||
}
|
||||
|
||||
|
@ -851,7 +851,7 @@ inline bool is_socket(path const &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;
|
||||
}
|
||||
|
||||
|
@ -859,7 +859,7 @@ inline bool is_other(path const &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;
|
||||
}
|
||||
|
||||
|
@ -867,9 +867,9 @@ inline bool mode_known(path const &p) {
|
|||
return mode_known(mode(p));
|
||||
}
|
||||
|
||||
struct file_info {
|
||||
file_info() {}
|
||||
file_info(ostd::path const &p): p_path(p) {}
|
||||
struct file_status {
|
||||
file_status() {}
|
||||
file_status(ostd::path const &p): p_path(p) {}
|
||||
|
||||
ostd::path const &path() const noexcept {
|
||||
return p_path;
|
||||
|
@ -895,9 +895,16 @@ private:
|
|||
ostd::path p_path{};
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
struct dir_range_impl;
|
||||
struct rdir_range_impl;
|
||||
} /* namespace detail */
|
||||
|
||||
struct 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 {
|
||||
return p_path;
|
||||
|
@ -907,8 +914,56 @@ struct directory_entry {
|
|||
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:
|
||||
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{};
|
||||
file_mode p_type{};
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
|
|
@ -93,7 +93,9 @@ namespace ostd {
|
|||
namespace fs {
|
||||
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 *o;
|
||||
for (;;) {
|
||||
|
@ -102,7 +104,7 @@ static void dir_read_next(DIR *dh, directory_entry &cur, path const &base) {
|
|||
abort();
|
||||
}
|
||||
if (!o) {
|
||||
cur = directory_entry{};
|
||||
cur = path{};
|
||||
return;
|
||||
}
|
||||
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};
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
@ -134,7 +144,10 @@ OSTD_EXPORT void dir_range_impl::close() noexcept {
|
|||
}
|
||||
|
||||
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 */
|
||||
|
@ -161,26 +174,29 @@ OSTD_EXPORT void rdir_range_impl::read_next() {
|
|||
if (p_handles.empty()) {
|
||||
return;
|
||||
}
|
||||
path curd;
|
||||
file_mode tp;
|
||||
/* 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 */
|
||||
DIR *nd = opendir(p_current.path().string().data());
|
||||
if (!nd) {
|
||||
abort();
|
||||
}
|
||||
directory_entry based = p_current, curd;
|
||||
dir_read_next(nd, curd, based);
|
||||
if (!curd.path().empty()) {
|
||||
directory_entry based = p_current;
|
||||
dir_read_next(nd, curd, tp, based);
|
||||
if (!curd.empty()) {
|
||||
p_dir = based;
|
||||
p_handles.push(nd);
|
||||
p_current = curd;
|
||||
p_current = directory_entry{std::move(curd), tp};
|
||||
return;
|
||||
} else {
|
||||
closedir(nd);
|
||||
}
|
||||
}
|
||||
/* 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 */
|
||||
if (p_current.path().empty()) {
|
||||
closedir(static_cast<DIR *>(p_handles.top()));
|
||||
|
@ -188,9 +204,8 @@ OSTD_EXPORT void rdir_range_impl::read_next() {
|
|||
if (!p_handles.empty()) {
|
||||
/* got back to another dir, read next so it's valid */
|
||||
p_dir.remove_name();
|
||||
dir_read_next(static_cast<DIR *>(p_handles.top()), p_current, p_dir);
|
||||
} else {
|
||||
p_current = directory_entry{};
|
||||
dir_read_next(static_cast<DIR *>(p_handles.top()), curd, tp, p_dir);
|
||||
p_current = directory_entry{std::move(curd), tp};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue