1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// Take a look at the license at the top of the repository in the LICENSE file.

#[cfg(not(any(target_os = "macos", target_os = "ios")))]
use crate::Group;

impl crate::GroupInner {
    pub(crate) fn new(id: crate::Gid, name: String) -> Self {
        Self { id, name }
    }

    pub(crate) fn id(&self) -> &crate::Gid {
        &self.id
    }

    pub(crate) fn name(&self) -> &str {
        &self.name
    }
}

// Not used by mac.
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
pub(crate) fn get_groups(groups: &mut Vec<Group>) {
    use crate::common::{Gid, GroupInner};
    use std::fs::File;
    use std::io::Read;

    #[inline]
    fn parse_id(id: &str) -> Option<u32> {
        id.parse::<u32>().ok()
    }

    groups.clear();

    let mut s = String::new();

    let _ = File::open("/etc/group").and_then(|mut f| f.read_to_string(&mut s));

    for line in s.lines() {
        let mut parts = line.split(':');
        if let Some(name) = parts.next() {
            let mut parts = parts.skip(1);
            // Skip the user if the uid cannot be parsed correctly
            if let Some(gid) = parts.next().and_then(parse_id) {
                groups.push(Group {
                    inner: GroupInner::new(Gid(gid), name.to_owned()),
                });
            }
        }
    }
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
pub(crate) use crate::unix::apple::groups::get_groups;