1use super::fd::{Fd, FdInner};
14use wasmer_wasix_types::wasi::Fd as WasiFd;
15
16#[derive(Debug)]
17pub struct FdList {
18 fds: Vec<Option<Fd>>,
19 first_free: Option<usize>,
20}
21
22pub struct FdListIterator<'a> {
23 fds_iterator: core::slice::Iter<'a, Option<Fd>>,
24 idx: usize,
25}
26
27pub struct FdListIteratorMut<'a> {
28 fds_iterator: core::slice::IterMut<'a, Option<Fd>>,
29 idx: usize,
30}
31
32impl Default for FdList {
33 fn default() -> Self {
34 Self::new()
35 }
36}
37
38impl FdList {
40 pub fn new() -> Self {
41 Self {
42 fds: vec![],
43 first_free: None,
44 }
45 }
46
47 pub fn next_free_fd(&self) -> WasiFd {
48 match self.first_free {
49 Some(i) => i as WasiFd,
50 None => self.last_fd().map(|i| i + 1).unwrap_or(0),
51 }
52 }
53
54 pub fn last_fd(&self) -> Option<WasiFd> {
55 self.fds
56 .iter()
57 .rev()
58 .position(|fd| fd.is_some())
59 .map(|idx| (self.fds.len() - idx - 1) as WasiFd)
60 }
61
62 pub fn get(&self, idx: WasiFd) -> Option<&Fd> {
63 self.fds.get(idx as usize).and_then(|x| x.as_ref())
64 }
65
66 pub fn get_mut(&mut self, idx: WasiFd) -> Option<&mut FdInner> {
67 self.fds
68 .get_mut(idx as usize)
69 .and_then(|x| x.as_mut())
70 .map(|x| &mut x.inner)
71 }
72
73 pub fn insert_first_free(&mut self, fd: Fd) -> WasiFd {
74 fd.inode.acquire_handle();
75 match self.first_free {
76 Some(free) => {
77 assert!(self.fds[free].is_none());
78
79 self.fds[free] = Some(fd);
80
81 self.first_free = self.first_free_after(free as WasiFd + 1);
82
83 free as WasiFd
84 }
85 None => {
86 self.fds.push(Some(fd));
87 (self.fds.len() - 1) as WasiFd
88 }
89 }
90 }
91
92 pub fn insert_first_free_after(&mut self, fd: Fd, after_or_equal: WasiFd) -> WasiFd {
93 match self.first_free {
94 _ if self.fds.len() < after_or_equal as usize => {
96 if !self.insert(true, after_or_equal, fd) {
97 panic!(
98 "Internal error in FdList - expected {after_or_equal} to be unoccupied since the list wasn't long enough"
99 );
100 }
101 after_or_equal
102 }
103
104 Some(free) if free >= after_or_equal as usize => self.insert_first_free(fd),
106
107 None if self.fds.len() >= after_or_equal as usize => self.insert_first_free(fd),
109
110 None => unreachable!("Both None cases were handled before"),
112
113 Some(_) => {
115 fd.inode.acquire_handle();
117
118 match self.first_free_after(after_or_equal) {
119 Some(free) => {
123 self.fds[free] = Some(fd);
124 free as WasiFd
125 }
126
127 None => {
129 self.fds.push(Some(fd));
130 (self.fds.len() - 1) as WasiFd
131 }
132 }
133 }
134 }
135 }
136
137 fn first_free_after(&self, after_or_equal: WasiFd) -> Option<usize> {
138 let skip = after_or_equal as usize;
139 self.fds
140 .iter()
141 .skip(skip)
142 .position(|fd| fd.is_none())
143 .map(|idx| idx + skip)
144 }
145
146 pub fn insert(&mut self, exclusive: bool, idx: WasiFd, fd: Fd) -> bool {
147 let idx = idx as usize;
148
149 if self.fds.len() <= idx {
150 if
151 self.first_free.is_none() &&
154 idx > self.fds.len()
157 {
158 self.first_free = Some(self.fds.len());
159 }
160
161 self.fds.resize(idx + 1, None);
162 }
163
164 if let Some(ref prev_fd) = self.fds[idx] {
165 if exclusive {
166 return false;
167 } else {
168 prev_fd.inode.drop_one_handle();
169 }
170 }
171
172 fd.inode.acquire_handle();
173 self.fds[idx] = Some(fd);
174
175 if self.first_free == Some(idx) {
176 self.first_free = self.first_free_after(idx as WasiFd + 1);
177 }
178
179 true
180 }
181
182 pub fn remove(&mut self, idx: WasiFd) -> Option<Fd> {
183 let idx = idx as usize;
184
185 let result = self.fds.get_mut(idx).and_then(|fd| fd.take());
186
187 if let Some(fd) = result.as_ref() {
188 match self.first_free {
189 None => self.first_free = Some(idx),
190 Some(x) if x > idx => self.first_free = Some(idx),
191 _ => (),
192 }
193
194 fd.inode.drop_one_handle();
195 }
196
197 result
198 }
199
200 pub fn clear(&mut self) {
201 for fd in &self.fds {
202 if let Some(fd) = fd.as_ref() {
203 fd.inode.drop_one_handle();
204 }
205 }
206
207 self.fds.clear();
208 self.first_free = None;
209 }
210
211 pub fn iter(&self) -> FdListIterator<'_> {
212 FdListIterator {
213 fds_iterator: self.fds.iter(),
214 idx: 0,
215 }
216 }
217
218 pub fn keys(&self) -> impl Iterator<Item = WasiFd> + '_ {
219 self.iter().map(|(key, _)| key)
220 }
221
222 pub fn iter_mut(&mut self) -> FdListIteratorMut<'_> {
223 FdListIteratorMut {
224 fds_iterator: self.fds.iter_mut(),
225 idx: 0,
226 }
227 }
228}
229
230impl Clone for FdList {
231 fn clone(&self) -> Self {
232 for fd in &self.fds {
233 if let Some(fd) = fd.as_ref() {
234 fd.inode.acquire_handle();
235 }
236 }
237
238 Self {
239 fds: self.fds.clone(),
240 first_free: self.first_free,
241 }
242 }
243}
244
245impl Drop for FdList {
246 fn drop(&mut self) {
247 self.clear();
248 }
249}
250
251impl<'a> Iterator for FdListIterator<'a> {
252 type Item = (WasiFd, &'a Fd);
253
254 fn next(&mut self) -> Option<Self::Item> {
255 loop {
256 match self.fds_iterator.next() {
257 None => return None,
258
259 Some(None) => {
260 self.idx += 1;
261 continue;
262 }
263
264 Some(Some(fd)) => {
265 let wasi_fd = self.idx as WasiFd;
266 self.idx += 1;
267 return Some((wasi_fd, fd));
268 }
269 }
270 }
271 }
272}
273
274impl<'a> Iterator for FdListIteratorMut<'a> {
275 type Item = (WasiFd, &'a mut FdInner);
276
277 fn next(&mut self) -> Option<Self::Item> {
278 loop {
279 match self.fds_iterator.next() {
280 None => return None,
281
282 Some(None) => {
283 self.idx += 1;
284 continue;
285 }
286
287 Some(Some(fd)) => {
288 let wasi_fd = self.idx as WasiFd;
289 self.idx += 1;
290 return Some((wasi_fd, &mut fd.inner));
291 }
292 }
293 }
294 }
295}
296
297#[cfg(test)]
298mod tests {
299 use std::{
300 borrow::Cow,
301 sync::{
302 Arc, RwLock,
303 atomic::{AtomicI32, AtomicU64},
304 },
305 };
306
307 use assert_panic::assert_panic;
308 use wasmer_wasix_types::wasi::{Fdflags, Fdflagsext, Rights};
309
310 use crate::fs::{Inode, InodeGuard, InodeVal, Kind, fd::FdInner};
311
312 use super::{Fd, FdList, WasiFd};
313
314 fn useless_fd(n: u16) -> Fd {
315 Fd {
316 open_flags: 0,
317 inode: InodeGuard {
318 ino: Inode(0),
319 inner: Arc::new(InodeVal {
320 is_preopened: false,
321 kind: RwLock::new(Kind::Buffer { buffer: vec![] }),
322 name: RwLock::new(Cow::Borrowed("")),
323 stat: RwLock::new(Default::default()),
324 }),
325 open_handles: Arc::new(AtomicI32::new(0)),
326 },
327 is_stdio: false,
328 inner: FdInner {
329 offset: Arc::new(AtomicU64::new(0)),
330 rights: Rights::empty(),
331 rights_inheriting: Rights::empty(),
332 flags: Fdflags::from_bits_preserve(n),
333 fd_flags: Fdflagsext::empty(),
334 },
335 }
336 }
337
338 fn is_useless_fd(fd: &Fd, n: u16) -> bool {
339 fd.inner.flags.bits() == n
340 }
341
342 fn is_useless_fd_inner(fd_inner: &FdInner, n: u16) -> bool {
343 fd_inner.flags.bits() == n
344 }
345
346 fn assert_fds_match(l: &FdList, expected: &[(WasiFd, u16)]) {
347 let mut i = l.iter();
348
349 for e in expected {
350 let next = i.next().expect("Should have a next element");
351 assert_eq!(next.0, e.0);
352 assert!(is_useless_fd(next.1, e.1));
353 }
354
355 assert!(i.next().is_none());
356 }
357
358 #[test]
359 fn can_append_fds() {
360 let mut l = FdList::new();
361 l.insert_first_free(useless_fd(0));
362 l.insert_first_free(useless_fd(1));
363
364 assert_fds_match(&l, &[(0, 0), (1, 1)]);
365 }
366
367 #[test]
368 fn can_append_in_holes() {
369 let mut l = FdList::new();
370 l.insert_first_free(useless_fd(0));
371 l.insert_first_free(useless_fd(1));
372 l.insert_first_free(useless_fd(2));
373 l.insert_first_free(useless_fd(3));
374 l.remove(1);
375 l.remove(2);
376 l.insert_first_free(useless_fd(4));
377
378 assert_fds_match(&l, &[(0, 0), (1, 4), (3, 3)]);
379 }
380
381 #[test]
382 fn can_have_holes_in_different_places() {
383 let mut l = FdList::new();
384 l.insert_first_free(useless_fd(0));
385 l.insert_first_free(useless_fd(1));
386 l.insert_first_free(useless_fd(2));
387 l.insert_first_free(useless_fd(3));
388 l.insert_first_free(useless_fd(4));
389 l.remove(1);
390 l.remove(3);
391 l.insert_first_free(useless_fd(5));
392 l.insert_first_free(useless_fd(6));
393
394 assert_fds_match(&l, &[(0, 0), (1, 5), (2, 2), (3, 6), (4, 4)]);
395 }
396
397 #[test]
398 fn hole_moves_back_correctly() {
399 let mut l = FdList::new();
400 l.insert_first_free(useless_fd(0));
401 l.insert_first_free(useless_fd(1));
402 l.insert_first_free(useless_fd(2));
403 l.insert_first_free(useless_fd(3));
404 l.remove(3);
405 assert_eq!(l.first_free, Some(3));
406 l.remove(1);
407 assert_eq!(l.first_free, Some(1));
408 l.insert_first_free(useless_fd(4));
409
410 assert_fds_match(&l, &[(0, 0), (1, 4), (2, 2)]);
411 }
412
413 #[test]
414 fn insert_at_first_free_updates_first_free() {
415 let mut l = FdList::new();
416 l.insert_first_free(useless_fd(0));
417 l.insert_first_free(useless_fd(1));
418 l.insert_first_free(useless_fd(2));
419 l.insert_first_free(useless_fd(3));
420 l.remove(1);
421 l.remove(2);
422 assert!(l.insert(true, 1, useless_fd(4)));
423 assert_eq!(l.first_free, Some(2));
424
425 assert_fds_match(&l, &[(0, 0), (1, 4), (3, 3)]);
426 }
427
428 #[test]
429 fn next_and_last_fd_reported_correctly() {
430 let mut l = FdList::new();
431
432 assert_eq!(l.next_free_fd(), 0);
433 assert_eq!(l.last_fd(), None);
434
435 l.insert_first_free(useless_fd(0));
436 l.insert_first_free(useless_fd(1));
437
438 assert_eq!(l.next_free_fd(), 2);
439 assert_eq!(l.last_fd(), Some(1));
440
441 l.insert_first_free(useless_fd(2));
442 l.insert_first_free(useless_fd(3));
443
444 assert_eq!(l.next_free_fd(), 4);
445 assert_eq!(l.last_fd(), Some(3));
446
447 l.remove(3);
448
449 assert_eq!(l.next_free_fd(), 3);
450 assert_eq!(l.last_fd(), Some(2));
451
452 l.remove(1);
453
454 assert_eq!(l.next_free_fd(), 1);
455 assert_eq!(l.last_fd(), Some(2));
456 }
457
458 #[test]
459 fn get_works() {
460 let mut l = FdList::new();
461
462 l.insert_first_free(useless_fd(0));
463 l.insert_first_free(useless_fd(1));
464 l.insert_first_free(useless_fd(2));
465 l.insert_first_free(useless_fd(3));
466 l.insert_first_free(useless_fd(4));
467 l.remove(1);
468 l.remove(3);
469
470 assert!(l.get(1).is_none());
471 assert!(is_useless_fd(l.get(2).unwrap(), 2));
472
473 let at_4 = l.get_mut(4).unwrap();
474 assert!(is_useless_fd_inner(at_4, 4));
475 at_4.flags = Fdflags::from_bits_preserve(5); assert!(is_useless_fd(l.get(4).unwrap(), 5));
477
478 assert!(l.get(10).is_none());
479 assert!(l.get_mut(10).is_none());
480 }
481
482 #[test]
483 fn insert_at_works() {
484 let mut l = FdList::new();
485
486 l.insert_first_free(useless_fd(0));
487 l.insert_first_free(useless_fd(1));
488 l.insert_first_free(useless_fd(2));
489 l.remove(1);
490
491 assert!(l.insert(false, 2, useless_fd(3)));
492 assert!(is_useless_fd(l.get(2).unwrap(), 3));
493
494 assert!(!l.insert(true, 2, useless_fd(4)));
495 assert!(is_useless_fd(l.get(2).unwrap(), 3));
496
497 assert!(l.insert(true, 1, useless_fd(5)));
498 assert!(is_useless_fd(l.get(1).unwrap(), 5));
499 }
500
501 #[test]
502 fn insert_at_can_insert_beyond_end_of_list() {
503 let mut l = FdList::new();
504
505 l.insert_first_free(useless_fd(0));
506
507 assert!(l.insert(false, 1, useless_fd(1)));
508 assert!(is_useless_fd(l.get(1).unwrap(), 1));
509
510 assert_eq!(l.last_fd(), Some(1));
512 assert_eq!(l.next_free_fd(), 2);
513 assert!(l.first_free.is_none());
514
515 assert!(l.insert(false, 5, useless_fd(5)));
517 assert!(is_useless_fd(l.get(5).unwrap(), 5));
518
519 for i in 2..=4 {
520 assert!(l.get(i).is_none());
521 }
522
523 assert_eq!(l.last_fd(), Some(5));
525 assert_eq!(l.next_free_fd(), 2);
526 assert_eq!(l.first_free, Some(2));
527 }
528
529 #[test]
530 fn insert_first_free_after_beyond_end_of_empty_list() {
531 let mut l = FdList::new();
532 assert_eq!(l.insert_first_free_after(useless_fd(1), 5), 5);
533 assert!(is_useless_fd(l.get(5).unwrap(), 1));
534 }
535
536 #[test]
537 fn insert_first_free_after_beyond_end_of_non_empty_list() {
538 let mut l = FdList::new();
539 l.insert(false, 0, useless_fd(0));
540 assert_eq!(l.insert_first_free_after(useless_fd(1), 5), 5);
541 assert!(is_useless_fd(l.get(5).unwrap(), 1));
542 }
543
544 #[test]
545 fn insert_first_free_after_beyond_end_of_non_empty_list_with_hole() {
546 let mut l = FdList::new();
547 l.insert(false, 0, useless_fd(0));
548 l.insert(false, 2, useless_fd(2));
549 assert_eq!(l.insert_first_free_after(useless_fd(1), 5), 5);
550 assert!(is_useless_fd(l.get(5).unwrap(), 1));
551 }
552
553 #[test]
554 fn insert_first_free_after_behind_hole() {
555 let mut l = FdList::new();
556 l.insert_first_free(useless_fd(0));
557 l.insert_first_free(useless_fd(1));
558 l.insert_first_free(useless_fd(2));
559 l.insert_first_free(useless_fd(3));
560 l.remove(2).unwrap();
561 assert_eq!(l.insert_first_free_after(useless_fd(5), 1), 2);
562 assert!(is_useless_fd(l.get(2).unwrap(), 5));
563 }
564
565 #[test]
566 fn insert_first_free_after_behind_end_without_hole() {
567 let mut l = FdList::new();
568 l.insert_first_free(useless_fd(0));
569 l.insert_first_free(useless_fd(1));
570 l.insert_first_free(useless_fd(2));
571 l.insert_first_free(useless_fd(3));
572 assert_eq!(l.insert_first_free_after(useless_fd(5), 2), 4);
573 assert!(is_useless_fd(l.get(4).unwrap(), 5));
574 }
575
576 #[test]
577 fn insert_first_free_after_between_hole_and_end_without_other_hole() {
578 let mut l = FdList::new();
579 l.insert_first_free(useless_fd(0));
580 l.insert_first_free(useless_fd(1));
581 l.insert_first_free(useless_fd(2));
582 l.insert_first_free(useless_fd(3));
583 l.insert_first_free(useless_fd(4));
584 l.remove(1).unwrap();
585 assert_eq!(l.insert_first_free_after(useless_fd(5), 2), 5);
586 assert!(is_useless_fd(l.get(5).unwrap(), 5));
587 }
588
589 #[test]
590 fn insert_first_free_after_between_hole_and_end_with_other_hole() {
591 let mut l = FdList::new();
592 l.insert_first_free(useless_fd(0));
593 l.insert_first_free(useless_fd(1));
594 l.insert_first_free(useless_fd(2));
595 l.insert_first_free(useless_fd(3));
596 l.insert_first_free(useless_fd(4));
597 l.remove(1).unwrap();
598 l.remove(3).unwrap();
599 assert_eq!(l.insert_first_free_after(useless_fd(5), 2), 3);
600 assert!(is_useless_fd(l.get(3).unwrap(), 5));
601 }
602
603 #[test]
604 fn remove_works() {
605 let mut l = FdList::new();
606
607 l.insert_first_free(useless_fd(0));
608 l.insert_first_free(useless_fd(1));
609 l.insert_first_free(useless_fd(2));
610
611 assert!(is_useless_fd(&l.remove(1).unwrap(), 1));
612 assert!(l.remove(1).is_none());
613 assert!(l.remove(100000).is_none());
614 }
615
616 #[test]
617 fn clear_works() {
618 let mut l = FdList::new();
619
620 l.insert_first_free(useless_fd(0));
621 l.insert_first_free(useless_fd(1));
622 l.insert_first_free(useless_fd(2));
623 l.remove(1);
624
625 l.clear();
626
627 assert_eq!(l.next_free_fd(), 0);
628 assert!(l.last_fd().is_none());
629 assert_eq!(l.fds.len(), 0);
630 assert!(l.first_free.is_none());
631 }
632
633 #[test]
634 fn iter_mut_works() {
635 let mut l = FdList::new();
636 l.insert_first_free(useless_fd(0));
637 l.insert_first_free(useless_fd(1));
638
639 let mut i = l.iter_mut();
640
641 let next = i.next().unwrap();
642 assert_eq!(next.0, 0);
643 assert!(is_useless_fd_inner(next.1, 0));
644 next.1.flags = Fdflags::from_bits_preserve(2); let next = i.next().unwrap();
647 assert_eq!(next.0, 1);
648 assert!(is_useless_fd_inner(next.1, 1));
649
650 assert!(i.next().is_none());
651
652 assert_fds_match(&l, &[(0, 2), (1, 1)]);
653 }
654
655 #[test]
656 fn open_handles_are_updated_correctly() {
657 let mut l = FdList::new();
658 l.insert_first_free(useless_fd(0));
659 l.insert_first_free(useless_fd(1));
660
661 let fd0 = l.get(0).unwrap().clone();
662 assert_eq!(fd0.inode.handle_count(), 1);
663
664 let fd1 = l.get(1).unwrap().clone();
666 assert_eq!(fd1.inode.handle_count(), 1);
667 l.remove(1).unwrap();
668 assert_eq!(fd1.inode.handle_count(), 0);
669
670 let mut l2 = l.clone();
672 assert_eq!(fd0.inode.handle_count(), 2);
673
674 {
675 let l3 = l2.clone();
677 assert_eq!(fd0.inode.handle_count(), 3);
678 drop(l3);
679 assert_eq!(fd0.inode.handle_count(), 2);
680 }
681
682 l.clear();
684 assert_eq!(fd0.inode.handle_count(), 1);
685
686 l2.clear();
688 assert_eq!(fd0.inode.handle_count(), 0);
689
690 assert_panic!(
691 fd0.inode.drop_one_handle(),
692 &str,
693 "InodeGuard handle dropped too many times"
694 );
695
696 assert_panic!(drop(fd0.inode.write()), String, contains "PoisonError");
697 }
698
699 #[test]
700 fn messing_with_inode_causes_panic() {
701 let mut l = FdList::new();
704 l.insert_first_free(useless_fd(0));
705
706 let fd = l.get(0).unwrap();
707 fd.inode.drop_one_handle();
708
709 assert_panic!(drop(l), &str, "InodeGuard handle dropped too many times");
710 }
711}