Skip to content

Commit

Permalink
feat: introduce macos mount API support (#2347)
Browse files Browse the repository at this point in the history
* feat: introduce macos mount API support

* feat: add doc comment

* feat: fix code

* feat: fix code

* feat: fix code

* feat: fix code

* feat: fix code

* feat: fix code

* feat: fix code

* feat: fix code

* feat: fix code

* feat: fix code
  • Loading branch information
oowl authored Apr 2, 2024
1 parent 1ed24e6 commit bc374af
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 11 deletions.
1 change: 1 addition & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ fn main() {
// cfg aliases we would like to use
apple_targets: { any(ios, macos, watchos, tvos) },
bsd: { any(freebsd, dragonfly, netbsd, openbsd, apple_targets) },
bsd_without_apple: { any(freebsd, dragonfly, netbsd, openbsd) },
linux_android: { any(android, linux) },
freebsdlike: { any(dragonfly, freebsd) },
netbsdlike: { any(netbsd, openbsd) },
Expand Down
1 change: 1 addition & 0 deletions changelog/2347.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add `mount` and `unmount` API for apple targets.
122 changes: 122 additions & 0 deletions src/mount/apple.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
use crate::{Errno, NixPath, Result};
use libc::c_int;

libc_bitflags!(
/// Used with [`mount()`] and [`unmount()`].
pub struct MntFlags: c_int {
/// Do not interpret special files on the filesystem.
MNT_NODEV;
/// Enable data protection on the filesystem if the filesystem is configured for it.
MNT_CPROTECT;
/// file system is quarantined
MNT_QUARANTINE;
/// filesystem is stored locally
MNT_LOCAL;
/// quotas are enabled on filesystem
MNT_QUOTA;
/// identifies the root filesystem
MNT_ROOTFS;
/// file system is not appropriate path to user data
MNT_DONTBROWSE;
/// VFS will ignore ownership information on filesystem objects
MNT_IGNORE_OWNERSHIP;
/// filesystem was mounted by automounter
MNT_AUTOMOUNTED;
/// filesystem is journaled
MNT_JOURNALED;
/// Don't allow user extended attributes
MNT_NOUSERXATTR;
/// filesystem should defer writes
MNT_DEFWRITE;
/// don't block unmount if not responding
MNT_NOBLOCK;
/// file system is exported
MNT_EXPORTED;
/// file system written asynchronously
MNT_ASYNC;
/// Force a read-write mount even if the file system appears to be
/// unclean.
MNT_FORCE;
/// MAC support for objects.
MNT_MULTILABEL;
/// Do not update access times.
MNT_NOATIME;
/// Disallow program execution.
MNT_NOEXEC;
/// Do not honor setuid or setgid bits on files when executing them.
MNT_NOSUID;
/// Mount read-only.
MNT_RDONLY;
/// Causes the vfs subsystem to update its data structures pertaining to
/// the specified already mounted file system.
MNT_RELOAD;
/// Create a snapshot of the file system.
MNT_SNAPSHOT;
/// All I/O to the file system should be done synchronously.
MNT_SYNCHRONOUS;
/// Union with underlying fs.
MNT_UNION;
/// Indicates that the mount command is being applied to an already
/// mounted file system.
MNT_UPDATE;
}
);

/// Mount a file system.
///
/// # Arguments
/// - `source` - Specifies the file system. e.g. `/dev/sd0`.
/// - `target` - Specifies the destination. e.g. `/mnt`.
/// - `flags` - Optional flags controlling the mount.
/// - `data` - Optional file system specific data.
///
/// # see also
/// [`mount`](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/mount.2.html)
pub fn mount<
P1: ?Sized + NixPath,
P2: ?Sized + NixPath,
P3: ?Sized + NixPath,
>(
source: &P1,
target: &P2,
flags: MntFlags,
data: Option<&P3>,
) -> Result<()> {
fn with_opt_nix_path<P, T, F>(p: Option<&P>, f: F) -> Result<T>
where
P: ?Sized + NixPath,
F: FnOnce(*const libc::c_char) -> T,
{
match p {
Some(path) => path.with_nix_path(|p_str| f(p_str.as_ptr())),
None => Ok(f(std::ptr::null())),
}
}

let res = source.with_nix_path(|s| {
target.with_nix_path(|t| {
with_opt_nix_path(data, |d| unsafe {
libc::mount(
s.as_ptr(),
t.as_ptr(),
flags.bits(),
d.cast_mut().cast(),
)
})
})
})???;

Errno::result(res).map(drop)
}

/// Umount the file system mounted at `target`.
pub fn unmount<P>(target: &P, flags: MntFlags) -> Result<()>
where
P: ?Sized + NixPath,
{
let res = target.with_nix_path(|cstr| unsafe {
libc::unmount(cstr.as_ptr(), flags.bits())
})?;

Errno::result(res).map(drop)
}
5 changes: 2 additions & 3 deletions src/mount/bsd.rs → src/mount/bsd_without_apple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ libc_bitflags!(
#[cfg(target_os = "freebsd")]
MNT_GJOURNAL;
/// MAC support for objects.
#[cfg(any(apple_targets, target_os = "freebsd"))]
#[cfg(target_os = "freebsd")]
MNT_MULTILABEL;
/// Disable read clustering.
#[cfg(freebsdlike)]
Expand Down Expand Up @@ -58,7 +58,7 @@ libc_bitflags!(
/// Create a snapshot of the file system.
///
/// See [mksnap_ffs(8)](https://www.freebsd.org/cgi/man.cgi?query=mksnap_ffs)
#[cfg(any(apple_targets, target_os = "freebsd"))]
#[cfg(target_os = "freebsd")]
MNT_SNAPSHOT;
/// Using soft updates.
#[cfg(any(freebsdlike, netbsdlike))]
Expand All @@ -71,7 +71,6 @@ libc_bitflags!(
MNT_SYNCHRONOUS;
/// Union with underlying fs.
#[cfg(any(
apple_targets,
target_os = "freebsd",
target_os = "netbsd"
))]
Expand Down
14 changes: 10 additions & 4 deletions src/mount/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@ mod linux;
#[cfg(linux_android)]
pub use self::linux::*;

#[cfg(bsd)]
mod bsd;
#[cfg(bsd_without_apple)]
mod bsd_without_apple;

#[cfg(bsd)]
pub use self::bsd::*;
#[cfg(bsd_without_apple)]
pub use self::bsd_without_apple::*;

#[cfg(apple_targets)]
mod apple;

#[cfg(apple_targets)]
pub use self::apple::*;
6 changes: 6 additions & 0 deletions test/mount/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#[cfg(target_os = "linux")]
mod test_mount;
#[cfg(apple_targets)]
mod test_mount_apple;
#[cfg(target_os = "freebsd")]
mod test_nmount;
File renamed without changes.
8 changes: 8 additions & 0 deletions test/mount/test_mount_apple.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use nix::errno::Errno;
use nix::mount::{mount, MntFlags};

#[test]
fn test_mount() {
let res = mount::<str, str, str>("", "", MntFlags::empty(), None);
assert_eq!(res, Err(Errno::ENOENT));
}
File renamed without changes.
5 changes: 1 addition & 4 deletions test/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ extern crate cfg_if;
extern crate nix;

mod common;
mod mount;
mod sys;
#[cfg(not(target_os = "redox"))]
mod test_dir;
mod test_errno;
mod test_fcntl;
#[cfg(linux_android)]
mod test_kmod;
#[cfg(target_os = "linux")]
mod test_mount;
#[cfg(any(
freebsdlike,
target_os = "fushsia",
Expand All @@ -23,8 +22,6 @@ mod test_mq;
#[cfg(not(target_os = "redox"))]
mod test_net;
mod test_nix_path;
#[cfg(target_os = "freebsd")]
mod test_nmount;
mod test_poll;
#[cfg(not(any(
target_os = "redox",
Expand Down

0 comments on commit bc374af

Please sign in to comment.