blob: 2ecf8479d773ab9be1b35a8f3b9ef5d0414b61e9 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
#include "filesystem/vfs.hpp"
#include "kapi/system.hpp"
#include "devices/device.hpp"
#include "devices/storage/storage_management.hpp"
#include "filesystem/custody.hpp"
#include "filesystem/device_file.hpp"
#include "filesystem/ext2/ext2_filesystem.hpp"
#include "filesystem/inode.hpp"
#include "filesystem/inode_file.hpp"
#include "filesystem/mount.hpp"
#include "filesystem/open_file_description.hpp"
#include <kstd/cstring>
#include <algorithm>
#include <optional>
#include <string_view>
namespace filesystem
{
namespace
{
constinit auto static active_vfs = std::optional<vfs>{};
// TODO BA-FS26 @Felix better solution? while dynamic memory not available?
// TODO BA-FS26 remove when dynamic memory available;
constinit auto static root_fs = std::optional<ext2::ext2_filesystem>{};
// TODO BA-FS26 remove when dynamic memory available;
constinit auto static temp_device_file = std::optional<device_file>{};
// TODO BA-FS26 remove when dynamic memory available;
constinit auto static temp_inode_file = std::optional<inode_file>{};
} // namespace
auto vfs::init() -> void
{
if (active_vfs)
{
kapi::system::panic("[FILESYSTEM] vfs has already been initialized.");
}
active_vfs.emplace(vfs{});
auto storage_mgmt = devices::storage::storage_management::get();
if (auto boot_device = storage_mgmt.determine_boot_device())
{
root_fs.emplace(ext2::ext2_filesystem{});
if (root_fs->mount(boot_device) != 0)
{
kapi::system::panic("[FILESYSTEM] Failed to mount root filesystem.");
}
active_vfs->m_root_mount = mount{"/", &*root_fs};
std::ranges::for_each(storage_mgmt.all_controllers(), [&](auto controller) {
std::ranges::for_each(controller->all_devices(), [&](auto device) { active_vfs->make_device_node(device); });
});
}
else
{
// TODO BA-FS26 ?? what when no boot_device == no modules loaded??
}
}
auto vfs::get() -> vfs &
{
if (!active_vfs)
{
kapi::system::panic("[FILESYSTEM] vfs has not been initialized.");
}
return *active_vfs;
}
auto vfs::open(std::string_view path) -> std::optional<open_file_description>
{
if (auto custody = resolve_path(path))
{
auto * node = custody->get_inode();
if (node->is_device())
{
temp_device_file.emplace(node->backing_device());
temp_device_file->open();
return open_file_description{&*temp_device_file};
}
temp_inode_file.emplace(node);
temp_inode_file->open();
return open_file_description{&*temp_inode_file};
}
return std::nullopt;
}
auto vfs::make_device_node(devices::device * device) -> void
{
if (!device)
{
kapi::system::panic("[FILESYSTEM] make_device_node called with null device.");
}
auto const device_name = device->name();
// TODO BA-FS26 this logic isn't needed anymore when kstd::vector available, just use push_back
auto const slot = std::ranges::find_if(m_device_nodes, [](auto const & entry) { return !entry.has_value(); });
if (slot == m_device_nodes.end())
{
kapi::system::panic("[FILESYSTEM] No free slot available for device nodes.");
}
slot->emplace(device_node_entry{device_name, inode{device}});
}
auto vfs::resolve_path(std::string_view path) -> std::optional<custody>
{
// TODO BA-FS26 implement real path resolution with mounts and directories etc.
// For now, just support device nodes at /dev/<device_name>.
constexpr auto device_prefix = std::string_view{"/dev/"};
if (path.starts_with(device_prefix))
{
auto const device_name = path.substr(device_prefix.size());
auto entry = std::ranges::find_if(m_device_nodes, [&](auto const & device_entry) {
return device_entry.has_value() && device_entry->name == device_name;
});
if (entry != m_device_nodes.end())
{
return custody{nullptr, &entry->value().node};
}
return std::nullopt;
}
return std::nullopt;
}
} // namespace filesystem
|