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}