use std::fmt;
use std::fs::Permissions;
use std::io;
use std::path::Path;
use serde::{Deserialize, Serialize};
#[derive(Debug, Default, Clone, Copy, PartialOrd, Ord, Serialize, Deserialize)]
pub struct UnixMode(Option<u32>);
const MODE_BITS: u32 = 0o7777;
impl UnixMode {
#[cfg(unix)]
pub fn set_permissions<P>(self, path: P) -> io::Result<()>
where
P: AsRef<Path>,
{
if let Some(mode) = self.0 {
let permissions = Permissions::from_mode(mode);
std::fs::set_permissions(&path, permissions)
} else {
Ok(())
}
}
#[cfg(not(unix))]
pub fn set_permissions<P>(self, _path: P) -> io::Result<()>
where
P: AsRef<Path>,
{
Ok(())
}
}
impl PartialEq for UnixMode {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl Eq for UnixMode {}
impl UnixMode {
pub fn readonly(self) -> bool {
match self.0 {
Some(mode) => mode & 0o200 == 0,
None => false,
}
}
}
impl fmt::Display for UnixMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.0 {
Some(mode) => write!(
f,
"{:<9}",
unix_mode::to_string(mode).trim_start_matches('?')
),
None => write!(f, "{:<9}", "none"),
}
}
}
impl From<u32> for UnixMode {
fn from(mode: u32) -> Self {
Self(Some(mode & MODE_BITS))
}
}
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;
#[cfg(unix)]
impl From<Permissions> for UnixMode {
fn from(p: Permissions) -> Self {
Self(Some(p.mode() & MODE_BITS))
}
}
#[cfg(not(unix))]
impl From<Permissions> for UnixMode {
fn from(p: Permissions) -> Self {
Self(
match p.readonly() {
true => Some(0o555),
false => Some(0o775),
},
)
}
}
#[cfg(test)]
mod tests {
use crate::unix_mode::UnixMode;
#[test]
fn display_unix_modes() {
assert_eq!("rwxrwxr--", format!("{}", UnixMode::from(0o774)));
assert_eq!("rwxr-xr-x", format!("{}", UnixMode::from(0o755)));
assert_eq!("rwxr---wx", format!("{}", UnixMode::from(0o743)));
assert_eq!("---r---wx", format!("{}", UnixMode::from(0o043)));
assert_eq!("rwsr-xr-x", format!("{}", UnixMode::from(0o4755)));
assert_eq!("rwxr-sr-x", format!("{}", UnixMode::from(0o2755)));
assert_eq!("rwxr-xr-t", format!("{}", UnixMode::from(0o1755)));
assert_eq!("rwxrwxr-T", format!("{}", UnixMode::from(0o1774)));
assert_eq!("rwxr-S-wx", format!("{}", UnixMode::from(0o2743)));
assert_eq!("--Sr---wx", format!("{}", UnixMode::from(0o4043)));
}
}