libos+rm: Add recursive removal of directories
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
apio 2023-04-19 18:20:44 +02:00
parent 05144f65d1
commit d56e8baca5
Signed by: apio
GPG Key ID: B8A7D06E42258954
3 changed files with 50 additions and 2 deletions

View File

@ -4,12 +4,16 @@
Result<int> luna_main(int argc, char** argv)
{
StringView path;
bool recursive;
os::ArgumentParser parser;
parser.add_positional_argument(path, "path"_sv, true);
parser.add_switch_argument(recursive, 'r', "recursive"_sv);
parser.parse(argc, argv);
TRY(os::FileSystem::remove(path));
if (!recursive) TRY(os::FileSystem::remove(path));
else
TRY(os::FileSystem::remove_tree(path));
return 0;
}

View File

@ -14,6 +14,10 @@ namespace os
Result<void> create_directory(StringView path, mode_t mode);
Result<void> remove(StringView path);
Result<void> removeat(int dirfd, StringView path);
Result<void> remove_tree(StringView path);
Result<void> remove_tree_at(int dirfd, StringView path);
Result<String> working_directory();
Result<String> home_directory();

View File

@ -1,6 +1,7 @@
#include <luna/String.h>
#include <os/FileSystem.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
@ -38,11 +39,50 @@ namespace os::FileSystem
Result<void> remove(StringView path)
{
long rc = syscall(SYS_unlinkat, AT_FDCWD, path.chars(), 0);
return removeat(AT_FDCWD, path);
}
Result<void> removeat(int dirfd, StringView path)
{
long rc = syscall(SYS_unlinkat, dirfd, path.chars(), 0);
return Result<void>::from_syscall(rc);
}
Result<void> remove_tree(StringView path)
{
return remove_tree_at(AT_FDCWD, path);
}
Result<void> remove_tree_at(int dirfd, StringView path)
{
auto rc = removeat(dirfd, path);
if (!rc.has_error()) return {};
if (rc.error() != ENOTEMPTY) return rc.release_error();
DIR* dp = opendir(path.chars());
if (!dp) return err(errno);
Vector<String> 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.
struct dirent* ent;
while ((ent = readdir(dp)))
{
if ("."_sv == ent->d_name || ".."_sv == ent->d_name) continue;
auto entry = TRY(String::from_cstring(ent->d_name));
TRY(entries.try_append(move(entry)));
}
for (const auto& entry : entries) { TRY(remove_tree_at(dp->_fd, entry.view())); }
closedir(dp);
return removeat(dirfd, path);
}
Result<String> working_directory()
{
char* ptr = getcwd(NULL, 0);