diff --git a/src/mode/mod.rs b/src/mode/mod.rs index b07b61a..320d556 100644 --- a/src/mode/mod.rs +++ b/src/mode/mod.rs @@ -8,7 +8,7 @@ pub fn get_umask() -> u32 { umask } -#[derive(Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum Bit { Suid = 0o4000, Sgid = 0o2000, diff --git a/src/mode/parser.rs b/src/mode/parser.rs index 7a5ad18..6727707 100644 --- a/src/mode/parser.rs +++ b/src/mode/parser.rs @@ -36,14 +36,13 @@ enum Who { User, Group, Other, - All, } pub struct Parser { mode: u32, op: Option, who: Vec, - bits: Vec, + bits: Vec, } impl Default for Parser { @@ -97,175 +96,95 @@ impl Parser { } } - fn push_bit(&mut self, bit: char) -> Result<(), ParseError> { - match self.op { - Some(_) => if self.bits.contains(&bit) { - return Err(ParseError::InvalidDigit); - } else { - self.bits.push(bit); - }, - None => return Err(ParseError::NoOpSet), + fn push_read_bits(&mut self) -> Result<(), ParseError> { + for w in &self.who { + match w { + Who::User => self.bits.push(Bit::URead), + Who::Group => self.bits.push(Bit::GRead), + Who::Other => self.bits.push(Bit::ORead), + } } Ok(()) } - fn push_suid(&mut self) -> Result<(), ParseError> { + fn push_write_bits(&mut self) -> Result<(), ParseError> { for w in &self.who { - if w == &Who::All || w == &Who::Other { - return Err(ParseError::InvalidBit); + match w { + Who::User => self.bits.push(Bit::UWrite), + Who::Group => self.bits.push(Bit::GWrite), + Who::Other => self.bits.push(Bit::OWrite), } } + Ok(()) + } + + fn push_exec_bits(&mut self) -> Result<(), ParseError> { + for w in &self.who { + match w { + Who::User => self.bits.push(Bit::UExec), + Who::Group => self.bits.push(Bit::GExec), + Who::Other => self.bits.push(Bit::OExec), + } + } + Ok(()) + } + + fn push_suid_sgid(&mut self) -> Result<(), ParseError> { if self.who.is_empty() { return Err(ParseError::InvalidBit); } - self.push_bit('s') + for w in &self.who { + match w { + &Who::Other => return Err(ParseError::InvalidBit), + &Who::User => self.bits.push(Bit::Suid), + &Who::Group => self.bits.push(Bit::Sgid), + } + } + Ok(()) } fn push_sticky(&mut self) -> Result<(), ParseError> { - for w in &self.who { - if w == &Who::All || w == &Who::User || w == &Who::Group { - return Err(ParseError::InvalidBit); - } - } if self.who.is_empty() { return Err(ParseError::InvalidBit); } - self.push_bit('t') - } - - fn add_user_bits(&mut self) { - for b in &self.bits { - match b { - 'r' => self.mode |= Bit::URead as u32, - 'w' => self.mode |= Bit::UWrite as u32, - 'x' => self.mode |= Bit::UExec as u32, - 's' => self.mode |= Bit::Suid as u32, - _ => unreachable!(), - } - } - } - - fn remove_user_bits(&mut self) { - for b in &self.bits { - match b { - 'r' => self.mode &= Bit::URead as u32, - 'w' => self.mode &= Bit::UWrite as u32, - 'x' => self.mode &= Bit::UExec as u32, - 's' => self.mode &= Bit::Suid as u32, - _ => unreachable!(), - } - } - } - - fn zero_user_bits(&mut self) { - self.mode &= 0o4444; - } - - fn set_user_bits(&mut self) { - match self.op { - Some(Op::Add) => self.add_user_bits(), - Some(Op::Remove) => self.remove_user_bits(), - Some(Op::Equals) => { - self.zero_user_bits(); - self.add_user_bits(); - }, - None => {}, - } - } - - fn add_group_bits(&mut self) { - for b in &self.bits { - match b { - 'r' => self.mode |= Bit::GRead as u32, - 'w' => self.mode |= Bit::GWrite as u32, - 'x' => self.mode |= Bit::GExec as u32, - 's' => self.mode |= Bit::Sgid as u32, - _ => unreachable!(), - } - } - } - - fn remove_group_bits(&mut self) { - for b in &self.bits { - match b { - 'r' => self.mode &= Bit::GRead as u32, - 'w' => self.mode &= Bit::GWrite as u32, - 'x' => self.mode &= Bit::GExec as u32, - 's' => self.mode &= Bit::Sgid as u32, - _ => unreachable!(), - } - } - } - - fn zero_group_bits(&mut self) { - self.mode &= 0o2222; - } - - fn set_group_bits(&mut self) { - match self.op { - Some(Op::Add) => self.add_group_bits(), - Some(Op::Remove) => self.remove_group_bits(), - Some(Op::Equals) => { - self.zero_group_bits(); - self.add_group_bits(); - }, - None => {}, - } - } - - fn add_other_bits(&mut self) { - for b in &self.bits { - match b { - 'r' => self.mode |= Bit::ORead as u32, - 'w' => self.mode |= Bit::OWrite as u32, - 'x' => self.mode |= Bit::OExec as u32, - 't' => self.mode |= Bit::Sticky as u32, - _ => unreachable!(), - } - } - } - - fn remove_other_bits(&mut self) { - for b in &self.bits { - match b { - 'r' => self.mode &= Bit::ORead as u32, - 'w' => self.mode &= Bit::OWrite as u32, - 'x' => self.mode &= Bit::OExec as u32, - 's' => self.mode &= Bit::Sticky as u32, - _ => unreachable!(), - } - } - } - - fn zero_other_bits(&mut self) { - self.mode &= 0o1111; - } - - fn set_other_bits(&mut self) { - match self.op { - Some(Op::Add) => self.add_other_bits(), - Some(Op::Remove) => self.remove_other_bits(), - Some(Op::Equals) => { - self.zero_other_bits(); - self.add_other_bits(); - }, - None => {}, - } - } - - fn set_bits(&mut self) { - for w in self.who.clone() { + for w in &self.who { match w { - Who::User => self.set_user_bits(), - Who::Group => self.set_group_bits(), - Who::Other => self.set_other_bits(), - Who::All => { - self.set_user_bits(); - self.set_group_bits(); - self.set_other_bits(); - } + &Who::User | &Who::Group => return Err(ParseError::InvalidBit), + &Who::Other => self.bits.push(Bit::Sticky), } } + Ok(()) + } + + fn add_bits(&mut self) { + for bit in &self.bits { + self.mode |= *bit as u32; + } + } + + fn remove_bits(&mut self) { + for bit in &self.bits { + self.mode &= *bit as u32; + } + } + + fn set_bits(&mut self) -> Result<(), ParseError> { + match self.op { + Some(Op::Add) => self.add_bits(), + Some(Op::Remove) => self.remove_bits(), + Some(Op::Equals) => { + for w in &self.who { + match w { + Who::User => self.mode &= 0o4444, + Who::Group => self.mode &= 0o2222, + Who::Other => self.mode &= 0o1111, + } + } + self.add_bits(); + }, + None => return Err(ParseError::NoOpSet), + } + Ok(()) } fn reset(&mut self) { @@ -293,17 +212,28 @@ impl Parser { 'u' => self.add_who(Who::User)?, 'g' => self.add_who(Who::Group)?, 'o' => self.add_who(Who::Other)?, - 'a' => self.add_who(Who::All)?, + 'a' => { + self.add_who(Who::User)?; + self.add_who(Who::Group)?; + self.add_who(Who::Other)?; + }, '-' => self.set_op(Op::Remove)?, '+' => self.set_op(Op::Add)?, '=' => self.set_op(Op::Equals)?, - 'r' | 'w' | 'x' => self.push_bit(c)?, - 's' => self.push_suid()?, + 'r' => self.push_read_bits()?, + 'w' => self.push_write_bits()?, + 'x' => self.push_exec_bits()?, + 's' => self.push_suid_sgid()?, 't' => self.push_sticky()?, _ => return Err(ParseError::InvalidDigit), } } - self.set_bits(); + if self.who.is_empty() { + self.who.push(Who::User); + self.who.push(Who::Group); + self.who.push(Who::Other); + } + self.set_bits()?; self.reset(); Ok(self.mode) }