SimpleKernel 1.17.0
Loading...
Searching...
No Matches
vfs Namespace Reference

Classes

class  BlockDevice
 块设备抽象基类 More...
 
struct  Dentry
 Dentry — 目录项缓存(路径名 ↔ Inode 的映射) More...
 
struct  DirEntry
 目录项结构(用于 readdir) More...
 
struct  File
 File — 打开的文件实例(每次 open 产生一个) More...
 
class  FileOps
 File 操作接口 More...
 
class  FileSystem
 文件系统类型基类 More...
 
struct  Inode
 Inode — 文件元数据(独立于路径名) More...
 
class  InodeOps
 Inode 操作接口 More...
 
struct  MountPoint
 挂载点 More...
 
class  MountTable
 挂载表管理器 More...
 
struct  VfsState
 VFS 全局状态结构体 More...
 

Enumerations

enum class  FileType : uint8_t {
  kUnknown = 0 , kRegular = 1 , kDirectory = 2 , kCharDevice = 3 ,
  kBlockDevice = 4 , kSymlink = 5 , kFifo = 6
}
 文件类型 More...
 
enum class  OpenFlags : uint32_t {
  kOReadOnly = 0x0000 , kOWriteOnly = 0x0001 , kOReadWrite = 0x0002 , kOCreate = 0x0040 ,
  kOTruncate = 0x0200 , kOAppend = 0x0400 , kODirectory = 0x010000
}
 文件打开标志(兼容 Linux O_* 定义) More...
 
enum class  SeekWhence : int { kSet = 0 , kCur = 1 , kEnd = 2 }
 文件 seek 基准 More...
 

Functions

auto Close (File *file) -> Expected< void >
 关闭文件
 
auto GetMountTable () -> MountTable &
 获取全局挂载表实例
 
auto Init () -> Expected< void >
 VFS 全局初始化
 
auto Lookup (const char *path) -> Expected< Dentry * >
 路径解析,查找 dentry
 
auto Open (const char *path, OpenFlags flags) -> Expected< File * >
 打开文件
 
auto Read (File *file, void *buf, size_t count) -> Expected< size_t >
 从文件读取数据
 
auto Write (File *file, const void *buf, size_t count) -> Expected< size_t >
 向文件写入数据
 
auto Seek (File *file, int64_t offset, SeekWhence whence) -> Expected< uint64_t >
 调整文件偏移量
 
auto MkDir (const char *path) -> Expected< void >
 创建目录
 
auto RmDir (const char *path) -> Expected< void >
 删除目录
 
auto Unlink (const char *path) -> Expected< void >
 删除文件
 
auto ReadDir (File *file, DirEntry *dirent, size_t count) -> Expected< size_t >
 读取目录内容
 
auto GetRootDentry () -> Dentry *
 获取根目录 dentry
 
constexpr auto operator| (OpenFlags lhs, OpenFlags rhs) -> OpenFlags
 按位或
 
constexpr auto operator& (OpenFlags lhs, OpenFlags rhs) -> OpenFlags
 按位与
 
constexpr auto operator~ (OpenFlags flags) -> OpenFlags
 按位取反
 
constexpr auto operator|= (OpenFlags &lhs, OpenFlags rhs) -> OpenFlags &
 按位或赋值
 
constexpr auto operator&= (OpenFlags &lhs, OpenFlags rhs) -> OpenFlags &
 按位与赋值
 
constexpr auto operator== (OpenFlags flags, uint32_t val) -> bool
 检查 OpenFlags 是否为零(无标志位设置)
 
constexpr auto operator!= (OpenFlags flags, uint32_t val) -> bool
 检查 OpenFlags 是否不为零
 
auto GetVfsState () -> VfsState &
 
auto SkipLeadingSlashes (const char *path) -> const char *
 跳过路径中的前导斜杠
 
auto CopyPathComponent (const char *src, char *dst, size_t dst_size) -> size_t
 复制路径组件到缓冲区
 
auto FindChild (Dentry *parent, const char *name) -> Dentry *
 在 dentry 的子节点中查找指定名称
 
auto AddChild (Dentry *parent, Dentry *child) -> void
 添加子 dentry
 
auto RemoveChild (Dentry *parent, Dentry *child) -> void
 从父 dentry 中移除子 dentry
 
auto SetRootDentry (Dentry *dentry) -> void
 
auto GetMountTableInternal () -> MountTable *
 

Variables

static constexpr size_t kMaxPathLength = 4096
 VFS 路径最大长度限制
 

Detailed Description

Enumeration Type Documentation

◆ FileType

enum class vfs::FileType : uint8_t
strong

文件类型

Enumerator
kUnknown 
kRegular 

普通文件

kDirectory 

目录

kCharDevice 

字符设备

kBlockDevice 

块设备

kSymlink 

符号链接

kFifo 

命名管道

