Compare commits
No commits in common. "cb0d5cb6a1a231093fb40b4d50e93df00fe9c8d6" and "64f9e9dcde714d846841a57298ada51fc81c4879" have entirely different histories.
cb0d5cb6a1
...
64f9e9dcde
30
apps/rm.cpp
30
apps/rm.cpp
@ -1,35 +1,10 @@
|
|||||||
#include <os/ArgumentParser.h>
|
#include <os/ArgumentParser.h>
|
||||||
#include <os/Directory.h>
|
|
||||||
#include <os/File.h>
|
|
||||||
#include <os/FileSystem.h>
|
#include <os/FileSystem.h>
|
||||||
|
|
||||||
Result<void> remove_wrapper(const os::Path& path, bool verbose)
|
|
||||||
{
|
|
||||||
TRY(os::FileSystem::remove(path));
|
|
||||||
if (verbose) os::println("removed '%s'", path.name().chars());
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<void> remove_tree(const os::Path& path, bool verbose)
|
|
||||||
{
|
|
||||||
auto rc = remove_wrapper(path, verbose);
|
|
||||||
if (!rc.has_error()) return {};
|
|
||||||
if (rc.error() != ENOTEMPTY) return rc.release_error();
|
|
||||||
|
|
||||||
auto dir = TRY(os::Directory::open(path));
|
|
||||||
|
|
||||||
Vector<String> entries = TRY(dir->list_names(os::Directory::Filter::ParentAndBase));
|
|
||||||
|
|
||||||
for (const auto& entry : entries) { TRY(remove_tree({ dir->fd(), entry.view() }, verbose)); }
|
|
||||||
|
|
||||||
return remove_wrapper(path, verbose);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<int> luna_main(int argc, char** argv)
|
Result<int> luna_main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
StringView path;
|
StringView path;
|
||||||
bool recursive;
|
bool recursive;
|
||||||
bool verbose;
|
|
||||||
|
|
||||||
os::ArgumentParser parser;
|
os::ArgumentParser parser;
|
||||||
parser.add_description("Remove a path from the file system."_sv);
|
parser.add_description("Remove a path from the file system."_sv);
|
||||||
@ -37,12 +12,11 @@ Result<int> luna_main(int argc, char** argv)
|
|||||||
parser.add_positional_argument(path, "path"_sv, true);
|
parser.add_positional_argument(path, "path"_sv, true);
|
||||||
parser.add_switch_argument(recursive, 'r', "recursive"_sv,
|
parser.add_switch_argument(recursive, 'r', "recursive"_sv,
|
||||||
"remove a directory recursively (by default, rm removes only empty directories)"_sv);
|
"remove a directory recursively (by default, rm removes only empty directories)"_sv);
|
||||||
parser.add_switch_argument(verbose, 'v', "verbose"_sv, "log every removed file and directory"_sv);
|
|
||||||
parser.parse(argc, argv);
|
parser.parse(argc, argv);
|
||||||
|
|
||||||
if (!recursive) TRY(remove_wrapper(path, verbose));
|
if (!recursive) TRY(os::FileSystem::remove(path));
|
||||||
else
|
else
|
||||||
TRY(remove_tree(path, verbose));
|
TRY(os::FileSystem::remove_tree(path));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -68,6 +68,15 @@ namespace os
|
|||||||
*/
|
*/
|
||||||
Result<void> remove(const Path& path);
|
Result<void> remove(const Path& path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Remove a directory tree from the file system recursively, deleting subfiles and subdirectories as
|
||||||
|
* well.
|
||||||
|
*
|
||||||
|
* @param path The path to remove.
|
||||||
|
* @return Result<void> Whether the operation succeeded.
|
||||||
|
*/
|
||||||
|
Result<void> remove_tree(const Path& path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read the target of a symbolic link.
|
* @brief Read the target of a symbolic link.
|
||||||
*
|
*
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <luna/CString.h>
|
#include <luna/CString.h>
|
||||||
#include <os/Directory.h>
|
#include <os/Directory.h>
|
||||||
#include <os/FileSystem.h>
|
#include <os/FileSystem.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
static bool should_skip_entry(const char* name, os::Directory::Filter filter)
|
static bool should_skip_entry(const char* name, os::Directory::Filter filter)
|
||||||
@ -32,8 +33,8 @@ namespace os
|
|||||||
{
|
{
|
||||||
auto dir = TRY(adopt_shared_if_nonnull(new (std::nothrow) Directory({})));
|
auto dir = TRY(adopt_shared_if_nonnull(new (std::nothrow) Directory({})));
|
||||||
|
|
||||||
int fd = openat(path.dirfd(), path.name().chars(), O_RDONLY | O_DIRECTORY, 0);
|
long rc = syscall(SYS_openat, path.dirfd(), path.name().chars(), O_RDONLY | O_DIRECTORY, 0);
|
||||||
if (fd < 0) return err(errno);
|
int fd = TRY(Result<int>::from_syscall(rc));
|
||||||
|
|
||||||
DIR* dp = fdopendir(fd);
|
DIR* dp = fdopendir(fd);
|
||||||
if (!dp)
|
if (!dp)
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <luna/StringBuilder.h>
|
#include <luna/StringBuilder.h>
|
||||||
#include <os/File.h>
|
#include <os/File.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
static SharedPtr<os::File> g_stdin = {};
|
static SharedPtr<os::File> g_stdin = {};
|
||||||
@ -82,8 +83,8 @@ namespace os
|
|||||||
{
|
{
|
||||||
auto file = TRY(adopt_shared_if_nonnull(new (std::nothrow) File({})));
|
auto file = TRY(adopt_shared_if_nonnull(new (std::nothrow) File({})));
|
||||||
|
|
||||||
int fd = openat(path.dirfd(), path.name().chars(), flags, mode);
|
long rc = syscall(SYS_openat, path.dirfd(), path.name().chars(), flags, mode);
|
||||||
if (fd < 0) return err(errno);
|
int fd = TRY(Result<int>::from_syscall(rc));
|
||||||
|
|
||||||
file->m_file = fdopen(fd, stdio_mode_from_openmode(flags));
|
file->m_file = fdopen(fd, stdio_mode_from_openmode(flags));
|
||||||
if (!file->m_file) return err(errno);
|
if (!file->m_file) return err(errno);
|
||||||
|
@ -10,13 +10,13 @@
|
|||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <luna/Buffer.h>
|
|
||||||
#include <luna/PathParser.h>
|
#include <luna/PathParser.h>
|
||||||
#include <luna/String.h>
|
#include <luna/String.h>
|
||||||
#include <os/Directory.h>
|
#include <os/Directory.h>
|
||||||
#include <os/FileSystem.h>
|
#include <os/FileSystem.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
namespace os::FileSystem
|
namespace os::FileSystem
|
||||||
@ -41,26 +41,39 @@ namespace os::FileSystem
|
|||||||
|
|
||||||
Result<void> stat(const Path& path, struct stat& st, bool follow_symlinks)
|
Result<void> stat(const Path& path, struct stat& st, bool follow_symlinks)
|
||||||
{
|
{
|
||||||
int rc = fstatat(path.dirfd(), path.name().chars(), &st,
|
long rc = syscall(SYS_fstatat, path.dirfd(), path.name().chars(), &st,
|
||||||
(int)(path.is_empty_path() | (follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW)));
|
(int)(path.is_empty_path() | (follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW)));
|
||||||
|
|
||||||
if (rc < 0) return err(errno);
|
return Result<void>::from_syscall(rc);
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void> create_directory(StringView path, mode_t mode)
|
Result<void> create_directory(StringView path, mode_t mode)
|
||||||
{
|
{
|
||||||
int rc = mkdir(path.chars(), mode);
|
long rc = syscall(SYS_mkdir, path.chars(), mode);
|
||||||
if (rc < 0) return err(errno);
|
|
||||||
return {};
|
return Result<void>::from_syscall(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void> remove(const Path& path)
|
Result<void> remove(const Path& path)
|
||||||
{
|
{
|
||||||
// FIXME: This will not work on many operating systems that require rmdir() for directories.
|
long rc = syscall(SYS_unlinkat, path.dirfd(), path.name().chars(), 0);
|
||||||
int rc = unlinkat(path.dirfd(), path.name().chars(), 0);
|
|
||||||
if (rc < 0) return err(errno);
|
return Result<void>::from_syscall(rc);
|
||||||
return {};
|
}
|
||||||
|
|
||||||
|
Result<void> remove_tree(const Path& path)
|
||||||
|
{
|
||||||
|
auto rc = remove(path);
|
||||||
|
if (!rc.has_error()) return {};
|
||||||
|
if (rc.error() != ENOTEMPTY) return rc.release_error();
|
||||||
|
|
||||||
|
auto dir = TRY(os::Directory::open(path));
|
||||||
|
|
||||||
|
Vector<String> entries = TRY(dir->list_names(os::Directory::Filter::ParentAndBase));
|
||||||
|
|
||||||
|
for (const auto& entry : entries) { TRY(remove_tree({ dir->fd(), entry.view() })); }
|
||||||
|
|
||||||
|
return remove(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<String> readlink(const Path& path)
|
Result<String> readlink(const Path& path)
|
||||||
@ -69,13 +82,14 @@ namespace os::FileSystem
|
|||||||
TRY(stat(path, st, false));
|
TRY(stat(path, st, false));
|
||||||
if (!S_ISLNK(st.st_mode)) return String {};
|
if (!S_ISLNK(st.st_mode)) return String {};
|
||||||
|
|
||||||
Buffer buf = TRY(Buffer::create_sized(st.st_size + 1));
|
char* buf = (char*)TRY(calloc_impl(st.st_size + 1, 1));
|
||||||
memset(buf.data(), 0, buf.size());
|
auto guard = make_scope_guard([buf] { free_impl(buf); });
|
||||||
|
usize nread = TRY(
|
||||||
|
Result<usize>::from_syscall(syscall(SYS_readlinkat, path.dirfd(), path.name().chars(), buf, st.st_size)));
|
||||||
|
|
||||||
ssize_t nread = readlinkat(path.dirfd(), path.name().chars(), (char*)buf.data(), st.st_size);
|
guard.deactivate();
|
||||||
if (nread < 0) return err(errno);
|
|
||||||
|
|
||||||
return String { (char*)buf.release_data(), (usize)nread };
|
return String { buf, nread };
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<String> working_directory()
|
Result<String> working_directory()
|
||||||
@ -98,8 +112,8 @@ namespace os::FileSystem
|
|||||||
|
|
||||||
Result<void> change_directory(StringView path)
|
Result<void> change_directory(StringView path)
|
||||||
{
|
{
|
||||||
int rc = chdir(path.chars());
|
long rc = syscall(SYS_chdir, path.chars());
|
||||||
if (rc < 0) return err(errno);
|
|
||||||
return {};
|
return Result<void>::from_syscall(rc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <os/Process.h>
|
#include <os/Process.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
extern char** environ;
|
extern char** environ;
|
||||||
@ -19,9 +19,8 @@ namespace os
|
|||||||
{
|
{
|
||||||
Result<pid_t> Process::fork()
|
Result<pid_t> Process::fork()
|
||||||
{
|
{
|
||||||
pid_t pid = ::fork();
|
long rc = syscall(SYS_fork);
|
||||||
if (pid < 0) return err(errno);
|
return Result<pid_t>::from_syscall(rc);
|
||||||
return pid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void> Process::exec(StringView path, Slice<String> args, bool search_in_path)
|
Result<void> Process::exec(StringView path, Slice<String> args, bool search_in_path)
|
||||||
@ -122,16 +121,14 @@ namespace os
|
|||||||
|
|
||||||
Result<pid_t> Process::wait(pid_t child, int* status, int options)
|
Result<pid_t> Process::wait(pid_t child, int* status, int options)
|
||||||
{
|
{
|
||||||
pid_t pid = waitpid(child, status, options);
|
long rc = syscall(SYS_waitpid, child, status, options);
|
||||||
if (pid < 0) return err(errno);
|
return Result<pid_t>::from_syscall(rc);
|
||||||
return pid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void> Process::kill(pid_t pid, int signo)
|
Result<void> Process::kill(pid_t pid, int signo)
|
||||||
{
|
{
|
||||||
int rc = ::kill(pid, signo);
|
long rc = syscall(SYS_kill, pid, signo);
|
||||||
if (rc < 0) return err(errno);
|
return Result<void>::from_syscall(rc);
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[[noreturn]] void Process::exit(int status)
|
[[noreturn]] void Process::exit(int status)
|
||||||
|
Loading…
Reference in New Issue
Block a user