wasmer_wasix/fs/fd.rs
1use std::{
2 borrow::Cow,
3 collections::HashMap,
4 path::PathBuf,
5 sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard, atomic::AtomicU64},
6};
7
8use virtual_fs::{Pipe, PipeRx, PipeTx, VirtualFile};
9use wasmer_wasix_types::wasi::{Fdflags, Fdflagsext, Filestat, Rights};
10
11use crate::net::socket::InodeSocket;
12use crate::os::epoll::EpollState;
13
14use super::{InodeGuard, InodeWeakGuard, NotificationInner};
15
16/// Shared handle to an open [`VirtualFile`].
17pub(crate) type VirtualFileLock = Arc<RwLock<Box<dyn VirtualFile + Send + Sync + 'static>>>;
18
19#[derive(Debug, Clone)]
20pub struct Fd {
21 pub inner: FdInner,
22
23 /// Flags that determine how the [`Fd`] can be used.
24 ///
25 /// Used when reopening a [`VirtualFile`] during deserialization.
26 pub open_flags: u16,
27 pub inode: InodeGuard,
28 pub is_stdio: bool,
29}
30
31// This struct contains the bits of Fd that are safe to mutate, so that
32// FdList::get_mut can safely return mutable references.
33#[derive(Debug, Clone)]
34pub struct FdInner {
35 pub rights: Rights,
36 pub rights_inheriting: Rights,
37 pub flags: Fdflags, // This is file table related flags, not fd flags
38 pub offset: Arc<AtomicU64>, // This also belongs in the file table
39 pub fd_flags: Fdflagsext, // This is the actual FD flags that belongs here
40}
41
42impl Fd {
43 /// This [`Fd`] can be used with read system calls.
44 pub const READ: u16 = 1;
45 /// This [`Fd`] can be used with write system calls.
46 pub const WRITE: u16 = 2;
47 /// This [`Fd`] can append in write system calls. Note that the append
48 /// permission implies the write permission.
49 pub const APPEND: u16 = 4;
50 /// This [`Fd`] will delete everything before writing. Note that truncate
51 /// permissions require the write permission.
52 ///
53 /// This permission is currently unused when deserializing.
54 pub const TRUNCATE: u16 = 8;
55 /// This [`Fd`] may create a file before writing to it. Note that create
56 /// permissions require write permissions.
57 ///
58 /// This permission is currently unused when deserializing.
59 pub const CREATE: u16 = 16;
60}
61
62/// A file that Wasi knows about that may or may not be open
63#[derive(Debug)]
64pub struct InodeVal {
65 pub stat: RwLock<Filestat>,
66 pub is_preopened: bool,
67 pub name: RwLock<Cow<'static, str>>,
68 pub kind: RwLock<Kind>,
69}
70
71impl InodeVal {
72 pub fn read(&self) -> RwLockReadGuard<'_, Kind> {
73 self.kind.read().unwrap()
74 }
75
76 pub fn write(&self) -> RwLockWriteGuard<'_, Kind> {
77 self.kind.write().unwrap()
78 }
79}
80
81/// The core of the filesystem abstraction. Includes directories,
82/// files, and symlinks.
83#[derive(Debug)]
84pub enum Kind {
85 File {
86 /// The open file, if it's open
87 handle: Option<VirtualFileLock>,
88 /// The path on the host system where the file is located
89 /// This is deprecated and will be removed soon
90 path: PathBuf,
91 /// Marks the file as a special file that only one `fd` can exist for
92 /// This is useful when dealing with host-provided special files that
93 /// should be looked up by path
94 /// TODO: clarify here?
95 fd: Option<u32>,
96 },
97 Socket {
98 /// Represents a networking socket
99 socket: InodeSocket,
100 },
101 PipeTx {
102 tx: PipeTx,
103 },
104 PipeRx {
105 rx: PipeRx,
106 },
107 DuplexPipe {
108 pipe: Pipe,
109 },
110 Epoll {
111 state: Arc<EpollState>,
112 },
113 Dir {
114 /// Parent directory
115 parent: InodeWeakGuard,
116 /// The path on the host system where the directory is located
117 // TODO: wrap it like VirtualFile
118 path: PathBuf,
119 /// The entries of a directory are lazily filled.
120 entries: HashMap<String, InodeGuard>,
121 },
122 /// The same as Dir but without the irrelevant bits
123 /// The root is immutable after creation; generally the Kind::Root
124 /// branch of whatever code you're writing will be a simpler version of
125 /// your Kind::Dir logic
126 Root {
127 entries: HashMap<String, InodeGuard>,
128 },
129 /// The first two fields are data _about_ the symlink; the last field is
130 /// the data _inside_ the symlink.
131 Symlink {
132 /// Whether the link came from the backing filesystem or from a WASI
133 /// `path_symlink` call. Backing links are resolved within their mount;
134 /// virtual links are resolved from the WASIX virtual root.
135 symlink_kind: SymlinkKind,
136 /// Full path to the symlink from the WASIX virtual root, with no
137 /// leading slash.
138 path_to_symlink: PathBuf,
139 /// the value of the symlink as a relative path
140 relative_path: PathBuf,
141 },
142 Buffer {
143 buffer: Vec<u8>,
144 },
145 EventNotifications {
146 inner: Arc<NotificationInner>,
147 },
148}
149
150#[derive(Clone, Copy, Debug)]
151pub enum SymlinkKind {
152 Backing,
153 Virtual,
154}