142 lines
3.3 KiB
Rust
142 lines
3.3 KiB
Rust
|
//! 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")
|
||
|
}
|
||
|
}
|