async_fusex/
channel.rs

1//! The implementation of FUSE channel
2
3use std::os::unix::io::RawFd;
4
5use anyhow::{anyhow, Context};
6use clippy_utilities::Cast;
7use nix::fcntl::{self, FcntlArg, FdFlag, OFlag};
8use nix::ioctl_read;
9use nix::sys::stat::Mode;
10use nix::unistd::close;
11
12use super::file_system::FileSystem;
13use super::session::Session;
14
15/// FUSE channel
16#[derive(Debug)]
17pub struct Channel {
18    /// FUSE channel fd cloned from session fd
19    chan_fd: RawFd,
20}
21
22impl Channel {
23    /// Create FUSE channel
24    #[allow(dead_code)]
25    pub async fn new<F: FileSystem + Send + Sync + 'static>(
26        session: &Session<F>,
27    ) -> anyhow::Result<Self> {
28        let devname = "/dev/fuse";
29        let clonefd = tokio::task::spawn_blocking(move || {
30            fcntl::open(devname, OFlag::O_RDWR | OFlag::O_CLOEXEC, Mode::empty())
31        })
32        .await?;
33
34        let clonefd = match clonefd {
35            Err(err) => {
36                return Err(anyhow!("fuse: failed to open {:?}: {:?}", devname, err));
37            }
38            Ok(fd) => fd,
39        };
40
41        if let Err(err) = tokio::task::spawn_blocking(move || {
42            fcntl::fcntl(clonefd, FcntlArg::F_SETFD(FdFlag::FD_CLOEXEC))
43        })
44        .await?
45        {
46            return Err(anyhow!(
47                "fuse: failed to set clonefd to FD_CLOEXEC: {:?}",
48                err,
49            ));
50        }
51
52        ioctl_read!(clone, 229, 0, u32);
53        let masterfd = session.dev_fd();
54        let mut masterfd_u32 = masterfd.cast();
55        let res = tokio::task::spawn_blocking(move || unsafe { clone(clonefd, &mut masterfd_u32) })
56            .await?;
57        if let Err(err) = res {
58            close(clonefd).context("fuse: failed to close clone device")?;
59            return Err(anyhow!("fuse: failed to clone device fd: {:?}", err,));
60        }
61
62        Ok(Self { chan_fd: clonefd })
63    }
64
65    /// Get channel fd
66    #[allow(dead_code)]
67    #[must_use]
68    pub const fn fd(&self) -> RawFd {
69        self.chan_fd
70    }
71}