1 #![warn(missing_copy_implementations)] 2 #![warn(missing_docs)] 3 #![warn(nonstandard_style)] 4 #![warn(trivial_numeric_casts)] 5 #![warn(unreachable_pub)] 6 #![warn(unused)] 7 8 9 //! This is a library for getting information on Unix users and groups. It 10 //! supports getting the system users, and creating your own mock tables. 11 //! 12 //! In Unix, each user has an individual *user ID*, and each process has an 13 //! *effective user ID* that says which user’s permissions it is using. 14 //! Furthermore, users can be the members of *groups*, which also have names and 15 //! IDs. This functionality is exposed in libc, the C standard library, but as 16 //! an unsafe Rust interface. This wrapper library provides a safe interface, 17 //! using [`User`](struct.user.html) and [`Group`](struct.group.html) types 18 //! and functions such as [`get_user_by_uid`](fn.get_user_by_uid.html) instead 19 //! of low-level pointers and strings. It also offers basic caching 20 //! functionality. 21 //! 22 //! It does not (yet) offer *editing* functionality; the values returned are 23 //! read-only. 24 //! 25 //! 26 //! ## Users 27 //! 28 //! The function [`get_current_uid`](fn.get_current_uid.html) returns a 29 //! `uid_t` value representing the user currently running the program, and the 30 //! [`get_user_by_uid`](fn.get_user_by_uid.html) function scans the users 31 //! database and returns a `User` with the user’s information. This function 32 //! returns `None` when there is no user for that ID. The `uid_t` type is 33 //! re-exported from the libc crate. 34 //! 35 //! A [`User`](struct.User.html) value has the following accessors: 36 //! 37 //! - **uid:** The user’s ID 38 //! - **name:** The user’s name 39 //! - **primary_group:** The ID of this user’s primary group 40 //! 41 //! Here is a complete example that prints out the current user’s name: 42 //! 43 //! ``` 44 //! use users::{get_user_by_uid, get_current_uid}; 45 //! 46 //! let user = get_user_by_uid(get_current_uid()).unwrap(); 47 //! println!("Hello, {}!", user.name().to_string_lossy()); 48 //! ``` 49 //! 50 //! This code assumes (with `unwrap()`) that the user hasn’t been deleted after 51 //! the program has started running. For arbitrary user IDs, this is **not** a 52 //! safe assumption: it’s possible to delete a user while it’s running a 53 //! program, or is the owner of files, or for that user to have never existed. 54 //! So always check the return values! 55 //! 56 //! There is also a [`get_current_username`](fn.get_current_username.html) 57 //! function, as it’s such a common operation that it deserves special 58 //! treatment. 59 //! 60 //! 61 //! ## Caching 62 //! 63 //! Despite the above warning, the users and groups database rarely changes. 64 //! While a short program may only need to get user information once, a 65 //! long-running one may need to re-query the database many times, and a 66 //! medium-length one may get away with caching the values to save on redundant 67 //! system calls. 68 //! 69 //! For this reason, this crate offers a caching interface to the database, 70 //! which offers the same functionality while holding on to every result, 71 //! caching the information so it can be re-used. 72 //! 73 //! To introduce a cache, create a new 74 //! [`UsersCache`](cache/struct.UsersCache.html). It has functions with the 75 //! same names as the ones from earlier. For example: 76 //! 77 //! ``` 78 //! use users::{Users, Groups, UsersCache}; 79 //! 80 //! let mut cache = UsersCache::new(); 81 //! let uid = cache.get_current_uid(); 82 //! let user = cache.get_user_by_uid(uid).unwrap(); 83 //! println!("Hello again, {}!", user.name().to_string_lossy()); 84 //! ``` 85 //! 86 //! This cache is **only additive**: it’s not possible to drop it, or erase 87 //! selected entries, as when the database may have been modified, it’s best to 88 //! start entirely afresh. So to accomplish this, just start using a new 89 //! `UsersCache`. 90 //! 91 //! 92 //! ## Groups 93 //! 94 //! Finally, it’s possible to get groups in a similar manner. 95 //! A [`Group`](struct.Group.html) has the following accessors: 96 //! 97 //! - **gid:** The group’s ID 98 //! - **name:** The group’s name 99 //! 100 //! And again, a complete example: 101 //! 102 //! ```no_run 103 //! use users::{Users, Groups, UsersCache}; 104 //! 105 //! let mut cache = UsersCache::new(); 106 //! let group = cache.get_group_by_name("admin").expect("No such group 'admin'!"); 107 //! println!("The '{}' group has the ID {}", group.name().to_string_lossy(), group.gid()); 108 //! ``` 109 //! 110 //! 111 //! ## Logging 112 //! 113 //! The `logging` feature, which is on by default, uses the `log` crate to 114 //! record all interactions with the operating system. 115 //! 116 //! 117 //! ## Caveats 118 //! 119 //! You should be prepared for the users and groups tables to be completely 120 //! broken: IDs shouldn’t be assumed to map to actual users and groups, and 121 //! usernames and group names aren’t guaranteed to map either! 122 //! 123 //! Use the [`mock`](mock/index.html) module to create custom tables to test 124 //! your code for these edge cases. 125 126 127 extern crate libc; 128 pub use libc::{uid_t, gid_t}; 129 130 mod base; 131 pub use base::{User, Group, os}; 132 pub use base::{get_user_by_uid, get_user_by_name}; 133 pub use base::{get_group_by_gid, get_group_by_name}; 134 pub use base::{get_current_uid, get_current_username}; 135 pub use base::{get_effective_uid, get_effective_username}; 136 pub use base::{get_current_gid, get_current_groupname}; 137 pub use base::{get_effective_gid, get_effective_groupname}; 138 pub use base::{get_user_groups, group_access_list}; 139 pub use base::{all_users}; 140 141 #[cfg(feature = "cache")] 142 pub mod cache; 143 144 #[cfg(feature = "cache")] 145 pub use cache::UsersCache; 146 147 #[cfg(feature = "mock")] 148 pub mod mock; 149 150 pub mod switch; 151 152 mod traits; 153 pub use traits::{Users, Groups}; 154