Definition at line 22 of file vfs_types.hpp.

22 : uint8_t {
23 kUnknown = 0,
25 kRegular = 1,
27 kDirectory = 2,
29 kCharDevice = 3,
31 kBlockDevice = 4,
33 kSymlink = 5,
35 kFifo = 6,
36};
@ kBlockDevice
块设备
@ kCharDevice
字符设备
@ kRegular
普通文件
@ kDirectory
目录
@ kFifo
命名管道
@ kSymlink
符号链接

◆ OpenFlags

enum class vfs::OpenFlags : uint32_t
strong

文件打开标志(兼容 Linux O_* 定义)

Enumerator
kOReadOnly 
kOWriteOnly 
kOReadWrite 
kOCreate 
kOTruncate 
kOAppend 
kODirectory 

必须是目录

Definition at line 39 of file vfs_types.hpp.

39 : uint32_t {
40 kOReadOnly = 0x0000,
41 kOWriteOnly = 0x0001,
42 kOReadWrite = 0x0002,
43 kOCreate = 0x0040,
44 kOTruncate = 0x0200,
45 kOAppend = 0x0400,
47 kODirectory = 0x010000,
48};
@ kODirectory
必须是目录

◆ SeekWhence

enum class vfs::SeekWhence : int
strong

文件 seek 基准

Enumerator
kSet 

从文件开头

kCur 

从当前位置

kEnd 

从文件末尾

Definition at line 94 of file vfs_types.hpp.

94 : int {
96 kSet = 0,
98 kCur = 1,
100 kEnd = 2,
101};
@ kSet
从文件开头
@ kCur
从当前位置
@ kEnd
从文件末尾

Function Documentation

◆ AddChild()

auto vfs::AddChild ( Dentry parent,
Dentry child 
) -> void

添加子 dentry

Definition at line 53 of file vfs.cpp.

53 {
54 if (parent == nullptr || child == nullptr) {
55 return;
56 }
57
58 child->parent = parent;
59 child->next_sibling = parent->children;
60 parent->children = child;
61}
Dentry * children
子目录项链表头
Definition vfs.hpp:49
Dentry * parent
父目录项
Definition vfs.hpp:47
Dentry * next_sibling
兄弟目录项(同一父目录下)
Definition vfs.hpp:51
Here is the caller graph for this function:

◆ Close()

auto vfs::Close ( File file) -> Expected< void >

关闭文件

Parameters
file文件对象
Returns
Expected<void> 成功或错误
Precondition
file != nullptr
Note
会调用文件系统特定的 close 回调
关闭后 File 指针失效,不应再使用

Definition at line 15 of file close.cpp.

15 {
16 if (file == nullptr) {
17 return std::unexpected(Error(ErrorCode::kInvalidArgument));
18 }
19
20 LockGuard<SpinLock> guard(GetVfsState().vfs_lock_);
21 if (file->ops != nullptr) {
22 auto result = file->ops->Close(file);
23 if (!result.has_value()) {
24 return result;
25 }
26 }
27
28 if (file->dentry != nullptr && file->dentry->ref_count > 0) {
29 file->dentry->ref_count--;
30 }
31
32 etl::unique_ptr<File> file_guard(file);
33 return {};
34}
RAII 风格的锁守卫模板类
Definition spinlock.hpp:131
virtual auto Close(File *file) -> Expected< void >=0
关闭文件
@ kInvalidArgument
错误类型,用于 std::expected
Definition expected.hpp:343
uint32_t ref_count
引用计数(打开的 File 数量)
Definition vfs.hpp:55
Dentry * dentry
关联的 dentry
Definition vfs.hpp:69
FileOps * ops
文件操作接口
Definition vfs.hpp:76
Here is the call graph for this function:
Here is the caller graph for this function:

◆ CopyPathComponent()

auto vfs::CopyPathComponent ( const char *  src,
char *  dst,
size_t  dst_size 
) -> size_t

复制路径组件到缓冲区

Parameters
src源路径(当前位置)
dst目标缓冲区
dst_size缓冲区大小
Returns
复制的长度

Definition at line 29 of file vfs.cpp.

29 {
30 size_t i = 0;
31 while (*src != '\0' && *src != '/' && i < dst_size - 1) {
32 dst[i++] = *src++;
33 }
34 dst[i] = '\0';
35 return i;
36}
Here is the caller graph for this function:

◆ FindChild()

auto vfs::FindChild ( Dentry parent,
const char *  name 
) -> Dentry *

在 dentry 的子节点中查找指定名称

Definition at line 38 of file vfs.cpp.

38 {
39 if (parent == nullptr || name == nullptr) {
40 return nullptr;
41 }
42
43 Dentry* child = parent->children;
44 while (child != nullptr) {
45 if (strcmp(child->name, name) == 0) {
46 return child;
47 }
48 child = child->next_sibling;
49 }
50 return nullptr;
51}
#define strcmp
Here is the caller graph for this function:

