1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use std::{
fs::File,
io,
os::{
fd::{AsFd, BorrowedFd},
unix::prelude::AsRawFd,
},
sync::Arc,
};
use libc::{c_int, c_void, size_t};
#[cfg(feature = "abi-7-40")]
use crate::passthrough::BackingId;
use crate::reply::ReplySender;
/// A raw communication channel to the FUSE kernel driver
#[derive(Debug)]
pub struct Channel(Arc<File>);
impl AsFd for Channel {
fn as_fd(&self) -> BorrowedFd<'_> {
self.0.as_fd()
}
}
impl Channel {
/// Create a new communication channel to the kernel driver by mounting the
/// given path. The kernel driver will delegate filesystem operations of
/// the given path to the channel.
pub(crate) fn new(device: Arc<File>) -> Self {
Self(device)
}
/// Receives data up to the capacity of the given buffer (can block).
pub fn receive(&self, buffer: &mut [u8]) -> io::Result<usize> {
let rc = unsafe {
libc::read(
self.0.as_raw_fd(),
buffer.as_ptr() as *mut c_void,
buffer.len() as size_t,
)
};
if rc < 0 {
Err(io::Error::last_os_error())
} else {
Ok(rc as usize)
}
}
/// Returns a sender object for this channel. The sender object can be
/// used to send to the channel. Multiple sender objects can be used
/// and they can safely be sent to other threads.
pub fn sender(&self) -> ChannelSender {
// Since write/writev syscalls are threadsafe, we can simply create
// a sender by using the same file and use it in other threads.
ChannelSender(self.0.clone())
}
}
#[derive(Clone, Debug)]
pub struct ChannelSender(Arc<File>);
impl ReplySender for ChannelSender {
fn send(&self, bufs: &[io::IoSlice<'_>]) -> io::Result<()> {
let rc = unsafe {
libc::writev(
self.0.as_raw_fd(),
bufs.as_ptr() as *const libc::iovec,
bufs.len() as c_int,
)
};
if rc < 0 {
Err(io::Error::last_os_error())
} else {
debug_assert_eq!(bufs.iter().map(|b| b.len()).sum::<usize>(), rc as usize);
Ok(())
}
}
#[cfg(feature = "abi-7-40")]
fn open_backing(&self, fd: BorrowedFd<'_>) -> std::io::Result<BackingId> {
BackingId::create(&self.0, fd)
}
}