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