◆ GetMountTable()

auto vfs::GetMountTable ( ) -> MountTable&

获取全局挂载表实例

Returns
MountTable& 挂载表引用

Definition at line 234 of file mount.cpp.

234 {
235 static MountTable instance;
236 return instance;
237}
挂载表管理器
Definition mount.hpp:34
Here is the caller graph for this function:

◆ GetMountTableInternal()

auto vfs::GetMountTableInternal ( ) -> MountTable*

Definition at line 104 of file vfs.cpp.

104 {
105 return GetVfsState().mount_table;
106}
auto GetVfsState() -> VfsState &
Definition vfs.cpp:17
Here is the call graph for this function:

◆ GetRootDentry()

auto vfs::GetRootDentry ( ) -> Dentry*

获取根目录 dentry

Returns
Dentry* 根目录 dentry
Precondition
VFS 已初始化且根文件系统已挂载
Note
返回 nullptr 表示根文件系统未挂载
返回的指针由 VFS 内部管理,不应释放

Definition at line 96 of file vfs.cpp.

96{ return GetVfsState().root_dentry; }
Here is the call graph for this function:

◆ GetVfsState()

auto vfs::GetVfsState ( ) -> VfsState &

Definition at line 17 of file vfs.cpp.

17 {
18 static VfsState state;
19 return state;
20}
VFS 全局状态结构体
Here is the caller graph for this function:

◆ Init()

auto vfs::Init ( ) -> Expected<void>

VFS 全局初始化

Returns
Expected<void> 成功或错误
Postcondition
VFS 子系统已准备好接受挂载请求
Note
线程安全:应在系统启动时单线程调用
幂等性:重复调用会返回成功(无操作)

Definition at line 80 of file vfs.cpp.

80 {
81 if (GetVfsState().initialized) {
82 return {};
83 }
84
85 LockGuard<SpinLock> guard(GetVfsState().vfs_lock_);
86 klog::Info("VFS: initializing...");
87
88 // 初始化挂载表(使用全局单例,与 GetMountTable() 统一)
89 GetVfsState().mount_table = &GetMountTable();
90
91 GetVfsState().initialized = true;
92 klog::Info("VFS: initialization complete");
93 return {};
94}
auto Info(etl::format_string< Args... > fmt, Args &&... args) -> void
以 INFO 级别记录日志
auto GetMountTable() -> MountTable &
获取全局挂载表实例
Definition mount.cpp:234
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Lookup()

auto vfs::Lookup ( const char *  path) -> Expected<Dentry*>

路径解析,查找 dentry

Parameters
path绝对路径(以 / 开头)
Returns
Expected<Dentry*> 找到的 dentry 或错误
Precondition
path != nullptr && path[0] == '/'
Note
线程安全:是,内部使用 MountTable
会自动跨越挂载点解析路径

Definition at line 14 of file lookup.cpp.

14 {
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}
@ kFsNotADirectory
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
auto SkipLeadingSlashes(const char *path) -> const char *
跳过路径中的前导斜杠
Definition vfs.cpp:22
auto CopyPathComponent(const char *src, char *dst, size_t dst_size) -> size_t
复制路径组件到缓冲区
Definition vfs.cpp:29
#define strncpy
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MkDir()

auto vfs::MkDir ( const char *  path) -> Expected<void>

创建目录

Parameters
path目录路径
Returns
Expected<void> 成功或错误
Precondition
path != nullptr
Note
父目录必须存在
如果目录已存在会返回错误

Definition at line 14 of file mkdir.cpp.

