#include #include #include #include #include #include static bool should_skip_entry(const char* name, os::Directory::Filter filter) { if (filter == os::Directory::Filter::None) return false; if (filter == os::Directory::Filter::Hidden) return *name == '.'; if (filter == os::Directory::Filter::ParentAndBase) return !strcmp(name, ".") || !strcmp(name, ".."); unreachable(); } namespace os { Result> Directory::open(StringView path) { auto dir = TRY(adopt_shared_if_nonnull(new (std::nothrow) Directory({}))); DIR* dp = opendir(path.chars()); if (!dp) return err(errno); dir->m_dirp = dp; return dir; } Result> Directory::openat(int dirfd, StringView path) { auto dir = TRY(adopt_shared_if_nonnull(new (std::nothrow) Directory({}))); long rc = syscall(SYS_openat, dirfd, path.chars(), O_RDONLY | O_DIRECTORY, 0); int fd = TRY(Result::from_syscall(rc)); DIR* dp = fdopendir(fd); if (!dp) { close(fd); return err(errno); } dir->m_dirp = dp; return dir; } Result Directory::next(Filter filter) { errno = 0; struct dirent* ent; do { ent = readdir(m_dirp); } while (ent && should_skip_entry(ent->d_name, filter)); if (!ent && errno) return err(errno); if (!ent) return String {}; return String::from_cstring(ent->d_name); } Directory::~Directory() { if (m_dirp) closedir(m_dirp); } Directory::Directory(Badge) { } }