diff --git a/build.rs b/build.rs index ecadc04f5d..fd19de0fe9 100644 --- a/build.rs +++ b/build.rs @@ -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) }, diff --git a/changelog/2347.added.md b/changelog/2347.added.md new file mode 100644 index 0000000000..9000d61deb --- /dev/null +++ b/changelog/2347.added.md @@ -0,0 +1 @@ +Add `mount` and `unmount` API for apple targets. diff --git a/src/mount/apple.rs b/src/mount/apple.rs new file mode 100644 index 0000000000..6759ed20bb --- /dev/null +++ b/src/mount/apple.rs @@ -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: Option<&P>, f: F) -> Result (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)
+}
diff --git a/src/mount/bsd.rs b/src/mount/bsd_without_apple.rs
similarity index 98%
rename from src/mount/bsd.rs
rename to src/mount/bsd_without_apple.rs
index 248e0ab1d2..ae9eed7c0e 100644
--- a/src/mount/bsd.rs
+++ b/src/mount/bsd_without_apple.rs
@@ -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)]
@@ -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))]
@@ -71,7 +71,6 @@ libc_bitflags!(
MNT_SYNCHRONOUS;
/// Union with underlying fs.
#[cfg(any(
- apple_targets,
target_os = "freebsd",
target_os = "netbsd"
))]
diff --git a/src/mount/mod.rs b/src/mount/mod.rs
index 8caf27f7df..41e7b3ec6d 100644
--- a/src/mount/mod.rs
+++ b/src/mount/mod.rs
@@ -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::*;
diff --git a/test/mount/mod.rs b/test/mount/mod.rs
new file mode 100644
index 0000000000..2764b83f71
--- /dev/null
+++ b/test/mount/mod.rs
@@ -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;
diff --git a/test/test_mount.rs b/test/mount/test_mount.rs
similarity index 100%
rename from test/test_mount.rs
rename to test/mount/test_mount.rs
diff --git a/test/mount/test_mount_apple.rs b/test/mount/test_mount_apple.rs
new file mode 100644
index 0000000000..f2868500d0
--- /dev/null
+++ b/test/mount/test_mount_apple.rs
@@ -0,0 +1,8 @@
+use nix::errno::Errno;
+use nix::mount::{mount, MntFlags};
+
+#[test]
+fn test_mount() {
+ let res = mount::