aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kapi/kapi/filesystem.hpp6
-rw-r--r--kernel/kapi/filesystem.cpp5
-rw-r--r--kernel/kernel/filesystem/device_inode.cpp15
-rw-r--r--kernel/kernel/filesystem/device_inode.hpp5
-rw-r--r--kernel/kernel/filesystem/device_inode.tests.cpp51
-rw-r--r--kernel/kernel/filesystem/ext2/inode.cpp32
-rw-r--r--kernel/kernel/filesystem/ext2/inode.hpp7
-rw-r--r--kernel/kernel/filesystem/inode.cpp46
-rw-r--r--kernel/kernel/filesystem/inode.hpp14
-rw-r--r--kernel/kernel/filesystem/vfs.cpp11
-rw-r--r--kernel/kernel/filesystem/vfs.hpp5
-rw-r--r--kernel/kernel/test_support/filesystem/filesystem.cpp5
-rw-r--r--kernel/kernel/test_support/filesystem/filesystem.hpp5
13 files changed, 203 insertions, 4 deletions
diff --git a/kapi/kapi/filesystem.hpp b/kapi/kapi/filesystem.hpp
index 2b5dc827..56bb295f 100644
--- a/kapi/kapi/filesystem.hpp
+++ b/kapi/kapi/filesystem.hpp
@@ -80,6 +80,12 @@ namespace kapi::filesystem
//! @return Nothing on success, an error on failure.
auto create(std::string_view path) -> kstd::result<void>;
+ //! Get the status information for the file at a given path.
+ //!
+ //! @param path The path to the file to query information for.
+ //! @return A populated file status object on success, an error otherwise.
+ auto status(std::string_view path) -> kstd::result<file_status>;
+
//! @}
} // namespace kapi::filesystem
diff --git a/kernel/kapi/filesystem.cpp b/kernel/kapi/filesystem.cpp
index b2f94747..10c9835a 100644
--- a/kernel/kapi/filesystem.cpp
+++ b/kernel/kapi/filesystem.cpp
@@ -68,4 +68,9 @@ namespace kapi::filesystem
return kernel::filesystem::vfs::get().create(path);
}
+ auto status(std::string_view path) -> kstd::result<file_status>
+ {
+ return kernel::filesystem::vfs::get().status(path);
+ }
+
} // namespace kapi::filesystem \ No newline at end of file
diff --git a/kernel/kernel/filesystem/device_inode.cpp b/kernel/kernel/filesystem/device_inode.cpp
index 464c5ea9..5ac18019 100644
--- a/kernel/kernel/filesystem/device_inode.cpp
+++ b/kernel/kernel/filesystem/device_inode.cpp
@@ -1,16 +1,21 @@
#include <kernel/filesystem/device_inode.hpp>
#include <kernel/devices/block_device_utils.hpp>
+#include <kernel/filesystem/device_number_registry.hpp>
#include <kernel/filesystem/error.hpp>
+#include <kernel/filesystem/inode.hpp>
#include <kapi/devices.hpp>
#include <kapi/devices/device.hpp>
+#include <kapi/filesystem.hpp>
#include <kapi/system.hpp>
#include <kstd/memory.hpp>
#include <kstd/result.hpp>
#include <kstd/units.hpp>
+#include <optional>
+
namespace kernel::filesystem
{
device_inode::device_inode(kstd::shared_ptr<kapi::devices::device> const & device)
@@ -54,4 +59,14 @@ namespace kernel::filesystem
return true;
}
+ auto device_inode::raw_device() const -> std::optional<kapi::filesystem::device_number>
+ {
+ if (auto number = device_number_registry::get().number_of(*m_device))
+ {
+ return *number;
+ }
+
+ return std::nullopt;
+ }
+
} // namespace kernel::filesystem \ No newline at end of file
diff --git a/kernel/kernel/filesystem/device_inode.hpp b/kernel/kernel/filesystem/device_inode.hpp
index be9fc577..698124f2 100644
--- a/kernel/kernel/filesystem/device_inode.hpp
+++ b/kernel/kernel/filesystem/device_inode.hpp
@@ -4,11 +4,14 @@
#include <kernel/filesystem/inode.hpp>
#include <kapi/devices/device.hpp>
+#include <kapi/filesystem.hpp>
#include <kstd/memory.hpp>
#include <kstd/result.hpp>
#include <kstd/units.hpp>
+#include <optional>
+
namespace kernel::filesystem
{
/**
@@ -58,6 +61,8 @@ namespace kernel::filesystem
*/
[[nodiscard]] auto is_block_device() const -> bool override;
+ [[nodiscard]] auto raw_device() const -> std::optional<kapi::filesystem::device_number> override;
+
private:
kstd::shared_ptr<kapi::devices::device> m_device;
};
diff --git a/kernel/kernel/filesystem/device_inode.tests.cpp b/kernel/kernel/filesystem/device_inode.tests.cpp
index e821ce1d..4c6e0338 100644
--- a/kernel/kernel/filesystem/device_inode.tests.cpp
+++ b/kernel/kernel/filesystem/device_inode.tests.cpp
@@ -1,11 +1,18 @@
#include <kernel/filesystem/device_inode.hpp>
+#include <kernel/filesystem/device_number_registry.hpp>
+#include <kernel/filesystem/inode.hpp>
#include <kernel/test_support/cpu.hpp>
#include <kernel/test_support/devices/block_device.hpp>
#include <kernel/test_support/devices/character_device.hpp>
+#include <kernel/test_support/filesystem/device_number_registry.hpp>
+
+#include <kapi/devices.hpp>
+#include <kapi/filesystem.hpp>
#include <kstd/memory.hpp>
#include <kstd/print.hpp>
+#include <kstd/result.hpp>
#include <kstd/system_error.hpp>
#include <kstd/units.hpp>
#include <kstd/vector.hpp>
@@ -17,6 +24,17 @@
using namespace kstd::units_literals;
+namespace
+{
+ struct registry_reset_guard
+ {
+ ~registry_reset_guard()
+ {
+ kernel::tests::filesystem::device_number_registry::deinit();
+ }
+ };
+} // namespace
+
SCENARIO("Device inode construction", "[filesystem][device_inode]")
{
GIVEN("a block device")
@@ -117,3 +135,36 @@ SCENARIO("Device inode read/write with a non-block device", "[filesystem][device
}
}
}
+
+SCENARIO("Device inode raw_device()", "[filesystem][device-inode]")
+{
+ auto resetter = registry_reset_guard{};
+
+ GIVEN("A block device that has been published and numbered")
+ {
+ auto device = kstd::make_shared<kernel::tests::devices::block_device>("ram0", 512_B);
+ REQUIRE(kapi::devices::interface_registry::get().publish<kapi::devices::block_device>(device, "ram0"));
+
+ auto inode = kernel::filesystem::device_inode{device};
+
+ THEN("raw_device() return the number assigned to the device")
+ {
+ auto expected = kernel::filesystem::device_number_registry::get().number_of(*device);
+ REQUIRE(expected);
+
+ auto actual = inode.raw_device();
+ REQUIRE(actual == expected);
+ }
+ }
+
+ GIVEN("a block device that has never been published")
+ {
+ auto device = kstd::make_shared<kernel::tests::devices::block_device>("never_published", 512_B);
+ auto inode = kernel::filesystem::device_inode{device};
+
+ THEN("raw_device() is nullopt, not a stale or default number")
+ {
+ REQUIRE_FALSE(inode.raw_device());
+ }
+ }
+}
diff --git a/kernel/kernel/filesystem/ext2/inode.cpp b/kernel/kernel/filesystem/ext2/inode.cpp
index f42e2c0c..89e52232 100644
--- a/kernel/kernel/filesystem/ext2/inode.cpp
+++ b/kernel/kernel/filesystem/ext2/inode.cpp
@@ -3,6 +3,7 @@
#include <kernel/filesystem/ext2/filesystem.hpp>
#include <kernel/filesystem/inode.hpp>
+#include <kapi/filesystem.hpp>
#include <kapi/system.hpp>
#include <kstd/cstring.hpp>
@@ -12,6 +13,7 @@
#include <algorithm>
#include <cstddef>
#include <cstdint>
+#include <optional>
using namespace kstd::units_literals;
@@ -201,6 +203,36 @@ namespace kernel::filesystem::ext2
return (m_data.mode & constants::mode_mask) == constants::mode_symbolic_link;
}
+ auto inode::status() const -> kstd::result<kapi::filesystem::file_status>
+ {
+ auto result = kernel::filesystem::inode::status();
+ if (!result)
+ {
+ return result;
+ }
+
+ result->size = size();
+ result->inode_number = m_inode_number;
+ result->link_count = m_data.links_count;
+
+ return result;
+ }
+
+ auto inode::raw_device() const -> std::optional<kapi::filesystem::device_number>
+ {
+ if (!is_device())
+ {
+ return std::nullopt;
+ }
+
+ auto const raw_device_number = m_data.block[0];
+
+ return kapi::filesystem::device_number{
+ .major = static_cast<std::uint8_t>((raw_device_number >> 8) & 0xff),
+ .minor = static_cast<std::uint8_t>(raw_device_number & 0xff),
+ };
+ }
+
auto inode::size() const -> kstd::units::bytes
{
uint64_t size = m_data.size;
diff --git a/kernel/kernel/filesystem/ext2/inode.hpp b/kernel/kernel/filesystem/ext2/inode.hpp
index 1d364a54..a15532b0 100644
--- a/kernel/kernel/filesystem/ext2/inode.hpp
+++ b/kernel/kernel/filesystem/ext2/inode.hpp
@@ -3,6 +3,8 @@
#include <kernel/filesystem/inode.hpp>
+#include <kapi/filesystem.hpp>
+
#include <kstd/memory.hpp>
#include <kstd/result.hpp>
#include <kstd/units.hpp>
@@ -10,6 +12,7 @@
#include <array>
#include <cstddef>
#include <cstdint>
+#include <optional>
namespace kernel::filesystem::ext2
{
@@ -107,6 +110,10 @@ namespace kernel::filesystem::ext2
*/
[[nodiscard]] auto is_symbolic_link() const -> bool override;
+ [[nodiscard]] auto status() const -> kstd::result<kapi::filesystem::file_status> override;
+
+ [[nodiscard]] auto raw_device() const -> std::optional<kapi::filesystem::device_number> override;
+
/**
@brief Get the size of the file represented by this inode.
@return The size of the file in bytes.
diff --git a/kernel/kernel/filesystem/inode.cpp b/kernel/kernel/filesystem/inode.cpp
index e564ab38..d0762472 100644
--- a/kernel/kernel/filesystem/inode.cpp
+++ b/kernel/kernel/filesystem/inode.cpp
@@ -1,5 +1,12 @@
#include <kernel/filesystem/inode.hpp>
+#include <kapi/filesystem.hpp>
+
+#include <kstd/result.hpp>
+
+#include <optional>
+#include <utility>
+
namespace kernel::filesystem
{
auto inode::is_directory() const -> bool
@@ -31,4 +38,43 @@ namespace kernel::filesystem
{
return false;
}
+
+ auto inode::status() const -> kstd::result<kapi::filesystem::file_status>
+ {
+ auto result = kapi::filesystem::file_status{};
+
+ if (is_directory())
+ {
+ result.mode = std::to_underlying(kapi::filesystem::file_type::directory);
+ }
+ else if (is_regular())
+ {
+ result.mode = std::to_underlying(kapi::filesystem::file_type::regular);
+ }
+ else if (is_block_device())
+ {
+ result.mode = std::to_underlying(kapi::filesystem::file_type::block_device);
+ }
+ else if (is_character_device())
+ {
+ result.mode = std::to_underlying(kapi::filesystem::file_type::character_device);
+ }
+ else if (is_symbolic_link())
+ {
+ result.mode = std::to_underlying(kapi::filesystem::file_type::symbolic_link);
+ }
+
+ if (auto const number = raw_device())
+ {
+ result.raw_device = *number;
+ }
+
+ return result;
+ }
+
+ auto inode::raw_device() const -> std::optional<kapi::filesystem::device_number>
+ {
+ return std::nullopt;
+ }
+
} // namespace kernel::filesystem \ No newline at end of file
diff --git a/kernel/kernel/filesystem/inode.hpp b/kernel/kernel/filesystem/inode.hpp
index 005dc57b..25e5df31 100644
--- a/kernel/kernel/filesystem/inode.hpp
+++ b/kernel/kernel/filesystem/inode.hpp
@@ -1,9 +1,13 @@
#ifndef TEACH_OS_KERNEL_FILESYSTEM_INODE_HPP
#define TEACH_OS_KERNEL_FILESYSTEM_INODE_HPP
+#include <kapi/filesystem.hpp>
+
#include <kstd/result.hpp>
#include <kstd/units.hpp>
+#include <optional>
+
namespace kernel::filesystem
{
//! Represents an inode in the filesystem.
@@ -62,6 +66,16 @@ namespace kernel::filesystem
//!
//! @return true iff. this inode is a symbolic link, false otherwise.
[[nodiscard]] virtual auto is_symbolic_link() const -> bool;
+
+ //! Get POSIX status information for this inode.
+ //!
+ //! @return a populated status information object, or an error or failure.
+ [[nodiscard]] virtual auto status() const -> kstd::result<kapi::filesystem::file_status>;
+
+ //! Get the raw device, if any, this inode refers to.
+ //!
+ //! @return a device number if this inode refers to a device, an empty optional otherwise.
+ [[nodiscard]] virtual auto raw_device() const -> std::optional<kapi::filesystem::device_number>;
};
} // namespace kernel::filesystem
diff --git a/kernel/kernel/filesystem/vfs.cpp b/kernel/kernel/filesystem/vfs.cpp
index 6533e027..c1a36856 100644
--- a/kernel/kernel/filesystem/vfs.cpp
+++ b/kernel/kernel/filesystem/vfs.cpp
@@ -186,6 +186,17 @@ namespace kernel::filesystem
return create_inode(path, vfs_types::inode_type::regular);
}
+ auto vfs::status(std::string_view path) const -> kstd::result<kapi::filesystem::file_status>
+ {
+ auto resolved = resolve_path(path);
+ if (!resolved)
+ {
+ return kstd::failure(resolved.error());
+ }
+
+ return (*resolved)->get_inode()->status();
+ }
+
auto vfs::create_inode(std::string_view path, vfs_types::inode_type type,
std::optional<kapi::filesystem::device_number> raw_device) -> kstd::result<void>
{
diff --git a/kernel/kernel/filesystem/vfs.hpp b/kernel/kernel/filesystem/vfs.hpp
index b965e426..6ab67ef8 100644
--- a/kernel/kernel/filesystem/vfs.hpp
+++ b/kernel/kernel/filesystem/vfs.hpp
@@ -96,6 +96,11 @@ namespace kernel::filesystem
// TODO remove again after the open method supports an optional create flag
auto create(std::string_view path) -> kstd::result<void>;
+ //! Get the status of the file at a given path.
+ //!
+ //! @return A populated file status object on success, an error otherwise.
+ [[nodiscard]] auto status(std::string_view path) const -> kstd::result<kapi::filesystem::file_status>;
+
private:
/**
* Note: Resolving a dentry requires traversing mount points; since the
diff --git a/kernel/kernel/test_support/filesystem/filesystem.cpp b/kernel/kernel/test_support/filesystem/filesystem.cpp
index 4dd69668..3acedd5f 100644
--- a/kernel/kernel/test_support/filesystem/filesystem.cpp
+++ b/kernel/kernel/test_support/filesystem/filesystem.cpp
@@ -1,10 +1,11 @@
#include <kernel/test_support/filesystem/filesystem.hpp>
-#include <kernel/filesystem/device_number.hpp>
#include <kernel/filesystem/inode.hpp>
#include <kernel/filesystem/vfs_types.hpp>
#include <kernel/test_support/filesystem/inode.hpp>
+#include <kapi/filesystem.hpp>
+
#include <kstd/memory.hpp>
#include <kstd/result.hpp>
#include <kstd/system_error.hpp>
@@ -22,7 +23,7 @@ namespace kernel::tests::filesystem
auto filesystem::create_inode(kstd::shared_ptr<kernel::filesystem::inode> const &, std::string_view,
kernel::filesystem::vfs_types::inode_type,
- std::optional<kernel::filesystem::device_number>)
+ std::optional<kapi::filesystem::device_number>)
-> kstd::result<kstd::shared_ptr<kernel::filesystem::inode>>
{
return kstd::make_shared<inode>();
diff --git a/kernel/kernel/test_support/filesystem/filesystem.hpp b/kernel/kernel/test_support/filesystem/filesystem.hpp
index 0f51499e..2b61aea3 100644
--- a/kernel/kernel/test_support/filesystem/filesystem.hpp
+++ b/kernel/kernel/test_support/filesystem/filesystem.hpp
@@ -1,11 +1,12 @@
#ifndef TEACHOS_KERNEL_TEST_SUPPORT_FILESYSTEM_FILESYSTEM_HPP
#define TEACHOS_KERNEL_TEST_SUPPORT_FILESYSTEM_FILESYSTEM_HPP
-#include <kernel/filesystem/device_number.hpp>
#include <kernel/filesystem/filesystem.hpp>
#include <kernel/filesystem/inode.hpp>
#include <kernel/filesystem/vfs_types.hpp>
+#include <kapi/filesystem.hpp>
+
#include <kstd/memory.hpp>
#include <kstd/result.hpp>
#include <kstd/system_error.hpp>
@@ -24,7 +25,7 @@ namespace kernel::tests::filesystem
[[nodiscard]] auto create_inode(kstd::shared_ptr<kernel::filesystem::inode> const & parent, std::string_view name,
kernel::filesystem::vfs_types::inode_type inode_type,
- std::optional<kernel::filesystem::device_number> = std::nullopt)
+ std::optional<kapi::filesystem::device_number> = std::nullopt)
-> kstd::result<kstd::shared_ptr<kernel::filesystem::inode>> override;
};
} // namespace kernel::tests::filesystem