diff --git a/apps/init.cpp b/apps/init.cpp index 76634064..132aebf0 100644 --- a/apps/init.cpp +++ b/apps/init.cpp @@ -239,8 +239,9 @@ static Result load_services() { auto dir = TRY(os::Directory::open("/etc/init")); - String entry; - while ((entry = TRY(dir->next(os::Directory::Filter::ParentAndBase))), !entry.is_empty()) + auto services = TRY(dir->list(os::Directory::Filter::ParentAndBase)); + + for (const auto& entry : services) { auto service_path = TRY(PathParser::join("/etc/init"_sv, entry.view())); TRY(load_service(service_path.view())); diff --git a/apps/ls.cpp b/apps/ls.cpp index 72820193..7955101f 100644 --- a/apps/ls.cpp +++ b/apps/ls.cpp @@ -25,13 +25,14 @@ Result luna_main(int argc, char** argv) else if (show_all) filter = os::Directory::Filter::None; + auto files = TRY(dir->list(filter)); + int first_ent = 1; - do { - auto ent = TRY(dir->next(filter)); - if (ent.is_empty()) break; - printf(first_ent ? "%s" : " %s", ent.chars()); + for (const auto& file : files) + { + printf(first_ent ? "%s" : " %s", file.chars()); first_ent = 0; - } while (1); + } putchar('\n'); diff --git a/libc/include/dirent.h b/libc/include/dirent.h index 07c8566d..8ed95bab 100644 --- a/libc/include/dirent.h +++ b/libc/include/dirent.h @@ -26,6 +26,7 @@ extern "C" struct dirent* readdir(DIR* stream); int closedir(DIR* stream); int dirfd(DIR* stream); + void rewinddir(DIR* stream); #ifdef __cplusplus } diff --git a/libc/src/dirent.cpp b/libc/src/dirent.cpp index cf81dceb..c58256f9 100644 --- a/libc/src/dirent.cpp +++ b/libc/src/dirent.cpp @@ -66,4 +66,9 @@ extern "C" { return stream->_fd; } + + void rewinddir(DIR* stream) + { + lseek(stream->_fd, 0, SEEK_SET); + } } diff --git a/libos/include/os/Directory.h b/libos/include/os/Directory.h index eaa68d9c..e8d12657 100644 --- a/libos/include/os/Directory.h +++ b/libos/include/os/Directory.h @@ -2,6 +2,7 @@ #include #include #include +#include namespace os { @@ -21,6 +22,10 @@ namespace os Result next(Filter filter); + Result> list(Filter filter); + + void rewind(); + int fd() { return dirfd(m_dirp); diff --git a/libos/src/Directory.cpp b/libos/src/Directory.cpp index 5003ae25..bd0dfc2f 100644 --- a/libos/src/Directory.cpp +++ b/libos/src/Directory.cpp @@ -66,6 +66,23 @@ namespace os return String::from_cstring(ent->d_name); } + Result> Directory::list(Filter filter) + { + Vector result; + + rewind(); + + String entry {}; + while ((entry = TRY(next(filter))), !entry.is_empty()) TRY(result.try_append(move(entry))); + + return result; + } + + void Directory::rewind() + { + rewinddir(m_dirp); + } + Directory::~Directory() { if (m_dirp) closedir(m_dirp); diff --git a/libos/src/FileSystem.cpp b/libos/src/FileSystem.cpp index a2c1a9a7..e7c7400f 100644 --- a/libos/src/FileSystem.cpp +++ b/libos/src/FileSystem.cpp @@ -63,16 +63,7 @@ namespace os::FileSystem auto dir = TRY(os::Directory::openat(dirfd, path)); - Vector entries; - - // FIXME: This is done because the kernel doesn't appreciate us deleting entries while iterating over - // directories. This means that we have to iterate first, then delete. - - String ent; - while ((ent = TRY(dir->next(os::Directory::Filter::ParentAndBase))), !ent.is_empty()) - { - TRY(entries.try_append(move(ent))); - } + Vector entries = TRY(dir->list(os::Directory::Filter::ParentAndBase)); for (const auto& entry : entries) { TRY(remove_tree_at(dir->fd(), entry.view())); }