14 {
15 if (path == nullptr) {
16 return std::unexpected(Error(ErrorCode::kInvalidArgument));
17 }
18
19 LockGuard<SpinLock> guard(GetVfsState().vfs_lock_);
20 // 解析父目录路径和目录名
21 char parent_path[512];
22 char dir_name[256];
23 const char* last_slash = strrchr(path, '/');
24 if (last_slash == nullptr || last_slash == path) {
25 strncpy(parent_path, "/", sizeof(parent_path));
26 const char* name_start = path[0] == '/' ? path + 1 : path;
27 if (strlen(name_start) >= sizeof(dir_name)) {
28 return std::unexpected(Error(ErrorCode::kFsInvalidPath));
29 }
30 strncpy(dir_name, name_start, sizeof(dir_name));
31 } else {
32 size_t parent_len = last_slash - path;
33 if (parent_len >= sizeof(parent_path)) {
34 return std::unexpected(Error(ErrorCode::kFsInvalidPath));
35 }
36 strncpy(parent_path, path, parent_len);
37 parent_path[parent_len] = '\0';
38 if (strlen(last_slash + 1) >= sizeof(dir_name)) {
39 return std::unexpected(Error(ErrorCode::kFsInvalidPath));
40 }
41 strncpy(dir_name, last_slash + 1, sizeof(dir_name));
42 }
43 dir_name[sizeof(dir_name) - 1] = '\0';
44
45 // 查找父目录
46 auto parent_result = Lookup(parent_path);
47 if (!parent_result.has_value()) {
48 return std::unexpected(parent_result.error());
49 }
50
51 Dentry* parent_dentry = parent_result.value();
52 if (parent_dentry->inode == nullptr ||
53 parent_dentry->inode->type != FileType::kDirectory) {
54 return std::unexpected(Error(ErrorCode::kFsNotADirectory));
55 }
56
57 // 检查目录是否已存在
58 if (FindChild(parent_dentry, dir_name) != nullptr) {
59 return std::unexpected(Error(ErrorCode::kFsFileExists));
60 }
61
62 // 创建目录
63 if (parent_dentry->inode->ops == nullptr) {
64 return std::unexpected(Error(ErrorCode::kDeviceNotSupported));
65 }
66
67 auto result =
68 parent_dentry->inode->ops->Mkdir(parent_dentry->inode, dir_name);
69 if (!result.has_value()) {
70 return std::unexpected(result.error());
71 }
72
73 // 创建 dentry
74 auto new_dentry = kstd::make_unique<Dentry>();
75 if (!new_dentry) {
76 return std::unexpected(Error(ErrorCode::kOutOfMemory));
77 }
78
79 strncpy(new_dentry->name, dir_name, sizeof(new_dentry->name) - 1);
80 new_dentry->name[sizeof(new_dentry->name) - 1] = '\0';
81 new_dentry->inode = result.value();
82 AddChild(parent_dentry, new_dentry.release());
83
84 klog::Debug("VFS: created directory '{}'", path);
85 return {};
86}
@ kDeviceNotSupported
auto Debug(etl::format_string< Args... > fmt, Args &&... args) -> void
以 DEBUG 级别记录日志(SIMPLEKERNEL_MIN_LOG_LEVEL > 0 时编译期消除)
auto Lookup(const char *path) -> Expected< Dentry * >
路径解析,查找 dentry
Definition lookup.cpp:14
#define strlen
#define strrchr
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Open()

auto vfs::Open ( const char *  path,
OpenFlags  flags 
) -> Expected<File*>

打开文件

Parameters
path文件路径
flags打开标志
Returns
Expected<File*> 文件对象或错误
Precondition
path != nullptr
Postcondition
成功时返回有效的 File 对象
Note
调用者负责调用 Close() 释放 File 对象
若 flags 包含 kOCreate,文件不存在时会自动创建

Definition at line 14 of file open.cpp.

