#[derive(Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub(crate) struct OwnerOptions {
pub(crate) uname: Option<String>,
pub(crate) gname: Option<String>,
pub(crate) uid: Option<u32>,
pub(crate) gid: Option<u32>,
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub(crate) struct Umask(u16);
impl Umask {
#[inline]
pub(crate) fn new(mask: u16) -> Self {
Self(mask & 0o777)
}
#[cfg(test)]
fn bits(self) -> u16 {
self.0
}
#[inline]
pub(crate) fn apply(self, mode: u16) -> u16 {
(mode & !0o7000) & !self.0
}
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub(crate) enum ModeStrategy {
#[default]
Never,
Preserve,
Masked(Umask),
}
#[derive(Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub(crate) enum OwnerStrategy {
#[default]
Never,
Preserve { options: OwnerOptions },
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn umask_new_masks_to_valid_range() {
assert_eq!(Umask::new(0o777).bits(), 0o777);
assert_eq!(Umask::new(0o022).bits(), 0o022);
assert_eq!(Umask::new(0o000).bits(), 0o000);
assert_eq!(Umask::new(0o1000).bits(), 0o000);
assert_eq!(Umask::new(0o7777).bits(), 0o777);
assert_eq!(Umask::new(0o4022).bits(), 0o022);
}
#[test]
fn umask_apply_clears_suid_bit() {
let umask = Umask::new(0o000);
assert_eq!(umask.apply(0o4755), 0o755);
}
#[test]
fn umask_apply_clears_sgid_bit() {
let umask = Umask::new(0o000);
assert_eq!(umask.apply(0o2755), 0o755);
}
#[test]
fn umask_apply_clears_sticky_bit() {
let umask = Umask::new(0o000);
assert_eq!(umask.apply(0o1755), 0o755);
}
#[test]
fn umask_apply_clears_all_special_bits() {
let umask = Umask::new(0o000);
assert_eq!(umask.apply(0o7777), 0o777);
assert_eq!(umask.apply(0o7755), 0o755);
}
#[test]
fn umask_apply_masks_permission_bits() {
let umask = Umask::new(0o022);
assert_eq!(umask.apply(0o777), 0o755);
assert_eq!(umask.apply(0o666), 0o644);
let umask = Umask::new(0o077);
assert_eq!(umask.apply(0o755), 0o700);
assert_eq!(umask.apply(0o777), 0o700);
let umask = Umask::new(0o027);
assert_eq!(umask.apply(0o755), 0o750);
}
#[test]
fn umask_apply_combined_special_bits_and_mask() {
let umask = Umask::new(0o027);
assert_eq!(umask.apply(0o4755), 0o750);
assert_eq!(umask.apply(0o7777), 0o750);
}
}