diff options
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | src/mount/linux.rs | 50 | ||||
-rw-r--r-- | src/net/if_.rs | 2 | ||||
-rw-r--r-- | src/unistd.rs | 86 |
4 files changed, 116 insertions, 24 deletions
@@ -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) + }) + } } } } |