14 {
15 if (!GetVfsState().initialized) {
16 return std::unexpected(Error(ErrorCode::kFsNotMounted));
17 }
18
19 if (path == nullptr) {
20 return std::unexpected(Error(ErrorCode::kInvalidArgument));
21 }
22
23 if (strlen(path) >= kMaxPathLength) {
24 return std::unexpected(Error(ErrorCode::kFsInvalidPath));
25 }
26
27 LockGuard<SpinLock> guard(GetVfsState().vfs_lock_);
28 // 查找或创建 dentry
29 auto lookup_result = Lookup(path);
30 Dentry* dentry = nullptr;
31
32 if (!lookup_result.has_value()) {
33 // 文件不存在,检查是否需要创建
34 if ((flags & OpenFlags::kOCreate) == 0U) {
35 return std::unexpected(lookup_result.error());
36 }
37
38 // 创建新文件
39 // 找到父目录路径
40 char parent_path[512];
41 char file_name[256];
42 const char* last_slash = strrchr(path, '/');
43 if (last_slash == nullptr || last_slash == path) {
44 strncpy(parent_path, "/", sizeof(parent_path));
45 const char* name_start = path[0] == '/' ? path + 1 : path;
46 if (strlen(name_start) >= sizeof(file_name)) {
47 return std::unexpected(Error(ErrorCode::kFsInvalidPath));
48 }
49 strncpy(file_name, name_start, sizeof(file_name));
50 } else {
51 size_t parent_len = last_slash - path;
52 if (parent_len >= sizeof(parent_path)) {
53 return std::unexpected(Error(ErrorCode::kFsInvalidPath));
54 }
55 strncpy(parent_path, path, parent_len);
56 parent_path[parent_len] = '\0';
57 if (strlen(last_slash + 1) >= sizeof(file_name)) {
58 return std::unexpected(Error(ErrorCode::kFsInvalidPath));
59 }
60 strncpy(file_name, last_slash + 1, sizeof(file_name));
61 }
62 file_name[sizeof(file_name) - 1] = '\0';
63
64 // 查找父目录
65 auto parent_result = Lookup(parent_path);
66 if (!parent_result.has_value()) {
67 return std::unexpected(parent_result.error());
68 }
69
70 Dentry* parent_dentry = parent_result.value();
71 if (parent_dentry->inode == nullptr ||
72 parent_dentry->inode->type != FileType::kDirectory) {
73 return std::unexpected(Error(ErrorCode::kFsNotADirectory));
74 }
75
76 // 创建文件
77 if (parent_dentry->inode->ops == nullptr) {
78 return std::unexpected(Error(ErrorCode::kDeviceNotSupported));
79 }
80
81 auto create_result = parent_dentry->inode->ops->Create(
82 parent_dentry->inode, file_name, FileType::kRegular);
83 if (!create_result.has_value()) {
84 return std::unexpected(create_result.error());
85 }
86
87 // 创建 dentry
88 auto new_dentry = kstd::make_unique<Dentry>();
89 if (!new_dentry) {
90 return std::unexpected(Error(ErrorCode::kOutOfMemory));
91 }
92
93 strncpy(new_dentry->name, file_name, sizeof(new_dentry->name) - 1);
94 new_dentry->name[sizeof(new_dentry->name) - 1] = '\0';
95 new_dentry->inode = create_result.value();
96 dentry = new_dentry.get();
97 AddChild(parent_dentry, new_dentry.release());
98 } else {
99 dentry = lookup_result.value();
100 }
101
102 if (dentry == nullptr || dentry->inode == nullptr) {
103 return std::unexpected(Error(ErrorCode::kFsCorrupted));
104 }
105
106 // 检查打开模式
107 if ((flags & OpenFlags::kODirectory) != 0U &&
108 dentry->inode->type != FileType::kDirectory) {
109 return std::unexpected(Error(ErrorCode::kFsNotADirectory));
110 }
111
112 // 创建 File 对象
113 auto new_file = kstd::make_unique<File>();
114 if (!new_file) {
115 return std::unexpected(Error(ErrorCode::kOutOfMemory));
116 }
117 File* file = new_file.release();
118
119 file->inode = dentry->inode;
120 file->dentry = dentry;
121 file->offset = 0;
122 file->flags = flags;
123 dentry->ref_count++;
124
125 // 从文件系统获取 FileOps
126 if (file->inode != nullptr && file->inode->fs != nullptr) {
127 file->ops = file->inode->fs->GetFileOps();
128 }
129
130 // 处理 O_TRUNC
131 if ((flags & OpenFlags::kOTruncate) != 0U &&
132 dentry->inode->type == FileType::kRegular) {
133 // 截断文件,由具体文件系统处理
134 // 这里不直接操作,而是通过后续的 write 来处理
135 }
136
137 klog::Debug("VFS: opened '{}', flags={:#x}", path,
138 static_cast<uint32_t>(flags));
139 return file;
140}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ operator!=()

constexpr auto vfs::operator!= ( OpenFlags  flags,
uint32_t  val 
) -> bool
inlineconstexpr

检查 OpenFlags 是否不为零

Definition at line 88 of file vfs_types.hpp.

89 {
90 return static_cast<uint32_t>(flags) != val;
91}

◆ operator&()

constexpr auto vfs::operator& ( OpenFlags  lhs,
OpenFlags  rhs 
) -> OpenFlags
inlineconstexpr

按位与

Definition at line 58 of file vfs_types.hpp.

59 {
60 return static_cast<OpenFlags>(static_cast<uint32_t>(lhs) &
61 static_cast<uint32_t>(rhs));
62}
OpenFlags
文件打开标志(兼容 Linux O_* 定义)
Definition vfs_types.hpp:39

◆ operator&=()

constexpr auto vfs::operator&= ( OpenFlags lhs,
OpenFlags  rhs 
) -> OpenFlags&
inlineconstexpr

按位与赋值

Definition at line 76 of file vfs_types.hpp.

76 {
77 lhs = lhs & rhs;
78 return lhs;
79}

◆ operator==()

constexpr auto vfs::operator== ( OpenFlags  flags,
uint32_t  val 
) -> bool
inlineconstexpr

检查 OpenFlags 是否为零(无标志位设置)

Definition at line 82 of file vfs_types.hpp.

83 {
84 return static_cast<uint32_t>(flags) == val;
85}

◆ operator|()

constexpr auto vfs::operator| ( OpenFlags  lhs,
OpenFlags  rhs 
) -> OpenFlags
inlineconstexpr

按位或

Definition at line 51 of file vfs_types.hpp.

52 {
53 return static_cast<OpenFlags>(static_cast<uint32_t>(lhs) |
54 static_cast<uint32_t>(rhs));
55}

◆ operator|=()

constexpr auto vfs::operator|= ( OpenFlags lhs,
OpenFlags  rhs 
) -> OpenFlags&
inlineconstexpr

按位或赋值

Definition at line 70 of file vfs_types.hpp.

