use std::ops::Deref;
use nix::libc::mode_t;
use nu_engine::command_prelude::*;
use nu_system::get_umask;
struct Mode(umask::Mode);
impl Deref for Mode {
type Target = umask::Mode;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<Mode> for mode_t {
#[allow(clippy::unnecessary_cast)]
fn from(mode: Mode) -> Self {
u32::from(mode.0) as mode_t
}
}
impl From<mode_t> for Mode {
#[allow(clippy::unnecessary_cast)]
fn from(value: mode_t) -> Self {
Self((value as u32).into())
}
}
#[derive(Clone)]
pub struct UMask;
impl Command for UMask {
fn name(&self) -> &str {
"umask"
}
fn description(&self) -> &str {
"Get or set default file creation permissions."
}
fn extra_description(&self) -> &str {
"When setting a new mask, the previous mask will be returned."
}
fn search_terms(&self) -> Vec<&str> {
vec!["permissions", "create", "file", "directory", "folder"]
}
fn signature(&self) -> Signature {
Signature::build("umask")
.input_output_types(vec![(Type::Nothing, Type::String)])
.optional(
"permissions",
SyntaxShape::String,
"The permissions to set on created files.",
)
.category(Category::Platform)
}
fn run(
&self,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
_input: PipelineData,
) -> Result<PipelineData, ShellError> {
let maybe_perms_val = call.opt::<Spanned<String>>(engine_state, stack, 0)?;
let prev_mask_bits = if let Some(perms_val) = maybe_perms_val {
let perms = Mode(
perms_val
.item
.parse()
.map_err(|err| ShellError::IncorrectValue {
msg: format!("Invalid mode: {0}.", err),
val_span: perms_val.span,
call_span: call.head,
})?,
);
let mask_bits = 0o777 ^ mode_t::from(perms);
let mask =
nix::sys::stat::Mode::from_bits(mask_bits).ok_or(ShellError::IncorrectValue {
msg: "Invalid mask; unrecognized permission bits.".into(),
val_span: perms_val.span,
call_span: call.head,
})?;
nix::sys::stat::umask(mask).bits()
} else {
get_umask() as mode_t
};
let prev_perms = Mode::from(0o777 ^ prev_mask_bits);
Ok(Value::string(prev_perms.to_string(), call.head).into_pipeline_data())
}
fn examples(&self) -> Vec<Example<'_>> {
vec![
Example {
description: "Print current default file creation permissions.",
example: "umask",
result: None,
},
Example {
description: "Make new files read-only to group and inaccessible to others.",
example: "umask rwxr-x---",
result: None,
},
]
}
}