Skip to content

Commit

Permalink
Expand documentation substantially (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
intgr committed Mar 10, 2020
1 parent 1993d92 commit a138059
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 15 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ jobs:
- name: LeakSanitizer
run: docker run --env RUSTFLAGS="-Z sanitizer=leak" posixacl-nightly cargo test --color=always
- name: AddressSanitizer
run: docker run --env RUSTFLAGS="-Z sanitizer=address" posixacl-nightly cargo test --color=always
# --tests to omit doc tests, doesn't play nice with AddressSanitizer
run: docker run --env RUSTFLAGS="-Z sanitizer=address" posixacl-nightly cargo test --tests --color=always

rust-stable:
runs-on: ubuntu-latest
Expand Down
40 changes: 34 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,43 @@ posix-acl
[![Documentation](https://docs.rs/posix-acl/badge.svg)](https://docs.rs/posix-acl/)
[![Tests status](https://github.com/intgr/posix-acl/workflows/Tests/badge.svg?branch=master)](https://github.com/intgr/posix-acl/actions?query=workflow:Tests)

posix-acl is a simple Rust library to interact with POSIX filesystem ACLs. It uses the operating
system's C API internally.

Turns out that the C POSIX ACL library is actually quite annoying to work with and this library
significantly improves on that.
**posix-acl** is a Rust library to interact with POSIX file system Access Control Lists (ACL).
It wraps the operating system's C interface with a safe Rust API. The API is deliberately different
from the POSIX C API to make it easier to use.

NB! Currently only tested on Linux.

Read [Documentation on Docs.rs](https://docs.rs/posix-acl/) for more details.
Resources:
* [Library API documentation on Docs.rs](https://docs.rs/posix-acl/)
* [Background information about ACL behavior](
https://www.usenix.org/legacy/publications/library/proceedings/usenix03/tech/freenix03/full_papers/gruenbacher/gruenbacher_html/main.html)

### Usage example
```rust
use posix_acl::{PosixACL, Qualifier, ACL_READ, ACL_WRITE};

fn main() {
// Read ACL from file (if there is no ACL yet, the OS will synthesize one)
let mut acl = PosixACL::read_acl("/tmp/posix-acl-testfile".as_ref()).unwrap();

// Get permissions of owning user of the file
let perm = acl.get(Qualifier::UserObj).unwrap();
assert_eq!(perm, ACL_READ | ACL_WRITE);

// Get permissions for user UID 1234
let perm = acl.get(Qualifier::User(1234));
assert!(perm.is_none());

// Grant read access to group GID 1234 (adds new entry or overwrites an existing entry)
acl.set(Qualifier::Group(1234), ACL_READ);

// Remove ACL entry of group GID 1234
acl.remove(Qualifier::Group(1234));

// Write ACL back to the file
acl.write_acl("/tmp/posix-acl-testfile".as_ref()).unwrap();
}
```

Release history
---------------
Expand Down
66 changes: 58 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,42 @@
//! posix-acl is a simple Rust library to interact with POSIX filesystem ACLs. It uses the
//! operating system's C API internally.
//! **posix-acl** is a Rust library to interact with POSIX file system Access Control Lists (ACL).
//! It wraps the operating system's C interface with a safe Rust API. The API is deliberately
//! different from the POSIX C API to make it easier to use.
//!
//! See the [`PosixACL`] struct as a starting point.
//! NB! Currently only tested on Linux.
//!
//! While officially called a "list", The main struct [`PosixACL`] implements a "mapping-like"
//! interface where key is the [`Qualifier`] enum and value is `u32` containing permission bits.
//! This is without any loss of functionality, as duplicate entries with the same Qualifier are
//! disallowed by POSIX anyway.
//!
//! For background information about ACL behavior, read [POSIX Access Control Lists on Linux](
//! https://www.usenix.org/legacy/publications/library/proceedings/usenix03/tech/freenix03/full_papers/gruenbacher/gruenbacher_html/main.html).
//!
//! ## Usage example
//! ```
//! use posix_acl::{PosixACL, Qualifier, ACL_READ, ACL_WRITE};
//!
//! # std::fs::File::create("/tmp/posix-acl-testfile");
//! // Read ACL from file (if there is no ACL yet, the OS will synthesize one)
//! let mut acl = PosixACL::read_acl("/tmp/posix-acl-testfile".as_ref()).unwrap();
//!
//! // Get permissions of owning user of the file
//! let perm = acl.get(Qualifier::UserObj).unwrap();
//! assert_eq!(perm, ACL_READ | ACL_WRITE);
//!
//! // Get permissions for user UID 1234
//! let perm = acl.get(Qualifier::User(1234));
//! assert!(perm.is_none());
//!
//! // Grant read access to group GID 1234 (adds new entry or overwrites an existing entry)
//! acl.set(Qualifier::Group(1234), ACL_READ);
//!
//! // Remove ACL entry of group GID 1234
//! acl.remove(Qualifier::Group(1234));
//!
//! // Write ACL back to the file
//! acl.write_acl("/tmp/posix-acl-testfile".as_ref()).unwrap();
//! ```
#[macro_use]
extern crate simple_error;

Expand Down Expand Up @@ -181,6 +215,14 @@ impl PosixACL {
/// contain at least four entries: UserObj, GroupObj, Mask and Other.
///
/// Bits higher than 9 (e.g. SUID flag, etc) are ignored.
///
/// ```
/// use posix_acl::PosixACL;
/// assert_eq!(
/// PosixACL::new(0o751).as_text(),
/// "user::rwx\ngroup::r-x\nmask::r-x\nother::--x\n"
/// );
/// ```
pub fn new(file_mode: u32) -> PosixACL {
let mut acl = PosixACL::empty();
acl.set(UserObj, (file_mode >> 6) & ACL_RWX);
Expand All @@ -202,13 +244,16 @@ impl PosixACL {
PosixACL { acl }
}

/// Read a path's ACL and return as `PosixACL` object.
/// Read a path's access ACL and return as `PosixACL` object.
pub fn read_acl(path: &Path) -> Result<PosixACL, SimpleError> {
Self::read_acl_flags(path, acl_sys::ACL_TYPE_ACCESS)
}

/// Read a directory's default ACL and return as `PosixACL` object.
/// This will fail if `path` is not a directory.
///
/// Default ACL determines permissions for new files and subdirectories created in the
/// directory.
pub fn read_default_acl(path: &Path) -> Result<PosixACL, SimpleError> {
Self::read_acl_flags(path, acl_sys::ACL_TYPE_DEFAULT)
}
Expand All @@ -231,9 +276,9 @@ impl PosixACL {
Ok(PosixACL { acl })
}

/// Write the current ACL to a file. Overwrites any existing ACL on the file.
/// Write this ACL to a path's access ACL. Overwrites any existing access ACL.
///
/// Automatically re-calculates the `Mask` entry and calls validation.
/// Automatically re-calculates the magic `Mask` entry and calls validation.
pub fn write_acl(&mut self, path: &Path) -> Result<(), SimpleError> {
let c_path = path_to_cstring(path);
self.fix_mask();
Expand All @@ -254,7 +299,7 @@ impl PosixACL {
RawACLIterator::new(&self)
}

/// Get all ACLEntry items. The POSIX ACL API does not allow multiple parallel iterators so we
/// Get all ACLEntry items. The POSIX ACL C API does not allow multiple parallel iterators so we
/// return a materialized vector just to be safe.
pub fn entries(&self) -> Vec<ACLEntry> {
unsafe { self.raw_iter() }
Expand Down Expand Up @@ -335,7 +380,10 @@ impl PosixACL {
}
}

/// Re-calculate the `Qualifier::Mask` entry. This is automatically done during `write_acl()`.
/// Re-calculate the `Qualifier::Mask` entry.
///
/// Usually there is no need to call this directly, as this is done during `write_acl()`
/// automatically.
pub fn fix_mask(&mut self) {
unsafe {
check_return(acl_calc_mask(&mut self.acl), "acl_calc_mask");
Expand All @@ -344,6 +392,8 @@ impl PosixACL {

/// Return the textual representation of the ACL. Individual entries are separated by newline
/// (`'\n'`).
///
/// UID/GID are automatically resolved to names by the platform.
pub fn as_text(&self) -> String {
let mut len: ssize_t = 0;
let txt = AutoPtr(unsafe { acl_to_text(self.acl, &mut len) });
Expand Down

0 comments on commit a138059

Please sign in to comment.