1use super::file::OpenFile;
6use crate::syscall::error::SyscallError;
7use alloc::{sync::Arc, vec::Vec};
8
9pub const STDIN: u32 = 0;
11pub const STDOUT: u32 = 1;
12pub const STDERR: u32 = 2;
13
14#[derive(Clone)]
16pub struct FileDescriptor {
17 pub file: Arc<OpenFile>,
19 pub cloexec: bool,
21}
22
23impl FileDescriptor {
24 pub fn new(file: Arc<OpenFile>) -> Self {
26 FileDescriptor {
27 file,
28 cloexec: false,
29 }
30 }
31
32 pub fn new_cloexec(file: Arc<OpenFile>, cloexec: bool) -> Self {
34 FileDescriptor { file, cloexec }
35 }
36}
37
38pub struct FileDescriptorTable {
40 fds: Vec<Option<FileDescriptor>>,
41 next_fd_hint: usize,
42}
43
44impl FileDescriptorTable {
45 fn advance_next_fd_hint(&mut self) {
47 while self.next_fd_hint < self.fds.len() && self.fds[self.next_fd_hint].is_some() {
48 self.next_fd_hint = self.next_fd_hint.saturating_add(1);
49 }
50 }
51
52 pub fn new() -> Self {
54 let mut fds = Vec::with_capacity(64);
55 fds.resize(3, None); FileDescriptorTable {
57 fds,
58 next_fd_hint: 3,
59 }
60 }
61
62 fn find_free_fd(&mut self) -> u32 {
64 for i in self.next_fd_hint..self.fds.len() {
65 if self.fds[i].is_none() {
66 self.next_fd_hint = i.saturating_add(1);
67 self.advance_next_fd_hint();
68 return i as u32;
69 }
70 }
71 for i in 0..self.next_fd_hint.min(self.fds.len()) {
72 if self.fds[i].is_none() {
73 self.next_fd_hint = i.saturating_add(1);
74 self.advance_next_fd_hint();
75 return i as u32;
76 }
77 }
78 self.next_fd_hint = self.fds.len().saturating_add(1);
79 self.fds.len() as u32
80 }
81
82 pub fn insert(&mut self, file: Arc<OpenFile>) -> u32 {
84 self.insert_with_flags(file, false)
85 }
86
87 pub fn insert_at(&mut self, fd: u32, file: Arc<OpenFile>) {
89 let fd_usize = fd as usize;
90 if fd_usize >= self.fds.len() {
91 self.fds.resize(fd_usize + 1, None);
92 }
93 self.fds[fd_usize] = Some(FileDescriptor::new(file));
94 if fd_usize == self.next_fd_hint {
95 self.next_fd_hint = self.next_fd_hint.saturating_add(1);
96 self.advance_next_fd_hint();
97 }
98 }
99
100 pub fn insert_with_flags(&mut self, file: Arc<OpenFile>, cloexec: bool) -> u32 {
102 let fd = self.find_free_fd();
103 let fd_usize = fd as usize;
104 if fd_usize >= self.fds.len() {
105 self.fds.resize(fd_usize + 1, None);
106 }
107 self.fds[fd_usize] = Some(FileDescriptor::new_cloexec(file, cloexec));
108 if fd_usize == self.next_fd_hint {
109 self.next_fd_hint = self.next_fd_hint.saturating_add(1);
110 self.advance_next_fd_hint();
111 }
112 fd
113 }
114
115 pub fn get(&self, fd: u32) -> Result<Arc<OpenFile>, SyscallError> {
117 let fd_usize = fd as usize;
118 if fd_usize < self.fds.len() {
119 if let Some(desc) = &self.fds[fd_usize] {
120 return Ok(desc.file.clone());
121 }
122 }
123 Err(SyscallError::BadHandle)
124 }
125
126 pub fn get_cloexec(&self, fd: u32) -> Result<bool, SyscallError> {
128 let fd_usize = fd as usize;
129 if fd_usize < self.fds.len() {
130 if let Some(desc) = &self.fds[fd_usize] {
131 return Ok(desc.cloexec);
132 }
133 }
134 Err(SyscallError::BadHandle)
135 }
136
137 pub fn set_cloexec(&mut self, fd: u32, cloexec: bool) -> Result<(), SyscallError> {
139 let fd_usize = fd as usize;
140 if fd_usize < self.fds.len() {
141 if let Some(desc) = &mut self.fds[fd_usize] {
142 desc.cloexec = cloexec;
143 return Ok(());
144 }
145 }
146 Err(SyscallError::BadHandle)
147 }
148
149 pub fn remove(&mut self, fd: u32) -> Result<Arc<OpenFile>, SyscallError> {
151 let fd_usize = fd as usize;
152 if fd_usize < self.fds.len() {
153 if let Some(desc) = self.fds[fd_usize].take() {
154 if fd_usize < self.next_fd_hint {
155 self.next_fd_hint = fd_usize;
156 }
157 return Ok(desc.file);
158 }
159 }
160 Err(SyscallError::BadHandle)
161 }
162
163 pub fn contains(&self, fd: u32) -> bool {
165 let fd_usize = fd as usize;
166 fd_usize < self.fds.len() && self.fds[fd_usize].is_some()
167 }
168
169 pub fn duplicate(&mut self, old_fd: u32) -> Result<u32, SyscallError> {
171 let file = self.get(old_fd)?;
172 Ok(self.insert(file))
173 }
174
175 pub fn duplicate_from(&mut self, old_fd: u32, min_fd: u32) -> Result<u32, SyscallError> {
177 let file = self.get(old_fd)?;
178 let min = min_fd as usize;
179 if min >= self.fds.len() {
180 self.fds.resize(min + 1, None);
181 }
182 let start = core::cmp::max(min, self.next_fd_hint);
183 for i in start..self.fds.len() {
184 if self.fds[i].is_none() {
185 self.fds[i] = Some(FileDescriptor::new(file));
186 if i == self.next_fd_hint {
187 self.next_fd_hint = self.next_fd_hint.saturating_add(1);
188 self.advance_next_fd_hint();
189 }
190 return Ok(i as u32);
191 }
192 }
193 for i in min..start.min(self.fds.len()) {
194 if self.fds[i].is_none() {
195 self.fds[i] = Some(FileDescriptor::new(file));
196 if i == self.next_fd_hint {
197 self.next_fd_hint = self.next_fd_hint.saturating_add(1);
198 self.advance_next_fd_hint();
199 }
200 return Ok(i as u32);
201 }
202 }
203 let fd = self.fds.len() as u32;
204 self.fds.push(Some(FileDescriptor::new(file)));
205 if (fd as usize) == self.next_fd_hint {
206 self.next_fd_hint = self.next_fd_hint.saturating_add(1);
207 self.advance_next_fd_hint();
208 }
209 Ok(fd)
210 }
211
212 pub fn duplicate_to(&mut self, old_fd: u32, new_fd: u32) -> Result<u32, SyscallError> {
214 let file = self.get(old_fd)?;
215 if old_fd == new_fd {
216 return Ok(new_fd);
217 }
218 let new_idx = new_fd as usize;
219 if new_idx >= self.fds.len() {
220 self.fds.resize(new_idx + 1, None);
221 }
222 self.fds[new_idx] = Some(FileDescriptor::new(file));
223 if new_idx == self.next_fd_hint {
224 self.next_fd_hint = self.next_fd_hint.saturating_add(1);
225 self.advance_next_fd_hint();
226 }
227 Ok(new_fd)
228 }
229
230 pub fn close_all(&mut self) {
232 self.fds.clear();
233 self.next_fd_hint = 0;
234 }
235
236 pub fn close_cloexec(&mut self) {
238 for (i, fd) in self.fds.iter_mut().enumerate() {
239 if let Some(desc) = fd {
240 if desc.cloexec {
241 *fd = None;
242 if i < self.next_fd_hint {
243 self.next_fd_hint = i;
244 }
245 }
246 }
247 }
248 }
249
250 pub fn clone_for_fork(&self) -> Self {
255 FileDescriptorTable {
256 fds: self.fds.clone(),
257 next_fd_hint: self.next_fd_hint,
258 }
259 }
260}
261
262impl Default for FileDescriptorTable {
263 fn default() -> Self {
265 Self::new()
266 }
267}