fuser/ll/
mod.rs

1//! Low-level kernel communication.
2
3mod argument;
4pub mod fuse_abi;
5pub(crate) mod notify;
6pub(crate) mod reply;
7mod request;
8
9use std::{convert::TryInto, num::NonZeroI32, time::SystemTime};
10
11pub use reply::Response;
12pub use request::{AnyRequest, FileHandle, INodeNo, Lock, Operation, Request, RequestId, Version};
13
14#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
15/// Possible input arguments for atime & mtime, which can either be set to a specified time,
16/// or to the current time
17pub enum TimeOrNow {
18    /// Specific time provided
19    SpecificTime(SystemTime),
20    /// Current time
21    Now,
22}
23
24macro_rules! errno {
25    ($x: expr_2021) => {
26        Errno(unsafe {
27            // This is a static assertion that the constant $x is > 0
28            const _X: [(); 0 - !{
29                const ASSERT: bool = ($x > 0);
30                ASSERT
31            } as usize] = [];
32            // Which makes this safe
33            NonZeroI32::new_unchecked($x)
34        })
35    };
36}
37
38/// Represents an error code to be returned to the caller
39#[derive(Debug)]
40pub struct Errno(pub NonZeroI32);
41impl Errno {
42    /// Operation not permitted
43    pub const EPERM: Errno = errno!(libc::EPERM);
44    /// No such file or directory
45    pub const ENOENT: Errno = errno!(libc::ENOENT);
46    /// No such process
47    pub const ESRCH: Errno = errno!(libc::ESRCH);
48    /// Interrupted system call
49    pub const EINTR: Errno = errno!(libc::EINTR);
50    /// Input/output error
51    pub const EIO: Errno = errno!(libc::EIO);
52    /// No such device or address
53    pub const ENXIO: Errno = errno!(libc::ENXIO);
54    /// Argument list too long
55    pub const E2BIG: Errno = errno!(libc::E2BIG);
56    /// Exec format error
57    pub const ENOEXEC: Errno = errno!(libc::ENOEXEC);
58    /// Bad file descriptor
59    pub const EBADF: Errno = errno!(libc::EBADF);
60    /// No child processes
61    pub const ECHILD: Errno = errno!(libc::ECHILD);
62    /// Resource temporarily unavailable
63    pub const EAGAIN: Errno = errno!(libc::EAGAIN);
64    /// Cannot allocate memory
65    pub const ENOMEM: Errno = errno!(libc::ENOMEM);
66    /// Permission denied
67    pub const EACCES: Errno = errno!(libc::EACCES);
68    /// Bad address
69    pub const EFAULT: Errno = errno!(libc::EFAULT);
70    /// Block device required
71    pub const ENOTBLK: Errno = errno!(libc::ENOTBLK);
72    /// Device or resource busy
73    pub const EBUSY: Errno = errno!(libc::EBUSY);
74    /// File exists
75    pub const EEXIST: Errno = errno!(libc::EEXIST);
76    /// Invalid cross-device link
77    pub const EXDEV: Errno = errno!(libc::EXDEV);
78    /// No such device
79    pub const ENODEV: Errno = errno!(libc::ENODEV);
80    /// Not a directory
81    pub const ENOTDIR: Errno = errno!(libc::ENOTDIR);
82    /// Is a directory
83    pub const EISDIR: Errno = errno!(libc::EISDIR);
84    /// Invalid argument
85    pub const EINVAL: Errno = errno!(libc::EINVAL);
86    /// Too many open files in system
87    pub const ENFILE: Errno = errno!(libc::ENFILE);
88    /// Too many open files
89    pub const EMFILE: Errno = errno!(libc::EMFILE);
90    /// Inappropriate ioctl for device
91    pub const ENOTTY: Errno = errno!(libc::ENOTTY);
92    /// Text file busy
93    pub const ETXTBSY: Errno = errno!(libc::ETXTBSY);
94    /// File too large
95    pub const EFBIG: Errno = errno!(libc::EFBIG);
96    /// No space left on device
97    pub const ENOSPC: Errno = errno!(libc::ENOSPC);
98    /// Illegal seek
99    pub const ESPIPE: Errno = errno!(libc::ESPIPE);
100    /// Read-only file system
101    pub const EROFS: Errno = errno!(libc::EROFS);
102    /// Too many links
103    pub const EMLINK: Errno = errno!(libc::EMLINK);
104    /// Broken pipe
105    pub const EPIPE: Errno = errno!(libc::EPIPE);
106    /// Numerical argument out of domain
107    pub const EDOM: Errno = errno!(libc::EDOM);
108    /// Numerical result out of range
109    pub const ERANGE: Errno = errno!(libc::ERANGE);
110    /// Resource deadlock avoided
111    pub const EDEADLK: Errno = errno!(libc::EDEADLK);
112    /// File name too long
113    pub const ENAMETOOLONG: Errno = errno!(libc::ENAMETOOLONG);
114    /// No locks available
115    pub const ENOLCK: Errno = errno!(libc::ENOLCK);
116    /// Function not implemented
117    pub const ENOSYS: Errno = errno!(libc::ENOSYS);
118    /// Directory not empty
119    pub const ENOTEMPTY: Errno = errno!(libc::ENOTEMPTY);
120    /// Too many levels of symbolic links
121    pub const ELOOP: Errno = errno!(libc::ELOOP);
122    /// Resource temporarily unavailable
123    pub const EWOULDBLOCK: Errno = errno!(libc::EWOULDBLOCK);
124    /// No message of desired type
125    pub const ENOMSG: Errno = errno!(libc::ENOMSG);
126    /// Identifier removed
127    pub const EIDRM: Errno = errno!(libc::EIDRM);
128    /// Object is remote
129    pub const EREMOTE: Errno = errno!(libc::EREMOTE);
130    /// Link has been severed
131    pub const ENOLINK: Errno = errno!(libc::ENOLINK);
132    /// Protocol error
133    pub const EPROTO: Errno = errno!(libc::EPROTO);
134    /// Multihop attempted
135    pub const EMULTIHOP: Errno = errno!(libc::EMULTIHOP);
136    /// Bad message
137    pub const EBADMSG: Errno = errno!(libc::EBADMSG);
138    /// Value too large for defined data type
139    pub const EOVERFLOW: Errno = errno!(libc::EOVERFLOW);
140    /// Invalid or incomplete multibyte or wide character
141    pub const EILSEQ: Errno = errno!(libc::EILSEQ);
142    /// Too many users
143    pub const EUSERS: Errno = errno!(libc::EUSERS);
144    /// Socket operation on non-socket
145    pub const ENOTSOCK: Errno = errno!(libc::ENOTSOCK);
146    /// Destination address required
147    pub const EDESTADDRREQ: Errno = errno!(libc::EDESTADDRREQ);
148    /// Message too long
149    pub const EMSGSIZE: Errno = errno!(libc::EMSGSIZE);
150    /// Protocol wrong type for socket
151    pub const EPROTOTYPE: Errno = errno!(libc::EPROTOTYPE);
152    /// Protocol not available
153    pub const ENOPROTOOPT: Errno = errno!(libc::ENOPROTOOPT);
154    /// Protocol not supported
155    pub const EPROTONOSUPPORT: Errno = errno!(libc::EPROTONOSUPPORT);
156    /// Socket type not supported
157    pub const ESOCKTNOSUPPORT: Errno = errno!(libc::ESOCKTNOSUPPORT);
158    /// Operation not supported
159    pub const EOPNOTSUPP: Errno = errno!(libc::EOPNOTSUPP);
160    /// Protocol family not supported
161    pub const EPFNOSUPPORT: Errno = errno!(libc::EPFNOSUPPORT);
162    /// Address family not supported by protocol
163    pub const EAFNOSUPPORT: Errno = errno!(libc::EAFNOSUPPORT);
164    /// Address already in use
165    pub const EADDRINUSE: Errno = errno!(libc::EADDRINUSE);
166    /// Cannot assign requested address
167    pub const EADDRNOTAVAIL: Errno = errno!(libc::EADDRNOTAVAIL);
168    /// Network is down
169    pub const ENETDOWN: Errno = errno!(libc::ENETDOWN);
170    /// Network is unreachable
171    pub const ENETUNREACH: Errno = errno!(libc::ENETUNREACH);
172    /// Network dropped connection on reset
173    pub const ENETRESET: Errno = errno!(libc::ENETRESET);
174    /// Software caused connection abort
175    pub const ECONNABORTED: Errno = errno!(libc::ECONNABORTED);
176    /// Connection reset by peer
177    pub const ECONNRESET: Errno = errno!(libc::ECONNRESET);
178    /// No buffer space available
179    pub const ENOBUFS: Errno = errno!(libc::ENOBUFS);
180    /// Transport endpoint is already connected
181    pub const EISCONN: Errno = errno!(libc::EISCONN);
182    /// Transport endpoint is not connected
183    pub const ENOTCONN: Errno = errno!(libc::ENOTCONN);
184    /// Cannot send after transport endpoint shutdown
185    pub const ESHUTDOWN: Errno = errno!(libc::ESHUTDOWN);
186    /// Too many references: cannot splice
187    pub const ETOOMANYREFS: Errno = errno!(libc::ETOOMANYREFS);
188    /// Connection timed out
189    pub const ETIMEDOUT: Errno = errno!(libc::ETIMEDOUT);
190    /// Connection refused
191    pub const ECONNREFUSED: Errno = errno!(libc::ECONNREFUSED);
192    /// Host is down
193    pub const EHOSTDOWN: Errno = errno!(libc::EHOSTDOWN);
194    /// No route to host
195    pub const EHOSTUNREACH: Errno = errno!(libc::EHOSTUNREACH);
196    /// Operation already in progress
197    pub const EALREADY: Errno = errno!(libc::EALREADY);
198    /// Operation now in progress
199    pub const EINPROGRESS: Errno = errno!(libc::EINPROGRESS);
200    /// Stale file handle
201    pub const ESTALE: Errno = errno!(libc::ESTALE);
202    /// Disk quota exceeded
203    pub const EDQUOT: Errno = errno!(libc::EDQUOT);
204    /// Operation cancelled
205    pub const ECANCELED: Errno = errno!(libc::ECANCELED);
206    /// Owner died
207    pub const EOWNERDEAD: Errno = errno!(libc::EOWNERDEAD);
208    /// State not recoverable
209    pub const ENOTRECOVERABLE: Errno = errno!(libc::ENOTRECOVERABLE);
210    /// Operation not supported
211    pub const ENOTSUP: Errno = errno!(libc::ENOTSUP);
212
213    /// No data available
214    #[cfg(target_os = "linux")]
215    pub const ENODATA: Errno = errno!(libc::ENODATA);
216    /// Attribute not found
217    #[cfg(not(target_os = "linux"))]
218    pub const ENOATTR: Errno = errno!(libc::ENOATTR);
219
220    /// Use this as an error return from getxattr/removexattr to indicate that the xattr doesn't
221    /// exist.  This resolves to the appropriate platform specific error code.
222    #[cfg(target_os = "linux")]
223    pub const NO_XATTR: Errno = Self::ENODATA;
224    #[cfg(not(target_os = "linux"))]
225    pub const NO_XATTR: Errno = Self::ENOATTR;
226
227    pub fn from_i32(err: i32) -> Errno {
228        err.try_into().ok().map(Errno).unwrap_or(Errno::EIO)
229    }
230}
231impl From<std::io::Error> for Errno {
232    fn from(err: std::io::Error) -> Self {
233        let errno = err.raw_os_error().unwrap_or(0);
234        match errno.try_into() {
235            Ok(i) => Errno(i),
236            Err(_) => Errno::EIO,
237        }
238    }
239}
240impl From<nix::errno::Errno> for Errno {
241    fn from(x: nix::errno::Errno) -> Self {
242        let err: std::io::Error = x.into();
243        err.into()
244    }
245}
246impl From<std::io::ErrorKind> for Errno {
247    fn from(x: std::io::ErrorKind) -> Self {
248        let err: std::io::Error = x.into();
249        err.into()
250    }
251}
252impl From<Errno> for i32 {
253    fn from(x: Errno) -> Self {
254        x.0.into()
255    }
256}
257
258/// A newtype for generation numbers
259///
260/// If the file system will be exported over NFS, the (ino, generation) pairs
261/// need to be unique over the file system's lifetime (rather than just the
262/// mount time). So if the file system reuses an inode after it has been
263/// deleted, it must assign a new, previously unused generation number to the
264/// inode at the same time.
265#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
266pub struct Generation(pub u64);
267impl From<Generation> for u64 {
268    fn from(fh: Generation) -> Self {
269        fh.0
270    }
271}
272
273#[cfg(test)]
274mod test {
275    use std::io::IoSlice;
276    use std::ops::{Deref, DerefMut};
277    /// If we want to be able to cast bytes to our fuse C struct types we need it
278    /// to be aligned.  This struct helps getting &[u8]s which are 8 byte aligned.
279    #[cfg(test)]
280    #[repr(align(8))]
281    pub(crate) struct AlignedData<T>(pub T);
282    impl<T> Deref for AlignedData<T> {
283        type Target = T;
284
285        fn deref(&self) -> &Self::Target {
286            &self.0
287        }
288    }
289    impl<T> DerefMut for AlignedData<T> {
290        fn deref_mut(&mut self) -> &mut Self::Target {
291            &mut self.0
292        }
293    }
294
295    pub fn ioslice_to_vec(s: &[IoSlice<'_>]) -> Vec<u8> {
296        let mut v = Vec::with_capacity(s.iter().map(|x| x.len()).sum());
297        for x in s {
298            v.extend_from_slice(x);
299        }
300        v
301    }
302}