SimpleKernel 1.17.0
Loading...
Searching...
No Matches
lookup.cpp
Go to the documentation of this file.
1
5#include "filesystem.hpp"
6#include "kernel_log.hpp"
7#include "kstd_cstring"
8#include "kstd_memory"
9#include "spinlock.hpp"
10#include "vfs_internal.hpp"
11
12namespace vfs {
13
14auto Lookup(const char* path) -> Expected<Dentry*> {
15 if (!GetVfsState().initialized) {
16 return std::unexpected(Error(ErrorCode::kFsNotMounted));
17 }
18
19 if (path == nullptr || path[0] != '/') {
20 return std::unexpected(Error(ErrorCode::kInvalidArgument));
21 }
22
23 // 注意:Lookup 是内部函数,由持锁的上层 VFS 函数(Open/MkDir 等)调用,
24 // 此处不需要额外加锁,否则会导致 SpinLock 递归死锁。
25 // 空路径或根目录
26 if (path[0] == '/' && (path[1] == '\0' || path[1] == '/')) {
27 if (GetVfsState().root_dentry == nullptr) {
28 return std::unexpected(Error(ErrorCode::kFsNotMounted));
29 }
30 return GetVfsState().root_dentry;
31 }
32
33 // 查找路径对应的挂载点
34 MountPoint* mp = GetVfsState().mount_table->Lookup(path);
35 if (mp == nullptr || mp->root_dentry == nullptr) {
36 return std::unexpected(Error(ErrorCode::kFsNotMounted));
37 }
38
39 // 从挂载点根开始解析路径
40 Dentry* current = mp->root_dentry;
41 const char* p = SkipLeadingSlashes(path);
42
43 // 如果挂载路径不是根,需要跳过挂载路径部分
44 if (mp->mount_path != nullptr && strcmp(mp->mount_path, "/") != 0) {
45 const char* mount_path = SkipLeadingSlashes(mp->mount_path);
46 while (*mount_path != '\0') {
47 char component[256];
48 size_t len = CopyPathComponent(mount_path, component, sizeof(component));
49 if (len == 0) {
50 break;
51 }
52 mount_path += len;
53 mount_path = SkipLeadingSlashes(mount_path);
54
55 // 跳过挂载路径的组件
56 len = CopyPathComponent(p, component, sizeof(component));
57 if (len == 0) {
58 break;
59 }
60 p += len;
61 p = SkipLeadingSlashes(p);
62 }
63 }
64
65 // 逐级解析路径组件
66 char component[256];
67 while (*p != '\0') {
68 // 检查当前 dentry 是否是目录
69 if (current->inode == nullptr ||
70 current->inode->type != FileType::kDirectory) {
71 return std::unexpected(Error(ErrorCode::kFsNotADirectory));
72 }
73
74 // 提取路径组件
75 size_t len = CopyPathComponent(p, component, sizeof(component));
76 if (len == 0) {
77 break;
78 }
79 p += len;
80 p = SkipLeadingSlashes(p);
81
82 // 处理 "." 和 ".."
83 if (strcmp(component, ".") == 0) {
84 continue;
85 }
86 if (strcmp(component, "..") == 0) {
87 if (current->parent != nullptr) {
88 current = current->parent;
89 }
90 continue;
91 }
92
93 // 在子节点中查找
94 Dentry* child = FindChild(current, component);
95 if (child == nullptr) {
96 // 尝试通过 inode ops 查找
97 if (current->inode->ops != nullptr) {
98 auto result = current->inode->ops->Lookup(current->inode, component);
99 if (!result.has_value()) {
100 return std::unexpected(Error(ErrorCode::kFsFileNotFound));
101 }
102
103 // 创建新的 dentry
104 auto new_child = kstd::make_unique<Dentry>();
105 if (!new_child) {
106 return std::unexpected(Error(ErrorCode::kOutOfMemory));
107 }
108
109 strncpy(new_child->name, component, sizeof(new_child->name) - 1);
110 new_child->name[sizeof(new_child->name) - 1] = '\0';
111 new_child->inode = result.value();
112 child = new_child.get();
113 AddChild(current, new_child.release());
114 } else {
115 return std::unexpected(Error(ErrorCode::kFsFileNotFound));
116 }
117 }
118
119 current = child;
120
121 // 检查是否遇到挂载点
122 if (current->inode != nullptr) {
123 MountPoint* next_mp =
124 GetVfsState().mount_table->FindByMountDentry(current);
125 if (next_mp != nullptr && next_mp != mp) {
126 mp = next_mp;
127 current = next_mp->root_dentry;
128 }
129 }
130 }
131
132 return current;
133}
134
135} // namespace vfs
virtual auto Lookup(Inode *dir, const char *name) -> Expected< Inode * >=0
在目录中查找指定名称的 inode
@ kInvalidArgument
@ kFsNotADirectory
std::expected< T, Error > Expected
std::expected 别名模板
Definition expected.hpp:365
auto AddChild(Dentry *parent, Dentry *child) -> void
添加子 dentry
Definition vfs.cpp:53
auto FindChild(Dentry *parent, const char *name) -> Dentry *
在 dentry 的子节点中查找指定名称
Definition vfs.cpp:38
@ kDirectory
目录
auto SkipLeadingSlashes(const char *path) -> const char *
跳过路径中的前导斜杠
Definition vfs.cpp:22
auto GetVfsState() -> VfsState &
Definition vfs.cpp:17
auto CopyPathComponent(const char *src, char *dst, size_t dst_size) -> size_t
复制路径组件到缓冲区
Definition vfs.cpp:29
auto Lookup(const char *path) -> Expected< Dentry * >
路径解析,查找 dentry
Definition lookup.cpp:14
#define strncpy
#define strcmp
错误类型,用于 std::expected
Definition expected.hpp:343
Dentry — 目录项缓存(路径名 ↔ Inode 的映射)
Definition vfs.hpp:41
Dentry * parent
父目录项
Definition vfs.hpp:47
Inode * inode
关联的 inode
Definition vfs.hpp:45
FileType type
文件类型
Definition vfs.hpp:20
InodeOps * ops
文件操作接口
Definition vfs.hpp:33
挂载点
Definition mount.hpp:15
Dentry * root_dentry
该文件系统的根 dentry
Definition mount.hpp:27
const char * mount_path
挂载路径(如 "/mnt/disk")
Definition mount.hpp:17