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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
extern crate libc;
use std::ffi::CString;
use std::ffi::CStr;
#[derive(Debug)]
pub struct Passwd {
pub name: String,
pub password: String,
pub uid: libc::uid_t,
pub gid: libc::gid_t,
pub gecos: String,
pub home_dir: String,
pub shell: String,
}
impl Passwd {
unsafe fn from_ptr(pwd: *const libc::passwd) -> Passwd {
Passwd {
name: CStr::from_ptr((*pwd).pw_name).to_str().unwrap().to_owned(),
password: CStr::from_ptr((*pwd).pw_passwd).to_str().unwrap().to_owned(),
uid: (*pwd).pw_uid,
gid: (*pwd).pw_gid,
gecos: CStr::from_ptr((*pwd).pw_gecos).to_str().unwrap().to_owned(),
home_dir: CStr::from_ptr((*pwd).pw_dir).to_str().unwrap().to_owned(),
shell: CStr::from_ptr((*pwd).pw_shell).to_str().unwrap().to_owned(),
}
}
pub fn from_name(user: &str) -> Option<Passwd> {
let c_user = CString::new(user).unwrap();
let mut pwd: libc::passwd = unsafe { std::mem::zeroed() };
let mut buf = Vec::with_capacity(getpw_r_size_max());
let mut result = std::ptr::null_mut();
unsafe {
libc::getpwnam_r(c_user.as_ptr(),
&mut pwd,
buf.as_mut_ptr(),
buf.capacity(),
&mut result);
}
if result.is_null() {
None
} else {
Some(unsafe { Passwd::from_ptr(result) })
}
}
pub fn from_uid(uid: libc::uid_t) -> Option<Passwd> {
let mut pwd: libc::passwd = unsafe { std::mem::zeroed() };
let mut buf = Vec::with_capacity(getpw_r_size_max());
let mut result = std::ptr::null_mut();
unsafe {
libc::getpwuid_r(uid, &mut pwd, buf.as_mut_ptr(), buf.capacity(), &mut result);
}
if result.is_null() {
None
} else {
Some(unsafe { Passwd::from_ptr(result) })
}
}
}
fn getpw_r_size_max() -> usize {
match unsafe { libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) } {
n if n < 0 => 512 as usize,
n => n as usize,
}
}