diff --git a/examples/example.rs b/examples/example.rs index 204122a..069d0ef 100644 --- a/examples/example.rs +++ b/examples/example.rs @@ -1,5 +1,5 @@ extern crate users; -use users::{Users, OSUsers}; +use users::{Users, Groups, OSUsers}; fn main() { let cache = OSUsers::empty_cache(); diff --git a/src/lib.rs b/src/lib.rs index e7a558b..92a6875 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,7 +64,7 @@ //! methods on it. For example: //! //! ```rust -//! use users::{Users, OSUsers}; +//! use users::{Users, Groups, OSUsers}; //! let mut cache = OSUsers::empty_cache(); //! let uid = cache.get_current_uid(); //! let user = cache.get_user_by_uid(uid).unwrap(); @@ -89,7 +89,7 @@ //! And again, a complete example: //! //! ```rust -//! use users::{Users, OSUsers}; +//! use users::{Users, Groups, OSUsers}; //! let mut cache = OSUsers::empty_cache(); //! let group = cache.get_group_by_name("admin").expect("No such group 'admin'!"); //! println!("The '{}' group has the ID {}", group.name, group.gid); @@ -127,43 +127,47 @@ pub mod mock; pub mod os; pub use os::OSUsers; -/// The trait for the `OSUsers` object. +/// Trait for producers of users. pub trait Users { - /// Return a User object if one exists for the given user ID; otherwise, return None. + /// Returns a User if one exists for the given user ID; otherwise, returns None. fn get_user_by_uid(&self, uid: uid_t) -> Option>; - /// Return a User object if one exists for the given username; otherwise, return None. + /// Returns a User if one exists for the given username; otherwise, returns None. fn get_user_by_name(&self, username: &str) -> Option>; - /// Return a Group object if one exists for the given group ID; otherwise, return None. - fn get_group_by_gid(&self, gid: gid_t) -> Option>; - - /// Return a Group object if one exists for the given groupname; otherwise, return None. - fn get_group_by_name(&self, group_name: &str) -> Option>; - - /// Return the user ID for the user running the process. + /// Returns the user ID for the user running the process. fn get_current_uid(&self) -> uid_t; - /// Return the username of the user running the process. + /// Returns the username of the user running the process. fn get_current_username(&self) -> Option>; - /// Return the group ID for the user running the process. - fn get_current_gid(&self) -> gid_t; - - /// Return the group name of the user running the process. - fn get_current_groupname(&self) -> Option>; - - /// Return the effective user id. + /// Returns the effective user id. fn get_effective_uid(&self) -> uid_t; - /// Return the effective group id. + /// Returns the effective username. + fn get_effective_username(&self) -> Option>; +} + +/// Trait for producers of groups. +pub trait Groups { + + /// Returns a Group object if one exists for the given group ID; otherwise, returns None. + fn get_group_by_gid(&self, gid: gid_t) -> Option>; + + /// Returns a Group object if one exists for the given groupname; otherwise, returns None. + fn get_group_by_name(&self, group_name: &str) -> Option>; + + /// Returns the group ID for the user running the process. + fn get_current_gid(&self) -> gid_t; + + /// Returns the group name of the user running the process. + fn get_current_groupname(&self) -> Option>; + + /// Returns the effective group id. fn get_effective_gid(&self) -> gid_t; - /// Return the effective username. - fn get_effective_username(&self) -> Option>; - - /// Return the effective group name. + /// Returns the effective group name. fn get_effective_groupname(&self) -> Option>; } @@ -225,8 +229,8 @@ extern { fn setregid(rgid: gid_t, egid: gid_t) -> c_int; } -#[derive(Clone)] /// Information about a particular user. +#[derive(Clone)] pub struct User { /// This user's ID @@ -312,12 +316,12 @@ unsafe fn members(groups: *const *const c_char) -> Vec { } -/// Return a User object if one exists for the given user ID; otherwise, return None. +/// Returns a User object if one exists for the given user ID; otherwise, return None. pub fn get_user_by_uid(uid: uid_t) -> Option { unsafe { passwd_to_user(getpwuid(uid)) } } -/// Return a User object if one exists for the given username; otherwise, return None. +/// Returns a User object if one exists for the given username; otherwise, return None. pub fn get_user_by_name(username: &str) -> Option { let username_c = CString::new(username); @@ -330,12 +334,12 @@ pub fn get_user_by_name(username: &str) -> Option { unsafe { passwd_to_user(getpwnam(username_c.unwrap().as_ptr())) } } -/// Return a Group object if one exists for the given group ID; otherwise, return None. +/// Returns a Group object if one exists for the given group ID; otherwise, return None. pub fn get_group_by_gid(gid: gid_t) -> Option { unsafe { struct_to_group(getgrgid(gid)) } } -/// Return a Group object if one exists for the given groupname; otherwise, return None. +/// Returns a Group object if one exists for the given groupname; otherwise, return None. pub fn get_group_by_name(group_name: &str) -> Option { let group_name_c = CString::new(group_name); @@ -348,51 +352,51 @@ pub fn get_group_by_name(group_name: &str) -> Option { unsafe { struct_to_group(getgrnam(group_name_c.unwrap().as_ptr())) } } -/// Return the user ID for the user running the process. +/// Returns the user ID for the user running the process. pub fn get_current_uid() -> uid_t { unsafe { getuid() } } -/// Return the username of the user running the process. +/// Returns the username of the user running the process. pub fn get_current_username() -> Option { let uid = get_current_uid(); get_user_by_uid(uid).map(|u| Arc::try_unwrap(u.name).unwrap()) } -/// Return the user ID for the effective user running the process. +/// Returns the user ID for the effective user running the process. pub fn get_effective_uid() -> uid_t { unsafe { geteuid() } } -/// Return the username of the effective user running the process. +/// Returns the username of the effective user running the process. pub fn get_effective_username() -> Option { let uid = get_effective_uid(); get_user_by_uid(uid).map(|u| Arc::try_unwrap(u.name).unwrap()) } -/// Return the group ID for the user running the process. +/// Returns the group ID for the user running the process. pub fn get_current_gid() -> gid_t { unsafe { getgid() } } -/// Return the groupname of the user running the process. +/// Returns the groupname of the user running the process. pub fn get_current_groupname() -> Option { let gid = get_current_gid(); get_group_by_gid(gid).map(|g| Arc::try_unwrap(g.name).unwrap()) } -/// Return the group ID for the effective user running the process. +/// Returns the group ID for the effective user running the process. pub fn get_effective_gid() -> gid_t { unsafe { getegid() } } -/// Return the groupname of the effective user running the process. +/// Returns the groupname of the effective user running the process. pub fn get_effective_groupname() -> Option { let gid = get_effective_gid(); get_group_by_gid(gid).map(|g| Arc::try_unwrap(g.name).unwrap()) } -/// Set current user for the running process, requires root priviledges. +/// Sets current user for the running process, requires root priviledges. pub fn set_current_uid(uid: uid_t) -> IOResult<()> { match unsafe { setuid(uid) } { 0 => Ok(()), diff --git a/src/mock.rs b/src/mock.rs index a5c613f..5480b02 100644 --- a/src/mock.rs +++ b/src/mock.rs @@ -53,7 +53,7 @@ //! print_current_username(&mut actual_users); //! ``` -pub use super::{Users, User, Group}; +pub use super::{Users, Groups, User, Group}; use std::collections::HashMap; use std::sync::Arc; use libc::{uid_t, gid_t}; @@ -96,14 +96,6 @@ impl Users for MockUsers { self.users.values().find(|u| &*u.name == username).cloned() } - fn get_group_by_gid(&self, gid: gid_t) -> Option> { - self.groups.get(&gid).cloned() - } - - fn get_group_by_name(&self, group_name: &str) -> Option> { - self.groups.values().find(|g| &*g.name == group_name).cloned() - } - fn get_current_uid(&self) -> uid_t { self.uid } @@ -112,14 +104,6 @@ impl Users for MockUsers { self.users.get(&self.uid).map(|u| u.name.clone()) } - fn get_current_gid(&self) -> uid_t { - self.uid - } - - fn get_current_groupname(&self) -> Option> { - self.groups.get(&self.uid).map(|u| u.name.clone()) - } - fn get_effective_uid(&self) -> uid_t { self.uid } @@ -127,6 +111,24 @@ impl Users for MockUsers { fn get_effective_username(&self) -> Option> { self.users.get(&self.uid).map(|u| u.name.clone()) } +} + +impl Groups for MockUsers { + fn get_group_by_gid(&self, gid: gid_t) -> Option> { + self.groups.get(&gid).cloned() + } + + fn get_group_by_name(&self, group_name: &str) -> Option> { + self.groups.values().find(|g| &*g.name == group_name).cloned() + } + + fn get_current_gid(&self) -> uid_t { + self.uid + } + + fn get_current_groupname(&self) -> Option> { + self.groups.get(&self.uid).map(|u| u.name.clone()) + } fn get_effective_gid(&self) -> uid_t { self.uid @@ -139,7 +141,7 @@ impl Users for MockUsers { #[cfg(test)] mod test { - use super::{Users, User, Group, MockUsers}; + use super::{Users, Groups, User, Group, MockUsers}; use std::sync::Arc; #[test] diff --git a/src/os.rs b/src/os.rs index 707fff9..5185ef0 100644 --- a/src/os.rs +++ b/src/os.rs @@ -68,7 +68,7 @@ use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::collections::HashMap; use std::sync::Arc; -use super::{User, Group, Users}; +use super::{User, Groups, Group, Users}; /// A producer of user and group instances that caches every result. @@ -174,6 +174,40 @@ impl Users for OSUsers { } } + fn get_current_uid(&self) -> uid_t { + match self.uid.get() { + Some(uid) => uid, + None => { + let uid = super::get_current_uid(); + self.uid.set(Some(uid)); + uid + } + } + } + + fn get_current_username(&self) -> Option> { + let uid = self.get_current_uid(); + self.get_user_by_uid(uid).map(|u| u.name.clone()) + } + + fn get_effective_uid(&self) -> uid_t { + match self.euid.get() { + Some(uid) => uid, + None => { + let uid = super::get_effective_uid(); + self.euid.set(Some(uid)); + uid + } + } + } + + fn get_effective_username(&self) -> Option> { + let uid = self.get_effective_uid(); + self.get_user_by_uid(uid).map(|u| u.name.clone()) + } +} + +impl Groups for OSUsers { fn get_group_by_gid(&self, gid: gid_t) -> Option> { let mut groups_forward = self.groups.forward.borrow_mut(); @@ -235,22 +269,6 @@ impl Users for OSUsers { } } - fn get_current_uid(&self) -> uid_t { - match self.uid.get() { - Some(uid) => uid, - None => { - let uid = super::get_current_uid(); - self.uid.set(Some(uid)); - uid - } - } - } - - fn get_current_username(&self) -> Option> { - let uid = self.get_current_uid(); - self.get_user_by_uid(uid).map(|u| u.name.clone()) - } - fn get_current_gid(&self) -> gid_t { match self.gid.get() { Some(gid) => gid, @@ -282,20 +300,4 @@ impl Users for OSUsers { let gid = self.get_effective_gid(); self.get_group_by_gid(gid).map(|g| g.name.clone()) } - - fn get_effective_uid(&self) -> uid_t { - match self.euid.get() { - Some(uid) => uid, - None => { - let uid = super::get_effective_uid(); - self.euid.set(Some(uid)); - uid - } - } - } - - fn get_effective_username(&self) -> Option> { - let uid = self.get_effective_uid(); - self.get_user_by_uid(uid).map(|u| u.name.clone()) - } }