mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2026-01-16 10:11:01 +00:00
Merge branch 'main' into openbsd-utmpx
This commit is contained in:
commit
1bfac9b25a
45 changed files with 387 additions and 257 deletions
|
|
@ -87,8 +87,7 @@ pub fn parse_base_cmd_args(
|
|||
usage: &str,
|
||||
) -> UResult<Config> {
|
||||
let command = base_app(about, usage);
|
||||
let arg_list = args.collect_lossy();
|
||||
Config::from(&command.try_get_matches_from(arg_list)?)
|
||||
Config::from(&command.try_get_matches_from(args)?)
|
||||
}
|
||||
|
||||
pub fn base_app(about: &'static str, usage: &str) -> Command {
|
||||
|
|
|
|||
|
|
@ -174,8 +174,6 @@ mod options {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_ignore();
|
||||
|
||||
let matches = uu_app().try_get_matches_from(args)?;
|
||||
|
||||
let number_mode = if matches.get_flag(options::NUMBER_NONBLANK) {
|
||||
|
|
|
|||
|
|
@ -33,8 +33,6 @@ mod options {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_lossy();
|
||||
|
||||
let matches = uu_app().try_get_matches_from(args).with_exit_code(125)?;
|
||||
|
||||
let default_shell: &'static str = "/bin/sh";
|
||||
|
|
|
|||
|
|
@ -221,8 +221,6 @@ mod options {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_ignore();
|
||||
|
||||
let matches = uu_app().try_get_matches_from(args)?;
|
||||
|
||||
let algo_name: &str = match matches.get_one::<String>(options::ALGORITHM) {
|
||||
|
|
|
|||
|
|
@ -145,8 +145,6 @@ fn open_file(name: &str, line_ending: LineEnding) -> io::Result<LineReader> {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_lossy();
|
||||
|
||||
let matches = uu_app().try_get_matches_from(args)?;
|
||||
let line_ending = LineEnding::from_zero_flag(matches.get_flag(options::ZERO_TERMINATED));
|
||||
let filename1 = matches.get_one::<String>(options::FILE_1).unwrap();
|
||||
|
|
|
|||
|
|
@ -552,8 +552,6 @@ where
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_ignore();
|
||||
|
||||
let matches = uu_app().try_get_matches_from(args)?;
|
||||
|
||||
// get the file to split
|
||||
|
|
|
|||
|
|
@ -1267,8 +1267,6 @@ fn is_fifo(filename: &str) -> bool {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_ignore();
|
||||
|
||||
let matches = uu_app().try_get_matches_from(args)?;
|
||||
|
||||
let settings: Settings = Parser::new().parse(
|
||||
|
|
|
|||
|
|
@ -129,8 +129,6 @@ fn generate_ls_colors(fmt: &OutputFmt, sep: &str) -> String {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_ignore();
|
||||
|
||||
let matches = uu_app().try_get_matches_from(args)?;
|
||||
|
||||
let files = matches
|
||||
|
|
|
|||
|
|
@ -21,8 +21,6 @@ mod options {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_lossy();
|
||||
|
||||
let matches = uu_app().after_help(AFTER_HELP).try_get_matches_from(args)?;
|
||||
|
||||
let line_ending = LineEnding::from_zero_flag(matches.get_flag(options::ZERO));
|
||||
|
|
|
|||
|
|
@ -590,8 +590,6 @@ pub fn div_ceil(a: u64, b: u64) -> u64 {
|
|||
#[uucore::main]
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_ignore();
|
||||
|
||||
let matches = uu_app().try_get_matches_from(args)?;
|
||||
|
||||
let summarize = matches.get_flag(options::SUMMARIZE);
|
||||
|
|
|
|||
|
|
@ -118,7 +118,6 @@ fn print_escaped(input: &str, mut output: impl Write) -> io::Result<ControlFlow<
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_lossy();
|
||||
let matches = uu_app().get_matches_from(args);
|
||||
|
||||
let no_newline = matches.get_flag(options::NO_NEWLINE);
|
||||
|
|
|
|||
|
|
@ -98,8 +98,6 @@ pub fn uu_app() -> Command {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_lossy();
|
||||
|
||||
// For expr utility we do not want getopts.
|
||||
// The following usage should work without escaping hyphens: `expr -15 = 1 + 2 \* \( 3 - -4 \)`
|
||||
let matches = uu_app().try_get_matches_from(args)?;
|
||||
|
|
@ -108,9 +106,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
|||
.map(|v| v.into_iter().map(|s| s.as_ref()).collect::<Vec<_>>())
|
||||
.unwrap_or_default();
|
||||
|
||||
let res = AstNode::parse(&token_strings)?.eval()?;
|
||||
let res: String = AstNode::parse(&token_strings)?.eval()?.eval_as_string();
|
||||
println!("{res}");
|
||||
if !is_truthy(&res) {
|
||||
if !is_truthy(&res.into()) {
|
||||
return Err(1.into());
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@
|
|||
|
||||
// spell-checker:ignore (ToDO) ints paren prec multibytes
|
||||
|
||||
use num_bigint::BigInt;
|
||||
use num_bigint::{BigInt, ParseBigIntError};
|
||||
use num_traits::ToPrimitive;
|
||||
use onig::{Regex, RegexOptions, Syntax};
|
||||
|
||||
use crate::{ExprError, ExprResult};
|
||||
|
|
@ -45,7 +46,7 @@ pub enum StringOp {
|
|||
}
|
||||
|
||||
impl BinOp {
|
||||
fn eval(&self, left: &AstNode, right: &AstNode) -> ExprResult<String> {
|
||||
fn eval(&self, left: &AstNode, right: &AstNode) -> ExprResult<NumOrStr> {
|
||||
match self {
|
||||
Self::Relation(op) => op.eval(left, right),
|
||||
Self::Numeric(op) => op.eval(left, right),
|
||||
|
|
@ -55,10 +56,10 @@ impl BinOp {
|
|||
}
|
||||
|
||||
impl RelationOp {
|
||||
fn eval(&self, a: &AstNode, b: &AstNode) -> ExprResult<String> {
|
||||
fn eval(&self, a: &AstNode, b: &AstNode) -> ExprResult<NumOrStr> {
|
||||
let a = a.eval()?;
|
||||
let b = b.eval()?;
|
||||
let b = if let (Ok(a), Ok(b)) = (a.parse::<BigInt>(), b.parse::<BigInt>()) {
|
||||
let b = if let (Ok(a), Ok(b)) = (&a.to_bigint(), &b.to_bigint()) {
|
||||
match self {
|
||||
Self::Lt => a < b,
|
||||
Self::Leq => a <= b,
|
||||
|
|
@ -79,24 +80,18 @@ impl RelationOp {
|
|||
}
|
||||
};
|
||||
if b {
|
||||
Ok("1".into())
|
||||
Ok(1.into())
|
||||
} else {
|
||||
Ok("0".into())
|
||||
Ok(0.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NumericOp {
|
||||
fn eval(&self, left: &AstNode, right: &AstNode) -> ExprResult<String> {
|
||||
let a: BigInt = left
|
||||
.eval()?
|
||||
.parse()
|
||||
.map_err(|_| ExprError::NonIntegerArgument)?;
|
||||
let b: BigInt = right
|
||||
.eval()?
|
||||
.parse()
|
||||
.map_err(|_| ExprError::NonIntegerArgument)?;
|
||||
Ok(match self {
|
||||
fn eval(&self, left: &AstNode, right: &AstNode) -> ExprResult<NumOrStr> {
|
||||
let a = left.eval()?.eval_as_bigint()?;
|
||||
let b = right.eval()?.eval_as_bigint()?;
|
||||
Ok(NumOrStr::Num(match self {
|
||||
Self::Add => a + b,
|
||||
Self::Sub => a - b,
|
||||
Self::Mul => a * b,
|
||||
|
|
@ -110,13 +105,12 @@ impl NumericOp {
|
|||
};
|
||||
a % b
|
||||
}
|
||||
}
|
||||
.to_string())
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl StringOp {
|
||||
fn eval(&self, left: &AstNode, right: &AstNode) -> ExprResult<String> {
|
||||
fn eval(&self, left: &AstNode, right: &AstNode) -> ExprResult<NumOrStr> {
|
||||
match self {
|
||||
Self::Or => {
|
||||
let left = left.eval()?;
|
||||
|
|
@ -127,23 +121,23 @@ impl StringOp {
|
|||
if is_truthy(&right) {
|
||||
return Ok(right);
|
||||
}
|
||||
Ok("0".into())
|
||||
Ok(0.into())
|
||||
}
|
||||
Self::And => {
|
||||
let left = left.eval()?;
|
||||
if !is_truthy(&left) {
|
||||
return Ok("0".into());
|
||||
return Ok(0.into());
|
||||
}
|
||||
let right = right.eval()?;
|
||||
if !is_truthy(&right) {
|
||||
return Ok("0".into());
|
||||
return Ok(0.into());
|
||||
}
|
||||
Ok(left)
|
||||
}
|
||||
Self::Match => {
|
||||
let left = left.eval()?;
|
||||
let right = right.eval()?;
|
||||
let re_string = format!("^{}", &right);
|
||||
let left = left.eval()?.eval_as_string();
|
||||
let right = right.eval()?.eval_as_string();
|
||||
let re_string = format!("^{}", right);
|
||||
let re = Regex::with_options(
|
||||
&re_string,
|
||||
RegexOptions::REGEX_OPTION_NONE,
|
||||
|
|
@ -158,19 +152,20 @@ impl StringOp {
|
|||
} else {
|
||||
re.find(&left)
|
||||
.map_or("0".to_string(), |(start, end)| (end - start).to_string())
|
||||
})
|
||||
}
|
||||
.into())
|
||||
}
|
||||
Self::Index => {
|
||||
let left = left.eval()?;
|
||||
let right = right.eval()?;
|
||||
let left = left.eval()?.eval_as_string();
|
||||
let right = right.eval()?.eval_as_string();
|
||||
for (current_idx, ch_h) in left.chars().enumerate() {
|
||||
for ch_n in right.chars() {
|
||||
for ch_n in right.to_string().chars() {
|
||||
if ch_n == ch_h {
|
||||
return Ok((current_idx + 1).to_string());
|
||||
return Ok((current_idx + 1).into());
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok("0".to_string())
|
||||
Ok(0.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -200,6 +195,55 @@ const PRECEDENCE: &[&[(&str, BinOp)]] = &[
|
|||
&[(":", BinOp::String(StringOp::Match))],
|
||||
];
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Ord, PartialOrd)]
|
||||
pub enum NumOrStr {
|
||||
Num(BigInt),
|
||||
Str(String),
|
||||
}
|
||||
|
||||
impl From<usize> for NumOrStr {
|
||||
fn from(num: usize) -> Self {
|
||||
Self::Num(BigInt::from(num))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BigInt> for NumOrStr {
|
||||
fn from(num: BigInt) -> Self {
|
||||
Self::Num(num)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for NumOrStr {
|
||||
fn from(str: String) -> Self {
|
||||
Self::Str(str)
|
||||
}
|
||||
}
|
||||
|
||||
impl NumOrStr {
|
||||
pub fn to_bigint(&self) -> Result<BigInt, ParseBigIntError> {
|
||||
match self {
|
||||
Self::Num(num) => Ok(num.clone()),
|
||||
Self::Str(str) => str.parse::<BigInt>(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eval_as_bigint(self) -> ExprResult<BigInt> {
|
||||
match self {
|
||||
Self::Num(num) => Ok(num),
|
||||
Self::Str(str) => str
|
||||
.parse::<BigInt>()
|
||||
.map_err(|_| ExprError::NonIntegerArgument),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eval_as_string(self) -> String {
|
||||
match self {
|
||||
Self::Num(num) => num.to_string(),
|
||||
Self::Str(str) => str,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum AstNode {
|
||||
Leaf {
|
||||
|
|
@ -225,9 +269,9 @@ impl AstNode {
|
|||
Parser::new(input).parse()
|
||||
}
|
||||
|
||||
pub fn eval(&self) -> ExprResult<String> {
|
||||
pub fn eval(&self) -> ExprResult<NumOrStr> {
|
||||
match self {
|
||||
Self::Leaf { value } => Ok(value.into()),
|
||||
Self::Leaf { value } => Ok(value.to_string().into()),
|
||||
Self::BinOp {
|
||||
op_type,
|
||||
left,
|
||||
|
|
@ -238,7 +282,7 @@ impl AstNode {
|
|||
pos,
|
||||
length,
|
||||
} => {
|
||||
let string = string.eval()?;
|
||||
let string: String = string.eval()?.eval_as_string();
|
||||
|
||||
// The GNU docs say:
|
||||
//
|
||||
|
|
@ -247,16 +291,31 @@ impl AstNode {
|
|||
//
|
||||
// So we coerce errors into 0 to make that the only case we
|
||||
// have to care about.
|
||||
let pos: usize = pos.eval()?.parse().unwrap_or(0);
|
||||
let length: usize = length.eval()?.parse().unwrap_or(0);
|
||||
let pos = pos
|
||||
.eval()?
|
||||
.eval_as_bigint()
|
||||
.ok()
|
||||
.and_then(|n| n.to_usize())
|
||||
.unwrap_or(0);
|
||||
let length = length
|
||||
.eval()?
|
||||
.eval_as_bigint()
|
||||
.ok()
|
||||
.and_then(|n| n.to_usize())
|
||||
.unwrap_or(0);
|
||||
|
||||
let (Some(pos), Some(_)) = (pos.checked_sub(1), length.checked_sub(1)) else {
|
||||
return Ok(String::new());
|
||||
return Ok(String::new().into());
|
||||
};
|
||||
|
||||
Ok(string.chars().skip(pos).take(length).collect())
|
||||
Ok(string
|
||||
.chars()
|
||||
.skip(pos)
|
||||
.take(length)
|
||||
.collect::<String>()
|
||||
.into())
|
||||
}
|
||||
Self::Length { string } => Ok(string.eval()?.chars().count().to_string()),
|
||||
Self::Length { string } => Ok(string.eval()?.eval_as_string().chars().count().into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -399,21 +458,26 @@ impl<'a> Parser<'a> {
|
|||
/// Determine whether `expr` should evaluate the string as "truthy"
|
||||
///
|
||||
/// Truthy strings are either empty or match the regex "-?0+".
|
||||
pub fn is_truthy(s: &str) -> bool {
|
||||
// Edge case: `-` followed by nothing is truthy
|
||||
if s == "-" {
|
||||
return true;
|
||||
pub fn is_truthy(s: &NumOrStr) -> bool {
|
||||
match s {
|
||||
NumOrStr::Num(num) => num != &BigInt::from(0),
|
||||
NumOrStr::Str(str) => {
|
||||
// Edge case: `-` followed by nothing is truthy
|
||||
if str == "-" {
|
||||
return true;
|
||||
}
|
||||
|
||||
let mut bytes = str.bytes();
|
||||
|
||||
// Empty string is falsy
|
||||
let Some(first) = bytes.next() else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let is_zero = (first == b'-' || first == b'0') && bytes.all(|b| b == b'0');
|
||||
!is_zero
|
||||
}
|
||||
}
|
||||
|
||||
let mut bytes = s.bytes();
|
||||
|
||||
// Empty string is falsy
|
||||
let Some(first) = bytes.next() else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let is_zero = (first == b'-' || first == b'0') && bytes.all(|b| b == b'0');
|
||||
!is_zero
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -8,8 +8,6 @@
|
|||
use std::io::{BufWriter, Stdout, Write};
|
||||
use std::{cmp, i64, mem};
|
||||
|
||||
use uucore::crash;
|
||||
|
||||
use crate::parasplit::{ParaWords, Paragraph, WordInfo};
|
||||
use crate::FmtOptions;
|
||||
|
||||
|
|
@ -363,28 +361,26 @@ fn find_kp_breakpoints<'a, T: Iterator<Item = &'a WordInfo<'a>>>(
|
|||
}
|
||||
|
||||
fn build_best_path<'a>(paths: &[LineBreak<'a>], active: &[usize]) -> Vec<(&'a WordInfo<'a>, bool)> {
|
||||
let mut breakwords = vec![];
|
||||
// of the active paths, we select the one with the fewest demerits
|
||||
let mut best_idx = match active.iter().min_by_key(|&&a| paths[a].demerits) {
|
||||
None => crash!(
|
||||
1,
|
||||
"Failed to find a k-p linebreak solution. This should never happen."
|
||||
),
|
||||
Some(&s) => s,
|
||||
};
|
||||
|
||||
// now, chase the pointers back through the break list, recording
|
||||
// the words at which we should break
|
||||
loop {
|
||||
let next_best = &paths[best_idx];
|
||||
match next_best.linebreak {
|
||||
None => return breakwords,
|
||||
Some(prev) => {
|
||||
breakwords.push((prev, next_best.break_before));
|
||||
best_idx = next_best.prev;
|
||||
active
|
||||
.iter()
|
||||
.min_by_key(|&&a| paths[a].demerits)
|
||||
.map(|&(mut best_idx)| {
|
||||
let mut breakwords = vec![];
|
||||
// now, chase the pointers back through the break list, recording
|
||||
// the words at which we should break
|
||||
loop {
|
||||
let next_best = &paths[best_idx];
|
||||
match next_best.linebreak {
|
||||
None => return breakwords,
|
||||
Some(prev) => {
|
||||
breakwords.push((prev, next_best.break_before));
|
||||
best_idx = next_best.prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
// "infinite" badness is more like (1+BAD_INFTY)^2 because of how demerits are computed
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@ const USAGE: &str = help_usage!("logname.md");
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_ignore();
|
||||
|
||||
let _ = uu_app().try_get_matches_from(args)?;
|
||||
|
||||
match get_userlogin() {
|
||||
|
|
|
|||
|
|
@ -1070,6 +1070,7 @@ pub fn uu_app() -> Command {
|
|||
.about(ABOUT)
|
||||
.infer_long_args(true)
|
||||
.disable_help_flag(true)
|
||||
.args_override_self(true)
|
||||
.arg(
|
||||
Arg::new(options::HELP)
|
||||
.long(options::HELP)
|
||||
|
|
@ -1552,7 +1553,7 @@ pub fn uu_app() -> Command {
|
|||
.short('h')
|
||||
.long(options::size::HUMAN_READABLE)
|
||||
.help("Print human readable file sizes (e.g. 1K 234M 56G).")
|
||||
.overrides_with(options::size::SI)
|
||||
.overrides_with_all([options::size::BLOCK_SIZE, options::size::SI])
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
|
|
@ -1569,6 +1570,7 @@ pub fn uu_app() -> Command {
|
|||
Arg::new(options::size::SI)
|
||||
.long(options::size::SI)
|
||||
.help("Print human readable file sizes using powers of 1000 instead of 1024.")
|
||||
.overrides_with_all([options::size::BLOCK_SIZE, options::size::HUMAN_READABLE])
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
|
|
@ -1576,7 +1578,8 @@ pub fn uu_app() -> Command {
|
|||
.long(options::size::BLOCK_SIZE)
|
||||
.require_equals(true)
|
||||
.value_name("BLOCK_SIZE")
|
||||
.help("scale sizes by BLOCK_SIZE when printing them"),
|
||||
.help("scale sizes by BLOCK_SIZE when printing them")
|
||||
.overrides_with_all([options::size::SI, options::size::HUMAN_READABLE]),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::INODE)
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@ mod options {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_ignore();
|
||||
|
||||
let matches = uu_app().try_get_matches_from(args)?;
|
||||
|
||||
if matches.contains_id(options::CONTEXT) {
|
||||
|
|
|
|||
|
|
@ -68,7 +68,6 @@ fn _mknod(file_name: &str, mode: mode_t, dev: dev_t) -> i32 {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_ignore();
|
||||
// Linux-specific options, not implemented
|
||||
// opts.optflag("Z", "", "set the SELinux security context to default type");
|
||||
// opts.optopt("", "context", "like -Z, or if CTX is specified then set the SELinux or SMACK security context to CTX");
|
||||
|
|
|
|||
|
|
@ -1,57 +0,0 @@
|
|||
// This file is part of the uutils coreutils package.
|
||||
//
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
// spell-checker:ignore (path) osrelease
|
||||
|
||||
use libc::{mode_t, S_IRGRP, S_IROTH, S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR};
|
||||
|
||||
use uucore::mode;
|
||||
|
||||
pub const MODE_RW_UGO: mode_t = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
|
||||
|
||||
pub fn parse_mode(mode: &str) -> Result<mode_t, String> {
|
||||
let result = if mode.chars().any(|c| c.is_ascii_digit()) {
|
||||
mode::parse_numeric(MODE_RW_UGO as u32, mode)
|
||||
} else {
|
||||
mode::parse_symbolic(MODE_RW_UGO as u32, mode, true)
|
||||
};
|
||||
result.map(|mode| mode as mode_t)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
/// Test if the program is running under WSL
|
||||
// ref: <https://github.com/microsoft/WSL/issues/4555> @@ <https://archive.is/dP0bz>
|
||||
// ToDO: test on WSL2 which likely doesn't need special handling; plan change to `is_wsl_1()` if WSL2 is less needy
|
||||
pub fn is_wsl() -> bool {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
if let Ok(b) = std::fs::read("/proc/sys/kernel/osrelease") {
|
||||
if let Ok(s) = std::str::from_utf8(&b) {
|
||||
let a = s.to_ascii_lowercase();
|
||||
return a.contains("microsoft") || a.contains("wsl");
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn symbolic_modes() {
|
||||
assert_eq!(super::parse_mode("u+x").unwrap(), 0o766);
|
||||
assert_eq!(
|
||||
super::parse_mode("+x").unwrap(),
|
||||
if is_wsl() { 0o776 } else { 0o777 }
|
||||
);
|
||||
assert_eq!(super::parse_mode("a-w").unwrap(), 0o444);
|
||||
assert_eq!(super::parse_mode("g-r").unwrap(), 0o626);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn numeric_modes() {
|
||||
assert_eq!(super::parse_mode("644").unwrap(), 0o644);
|
||||
assert_eq!(super::parse_mode("+100").unwrap(), 0o766);
|
||||
assert_eq!(super::parse_mode("-4").unwrap(), 0o662);
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ use uucore::{format_usage, help_about, help_usage};
|
|||
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::ffi::OsStr;
|
||||
use std::fmt::Display;
|
||||
use std::io::ErrorKind;
|
||||
use std::iter;
|
||||
|
|
@ -308,8 +309,7 @@ impl Params {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_lossy();
|
||||
|
||||
let args: Vec<_> = args.collect();
|
||||
let matches = match uu_app().try_get_matches_from(&args) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
|
|
@ -333,7 +333,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
|||
// If POSIXLY_CORRECT was set, template MUST be the last argument.
|
||||
if matches.contains_id(ARG_TEMPLATE) {
|
||||
// Template argument was provided, check if was the last one.
|
||||
if args.last().unwrap() != &options.template {
|
||||
if args.last().unwrap() != OsStr::new(&options.template) {
|
||||
return Err(Box::new(MkTempError::TooManyTemplates));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,7 +87,6 @@ impl Options {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_lossy();
|
||||
let matches = match uu_app().try_get_matches_from(args) {
|
||||
Ok(m) => m,
|
||||
Err(e) => return Err(e.into()),
|
||||
|
|
|
|||
|
|
@ -178,8 +178,6 @@ pub mod options {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_lossy();
|
||||
|
||||
let matches = uu_app().try_get_matches_from(args)?;
|
||||
|
||||
let mut settings = Settings::default();
|
||||
|
|
|
|||
|
|
@ -74,8 +74,6 @@ impl Display for NohupError {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_lossy();
|
||||
|
||||
let matches = uu_app().try_get_matches_from(args).with_exit_code(125)?;
|
||||
|
||||
replace_fds()?;
|
||||
|
|
|
|||
|
|
@ -36,8 +36,6 @@ const POSIX_NAME_MAX: usize = 14;
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_lossy();
|
||||
|
||||
let matches = uu_app().try_get_matches_from(args)?;
|
||||
|
||||
// set working mode
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ mod options {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_ignore();
|
||||
let matches = uu_app().get_matches_from(args);
|
||||
|
||||
let format_string = matches
|
||||
|
|
|
|||
|
|
@ -715,8 +715,6 @@ mod options {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_ignore();
|
||||
|
||||
let matches = uu_app().try_get_matches_from(args)?;
|
||||
|
||||
let mut input_files: Vec<String> = match &matches.get_many::<String>(options::FILE) {
|
||||
|
|
|
|||
|
|
@ -200,8 +200,6 @@ impl BytesWriter {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_ignore();
|
||||
|
||||
let matches = uu_app().try_get_matches_from(args)?;
|
||||
|
||||
if !matches.contains_id(options::FILE) {
|
||||
|
|
|
|||
|
|
@ -47,8 +47,6 @@ mod options {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_lossy();
|
||||
|
||||
let matches = uu_app().try_get_matches_from(args)?;
|
||||
|
||||
let mode = if let Some(args) = matches.get_many::<String>(options::ECHO) {
|
||||
|
|
|
|||
|
|
@ -1029,7 +1029,6 @@ fn make_sort_mode_arg(mode: &'static str, short: char, help: &'static str) -> Ar
|
|||
#[uucore::main]
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_ignore();
|
||||
let mut settings = GlobalSettings::default();
|
||||
|
||||
let matches = match uu_app().try_get_matches_from(args) {
|
||||
|
|
|
|||
|
|
@ -141,8 +141,6 @@ fn get_preload_env(tmp_dir: &TempDir) -> UResult<(String, PathBuf)> {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_ignore();
|
||||
|
||||
let matches = uu_app().try_get_matches_from(args)?;
|
||||
|
||||
let options = ProgramOptions::try_from(&matches).map_err(|e| UUsageError::new(125, e.0))?;
|
||||
|
|
|
|||
|
|
@ -176,8 +176,6 @@ ioctl_write_ptr_bad!(
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_lossy();
|
||||
|
||||
let matches = uu_app().try_get_matches_from(args)?;
|
||||
|
||||
let opts = Options::from(&matches)?;
|
||||
|
|
|
|||
|
|
@ -102,8 +102,6 @@ mod options {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_lossy();
|
||||
|
||||
let matches = uu_app().try_get_matches_from(args)?;
|
||||
|
||||
let files: Vec<String> = match matches.get_many::<String>(options::FILE) {
|
||||
|
|
|
|||
|
|
@ -33,8 +33,6 @@ mod options {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_lossy();
|
||||
|
||||
let matches = uu_app().try_get_matches_from(args)?;
|
||||
|
||||
let before = matches.get_flag(options::BEFORE);
|
||||
|
|
|
|||
|
|
@ -107,8 +107,6 @@ impl Config {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_lossy();
|
||||
|
||||
let matches = uu_app().try_get_matches_from(args).with_exit_code(125)?;
|
||||
|
||||
let config = Config::from(&matches)?;
|
||||
|
|
|
|||
|
|
@ -33,8 +33,6 @@ mod options {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_lossy();
|
||||
|
||||
let matches = uu_app().after_help(AFTER_HELP).try_get_matches_from(args)?;
|
||||
|
||||
let delete_flag = matches.get_flag(options::DELETE);
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@ mod options {
|
|||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_lossy();
|
||||
|
||||
let matches = uu_app().try_get_matches_from(args)?;
|
||||
|
||||
let input = matches
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue