Skip to content

Commit a154b26

Browse files
committed
unistd: Add setgroups()
1 parent 7fff6d5 commit a154b26

File tree

1 file changed

+46
-1
lines changed

1 file changed

+46
-1
lines changed

src/unistd.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ pub fn mkdir<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
464464
/// fn main() {
465465
/// let tmp_dir = TempDir::new("test_fifo").unwrap();
466466
/// let fifo_path = tmp_dir.path().join("foo.pipe");
467-
///
467+
///
468468
/// // create new fifo and give read, write and execute rights to the owner
469469
/// match unistd::mkfifo(&fifo_path, stat::S_IRWXU) {
470470
/// Ok(_) => println!("created {:?}", fifo_path),
@@ -1047,6 +1047,51 @@ pub fn setgid(gid: Gid) -> Result<()> {
10471047
Errno::result(res).map(drop)
10481048
}
10491049

1050+
/// Set the list of supplementary group IDs for the calling process.
1051+
///
1052+
/// *Note:* On macOS, `getgroups()` may not return the same group list set by
1053+
/// calling `setgroups()`. The use of `setgroups()` on macOS is 'highly
1054+
/// discouraged' by Apple. Developers are referred to the `opendirectoryd`
1055+
/// daemon and its set of APIs.
1056+
///
1057+
/// [Further reading](http://man7.org/linux/man-pages/man2/getgroups.2.html)
1058+
///
1059+
/// # Examples
1060+
///
1061+
/// `setgroups` can be used when dropping privileges from the root user to a
1062+
/// specific user and group. For example, given the user `www-data` with UID
1063+
/// `33` and the group `backup` with the GID `34`, one could switch user as
1064+
/// follows:
1065+
/// ```
1066+
/// let uid = Uid::from_raw(33);
1067+
/// let gid = Gid::from_raw(34);
1068+
/// setgroups(&[gid])?;
1069+
/// setgid(gid)?;
1070+
/// setuid(uid)?;
1071+
/// ```
1072+
pub fn setgroups(groups: &[Gid]) -> Result<()> {
1073+
cfg_if! {
1074+
if #[cfg(any(target_os = "dragonfly",
1075+
target_os = "freebsd",
1076+
target_os = "ios",
1077+
target_os = "macos",
1078+
target_os = "netbsd",
1079+
target_os = "openbsd"))] {
1080+
type setgroups_ngroups_t = c_int;
1081+
} else {
1082+
type setgroups_ngroups_t = size_t;
1083+
}
1084+
}
1085+
// FIXME: On the platforms we currently support, the `Gid` struct has the
1086+
// same representation in memory as a bare `gid_t`. This is not necessarily
1087+
// the case on all Rust platforms, though. See RFC 1785.
1088+
let res = unsafe {
1089+
libc::setgroups(groups.len() as setgroups_ngroups_t, groups.as_ptr() as *const gid_t)
1090+
};
1091+
1092+
Errno::result(res).map(|_| ())
1093+
}
1094+
10501095
/// Suspend the thread until a signal is received
10511096
///
10521097
/// See also [pause(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pause.html)

0 commit comments

Comments
 (0)