use std::io::Result as IoResult;
use std::path::Path;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use nix::sys::stat::mode_t;
pub use async_trait::async_trait;
pub use errno::Errno;
pub use filesystem::Filesystem;
pub use helper::perm_from_mode_and_kind;
pub use mount_options::MountOptions;
pub use request::Request;
#[cfg(any(feature = "async-std-runtime", feature = "tokio-runtime"))]
use session::Session;
use crate::abi::{
fuse_attr, fuse_setattr_in, FATTR_ATIME, FATTR_CTIME, FATTR_FH, FATTR_GID, FATTR_LOCKOWNER,
FATTR_MODE, FATTR_MTIME, FATTR_SIZE, FATTR_UID,
};
use crate::helper::mode_from_kind_and_perm;
mod abi;
mod connection;
mod errno;
mod filesystem;
mod helper;
mod mount_options;
pub mod reply;
mod request;
mod session;
mod spawn;
pub type Result<T> = std::result::Result<T, Errno>;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct FileAttr {
pub ino: u64,
pub generation: u64,
pub size: u64,
pub blocks: u64,
pub atime: SystemTime,
pub mtime: SystemTime,
pub ctime: SystemTime,
#[cfg(target_os = "macos")]
pub crtime: SystemTime,
pub kind: FileType,
pub perm: u16,
pub nlink: u32,
pub uid: u32,
pub gid: u32,
pub rdev: u32,
#[cfg(target_os = "macos")]
pub flags: u32,
pub blksize: u32,
}
impl Into<fuse_attr> for FileAttr {
fn into(self) -> fuse_attr {
fuse_attr {
ino: self.ino,
size: self.size,
blocks: self.blocks,
atime: self
.atime
.duration_since(UNIX_EPOCH)
.expect("won't early")
.as_secs(),
mtime: self
.mtime
.duration_since(UNIX_EPOCH)
.expect("won't early")
.as_secs(),
ctime: self
.ctime
.duration_since(UNIX_EPOCH)
.expect("won't early")
.as_secs(),
atimensec: self
.atime
.duration_since(UNIX_EPOCH)
.expect("won't early")
.subsec_nanos(),
mtimensec: self
.mtime
.duration_since(UNIX_EPOCH)
.expect("won't early")
.subsec_nanos(),
ctimensec: self
.ctime
.duration_since(UNIX_EPOCH)
.expect("won't early")
.subsec_nanos(),
mode: mode_from_kind_and_perm(self.kind, self.perm),
nlink: self.nlink,
uid: self.uid,
gid: self.gid,
rdev: self.rdev,
blksize: self.blksize,
padding: 0,
}
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum FileType {
NamedPipe,
CharDevice,
BlockDevice,
Directory,
RegularFile,
Symlink,
Socket,
}
impl From<FileType> for mode_t {
fn from(kind: FileType) -> Self {
match kind {
FileType::NamedPipe => libc::S_IFIFO,
FileType::CharDevice => libc::S_IFCHR,
FileType::BlockDevice => libc::S_IFBLK,
FileType::Directory => libc::S_IFDIR,
FileType::RegularFile => libc::S_IFREG,
FileType::Symlink => libc::S_IFLNK,
FileType::Socket => libc::S_IFSOCK,
}
}
}
#[derive(Debug, Clone, Default)]
pub struct SetAttr {
pub mode: Option<u32>,
pub uid: Option<u32>,
pub gid: Option<u32>,
pub size: Option<u64>,
pub lock_owner: Option<u64>,
pub atime: Option<SystemTime>,
pub mtime: Option<SystemTime>,
pub fh: Option<u64>,
pub atime_now: Option<SystemTime>,
pub mtime_now: Option<SystemTime>,
pub ctime: Option<SystemTime>,
#[cfg(target_os = "macos")]
pub crtime: Option<SystemTime>,
#[cfg(target_os = "macos")]
pub chgtime: Option<SystemTime>,
#[cfg(target_os = "macos")]
pub bkuptime: Option<SystemTime>,
#[cfg(target_os = "macos")]
pub flags: Option<u32>,
}
impl From<&fuse_setattr_in> for SetAttr {
fn from(setattr_in: &fuse_setattr_in) -> Self {
let mut set_attr = Self::default();
if setattr_in.valid & FATTR_MODE > 0 {
set_attr.mode = Some(setattr_in.mode);
}
if setattr_in.valid & FATTR_UID > 0 {
set_attr.uid = Some(setattr_in.uid);
}
if setattr_in.valid & FATTR_GID > 0 {
set_attr.gid = Some(setattr_in.gid);
}
if setattr_in.valid & FATTR_SIZE > 0 {
set_attr.size = Some(setattr_in.size);
}
if setattr_in.valid & FATTR_ATIME > 0 {
set_attr.atime =
Some(UNIX_EPOCH + Duration::new(setattr_in.atime, setattr_in.atimensec));
}
if setattr_in.valid & FATTR_MTIME > 0 {
set_attr.mtime =
Some(UNIX_EPOCH + Duration::new(setattr_in.mtime, setattr_in.mtimensec));
}
if setattr_in.valid & FATTR_FH > 0 {
set_attr.fh = Some(setattr_in.fh);
}
if setattr_in.valid & FATTR_LOCKOWNER > 0 {
set_attr.lock_owner = Some(setattr_in.lock_owner);
}
if setattr_in.valid & FATTR_CTIME > 0 {
set_attr.ctime =
Some(UNIX_EPOCH + Duration::new(setattr_in.ctime, setattr_in.ctimensec));
}
set_attr
}
}
#[cfg(any(feature = "async-std-runtime", feature = "tokio-runtime"))]
pub async fn mount<FS, P>(fs: FS, mount_path: P, mount_options: MountOptions) -> IoResult<()>
where
FS: Filesystem + Send + Sync + 'static,
P: AsRef<Path>,
{
Session::mount(fs, mount_path, mount_options).await
}
#[cfg(all(
any(feature = "async-std-runtime", feature = "tokio-runtime"),
feature = "unprivileged"
))]
pub async fn mount_with_unprivileged<FS, P>(
fs: FS,
mount_path: P,
mount_options: MountOptions,
) -> IoResult<()>
where
FS: Filesystem + Send + Sync + 'static,
P: AsRef<Path>,
{
Session::mount_with_unprivileged(fs, mount_path, mount_options).await
}
pub mod prelude {
pub use crate::reply::*;
pub use crate::Errno;
pub use crate::FileAttr;
pub use crate::FileType;
pub use crate::Filesystem;
pub use crate::MountOptions;
pub use crate::Request;
pub use crate::Result;
pub use crate::SetAttr;
}