70 {
71 lhs = lhs | rhs;
72 return lhs;
73}

◆ operator~()

constexpr auto vfs::operator~ ( OpenFlags  flags) -> OpenFlags
inlineconstexpr

按位取反

Definition at line 65 of file vfs_types.hpp.

65 {
66 return static_cast<OpenFlags>(~static_cast<uint32_t>(flags));
67}

◆ Read()

auto vfs::Read ( File file,
void *  buf,
size_t  count 
) -> Expected<size_t>

从文件读取数据

Parameters
file文件对象
buf输出缓冲区
count最大读取字节数
Returns
Expected<size_t> 实际读取的字节数或错误
Precondition
file != nullptr && buf != nullptr
Note
实际读取字节数可能小于 count(到达文件末尾)
会自动更新 file->offset

Definition at line 13 of file read.cpp.

13 {
14 if (file == nullptr || buf == nullptr) {
15 return std::unexpected(Error(ErrorCode::kInvalidArgument));
16 }
17
18 LockGuard<SpinLock> guard(GetVfsState().vfs_lock_);
19 if (file->ops == nullptr) {
20 return std::unexpected(Error(ErrorCode::kDeviceNotSupported));
21 }
22
23 return file->ops->Read(file, buf, count);
24}
virtual auto Read(File *file, void *buf, size_t count) -> Expected< size_t >=0
从文件读取数据
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ReadDir()

auto vfs::ReadDir ( File file,
DirEntry dirent,
size_t  count 
) -> Expected<size_t>

读取目录内容

Parameters
file目录文件对象
dirent输出目录项数组
count最多读取的条目数
Returns
Expected<size_t> 实际读取的条目数或错误
Precondition
file != nullptr && file->inode->type == FileType::kDirectory
Note
会返回 . 和 .. 目录项
多次调用可遍历整个目录,自动维护偏移量

Definition at line 13 of file readdir.cpp.

13 {
14 if (file == nullptr || dirent == nullptr) {
15 return std::unexpected(Error(ErrorCode::kInvalidArgument));
16 }
17
18 LockGuard<SpinLock> guard(GetVfsState().vfs_lock_);
19 if (file->inode == nullptr || file->inode->type != FileType::kDirectory) {
20 return std::unexpected(Error(ErrorCode::kFsNotADirectory));
21 }
22
23 if (file->ops == nullptr) {
24 return std::unexpected(Error(ErrorCode::kDeviceNotSupported));
25 }
26
27 return file->ops->ReadDir(file, dirent, count);
28}
virtual auto ReadDir(File *file, DirEntry *dirent, size_t count) -> Expected< size_t >=0
读取目录项
Inode * inode
关联的 inode
Definition vfs.hpp:67
FileType type
文件类型
Definition vfs.hpp:20
Here is the call graph for this function:
Here is the caller graph for this function:

◆ RemoveChild()

auto vfs::RemoveChild ( Dentry parent,
Dentry child 
) -> void

从父 dentry 中移除子 dentry

Definition at line 63 of file vfs.cpp.

63 {
64 if (parent == nullptr || child == nullptr) {
65 return;
66 }
67
68 Dentry** current = &parent->children;
69 while (*current != nullptr) {
70 if (*current == child) {
71 *current = child->next_sibling;
72 child->parent = nullptr;
73 child->next_sibling = nullptr;
74 return;
75 }
76 current = &(*current)->next_sibling;
77 }
78}
Here is the caller graph for this function:

◆ RmDir()

auto vfs::RmDir ( const char *  path) -> Expected<void>

删除目录

Parameters
path目录路径
Returns
Expected<void> 成功或错误
Precondition
path != nullptr
Note
目录必须为空(不含子项)
不能删除挂载点

Definition at line 15 of file rmdir.cpp.

