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