use std::path::Path;
use super::fd_handler_helper::*;
use crate::types::*;
use crate::unix_fs;
macro_rules! mirror_fs_readonly_methods {
() => {
pub fn access(&self, _req: &RequestInfo, file_id: std::path:: PathBuf, mask: AccessMask) -> FuseResult<()> {
let file_path = self.source_path.join(file_id);
unix_fs::access(&file_path, mask)
}
pub fn getattr(
&self,
_req: &RequestInfo,
file_id: std::path:: PathBuf,
_file_handle: Option<BorrowedFileHandle>,
) -> FuseResult<FileAttribute> {
let file_path = self.source_path.join(file_id);
unix_fs::lookup(&file_path)
}
pub fn getxattr(
&self,
_req: &RequestInfo,
file_id: std::path:: PathBuf,
name: &std::ffi::OsStr,
size: u32,
) -> FuseResult<Vec<u8>> {
let file_path = self.source_path.join(file_id);
unix_fs::getxattr(&file_path, name, size)
}
pub fn listxattr(
&self,
_req: &RequestInfo,
file_id: std::path:: PathBuf,
size: u32,
) -> FuseResult<Vec<u8>> {
let file_path = self.source_path.join(file_id);
unix_fs::listxattr(&file_path, size)
}
pub fn lookup(
&self,
_req: &RequestInfo,
parent_id: std::path:: PathBuf,
name: &std::ffi::OsStr,
) -> FuseResult<FileAttribute> {
let file_path = self.source_path.join(parent_id).join(name);
unix_fs::lookup(&file_path)
}
pub fn open(
&self,
_req: &RequestInfo,
file_id: std::path:: PathBuf,
flags: OpenFlags,
) -> FuseResult<(OwnedFileHandle, FUSEOpenResponseFlags)> {
let file_path = self.source_path.join(file_id);
let fd = unix_fs::open(file_path.as_ref(), flags)?;
let file_handle = OwnedFileHandle::from_owned_fd(fd).unwrap();
Ok((file_handle, FUSEOpenResponseFlags::empty()))
}
pub fn readdir(
&self,
_req: &RequestInfo,
file_id: std::path:: PathBuf,
_file_handle: BorrowedFileHandle,
) -> FuseResult<Vec<(std::ffi::OsString, FileKind)>> {
let folder_path = self.source_path.join(file_id);
let children = unix_fs::readdir(folder_path.as_ref())?;
let mut result = Vec::new();
result.push((std::ffi::OsString::from("."), FileKind::Directory));
result.push((std::ffi::OsString::from(".."), FileKind::Directory));
for (child_name, child_kind) in children {
result.push((child_name, child_kind));
}
Ok(result)
}
pub fn readlink(&self, _req: &RequestInfo, file_id: std::path:: PathBuf) -> FuseResult<Vec<u8>> {
let file_path = self.source_path.join(file_id);
unix_fs::readlink(&file_path)
}
pub fn statfs(&self, _req: &RequestInfo, file_id: std::path:: PathBuf) -> FuseResult<StatFs> {
let file_path = self.source_path.join(file_id);
unix_fs::statfs(&file_path)
}
};
}
macro_rules! mirror_fs_readwrite_methods {
() => {
pub fn create(
&self,
_req: &RequestInfo,
parent_id: std::path:: PathBuf,
name: &std::ffi::OsStr,
mode: u32,
umask: u32,
flags: OpenFlags,
) -> FuseResult<(OwnedFileHandle, FileAttribute, FUSEOpenResponseFlags)> {
let file_path = self.source_path.join(parent_id).join(name);
let (fd, file_attr) = unix_fs::create(&file_path, mode, umask, flags)?;
let file_handle = OwnedFileHandle::from_owned_fd(fd).unwrap();
Ok((file_handle, file_attr, FUSEOpenResponseFlags::empty()))
}
pub fn mkdir(
&self,
_req: &RequestInfo,
parent_id: std::path:: PathBuf,
name: &std::ffi::OsStr,
mode: u32,
umask: u32,
) -> FuseResult<FileAttribute> {
let file_path = self.source_path.join(parent_id).join(name);
unix_fs::mkdir(&file_path, mode, umask)
}
pub fn mknod(
&self,
_req: &RequestInfo,
parent_id: std::path:: PathBuf,
name: &std::ffi::OsStr,
mode: u32,
umask: u32,
rdev: DeviceType,
) -> FuseResult<FileAttribute> {
let file_path = self.source_path.join(parent_id).join(name);
unix_fs::mknod(&file_path, mode, umask, rdev)
}
pub fn removexattr(
&self,
_req: &RequestInfo,
file_id: std::path:: PathBuf,
name: &std::ffi::OsStr,
) -> FuseResult<()> {
let file_path = self.source_path.join(file_id);
unix_fs::removexattr(&file_path, name)
}
pub fn rename(
&self,
_req: &RequestInfo,
parent_id: std::path:: PathBuf,
name: &std::ffi::OsStr,
newparent: std::path:: PathBuf,
newname: &std::ffi::OsStr,
flags: RenameFlags,
) -> FuseResult<()> {
let oldpath = self.source_path.join(parent_id).join(name);
let newpath = self.source_path.join(newparent).join(newname);
unix_fs::rename(&oldpath, &newpath, flags)
}
pub fn rmdir(&self, _req: &RequestInfo, parent_id: std::path:: PathBuf, name: &std::ffi::OsStr) -> FuseResult<()> {
let file_path = self.source_path.join(parent_id).join(name);
unix_fs::rmdir(&file_path)
}
pub fn setattr(
&self,
_req: &RequestInfo,
file_id: std::path:: PathBuf,
attrs: SetAttrRequest,
) -> FuseResult<FileAttribute> {
let file_path = self.source_path.join(file_id);
unix_fs::setattr(&file_path, attrs)
}
pub fn setxattr(
&self,
_req: &RequestInfo,
file_id: std::path:: PathBuf,
name: &std::ffi::OsStr,
value: Vec<u8>,
flags: FUSESetXAttrFlags,
position: u32,
) -> FuseResult<()> {
let file_path = self.source_path.join(file_id);
unix_fs::setxattr(&file_path, name, &value, flags, position)
}
pub fn symlink(
&self,
_req: &RequestInfo,
parent_id: std::path:: PathBuf,
link_name: &std::ffi::OsStr,
target: &std::path::Path,
) -> FuseResult<FileAttribute> {
let file_path = self.source_path.join(parent_id).join(link_name);
unix_fs::symlink(&file_path, target)
}
pub fn unlink(&self, _req: &RequestInfo, parent_id: std::path:: PathBuf, name: &std::ffi::OsStr) -> FuseResult<()> {
let file_path = self.source_path.join(parent_id).join(name);
unix_fs::unlink(&file_path)
}
};
}
pub trait MirrorFsTrait {
fn new(source_path: std::path:: PathBuf) -> Self;
fn source_dir(&self) -> &Path;
}
pub struct MirrorFs {
source_path: std::path:: PathBuf,
}
impl MirrorFsTrait for MirrorFs {
fn new(source_path: std::path:: PathBuf) -> Self {
Self { source_path }
}
fn source_dir(&self) -> &Path {
self.source_path.as_path()
}
}
impl MirrorFs {
mirror_fs_readonly_methods!();
mirror_fs_readwrite_methods!();
fd_handler_readonly_methods!(std::path::PathBuf);
fd_handler_readwrite_methods!(std::path::PathBuf);
}
pub struct MirrorFsReadOnly {
source_path: std::path:: PathBuf,
}
impl MirrorFsTrait for MirrorFsReadOnly {
fn new(source_path: std::path:: PathBuf) -> Self {
Self { source_path }
}
fn source_dir(&self) -> &Path {
self.source_path.as_path()
}
}
impl MirrorFsReadOnly {
mirror_fs_readonly_methods!();
fd_handler_readonly_methods!(std::path::PathBuf);
}