Skip to content

Commit

Permalink
feat: introduce macos support (#108)
Browse files Browse the repository at this point in the history
* feat: introduce macos support
  • Loading branch information
oowl authored Sep 27, 2024
1 parent 60ce9fa commit 42c54ec
Show file tree
Hide file tree
Showing 13 changed files with 543 additions and 75 deletions.
11 changes: 11 additions & 0 deletions .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ task:
- . $HOME/.cargo/env
<< : *BUILD

task:
name: MacOS
macos_instance:
image: ghcr.io/cirruslabs/macos-sonoma-base:latest
setup_script:
- curl https://sh.rustup.rs -o rustup.sh
- sh rustup.sh -y --profile=minimal
- . $HOME/.cargo/env
<< : *BUILD

task:
name: Linux
container:
Expand All @@ -34,6 +44,7 @@ minver_task:
depends_on:
- FreeBSD
- Linux
- MacOS
freebsd_instance:
image: freebsd-13-2-release-amd64
setup_script:
Expand Down
10 changes: 5 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 3 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,17 @@ bincode = "1.3.3"
bytes = "1.5"
futures-channel = { version = "0.3.30", features = ["sink"] }
futures-util = { version = "0.3.30", features = ["sink"] }
libc = "0.2.155"
nix = { version = "0.29.0", default-features = false, features = ["fs", "mount"] }
libc = "0.2.158"
nix = { version = "0.29.0", default-features = false, features = ["fs", "mount", "user"] }
serde = { version = "1.0.196", features = ["derive"] }
slab = "0.4.9"
tracing = "0.1.40"
trait-make = "0.1"
which = { version = "6", optional = true }

[target.'cfg(target_os = "linux")'.dependencies]
nix = { version = "0.29.0", default-features = false, features = ["user"] }

[dependencies.tokio]
version = "1.36"
features = ["fs", "rt", "sync", "net", "macros", "process"]
features = ["fs", "rt", "sync", "net", "macros", "process", "time"]
optional = true

[package.metadata.docs.rs]
Expand Down
2 changes: 1 addition & 1 deletion examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ path = "src/path_memfs/main.rs"

[dependencies]
fuse3 = { path = "../", features = ["tokio-runtime", "unprivileged"] }
libc = "0.2.155"
libc = "0.2.158"
tokio = { version = "1.36", features = ["macros", "rt", "time", "signal"] }
futures-util = "0.3.30"
mio = { version = "0.8.11", features = ["os-poll"] }
Expand Down
5 changes: 4 additions & 1 deletion src/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ pub const fn mode_from_kind_and_perm(kind: FileType, perm: u16) -> u32 {

// Some platforms like Linux x86_64 have mode_t = u32, and lint warns of a trivial_numeric_casts.
// But others like macOS x86_64 have mode_t = u16, requiring a typecast. So, just silence lint.
#[cfg(all(not(target_os = "linux"), target_os = "freebsd"))]
#[cfg(all(
not(target_os = "linux"),
any(target_os = "freebsd", target_os = "macos")
))]
#[allow(trivial_numeric_casts)]
/// returns the mode for a given file kind and permission
pub const fn mode_from_kind_and_perm(kind: FileType, perm: u16) -> u32 {
Expand Down
41 changes: 38 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]

#[cfg(all(target_os = "linux", feature = "unprivileged"))]
#[cfg(any(all(target_os = "linux", feature = "unprivileged"), target_os = "macos"))]
use std::io::{self, ErrorKind};
#[cfg(all(target_os = "linux", feature = "unprivileged"))]
use std::path::PathBuf;
#[cfg(any(all(target_os = "linux", feature = "unprivileged"), target_os = "macos"))]
use std::path::{PathBuf, Path};
use std::time::{Duration, SystemTime, UNIX_EPOCH};

pub use errno::Errno;
Expand All @@ -35,6 +35,9 @@ use raw::abi::{
FATTR_MODE, FATTR_MTIME, FATTR_MTIME_NOW, FATTR_SIZE, FATTR_UID,
};

#[cfg(target_os = "macos")]
use raw::abi::{FATTR_BKUPTIME, FATTR_CHGTIME, FATTR_CRTIME, FATTR_FLAGS};

mod errno;
mod helper;
mod mount_options;
Expand Down Expand Up @@ -169,6 +172,26 @@ impl From<&fuse_setattr_in> for SetAttr {
set_attr.ctime = fsai2ts!(setattr_in.ctime, setattr_in.ctimensec);
}

#[cfg(target_os = "macos")]
if setattr_in.valid & FATTR_CRTIME > 0 {
set_attr.ctime = fsai2ts!(setattr_in.crtime, setattr_in.crtimensec);
}

#[cfg(target_os = "macos")]
if setattr_in.valid & FATTR_CHGTIME > 0 {
set_attr.ctime = fsai2ts!(setattr_in.chgtime, setattr_in.chgtimensec);
}

