1use super::{file::OpenFile, scheme::OpenFlags};
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_mut(&self, fd: u32) -> Result<&OpenFile, 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.file);
132 }
133 }
134 Err(SyscallError::BadHandle)
135 }
136
137 pub fn replace_open_flags(
140 &mut self,
141 fd: u32,
142 new_flags: OpenFlags,
143 ) -> Result<(), SyscallError> {
144 let fd_usize = fd as usize;
145 if fd_usize >= self.fds.len() {
146 return Err(SyscallError::BadHandle);
147 }
148 let desc = self.fds[fd_usize].as_mut().ok_or(SyscallError::BadHandle)?;
149 let old = desc.file.clone();
150 let new_file = Arc::new(OpenFile::new(
151 old.scheme().clone(),
152 old.file_id(),
153 alloc::string::String::from(old.path()),
154 new_flags,
155 old.flags(),
156 None,
157 ));
158 desc.file = new_file;
159 Ok(())
160 }
161
162 pub fn get_cloexec(&self, fd: u32) -> Result<bool, SyscallError> {
164 let fd_usize = fd as usize;
165 if fd_usize < self.fds.len() {
166 if let Some(desc) = &self.fds[fd_usize] {
167 return Ok(desc.cloexec);
168 }
169 }
170 Err(SyscallError::BadHandle)
171 }
172
173 pub fn set_cloexec(&mut self, fd: u32, cloexec: bool) -> Result<(), SyscallError> {
175 let fd_usize = fd as usize;
176 if fd_usize < self.fds.len() {
177 if let Some(desc) = &mut self.fds[fd_usize] {
178 desc.cloexec = cloexec;
179 return Ok(());
180 }
181 }
182 Err(SyscallError::BadHandle)
183 }
184
185 pub fn remove(&mut self, fd: u32) -> Result<Arc<OpenFile>, SyscallError> {
187 let fd_usize = fd as usize;
188 if fd_usize < self.fds.len() {
189 if let Some(desc) = self.fds[fd_usize].take() {
190 if fd_usize < self.next_fd_hint {
191 self.next_fd_hint = fd_usize;
192 }
193 return Ok(desc.file);
194 }
195 }
196 Err(SyscallError::BadHandle)
197 }
198
199 pub fn contains(&self, fd: u32) -> bool {
201 let fd_usize = fd as usize;
202 fd_usize < self.fds.len() && self.fds[fd_usize].is_some()
203 }
204
205 pub fn duplicate(&mut self, old_fd: u32) -> Result<u32, SyscallError> {
207 let file = self.get(old_fd)?;
208 Ok(self.insert(file))
209 }
210
211 pub fn duplicate_from(&mut self, old_fd: u32, min_fd: u32) -> Result<u32, SyscallError> {
213 let file = self.get(old_fd)?;
214 let min = min_fd as usize;
215 if min >= self.fds.len() {
216 self.fds.resize(min + 1, None);
217 }
218 let start = core::cmp::max(min, self.next_fd_hint);
219 for i in start..self.fds.len() {
220 if self.fds[i].is_none() {
221 self.fds[i] = Some(FileDescriptor::new(file));
222 if i == self.next_fd_hint {
223 self.next_fd_hint = self.next_fd_hint.saturating_add(1);
224 self.advance_next_fd_hint();
225 }
226 return Ok(i as u32);
227 }
228 }
229 for i in min..start.min(self.fds.len()) {
230 if self.fds[i].is_none() {
231 self.fds[i] = Some(FileDescriptor::new(file));
232 if i == self.next_fd_hint {
233 self.next_fd_hint = self.next_fd_hint.saturating_add(1);
234 self.advance_next_fd_hint();
235 }
236 return Ok(i as u32);
237 }
238 }
239 let fd = self.fds.len() as u32;
240 self.fds.push(Some(FileDescriptor::new(file)));
241 if (fd as usize) == self.next_fd_hint {
242 self.next_fd_hint = self.next_fd_hint.saturating_add(1);
243 self.advance_next_fd_hint();
244 }
245 Ok(fd)
246 }
247
248 pub fn duplicate_to(&mut self, old_fd: u32, new_fd: u32) -> Result<u32, SyscallError> {
250 let file = self.get(old_fd)?;
251 if old_fd == new_fd {
252 return Ok(new_fd);
253 }
254 let new_idx = new_fd as usize;
255 if new_idx >= self.fds.len() {
256 self.fds.resize(new_idx + 1, None);
257 }
258 self.fds[new_idx] = Some(FileDescriptor::new(file));
259 if new_idx == self.next_fd_hint {
260 self.next_fd_hint = self.next_fd_hint.saturating_add(1);
261 self.advance_next_fd_hint();
262 }
263 Ok(new_fd)
264 }
265
266 pub fn close_all(&mut self) {
268 self.fds.clear();
269 self.next_fd_hint = 0;
270 }
271
272 pub fn close_cloexec(&mut self) {
274 for (i, fd) in self.fds.iter_mut().enumerate() {
275 if let Some(desc) = fd {
276 if desc.cloexec {
277 *fd = None;
278 if i < self.next_fd_hint {
279 self.next_fd_hint = i;
280 }
281 }
282 }
283 }
284 }
285
286 pub fn clone_for_fork(&self) -> Self {
291 FileDescriptorTable {
292 fds: self.fds.clone(),
293 next_fd_hint: self.next_fd_hint,
294 }
295 }
296}
297
298impl Default for FileDescriptorTable {
299 fn default() -> Self {
301 Self::new()
302 }
303}