diff options
Diffstat (limited to 'src/unistd.rs')
-rw-r--r-- | src/unistd.rs | 86 |
1 files changed, 64 insertions, 22 deletions
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) + }) + } } } } |