easy_fuser 0.7.1

A flexible and idiomatic Fuse implementation for Rust
Documentation
use super::super::file_descriptor_handler::{
    file_descriptor_handler_readonly_methods, file_descriptor_handler_readwrite_methods,
};
use super::*;
use std::os::fd::{AsFd, OwnedFd};

impl OverlayFs {
    pub fn access(
        &self,
        _req: &RequestInfo,
        file_id: PathBuf,
        mask: AccessFlags,
    ) -> FuseResult<()> {
        let entry = self
            .resolve(&file_id)?
            .ok_or_else(|| ErrorKind::FileNotFound.to_error("overlay entry does not exist"))?;
        unix_fs::access(&entry.path, mask)
    }

    pub fn getattr(
        &self,
        _req: &RequestInfo,
        file_id: PathBuf,
        file_handle: Option<&mut OwnedFd>,
    ) -> FuseResult<FileAttribute> {
        if let Some(file_handle) = file_handle {
            return unix_fs::getattr(file_handle.as_fd());
        }
        let entry = self
            .resolve(&file_id)?
            .ok_or_else(|| ErrorKind::FileNotFound.to_error("overlay entry does not exist"))?;
        unix_fs::lookup(&entry.path)
    }

    pub fn getxattr(
        &self,
        _req: &RequestInfo,
        file_id: PathBuf,
        name: &OsStr,
        size: u32,
    ) -> FuseResult<Vec<u8>> {
        let entry = self
            .resolve(&file_id)?
            .ok_or_else(|| ErrorKind::FileNotFound.to_error("overlay entry does not exist"))?;
        unix_fs::getxattr(&entry.path, name, size)
    }

    pub fn listxattr(
        &self,
        _req: &RequestInfo,
        file_id: PathBuf,
        size: u32,
    ) -> FuseResult<Vec<u8>> {
        let entry = self
            .resolve(&file_id)?
            .ok_or_else(|| ErrorKind::FileNotFound.to_error("overlay entry does not exist"))?;
        unix_fs::listxattr(&entry.path, size)
    }

    pub fn link(
        &self,
        _req: &RequestInfo,
        file_id: PathBuf,
        newparent: PathBuf,
        newname: &OsStr,
    ) -> FuseResult<FileAttribute> {
        let _guard = self.mutation_guard()?;
        let destination_path = self.child_path(&newparent, newname)?;
        self.link_path(&file_id, &destination_path)
    }

    pub fn lookup(
        &self,
        _req: &RequestInfo,
        parent_id: PathBuf,
        name: &OsStr,
    ) -> FuseResult<FileAttribute> {
        let path = self.child_path(&parent_id, name)?;
        let entry = self
            .resolve(&path)?
            .ok_or_else(|| ErrorKind::FileNotFound.to_error("overlay entry does not exist"))?;
        unix_fs::lookup(&entry.path)
    }

    pub fn open(
        &self,
        _req: &RequestInfo,
        file_id: PathBuf,
        flags: OpenFlags,
    ) -> FuseResult<(OwnedFd, FopenFlags)> {
        let path = self.normalize_path(&file_id)?;
        if flags.0 & libc::O_ACCMODE != libc::O_RDONLY {
            let _guard = self.mutation_guard()?;
            self.copy_up(&path)?;
        }
        let entry = self
            .resolve(&path)?
            .ok_or_else(|| ErrorKind::FileNotFound.to_error("overlay entry does not exist"))?;
        let fd = unix_fs::open(&entry.path, flags)?;
        Ok((fd, FopenFlags::empty()))
    }

    pub fn readdir(
        &self,
        _req: &RequestInfo,
        file_id: PathBuf,
        _file_handle: BorrowedFileHandle<'_>,
    ) -> FuseResult<Vec<(OsString, FileKind)>> {
        self.readdir_entries(&file_id)
    }

    pub fn readdirplus(
        &self,
        req: &RequestInfo,
        file_id: PathBuf,
        file_handle: BorrowedFileHandle<'_>,
    ) -> FuseResult<Vec<(OsString, FileAttribute)>> {
        let entries = self.readdir(req, file_id.clone(), file_handle)?;
        entries
            .into_iter()
            .map(|(name, _)| {
                let attribute = match name.as_os_str() {
                    name if name == OsStr::new(".") => self.getattr(req, file_id.clone(), None)?,
                    name if name == OsStr::new("..") => {
                        let parent = file_id.parent().unwrap_or(Path::new(""));
                        self.getattr(req, parent.to_path_buf(), None)?
                    }
                    _ => self.lookup(req, file_id.clone(), &name)?,
                };
                Ok((name, attribute))
            })
            .collect()
    }

    pub fn bmap(
        &self,
        _req: &RequestInfo,
        file_id: PathBuf,
        blocksize: u32,
        index: u64,
    ) -> FuseResult<u64> {
        let entry = self
            .resolve(&file_id)?
            .ok_or_else(|| ErrorKind::FileNotFound.to_error("overlay entry does not exist"))?;
        unix_fs::bmap(&entry.path, blocksize, index)
    }

    pub fn readlink(&self, _req: &RequestInfo, file_id: PathBuf) -> FuseResult<Vec<u8>> {
        let entry = self
            .resolve(&file_id)?
            .ok_or_else(|| ErrorKind::FileNotFound.to_error("overlay entry does not exist"))?;
        unix_fs::readlink(&entry.path)
    }

