diff --git a/src/mode/mod.rs b/src/mode/mod.rs index 320d556..04f1f3d 100644 --- a/src/mode/mod.rs +++ b/src/mode/mod.rs @@ -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 for Bit { + type Output = u32; + + fn bitand(self, rhs: u32) -> Self::Output { + self as u32 & rhs + } +} + +impl BitAnd for u32 { + type Output = u32; + + fn bitand(self, rhs: Bit) -> Self::Output { + self & rhs as u32 + } +} + +impl BitAndAssign for u32 { + fn bitand_assign(&mut self, rhs: Bit) { + *self = *self & rhs; + } +} + +impl BitOr for Bit { + type Output = u32; + + fn bitor(self, rhs: u32) -> Self::Output { + self as u32 | rhs + } +} + +impl BitOr for u32 { + type Output = u32; + + fn bitor(self, rhs: Bit) -> Self::Output { + self | rhs as u32 + } +} + +impl BitOrAssign for u32 { + fn bitor_assign(&mut self, rhs: Bit) { + *self = *self | rhs; + } +} diff --git a/src/mode/parser.rs b/src/mode/parser.rs index 2864d63..bcb030f 100644 --- a/src/mode/parser.rs +++ b/src/mode/parser.rs @@ -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 for u32 { + type Output = u32; + + fn bitand(self, rhs: Who) -> Self::Output { + self & rhs as u32 + } +} + +impl BitAndAssign for u32 { + fn bitand_assign(&mut self, rhs: Who) { + *self = *self & rhs; + } +} + +impl BitOr for u32 { + type Output = u32; + + fn bitor(self, rhs: Who) -> Self::Output { + self | rhs as u32 + } +} + +impl BitOrAssign for u32 { + fn bitor_assign(&mut self, rhs: Who) { + *self = *self | rhs; + } +} + pub struct Parser { mode: u32, op: Option, who: u32, - bits: Vec, + 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 { - 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)) + } }