1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#![warn(missing_copy_implementations)]
#![warn(missing_docs)]
#![warn(nonstandard_style)]
#![warn(trivial_numeric_casts)]
#![warn(unreachable_pub)]
#![warn(unused)]

//! This is a library for getting information on Unix users and groups. It
//! supports getting the system users, and creating your own mock tables.
//!
//! In Unix, each user has an individual *user ID*, and each process has an
//! *effective user ID* that says which user’s permissions it is using.
//! Furthermore, users can be the members of *groups*, which also have names and
//! IDs. This functionality is exposed in libc, the C standard library, but as
//! an unsafe Rust interface. This wrapper library provides a safe interface,
//! using [`User`](struct.user.html) and [`Group`](struct.group.html) types
//! and functions such as [`get_user_by_uid`](fn.get_user_by_uid.html) instead
//! of low-level pointers and strings. It also offers basic caching
//! functionality.
//!
//! It does not (yet) offer *editing* functionality; the values returned are
//! read-only.
//!
//!
//! ## Users
//!
//! The function [`get_current_uid`](fn.get_current_uid.html) returns a
//! `uid_t` value representing the user currently running the program, and the
//! [`get_user_by_uid`](fn.get_user_by_uid.html) function scans the users
//! database and returns a `User` with the user’s information. This function
//! returns `None` when there is no user for that ID. The `uid_t` type is
//! re-exported from the libc crate.
//!
//! A [`User`](struct.User.html) value has the following accessors:
//!
//! - **uid:** The user’s ID
//! - **name:** The user’s name
//! - **primary_group:** The ID of this user’s primary group
//! - [OS-specific extensions](os/index.html) such as home directories
//!
//! Here is a complete example that prints out the current user’s name:
//!
//! ```
//! use uzers::{get_user_by_uid, get_current_uid};
//!
//! let user = get_user_by_uid(get_current_uid()).unwrap();
//! println!("Hello, {}!", user.name().to_string_lossy());
//! ```
//!
//! This code assumes (with `unwrap()`) that the user hasn’t been deleted after
//! the program has started running. For arbitrary user IDs, this is **not** a
//! safe assumption: it’s possible to delete a user while it’s running a
//! program, or is the owner of files, or for that user to have never existed.
//! So always check the return values!
//!
//! There is also a [`get_current_username`](fn.get_current_username.html)
//! function, as it’s such a common operation that it deserves special
//! treatment.
//!
//!
//! ## Caching
//!
//! Despite the above warning, the users and groups database rarely changes.
//! While a short program may only need to get user information once, a
//! long-running one may need to re-query the database many times, and a
//! medium-length one may get away with caching the values to save on redundant
//! system calls.
//!
//! For this reason, this create offers two caching interfaces that expose the
//! same functionality while reducing system calls:
//! [`UsersCache`](cache/struct.UsersCache.html) and
//! [`UsersSnapshot`](cache/struct.UsersSnapshot.html). `UsersCache` is a lazy
//! cache, storing answers as they arrive from the OS. `UsersSnapshot` is an
//! eager cache, querying all data at once when constructed.
//!
//! `UsersCache` has a smaller memory and performance overhead, while
//! `UsersSnapshot` offers better consistency and allows iterating over users
//! and groups.
//!
//! For example, to introduce a lazy cache, create a new
//! [`UsersCache`](cache/struct.UsersCache.html). It has functions with the
//! same names as the ones from earlier:
//!
//! ```
//! use uzers::{Users, Groups, UsersCache};
//!
//! let mut cache = UsersCache::new();
//! let uid = cache.get_current_uid();
//! let user = cache.get_user_by_uid(uid).unwrap();
//! println!("Hello again, {}!", user.name().to_string_lossy());
//! ```
//!
//! See documentation for [`UsersCache`](cache/struct.UsersCache.html) and
//! [`UsersSnapshot`](cache/struct.UsersSnapshot.html) for more details.
//!
//!
//! ## Groups
//!
//! Finally, it’s possible to get groups in a similar manner.
//! A [`Group`](struct.Group.html) has the following accessors:
//!
//! - **gid:** The group’s ID
//! - **name:** The group’s name
//! - [OS-specific extensions](os/index.html) such as lists of members
//!
//! And again, a complete example:
//!
//! ```no_run
//! use uzers::{Users, Groups, UsersCache};
//!
//! 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().to_string_lossy(), group.gid());
//! ```
//!
//!
//! ## Logging
//!
//! The `logging` feature, which is on by default, uses the `log` crate to
//! record all interactions with the operating system.
//!
//!
//! ## Caveats
//!
//! You should be prepared for the users and groups tables to be completely
//! broken: IDs shouldn’t be assumed to map to actual users and groups, and
//! usernames and group names aren’t guaranteed to map either!
//!
//! Use the [`mock`](mock/index.html) module to create custom tables to test
//! your code for these edge cases.

extern crate libc;
pub use libc::{gid_t, uid_t};

mod base;
pub use base::{all_groups, all_users};
pub use base::{get_current_gid, get_current_groupname};
pub use base::{get_current_uid, get_current_username};
pub use base::{get_effective_gid, get_effective_groupname};
pub use base::{get_effective_uid, get_effective_username};
pub use base::{get_group_by_gid, get_group_by_name};
pub use base::{get_user_by_name, get_user_by_uid};
pub use base::{get_user_groups, group_access_list};
pub use base::{os, Group, User};

#[cfg(feature = "cache")]
pub mod cache;

#[cfg(feature = "cache")]
pub use cache::{UsersCache, UsersSnapshot};

#[cfg(feature = "mock")]
pub mod mock;

pub mod switch;

mod traits;
pub use traits::{AllGroups, AllUsers, Groups, Users};