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
54
55
56
57
58
59
60
61
62
63
// Copyright (c) 2021 Xu Shaohua <shaohua@biofan.org>. All rights reserved.
// Use of this source is governed by Apache-2.0 License that can be found
// in the LICENSE file.

use crate::core::{grp, pwd};
use crate::error::{Error, ErrorKind};

#[derive(Debug, Clone)]
pub struct Id {
    name: String,
    uid: nc::uid_t,

    group_name: String,
    gid: nc::gid_t,

    groups: Vec<(String, nc::gid_t)>,
}

/// Get real and effective user nad group IDs.
pub fn id(uid: nc::uid_t) -> Result<Id, Error> {
    let passwd = pwd::getpwuid(uid)?;
    match passwd {
        None => Err(Error::from_string(
            ErrorKind::PwdError,
            format!("Invalid uid: {}", uid),
        )),
        Some(passwd) => {
            let group_iter = grp::getgrent()?;
            let mut groups = Vec::new();
            let mut group_name = String::new();
            for g in group_iter {
                if g.mem.contains(&passwd.name) {
                    groups.push((g.name, g.gid));
                } else if g.gid == passwd.gid {
                    groups.push((g.name.clone(), g.gid));
                    group_name = g.name;
                }
            }
            return Ok(Id {
                name: passwd.name,
                uid: passwd.uid,
                group_name,
                gid: passwd.gid,
                groups,
            });
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_id() {
        let root_id = 0;
        let ret = id(root_id);
        assert!(ret.is_ok());
        let id = ret.unwrap();
        assert_eq!(id.uid, 0);
        assert_eq!(id.gid, 0);
    }
}