From 3eb78aa5f34398d65fad56e6fe66b19b29401c3b Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 3 May 2023 17:37:26 +0200 Subject: [PATCH] libos+init: Add a new Path class to handle both file descriptors and file paths --- apps/init.cpp | 10 +++------- libos/CMakeLists.txt | 1 + libos/include/os/Directory.h | 5 ++--- libos/include/os/File.h | 9 +++++---- libos/include/os/FileSystem.h | 11 +++++------ libos/include/os/Path.h | 36 +++++++++++++++++++++++++++++++++++ libos/src/Directory.cpp | 17 +++-------------- libos/src/File.cpp | 10 +++++----- libos/src/FileSystem.cpp | 32 +++++++++++-------------------- libos/src/Path.cpp | 20 +++++++++++++++++++ 10 files changed, 91 insertions(+), 60 deletions(-) create mode 100644 libos/include/os/Path.h create mode 100644 libos/src/Path.cpp diff --git a/apps/init.cpp b/apps/init.cpp index 716fa3ed..2b23681b 100644 --- a/apps/init.cpp +++ b/apps/init.cpp @@ -132,9 +132,9 @@ static void start_service(Service& service) } } -static Result load_service(StringView path) +static Result load_service(const os::Path& path) { - fprintf(g_init_log, "[init] reading service file: %s\n", path.chars()); + fprintf(g_init_log, "[init] reading service file: %s\n", path.name().chars()); auto file = TRY(os::File::open(path, os::File::ReadOnly)); @@ -242,11 +242,7 @@ static Result load_services() auto services = TRY(dir->list(os::Directory::Filter::ParentAndBase)); sort(services.begin(), services.end(), String::compare); - for (const auto& entry : services) - { - auto service_path = TRY(PathParser::join("/etc/init"_sv, entry.view())); - TRY(load_service(service_path.view())); - } + for (const auto& entry : services) TRY(load_service({ dir->fd(), entry.view() })); return {}; } diff --git a/libos/CMakeLists.txt b/libos/CMakeLists.txt index 0e9b441d..b4872abe 100644 --- a/libos/CMakeLists.txt +++ b/libos/CMakeLists.txt @@ -10,6 +10,7 @@ set(SOURCES src/Process.cpp src/Directory.cpp src/Main.cpp + src/Path.cpp ) add_library(os ${SOURCES}) diff --git a/libos/include/os/Directory.h b/libos/include/os/Directory.h index e8d12657..6f295ff0 100644 --- a/libos/include/os/Directory.h +++ b/libos/include/os/Directory.h @@ -3,15 +3,14 @@ #include #include #include +#include namespace os { class Directory { public: - static Result> open(StringView path); - - static Result> openat(int dirfd, StringView path); + static Result> open(const Path& path); enum class Filter { diff --git a/libos/include/os/File.h b/libos/include/os/File.h index 7f9f9156..74144933 100644 --- a/libos/include/os/File.h +++ b/libos/include/os/File.h @@ -4,6 +4,7 @@ #include #include #include +#include #include namespace os @@ -20,9 +21,9 @@ namespace os ReadAppend = O_RDWR | O_APPEND, }; - static Result> open(StringView path, OpenMode flags); - static Result> open_or_create(StringView path, OpenMode flags, mode_t mode = 0644); - static Result> create(StringView path, OpenMode flags, mode_t mode = 0644); + static Result> open(const Path& path, OpenMode flags); + static Result> open_or_create(const Path& path, OpenMode flags, mode_t mode = 0644); + static Result> create(const Path& path, OpenMode flags, mode_t mode = 0644); /* If path is "-", return standard input (as is common for many CLI apps). Otherwise, open path for reading. @@ -58,7 +59,7 @@ namespace os ~File(); private: - static Result> construct(StringView path, int flags, mode_t mode); + static Result> construct(const Path& path, int flags, mode_t mode); static void initialize_standard_streams(); Result raw_read(u8* buf, usize length); diff --git a/libos/include/os/FileSystem.h b/libos/include/os/FileSystem.h index 2e2c1d2c..4bca16dc 100644 --- a/libos/include/os/FileSystem.h +++ b/libos/include/os/FileSystem.h @@ -1,23 +1,22 @@ #pragma once #include #include +#include #include namespace os { namespace FileSystem { - bool exists(StringView path); + bool exists(const Path& path); - bool is_directory(StringView path); + bool is_directory(const Path& path); Result create_directory(StringView path, mode_t mode); - Result remove(StringView path); - Result removeat(int dirfd, StringView path); + Result remove(const Path& path); - Result remove_tree(StringView path); - Result remove_tree_at(int dirfd, StringView path); + Result remove_tree(const Path& path); Result working_directory(); Result home_directory(); diff --git a/libos/include/os/Path.h b/libos/include/os/Path.h new file mode 100644 index 00000000..f6dfd1d1 --- /dev/null +++ b/libos/include/os/Path.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include + +namespace os +{ + class Path + { + public: + Path(const char* path); + Path(StringView path); + Path(int fd); + Path(int dirfd, StringView name); + + int dirfd() const + { + return m_dirfd.value_or(AT_FDCWD); + } + + StringView name() const + { + return m_name.value_or(""_sv); + } + + int is_empty_path() const + { + if (m_dirfd.has_value() && !m_name.has_value()) return AT_EMPTY_PATH; + + return 0; + } + + private: + Option m_dirfd; + Option m_name; + }; +} diff --git a/libos/src/Directory.cpp b/libos/src/Directory.cpp index 03faebc0..55c599f0 100644 --- a/libos/src/Directory.cpp +++ b/libos/src/Directory.cpp @@ -18,23 +18,12 @@ static bool should_skip_entry(const char* name, os::Directory::Filter filter) namespace os { - Result> Directory::open(StringView path) + + Result> Directory::open(const Path& 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); + long rc = syscall(SYS_openat, path.dirfd(), path.name().chars(), O_RDONLY | O_DIRECTORY, 0); int fd = TRY(Result::from_syscall(rc)); DIR* dp = fdopendir(fd); diff --git a/libos/src/File.cpp b/libos/src/File.cpp index 33c1dd49..0c8fe70e 100644 --- a/libos/src/File.cpp +++ b/libos/src/File.cpp @@ -55,11 +55,11 @@ namespace os return g_stderr; } - Result> File::construct(StringView path, int flags, mode_t mode) + Result> File::construct(const Path& path, int flags, mode_t mode) { auto file = TRY(adopt_shared_if_nonnull(new (std::nothrow) File({}))); - long rc = syscall(SYS_openat, AT_FDCWD, path.chars(), flags, mode); + long rc = syscall(SYS_openat, path.dirfd(), path.name().chars(), flags, mode); int fd = TRY(Result::from_syscall(rc)); file->m_fd = fd; @@ -67,17 +67,17 @@ namespace os return file; } - Result> File::open(StringView path, OpenMode flags) + Result> File::open(const Path& path, OpenMode flags) { return construct(path, (int)flags, 0); } - Result> File::open_or_create(StringView path, OpenMode flags, mode_t mode) + Result> File::open_or_create(const Path& path, OpenMode flags, mode_t mode) { return construct(path, (int)flags | O_CREAT, mode); } - Result> File::create(StringView path, OpenMode flags, mode_t mode) + Result> File::create(const Path& path, OpenMode flags, mode_t mode) { return construct(path, (int)flags | (O_CREAT | O_EXCL), mode); } diff --git a/libos/src/FileSystem.cpp b/libos/src/FileSystem.cpp index 8a1e35fb..01793e01 100644 --- a/libos/src/FileSystem.cpp +++ b/libos/src/FileSystem.cpp @@ -12,20 +12,20 @@ namespace os::FileSystem { - bool exists(StringView path) + bool exists(const Path& path) { struct stat st; - if (stat(path.chars(), &st) < 0) return false; + if (fstatat(path.dirfd(), path.name().chars(), &st, path.is_empty_path()) < 0) return false; return true; } - bool is_directory(StringView path) + bool is_directory(const Path& path) { struct stat st; - if (stat(path.chars(), &st) < 0) return false; + if (fstatat(path.dirfd(), path.name().chars(), &st, path.is_empty_path()) < 0) return false; return S_ISDIR(st.st_mode); } @@ -37,36 +37,26 @@ namespace os::FileSystem return Result::from_syscall(rc); } - Result remove(StringView path) + Result remove(const Path& path) { - return removeat(AT_FDCWD, path); - } - - Result removeat(int dirfd, StringView path) - { - long rc = syscall(SYS_unlinkat, dirfd, path.chars(), 0); + long rc = syscall(SYS_unlinkat, path.dirfd(), path.name().chars(), 0); return Result::from_syscall(rc); } - Result remove_tree(StringView path) + Result remove_tree(const Path& path) { - return remove_tree_at(AT_FDCWD, path); - } - - Result remove_tree_at(int dirfd, StringView path) - { - auto rc = removeat(dirfd, path); + auto rc = remove(path); if (!rc.has_error()) return {}; if (rc.error() != ENOTEMPTY) return rc.release_error(); - auto dir = TRY(os::Directory::openat(dirfd, path)); + auto dir = TRY(os::Directory::open(path)); Vector entries = TRY(dir->list(os::Directory::Filter::ParentAndBase)); - for (const auto& entry : entries) { TRY(remove_tree_at(dir->fd(), entry.view())); } + for (const auto& entry : entries) { TRY(remove_tree({ dir->fd(), entry.view() })); } - return removeat(dirfd, path); + return remove(path); } Result working_directory() diff --git a/libos/src/Path.cpp b/libos/src/Path.cpp new file mode 100644 index 00000000..2575b721 --- /dev/null +++ b/libos/src/Path.cpp @@ -0,0 +1,20 @@ +#include + +namespace os +{ + Path::Path(const char* path) : m_dirfd(), m_name(path) + { + } + + Path::Path(StringView path) : m_dirfd(), m_name(path) + { + } + + Path::Path(int fd) : m_dirfd(fd), m_name() + { + } + + Path::Path(int dirfd, StringView name) : m_dirfd(dirfd), m_name(name) + { + } +}