    pub fn statfs(&self, _req: &RequestInfo, _file_id: PathBuf) -> FuseResult<StatFs> {
        unix_fs::statfs(&self.upper_dir)
    }

    pub fn create(
        &self,
        _req: &RequestInfo,
        parent_id: PathBuf,
        name: &OsStr,
        mode: u32,
        umask: u32,
        flags: OpenFlags,
    ) -> FuseResult<(OwnedFd, FileAttribute, FopenFlags)> {
        let _guard = self.mutation_guard()?;
        let path = self.child_path(&parent_id, name)?;
        if let Some(entry) = self.resolve(&path)? {
            if flags.0 & libc::O_EXCL != 0 {
                return Err(ErrorKind::FileExists.to_error("overlay entry already exists"));
            }
            if !entry.from_upper {
                self.copy_up(&path)?;
            }
        }
        self.ensure_upper_parents(&path)?;
        let upper_path = self.upper_dir.join(&path);
        let (fd, attributes) = unix_fs::create(&upper_path, mode, umask, flags)?;
        Ok((fd, attributes, FopenFlags::empty()))
    }

    pub fn mkdir(
        &self,
        _req: &RequestInfo,
        parent_id: PathBuf,
        name: &OsStr,
        mode: u32,
        umask: u32,
    ) -> FuseResult<FileAttribute> {
        let _guard = self.mutation_guard()?;
        let path = self.child_path(&parent_id, name)?;
        if self.resolve(&path)?.is_some() {
            return Err(ErrorKind::FileExists.to_error("overlay entry already exists"));
        }
        self.ensure_upper_parents(&path)?;
        unix_fs::mkdir(&self.upper_dir.join(path), mode, umask)
    }

    pub fn mknod(
        &self,
        _req: &RequestInfo,
        parent_id: PathBuf,
        name: &OsStr,
        mode: u32,
        umask: u32,
        rdev: DeviceType,
    ) -> FuseResult<FileAttribute> {
        let _guard = self.mutation_guard()?;
        let path = self.child_path(&parent_id, name)?;
        if self.resolve(&path)?.is_some() {
            return Err(ErrorKind::FileExists.to_error("overlay entry already exists"));
        }
        self.ensure_upper_parents(&path)?;
        unix_fs::mknod(&self.upper_dir.join(path), mode, umask, rdev)
    }

    pub fn removexattr(
        &self,
        _req: &RequestInfo,
        file_id: PathBuf,
        name: &OsStr,
    ) -> FuseResult<()> {
        let _guard = self.mutation_guard()?;
        let path = self.normalize_path(&file_id)?;
        let upper_path = self.copy_up_for_metadata(&path)?;
        unix_fs::removexattr(&upper_path, name)
    }

    pub fn rename(
        &self,
        _req: &RequestInfo,
        parent_id: PathBuf,
        name: &OsStr,
        newparent: PathBuf,
        newname: &OsStr,
        flags: RenameFlags,
    ) -> FuseResult<()> {
        let _guard = self.mutation_guard()?;
        let old_path = self.child_path(&parent_id, name)?;
        let new_path = self.child_path(&newparent, newname)?;
        self.rename_path(&old_path, &new_path, flags)
    }

    pub fn rmdir(&self, _req: &RequestInfo, parent_id: PathBuf, name: &OsStr) -> FuseResult<()> {
        let _guard = self.mutation_guard()?;
        let path = self.child_path(&parent_id, name)?;
        self.rmdir_path(&path)
    }

    pub fn setattr(
        &self,
        _req: &RequestInfo,
        file_id: PathBuf,
        attrs: SetAttrRequest,
        _file_handle: Option<&mut OwnedFd>,
    ) -> FuseResult<FileAttribute> {
        let _guard = self.mutation_guard()?;
        let path = self.normalize_path(&file_id)?;
        let upper_path = self.copy_up_for_metadata(&path)?;
        unix_fs::setattr(&upper_path, attrs)
    }

    pub fn setxattr(
        &self,
        _req: &RequestInfo,
        file_id: PathBuf,
        name: &OsStr,
        value: Vec<u8>,
        flags: SetXAttrFlags,
        position: u32,
    ) -> FuseResult<()> {
        let _guard = self.mutation_guard()?;
        let path = self.normalize_path(&file_id)?;
        let upper_path = self.copy_up_for_metadata(&path)?;
        unix_fs::setxattr(&upper_path, name, &value, flags, position)
    }

    pub fn symlink(
        &self,
        _req: &RequestInfo,
        parent_id: PathBuf,
        link_name: &OsStr,
        target: &Path,
    ) -> FuseResult<FileAttribute> {
        let _guard = self.mutation_guard()?;
        let path = self.child_path(&parent_id, link_name)?;
        if self.resolve(&path)?.is_some() {
            return Err(ErrorKind::FileExists.to_error("overlay entry already exists"));
        }
        self.ensure_upper_parents(&path)?;
        unix_fs::symlink(&self.upper_dir.join(path), target)
    }

    pub fn unlink(&self, _req: &RequestInfo, parent_id: PathBuf, name: &OsStr) -> FuseResult<()> {
        let _guard = self.mutation_guard()?;
        let path = self.child_path(&parent_id, name)?;
        self.unlink_path(&path)
    }

    file_descriptor_handler_readonly_methods!(PathBuf);
    file_descriptor_handler_readwrite_methods!(PathBuf);
}