From 3ef3a8b3aaa71600d4b0200b8161be4505876d06 Mon Sep 17 00:00:00 2001 From: Nathan Fisher Date: Mon, 23 Jan 2023 09:39:02 -0500 Subject: [PATCH] Use `Bitflags` trait and `Bit` enum in `which` applet; Move `Bit` and `Who` enums out of `mode` module into submodules --- src/cmd/which/mod.rs | 5 ++- src/mode/bit.rs | 99 ++++++++++++++++++++++++++++++++++++++++++++ src/mode/mod.rs | 89 ++------------------------------------- src/mode/parser.rs | 51 +---------------------- src/mode/who.rs | 49 ++++++++++++++++++++++ 5 files changed, 156 insertions(+), 137 deletions(-) create mode 100644 src/mode/bit.rs create mode 100644 src/mode/who.rs diff --git a/src/cmd/which/mod.rs b/src/cmd/which/mod.rs index 79df4d8..da2238a 100644 --- a/src/cmd/which/mod.rs +++ b/src/cmd/which/mod.rs @@ -1,3 +1,4 @@ +use crate::{bitflags::BitFlags, mode::Bit}; use super::Cmd; use clap::{Arg, Command}; use std::{env, fs::File, io, os::unix::prelude::MetadataExt, path::PathBuf, process}; @@ -60,10 +61,10 @@ fn which(command: &str, path: &[&str]) -> Option { let myuid = unsafe { libc::geteuid() }; let mygroups = crate::pw::get_gids(); // we own the file and it has u+x - if myuid == meta.uid() && mode & 0o100 != 0 { + if myuid == meta.uid() && mode.contains(Bit::UExec) { return Some(format!("{}", file.display())); // file has ug+x - } else if mode & 0o110 != 0 { + } else if mode.contains(Bit::UExec | Bit::GExec) { if let Ok(groups) = mygroups { // one of our groups owns the file if groups.contains(&meta.gid()) { diff --git a/src/mode/bit.rs b/src/mode/bit.rs new file mode 100644 index 0000000..4f15870 --- /dev/null +++ b/src/mode/bit.rs @@ -0,0 +1,99 @@ +use crate::bitflags::BitFlags; +use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign}; + +/// Unix permission bit flags +#[derive(Clone, Copy, PartialEq)] +pub enum Bit { + Suid = 0o4000, + Sgid = 0o2000, + Sticky = 0o1000, + URead = 0o400, + UWrite = 0o200, + UExec = 0o100, + GRead = 0o40, + GWrite = 0o20, + GExec = 0o10, + ORead = 0o4, + 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 BitAnd for Bit { + type Output = u32; + + fn bitand(self, rhs: Self) -> Self::Output { + self as u32 & 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 BitOr for Bit { + type Output = u32; + + fn bitor(self, rhs: Self) -> Self::Output { + self as u32 | rhs as u32 + } +} + +impl BitOrAssign for u32 { + fn bitor_assign(&mut self, rhs: Bit) { + *self = *self | rhs; + } +} + +impl Bit { + pub fn as_char(&self, mode: u32) -> char { + if mode & *self != 0 { + match self { + Self::Suid | Self::Sgid => 's', + Self::Sticky => 't', + Self::URead | Self::GRead | Self::ORead => 'r', + Self::UWrite | Self::GWrite | Self::OWrite => 'w', + Self::UExec if mode.contains(Self::Suid) => 's', + Self::GExec if mode.contains(Self::Sgid) => 's', + Self::OExec if mode.contains(Self::Sticky) => 't', + Self::UExec | Self::GExec | Self::OExec => 'x', + } + } else { + '-' + } + } +} + diff --git a/src/mode/mod.rs b/src/mode/mod.rs index b763ed4..8ba79f8 100644 --- a/src/mode/mod.rs +++ b/src/mode/mod.rs @@ -1,11 +1,10 @@ //! Functions for parsing and managing permissions +mod bit; mod parser; -use std::{ - fmt::{self, Write}, - ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign}, -}; +mod who; +use std::fmt::{self, Write}; -pub use parser::{ParseError, Parser}; +pub use {bit::Bit, parser::{ParseError, Parser}, who::Who}; /// Gets the umask for the current user #[must_use] @@ -15,42 +14,6 @@ pub fn get_umask() -> u32 { mask } -/// Unix permission bit flags -#[derive(Clone, Copy, PartialEq)] -pub enum Bit { - Suid = 0o4000, - Sgid = 0o2000, - Sticky = 0o1000, - URead = 0o400, - UWrite = 0o200, - UExec = 0o100, - GRead = 0o40, - GWrite = 0o20, - GExec = 0o10, - ORead = 0o4, - OWrite = 0o2, - OExec = 0o1, -} - -impl Bit { - fn as_char(&self, mode: u32) -> char { - if mode & *self != 0 { - match self { - Self::Suid | Self::Sgid => 's', - Self::Sticky => 't', - Self::URead | Self::GRead | Self::ORead => 'r', - Self::UWrite | Self::GWrite | Self::OWrite => 'w', - Self::UExec if mode & Self::Suid != 0 => 's', - Self::GExec if mode & Self::Sgid != 0 => 's', - Self::OExec if mode & Self::Sticky != 0 => 't', - Self::UExec | Self::GExec | Self::OExec => 'x', - } - } else { - '-' - } - } -} - /// Functions for extracting information about Unix modes pub trait Mode { /// Returns a string representing permissions in symbolic format @@ -110,50 +73,6 @@ impl Mode for u32 { } } -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; - } -} - #[cfg(test)] mod test { use super::*; diff --git a/src/mode/parser.rs b/src/mode/parser.rs index 31766d0..afbb7e4 100644 --- a/src/mode/parser.rs +++ b/src/mode/parser.rs @@ -1,11 +1,9 @@ use crate::bitflags::BitFlags; - -use super::{get_umask, Bit}; +use super::{get_umask, Bit, Who}; use std::{ error, fmt::Display, num::ParseIntError, - ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign}, }; /// Errors which might occur when parsing Unix permissions from a string @@ -48,53 +46,6 @@ enum Op { Equals, } -#[derive(PartialEq)] -/// The granularity of the given permissions -enum Who { - /// applies for the current user - User = 0o100, - /// applies for the current group - Group = 0o10, - /// applies for everyone else - Other = 0o1, -} - -impl BitAnd for u32 { - type Output = u32; - - fn bitand(self, rhs: Who) -> Self::Output { - self & rhs as u32 - } -} - -impl BitAnd for Who { - type Output = u32; - - fn bitand(self, rhs: u32) -> Self::Output { - self as u32 & rhs - } -} - -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; - } -} - /// A parser for octal and symbolic permissions. `Parser::default` creates an /// instance which applies the given operations to the default setting for the /// current user's umask. `Parser::new` creates a parser which applies the given diff --git a/src/mode/who.rs b/src/mode/who.rs new file mode 100644 index 0000000..c5b7992 --- /dev/null +++ b/src/mode/who.rs @@ -0,0 +1,49 @@ +use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign}; + +#[derive(PartialEq)] +/// The granularity of the given permissions +pub enum Who { + /// applies for the current user + User = 0o100, + /// applies for the current group + Group = 0o10, + /// applies for everyone else + Other = 0o1, +} + +impl BitAnd for u32 { + type Output = u32; + + fn bitand(self, rhs: Who) -> Self::Output { + self & rhs as u32 + } +} + +impl BitAnd for Who { + type Output = u32; + + fn bitand(self, rhs: u32) -> Self::Output { + self as u32 & rhs + } +} + +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; + } +} +