SimpleKernel 1.17.0
Loading...
Searching...
No Matches
open.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 Open(const char* path, OpenFlags flags) -> Expected<File*> {
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}
141
142} // namespace vfs
RAII 风格的锁守卫模板类
Definition spinlock.hpp:131
virtual auto GetFileOps() -> FileOps *=0
获取文件系统的文件操作接口
virtual auto Create(Inode *dir, const char *name, FileType type) -> Expected< Inode * >=0
在目录中创建新文件
@ kInvalidArgument
@ kDeviceNotSupported
@ kFsNotADirectory
std::expected< T, Error > Expected
std::expected 别名模板
Definition expected.hpp:365
auto Debug(etl::format_string< Args... > fmt, Args &&... args) -> void
以 DEBUG 级别记录日志(SIMPLEKERNEL_MIN_LOG_LEVEL > 0 时编译期消除)
OpenFlags
文件打开标志(兼容 Linux O_* 定义)
Definition vfs_types.hpp:39
@ kODirectory
必须是目录
auto AddChild(Dentry *parent, Dentry *child) -> void
添加子 dentry
Definition vfs.cpp:53
@ kRegular
普通文件
@ kDirectory
目录
auto Open(const char *path, OpenFlags flags) -> Expected< File * >
打开文件
Definition open.cpp:14
auto GetVfsState() -> VfsState &
Definition vfs.cpp:17
auto Lookup(const char *path) -> Expected< Dentry * >
路径解析,查找 dentry
Definition lookup.cpp:14
static constexpr size_t kMaxPathLength
VFS 路径最大长度限制
#define strlen
#define strncpy
#define strrchr
错误类型,用于 std::expected
Definition expected.hpp:343
Dentry — 目录项缓存(路径名 ↔ Inode 的映射)
Definition vfs.hpp:41
uint32_t ref_count
引用计数(打开的 File 数量)
Definition vfs.hpp:55
Inode * inode
关联的 inode
Definition vfs.hpp:45
File — 打开的文件实例(每次 open 产生一个)
Definition vfs.hpp:65
OpenFlags flags
打开标志 (OpenFlags)
Definition vfs.hpp:73
Dentry * dentry
关联的 dentry
Definition vfs.hpp:69
Inode * inode
关联的 inode
Definition vfs.hpp:67
uint64_t offset
当前读写偏移量
Definition vfs.hpp:71
FileOps * ops
文件操作接口
Definition vfs.hpp:76
FileSystem * fs
所属文件系统
Definition vfs.hpp:30
FileType type
文件类型
Definition vfs.hpp:20
InodeOps * ops
文件操作接口
Definition vfs.hpp:33