summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml2
-rw-r--r--src/mount/linux.rs50
-rw-r--r--src/net/if_.rs2
-rw-r--r--src/unistd.rs86
4 files changed, 116 insertions, 24 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 18eae535..960d4f61 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -34,7 +34,7 @@ pin-utils = { version = "0.1.0", optional = true }
static_assertions = "1"
[target.'cfg(not(target_os = "redox"))'.dependencies]
-memoffset = { version = "0.7", optional = true }
+memoffset = { version = "0.8", optional = true }
[features]
default = [
diff --git a/src/mount/linux.rs b/src/mount/linux.rs
index cf6a60b0..5f19a5f1 100644
--- a/src/mount/linux.rs
+++ b/src/mount/linux.rs
@@ -1,9 +1,9 @@
-#![allow(missing_docs)]
use crate::errno::Errno;
use crate::{NixPath, Result};
use libc::{self, c_int, c_ulong};
libc_bitflags!(
+ /// Used with [`mount`].
pub struct MsFlags: c_ulong {
/// Mount read-only
MS_RDONLY;
@@ -27,36 +27,80 @@ libc_bitflags!(
MS_NODIRATIME;
/// Linux 2.4.0 - Bind directory at different place
MS_BIND;
+ /// Move an existing mount to a new location
MS_MOVE;
+ /// Used to create a recursive bind mount.
MS_REC;
+ /// Suppress the display of certain kernel warning messages.
MS_SILENT;
+ /// VFS does not apply the umask
MS_POSIXACL;
+ /// The resulting mount cannot subsequently be bind mounted.
MS_UNBINDABLE;
+ /// Make this mount point private.
MS_PRIVATE;
+ /// If this is a shared mount point that is a member of a peer group
+ /// that contains other members, convert it to a slave mount.
MS_SLAVE;
+ /// Make this mount point shared.
MS_SHARED;
+ /// When a file on this filesystem is accessed, update the file's
+ /// last access time (atime) only if the current value of atime is
+ /// less than or equal to the file's last modification time (mtime) or
+ /// last status change time (ctime).
MS_RELATIME;
+ /// Mount request came from within the kernel
+ #[deprecated(since = "0.27.0", note = "Should only be used in-kernel")]
MS_KERNMOUNT;
+ /// Update inode I_version field
MS_I_VERSION;
+ /// Always update the last access time (atime) when files on this
+ /// filesystem are accessed.
MS_STRICTATIME;
+ /// Reduce on-disk updates of inode timestamps (atime, mtime, ctime) by
+ /// maintaining these changes only in memory.
MS_LAZYTIME;
+ #[deprecated(since = "0.27.0", note = "Should only be used in-kernel")]
+ #[allow(missing_docs)] // Not documented in Linux
MS_ACTIVE;
+ #[deprecated(since = "0.27.0", note = "Should only be used in-kernel")]
+ #[allow(missing_docs)] // Not documented in Linux
MS_NOUSER;
+ #[allow(missing_docs)] // Not documented in Linux; possibly kernel-only
MS_RMT_MASK;
+ #[allow(missing_docs)] // Not documented in Linux; possibly kernel-only
MS_MGC_VAL;
+ #[allow(missing_docs)] // Not documented in Linux; possibly kernel-only
MS_MGC_MSK;
}
);
libc_bitflags!(
+ /// Used with [`umount2].
pub struct MntFlags: c_int {
+ /// Attempt to unmount even if still in use, aborting pending requests.
MNT_FORCE;
+ /// Lazy unmount. Disconnect the file system immediately, but don't
+ /// actually unmount it until it ceases to be busy.
MNT_DETACH;
+ /// Mark the mount point as expired.
MNT_EXPIRE;
+ /// Don't dereference `target` if it is a symlink.
UMOUNT_NOFOLLOW;
}
);
+/// Mount a file system.
+///
+/// # Arguments
+/// - `source` - Specifies the file system. e.g. `/dev/sd0`.
+/// - `target` - Specifies the destination. e.g. `/mnt`.
+/// - `fstype` - The file system type, e.g. `ext4`.
+/// - `flags` - Optional flags controlling the mount.
+/// - `data` - Optional file system specific data.
+///
+/// # See Also
+/// [`mount`](https://man7.org/linux/man-pages/man2/mount.2.html)
pub fn mount<
P1: ?Sized + NixPath,
P2: ?Sized + NixPath,
@@ -99,6 +143,7 @@ pub fn mount<
Errno::result(res).map(drop)
}
+/// Unmount the file system mounted at `target`.
pub fn umount<P: ?Sized + NixPath>(target: &P) -> Result<()> {
let res =
target.with_nix_path(|cstr| unsafe { libc::umount(cstr.as_ptr()) })?;
@@ -106,6 +151,9 @@ pub fn umount<P: ?Sized + NixPath>(target: &P) -> Result<()> {
Errno::result(res).map(drop)
}
+/// Unmount the file system mounted at `target`.
+///
+/// See also [`umount`](https://man7.org/linux/man-pages/man2/umount.2.html)
pub fn umount2<P: ?Sized + NixPath>(target: &P, flags: MntFlags) -> Result<()> {
let res = target.with_nix_path(|cstr| unsafe {
libc::umount2(cstr.as_ptr(), flags.bits)
diff --git a/src/net/if_.rs b/src/net/if_.rs
index b2423bc6..ec462607 100644
--- a/src/net/if_.rs
+++ b/src/net/if_.rs
@@ -334,6 +334,7 @@ libc_bitflags!(
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd",
+ target_os = "illumos",
))]
#[cfg_attr(docsrs, doc(cfg(all())))]
mod if_nameindex {
@@ -465,5 +466,6 @@ mod if_nameindex {
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd",
+ target_os = "illumos",
))]
pub use if_nameindex::*;
diff --git a/src/unistd.rs b/src/unistd.rs
index 8cad67f4..a10c17b5 100644
--- a/src/unistd.rs
+++ b/src/unistd.rs
@@ -1652,8 +1652,8 @@ pub fn setgroups(groups: &[Gid]) -> Result<()> {
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
- target_os = "illumos",
- target_os = "openbsd"))] {
+ target_os = "openbsd",
+ target_os = "solaris"))] {
type setgroups_ngroups_t = c_int;
} else {
type setgroups_ngroups_t = size_t;
@@ -3631,7 +3631,12 @@ impl From<User> for libc::passwd {
#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
impl User {
- fn from_anything<F>(f: F) -> Result<Option<Self>>
+ /// # Safety
+ ///
+ /// If `f` writes to its `*mut *mut libc::passwd` parameter, then it must
+ /// also initialize the value pointed to by its `*mut libc::group`
+ /// parameter.
+ unsafe fn from_anything<F>(f: F) -> Result<Option<Self>>
where
F: Fn(
*mut libc::passwd,
@@ -3661,7 +3666,9 @@ impl User {
if res.is_null() {
return Ok(None);
} else {
- let pwd = unsafe { pwd.assume_init() };
+ // SAFETY: `f` guarantees that `pwd` is initialized if `res`
+ // is not null.
+ let pwd = pwd.assume_init();
return Ok(Some(User::from(&pwd)));
}
} else if Errno::last() == Errno::ERANGE {
@@ -3687,9 +3694,13 @@ impl User {
/// assert_eq!(res.name, "root");
/// ```
pub fn from_uid(uid: Uid) -> Result<Option<Self>> {
- User::from_anything(|pwd, cbuf, cap, res| unsafe {
- libc::getpwuid_r(uid.0, pwd, cbuf, cap, res)
- })
+ // SAFETY: `getpwuid_r` will write to `res` if it initializes the value
+ // at `pwd`.
+ unsafe {
+ User::from_anything(|pwd, cbuf, cap, res| {
+ libc::getpwuid_r(uid.0, pwd, cbuf, cap, res)
+ })
+ }
}
/// Get a user by name.
@@ -3710,9 +3721,13 @@ impl User {
Ok(c_str) => c_str,
Err(_nul_error) => return Ok(None),
};
- User::from_anything(|pwd, cbuf, cap, res| unsafe {
- libc::getpwnam_r(name.as_ptr(), pwd, cbuf, cap, res)
- })
+ // SAFETY: `getpwnam_r` will write to `res` if it initializes the value
+ // at `pwd`.
+ unsafe {
+ User::from_anything(|pwd, cbuf, cap, res| {
+ libc::getpwnam_r(name.as_ptr(), pwd, cbuf, cap, res)
+ })
+ }
}
}
@@ -3735,11 +3750,23 @@ impl From<&libc::group> for Group {
fn from(gr: &libc::group) -> Group {
unsafe {
Group {
- name: CStr::from_ptr(gr.gr_name).to_string_lossy().into_owned(),
- passwd: CString::new(CStr::from_ptr(gr.gr_passwd).to_bytes())
- .unwrap(),
+ name: if gr.gr_name.is_null() {
+ Default::default()
+ } else {
+ CStr::from_ptr(gr.gr_name).to_string_lossy().into_owned()
+ },
+ passwd: if gr.gr_passwd.is_null() {
+ Default::default()
+ } else {
+ CString::new(CStr::from_ptr(gr.gr_passwd).to_bytes())
+ .unwrap()
+ },
gid: Gid::from_raw(gr.gr_gid),
- mem: Group::members(gr.gr_mem),
+ mem: if gr.gr_mem.is_null() {
+ Default::default()
+ } else {
+ Group::members(gr.gr_mem)
+ },
}
}
}
@@ -3763,7 +3790,12 @@ impl Group {
ret
}
- fn from_anything<F>(f: F) -> Result<Option<Self>>
+ /// # Safety
+ ///
+ /// If `f` writes to its `*mut *mut libc::group` parameter, then it must
+ /// also initialize the value pointed to by its `*mut libc::group`
+ /// parameter.
+ unsafe fn from_anything<F>(f: F) -> Result<Option<Self>>
where
F: Fn(
*mut libc::group,
@@ -3793,7 +3825,9 @@ impl Group {
if res.is_null() {
return Ok(None);
} else {
- let grp = unsafe { grp.assume_init() };
+ // SAFETY: `f` guarantees that `grp` is initialized if `res`
+ // is not null.
+ let grp = grp.assume_init();
return Ok(Some(Group::from(&grp)));
}
} else if Errno::last() == Errno::ERANGE {
@@ -3821,9 +3855,13 @@ impl Group {
/// assert!(res.name == "root");
/// ```
pub fn from_gid(gid: Gid) -> Result<Option<Self>> {
- Group::from_anything(|grp, cbuf, cap, res| unsafe {
- libc::getgrgid_r(gid.0, grp, cbuf, cap, res)
- })
+ // SAFETY: `getgrgid_r` will write to `res` if it initializes the value
+ // at `grp`.
+ unsafe {
+ Group::from_anything(|grp, cbuf, cap, res| {
+ libc::getgrgid_r(gid.0, grp, cbuf, cap, res)
+ })
+ }
}
/// Get a group by name.
@@ -3846,9 +3884,13 @@ impl Group {
Ok(c_str) => c_str,
Err(_nul_error) => return Ok(None),
};
- Group::from_anything(|grp, cbuf, cap, res| unsafe {
- libc::getgrnam_r(name.as_ptr(), grp, cbuf, cap, res)
- })
+ // SAFETY: `getgrnam_r` will write to `res` if it initializes the value
+ // at `grp`.
+ unsafe {
+ Group::from_anything(|grp, cbuf, cap, res| {
+ libc::getgrnam_r(name.as_ptr(), grp, cbuf, cap, res)
+ })
+ }
}
}
}