From 052cf245f40c6cbf15c99c799fff82312b3082e6 Mon Sep 17 00:00:00 2001 From: Benjamin Sago Date: Thu, 14 Jan 2016 23:15:53 -1000 Subject: [PATCH] Split Users trait into Users and Groups traits It was getting crowded in there! Not only are two groups of six easier to manage than one group of twelve, but the groups functions didn't actually have anything to do with users... --- examples/example.rs | 2 +- src/lib.rs | 82 ++++++++++++++++++++++++--------------------- src/mock.rs | 38 +++++++++++---------- src/os.rs | 68 +++++++++++++++++++------------------ 4 files changed, 99 insertions(+), 91 deletions(-) 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()) - } }