15 {
16 if (path == nullptr) {
17 return std::unexpected(Error(ErrorCode::kInvalidArgument));
18 }
19
20 LockGuard<SpinLock> guard(GetVfsState().vfs_lock_);
21 // 解析父目录路径和目录名
22 char parent_path[512];
23 char dir_name[256];
24 const char* last_slash = strrchr(path, '/');
25 if (last_slash == nullptr || last_slash == path) {
26 strncpy(parent_path, "/", sizeof(parent_path));
27 strncpy(dir_name, path[0] == '/' ? path + 1 : path, sizeof(dir_name));
28 } else {
29 size_t parent_len = last_slash - path;
30 if (parent_len >= sizeof(parent_path)) {
31 parent_len = sizeof(parent_path) - 1;
32 }
33 strncpy(parent_path, path, parent_len);
34 parent_path[parent_len] = '\0';
35 strncpy(dir_name, last_slash + 1, sizeof(dir_name));
36 }
37 dir_name[sizeof(dir_name) - 1] = '\0';
38
39 // 查找父目录
40 auto parent_result = Lookup(parent_path);
41 if (!parent_result.has_value()) {
42 return std::unexpected(parent_result.error());
43 }
44
45 Dentry* parent_dentry = parent_result.value();
46 if (parent_dentry->inode == nullptr) {
47 return std::unexpected(Error(ErrorCode::kFsCorrupted));
48 }
49
50 // 查找目标目录
51 Dentry* target_dentry = FindChild(parent_dentry, dir_name);
52 if (target_dentry == nullptr) {
53 return std::unexpected(Error(ErrorCode::kFsFileNotFound));
54 }
55
56 if (target_dentry->inode == nullptr ||
57 target_dentry->inode->type != FileType::kDirectory) {
58 return std::unexpected(Error(ErrorCode::kFsNotADirectory));
59 }
60
61 // 检查目录是否为空
62 if (target_dentry->children != nullptr) {
63 return std::unexpected(Error(ErrorCode::kFsNotEmpty));
64 }
65
66 // 删除目录
67 if (parent_dentry->inode->ops == nullptr) {
68 return std::unexpected(Error(ErrorCode::kDeviceNotSupported));
69 }
70
71 auto result =
72 parent_dentry->inode->ops->Rmdir(parent_dentry->inode, dir_name);
73 if (!result.has_value()) {
74 return std::unexpected(result.error());
75 }
76
77 // 从父目录中移除 dentry
78 RemoveChild(parent_dentry, target_dentry);
79
80 if (target_dentry->ref_count > 0) {
81 target_dentry->deleted = true;
82 target_dentry->inode = nullptr;
83 } else {
84 etl::unique_ptr<Dentry> dentry_guard(target_dentry);
85 }
86
87 klog::Debug("VFS: removed directory '{}'", path);
88 return {};
89}
auto RemoveChild(Dentry *parent, Dentry *child) -> void
从父 dentry 中移除子 dentry
Definition vfs.cpp:63
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Seek()

auto vfs::Seek ( File file,
int64_t  offset,
SeekWhence  whence 
) -> Expected<uint64_t>

调整文件偏移量

Parameters
file文件对象
offset偏移量
whence基准位置
Returns
Expected<uint64_t> 新的偏移量或错误
Precondition
file != nullptr
Note
如果 whence 为 kEnd 且 offset 为正,可能超过文件末尾
返回的偏移量是绝对位置(从文件开头计算)

Definition at line 13 of file seek.cpp.

13 {
14 if (file == nullptr) {
15 return std::unexpected(Error(ErrorCode::kInvalidArgument));
16 }
17
18 LockGuard<SpinLock> guard(GetVfsState().vfs_lock_);
19 if (file->ops != nullptr) {
20 return file->ops->Seek(file, offset, whence);
21 }
22
23 // 默认实现
24 uint64_t new_offset = file->offset;
25
26 switch (whence) {
27 case SeekWhence::kSet:
28 if (offset < 0) {
29 return std::unexpected(Error(ErrorCode::kInvalidArgument));
30 }
31 new_offset = static_cast<uint64_t>(offset);
32 break;
33 case SeekWhence::kCur:
34 if (offset < 0 && static_cast<uint64_t>(-offset) > file->offset) {
35 return std::unexpected(Error(ErrorCode::kInvalidArgument));
36 }
37 new_offset =
38 static_cast<uint64_t>(static_cast<int64_t>(file->offset) + offset);
39 break;
40 case SeekWhence::kEnd:
41 if (file->inode == nullptr) {
42 return std::unexpected(Error(ErrorCode::kFsCorrupted));
43 }
44 if (offset < 0 && static_cast<uint64_t>(-offset) > file->inode->size) {
45 return std::unexpected(Error(ErrorCode::kInvalidArgument));
46 }
47 new_offset = static_cast<uint64_t>(
48 static_cast<int64_t>(file->inode->size) + offset);
49 break;
50 default:
51 return std::unexpected(Error(ErrorCode::kInvalidArgument));
52 }
53
54 file->offset = new_offset;
55 return new_offset;
56}
virtual auto Seek(File *file, int64_t offset, SeekWhence whence) -> Expected< uint64_t >=0
调整文件偏移量
uint64_t offset
当前读写偏移量
Definition vfs.hpp:71
uint64_t size
文件大小(字节)
Definition vfs.hpp:22
Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetRootDentry()

auto vfs::SetRootDentry ( Dentry dentry) -> void

Definition at line 99 of file vfs.cpp.

99 {
100 GetVfsState().root_dentry = dentry;
101}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ SkipLeadingSlashes()

auto vfs::SkipLeadingSlashes ( const char *  path) -> const char *

跳过路径中的前导斜杠

Parameters
path输入路径
Returns
跳过前导斜杠后的路径指针

Definition at line 22 of file vfs.cpp.

