More test coverage fixed some logic errors; Impl BitAnd, BitAndAssign,
BitOr and BitOrAssign for Bit and Who enums against u32
This commit is contained in:
parent
528d2478cd
commit
e9819b6228
@ -1,5 +1,7 @@
|
||||
//! Functions for parsing and managing permissions
|
||||
mod parser;
|
||||
use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign};
|
||||
|
||||
pub use parser::{Parser, ParseError};
|
||||
|
||||
pub fn get_umask() -> u32 {
|
||||
@ -23,3 +25,47 @@ pub enum Bit {
|
||||
OWrite = 0o2,
|
||||
OExec = 0o1,
|
||||
}
|
||||
|
||||
impl BitAnd<u32> for Bit {
|
||||
type Output = u32;
|
||||
|
||||
fn bitand(self, rhs: u32) -> Self::Output {
|
||||
self as u32 & rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl BitAnd<Bit> for u32 {
|
||||
type Output = u32;
|
||||
|
||||
fn bitand(self, rhs: Bit) -> Self::Output {
|
||||
self & rhs as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl BitAndAssign<Bit> for u32 {
|
||||
fn bitand_assign(&mut self, rhs: Bit) {
|
||||
*self = *self & rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl BitOr<u32> for Bit {
|
||||
type Output = u32;
|
||||
|
||||
fn bitor(self, rhs: u32) -> Self::Output {
|
||||
self as u32 | rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl BitOr<Bit> for u32 {
|
||||
type Output = u32;
|
||||
|
||||
fn bitor(self, rhs: Bit) -> Self::Output {
|
||||
self | rhs as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl BitOrAssign<Bit> for u32 {
|
||||
fn bitor_assign(&mut self, rhs: Bit) {
|
||||
*self = *self | rhs;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::{error, fmt::Display, num::ParseIntError};
|
||||
use std::{error, fmt::Display, num::ParseIntError, ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign}};
|
||||
use super::{Bit, get_umask};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
@ -38,11 +38,39 @@ enum Who {
|
||||
Other = 0o1,
|
||||
}
|
||||
|
||||
impl BitAnd<Who> for u32 {
|
||||
type Output = u32;
|
||||
|
||||
fn bitand(self, rhs: Who) -> Self::Output {
|
||||
self & rhs as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl BitAndAssign<Who> for u32 {
|
||||
fn bitand_assign(&mut self, rhs: Who) {
|
||||
*self = *self & rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl BitOr<Who> for u32 {
|
||||
type Output = u32;
|
||||
|
||||
fn bitor(self, rhs: Who) -> Self::Output {
|
||||
self | rhs as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl BitOrAssign<Who> for u32 {
|
||||
fn bitor_assign(&mut self, rhs: Who) {
|
||||
*self = *self | rhs;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Parser {
|
||||
mode: u32,
|
||||
op: Option<Op>,
|
||||
who: u32,
|
||||
bits: Vec<Bit>,
|
||||
bits: u32,
|
||||
}
|
||||
|
||||
impl Default for Parser {
|
||||
@ -54,7 +82,7 @@ impl Default for Parser {
|
||||
mode,
|
||||
op: None,
|
||||
who: 0,
|
||||
bits: vec![],
|
||||
bits: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -65,7 +93,7 @@ impl Parser {
|
||||
mode,
|
||||
op: None,
|
||||
who: 0,
|
||||
bits: vec![],
|
||||
bits: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,58 +107,61 @@ impl Parser {
|
||||
}
|
||||
|
||||
fn add_who(&mut self, who: Who) -> Result<(), ParseError> {
|
||||
if self.op.is_some() || !self.bits.is_empty() {
|
||||
if self.op.is_some() || !self.bits == 0 {
|
||||
Err(ParseError::InvalidDigit)
|
||||
} else {
|
||||
self.who |= who as u32;
|
||||
self.who |= who;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn set_op(&mut self, op: Op) -> Result<(), ParseError> {
|
||||
if self.op.is_some() || !self.bits.is_empty() {
|
||||
if self.op.is_some() || !self.bits == 0 {
|
||||
Err(ParseError::InvalidDigit)
|
||||
} else {
|
||||
self.op = Some(op);
|
||||
if self.who == 0 {
|
||||
self.who |= 0o111;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn push_read_bits(&mut self) -> Result<(), ParseError> {
|
||||
if self.who & 0o100 != 0 {
|
||||
self.bits.push(Bit::URead);
|
||||
self.bits |= Bit::URead;
|
||||
}
|
||||
if self.who & 0o10 != 0 {
|
||||
self.bits.push(Bit::GRead);
|
||||
self.bits |= Bit::GRead;
|
||||
}
|
||||
if self.who & 0o1 != 0 {
|
||||
self.bits.push(Bit::ORead);
|
||||
self.bits |= Bit::ORead;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn push_write_bits(&mut self) -> Result<(), ParseError> {
|
||||
if self.who & 0o100 != 0 {
|
||||
self.bits.push(Bit::UWrite);
|
||||
self.bits |= Bit::UWrite;
|
||||
}
|
||||
if self.who & 0o10 != 0 {
|
||||
self.bits.push(Bit::GWrite);
|
||||
self.bits |= Bit::GWrite;
|
||||
}
|
||||
if self.who & 0o1 != 0 {
|
||||
self.bits.push(Bit::OWrite);
|
||||
self.bits |= Bit::OWrite;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn push_exec_bits(&mut self) -> Result<(), ParseError> {
|
||||
if self.who & 0o100 != 0 {
|
||||
self.bits.push(Bit::UExec);
|
||||
self.bits |= Bit::UExec;
|
||||
}
|
||||
if self.who & 0o10 != 0 {
|
||||
self.bits.push(Bit::GExec);
|
||||
self.bits |= Bit::GExec;
|
||||
}
|
||||
if self.who & 0o1 != 0 {
|
||||
self.bits.push(Bit::OExec);
|
||||
self.bits |= Bit::OExec;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -140,10 +171,10 @@ impl Parser {
|
||||
return Err(ParseError::InvalidBit);
|
||||
}
|
||||
if self.who & 0o100 != 0 {
|
||||
self.bits.push(Bit::Suid);
|
||||
self.bits |= Bit::Suid;
|
||||
}
|
||||
if self.who &0o10 != 0 {
|
||||
self.bits.push(Bit::Sgid);
|
||||
self.bits |= Bit::Sgid;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -153,21 +184,17 @@ impl Parser {
|
||||
return Err(ParseError::InvalidBit);
|
||||
}
|
||||
if self.who & 0o1 != 0 {
|
||||
self.bits.push(Bit::Sticky);
|
||||
self.bits |= Bit::Sticky;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_bits(&mut self) {
|
||||
for bit in &self.bits {
|
||||
self.mode |= *bit as u32;
|
||||
}
|
||||
self.mode |= self.bits;
|
||||
}
|
||||
|
||||
fn remove_bits(&mut self) {
|
||||
for bit in &self.bits {
|
||||
self.mode &= !(*bit as u32);
|
||||
}
|
||||
self.mode &= !self.bits;
|
||||
}
|
||||
|
||||
fn set_bits(&mut self) -> Result<(), ParseError> {
|
||||
@ -176,13 +203,13 @@ impl Parser {
|
||||
Some(Op::Remove) => self.remove_bits(),
|
||||
Some(Op::Equals) => {
|
||||
if self.who & 0o100 != 0 {
|
||||
self.mode &= 0o4444;
|
||||
self.mode &= !(0o4700);
|
||||
}
|
||||
if self.who & 0o10 != 0 {
|
||||
self.mode &= 0o2222;
|
||||
self.mode &= !(0o2070);
|
||||
}
|
||||
if self.who &0o1 != 0 {
|
||||
self.mode &= 0o1111;
|
||||
self.mode &= !(0o1007);
|
||||
}
|
||||
self.add_bits();
|
||||
},
|
||||
@ -194,7 +221,7 @@ impl Parser {
|
||||
fn reset(&mut self) {
|
||||
self.who = 0;
|
||||
self.op = None;
|
||||
self.bits.clear();
|
||||
self.bits = 0;
|
||||
}
|
||||
|
||||
pub fn mode(&self) -> u32 {
|
||||
@ -229,23 +256,17 @@ impl Parser {
|
||||
'x' => self.push_exec_bits()?,
|
||||
's' => self.push_suid_sgid()?,
|
||||
't' => self.push_sticky()?,
|
||||
',' => {
|
||||
self.set_bits()?;
|
||||
self.reset();
|
||||
},
|
||||
_ => return Err(ParseError::InvalidDigit),
|
||||
}
|
||||
}
|
||||
if self.who == 0 {
|
||||
self.who |= 0o111;
|
||||
}
|
||||
self.set_bits()?;
|
||||
self.reset();
|
||||
Ok(self.mode)
|
||||
}
|
||||
|
||||
pub fn parse_all(&mut self, value: &str) -> Result<u32, ParseError> {
|
||||
for seg in value.split(',') {
|
||||
let _mode = self.parse(seg);
|
||||
}
|
||||
Ok(self.mode())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -279,4 +300,53 @@ mod test {
|
||||
let mode = parser.parse("ugo=rw");
|
||||
assert_eq!(mode, Ok(0o666));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn o_equals() {
|
||||
let mut parser = Parser::new(0o752);
|
||||
let mode = parser.parse("o=rx");
|
||||
assert_eq!(mode, Ok(0o755));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_who() {
|
||||
let mut parser = Parser::new(0o644);
|
||||
let mode = parser.parse("+x");
|
||||
assert_eq!(mode, Ok(0o755));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compound_ops() {
|
||||
let mut parser = Parser::new(0o666);
|
||||
let mode = parser.parse("u+x,g-w,o-r");
|
||||
assert_eq!(mode, Ok(0o742));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compount_ops2() {
|
||||
let mut parser = Parser::new(0o4444);
|
||||
let mode = parser.parse("u+w,ug+x,o=rx,u-s");
|
||||
assert_eq!(mode, Ok(0o755));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_sticky_bit() {
|
||||
let mut parser = Parser::default();
|
||||
let mode = parser.parse("u+t");
|
||||
assert_eq!(mode, Err(ParseError::InvalidBit));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_s() {
|
||||
let mut parser = Parser::default();
|
||||
let mode = parser.parse("+s");
|
||||
assert_eq!(mode, Err(ParseError::InvalidBit));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn outside_range() {
|
||||
let mut parser = Parser::default();
|
||||
let mode = parser.parse("10000");
|
||||
assert_eq!(mode, Err(ParseError::OutsideRange))
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user