kernel/fs/
syscall.rs

1use alloc::{string::ToString, vec::Vec};
2
3use crate::{arch::Trapframe, task::mytask};
4
5use super::{File, SeekFrom, VfsManager, MAX_PATH_LENGTH};
6
7pub fn sys_open(trapframe: &mut Trapframe) -> usize {
8    let task = mytask().unwrap();
9    let path_ptr = task.vm_manager.translate_vaddr(trapframe.get_arg(0)).unwrap() as *const u8;
10    let _flags = trapframe.get_arg(1) as i32;
11    let _mode = trapframe.get_arg(2) as i32;
12
13    // Increment PC to avoid infinite loop if open fails
14    trapframe.epc += 4;
15
16    // Parse path as a null-terminated C string
17    let mut path_bytes = Vec::new();
18    let mut i = 0;
19    unsafe {
20        loop {
21            let byte = *path_ptr.add(i);
22            if byte == 0 {
23                break;
24            }
25            path_bytes.push(byte);
26            i += 1;
27
28            if i > MAX_PATH_LENGTH {
29                return usize::MAX; // Path too long
30            }
31        }
32    }
33
34    // Convert path bytes to string
35    let path_str = match str::from_utf8(&path_bytes) {
36        Ok(s) => VfsManager::to_absolute_path(&task, s).unwrap(),
37        Err(_) => return usize::MAX, // Invalid UTF-8
38    };
39
40    // Try to open the file
41    let vfs = match task.vfs.as_ref() {
42        Some(vfs) => vfs,
43        None => return usize::MAX, // VFS not initialized
44    };
45    let file = vfs.open(&path_str, 0);
46    match file {
47        Ok(file) => {
48            // Register the file with the task
49            let fd = task.add_file(file);
50            if fd.is_err() {
51                return usize::MAX; // File descriptor error
52            }
53            fd.unwrap() as usize
54        }
55        Err(_) => usize::MAX, // File open error
56    }
57}
58
59pub fn sys_close(trapframe: &mut Trapframe) -> usize {
60    let task = mytask().unwrap();
61    let fd = trapframe.get_arg(0) as usize;
62    trapframe.epc += 4;
63    if task.remove_file(fd).is_ok() {
64        0
65    } else {
66        usize::MAX // -1
67    }
68}
69
70pub fn sys_read(trapframe: &mut Trapframe) -> usize {
71    let task = mytask().unwrap();
72    let fd = trapframe.get_arg(0) as usize;
73    let buf_ptr = task.vm_manager.translate_vaddr(trapframe.get_arg(1)).unwrap() as *mut u8;
74    let count = trapframe.get_arg(2) as usize;
75
76    // Increment PC to avoid infinite loop if read fails
77    trapframe.epc += 4;
78
79    let file = task.get_mut_file(fd);
80    if file.is_none() {
81        return usize::MAX; // Invalid file descriptor
82    }
83
84    let file = file.unwrap();
85
86    let buffer = unsafe { core::slice::from_raw_parts_mut(buf_ptr, count) };
87    
88    match file.read(buffer) {
89        Ok(n) => {
90            n
91        }
92        Err(_) => {
93            return usize::MAX; // Read error
94        }
95    }
96}
97
98pub fn sys_write(trapframe: &mut Trapframe) -> usize {
99    let task = mytask().unwrap();
100    let fd = trapframe.get_arg(0) as usize;
101    let buf_ptr = task.vm_manager.translate_vaddr(trapframe.get_arg(1)).unwrap() as *const u8;
102    let count = trapframe.get_arg(2) as usize;
103
104    // Increment PC to avoid infinite loop if write fails
105    trapframe.epc += 4;
106
107    let file = task.get_mut_file(fd);
108    if file.is_none() {
109        return usize::MAX; // Invalid file descriptor
110    }
111
112    let file = file.unwrap();
113
114    let buffer = unsafe { core::slice::from_raw_parts(buf_ptr, count) };
115    
116    match file.write(buffer) {
117        Ok(n) => {
118            n
119        }
120        Err(_) => {
121            return usize::MAX; // Write error
122        }
123    }
124}
125
126pub fn sys_lseek(trapframe: &mut Trapframe) -> usize {
127    let task = mytask().unwrap();
128    let fd = trapframe.get_arg(0) as usize;
129    let offset = trapframe.get_arg(1) as i64;
130    let whence = trapframe.get_arg(2) as i32;
131
132    // Increment PC to avoid infinite loop if lseek fails
133    trapframe.epc += 4;
134
135    let file = task.get_mut_file(fd);
136    if file.is_none() {
137        return usize::MAX; // Invalid file descriptor
138    }
139
140    let file = file.unwrap();
141    let whence  = match whence {
142        0 => SeekFrom::Start(offset as u64),
143        1 => SeekFrom::Current(offset),
144        2 => SeekFrom::End(offset),
145        _ => return usize::MAX, // Invalid whence
146    };
147
148    match file.seek(whence) {
149        Ok(pos) => {
150            pos as usize
151        }
152        Err(_) => {
153            return usize::MAX; // Lseek error
154        }
155    }
156}