systemd-cron-next/vendor/users/README.md
2024-11-12 15:03:58 +03:00

152 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# rust-users [![users on crates.io](http://meritbadge.herokuapp.com/users)](https://crates.io/crates/users) [![Build status](https://travis-ci.org/ogham/rust-users.svg?branch=master)](https://travis-ci.org/ogham/rust-users)
This is a library for getting information on Unix users and groups. It supports getting the system users, and creating your own mock tables.
### [View the Rustdoc](http://ogham.rustdocs.org/users)
# Installation
This crate works with [Cargo](http://crates.io). Add the following to your `Cargo.toml` dependencies section:
```toml
[dependencies]
users = "0.5.0"
```
# Usage
In Unix, each user has an individual *user ID*, and each process has an *effective user ID* that says which users 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 and Group objects instead of low-level pointers and strings.
It also offers basic caching functionality.
It does not (yet) offer *editing* functionality; the objects returned are read-only.
## Users
The function `get_current_uid` returns a `uid_t` value representing the user currently running the program, and the `get_user_by_uid` function scans the users database and returns a User object with the users information.
This function returns `None` when there is no user for that ID.
A `User` object has the following accessors:
- **uid:** The users ID
- **name:** The users name
- **primary_group:** The ID of this users primary group
Here is a complete example that prints out the current users name:
```rust
use users::{get_user_by_uid, get_current_uid};
let user = get_user_by_uid(get_current_uid()).unwrap();
println!("Hello, {}!", user.name());
```
This code assumes (with `unwrap()`) that the user hasnt been deleted after the program has started running.
For arbitrary user IDs, this is **not** a safe assumption: its possible to delete a user while its running a program, or is the owner of files, or for that user to have never existed.
So always check the return values from `user_to_uid`!
There is also a `get_current_username` function, as its 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 crate offers a caching interface to the database, which offers the same functionality while holding on to every result, caching the information so it can be re-used.
To introduce a cache, create a new `OSUsers` object and call the same methods on it.
For example:
```rust
use users::{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());
```
This cache is **only additive**: its not possible to drop it, or erase selected entries, as when the database may have been modified, its best to start entirely afresh.
So to accomplish this, just start using a new `OSUsers` object.
## Groups
Finally, its possible to get groups in a similar manner.
A `Group` object has the following accessors:
- **gid:** The groups ID
- **name:** The groups name
And again, a complete example:
```rust
use users::{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(), group.gid());
```
## Caveats
You should be prepared for the users and groups tables to be completely broken: IDs shouldnt be assumed to map to actual users and groups, and usernames and group names arent guaranteed to map either!
Use the mocking module to create custom tables to test your code for these edge cases.
# Mockable users and groups
When youre testing your code, you dont want to actually rely on the system actually having various users and groups present - its much better to have a custom set of users that are *guaranteed* to be there, so you can test against them.
This sub-library allows you to create these custom users and groups definitions, then access them using the same `Users` trait as in the main library, with few changes to your code.
## Creating mock users
The only thing a mock users object needs to know in advance is the UID of the current user.
Aside from that, you can add users and groups with `add_user` and `add_group` to the object:
```rust
use users::mock::{MockUsers, User, Group};
use users::os::unix::{UserExt, GroupExt};
use std::sync::Arc;
let mut users = MockUsers::with_current_uid(1000);
let bobbins = User::new(1000, "Bobbins", 1000).with_home_dir("/home/bobbins");
users.add_user(bobbins);
users.add_group(Group::new(100, "funkyppl"));
```
The exports get re-exported into the mock module, for simpler `use` lines.
## Using mock users
To set your program up to use either type of Users object, make your functions and structs accept a generic parameter that implements the `Users` trait.
Then, you can pass in an object of either OS or Mock type.
Here's a complete example:
```rust
use users::{Users, UsersCache, User};
use users::os::unix::UserExt;
use users::mock::MockUsers;
use std::sync::Arc;
fn print_current_username<U: Users>(users: &mut U) {
println!("Current user: {:?}", users.get_current_username());
}
let mut users = MockUsers::with_current_uid(1001);
users.add_user(User::new(1001, "fred", 101));
print_current_username(&mut users);
let mut actual_users = UsersCache::new();
print_current_username(&mut actual_users);
```