diff --git a/examples/example.rs b/examples/example.rs index f5c71bd..d8cd69d 100644 --- a/examples/example.rs +++ b/examples/example.rs @@ -12,13 +12,4 @@ fn main() { let primary_group = cache.get_group_by_gid(you.primary_group_id()).expect("No entry for your primary group!"); println!("Your primary group has ID {} and name {}", primary_group.gid, primary_group.name); - - if primary_group.members.is_empty() { - println!("There are no other members of that group."); - } - else { - for username in primary_group.members.iter() { - println!("User {} is also a member of that group.", username); - } - } } diff --git a/examples/os.rs b/examples/os.rs index d2634ba..7a0a104 100644 --- a/examples/os.rs +++ b/examples/os.rs @@ -1,6 +1,6 @@ extern crate users; use users::{Users, Groups, UsersCache}; -use users::os::unix::UserExt; +use users::os::unix::{UserExt, GroupExt}; fn main() { let cache = UsersCache::new(); @@ -16,11 +16,11 @@ fn main() { let primary_group = cache.get_group_by_gid(you.primary_group_id()).expect("No entry for your primary group!"); println!("Your primary group has ID {} and name {}", primary_group.gid, primary_group.name); - if primary_group.members.is_empty() { + if primary_group.members().is_empty() { println!("There are no other members of that group."); } else { - for username in primary_group.members.iter() { + for username in primary_group.members() { println!("User {} is also a member of that group.", username); } } diff --git a/src/base.rs b/src/base.rs index f6b4b33..ae36f80 100644 --- a/src/base.rs +++ b/src/base.rs @@ -141,8 +141,25 @@ pub struct Group { /// This group's name pub name: Arc, - /// Vector of the names of the users who belong to this group as a non-primary member - pub members: Vec, + extras: os::GroupExtras, + + // Vector of the names of the users who belong to this group as a non-primary member + //pub members: Vec, +} + +impl Group { + /// Create a new `Group` with the given group ID and name, with the + /// rest of the fields filled in with dummy values. + /// + /// This method does not actually create a new group on the system—it + /// should only be used for comparing groups in tests. + pub fn new(gid: gid_t, name: &str) -> Self { + Group { + gid: gid, + name: Arc::new(String::from(name)), + extras: os::GroupExtras::default(), + } + } } /// Reads data from a `*char` field in `c_passwd` or `g_group` into a UTF-8 @@ -172,7 +189,7 @@ unsafe fn ptr_as_ref(pointer: *const T) -> Option { unsafe fn passwd_to_user(pointer: *const c_passwd) -> Option { if let Some(passwd) = ptr_as_ref(pointer) { - let name = Arc::new(from_raw_buf(passwd.pw_name)); + let name = Arc::new(from_raw_buf(passwd.pw_name)); Some(User { uid: passwd.pw_uid, @@ -188,13 +205,12 @@ unsafe fn passwd_to_user(pointer: *const c_passwd) -> Option { unsafe fn struct_to_group(pointer: *const c_group) -> Option { if let Some(group) = ptr_as_ref(pointer) { - let name = Arc::new(from_raw_buf(group.gr_name)); - let members = members(group.gr_mem); + let name = Arc::new(from_raw_buf(group.gr_name)); Some(Group { gid: group.gr_gid, name: name, - members: members, + extras: os::GroupExtras::from_struct(group), }) } else { @@ -354,7 +370,7 @@ pub mod os { use std::sync::Arc; use libc::{uid_t, gid_t}; - use super::super::{c_passwd, from_raw_buf, User, Group}; + use super::super::{c_passwd, c_group, members, from_raw_buf, User, Group}; /// Unix-specific extensions for `User`s. pub trait UserExt { @@ -385,13 +401,6 @@ pub mod os { /// Returns a slice of the list of users that are in this group as /// their non-primary group. fn members(&self) -> &[String]; - - /// Create a new `Group` with the given group ID and name, with the - /// rest of the fields filled in with dummy values. - /// - /// This method does not actually create a new group on the system—it - /// should only be used for comparing groups in tests. - fn new(gid: gid_t, name: &str) -> Self; } #[derive(Clone)] @@ -442,17 +451,24 @@ pub mod os { } } + #[derive(Clone, Default)] + pub struct GroupExtras { + pub members: Vec, + } + + impl GroupExtras { + pub unsafe fn from_struct(group: c_group) -> GroupExtras { + let members = members(group.gr_mem); + + GroupExtras { + members: members, + } + } + } + impl GroupExt for Group { fn members(&self) -> &[String] { - &*self.members - } - - fn new(gid: gid_t, name: &str) -> Group { - Group { - gid: gid, - name: Arc::new(name.to_owned()), - members: Vec::new(), - } + &*self.extras.members } } } @@ -517,6 +533,8 @@ pub mod os { #[cfg(any(target_os = "linux"))] pub type UserExtras = unix::UserExtras; + #[cfg(any(target_os = "linux", target_os = "macos", target_os = "freebsd", target_os = "dragonfly"))] + pub type GroupExtras = unix::GroupExtras; } diff --git a/src/lib.rs b/src/lib.rs index 047d019..5bdc415 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,7 +24,7 @@ //! users database and returns a User object with the user’s information. This //! function returns `None` when there is no user for that ID. //! -//! A `User` object has the following public fields: +//! A `User` object has the following accessors: //! //! - **uid:** The user’s ID //! - **name:** The user’s name @@ -80,11 +80,10 @@ //! ## Groups //! //! Finally, it’s possible to get groups in a similar manner. -//! A `Group` has the following public fields: +//! A `Group` has the following accessors: //! //! - **gid:** The group’s ID //! - **name:** The group’s name -//! - **members:** Vector of names of the users that belong to this group //! //! And again, a complete example: //! @@ -93,9 +92,6 @@ //! let mut cache = UsersCache::new(); //! let group = cache.get_group_by_name("admin").expect("No such group 'admin'!"); //! println!("The '{}' group has the ID {}", group.name, group.gid); -//! for member in &group.members { -//! println!("{} is a member of the group", member); -//! } //! ``` //! //!