78 lines
1.7 KiB
C++
78 lines
1.7 KiB
C++
#include <luna/CString.h>
|
|
#include <os/Directory.h>
|
|
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <sys/syscall.h>
|
|
#include <unistd.h>
|
|
|
|
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<SharedPtr<Directory>> 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<SharedPtr<Directory>> 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<int>::from_syscall(rc));
|
|
|
|
DIR* dp = fdopendir(fd);
|
|
if (!dp)
|
|
{
|
|
close(fd);
|
|
return err(errno);
|
|
}
|
|
|
|
dir->m_dirp = dp;
|
|
|
|
return dir;
|
|
}
|
|
|
|
Result<String> 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<Directory>)
|
|
{
|
|
}
|
|
}
|