extern crate libc;
use std::ffi::{CString};
#[repr(C)]
#[allow(dead_code)]
struct passwd {
pw_name: *const libc::c_char,
pw_passwd: *const libc::c_char,
pw_uid: libc::uid_t,
pw_gid: libc::gid_t,
pw_gecos: *const libc::c_char,
pw_dir: *const libc::c_char,
pw_shell: *const libc::c_char,
}
#[repr(C)]
#[allow(dead_code)]
struct group {
gr_name: *const libc::c_char,
gr_passwd: *const libc::c_char,
gr_gid: libc::gid_t,
gr_mem: *const *const libc::c_char,
}
extern {
fn getgrnam(name: *const libc::c_char) -> *const group;
fn getpwnam(name: *const libc::c_char) -> *const passwd;
pub fn umask(mask: libc::mode_t) -> libc::mode_t;
pub fn flock(fd: libc::c_int, operation: libc::c_int) -> libc::c_int;
}
#[cfg(target_os = "linux")]
unsafe fn errno_location() -> *const libc::c_int {
extern { fn __errno_location() -> *const libc::c_int; }
__errno_location()
}
#[cfg(target_os = "macos")]
unsafe fn errno_location() -> *const libc::c_int {
extern { fn __error() -> *const libc::c_int; }
__error()
}
pub unsafe fn errno() -> libc::c_int {
*errno_location()
}
pub unsafe fn get_gid_by_name(name: &CString) -> Option<libc::gid_t> {
let ptr = getgrnam(name.as_ptr() as *const libc::c_char);
if ptr.is_null() {
None
} else {
let ref s = *ptr;
Some(s.gr_gid)
}
}
pub unsafe fn get_uid_by_name(name: &CString) -> Option<libc::uid_t> {
let ptr = getpwnam(name.as_ptr() as *const libc::c_char);
if ptr.is_null() {
None
} else {
let ref s = *ptr;
Some(s.pw_uid)
}
}
#[cfg(target_os = "linux")]
#[allow(dead_code)]
unsafe fn nobody_uid_gid() -> libc::uid_t {
(u16::max_value() - 1) as libc::uid_t
}
#[cfg(target_os = "macos")]
#[allow(dead_code)]
unsafe fn nobody_uid_gid() -> libc::uid_t {
(u32::max_value() - 1) as libc::uid_t
}
#[test]
fn test_get_gid_by_name() {
let group_name = ::std::ffi::CString::new(match ::std::fs::metadata("/etc/debian_version") {
Ok(_) => "nogroup",
Err(_) => "nobody",
}).unwrap();
unsafe {
let gid = get_gid_by_name(&group_name);
assert_eq!(gid, Some(nobody_uid_gid()))
}
}
#[test]
fn test_get_uid_by_name() {
let user_name = ::std::ffi::CString::new("nobody").unwrap();
unsafe {
let uid = get_uid_by_name(&user_name);
assert_eq!(uid, Some(nobody_uid_gid()))
}
}