22 {
23 while (*path == '/') {
24 ++path;
25 }
26 return path;
27}
Here is the caller graph for this function:

◆ Unlink()

auto vfs::Unlink ( const char *  path) -> Expected<void>

删除文件

Parameters
path文件路径
Returns
Expected<void> 成功或错误
Precondition
path != nullptr
Note
不能删除目录(使用 RmDir)
如果多个硬链接,只会减少链接计数

Definition at line 15 of file unlink.cpp.

15 {
16 if (path == nullptr) {
17 return std::unexpected(Error(ErrorCode::kInvalidArgument));
18 }
19
20 LockGuard<SpinLock> guard(GetVfsState().vfs_lock_);
21 // 解析父目录路径和文件名
22 char parent_path[512];
23 char file_name[256];
24 const char* last_slash = strrchr(path, '/');
25 if (last_slash == nullptr || last_slash == path) {
26 strncpy(parent_path, "/", sizeof(parent_path));
27 strncpy(file_name, path[0] == '/' ? path + 1 : path, sizeof(file_name));
28 } else {
29 size_t parent_len = last_slash - path;
30 if (parent_len >= sizeof(parent_path)) {
31 parent_len = sizeof(parent_path) - 1;
32 }
33 strncpy(parent_path, path, parent_len);
34 parent_path[parent_len] = '\0';
35 strncpy(file_name, last_slash + 1, sizeof(file_name));
36 }
37 file_name[sizeof(file_name) - 1] = '\0';
38
39 // 查找父目录
40 auto parent_result = Lookup(parent_path);
41 if (!parent_result.has_value()) {
42 return std::unexpected(parent_result.error());
43 }
44
45 Dentry* parent_dentry = parent_result.value();
46 if (parent_dentry->inode == nullptr) {
47 return std::unexpected(Error(ErrorCode::kFsCorrupted));
48 }
49
50 // 查找目标文件
51 Dentry* target_dentry = FindChild(parent_dentry, file_name);
52 if (target_dentry == nullptr) {
53 return std::unexpected(Error(ErrorCode::kFsFileNotFound));
54 }
55
56 if (target_dentry->inode == nullptr) {
57 return std::unexpected(Error(ErrorCode::kFsCorrupted));
58 }
59
60 // 不能删除目录
61 if (target_dentry->inode->type == FileType::kDirectory) {
62 return std::unexpected(Error(ErrorCode::kFsIsADirectory));
63 }
64
65 // 删除文件
66 if (parent_dentry->inode->ops == nullptr) {
67 return std::unexpected(Error(ErrorCode::kDeviceNotSupported));
68 }
69
70 auto result =
71 parent_dentry->inode->ops->Unlink(parent_dentry->inode, file_name);
72 if (!result.has_value()) {
73 return std::unexpected(result.error());
74 }
75
76 // 从父目录中移除 dentry
77 RemoveChild(parent_dentry, target_dentry);
78
79 if (target_dentry->ref_count > 0) {
80 target_dentry->deleted = true;
81 target_dentry->inode = nullptr;
82 } else {
83 etl::unique_ptr<Dentry> dentry_guard(target_dentry);
84 }
85
86 klog::Debug("VFS: unlinked '{}'", path);
87 return {};
88}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Write()

auto vfs::Write ( File file,
const void *  buf,
size_t  count 
) -> Expected<size_t>

向文件写入数据

Parameters
file文件对象
buf输入缓冲区
count要写入的字节数
Returns
Expected<size_t> 实际写入的字节数或错误
Precondition
file != nullptr && buf != nullptr
Note
文件系统可能需要在写入前扩展文件大小
会自动更新 file->offset 和 file->inode->size

Definition at line 13 of file write.cpp.

13 {
14 if (file == nullptr || buf == nullptr) {
15 return std::unexpected(Error(ErrorCode::kInvalidArgument));
16 }
17
18 // 检查写入权限
19 LockGuard<SpinLock> guard(GetVfsState().vfs_lock_);
20 if ((file->flags & OpenFlags::kOWriteOnly) == 0U &&
21 (file->flags & OpenFlags::kOReadWrite) == 0U) {
22 return std::unexpected(Error(ErrorCode::kFsPermissionDenied));
23 }
24
25 if (file->ops == nullptr) {
26 return std::unexpected(Error(ErrorCode::kDeviceNotSupported));
27 }
28
29 return file->ops->Write(file, buf, count);
30}
virtual auto Write(File *file, const void *buf, size_t count) -> Expected< size_t >=0
向文件写入数据
@ kFsPermissionDenied
OpenFlags flags
打开标志 (OpenFlags)
Definition vfs.hpp:73
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ kMaxPathLength

constexpr size_t vfs::kMaxPathLength = 4096
staticconstexpr

VFS 路径最大长度限制

Definition at line 14 of file vfs_internal.hpp.