Skip to content

Commit bc374af

Browse files
authored
feat: introduce macos mount API support (#2347)
* 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
1 parent 1ed24e6 commit bc374af

File tree

10 files changed

+151
-11
lines changed

10 files changed

+151
-11
lines changed

build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ fn main() {
1919
// cfg aliases we would like to use
2020
apple_targets: { any(ios, macos, watchos, tvos) },
2121
bsd: { any(freebsd, dragonfly, netbsd, openbsd, apple_targets) },
22+
bsd_without_apple: { any(freebsd, dragonfly, netbsd, openbsd) },
2223
linux_android: { any(android, linux) },
2324
freebsdlike: { any(dragonfly, freebsd) },
2425
netbsdlike: { any(netbsd, openbsd) },

changelog/2347.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add `mount` and `unmount` API for apple targets.

src/mount/apple.rs

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
use crate::{Errno, NixPath, Result};
2+
use libc::c_int;
3+
4+
libc_bitflags!(
5+
/// Used with [`mount()`] and [`unmount()`].
6+
pub struct MntFlags: c_int {
7+
/// Do not interpret special files on the filesystem.
8+
MNT_NODEV;
9+
/// Enable data protection on the filesystem if the filesystem is configured for it.
10+
MNT_CPROTECT;
11+
/// file system is quarantined
12+
MNT_QUARANTINE;
13+
/// filesystem is stored locally
14+
MNT_LOCAL;
15+
/// quotas are enabled on filesystem
16+
MNT_QUOTA;
17+
/// identifies the root filesystem
18+
MNT_ROOTFS;
19+
/// file system is not appropriate path to user data
20+
MNT_DONTBROWSE;
21+
/// VFS will ignore ownership information on filesystem objects
22+
MNT_IGNORE_OWNERSHIP;
23+
/// filesystem was mounted by automounter
24+
MNT_AUTOMOUNTED;
25+
/// filesystem is journaled
26+
MNT_JOURNALED;
27+
/// Don't allow user extended attributes
28+
MNT_NOUSERXATTR;
29+
/// filesystem should defer writes
30+
MNT_DEFWRITE;
31+
/// don't block unmount if not responding
32+
MNT_NOBLOCK;
33+
/// file system is exported
34+
MNT_EXPORTED;
35+
/// file system written asynchronously
36+
MNT_ASYNC;
37+
/// Force a read-write mount even if the file system appears to be
38+
/// unclean.
39+
MNT_FORCE;
40+
/// MAC support for objects.
41+
MNT_MULTILABEL;
42+
/// Do not update access times.
43+
MNT_NOATIME;
44+
/// Disallow program execution.
45+
MNT_NOEXEC;
46+
/// Do not honor setuid or setgid bits on files when executing them.
47+
MNT_NOSUID;
48+
/// Mount read-only.
49+
MNT_RDONLY;
50+
/// Causes the vfs subsystem to update its data structures pertaining to
51+
/// the specified already mounted file system.
52+
MNT_RELOAD;
53+
/// Create a snapshot of the file system.
54+
MNT_SNAPSHOT;
55+
/// All I/O to the file system should be done synchronously.
56+
MNT_SYNCHRONOUS;
57+
/// Union with underlying fs.
58+
MNT_UNION;
59+
/// Indicates that the mount command is being applied to an already
60+
/// mounted file system.
61+
MNT_UPDATE;
62+
}
63+
);
64+
65+
/// Mount a file system.
66+
///
67+
/// # Arguments
68+
/// - `source` - Specifies the file system. e.g. `/dev/sd0`.
69+
/// - `target` - Specifies the destination. e.g. `/mnt`.
70+
/// - `flags` - Optional flags controlling the mount.
71+
/// - `data` - Optional file system specific data.
72+
///
73+
/// # see also
74+
/// [`mount`](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/mount.2.html)
75+
pub fn mount<
76+
P1: ?Sized + NixPath,
77+
P2: ?Sized + NixPath,
78+
P3: ?Sized + NixPath,
79+
>(
80+
source: &P1,
81+
target: &P2,
82+
flags: MntFlags,
83+
data: Option<&P3>,
84+
) -> Result<()> {
85+
fn with_opt_nix_path<P, T, F>(p: Option<&P>, f: F) -> Result<T>
86+
where
87+
P: ?Sized + NixPath,
88+
F: FnOnce(*const libc::c_char) -> T,
89+
{
90+
match p {
91+
Some(path) => path.with_nix_path(|p_str| f(p_str.as_ptr())),
92+
None => Ok(f(std::ptr::null())),
93+
}
94+
}
95+
96+
let res = source.with_nix_path(|s| {
97+
target.with_nix_path(|t| {
98+
with_opt_nix_path(data, |d| unsafe {
99+
libc::mount(
100+
s.as_ptr(),
101+
t.as_ptr(),
102+
flags.bits(),
103+
d.cast_mut().cast(),
104+
)
105+
})
106+
})
107+
})???;
108+
109+
Errno::result(res).map(drop)
110+
}
111+
112+
/// Umount the file system mounted at `target`.
113+
pub fn unmount<P>(target: &P, flags: MntFlags) -> Result<()>
114+
where
115+
P: ?Sized + NixPath,
116+
{
117+
let res = target.with_nix_path(|cstr| unsafe {
118+
libc::unmount(cstr.as_ptr(), flags.bits())
119+
})?;
120+
121+
Errno::result(res).map(drop)
122+
}

src/mount/bsd.rs renamed to src/mount/bsd_without_apple.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ libc_bitflags!(
3030
#[cfg(target_os = "freebsd")]
3131
MNT_GJOURNAL;
3232
/// MAC support for objects.
33-
#[cfg(any(apple_targets, target_os = "freebsd"))]
33+
#[cfg(target_os = "freebsd")]
3434
MNT_MULTILABEL;
3535
/// Disable read clustering.
3636
#[cfg(freebsdlike)]
@@ -58,7 +58,7 @@ libc_bitflags!(
5858
/// Create a snapshot of the file system.
5959
///
6060
/// See [mksnap_ffs(8)](https://www.freebsd.org/cgi/man.cgi?query=mksnap_ffs)
61-
#[cfg(any(apple_targets, target_os = "freebsd"))]
61+
#[cfg(target_os = "freebsd")]
6262
MNT_SNAPSHOT;
6363
/// Using soft updates.
6464
#[cfg(any(freebsdlike, netbsdlike))]
@@ -71,7 +71,6 @@ libc_bitflags!(
7171
MNT_SYNCHRONOUS;
7272
/// Union with underlying fs.
7373
#[cfg(any(
74-
apple_targets,
7574
target_os = "freebsd",
7675
target_os = "netbsd"
7776
))]

src/mount/mod.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,14 @@ mod linux;
55
#[cfg(linux_android)]
66
pub use self::linux::*;
77

8-
#[cfg(bsd)]
9-
mod bsd;
8+
#[cfg(bsd_without_apple)]
9+
mod bsd_without_apple;
1010

11-
#[cfg(bsd)]
12-
pub use self::bsd::*;
11+
#[cfg(bsd_without_apple)]
12+
pub use self::bsd_without_apple::*;
13+
14+
#[cfg(apple_targets)]
15+
mod apple;
16+
17+
#[cfg(apple_targets)]
18+
pub use self::apple::*;

test/mount/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#[cfg(target_os = "linux")]
2+
mod test_mount;
3+
#[cfg(apple_targets)]
4+
mod test_mount_apple;
5+
#[cfg(target_os = "freebsd")]
6+
mod test_nmount;
File renamed without changes.

test/mount/test_mount_apple.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
use nix::errno::Errno;
2+
use nix::mount::{mount, MntFlags};
3+
4+
#[test]
5+
fn test_mount() {
6+
let res = mount::<str, str, str>("", "", MntFlags::empty(), None);
7+
assert_eq!(res, Err(Errno::ENOENT));
8+
}
File renamed without changes.

test/test.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@ extern crate cfg_if;
44
extern crate nix;
55

66
mod common;
7+
mod mount;
78
mod sys;
89
#[cfg(not(target_os = "redox"))]
910
mod test_dir;
1011
mod test_errno;
1112
mod test_fcntl;
1213
#[cfg(linux_android)]
1314
mod test_kmod;
14-
#[cfg(target_os = "linux")]
15-
mod test_mount;
1615
#[cfg(any(
1716
freebsdlike,
1817
target_os = "fushsia",
@@ -23,8 +22,6 @@ mod test_mq;
2322
#[cfg(not(target_os = "redox"))]
2423
mod test_net;
2524
mod test_nix_path;
26-
#[cfg(target_os = "freebsd")]
27-
mod test_nmount;
2825
mod test_poll;
2926
#[cfg(not(any(
3027
target_os = "redox",

0 commit comments

Comments
 (0)