#[cfg(target_os = "macos")]
if setattr_in.valid & FATTR_BKUPTIME > 0 {
set_attr.ctime = fsai2ts!(setattr_in.bkuptime, setattr_in.bkuptimensec);
}

#[cfg(target_os = "macos")]
if setattr_in.valid & FATTR_FLAGS > 0 {
set_attr.flags = Some(setattr_in.flags);
}

set_attr
}
}
Expand Down Expand Up @@ -214,3 +237,15 @@ fn find_fusermount3() -> io::Result<PathBuf> {
)
})
}

#[cfg(target_os = "macos")]
fn find_macfuse_mount() -> io::Result<PathBuf> {
if Path::new("/Library/Filesystems/macfuse.fs/Contents/Resources/mount_macfuse").exists() {
Ok(PathBuf::from("/Library/Filesystems/macfuse.fs/Contents/Resources/mount_macfuse"))
} else {
Err(io::Error::new(
ErrorKind::NotFound,
"macfuse mount binary not found, Please install macfuse first.",
))
}
}
55 changes: 51 additions & 4 deletions src/mount_options.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use std::ffi::OsString;
#[cfg(target_os = "linux")]
#[cfg(any(target_os = "linux", target_os = "macos"))]
use std::os::unix::io::RawFd;

#[cfg(target_os = "freebsd")]
use nix::mount::Nmount;
#[cfg(target_os = "linux")]
#[cfg(any(target_os = "macos", target_os = "linux"))]
use nix::unistd;

/// mount options.
Expand All @@ -22,7 +22,7 @@ pub struct MountOptions {
pub(crate) default_permissions: bool,
pub(crate) fs_name: Option<String>,
pub(crate) gid: Option<u32>,
#[cfg(target_os = "freebsd")]
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
pub(crate) intr: bool,
#[cfg(target_os = "linux")]
pub(crate) nodiratime: bool,
Expand All @@ -47,7 +47,6 @@ pub struct MountOptions {

// Other FUSE mount options
// default 40000
#[cfg(target_os = "linux")]
pub(crate) rootmode: Option<u32>,
}

Expand Down Expand Up @@ -244,6 +243,30 @@ impl MountOptions {
options
}

#[cfg(target_os = "macos")]
pub(crate) fn build(&self) -> OsString {
let mut opts = vec![
String::from("-o fsname=ofs"),
];

if self.allow_root {
opts.push("-o allow_root".to_string());
}

if self.allow_other {
opts.push("-o allow_other".to_string());
}

let mut options = OsString::from(opts.join(" "));

if let Some(custom_options) = &self.custom_options {
options.push(" ");
options.push(custom_options);
}

options
}

#[cfg(all(target_os = "linux", feature = "unprivileged"))]
pub(crate) fn build_with_unprivileged(&self) -> OsString {
let mut opts = vec![
Expand Down Expand Up @@ -314,6 +337,30 @@ impl MountOptions {
flags
}

#[cfg(target_os = "macos")]
pub(crate) fn flags(&self) -> nix::mount::MntFlags {
use nix::mount::MntFlags;

let mut flags = MntFlags::empty();
if self.noatime {
flags.insert(MntFlags::MNT_NOATIME);
}
if self.noexec {
flags.insert(MntFlags::MNT_NOEXEC);
}
if self.nosuid {
flags.insert(MntFlags::MNT_NOSUID);
}
if self.read_only {
flags.insert(MntFlags::MNT_RDONLY);
}

if self.sync {
flags.insert(MntFlags::MNT_SYNCHRONOUS);
}
flags
}

#[cfg(target_os = "linux")]
pub(crate) fn flags(&self) -> nix::mount::MsFlags {
use nix::mount::MsFlags;
Expand Down
4 changes: 4 additions & 0 deletions src/path/reply.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,16 @@ impl From<(Inode, FileAttr)> for crate::raw::reply::FileAttr {
atime: attr.atime.into(),
mtime: attr.mtime.into(),
ctime: attr.ctime.into(),
#[cfg(target_os = "macos")]
crtime: attr.crtime.into(),
kind: attr.kind,
perm: attr.perm,
nlink: attr.nlink,
uid: attr.uid,
gid: attr.gid,
rdev: attr.rdev,
#[cfg(target_os = "macos")]
flags: attr.flags,
blksize: attr.blksize,
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/raw/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,11 @@ pub const FUSE_RENAME_IN_SIZE: usize = mem::size_of::<fuse_rename_in>();
#[allow(non_camel_case_types)]
pub struct fuse_rename_in {
pub newdir: u64,
// https://github.com/osxfuse/fuse/blob/master/include/fuse_kernel.h#L448
#[cfg(target_os = "macos")]
pub flags: u32,
#[cfg(target_os = "macos")]
_padding: u32,
}

pub const FUSE_RENAME2_IN_SIZE: usize = mem::size_of::<fuse_rename2_in>();
Expand Down
Loading

0 comments on commit 42c54ec

Please sign in to comment.