shitbox/unix-mode/src/lib.rs

144 lines
3.3 KiB
Rust

#![warn(clippy::all, clippy::pedantic)]
#![allow(clippy::missing_errors_doc)]
//! Functions for parsing and managing permissions
mod bit;
mod parser;
mod who;
use std::fmt::{self, Write};
pub use {
bit::Bit,
parser::{ParseError, Parser},
who::Who,
};
/// Gets the umask for the current user
#[must_use]
pub fn get_umask() -> u32 {
let mask = unsafe { libc::umask(0) };
let _mask = unsafe { libc::umask(mask) };
mask
}
/// Functions for extracting information about Unix modes
pub trait Mode {
/// Returns a string representing permissions in symbolic format
/// including file type
fn mode_string_full(&self) -> Result<String, fmt::Error>;
/// Returns a string representing permissions in symbolic format
/// minus file type
fn mode_string(&self) -> Result<String, fmt::Error>;
}
impl Mode for u32 {
fn mode_string_full(&self) -> Result<String, fmt::Error> {
let b = if self & 0o40000 != 0 && self & 0o20000 != 0 {
'b'
} else if self & 0o40000 != 0 {
'd'
} else if self & 0o20000 != 0 {
'c'
} else {
'-'
};
let mut s = String::new();
write!(s, "{b}")?;
[
Bit::URead,
Bit::UWrite,
Bit::UExec,
Bit::GRead,
Bit::GWrite,
Bit::GExec,
Bit::ORead,
Bit::OWrite,
Bit::OExec,
]
.iter()
.try_for_each(|b| write!(s, "{}", b.as_char(*self)))?;
Ok(s)
}
fn mode_string(&self) -> Result<String, fmt::Error> {
let mut s = String::new();
[
Bit::URead,
Bit::UWrite,
Bit::UExec,
Bit::GRead,
Bit::GWrite,
Bit::GExec,
Bit::ORead,
Bit::OWrite,
Bit::OExec,
]
.iter()
.try_for_each(|b| write!(s, "{}", b.as_char(*self)))?;
Ok(s)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn getumask() {
let mask = unsafe { libc::umask(0o22) };
assert_eq!(get_umask(), 0o022);
unsafe {
libc::umask(mask);
}
}
#[test]
fn display_bits_dir() {
let m: u32 = 0o40755;
let s = m.mode_string_full().unwrap();
assert_eq!(s.as_str(), "drwxr-xr-x")
}
#[test]
fn display_bits_char() {
let m: u32 = 0o20666;
let s = m.mode_string_full().unwrap();
assert_eq!(s.as_str(), "crw-rw-rw-")
}
#[test]
fn display_bits_block() {
let m: u32 = 0o60660;
let s = m.mode_string_full().unwrap();
assert_eq!(s.as_str(), "brw-rw----")
}
#[test]
fn display_bits_file() {
let m: u32 = 0o100644;
let s = m.mode_string_full().unwrap();
assert_eq!(s.as_str(), "-rw-r--r--")
}
#[test]
fn display_bits_suid() {
let m: u32 = 0o104755;
let s = m.mode_string_full().unwrap();
assert_eq!(s.as_str(), "-rwsr-xr-x")
}
#[test]
fn display_bits_sgid() {
let m: u32 = 0o102755;
let s = m.mode_string_full().unwrap();
assert_eq!(s.as_str(), "-rwxr-sr-x")
}
#[test]
fn display_bits_sticky() {
let m: u32 = 0o41777;
let s = m.mode_string_full().unwrap();
assert_eq!(s.as_str(), "drwxrwxrwt")
}
}