os/kernel/syscall/
fs.rs

1//! 文件系统相关的系统调用实现
2
3use core::ffi::c_char;
4
5use alloc::{string::ToString, sync::Arc};
6
7use crate::{
8    arch::trap::SumGuard,
9    kernel::{
10        current_cpu, current_task,
11        syscall::util::{
12            create_file_at, create_file_from_dentry, get_path_safe, resolve_at_path,
13            resolve_at_path_with_flags,
14        },
15    },
16    uapi::{
17        errno::{EACCES, EINVAL, ENOENT},
18        fs::{AtFlags, F_OK, FileSystemType, LinuxStatFs, R_OK, W_OK, X_OK},
19        time::TimeSpec,
20    },
21    vfs::{
22        DENTRY_CACHE, Dentry, FileMode, FsError, InodeType, OpenFlags, RegFile, SeekWhence, Stat,
23        split_path, vfs_lookup,
24    },
25};
26
27pub const AT_FDCWD: i32 = -100;
28pub const AT_SYMLINK_NOFOLLOW: u32 = 0x100;
29pub const AT_REMOVEDIR: u32 = 0x200;
30pub const O_CLOEXEC: u32 = 0o2000000;
31
32pub fn close(fd: usize) -> isize {
33    let task = current_cpu().lock().current_task.as_ref().unwrap().clone();
34    match task.lock().fd_table.close(fd) {
35        Ok(()) => 0,
36        Err(e) => e.to_errno(),
37    }
38}
39
40pub fn lseek(fd: usize, offset: isize, whence: usize) -> isize {
41    // 获取文件对象
42    let task = current_cpu().lock().current_task.as_ref().unwrap().clone();
43    let file = match task.lock().fd_table.get(fd) {
44        Ok(f) => f,
45        Err(e) => return e.to_errno(),
46    };
47
48    // 转换whence参数
49    let seek_whence = match SeekWhence::from_usize(whence) {
50        Some(w) => w,
51        None => return FsError::InvalidArgument.to_errno(),
52    };
53
54    // 执行lseek
55    match file.lseek(offset, seek_whence) {
56        Ok(new_pos) => new_pos as isize,
57        Err(e) => e.to_errno(),
58    }
59}
60
61/// openat - 相对于目录文件描述符打开文件
62pub fn openat(dirfd: i32, pathname: *const c_char, flags: u32, mode: u32) -> isize {
63    // 解析路径字符串
64    let _guard = SumGuard::new();
65    let path_str = match get_path_safe(pathname) {
66        Ok(s) => s.to_string(),
67        Err(_) => {
68            return FsError::InvalidArgument.to_errno();
69        }
70    };
71
72    // 解析标志位
73    let open_flags = match OpenFlags::from_bits(flags) {
74        Some(f) => f,
75        None => {
76            return FsError::InvalidArgument.to_errno();
77        }
78    };
79
80    // crate::println!("[openat] path: {}, flags: {:?} (raw: 0x{:x})", path_str, open_flags, flags);
81
82    // 解析路径(处理AT_FDCWD和相对路径)
83    let dentry = match resolve_at_path(dirfd, &path_str) {
84        Ok(Some(d)) => {
85            // 文件已存在
86            // 检查 O_EXCL (与 O_CREAT 一起使用时,文件必须不存在)
87            if open_flags.contains(OpenFlags::O_CREAT) && open_flags.contains(OpenFlags::O_EXCL) {
88                return FsError::AlreadyExists.to_errno();
89            }
90            d
91        }
92        Ok(None) => {
93            // 文件不存在,检查是否需要创建
94            if !open_flags.contains(OpenFlags::O_CREAT) {
95                return FsError::NotFound.to_errno();
96            }
97
98            // 创建新文件
99            match create_file_at(dirfd, &path_str, mode) {
100                Ok(d) => d,
101                Err(e) => return e.to_errno(),
102            }
103        }
104        Err(e) => return e.to_errno(),
105    };
106
107    // 获取文件元数据
108    let meta = match dentry.inode.metadata() {
109        Ok(m) => m,
110        Err(e) => return e.to_errno(),
111    };
112
113    // 检查 O_DIRECTORY (必须是目录)
114    if open_flags.contains(OpenFlags::O_DIRECTORY) {
115        if meta.inode_type != InodeType::Directory {
116            return FsError::NotDirectory.to_errno();
117        }
118    }
119
120    // 处理 O_TRUNC (截断文件)
121    if open_flags.contains(OpenFlags::O_TRUNC) && open_flags.writable() {
122        if meta.inode_type == InodeType::File {
123            if let Err(e) = dentry.inode.truncate(0) {
124                return e.to_errno();
125            }
126        }
127    }
128
129    // 创建 File 对象
130    let file = match create_file_from_dentry(dentry, open_flags) {
131        Ok(f) => f,
132        Err(e) => return e.to_errno(),
133    };
134
135    // 分配文件描述符
136    let task = current_cpu().lock().current_task.as_ref().unwrap().clone();
137    match task.lock().fd_table.alloc(file) {
138        Ok(fd) => fd as isize,
139        Err(e) => e.to_errno(),
140    }
141}
142
143pub fn mkdirat(dirfd: i32, pathname: *const c_char, mode: u32) -> isize {
144    // 解析路径
145    let _guard = SumGuard::new();
146    let path_str = match get_path_safe(pathname) {
147        Ok(s) => s.to_string(),
148        Err(_) => {
149            return FsError::InvalidArgument.to_errno();
150        }
151    };
152
153    // 分割路径为目录和文件名
154    let (dir_path, dirname) = match split_path(&path_str) {
155        Ok(p) => p,
156        Err(e) => return e.to_errno(),
157    };
158
159    // 查找父目录
160    let parent_dentry = match resolve_at_path(dirfd, &dir_path) {
161        Ok(Some(d)) => d,
162        Ok(None) => return FsError::NotFound.to_errno(),
163        Err(e) => return e.to_errno(),
164    };
165
166    // 创建目录
167    let dir_mode = FileMode::from_bits_truncate(mode) | FileMode::S_IFDIR;
168    match parent_dentry.inode.mkdir(&dirname, dir_mode) {
169        Ok(_) => 0,
170        Err(e) => e.to_errno(),
171    }
172}
173
174pub fn unlinkat(dirfd: i32, pathname: *const c_char, flags: u32) -> isize {
175    // 解析路径
176    let _guard = SumGuard::new();
177    let path_str = match get_path_safe(pathname) {
178        Ok(s) => s.to_string(),
179        Err(_) => {
180            return FsError::InvalidArgument.to_errno();
181        }
182    };
183
184    let is_rmdir = (flags & AT_REMOVEDIR) != 0;
185
186    // 分割路径
187    let (dir_path, filename) = match split_path(&path_str) {
188        Ok(p) => p,
189        Err(e) => return e.to_errno(),
190    };
191
192    // 查找父目录
193    let parent_dentry = match resolve_at_path(dirfd, &dir_path) {
194        Ok(Some(d)) => d,
195        Ok(None) => return FsError::NotFound.to_errno(),
196        Err(e) => return e.to_errno(),
197    };
198
199    // 检查目标文件类型
200    let target_inode = match parent_dentry.inode.lookup(&filename) {
201        Ok(i) => i,
202        Err(e) => return e.to_errno(),
203    };
204
205    let meta = match target_inode.metadata() {
206        Ok(m) => m,
207        Err(e) => return e.to_errno(),
208    };
209
210    // 验证文件类型与flags匹配
211    if is_rmdir {
212        // rmdir: 必须是目录
213        if meta.inode_type != InodeType::Directory {
214            return FsError::NotDirectory.to_errno();
215        }
216    } else {
217        // unlink: 不能是目录
218        if meta.inode_type == InodeType::Directory {
219            return FsError::IsDirectory.to_errno();
220        }
221    }
222
223    // 删除目录项
224    match parent_dentry.inode.unlink(&filename) {
225        Ok(()) => {
226            // 从缓存中移除
227            parent_dentry.remove_child(&filename);
228            0
229        }
230        Err(e) => e.to_errno(),
231    }
232}
233
234pub fn chdir(path: *const c_char) -> isize {
235    // 解析路径
236    let _guard = SumGuard::new();
237    let path_str = match get_path_safe(path) {
238        Ok(s) => s.to_string(),
239        Err(_) => {
240            return FsError::InvalidArgument.to_errno();
241        }
242    };
243
244    // 查找目标目录
245    let dentry = match vfs_lookup(&path_str) {
246        Ok(d) => d,
247        Err(e) => return e.to_errno(),
248    };
249
250    // 检查是否为目录
251    let meta = match dentry.inode.metadata() {
252        Ok(m) => m,
253        Err(e) => return e.to_errno(),
254    };
255
256    if meta.inode_type != InodeType::Directory {
257        return FsError::NotDirectory.to_errno();
258    }
259
260    // 更新当前工作目录
261    current_task().lock().fs.lock().cwd = Some(dentry);
262    0
263}
264
265pub fn getcwd(buf: *mut u8, size: usize) -> isize {
266    // 获取当前工作目录dentry
267    let cwd_dentry = match current_task().lock().fs.lock().cwd.clone() {
268        Some(d) => d,
269        None => return FsError::NotSupported.to_errno(),
270    };
271
272    // 获取完整路径
273    let path = cwd_dentry.full_path();
274    let path_bytes = path.as_bytes();
275
276    // 检查缓冲区大小
277    if path_bytes.len() + 1 > size {
278        return FsError::InvalidArgument.to_errno();
279    }
280
281    // 复制到用户态缓冲区
282    {
283        let _guard = SumGuard::new();
284        unsafe {
285            core::ptr::copy_nonoverlapping(path_bytes.as_ptr(), buf, path_bytes.len());
286            *buf.add(path_bytes.len()) = 0; // null terminator
287        }
288    }
289
290    buf as isize
291}
292
293pub fn fstat(fd: usize, statbuf: *mut Stat) -> isize {
294    // 检查指针有效性
295    if statbuf.is_null() {
296        return FsError::InvalidArgument.to_errno();
297    }
298
299    // 获取当前任务和文件对象
300    let task = current_cpu().lock().current_task.as_ref().unwrap().clone();
301    let file = match task.lock().fd_table.get(fd) {
302        Ok(f) => f,
303        Err(e) => return e.to_errno(),
304    };
305
306    // 获取文件元数据
307    let metadata = match file.metadata() {
308        Ok(m) => m,
309        Err(e) => return e.to_errno(),
310    };
311
312    // 转换为 Stat 结构
313    let stat = crate::vfs::Stat::from_metadata(&metadata);
314
315    // 写回用户空间
316    {
317        let _guard = SumGuard::new();
318        unsafe {
319            core::ptr::write(statbuf, stat);
320        }
321    }
322
323    0
324}
325
326pub fn getdents64(fd: usize, dirp: *mut u8, count: usize) -> isize {
327    use crate::vfs::{LinuxDirent64, inode_type_to_d_type};
328
329    // 检查参数有效性
330    if dirp.is_null() || count == 0 {
331        return FsError::InvalidArgument.to_errno();
332    }
333
334    // 获取当前任务和文件对象
335    let task = current_cpu().lock().current_task.as_ref().unwrap().clone();
336    let file = match task.lock().fd_table.get(fd) {
337        Ok(f) => f,
338        Err(e) => return e.to_errno(),
339    };
340
341    // 获取 inode(目录必须通过 inode 读取)
342    let inode = match file.inode() {
343        Ok(i) => i,
344        Err(e) => return e.to_errno(),
345    };
346
347    // 读取目录项
348    // TODO: readdir 返回所有项,对于大目录效率低,且 racey。
349    // 应改进为支持从 offset 读取,或者缓存 readdir 结果。
350    let entries = match inode.readdir() {
351        Ok(e) => e,
352        Err(e) => return e.to_errno(),
353    };
354
355    // 获取当前文件偏移量 (作为 entry 索引)
356    // 假设目录的 offset 就是 entry 的 index
357    let start_index = match file.lseek(0, SeekWhence::Cur) {
358        Ok(pos) => pos,
359        Err(e) => return e.to_errno(),
360    };
361
362    // 写入目录项到用户空间
363    let mut written = 0usize;
364    let mut items_written = 0usize;
365
366    unsafe {
367        let _guard = SumGuard::new();
368
369        for (_, entry) in entries.iter().skip(start_index).enumerate() {
370            // 计算这个 dirent 需要的空间
371            let dirent_len = LinuxDirent64::total_len(&entry.name);
372
373            // 检查缓冲区是否还有足够空间
374            if written + dirent_len > count {
375                break;
376            }
377
378            // 计算下一个 entry 的 offset (index + 1)
379            let current_off = (start_index + items_written + 1) as i64;
380
381            // 写入 dirent 头部
382            let dirent_ptr = dirp.add(written) as *mut LinuxDirent64;
383            core::ptr::write(
384                dirent_ptr,
385                LinuxDirent64 {
386                    d_ino: entry.inode_no as u64,
387                    d_off: current_off,
388                    d_reclen: dirent_len as u16,
389                    d_type: inode_type_to_d_type(entry.inode_type),
390                },
391            );
392
393            // 写入文件名
394            // 注意:LinuxDirent64 在 Rust 中由 padding (到 24 字节)
395            // 但 d_name 实际上应该从 offset 19 开始 (u64+u64+u16+u8 = 8+8+2+1 = 19)
396            // 我们必须覆盖 padding 区域
397            let name_ptr = dirp.add(written + 19);
398            let name_bytes = entry.name.as_bytes();
399            core::ptr::copy_nonoverlapping(name_bytes.as_ptr(), name_ptr, name_bytes.len());
400            // 添加 null 终止符
401            core::ptr::write(name_ptr.add(name_bytes.len()), 0);
402
403            written += dirent_len;
404            items_written += 1;
405        }
406    }
407
408    // 更新文件偏移量
409    if items_written > 0 {
410        // 更新为新的 index
411        if let Err(e) = file.lseek((start_index + items_written) as isize, SeekWhence::Set) {
412            crate::pr_warn!(
413                "[getdents64] failed to update file offset for fd {}: {:?}",
414                fd,
415                e
416            );
417            // 即使更新 offset 失败,我们已经写入了数据,返回 written 更合理。
418            // 下一次 getdents64 调用可能会重复读取一些条目,但这比丢失数据或为部分成功的读取返回错误要好。
419        }
420    }
421
422    // 返回写入的字节数
423    written as isize
424}
425
426pub fn statfs(path: *const c_char, buf: *mut LinuxStatFs) -> isize {
427    // 参数校验
428    if buf.is_null() {
429        return -(EINVAL as isize);
430    }
431
432    // 解析路径字符串
433    let _guard = SumGuard::new();
434    let path_str = match get_path_safe(path) {
435        Ok(s) => s.to_string(),
436        Err(_) => {
437            return -(EINVAL as isize);
438        }
439    };
440
441    // 验证路径存在
442    if vfs_lookup(&path_str).is_err() {
443        return -(EINVAL as isize);
444    }
445
446    // 通过 MOUNT_TABLE 查找文件系统
447    use crate::vfs::MOUNT_TABLE;
448    let mount_point = match MOUNT_TABLE.find_mount(&path_str) {
449        Some(mp) => mp,
450        None => return -(EINVAL as isize),
451    };
452
453    // 获取文件系统统计信息
454    let fs_stat = match mount_point.fs.statfs() {
455        Ok(s) => s,
456        Err(e) => return e.to_errno(),
457    };
458
459    // 转换为 Linux statfs 结构
460    let fs_type = FileSystemType::from_str(mount_point.fs.fs_type());
461
462    let statfs_buf = LinuxStatFs {
463        f_type: fs_type.magic(),
464        f_bsize: fs_stat.block_size as i64,
465        f_blocks: fs_stat.total_blocks as u64,
466        f_bfree: fs_stat.free_blocks as u64,
467        f_bavail: fs_stat.available_blocks as u64,
468        f_files: fs_stat.total_inodes as u64,
469        f_ffree: fs_stat.free_inodes as u64,
470        f_fsid: [
471            (fs_stat.fsid & 0xFFFFFFFF) as i32,
472            (fs_stat.fsid >> 32) as i32,
473        ],
474        f_namelen: fs_stat.max_filename_len as i64,
475        f_frsize: fs_stat.block_size as i64, // 片段大小等于块大小
476        f_flags: 0,                          // TODO: 添加挂载标志支持
477        f_spare: [0; 4],
478    };
479
480    // 写回用户空间
481    {
482        let _guard = SumGuard::new();
483        unsafe {
484            core::ptr::write(buf, statfs_buf);
485        }
486    }
487
488    0
489}
490
491pub fn faccessat(dirfd: i32, pathname: *const c_char, mode: i32, flags: u32) -> isize {
492    // 解析路径字符串
493    let _guard = SumGuard::new();
494    let path_str = match get_path_safe(pathname) {
495        Ok(s) => s.to_string(),
496        Err(_) => {
497            return -(EINVAL as isize);
498        }
499    };
500
501    // 解析标志
502    let at_flags = match AtFlags::from_bits(flags) {
503        Some(f) => f,
504        None => return -(EINVAL as isize),
505    };
506
507    // 查找文件
508    let follow_symlink = !at_flags.contains(AtFlags::SYMLINK_NOFOLLOW);
509    let dentry = match resolve_at_path_with_flags(dirfd, &path_str, follow_symlink) {
510        Ok(d) => d,
511        Err(e) => return e.to_errno(),
512    };
513
514    // 获取文件元数据
515    let meta = match dentry.inode.metadata() {
516        Ok(m) => m,
517        Err(e) => return e.to_errno(),
518    };
519
520    // F_OK 模式:仅检查文件是否存在
521    if mode == F_OK {
522        return 0;
523    }
524
525    // 检查权限
526    // TODO: 完整的权限检查需要考虑:
527    // - 进程的 uid/euid/gid/egid
528    // - 文件的 uid/gid/mode
529    // - Capabilities (CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH)
530    // - AT_EACCESS 标志(使用有效 UID 而非实际 UID)
531    //
532    // 临时实现:简化的权限检查
533
534    // 简化版:只检查文件权限位,假设当前用户有权限
535    if (mode & R_OK) != 0 {
536        // 检查是否有任何读权限位
537        if !meta.mode.contains(FileMode::S_IRUSR)
538            && !meta.mode.contains(FileMode::S_IRGRP)
539            && !meta.mode.contains(FileMode::S_IROTH)
540        {
541            return -(EACCES as isize);
542        }
543    }
544
545    if (mode & W_OK) != 0 {
546        // 检查是否有任何写权限位
547        if !meta.mode.contains(FileMode::S_IWUSR)
548            && !meta.mode.contains(FileMode::S_IWGRP)
549            && !meta.mode.contains(FileMode::S_IWOTH)
550        {
551            return -(EACCES as isize);
552        }
553    }
554
555    if (mode & X_OK) != 0 {
556        // 检查是否有任何执行权限位
557        if !meta.mode.contains(FileMode::S_IXUSR)
558            && !meta.mode.contains(FileMode::S_IXGRP)
559            && !meta.mode.contains(FileMode::S_IXOTH)
560        {
561            return -(EACCES as isize);
562        }
563    }
564
565    0
566}
567
568pub fn readlinkat(dirfd: i32, pathname: *const c_char, buf: *mut u8, bufsiz: usize) -> isize {
569    // 参数校验
570    if buf.is_null() || bufsiz == 0 {
571        return -(EINVAL as isize);
572    }
573
574    // 解析路径字符串
575    let _guard = SumGuard::new();
576    let path_str = match get_path_safe(pathname) {
577        Ok(s) => s.to_string(),
578        Err(_) => {
579            return -(EINVAL as isize);
580        }
581    };
582
583    // 查找符号链接(不跟随最后一级的符号链接)
584    let dentry = match resolve_at_path_with_flags(dirfd, &path_str, false) {
585        Ok(d) => d,
586        Err(e) => return e.to_errno(),
587    };
588
589    // 验证是符号链接
590    let meta = match dentry.inode.metadata() {
591        Ok(m) => m,
592        Err(e) => return e.to_errno(),
593    };
594
595    if meta.inode_type != InodeType::Symlink {
596        return -(EINVAL as isize);
597    }
598
599    // 读取符号链接目标(使用 read_at)
600    let read_size = core::cmp::min(meta.size, bufsiz);
601    let mut temp_buf = alloc::vec![0u8; read_size];
602
603    let bytes_read = match dentry.inode.read_at(0, &mut temp_buf) {
604        Ok(n) => n,
605        Err(e) => return e.to_errno(),
606    };
607
608    // 复制到用户空间(注意:readlink 不添加 null 终止符)
609    {
610        let _guard = SumGuard::new();
611        unsafe {
612            core::ptr::copy_nonoverlapping(temp_buf.as_ptr(), buf, bytes_read);
613        }
614    }
615
616    bytes_read as isize
617}
618
619pub fn newfstatat(dirfd: i32, pathname: *const c_char, statbuf: *mut Stat, flags: u32) -> isize {
620    // 参数校验
621    if statbuf.is_null() {
622        return -(EINVAL as isize);
623    }
624
625    // 解析路径
626    let _guard = SumGuard::new();
627    let path_str = match get_path_safe(pathname) {
628        Ok(s) => s.to_string(),
629        Err(_) => {
630            return -(EINVAL as isize);
631        }
632    };
633
634    // 解析标志
635    let at_flags = match AtFlags::from_bits(flags) {
636        Some(f) => f,
637        None => return -(EINVAL as isize),
638    };
639
640    // 处理 AT_EMPTY_PATH 标志
641    if path_str.is_empty() && at_flags.contains(AtFlags::EMPTY_PATH) {
642        if dirfd == AT_FDCWD {
643            return -(EINVAL as isize);
644        }
645        // 对 dirfd 执行 fstat
646        return fstat(dirfd as usize, statbuf);
647    }
648
649    // 查找文件
650    let follow_symlink = !at_flags.contains(AtFlags::SYMLINK_NOFOLLOW);
651    let dentry = match resolve_at_path_with_flags(dirfd, &path_str, follow_symlink) {
652        Ok(d) => d,
653        Err(e) => return e.to_errno(),
654    };
655
656    // 获取文件元数据
657    let metadata = match dentry.inode.metadata() {
658        Ok(m) => m,
659        Err(e) => return e.to_errno(),
660    };
661
662    // 转换为 Stat 结构
663    let stat = Stat::from_metadata(&metadata);
664
665    // 写回用户空间
666    {
667        let _guard = SumGuard::new();
668        unsafe {
669            core::ptr::write(statbuf, stat);
670        }
671    }
672
673    0
674}
675
676pub fn utimensat(dirfd: i32, pathname: *const c_char, times: *const TimeSpec, flags: u32) -> isize {
677    // 解析路径
678    let _guard = SumGuard::new();
679    let path_str = match get_path_safe(pathname) {
680        Ok(s) => s.to_string(),
681        Err(_) => {
682            return -(EINVAL as isize);
683        }
684    };
685
686    // 解析标志
687    let at_flags = match AtFlags::from_bits(flags) {
688        Some(f) => f,
689        None => return -(EINVAL as isize),
690    };
691
692    // 查找文件
693    let follow_symlink = !at_flags.contains(AtFlags::SYMLINK_NOFOLLOW);
694    let dentry = match resolve_at_path_with_flags(dirfd, &path_str, follow_symlink) {
695        Ok(d) => d,
696        Err(e) => return e.to_errno(),
697    };
698
699    // 解析时间参数
700    let (atime_opt, mtime_opt) = if times.is_null() {
701        // NULL 表示将两个时间都设置为当前时间
702        let now = TimeSpec::now();
703        (Some(now), Some(now))
704    } else {
705        unsafe {
706            let _guard = SumGuard::new();
707            let user_times = core::slice::from_raw_parts(times, 2);
708
709            // 验证时间结构
710            if let Err(e) = user_times[0].validate() {
711                return -(e as isize);
712            }
713            if let Err(e) = user_times[1].validate() {
714                return -(e as isize);
715            }
716
717            // 处理访问时间
718            let atime_opt = if user_times[0].is_omit() {
719                None // 不修改
720            } else if user_times[0].is_now() {
721                Some(TimeSpec::now())
722            } else {
723                Some(user_times[0])
724            };
725
726            // 处理修改时间
727            let mtime_opt = if user_times[1].is_omit() {
728                None
729            } else if user_times[1].is_now() {
730                Some(TimeSpec::now())
731            } else {
732                Some(user_times[1])
733            };
734
735            (atime_opt, mtime_opt)
736        }
737    };
738
739    // 设置时间戳
740    if let Err(e) = dentry.inode.set_times(atime_opt, mtime_opt) {
741        return e.to_errno();
742    }
743
744    0
745}
746
747/// 重命名或移动文件/目录
748pub fn renameat2(
749    olddirfd: i32,
750    oldpath: *const c_char,
751    newdirfd: i32,
752    newpath: *const c_char,
753    flags: u32,
754) -> isize {
755    use crate::uapi::{
756        errno::{EEXIST, ENOTDIR},
757        fs::RenameFlags,
758    };
759
760    // 解析标志
761    let rename_flags = match RenameFlags::from_bits(flags) {
762        Some(f) => f,
763        None => return -(EINVAL as isize),
764    };
765
766    // 检查标志组合的合法性
767    if !rename_flags.is_valid() {
768        return -(EINVAL as isize);
769    }
770
771    // 解析旧路径
772    let _guard = SumGuard::new();
773    let old_path_str = match get_path_safe(oldpath) {
774        Ok(s) => s.to_string(),
775        Err(_) => {
776            return -(EINVAL as isize);
777        }
778    };
779
780    // 解析新路径
781    let new_path_str = match get_path_safe(newpath) {
782        Ok(s) => s.to_string(),
783        Err(_) => {
784            return -(EINVAL as isize);
785        }
786    };
787
788    // 分割路径为 (父目录, 文件名)
789    let (old_dir_path, old_name) = match split_path(&old_path_str) {
790        Ok(p) => p,
791        Err(e) => return e.to_errno(),
792    };
793
794    let (new_dir_path, new_name) = match split_path(&new_path_str) {
795        Ok(p) => p,
796        Err(e) => return e.to_errno(),
797    };
798
799    // 查找父目录
800    let old_parent = match resolve_at_path(olddirfd, &old_dir_path) {
801        Ok(Some(d)) => d,
802        Ok(None) => return -(ENOENT as isize),
803        Err(e) => return e.to_errno(),
804    };
805
806    let new_parent = match resolve_at_path(newdirfd, &new_dir_path) {
807        Ok(Some(d)) => d,
808        Ok(None) => return -(ENOENT as isize),
809        Err(e) => return e.to_errno(),
810    };
811
812    // 验证父目录是目录
813    let old_parent_meta = match old_parent.inode.metadata() {
814        Ok(m) => m,
815        Err(e) => return e.to_errno(),
816    };
817    if old_parent_meta.inode_type != InodeType::Directory {
818        return -(ENOTDIR as isize);
819    }
820
821    let new_parent_meta = match new_parent.inode.metadata() {
822        Ok(m) => m,
823        Err(e) => return e.to_errno(),
824    };
825    if new_parent_meta.inode_type != InodeType::Directory {
826        return -(ENOTDIR as isize);
827    }
828
829    // 查找源文件(验证存在)
830    let _old_inode = match old_parent.inode.lookup(&old_name) {
831        Ok(inode) => inode,
832        Err(e) => return e.to_errno(),
833    };
834
835    // 处理不同的重命名标志
836    if rename_flags.contains(RenameFlags::EXCHANGE) {
837        // ⚠️ 非原子交换实现警告 ⚠️
838        //
839        // 由于 ext4_rs 缺少事务日志支持,此实现通过三步操作模拟原子交换:
840        //   1. old_name -> temp_name
841        //   2. new_name -> old_name
842        //   3. temp_name -> new_name
843        //
844        // 安全性限制:
845        // - 在步骤 2/3 失败时会尝试回滚,但回滚本身可能失败
846        // - 系统崩溃可能导致文件丢失或重复
847        // - 不满足 POSIX 的原子性要求
848        //
849        // 建议:
850        // - 仅在非关键场景使用
851        // - 操作后调用 sync() 减少崩溃风险
852
853        crate::pr_warn!(
854            "[renameat2] EXCHANGE is non-atomic: {} <-> {} (no transaction support)",
855            old_name,
856            new_name
857        );
858
859        // 验证目标文件存在
860        let _new_inode = match new_parent.inode.lookup(&new_name) {
861            Ok(inode) => inode,
862            Err(e) => {
863                crate::pr_err!(
864                    "[renameat2] EXCHANGE failed: target '{}' does not exist (error: {:?})",
865                    new_name,
866                    e
867                );
868                return -(ENOENT as isize); // EXCHANGE 要求目标必须存在
869            }
870        };
871
872        // 生成临时文件名(使用时间戳或特殊前缀避免冲突)
873        let temp_name = alloc::format!(".rename_temp_{}_{}", old_name, new_name);
874
875        crate::pr_debug!(
876            "[renameat2] EXCHANGE step 1/3: '{}' -> '{}' (temp)",
877            old_name,
878            temp_name
879        );
880
881        // 步骤1: old_name -> temp_name
882        if let Err(e) = old_parent
883            .inode
884            .rename(&old_name, old_parent.inode.clone(), &temp_name)
885        {
886            crate::pr_err!(
887                "[renameat2] EXCHANGE step 1/3 failed: '{}' -> '{}' (error: {:?})",
888                old_name,
889                temp_name,
890                e
891            );
892            return e.to_errno();
893        }
894
895        crate::pr_debug!(
896            "[renameat2] EXCHANGE step 2/3: '{}' -> '{}'",
897            new_name,
898            old_name
899        );
900
901        // 步骤2: new_name -> old_name
902        if let Err(e) = new_parent
903            .inode
904            .rename(&new_name, old_parent.inode.clone(), &old_name)
905        {
906            crate::pr_err!(
907                "[renameat2] EXCHANGE step 2/3 failed: '{}' -> '{}' (error: {:?})",
908                new_name,
909                old_name,
910                e
911            );
912
913            // 尝试回滚步骤1
914            crate::pr_warn!(
915                "[renameat2] Attempting rollback: '{}' -> '{}'",
916                temp_name,
917                old_name
918            );
919
920            match old_parent
921                .inode
922                .rename(&temp_name, old_parent.inode.clone(), &old_name)
923            {
924                Ok(_) => {
925                    crate::pr_info!("[renameat2] Rollback successful: restored '{}'", old_name);
926                }
927                Err(rollback_err) => {
928                    crate::pr_err!(
929                        "[renameat2] CRITICAL: Rollback failed! File '{}' may be lost or duplicated (error: {:?})",
930                        old_name,
931                        rollback_err
932                    );
933                    crate::pr_err!(
934                        "[renameat2] File system may be in inconsistent state. Temp file '{}' exists.",
935                        temp_name
936                    );
937                }
938            }
939
940            return e.to_errno();
941        }
942
943        crate::pr_debug!(
944            "[renameat2] EXCHANGE step 3/3: '{}' (temp) -> '{}'",
945            temp_name,
946            new_name
947        );
948
949        // 步骤3: temp_name -> new_name
950        if let Err(e) = old_parent
951            .inode
952            .rename(&temp_name, new_parent.inode.clone(), &new_name)
953        {
954            crate::pr_err!(
955                "[renameat2] EXCHANGE step 3/3 failed: '{}' -> '{}' (error: {:?})",
956                temp_name,
957                new_name,
958                e
959            );
960
961            // 尝试回滚步骤2和步骤1
962            crate::pr_warn!("[renameat2] Attempting full rollback (2 operations)");
963
964            let mut rollback_success = true;
965
966            // 回滚步骤2: old_name -> new_name
967            crate::pr_debug!("[renameat2] Rollback 1/2: '{}' -> '{}'", old_name, new_name);
968            match old_parent
969                .inode
970                .rename(&old_name, new_parent.inode.clone(), &new_name)
971            {
972                Ok(_) => {
973                    crate::pr_debug!("[renameat2] Rollback 1/2 successful");
974                }
975                Err(rollback_err) => {
976                    crate::pr_err!(
977                        "[renameat2] CRITICAL: Rollback 1/2 failed! '{}' -> '{}' (error: {:?})",
978                        old_name,
979                        new_name,
980                        rollback_err
981                    );
982                    rollback_success = false;
983                }
984            }
985
986            // 回滚步骤1: temp_name -> old_name
987            crate::pr_debug!(
988                "[renameat2] Rollback 2/2: '{}' -> '{}'",
989                temp_name,
990                old_name
991            );
992            match old_parent
993                .inode
994                .rename(&temp_name, old_parent.inode.clone(), &old_name)
995            {
996                Ok(_) => {
997                    crate::pr_debug!("[renameat2] Rollback 2/2 successful");
998                }
999                Err(rollback_err) => {
1000                    crate::pr_err!(
1001                        "[renameat2] CRITICAL: Rollback 2/2 failed! '{}' -> '{}' (error: {:?})",
1002                        temp_name,
1003                        old_name,
1004                        rollback_err
1005                    );
1006                    rollback_success = false;
1007                }
1008            }
1009
1010            if rollback_success {
1011                crate::pr_info!(
1012                    "[renameat2] Full rollback successful: files restored to original state"
1013                );
1014            } else {
1015                crate::pr_err!("[renameat2] CRITICAL: Partial or complete rollback failure!");
1016                crate::pr_err!(
1017                    "[renameat2] File system is in INCONSISTENT STATE. Manual recovery may be required."
1018                );
1019                crate::pr_err!(
1020                    "[renameat2] Affected files: '{}', '{}', temp '{}'",
1021                    old_name,
1022                    new_name,
1023                    temp_name
1024                );
1025            }
1026
1027            return e.to_errno();
1028        }
1029
1030        crate::pr_info!(
1031            "[renameat2] EXCHANGE completed: '{}' <-> '{}'",
1032            old_name,
1033            new_name
1034        );
1035
1036        // 更新 dentry 缓存
1037        old_parent.remove_child(&old_name);
1038        old_parent.remove_child(&temp_name);
1039        new_parent.remove_child(&new_name);
1040    } else if rename_flags.contains(RenameFlags::NOREPLACE) {
1041        // 目标存在时失败
1042        if new_parent.inode.lookup(&new_name).is_ok() {
1043            return -(EEXIST as isize);
1044        }
1045
1046        // 执行重命名
1047        if let Err(e) = old_parent
1048            .inode
1049            .rename(&old_name, new_parent.inode.clone(), &new_name)
1050        {
1051            return e.to_errno();
1052        }
1053
1054        // 更新 dentry 缓存
1055        old_parent.remove_child(&old_name);
1056    } else if rename_flags.contains(RenameFlags::WHITEOUT) {
1057        // WHITEOUT 暂不支持(需要 Union FS 支持)
1058        return FsError::NotSupported.to_errno();
1059    } else {
1060        // 普通重命名/移动(允许覆盖目标)
1061        if let Err(e) = old_parent
1062            .inode
1063            .rename(&old_name, new_parent.inode.clone(), &new_name)
1064        {
1065            return e.to_errno();
1066        }
1067
1068        // 更新 dentry 缓存
1069        old_parent.remove_child(&old_name);
1070        new_parent.remove_child(&new_name);
1071    }
1072
1073    0
1074}
1075
1076/// mount - 挂载文件系统
1077///
1078/// # 系统调用号
1079/// 40 (SYS_MOUNT)
1080///
1081/// # 简化实现说明
1082/// - 只支持 ext4 文件系统(忽略 filesystemtype 参数)
1083/// - 使用第一个可用的块设备(忽略 source 参数)
1084/// - 忽略所有 mountflags(但保留以保持 ABI 兼容)
1085/// - 忽略 data 参数
1086pub fn mount(
1087    source: *const c_char,
1088    target: *const c_char,
1089    filesystemtype: *const c_char,
1090    _mountflags: u64,
1091    _data: *const core::ffi::c_void,
1092) -> isize {
1093    use crate::config::EXT4_BLOCK_SIZE;
1094    use crate::fs::ext4::Ext4FileSystem;
1095    use crate::fs::sysfs::find_block_device;
1096    use crate::fs::{init_dev, init_procfs, init_sysfs, mount_tmpfs};
1097    use crate::vfs::{MOUNT_TABLE, MountFlags as VfsMountFlags};
1098    use alloc::string::String;
1099
1100    // 启用用户空间内存访问
1101    let _guard = SumGuard::new();
1102
1103    // 解析目标路径
1104    let target_str = match get_path_safe(target) {
1105        Ok(s) => s.to_string(),
1106        Err(_) => {
1107            return FsError::InvalidArgument.to_errno();
1108        }
1109    };
1110
1111    // 解析 source (可能为空)
1112    let source_str = if !source.is_null() {
1113        match get_path_safe(source) {
1114            Ok(s) => s.to_string(),
1115            Err(_) => {
1116                return FsError::InvalidArgument.to_errno();
1117            }
1118        }
1119    } else {
1120        String::new()
1121    };
1122
1123    // 解析 filesystemtype (可能为空)
1124    let fstype_str = if !filesystemtype.is_null() {
1125        match get_path_safe(filesystemtype) {
1126            Ok(s) => s.to_string(),
1127            Err(_) => {
1128                return FsError::InvalidArgument.to_errno();
1129            }
1130        }
1131    } else {
1132        String::new()
1133    };
1134
1135    crate::pr_info!(
1136        "[SYSCALL] mount: source='{}', target='{}', type='{}'",
1137        source_str,
1138        target_str,
1139        fstype_str
1140    );
1141
1142    // 特殊挂载点处理
1143    match target_str.as_str() {
1144        "/proc" => {
1145            return match init_procfs() {
1146                Ok(_) => 0,
1147                Err(e) => e.to_errno(),
1148            };
1149        }
1150        "/sys" => {
1151            return match init_sysfs() {
1152                Ok(_) => 0,
1153                Err(e) => e.to_errno(),
1154            };
1155        }
1156        "/tmp" => {
1157            return match mount_tmpfs("/tmp", 0) {
1158                Ok(_) => 0,
1159                Err(e) => e.to_errno(),
1160            };
1161        }
1162        "/dev" => {
1163            // 先挂载 tmpfs 到 /dev
1164            if let Err(e) = mount_tmpfs("/dev", 0) {
1165                return e.to_errno();
1166            }
1167            // 然后初始化设备节点
1168            return match init_dev() {
1169                Ok(_) => 0,
1170                Err(e) => e.to_errno(),
1171            };
1172        }
1173        _ => {}
1174    }
1175
1176    // 通用挂载逻辑 (目前只支持 ext4)
1177    if fstype_str == "ext4" {
1178        // 查找块设备
1179        let dev_info = match find_block_device(&source_str) {
1180            Some(info) => info,
1181            None => {
1182                crate::pr_err!("[SYSCALL] mount: block device '{}' not found", source_str);
1183                return -(ENOENT as isize);
1184            }
1185        };
1186
1187        let block_device = dev_info.device;
1188
1189        // 创建 Ext4 文件系统
1190        let block_size = EXT4_BLOCK_SIZE;
1191        // 注意:这里我们无法直接知道设备的总块数,
1192        // 但 Ext4FileSystem::open 通常会读取超级块来获取这些信息,
1193        // 或者我们可以从 block_device 获取容量。
1194        // 暂时使用 fs.img 的默认大小计算,或者让 Ext4FileSystem 自己处理。
1195        // 为了兼容现有 API,我们尝试从设备获取大小。
1196        let total_blocks = block_device.total_blocks();
1197
1198        let ext4_fs = match Ext4FileSystem::open(block_device.clone(), block_size, total_blocks, 0)
1199        {
1200            Ok(fs) => fs,
1201            Err(e) => {
1202                crate::pr_err!("[SYSCALL] mount: failed to open ext4: {:?}", e);
1203                return e.to_errno();
1204            }
1205        };
1206
1207        // 挂载文件系统
1208        match MOUNT_TABLE.mount(
1209            ext4_fs,
1210            &target_str,
1211            VfsMountFlags::empty(),
1212            Some(source_str),
1213        ) {
1214            Ok(()) => {
1215                crate::pr_info!(
1216                    "[SYSCALL] mount: successfully mounted ext4 at '{}'",
1217                    target_str
1218                );
1219                return 0;
1220            }
1221            Err(e) => {
1222                crate::pr_err!("[SYSCALL] mount: failed: {:?}", e);
1223                return e.to_errno();
1224            }
1225        }
1226    }
1227
1228    crate::pr_err!(
1229        "[SYSCALL] mount: unsupported filesystem type '{}' or target '{}'",
1230        fstype_str,
1231        target_str
1232    );
1233    -(EINVAL as isize)
1234}
1235
1236/// umount2 - 卸载文件系统
1237///
1238/// # 系统调用号
1239/// 39 (SYS_UMOUNT2)
1240///
1241/// # 简化实现说明
1242/// - 忽略 flags 参数(但保留以保持 ABI 兼容)
1243/// - 不检查文件是否被占用
1244/// - 直接调用 MOUNT_TABLE.umount()
1245pub fn umount2(target: *const c_char, _flags: i32) -> isize {
1246    use crate::vfs::MOUNT_TABLE;
1247
1248    // 启用用户空间内存访问
1249    let _guard = SumGuard::new();
1250
1251    // 解析目标路径
1252    let target_str = match get_path_safe(target) {
1253        Ok(s) => s.to_string(),
1254        Err(_) => {
1255            return FsError::InvalidArgument.to_errno();
1256        }
1257    };
1258
1259    crate::pr_info!("[SYSCALL] umount2: unmounting '{}'", target_str);
1260
1261    // 卸载文件系统
1262
1263    // 注意:MOUNT_TABLE.umount() 会自动调用 fs.sync()
1264    match MOUNT_TABLE.umount(&target_str) {
1265        Ok(()) => {
1266            crate::pr_info!("[SYSCALL] umount2: successfully unmounted '{}'", target_str);
1267            0
1268        }
1269        Err(e) => {
1270            crate::pr_err!("[SYSCALL] umount2: failed: {:?}", e);
1271            e.to_errno()
1272        }
1273    }
1274}
1275
1276/// 同步所有文件系统
1277///
1278/// # 实现说明
1279/// 由于 Comix 使用写直达架构,数据已在块设备中,
1280/// 此调用只需刷新硬件写缓存。
1281pub fn sync() -> isize {
1282    use crate::kernel::syscall::util::flush_all_block_devices;
1283
1284    // sync 总是成功(即使 flush 失败也不返回错误)
1285    let _ = flush_all_block_devices();
1286    0
1287}
1288
1289/// syncfs - 同步指定文件系统
1290pub fn syncfs(fd: usize) -> isize {
1291    use crate::kernel::syscall::util::flush_block_device_by_fd;
1292
1293    match flush_block_device_by_fd(fd) {
1294        Ok(()) => 0,
1295        Err(errno) => errno,
1296    }
1297}
1298
1299/// fsync - 同步文件数据和元数据
1300///
1301/// # 实现说明
1302/// 在写直达架构下,等同于 syncfs
1303pub fn fsync(fd: usize) -> isize {
1304    syncfs(fd)
1305}
1306
1307/// fdatasync - 同步文件数据(元数据可选)
1308///
1309/// # 实现说明
1310/// 在写直达架构下,完全等同于 fsync
1311pub fn fdatasync(fd: usize) -> isize {
1312    fsync(fd)
1313}
1314
1315/// fchownat - 修改文件所有者和组
1316///
1317/// # 参数
1318/// * `dirfd` - 目录文件描述符(AT_FDCWD 表示当前目录)
1319/// * `pathname` - 文件路径
1320/// * `owner` - 新的用户 ID(u32::MAX 表示不改变)
1321/// * `group` - 新的组 ID(u32::MAX 表示不改变)
1322/// * `flags` - 标志位(AT_SYMLINK_NOFOLLOW、AT_EMPTY_PATH 等)
1323///
1324/// # 返回值
1325/// * 0 - 成功
1326/// * -errno - 失败
1327///
1328/// # 在单 root 用户系统中的行为
1329/// 所有调用都会成功并更新 inode 的 uid/gid 字段,不进行权限检查
1330pub fn fchownat(dirfd: i32, pathname: *const c_char, owner: u32, group: u32, flags: u32) -> isize {
1331    use crate::uapi::fs::AtFlags;
1332
1333    // 解析路径字符串
1334    let _guard = SumGuard::new();
1335    let path_str = match get_path_safe(pathname) {
1336        Ok(s) => s.to_string(),
1337        Err(_) => {
1338            return -(EINVAL as isize);
1339        }
1340    };
1341
1342    // 解析标志位
1343    let at_flags = AtFlags::from_bits_truncate(flags);
1344    let follow_symlink = !at_flags.contains(AtFlags::SYMLINK_NOFOLLOW);
1345    let empty_path = at_flags.contains(AtFlags::EMPTY_PATH);
1346
1347    // 处理 AT_EMPTY_PATH 情况
1348    if empty_path && path_str.is_empty() {
1349        // pathname 为空,操作 dirfd 本身
1350        if dirfd == AT_FDCWD {
1351            // 不能对当前目录使用 AT_EMPTY_PATH
1352            return -(EINVAL as isize);
1353        }
1354
1355        let task = current_task();
1356        let file = match task.lock().fd_table.get(dirfd as usize) {
1357            Ok(f) => f,
1358            Err(e) => return e.to_errno(),
1359        };
1360
1361        let dentry = match file.dentry() {
1362            Ok(d) => d,
1363            Err(e) => return e.to_errno(),
1364        };
1365
1366        return match dentry.inode.chown(owner, group) {
1367            Ok(()) => 0,
1368            Err(e) => e.to_errno(),
1369        };
1370    }
1371
1372    // 解析路径,获取 dentry(使用辅助函数)
1373    let dentry = match resolve_at_path_with_flags(dirfd, &path_str, follow_symlink) {
1374        Ok(d) => d,
1375        Err(e) => return e.to_errno(),
1376    };
1377
1378    // 调用 inode 的 chown 方法
1379    match dentry.inode.chown(owner, group) {
1380        Ok(()) => 0,
1381        Err(e) => e.to_errno(),
1382    }
1383}
1384
1385/// fchmodat - 修改文件权限模式
1386///
1387/// # 参数
1388/// * `dirfd` - 目录文件描述符(AT_FDCWD 表示当前目录)
1389/// * `pathname` - 文件路径
1390/// * `mode` - 新的权限模式(12 位权限位)
1391/// * `flags` - 标志位(AT_SYMLINK_NOFOLLOW 等)
1392///
1393/// # 返回值
1394/// * 0 - 成功
1395/// * -errno - 失败
1396///
1397/// # 在单 root 用户系统中的行为
1398/// 所有调用都会成功并更新 inode 的 mode 字段,不进行权限检查
1399pub fn fchmodat(dirfd: i32, pathname: *const c_char, mode: u32, flags: u32) -> isize {
1400    use crate::uapi::fs::AtFlags;
1401
1402    // 解析路径字符串
1403    let _guard = SumGuard::new();
1404    let path_str = match get_path_safe(pathname) {
1405        Ok(s) => s.to_string(),
1406        Err(_) => {
1407            return -(EINVAL as isize);
1408        }
1409    };
1410
1411    // 解析标志位
1412    let at_flags = AtFlags::from_bits_truncate(flags);
1413    let follow_symlink = !at_flags.contains(AtFlags::SYMLINK_NOFOLLOW);
1414
1415    // 验证 mode 参数(只保留权限位,去除文件类型位)
1416    let mode = mode & 0o7777; // 保留 12 位权限位(包括 setuid/setgid/sticky)
1417    let file_mode = match FileMode::from_bits(mode) {
1418        Some(m) => m,
1419        None => return -(EINVAL as isize),
1420    };
1421
1422    // 解析路径,获取 dentry(使用辅助函数)
1423    let dentry = match resolve_at_path_with_flags(dirfd, &path_str, follow_symlink) {
1424        Ok(d) => d,
1425        Err(e) => return e.to_errno(),
1426    };
1427
1428    // 调用 inode 的 chmod 方法
1429    match dentry.inode.chmod(file_mode) {
1430        Ok(()) => 0,
1431        Err(e) => e.to_errno(),
1432    }
1433}
1434
1435/// mknodat 系统调用
1436///
1437/// # 参数
1438/// - `dirfd`: 目录文件描述符(-100 表示当前工作目录)
1439/// - `pathname`: 路径名
1440/// - `mode`: 文件模式(包含类型和权限)
1441/// - `dev`: 设备号
1442///
1443/// # 返回
1444/// * 0: 成功
1445/// * -errno - 失败
1446pub fn mknodat(dirfd: i32, pathname: *const c_char, mode: u32, dev: u64) -> isize {
1447    // 安全地读取路径字符串
1448    let _guard = SumGuard::new();
1449    let path_str = match get_path_safe(pathname) {
1450        Ok(s) => s.to_string(),
1451        Err(_) => {
1452            return FsError::InvalidArgument.to_errno();
1453        }
1454    };
1455
1456    // 分割路径为目录和文件名
1457    let (dir_path, filename) = match split_path(&path_str) {
1458        Ok(p) => p,
1459        Err(e) => return e.to_errno(),
1460    };
1461
1462    // 解析父目录路径
1463    let parent_dentry = match resolve_at_path(dirfd, &dir_path) {
1464        Ok(Some(d)) => d,
1465        Ok(None) => return FsError::NotFound.to_errno(),
1466        Err(e) => return e.to_errno(),
1467    };
1468
1469    // 构造文件模式
1470    let file_mode = FileMode::from_bits_truncate(mode);
1471
1472    // 调用 inode.mknod()
1473    match parent_dentry.inode.mknod(&filename, file_mode, dev) {
1474        Ok(child_inode) => {
1475            // 创建 dentry 并加入缓存
1476            let child_dentry = Dentry::new(filename.clone(), child_inode);
1477            parent_dentry.add_child(child_dentry.clone());
1478            DENTRY_CACHE.insert(&child_dentry);
1479            0
1480        }
1481        Err(e) => e.to_errno(),
1482    }
1483}
1484
1485/// symlinkat - 创建符号链接
1486///
1487/// # 参数
1488/// * `target` - 符号链接的目标路径(可以是相对或绝对路径)
1489/// * `newdirfd` - 新符号链接所在目录的文件描述符
1490/// * `linkpath` - 新符号链接的路径
1491///
1492/// # 返回值
1493/// * 0 - 成功
1494/// * -errno - 失败
1495///
1496/// # 注意
1497/// target 参数不会被检查,即使目标不存在也能创建符号链接
1498pub fn symlinkat(target: *const c_char, newdirfd: i32, linkpath: *const c_char) -> isize {
1499    // 解析 target 路径
1500    let _guard = SumGuard::new();
1501    let target_str = match get_path_safe(target) {
1502        Ok(s) => s.to_string(),
1503        Err(_) => {
1504            return FsError::InvalidArgument.to_errno();
1505        }
1506    };
1507
1508    // 解析 linkpath 路径
1509    let link_str = match get_path_safe(linkpath) {
1510        Ok(s) => s.to_string(),
1511        Err(_) => {
1512            return FsError::InvalidArgument.to_errno();
1513        }
1514    };
1515
1516    // 分割路径为目录和文件名
1517    let (dir_path, link_name) = match split_path(&link_str) {
1518        Ok(p) => p,
1519        Err(e) => return e.to_errno(),
1520    };
1521
1522    // 查找父目录
1523    let parent_dentry = match resolve_at_path(newdirfd, &dir_path) {
1524        Ok(Some(d)) => d,
1525        Ok(None) => return FsError::NotFound.to_errno(),
1526        Err(e) => return e.to_errno(),
1527    };
1528
1529    // 创建符号链接
1530    match parent_dentry.inode.symlink(&link_name, &target_str) {
1531        Ok(symlink_inode) => {
1532            // 创建 dentry 并加入缓存
1533            let symlink_dentry = Dentry::new(link_name.clone(), symlink_inode);
1534            parent_dentry.add_child(symlink_dentry.clone());
1535            DENTRY_CACHE.insert(&symlink_dentry);
1536            0
1537        }
1538        Err(e) => e.to_errno(),
1539    }
1540}