mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-27 19:17:43 +00:00
Merge pull request #1110 from Arcterus/mode-to-uucore
chmod, install, mknod: move mode parsing into uucore
This commit is contained in:
commit
7967f3aec7
78 changed files with 298 additions and 673 deletions
|
@ -13,11 +13,11 @@ extern crate uucore;
|
|||
use uucore::encoding::{Data, Format, wrap_print};
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, Read, stdin, Write};
|
||||
use std::io::{BufReader, Read, stdin};
|
||||
use std::path::Path;
|
||||
|
||||
static SYNTAX: &'static str = "[OPTION]... [FILE]";
|
||||
static SUMMARY: &'static str = "Base32 encode or decode FILE, or standard input, to standard output.";
|
||||
static SYNTAX: &'static str = "[OPTION]... [FILE]";
|
||||
static SUMMARY: &'static str = "Base32 encode or decode FILE, or standard input, to standard output.";
|
||||
static LONG_HELP: &'static str = "
|
||||
With no FILE, or when FILE is -, read standard input.
|
||||
|
||||
|
@ -39,7 +39,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
"wrap encoded lines after COLS character (default 76, 0 to disable wrapping)",
|
||||
"COLS")
|
||||
.parse(args);
|
||||
|
||||
|
||||
let line_wrap = match matches.opt_str("wrap") {
|
||||
Some(s) => {
|
||||
match s.parse() {
|
||||
|
|
|
@ -15,11 +15,11 @@ extern crate uucore;
|
|||
use uucore::encoding::{Data, Format, wrap_print};
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, Read, stdin, Write};
|
||||
use std::io::{BufReader, Read, stdin};
|
||||
use std::path::Path;
|
||||
|
||||
static SYNTAX: &'static str = "[OPTION]... [FILE]";
|
||||
static SUMMARY: &'static str = "Base64 encode or decode FILE, or standard input, to standard output.";
|
||||
static SYNTAX: &'static str = "[OPTION]... [FILE]";
|
||||
static SUMMARY: &'static str = "Base64 encode or decode FILE, or standard input, to standard output.";
|
||||
static LONG_HELP: &'static str = "
|
||||
With no FILE, or when FILE is -, read standard input.
|
||||
|
||||
|
|
|
@ -12,13 +12,12 @@
|
|||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use std::io::Write;
|
||||
use std::path::{is_separator, PathBuf};
|
||||
|
||||
static NAME: &'static str = "basename";
|
||||
static SYNTAX: &'static str = "NAME [SUFFIX]";
|
||||
static SYNTAX: &'static str = "NAME [SUFFIX]";
|
||||
static SUMMARY: &'static str = "Print NAME with any leading directory components removed
|
||||
If specified, also remove a trailing SUFFIX";
|
||||
If specified, also remove a trailing SUFFIX";
|
||||
static LONG_HELP: &'static str = "";
|
||||
|
||||
pub fn uumain(args: Vec<String>) -> i32 {
|
||||
|
|
|
@ -17,7 +17,6 @@ use uucore::fs::resolve_relative_path;
|
|||
extern crate walkdir;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
use std::io::prelude::*;
|
||||
use std::io::Result as IOResult;
|
||||
use std::io::Error as IOError;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
* (c) Arcterus <arcterus@mail.com>
|
||||
* (c) Alex Lyon <arcterus@mail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
@ -16,16 +16,16 @@ extern crate walker;
|
|||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use std::error::Error;
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::os::unix::fs::{MetadataExt, PermissionsExt};
|
||||
use std::path::Path;
|
||||
use walker::Walker;
|
||||
#[cfg(not(windows))]
|
||||
use uucore::mode;
|
||||
|
||||
const NAME: &'static str = "chmod";
|
||||
static SUMMARY: &'static str = "Change the mode of each FILE to MODE.
|
||||
With --reference, change the mode of each FILE to that of RFILE.";
|
||||
With --reference, change the mode of each FILE to that of RFILE.";
|
||||
static LONG_HELP: &'static str = "
|
||||
Each MODE is of the form '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+'.
|
||||
";
|
||||
|
@ -197,9 +197,9 @@ impl Chmoder {
|
|||
let arr: &[char] = &['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
|
||||
let result =
|
||||
if mode.contains(arr) {
|
||||
self.parse_numeric(fperm, mode)
|
||||
mode::parse_numeric(fperm, mode)
|
||||
} else {
|
||||
self.parse_symbolic(fperm, mode, file)
|
||||
mode::parse_symbolic(fperm, mode, file.is_dir())
|
||||
};
|
||||
match result {
|
||||
Ok(mode) => {
|
||||
|
@ -220,126 +220,6 @@ impl Chmoder {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_numeric(&self, fperm: u32, mut mode: &str) -> Result<u32, String> {
|
||||
let (op, pos) = try!(self.parse_op(mode, Some('=')));
|
||||
mode = mode[pos..].trim_left_matches('0');
|
||||
if mode.len() > 4 {
|
||||
Err(format!("mode is too large ({} > 7777)", mode))
|
||||
} else {
|
||||
match u32::from_str_radix(mode, 8) {
|
||||
Ok(change) => {
|
||||
Ok(match op {
|
||||
'+' => fperm | change,
|
||||
'-' => fperm & !change,
|
||||
'=' => change,
|
||||
_ => unreachable!()
|
||||
})
|
||||
}
|
||||
Err(err) => Err(err.description().to_owned())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_symbolic(&self, mut fperm: u32, mut mode: &str, file: &Path) -> Result<u32, String> {
|
||||
#[cfg(unix)]
|
||||
use libc::umask;
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
unsafe fn umask(_mask: u32) -> u32 {
|
||||
// XXX Redox does not currently have umask
|
||||
0
|
||||
}
|
||||
|
||||
let (mask, pos) = self.parse_levels(mode);
|
||||
if pos == mode.len() {
|
||||
return Err(format!("invalid mode ({})", mode));
|
||||
}
|
||||
let respect_umask = pos == 0;
|
||||
let last_umask = unsafe {
|
||||
umask(0)
|
||||
};
|
||||
mode = &mode[pos..];
|
||||
while mode.len() > 0 {
|
||||
let (op, pos) = try!(self.parse_op(mode, None));
|
||||
mode = &mode[pos..];
|
||||
let (mut srwx, pos) = self.parse_change(mode, fperm, file);
|
||||
if respect_umask {
|
||||
srwx &= !(last_umask as u32);
|
||||
}
|
||||
mode = &mode[pos..];
|
||||
match op {
|
||||
'+' => fperm |= srwx & mask,
|
||||
'-' => fperm &= !(srwx & mask),
|
||||
'=' => fperm = (fperm & !mask) | (srwx & mask),
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
umask(last_umask);
|
||||
}
|
||||
Ok(fperm)
|
||||
}
|
||||
|
||||
fn parse_levels(&self, mode: &str) -> (u32, usize) {
|
||||
let mut mask = 0;
|
||||
let mut pos = 0;
|
||||
for ch in mode.chars() {
|
||||
mask |= match ch {
|
||||
'u' => 0o7700,
|
||||
'g' => 0o7070,
|
||||
'o' => 0o7007,
|
||||
'a' => 0o7777,
|
||||
_ => break
|
||||
};
|
||||
pos += 1;
|
||||
}
|
||||
if pos == 0 {
|
||||
mask = 0o7777; // default to 'a'
|
||||
}
|
||||
(mask, pos)
|
||||
}
|
||||
|
||||
fn parse_op(&self, mode: &str, default: Option<char>) -> Result<(char, usize), String> {
|
||||
match mode.chars().next() {
|
||||
Some(ch) => match ch {
|
||||
'+' | '-' | '=' => Ok((ch, 1)),
|
||||
_ => match default {
|
||||
Some(ch) => Ok((ch, 0)),
|
||||
None => Err(format!("invalid operator (expected +, -, or =, but found {})", ch))
|
||||
}
|
||||
},
|
||||
None => Err("unexpected end of mode".to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_change(&self, mode: &str, fperm: u32, file: &Path) -> (u32, usize) {
|
||||
let mut srwx = fperm & 0o7000;
|
||||
let mut pos = 0;
|
||||
for ch in mode.chars() {
|
||||
match ch {
|
||||
'r' => srwx |= 0o444,
|
||||
'w' => srwx |= 0o222,
|
||||
'x' => srwx |= 0o111,
|
||||
'X' => {
|
||||
if file.is_dir() || (fperm & 0o0111) != 0 {
|
||||
srwx |= 0o111
|
||||
}
|
||||
}
|
||||
's' => srwx |= 0o4000 | 0o2000,
|
||||
't' => srwx |= 0o1000,
|
||||
'u' => srwx = (fperm & 0o700) | ((fperm >> 3) & 0o070) | ((fperm >> 6) & 0o007),
|
||||
'g' => srwx = ((fperm << 3) & 0o700) | (fperm & 0o070) | ((fperm >> 3) & 0o007),
|
||||
'o' => srwx = ((fperm << 6) & 0o700) | ((fperm << 3) & 0o070) | (fperm & 0o007),
|
||||
_ => break
|
||||
};
|
||||
pos += 1;
|
||||
}
|
||||
if pos == 0 {
|
||||
srwx = 0;
|
||||
}
|
||||
(srwx, pos)
|
||||
}
|
||||
|
||||
fn change_file(&self, fperm: u32, mode: u32, file: &Path, path: &str) -> Result<(), i32> {
|
||||
if fperm == mode {
|
||||
if self.verbose && !self.changes {
|
||||
|
|
|
@ -23,7 +23,7 @@ use walkdir::WalkDir;
|
|||
use std::fs::{self, Metadata};
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
|
||||
use std::io::{self, Write};
|
||||
use std::io;
|
||||
use std::io::Result as IOResult;
|
||||
|
||||
use std::path::Path;
|
||||
|
|
|
@ -18,18 +18,18 @@ use uucore::libc::{self, setgid, setuid, chroot, setgroups};
|
|||
use uucore::entries;
|
||||
|
||||
use std::ffi::CString;
|
||||
use std::io::{Error, Write};
|
||||
use std::io::Error;
|
||||
use std::iter::FromIterator;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
static NAME: &'static str = "chroot";
|
||||
static SYNTAX: &'static str = "[OPTION]... NEWROOT [COMMAND [ARG]...]";
|
||||
static SUMMARY: &'static str = "Run COMMAND with root directory set to NEWROOT.";
|
||||
static SYNTAX: &'static str = "[OPTION]... NEWROOT [COMMAND [ARG]...]";
|
||||
static SUMMARY: &'static str = "Run COMMAND with root directory set to NEWROOT.";
|
||||
static LONG_HELP: &'static str = "
|
||||
If COMMAND is not specified, it defaults to '$(SHELL) -i'.
|
||||
If $(SHELL) is not set, /bin/sh is used.
|
||||
";
|
||||
";
|
||||
|
||||
pub fn uumain(args: Vec<String>) -> i32 {
|
||||
let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
* (c) Arcterus <arcterus@mail.com>
|
||||
* (c) Alex Lyon <arcterus@mail.com>
|
||||
* (c) Michael Gehring <mg@ebfe.org>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
|
|
|
@ -14,16 +14,16 @@
|
|||
extern crate uucore;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{self, stdin, Read, Write, BufReader};
|
||||
use std::io::{self, stdin, Read, BufReader};
|
||||
#[cfg(not(windows))]
|
||||
use std::mem;
|
||||
use std::path::Path;
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/crc_table.rs"));
|
||||
|
||||
static SYNTAX: &'static str = "[OPTIONS] [FILE]...";
|
||||
static SUMMARY: &'static str = "Print CRC and size for each file";
|
||||
static LONG_HELP: &'static str = "";
|
||||
static SYNTAX: &'static str = "[OPTIONS] [FILE]...";
|
||||
static SUMMARY: &'static str = "Print CRC and size for each file";
|
||||
static LONG_HELP: &'static str = "";
|
||||
|
||||
#[inline]
|
||||
fn crc_update(crc: u32, input: u8) -> u32 {
|
||||
|
|
10
src/cp/cp.rs
10
src/cp/cp.rs
|
@ -39,7 +39,7 @@ use clap::{Arg, App, ArgMatches};
|
|||
use quick_error::ResultExt;
|
||||
use std::collections::HashSet;
|
||||
use std::fs;
|
||||
use std::io::{BufReader, BufRead, stdin, Write};
|
||||
use std::io::{BufReader, BufRead, stdin, stdout, Write};
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf, StripPrefixError};
|
||||
use std::str::FromStr;
|
||||
|
@ -114,9 +114,9 @@ macro_rules! or_continue(
|
|||
/// answered yes.
|
||||
macro_rules! prompt_yes(
|
||||
($($args:tt)+) => ({
|
||||
pipe_write!(&mut ::std::io::stdout(), $($args)+);
|
||||
pipe_write!(&mut ::std::io::stdout(), " [y/N]: ");
|
||||
pipe_flush!();
|
||||
print!($($args)+);
|
||||
print!(" [y/N]: ");
|
||||
crash_if_err!(1, stdout().flush());
|
||||
let mut s = String::new();
|
||||
match BufReader::new(stdin()).read_line(&mut s) {
|
||||
Ok(_) => match s.char_indices().nth(0) {
|
||||
|
@ -573,7 +573,7 @@ impl Options {
|
|||
attributes.push(Attribute::Xattr);
|
||||
attributes.push(Attribute::Links);
|
||||
break;
|
||||
} else {
|
||||
} else {
|
||||
attributes.push(Attribute::from_str(attribute_str)?);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@ impl<R: Read> self::Bytes::Select for ByteReader<R> {
|
|||
};
|
||||
|
||||
match out {
|
||||
Some(out) => pipe_crash_if_err!(1, out.write_all(&buffer[0..consume_val])),
|
||||
Some(out) => crash_if_err!(1, out.write_all(&buffer[0..consume_val])),
|
||||
None => (),
|
||||
}
|
||||
(res, consume_val)
|
||||
|
|
|
@ -150,7 +150,7 @@ fn cut_bytes<R: Read>(reader: R, ranges: &[Range], opts: &Options) -> i32 {
|
|||
loop {
|
||||
match buf_read.select(low - cur_pos, None::<&mut Stdout>) {
|
||||
NewlineFound => {
|
||||
pipe_crash_if_err!(1, out.write_all(&[newline_char]));
|
||||
crash_if_err!(1, out.write_all(&[newline_char]));
|
||||
continue 'newline
|
||||
}
|
||||
Complete(len) => {
|
||||
|
@ -160,7 +160,7 @@ fn cut_bytes<R: Read>(reader: R, ranges: &[Range], opts: &Options) -> i32 {
|
|||
Partial(len) => cur_pos += len,
|
||||
EndOfFile => {
|
||||
if orig_pos != cur_pos {
|
||||
pipe_crash_if_err!(1, out.write_all(&[newline_char]));
|
||||
crash_if_err!(1, out.write_all(&[newline_char]));
|
||||
}
|
||||
|
||||
break 'newline
|
||||
|
@ -171,7 +171,7 @@ fn cut_bytes<R: Read>(reader: R, ranges: &[Range], opts: &Options) -> i32 {
|
|||
match opts.out_delim {
|
||||
Some(ref delim) => {
|
||||
if print_delim {
|
||||
pipe_crash_if_err!(1, out.write_all(delim.as_bytes()));
|
||||
crash_if_err!(1, out.write_all(delim.as_bytes()));
|
||||
}
|
||||
print_delim = true;
|
||||
}
|
||||
|
@ -189,7 +189,7 @@ fn cut_bytes<R: Read>(reader: R, ranges: &[Range], opts: &Options) -> i32 {
|
|||
}
|
||||
EndOfFile => {
|
||||
if cur_pos != low || low == high {
|
||||
pipe_crash_if_err!(1, out.write_all(&[newline_char]));
|
||||
crash_if_err!(1, out.write_all(&[newline_char]));
|
||||
}
|
||||
|
||||
break 'newline
|
||||
|
@ -199,7 +199,7 @@ fn cut_bytes<R: Read>(reader: R, ranges: &[Range], opts: &Options) -> i32 {
|
|||
}
|
||||
|
||||
buf_read.consume_line();
|
||||
pipe_crash_if_err!(1, out.write_all(&[newline_char]));
|
||||
crash_if_err!(1, out.write_all(&[newline_char]));
|
||||
}
|
||||
|
||||
0
|
||||
|
@ -230,9 +230,9 @@ fn cut_fields_delimiter<R: Read>(reader: R, ranges: &[Range], delim: &str, only_
|
|||
|
||||
if delim_search.peek().is_none() {
|
||||
if ! only_delimited {
|
||||
pipe_crash_if_err!(1, out.write_all(line));
|
||||
crash_if_err!(1, out.write_all(line));
|
||||
if line[line.len() - 1] != newline_char {
|
||||
pipe_crash_if_err!(1, out.write_all(&[newline_char]));
|
||||
crash_if_err!(1, out.write_all(&[newline_char]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -249,14 +249,14 @@ fn cut_fields_delimiter<R: Read>(reader: R, ranges: &[Range], delim: &str, only_
|
|||
|
||||
for _ in 0..high - low + 1 {
|
||||
if print_delim {
|
||||
pipe_crash_if_err!(1, out.write_all(out_delim.as_bytes()));
|
||||
crash_if_err!(1, out.write_all(out_delim.as_bytes()));
|
||||
}
|
||||
|
||||
match delim_search.next() {
|
||||
Some((high_idx, next_low_idx)) => {
|
||||
let segment = &line[low_idx..high_idx];
|
||||
|
||||
pipe_crash_if_err!(1, out.write_all(segment));
|
||||
crash_if_err!(1, out.write_all(segment));
|
||||
|
||||
print_delim = true;
|
||||
|
||||
|
@ -266,7 +266,7 @@ fn cut_fields_delimiter<R: Read>(reader: R, ranges: &[Range], delim: &str, only_
|
|||
None => {
|
||||
let segment = &line[low_idx..];
|
||||
|
||||
pipe_crash_if_err!(1, out.write_all(segment));
|
||||
crash_if_err!(1, out.write_all(segment));
|
||||
|
||||
if line[line.len() - 1] == newline_char {
|
||||
continue 'newline
|
||||
|
@ -277,7 +277,7 @@ fn cut_fields_delimiter<R: Read>(reader: R, ranges: &[Range], delim: &str, only_
|
|||
}
|
||||
}
|
||||
|
||||
pipe_crash_if_err!(1, out.write_all(&[newline_char]));
|
||||
crash_if_err!(1, out.write_all(&[newline_char]));
|
||||
}
|
||||
|
||||
0
|
||||
|
@ -318,9 +318,9 @@ fn cut_fields<R: Read>(reader: R, ranges: &[Range], opts: &FieldOptions) -> i32
|
|||
|
||||
if delim_search.peek().is_none() {
|
||||
if ! opts.only_delimited {
|
||||
pipe_crash_if_err!(1, out.write_all(line));
|
||||
crash_if_err!(1, out.write_all(line));
|
||||
if line[line.len() - 1] != newline_char {
|
||||
pipe_crash_if_err!(1, out.write_all(&[newline_char]));
|
||||
crash_if_err!(1, out.write_all(&[newline_char]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -345,7 +345,7 @@ fn cut_fields<R: Read>(reader: R, ranges: &[Range], opts: &FieldOptions) -> i32
|
|||
Some((high_idx, next_low_idx)) => {
|
||||
let segment = &line[low_idx..high_idx];
|
||||
|
||||
pipe_crash_if_err!(1, out.write_all(segment));
|
||||
crash_if_err!(1, out.write_all(segment));
|
||||
|
||||
print_delim = true;
|
||||
low_idx = next_low_idx;
|
||||
|
@ -354,7 +354,7 @@ fn cut_fields<R: Read>(reader: R, ranges: &[Range], opts: &FieldOptions) -> i32
|
|||
None => {
|
||||
let segment = &line[low_idx..line.len()];
|
||||
|
||||
pipe_crash_if_err!(1, out.write_all(segment));
|
||||
crash_if_err!(1, out.write_all(segment));
|
||||
|
||||
if line[line.len() - 1] == newline_char {
|
||||
continue 'newline
|
||||
|
@ -364,7 +364,7 @@ fn cut_fields<R: Read>(reader: R, ranges: &[Range], opts: &FieldOptions) -> i32
|
|||
}
|
||||
}
|
||||
|
||||
pipe_crash_if_err!(1, out.write_all(&[newline_char]));
|
||||
crash_if_err!(1, out.write_all(&[newline_char]));
|
||||
}
|
||||
|
||||
0
|
||||
|
|
|
@ -13,19 +13,18 @@ extern crate glob;
|
|||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Write};
|
||||
use std::io::{BufRead, BufReader};
|
||||
use std::borrow::Borrow;
|
||||
use std::env;
|
||||
|
||||
static SYNTAX: &'static str = "[OPTION]... [FILE]";
|
||||
static SUMMARY: &'static str = "Output commands to set the LS_COLORS environment variable.";
|
||||
static SUMMARY: &'static str = "Output commands to set the LS_COLORS environment variable.";
|
||||
static LONG_HELP: &'static str = "
|
||||
If FILE is specified, read it to determine which colors to use for which
|
||||
file types and extensions. Otherwise, a precompiled database is used.
|
||||
For details on the format of these files, run 'dircolors --print-database'
|
||||
";
|
||||
";
|
||||
|
||||
mod colors;
|
||||
use colors::INTERNAL_DB;
|
||||
|
|
|
@ -12,12 +12,12 @@
|
|||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use std::io::Write;
|
||||
use std::io::{Write, stdout};
|
||||
use std::str::from_utf8;
|
||||
|
||||
#[allow(dead_code)]
|
||||
static SYNTAX: &'static str = "[OPTIONS]... [STRING]...";
|
||||
static SUMMARY: &'static str = "display a line of text";
|
||||
static SYNTAX: &'static str = "[OPTIONS]... [STRING]...";
|
||||
static SUMMARY: &'static str = "display a line of text";
|
||||
static LONG_HELP: &'static str = r#"
|
||||
Echo the STRING(s) to standard output.
|
||||
If -e is in effect, the following sequences are recognized:
|
||||
|
@ -34,7 +34,7 @@ static LONG_HELP: &'static str = r#"
|
|||
\\v vertical tab
|
||||
\\0NNN byte with octal value NNN (1 to 3 digits)
|
||||
\\xHH byte with hexadecimal value HH (1 to 2 digits)
|
||||
"#;
|
||||
"#;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct EchoOptions {
|
||||
|
@ -173,7 +173,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
}
|
||||
|
||||
if options.newline {
|
||||
pipe_flush!();
|
||||
return_if_err!(1, stdout().flush())
|
||||
} else {
|
||||
println!("")
|
||||
}
|
||||
|
|
14
src/env/env.rs
vendored
14
src/env/env.rs
vendored
|
@ -17,15 +17,15 @@
|
|||
extern crate uucore;
|
||||
|
||||
use std::env;
|
||||
use std::io::Write;
|
||||
use std::io::{Write, stdout};
|
||||
use std::process::Command;
|
||||
|
||||
static NAME: &'static str = "env";
|
||||
static SYNTAX: &'static str = "[OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]";
|
||||
static SUMMARY: &'static str = "Set each NAME to VALUE in the environment and run COMMAND";
|
||||
static NAME: &'static str = "env";
|
||||
static SYNTAX: &'static str = "[OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]";
|
||||
static SUMMARY: &'static str = "Set each NAME to VALUE in the environment and run COMMAND";
|
||||
static LONG_HELP: &'static str = "
|
||||
A mere - implies -i. If no COMMAND, print the resulting environment
|
||||
";
|
||||
";
|
||||
|
||||
struct options {
|
||||
ignore_env: bool,
|
||||
|
@ -48,7 +48,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
core_opts.optflag("i", "ignore-environment", "start with an empty environment")
|
||||
.optflag("0", "null", "end each output line with a 0 byte rather than newline")
|
||||
.optopt("u", "unset", "remove variable from the environment", "NAME");
|
||||
|
||||
|
||||
let mut opts = Box::new(options {
|
||||
ignore_env: false,
|
||||
null: false,
|
||||
|
@ -189,7 +189,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
} else {
|
||||
// no program provided
|
||||
print_env(opts.null);
|
||||
pipe_flush!();
|
||||
return_if_err!(1, stdout().flush());
|
||||
}
|
||||
|
||||
0
|
||||
|
|
|
@ -16,8 +16,6 @@ extern crate onig;
|
|||
mod tokens;
|
||||
mod syntax_tree;
|
||||
|
||||
use std::io::{Write};
|
||||
|
||||
static NAME: &'static str = "expr";
|
||||
static VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ extern crate uucore;
|
|||
use numeric::*;
|
||||
use rand::distributions::{Range, IndependentSample};
|
||||
use std::cmp::{max, min};
|
||||
use std::io::{stdin, BufRead, BufReader, Write};
|
||||
use std::io::{stdin, BufRead, BufReader};
|
||||
use std::num::Wrapping;
|
||||
use std::mem::swap;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
* (c) Arcterus <arcterus@mail.com>
|
||||
* (c) Alex Lyon <arcterus@mail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
@ -13,13 +13,13 @@
|
|||
extern crate uucore;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Read, stdin, Write};
|
||||
use std::io::{BufRead, BufReader, Read, stdin};
|
||||
use std::path::Path;
|
||||
|
||||
static SYNTAX: &'static str = "[OPTION]... [FILE]...";
|
||||
static SUMMARY: &'static str = "Writes each file (or standard input if no files are given)
|
||||
to standard output whilst breaking long lines";
|
||||
static LONG_HELP: &'static str = "";
|
||||
static SYNTAX: &'static str = "[OPTION]... [FILE]...";
|
||||
static SUMMARY: &'static str = "Writes each file (or standard input if no files are given)
|
||||
to standard output whilst breaking long lines";
|
||||
static LONG_HELP: &'static str = "";
|
||||
|
||||
pub fn uumain(args: Vec<String>) -> i32 {
|
||||
let (args, obs_width) = handle_obsolete(&args[..]);
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#[macro_use]
|
||||
extern crate uucore;
|
||||
use uucore::entries::{Passwd, Locate, get_groups, gid2grp};
|
||||
use std::io::Write;
|
||||
|
||||
static SYNTAX: &'static str = "[user]";
|
||||
static SUMMARY: &'static str = "display current group names";
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
* (c) Arcterus <arcterus@mail.com>
|
||||
* (c) Alex Lyon <arcterus@mail.com>
|
||||
* (c) Vsevolod Velichko <torkvemada@sorokdva.net>
|
||||
* (c) Gil Cottle <gcottle@redtown.org>
|
||||
*
|
||||
|
@ -34,7 +34,7 @@ use sha2::{Sha224, Sha256, Sha384, Sha512};
|
|||
use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512, Shake128, Shake256};
|
||||
use std::ascii::AsciiExt;
|
||||
use std::fs::File;
|
||||
use std::io::{self, BufRead, BufReader, Read, stdin, Write};
|
||||
use std::io::{self, BufRead, BufReader, Read, stdin};
|
||||
use std::path::Path;
|
||||
|
||||
static NAME: &'static str = "hashsum";
|
||||
|
@ -232,7 +232,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
}
|
||||
|
||||
fn version() {
|
||||
pipe_println!("{} {}", NAME, VERSION);
|
||||
println!("{} {}", NAME, VERSION);
|
||||
}
|
||||
|
||||
fn usage(program: &str, binary_name: &str, opts: &getopts::Options) {
|
||||
|
@ -251,7 +251,7 @@ Usage:
|
|||
|
||||
Compute and check message digests.", NAME, VERSION, spec);
|
||||
|
||||
pipe_print!("{}", opts.usage(&msg));
|
||||
print!("{}", opts.usage(&msg));
|
||||
}
|
||||
|
||||
fn hashsum(algoname: &str, mut digest: Box<Digest>, files: Vec<String>, binary: bool, check: bool, tag: bool, status: bool, quiet: bool, strict: bool, warn: bool, output_bits: usize) -> Result<(), i32> {
|
||||
|
@ -325,11 +325,11 @@ fn hashsum(algoname: &str, mut digest: Box<Digest>, files: Vec<String>, binary:
|
|||
.to_ascii_lowercase();
|
||||
if sum == real_sum {
|
||||
if !quiet {
|
||||
pipe_println!("{}: OK", ck_filename);
|
||||
println!("{}: OK", ck_filename);
|
||||
}
|
||||
} else {
|
||||
if !status {
|
||||
pipe_println!("{}: FAILED", ck_filename);
|
||||
println!("{}: FAILED", ck_filename);
|
||||
}
|
||||
failed += 1;
|
||||
}
|
||||
|
@ -337,9 +337,9 @@ fn hashsum(algoname: &str, mut digest: Box<Digest>, files: Vec<String>, binary:
|
|||
} else {
|
||||
let sum = safe_unwrap!(digest_reader(&mut digest, &mut file, binary, output_bits));
|
||||
if tag {
|
||||
pipe_println!("{} ({}) = {}", algoname, filename, sum);
|
||||
println!("{} ({}) = {}", algoname, filename, sum);
|
||||
} else {
|
||||
pipe_println!("{} {}{}", sum, binary_marker, filename);
|
||||
println!("{} {}{}", sum, binary_marker, filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use std::io::{BufRead, BufReader, Read, stdin, Write};
|
||||
use std::io::{BufRead, BufReader, Read, stdin};
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
use std::str::from_utf8;
|
||||
|
@ -115,8 +115,8 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
|
||||
for file in &files {
|
||||
if settings.verbose {
|
||||
if !firstime { pipe_println!(""); }
|
||||
pipe_println!("==> {} <==", file);
|
||||
if !firstime { println!(""); }
|
||||
println!("==> {} <==", file);
|
||||
}
|
||||
firstime = false;
|
||||
|
||||
|
@ -171,16 +171,12 @@ fn head<T: Read>(reader: &mut BufReader<T>, settings: &Settings) -> bool {
|
|||
match settings.mode {
|
||||
FilterMode::Bytes(count) => {
|
||||
for byte in reader.bytes().take(count) {
|
||||
if !pipe_print!("{}", byte.unwrap() as char) {
|
||||
return false;
|
||||
}
|
||||
print!("{}", byte.unwrap() as char);
|
||||
}
|
||||
},
|
||||
FilterMode::Lines(count) => {
|
||||
for line in reader.lines().take(count) {
|
||||
if !pipe_println!("{}", line.unwrap()) {
|
||||
return false;
|
||||
}
|
||||
println!("{}", line.unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,12 +21,11 @@ extern crate uucore;
|
|||
use std::collections::hash_set::HashSet;
|
||||
use std::iter::repeat;
|
||||
use std::str;
|
||||
use std::io::Write;
|
||||
use std::net::ToSocketAddrs;
|
||||
|
||||
static SYNTAX: &'static str = "[OPTION]... [HOSTNAME]";
|
||||
static SUMMARY: &'static str = "Print or set the system's host name.";
|
||||
static LONG_HELP: &'static str = "";
|
||||
static SYNTAX: &'static str = "[OPTION]... [HOSTNAME]";
|
||||
static SUMMARY: &'static str = "Print or set the system's host name.";
|
||||
static LONG_HELP: &'static str = "";
|
||||
|
||||
extern {
|
||||
fn gethostname(name: *mut libc::c_char, namelen: libc::size_t) -> libc::c_int;
|
||||
|
|
|
@ -22,7 +22,6 @@ pub use uucore::libc;
|
|||
use uucore::libc::{getlogin, uid_t};
|
||||
use uucore::entries::{self, Passwd, Group, Locate};
|
||||
use uucore::process::{getgid, getuid, getegid, geteuid};
|
||||
use std::io::Write;
|
||||
use std::ffi::CStr;
|
||||
|
||||
macro_rules! cstr2cow {
|
||||
|
|
|
@ -18,7 +18,6 @@ mod mode;
|
|||
extern crate uucore;
|
||||
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::result::Result;
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
extern crate libc;
|
||||
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use std::fs;
|
||||
#[cfg(not(windows))]
|
||||
use uucore::mode;
|
||||
|
||||
/// Takes a user-supplied string and tries to parse to u16 mode bitmask.
|
||||
pub fn parse(mode_string: &str, considering_dir: bool) -> Result<u32, String> {
|
||||
|
@ -10,9 +11,9 @@ pub fn parse(mode_string: &str, considering_dir: bool) -> Result<u32, String> {
|
|||
|
||||
// Passing 000 as the existing permissions seems to mirror GNU behaviour.
|
||||
if mode_string.contains(numbers) {
|
||||
chmod_rs::parse_numeric(0, mode_string)
|
||||
mode::parse_numeric(0, mode_string)
|
||||
} else {
|
||||
chmod_rs::parse_symbolic(0, mode_string, considering_dir)
|
||||
mode::parse_symbolic(0, mode_string, considering_dir)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,131 +38,3 @@ pub fn chmod(path: &Path, mode: u32) -> Result<(), ()> {
|
|||
// chmod on Windows only sets the readonly flag, which isn't even honored on directories
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Parsing functions taken from chmod.rs.
|
||||
///
|
||||
/// We keep these in a dedicated module to minimize debt of duplicated code.
|
||||
///
|
||||
mod chmod_rs {
|
||||
extern crate libc;
|
||||
|
||||
pub fn parse_numeric(fperm: u32, mut mode: &str) -> Result<u32, String> {
|
||||
let (op, pos) = try!(parse_op(mode, Some('=')));
|
||||
mode = mode[pos..].trim_left_matches('0');
|
||||
if mode.len() > 4 {
|
||||
Err(format!("mode is too large ({} > 7777)", mode))
|
||||
} else {
|
||||
match u32::from_str_radix(mode, 8) {
|
||||
Ok(change) => {
|
||||
Ok(match op {
|
||||
'+' => fperm | change,
|
||||
'-' => fperm & !change,
|
||||
'=' => change,
|
||||
_ => unreachable!()
|
||||
})
|
||||
}
|
||||
Err(_) => Err(String::from("numeric parsing error"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_symbolic(mut fperm: u32, mut mode: &str, considering_dir: bool) -> Result<u32, String> {
|
||||
#[cfg(unix)]
|
||||
use libc::umask;
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
unsafe fn umask(_mask: u32) -> u32 {
|
||||
// XXX Redox does not currently have umask
|
||||
0
|
||||
}
|
||||
|
||||
let (mask, pos) = parse_levels(mode);
|
||||
if pos == mode.len() {
|
||||
return Err(format!("invalid mode ({})", mode));
|
||||
}
|
||||
let respect_umask = pos == 0;
|
||||
let last_umask = unsafe {
|
||||
umask(0)
|
||||
};
|
||||
mode = &mode[pos..];
|
||||
while mode.len() > 0 {
|
||||
let (op, pos) = try!(parse_op(mode, None));
|
||||
mode = &mode[pos..];
|
||||
let (mut srwx, pos) = parse_change(mode, fperm, considering_dir);
|
||||
if respect_umask {
|
||||
srwx &= !(last_umask as u32);
|
||||
}
|
||||
mode = &mode[pos..];
|
||||
match op {
|
||||
'+' => fperm |= srwx & mask,
|
||||
'-' => fperm &= !(srwx & mask),
|
||||
'=' => fperm = (fperm & !mask) | (srwx & mask),
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
umask(last_umask);
|
||||
}
|
||||
Ok(fperm)
|
||||
}
|
||||
|
||||
fn parse_levels(mode: &str) -> (u32, usize) {
|
||||
let mut mask = 0;
|
||||
let mut pos = 0;
|
||||
for ch in mode.chars() {
|
||||
mask |= match ch {
|
||||
'u' => 0o7700,
|
||||
'g' => 0o7070,
|
||||
'o' => 0o7007,
|
||||
'a' => 0o7777,
|
||||
_ => break
|
||||
};
|
||||
pos += 1;
|
||||
}
|
||||
if pos == 0 {
|
||||
mask = 0o7777; // default to 'a'
|
||||
}
|
||||
(mask, pos)
|
||||
}
|
||||
|
||||
fn parse_op(mode: &str, default: Option<char>) -> Result<(char, usize), String> {
|
||||
match mode.chars().next() {
|
||||
Some(ch) => match ch {
|
||||
'+' | '-' | '=' => Ok((ch, 1)),
|
||||
_ => match default {
|
||||
Some(ch) => Ok((ch, 0)),
|
||||
None => Err(format!("invalid operator (expected +, -, or =, but found {})", ch))
|
||||
}
|
||||
},
|
||||
None => Err("unexpected end of mode".to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_change(mode: &str, fperm: u32, considering_dir: bool) -> (u32, usize) {
|
||||
let mut srwx = fperm & 0o7000;
|
||||
let mut pos = 0;
|
||||
for ch in mode.chars() {
|
||||
match ch {
|
||||
'r' => srwx |= 0o444,
|
||||
'w' => srwx |= 0o222,
|
||||
'x' => srwx |= 0o111,
|
||||
'X' => {
|
||||
if considering_dir || (fperm & 0o0111) != 0 {
|
||||
srwx |= 0o111
|
||||
}
|
||||
}
|
||||
's' => srwx |= 0o4000 | 0o2000,
|
||||
't' => srwx |= 0o1000,
|
||||
'u' => srwx = (fperm & 0o700) | ((fperm >> 3) & 0o070) | ((fperm >> 6) & 0o007),
|
||||
'g' => srwx = ((fperm << 3) & 0o700) | (fperm & 0o070) | ((fperm >> 3) & 0o007),
|
||||
'o' => srwx = ((fperm << 6) & 0o700) | ((fperm << 3) & 0o070) | (fperm & 0o007),
|
||||
_ => break
|
||||
};
|
||||
pos += 1;
|
||||
}
|
||||
if pos == 0 {
|
||||
srwx = 0;
|
||||
}
|
||||
(srwx, pos)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,12 +15,12 @@ extern crate libc;
|
|||
extern crate uucore;
|
||||
|
||||
use libc::{c_int, pid_t};
|
||||
use std::io::{Error, Write};
|
||||
use std::io::Error;
|
||||
use uucore::signals::ALL_SIGNALS;
|
||||
|
||||
static SYNTAX: &'static str = "[options] <pid> [...]";
|
||||
static SUMMARY: &'static str = "";
|
||||
static LONG_HELP: &'static str = "";
|
||||
static SYNTAX: &'static str = "[options] <pid> [...]";
|
||||
static SUMMARY: &'static str = "";
|
||||
static LONG_HELP: &'static str = "";
|
||||
|
||||
static EXIT_OK: i32 = 0;
|
||||
static EXIT_ERR: i32 = 1;
|
||||
|
|
|
@ -13,13 +13,12 @@
|
|||
extern crate uucore;
|
||||
|
||||
use std::fs::hard_link;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use std::io::Error;
|
||||
|
||||
static SYNTAX: &'static str = "[OPTIONS] FILE1 FILE2";
|
||||
static SUMMARY: &'static str = "Create a link named FILE2 to FILE1";
|
||||
static LONG_HELP: &'static str = "";
|
||||
static SYNTAX: &'static str = "[OPTIONS] FILE1 FILE2";
|
||||
static SUMMARY: &'static str = "Create a link named FILE2 to FILE1";
|
||||
static LONG_HELP: &'static str = "";
|
||||
|
||||
pub fn normalize_error_message(e: Error) -> String {
|
||||
match e.raw_os_error() {
|
||||
|
|
|
@ -14,13 +14,13 @@
|
|||
extern crate uucore;
|
||||
|
||||
use std::fs;
|
||||
use std::io::{BufRead, BufReader, Result, stdin, Write};
|
||||
use std::io::{BufRead, BufReader, Result, stdin};
|
||||
#[cfg(unix)] use std::os::unix::fs::symlink;
|
||||
#[cfg(windows)] use std::os::windows::fs::{symlink_file,symlink_dir};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
static NAME: &'static str = "ln";
|
||||
static SUMMARY: &'static str = "";
|
||||
static NAME: &'static str = "ln";
|
||||
static SUMMARY: &'static str = "";
|
||||
static LONG_HELP: &'static str = "
|
||||
In the 1st form, create a link to TARGET with the name LINK_NAME.
|
||||
In the 2nd form, create a link to TARGET in the current directory.
|
||||
|
@ -30,7 +30,7 @@ static LONG_HELP: &'static str = "
|
|||
When creating hard links, each TARGET must exist. Symbolic links
|
||||
can hold arbitrary text; if later resolved, a relative link is
|
||||
interpreted in relation to its parent directory.
|
||||
";
|
||||
";
|
||||
|
||||
pub struct Settings {
|
||||
overwrite: OverwriteMode,
|
||||
|
|
|
@ -17,7 +17,6 @@ extern crate libc;
|
|||
extern crate uucore;
|
||||
|
||||
use std::ffi::CStr;
|
||||
use std::io::Write;
|
||||
|
||||
extern {
|
||||
// POSIX requires using getlogin (or equivalent code)
|
||||
|
@ -35,9 +34,9 @@ fn get_userlogin() -> Option<String> {
|
|||
}
|
||||
}
|
||||
|
||||
static SYNTAX: &'static str = "";
|
||||
static SUMMARY: &'static str = "Print user's login name";
|
||||
static LONG_HELP: &'static str = "";
|
||||
static SYNTAX: &'static str = "";
|
||||
static SUMMARY: &'static str = "Print user's login name";
|
||||
static LONG_HELP: &'static str = "";
|
||||
|
||||
pub fn uumain(args: Vec<String>) -> i32 {
|
||||
new_coreopts!(SYNTAX, SUMMARY, LONG_HELP).parse(args);
|
||||
|
|
|
@ -30,7 +30,6 @@ use uucore::libc::{S_ISUID, S_ISGID, S_ISVTX, S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP
|
|||
use std::fs;
|
||||
use std::fs::{DirEntry, FileType, Metadata};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::io::Write;
|
||||
use std::cmp::Reverse;
|
||||
#[cfg(unix)]
|
||||
use std::collections::HashMap;
|
||||
|
|
|
@ -16,7 +16,6 @@ extern crate libc;
|
|||
extern crate uucore;
|
||||
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
static NAME: &'static str = "mkdir";
|
||||
|
|
|
@ -17,7 +17,7 @@ extern crate uucore;
|
|||
|
||||
use libc::mkfifo;
|
||||
use std::ffi::CString;
|
||||
use std::io::{Error, Write};
|
||||
use std::io::Error;
|
||||
|
||||
static NAME: &'static str = "mkfifo";
|
||||
static VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
||||
|
|
|
@ -20,7 +20,6 @@ use libc::{mode_t, dev_t};
|
|||
use libc::{S_IRUSR, S_IWUSR, S_IRGRP, S_IWGRP, S_IROTH, S_IWOTH, S_IFIFO, S_IFBLK, S_IFCHR};
|
||||
|
||||
use getopts::Options;
|
||||
use std::io::Write;
|
||||
|
||||
use std::ffi::CString;
|
||||
|
||||
|
|
|
@ -1,124 +1,23 @@
|
|||
extern crate libc;
|
||||
use libc::{mode_t, S_IRGRP, S_IWGRP, S_IROTH, S_IWOTH, S_IRUSR, S_IWUSR};
|
||||
|
||||
fn parse_change(mode: &str, fperm: mode_t) -> (mode_t, usize) {
|
||||
let mut srwx = fperm & 0o7000;
|
||||
let mut pos = 0;
|
||||
for ch in mode.chars() {
|
||||
match ch {
|
||||
'r' => srwx |= 0o444,
|
||||
'w' => srwx |= 0o222,
|
||||
'x' => srwx |= 0o111,
|
||||
'X' => srwx |= 0o111,
|
||||
's' => srwx |= 0o4000 | 0o2000,
|
||||
't' => srwx |= 0o1000,
|
||||
'u' => srwx = (fperm & 0o700) | ((fperm >> 3) & 0o070) | ((fperm >> 6) & 0o007),
|
||||
'g' => srwx = ((fperm << 3) & 0o700) | (fperm & 0o070) | ((fperm >> 3) & 0o007),
|
||||
'o' => srwx = ((fperm << 6) & 0o700) | ((fperm << 3) & 0o070) | (fperm & 0o007),
|
||||
_ => break,
|
||||
};
|
||||
pos += 1;
|
||||
}
|
||||
if pos == 0 {
|
||||
srwx = 0;
|
||||
}
|
||||
(srwx, pos)
|
||||
}
|
||||
use uucore::mode;
|
||||
|
||||
fn parse_levels(mode: &str) -> (mode_t, usize) {
|
||||
let mut mask = 0;
|
||||
let mut pos = 0;
|
||||
for ch in mode.chars() {
|
||||
mask |= match ch {
|
||||
'u' => 0o7700,
|
||||
'g' => 0o7070,
|
||||
'o' => 0o7007,
|
||||
'a' => 0o7777,
|
||||
_ => break,
|
||||
};
|
||||
pos += 1;
|
||||
}
|
||||
if pos == 0 {
|
||||
mask = 0o7777; // default to 'a'
|
||||
}
|
||||
(mask, pos)
|
||||
}
|
||||
|
||||
fn parse_symbolic(mut fperm: mode_t, mut mode: &str) -> Result<mode_t, String> {
|
||||
let (mask, pos) = parse_levels(mode);
|
||||
if pos == mode.len() {
|
||||
return Err("invalid mode".to_owned());
|
||||
}
|
||||
mode = &mode[pos..];
|
||||
while mode.len() > 0 {
|
||||
let (op, pos) = try!(parse_op(mode, None));
|
||||
mode = &mode[pos..];
|
||||
let (srwx, pos) = parse_change(mode, fperm);
|
||||
mode = &mode[pos..];
|
||||
match op {
|
||||
'+' => fperm |= srwx & mask,
|
||||
'-' => fperm &= !(srwx & mask),
|
||||
'=' => fperm = (fperm & !mask) | (srwx & mask),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
Ok(fperm)
|
||||
}
|
||||
|
||||
fn parse_op(mode: &str, default: Option<char>) -> Result<(char, usize), String> {
|
||||
match mode.chars().next() {
|
||||
Some(ch) => {
|
||||
match ch {
|
||||
'+' | '-' | '=' => Ok((ch, 1)),
|
||||
_ => {
|
||||
match default {
|
||||
Some(ch) => Ok((ch, 0)),
|
||||
None => {
|
||||
Err(format!("invalid operator (expected +, -, or =, but found {})", ch))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None => Err("unexpected end of mode".to_owned()),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_numeric(fperm: mode_t, mut mode: &str) -> Result<mode_t, String> {
|
||||
let (op, pos) = try!(parse_op(mode, Some('=')));
|
||||
mode = mode[pos..].trim_left_matches('0');
|
||||
match mode_t::from_str_radix(mode, 8) {
|
||||
Ok(change) => {
|
||||
let after = match op {
|
||||
'+' => fperm | change,
|
||||
'-' => fperm & !change,
|
||||
'=' => change,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
if after > 0o7777 {
|
||||
return Err("invalid mode".to_owned());
|
||||
}
|
||||
Ok(after)
|
||||
}
|
||||
Err(_) => Err("invalid mode".to_owned()),
|
||||
}
|
||||
}
|
||||
pub fn parse_mode(mode: Option<String>) -> Result<mode_t, String> {
|
||||
let fperm = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
|
||||
if let Some(mode) = mode {
|
||||
let arr: &[char] = &['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
|
||||
let result = if mode.contains(arr) {
|
||||
parse_numeric(fperm, mode.as_str())
|
||||
mode::parse_numeric(fperm, mode.as_str())
|
||||
} else {
|
||||
parse_symbolic(fperm, mode.as_str())
|
||||
mode::parse_symbolic(fperm, mode.as_str(), true)
|
||||
};
|
||||
result
|
||||
result.map(|mode| mode as mode_t)
|
||||
} else {
|
||||
Ok(fperm)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn symbolic_modes() {
|
||||
assert_eq!(parse_mode(Some("u+x".to_owned())).unwrap(), 0o766);
|
||||
|
|
|
@ -17,7 +17,6 @@ extern crate rand;
|
|||
extern crate uucore;
|
||||
|
||||
use std::env;
|
||||
use std::io::Write;
|
||||
use std::path::{PathBuf, is_separator};
|
||||
use std::mem::forget;
|
||||
use std::iter;
|
||||
|
|
|
@ -16,7 +16,7 @@ extern crate uucore;
|
|||
|
||||
use std::fs;
|
||||
use std::env;
|
||||
use std::io::{BufRead, BufReader, Result, stdin, Write};
|
||||
use std::io::{BufRead, BufReader, Result, stdin};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
static NAME: &'static str = "mv";
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
* (c) Arcterus <arcterus@mail.com>
|
||||
* (c) Alex Lyon <arcterus@mail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
@ -17,7 +17,7 @@ extern crate uucore;
|
|||
|
||||
use libc::{c_char, c_int, execvp};
|
||||
use std::ffi::CString;
|
||||
use std::io::{Error, Write};
|
||||
use std::io::Error;
|
||||
|
||||
const NAME: &'static str = "nice";
|
||||
const VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
||||
|
|
|
@ -20,7 +20,7 @@ extern crate regex;
|
|||
extern crate uucore;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Read, stdin, Write};
|
||||
use std::io::{BufRead, BufReader, Read, stdin};
|
||||
use std::iter::repeat;
|
||||
use std::path::Path;
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ use libc::{c_char, signal, dup2, execvp};
|
|||
use libc::{SIG_IGN, SIGHUP};
|
||||
use std::ffi::CString;
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::{Error, Write};
|
||||
use std::io::Error;
|
||||
use std::os::unix::prelude::*;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::env;
|
||||
|
|
|
@ -18,7 +18,6 @@ extern crate libc;
|
|||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use std::io::Write;
|
||||
use std::env;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
|
|
|
@ -2,7 +2,6 @@ use std;
|
|||
use std::io;
|
||||
use std::io::BufReader;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::vec::Vec;
|
||||
|
||||
pub enum InputSource<'a> {
|
||||
|
|
|
@ -34,7 +34,6 @@ mod output_info;
|
|||
mod mockstream;
|
||||
|
||||
use std::cmp;
|
||||
use std::io::Write;
|
||||
use byteorder_io::*;
|
||||
use multifilereader::*;
|
||||
use partialreader::*;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
* (c) Arcterus <arcterus@mail.com>
|
||||
* (c) Alex Lyon <arcterus@mail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
@ -14,7 +14,7 @@ extern crate getopts;
|
|||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use std::io::{BufRead, BufReader, Read, stdin, Write};
|
||||
use std::io::{BufRead, BufReader, Read, stdin};
|
||||
use std::iter::repeat;
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
|
|
|
@ -16,7 +16,6 @@ extern crate getopts;
|
|||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use std::io::Write;
|
||||
use std::env;
|
||||
|
||||
static NAME: &'static str = "printenv";
|
||||
|
@ -40,7 +39,7 @@ Usage:
|
|||
{0} [VARIABLE]... [OPTION]...
|
||||
|
||||
Prints the given environment VARIABLE(s), otherwise prints them all.", NAME, VERSION);
|
||||
print!("{}", opts.usage(&msg));
|
||||
print!("{}", opts.usage(&msg));
|
||||
return 0;
|
||||
}
|
||||
if matches.opt_present("version") {
|
||||
|
|
|
@ -14,7 +14,6 @@ extern crate getopts;
|
|||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use std::io::Write;
|
||||
use std::env;
|
||||
|
||||
static NAME: &'static str = "pwd";
|
||||
|
|
|
@ -15,7 +15,7 @@ extern crate getopts;
|
|||
extern crate uucore;
|
||||
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::io::{Write, stdout};
|
||||
use std::path::PathBuf;
|
||||
use uucore::fs::{canonicalize, CanonicalizeMode};
|
||||
|
||||
|
@ -121,7 +121,7 @@ fn show(path: &PathBuf, no_newline: bool, use_zero: bool) {
|
|||
} else {
|
||||
println!("{}", path);
|
||||
}
|
||||
pipe_flush!();
|
||||
crash_if_err!(1, stdout().flush());
|
||||
}
|
||||
|
||||
fn show_usage(opts: &getopts::Options) {
|
||||
|
|
|
@ -15,7 +15,6 @@ extern crate getopts;
|
|||
extern crate uucore;
|
||||
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
use uucore::fs::{canonicalize, CanonicalizeMode};
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ extern crate getopts;
|
|||
extern crate uucore;
|
||||
|
||||
use std::env;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
use uucore::fs::{canonicalize, CanonicalizeMode};
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
* (c) Arcterus <arcterus@mail.com>
|
||||
* (c) Alex Lyon <arcterus@mail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
* (c) Arcterus <arcterus@mail.com>
|
||||
* (c) Alex Lyon <arcterus@mail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
@ -15,7 +15,6 @@ extern crate getopts;
|
|||
extern crate uucore;
|
||||
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
||||
static NAME: &'static str = "rmdir";
|
||||
|
|
|
@ -9,7 +9,7 @@ extern crate getopts;
|
|||
extern crate uucore;
|
||||
|
||||
use std::cmp;
|
||||
use std::io::Write;
|
||||
use std::io::{Write, stdout};
|
||||
|
||||
static NAME: &'static str = "seq";
|
||||
static VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
||||
|
@ -225,22 +225,18 @@ fn print_seq(first: f64, step: f64, last: f64, largest_dec: usize, separator: St
|
|||
let before_dec = istr.find('.').unwrap_or(ilen);
|
||||
if pad && before_dec < padding {
|
||||
for _ in 0..(padding - before_dec) {
|
||||
if !pipe_print!("0") {
|
||||
return;
|
||||
}
|
||||
print!("0");
|
||||
}
|
||||
}
|
||||
pipe_print!("{}", istr);
|
||||
print!("{}", istr);
|
||||
i += 1;
|
||||
value = first + i as f64 * step;
|
||||
if !done_printing(value, step, last) {
|
||||
if !pipe_print!("{}", separator) {
|
||||
return;
|
||||
}
|
||||
print!("{}", separator);
|
||||
}
|
||||
}
|
||||
if (first >= last && step < 0f64) || (first <= last && step > 0f64) {
|
||||
pipe_print!("{}", terminator);
|
||||
print!("{}", terminator);
|
||||
}
|
||||
pipe_flush!();
|
||||
crash_if_err!(1, stdout().flush());
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
* (c) Arcterus <arcterus@mail.com>
|
||||
* (c) Alex Lyon <arcterus@mail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
* (c) Arcterus <arcterus@mail.com>
|
||||
* (c) Alex Lyon <arcterus@mail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
@ -14,8 +14,7 @@ extern crate getopts;
|
|||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use std::io::Write;
|
||||
use std::thread::{self};
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
static NAME: &'static str = "sleep";
|
||||
|
|
|
@ -21,7 +21,7 @@ use uucore::entries;
|
|||
|
||||
use std::{fs, iter, cmp};
|
||||
use std::fs::File;
|
||||
use std::io::{Write, BufReader, BufRead};
|
||||
use std::io::{BufReader, BufRead};
|
||||
use std::borrow::Cow;
|
||||
use std::os::unix::fs::{FileTypeExt, MetadataExt};
|
||||
use std::path::Path;
|
||||
|
|
|
@ -5,7 +5,6 @@ extern crate uucore;
|
|||
|
||||
use libc::{c_int, size_t, c_char, FILE, _IOFBF, _IONBF, _IOLBF};
|
||||
use std::env;
|
||||
use std::io::Write;
|
||||
use std::ptr;
|
||||
|
||||
extern {
|
||||
|
|
|
@ -15,7 +15,7 @@ extern crate getopts;
|
|||
extern crate uucore;
|
||||
|
||||
use getopts::{Matches, Options};
|
||||
use std::io::{self, Write};
|
||||
use std::io;
|
||||
use std::os::unix::process::ExitStatusExt;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
@ -23,7 +23,7 @@ use uucore::fs::{canonicalize, CanonicalizeMode};
|
|||
|
||||
static NAME: &'static str = "stdbuf";
|
||||
static VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
||||
static LIBSTDBUF: &'static str = "libstdbuf";
|
||||
static LIBSTDBUF: &'static str = "libstdbuf";
|
||||
|
||||
enum BufferType {
|
||||
Default,
|
||||
|
@ -49,17 +49,17 @@ enum OkMsg {
|
|||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn preload_strings() -> (&'static str, &'static str) {
|
||||
fn preload_strings() -> (&'static str, &'static str) {
|
||||
("LD_PRELOAD", ".so")
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn preload_strings() -> (&'static str, &'static str) {
|
||||
fn preload_strings() -> (&'static str, &'static str) {
|
||||
("DYLD_LIBRARY_PATH", ".dylib")
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
|
||||
fn preload_strings() -> (&'static str, &'static str) {
|
||||
fn preload_strings() -> (&'static str, &'static str) {
|
||||
crash!(1, "Command not supported for this operating system!")
|
||||
}
|
||||
|
||||
|
@ -68,10 +68,10 @@ fn print_version() {
|
|||
}
|
||||
|
||||
fn print_usage(opts: &Options) {
|
||||
let brief =
|
||||
let brief =
|
||||
"Run COMMAND, with modified buffering operations for its standard streams\n \
|
||||
Mandatory arguments to long options are mandatory for short options too.";
|
||||
let explanation =
|
||||
let explanation =
|
||||
"If MODE is 'L' the corresponding stream will be line buffered.\n \
|
||||
This option is invalid with standard input.\n\n \
|
||||
If MODE is '0' the corresponding stream will be unbuffered.\n\n \
|
||||
|
|
|
@ -15,7 +15,7 @@ extern crate getopts;
|
|||
extern crate uucore;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Result, stdin, Write};
|
||||
use std::io::{Read, Result, stdin};
|
||||
use std::path::Path;
|
||||
|
||||
static NAME: &'static str = "sum";
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
* (c) Arcterus <arcterus@mail.com>
|
||||
* (c) Alex Lyon <arcterus@mail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
|
||||
extern crate getopts;
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use std::fs::OpenOptions;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
* (c) Arcterus <arcterus@mail.com>
|
||||
* (c) Alex Lyon <arcterus@mail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
@ -16,7 +16,7 @@ extern crate time;
|
|||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use std::io::{ErrorKind, Write};
|
||||
use std::io::ErrorKind;
|
||||
use std::process::{Command, Stdio};
|
||||
use std::time::Duration;
|
||||
use uucore::process::ChildExt;
|
||||
|
|
|
@ -18,7 +18,7 @@ extern crate uucore;
|
|||
|
||||
use filetime::*;
|
||||
use std::fs::{self, File};
|
||||
use std::io::{self, Error, Write};
|
||||
use std::io::{self, Error};
|
||||
use std::path::Path;
|
||||
|
||||
static NAME: &'static str = "touch";
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
* (c) Arcterus <arcterus@mail.com>
|
||||
* (c) Alex Lyon <arcterus@mail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
@ -16,7 +16,7 @@ extern crate uucore;
|
|||
|
||||
use std::ascii::AsciiExt;
|
||||
use std::fs::{File, metadata, OpenOptions};
|
||||
use std::io::{Result, Write};
|
||||
use std::io::Result;
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(Eq, PartialEq)]
|
||||
|
|
|
@ -17,7 +17,7 @@ extern crate uucore;
|
|||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Read, stdin, Write};
|
||||
use std::io::{BufRead, BufReader, Read, stdin};
|
||||
use std::path::Path;
|
||||
|
||||
static NAME: &'static str = "tsort";
|
||||
|
|
|
@ -18,7 +18,6 @@ extern crate libc;
|
|||
extern crate uucore;
|
||||
|
||||
use std::ffi::CStr;
|
||||
use std::io::Write;
|
||||
use uucore::fs::is_stdin_interactive;
|
||||
|
||||
extern {
|
||||
|
|
|
@ -249,7 +249,7 @@ fn unexpand(options: Options) {
|
|||
scol = col; // now printed up to this column
|
||||
}
|
||||
},
|
||||
Other | Backspace => { // always
|
||||
Other | Backspace => { // always
|
||||
write_tabs(&mut output, ts, scol, col, pctype == Tab, init, options.aflag);
|
||||
init = false; // no longer at the start of a line
|
||||
col = if ctype == Other { // use computed width
|
||||
|
@ -273,5 +273,5 @@ fn unexpand(options: Options) {
|
|||
buf.truncate(0); // clear out the buffer
|
||||
}
|
||||
}
|
||||
pipe_flush!(output);
|
||||
crash_if_err!(1, output.flush())
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ extern crate uucore;
|
|||
use getopts::Options;
|
||||
use libc::{S_IFMT, S_IFLNK, S_IFREG};
|
||||
use libc::{lstat, unlink, c_char, stat};
|
||||
use std::io::{Error, ErrorKind, Write};
|
||||
use std::io::{Error, ErrorKind};
|
||||
use std::mem::uninitialized;
|
||||
|
||||
static NAME: &'static str = "unlink";
|
||||
|
|
|
@ -23,7 +23,7 @@ pub use uucore::libc;
|
|||
|
||||
use getopts::Options;
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
use std::io::Read;
|
||||
use std::mem::transmute;
|
||||
|
||||
static NAME: &'static str = "uptime";
|
||||
|
|
|
@ -17,13 +17,14 @@ fs = ["libc"]
|
|||
utf8 = []
|
||||
encoding = ["data-encoding"]
|
||||
parse_time = []
|
||||
mode = ["libc"]
|
||||
utmpx = ["time", "libc"]
|
||||
process = ["libc"]
|
||||
signals = []
|
||||
entries = ["libc"]
|
||||
wide = []
|
||||
utsname = ["libc"]
|
||||
default = ["fs", "libc", "utf8", "utsname", "encoding", "parse_time", "utmpx", "process", "entries", "signals", "wide"]
|
||||
default = ["fs", "libc", "utf8", "utsname", "encoding", "parse_time", "mode", "utmpx", "process", "entries", "signals", "wide"]
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
extern crate getopts;
|
||||
use std::io::Write;
|
||||
|
||||
pub struct HelpText<'a> {
|
||||
pub name : &'a str,
|
||||
|
@ -53,8 +52,8 @@ impl<'a> CoreOptions<'a> {
|
|||
let matches = match self.options.parse(&args[1..]) {
|
||||
Ok(m) => { Some(m) },
|
||||
Err(f) => {
|
||||
pipe_write!(&mut ::std::io::stderr(), "{}: error: ", self.help_text.name);
|
||||
pipe_writeln!(&mut ::std::io::stderr(), "{}", f);
|
||||
eprint!("{}: error: ", self.help_text.name);
|
||||
eprintln!("{}", f);
|
||||
::std::process::exit(1);
|
||||
}
|
||||
}.unwrap();
|
||||
|
|
|
@ -18,6 +18,8 @@ pub mod encoding;
|
|||
#[cfg(feature = "parse_time")]
|
||||
pub mod parse_time;
|
||||
|
||||
#[cfg(all(not(windows), feature = "mode"))]
|
||||
pub mod mode;
|
||||
#[cfg(all(unix, not(target_os = "fuchsia"), feature = "utmpx"))]
|
||||
pub mod utmpx;
|
||||
#[cfg(all(unix, feature = "utsname"))]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
* (c) Arcterus <arcterus@mail.com>
|
||||
* (c) Alex Lyon <arcterus@mail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
@ -22,46 +22,36 @@ macro_rules! executable(
|
|||
#[macro_export]
|
||||
macro_rules! show_error(
|
||||
($($args:tt)+) => ({
|
||||
pipe_write!(&mut ::std::io::stderr(), "{}: error: ", executable!());
|
||||
pipe_writeln!(&mut ::std::io::stderr(), $($args)+);
|
||||
eprint!("{}: error: ", executable!());
|
||||
eprintln!($($args)+);
|
||||
})
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! show_warning(
|
||||
($($args:tt)+) => ({
|
||||
pipe_write!(&mut ::std::io::stderr(), "{}: warning: ", executable!());
|
||||
pipe_writeln!(&mut ::std::io::stderr(), $($args)+);
|
||||
eprint!("{}: warning: ", executable!());
|
||||
eprintln!($($args)+);
|
||||
})
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! show_info(
|
||||
($($args:tt)+) => ({
|
||||
pipe_write!(&mut ::std::io::stderr(), "{}: ", executable!());
|
||||
pipe_writeln!(&mut ::std::io::stderr(), $($args)+);
|
||||
eprint!("{}: ", executable!());
|
||||
eprintln!($($args)+);
|
||||
})
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! disp_err(
|
||||
($($args:tt)+) => ({
|
||||
pipe_write!(&mut ::std::io::stderr(), "{}: ", executable!());
|
||||
pipe_writeln!(&mut ::std::io::stderr(), $($args)+);
|
||||
pipe_writeln!(&mut ::std::io::stderr(), "Try '{} --help' for more information.", executable!());
|
||||
eprint!("{}: ", executable!());
|
||||
eprintln!($($args)+);
|
||||
eprintln!("Try '{} --help' for more information.", executable!());
|
||||
})
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! eprint(
|
||||
($($args:tt)+) => (pipe_write!(&mut ::std::io::stderr(), $($args)+))
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! eprintln(
|
||||
($($args:tt)+) => (pipe_writeln!(&mut ::std::io::stderr(), $($args)+))
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! crash(
|
||||
($exitcode:expr, $($args:tt)+) => ({
|
||||
|
@ -87,22 +77,6 @@ macro_rules! crash_if_err(
|
|||
)
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! pipe_crash_if_err(
|
||||
($exitcode:expr, $exp:expr) => (
|
||||
match $exp {
|
||||
Ok(_) => (),
|
||||
Err(f) => {
|
||||
if f.kind() == ::std::io::ErrorKind::BrokenPipe {
|
||||
()
|
||||
} else {
|
||||
crash!($exitcode, "{}", f)
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! return_if_err(
|
||||
($exitcode:expr, $exp:expr) => (
|
||||
|
@ -116,100 +90,6 @@ macro_rules! return_if_err(
|
|||
)
|
||||
);
|
||||
|
||||
// XXX: should the pipe_* macros return an Err just to show the write failed?
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! pipe_print(
|
||||
($($args:tt)+) => (
|
||||
match write!(&mut ::std::io::stdout(), $($args)+) {
|
||||
Ok(_) => true,
|
||||
Err(f) => {
|
||||
if f.kind() == ::std::io::ErrorKind::BrokenPipe {
|
||||
false
|
||||
} else {
|
||||
panic!("{}", f)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! pipe_println(
|
||||
($($args:tt)+) => (
|
||||
match writeln!(&mut ::std::io::stdout(), $($args)+) {
|
||||
Ok(_) => true,
|
||||
Err(f) => {
|
||||
if f.kind() == ::std::io::ErrorKind::BrokenPipe {
|
||||
false
|
||||
} else {
|
||||
panic!("{}", f)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! pipe_write(
|
||||
($fd:expr, $($args:tt)+) => (
|
||||
match write!($fd, $($args)+) {
|
||||
Ok(_) => true,
|
||||
Err(f) => {
|
||||
if f.kind() == ::std::io::ErrorKind::BrokenPipe {
|
||||
false
|
||||
} else {
|
||||
panic!("{}", f)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! pipe_writeln(
|
||||
($fd:expr, $($args:tt)+) => (
|
||||
match writeln!($fd, $($args)+) {
|
||||
Ok(_) => true,
|
||||
Err(f) => {
|
||||
if f.kind() == ::std::io::ErrorKind::BrokenPipe {
|
||||
false
|
||||
} else {
|
||||
panic!("{}", f)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! pipe_flush(
|
||||
() => (
|
||||
match ::std::io::stdout().flush() {
|
||||
Ok(_) => true,
|
||||
Err(f) => {
|
||||
if f.kind() == ::std::io::ErrorKind::BrokenPipe {
|
||||
false
|
||||
} else {
|
||||
panic!("{}", f)
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
($fd:expr) => (
|
||||
match $fd.flush() {
|
||||
Ok(_) => true,
|
||||
Err(f) => {
|
||||
if f.kind() == ::std::io::ErrorKind::BrokenPipe {
|
||||
false
|
||||
} else {
|
||||
panic!("{}", f)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! safe_write(
|
||||
($fd:expr, $($args:tt)+) => (
|
||||
|
|
129
src/uucore/mode.rs
Normal file
129
src/uucore/mode.rs
Normal file
|
@ -0,0 +1,129 @@
|
|||
// This file is part of the uutils coreutils package.
|
||||
//
|
||||
// (c) Alex Lyon <arcterus@mail.com>
|
||||
//
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
//
|
||||
|
||||
use std::error::Error;
|
||||
|
||||
pub fn parse_numeric(fperm: u32, mut mode: &str) -> Result<u32, String> {
|
||||
let (op, pos) = parse_op(mode, Some('='))?;
|
||||
mode = mode[pos..].trim_left_matches('0');
|
||||
if mode.len() > 4 {
|
||||
Err(format!("mode is too large ({} > 7777)", mode))
|
||||
} else {
|
||||
match u32::from_str_radix(mode, 8) {
|
||||
Ok(change) => {
|
||||
Ok(match op {
|
||||
'+' => fperm | change,
|
||||
'-' => fperm & !change,
|
||||
'=' => change,
|
||||
_ => unreachable!()
|
||||
})
|
||||
}
|
||||
Err(err) => Err(err.description().to_owned())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_symbolic(mut fperm: u32, mut mode: &str, considering_dir: bool) -> Result<u32, String> {
|
||||
#[cfg(unix)]
|
||||
use libc::umask;
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
unsafe fn umask(_mask: u32) -> u32 {
|
||||
// XXX Redox does not currently have umask
|
||||
0
|
||||
}
|
||||
|
||||
let (mask, pos) = parse_levels(mode);
|
||||
if pos == mode.len() {
|
||||
return Err(format!("invalid mode ({})", mode));
|
||||
}
|
||||
let respect_umask = pos == 0;
|
||||
let last_umask = unsafe {
|
||||
umask(0)
|
||||
};
|
||||
mode = &mode[pos..];
|
||||
while mode.len() > 0 {
|
||||
let (op, pos) = parse_op(mode, None)?;
|
||||
mode = &mode[pos..];
|
||||
let (mut srwx, pos) = parse_change(mode, fperm, considering_dir);
|
||||
if respect_umask {
|
||||
srwx &= !(last_umask as u32);
|
||||
}
|
||||
mode = &mode[pos..];
|
||||
match op {
|
||||
'+' => fperm |= srwx & mask,
|
||||
'-' => fperm &= !(srwx & mask),
|
||||
'=' => fperm = (fperm & !mask) | (srwx & mask),
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
umask(last_umask);
|
||||
}
|
||||
Ok(fperm)
|
||||
}
|
||||
|
||||
fn parse_levels(mode: &str) -> (u32, usize) {
|
||||
let mut mask = 0;
|
||||
let mut pos = 0;
|
||||
for ch in mode.chars() {
|
||||
mask |= match ch {
|
||||
'u' => 0o7700,
|
||||
'g' => 0o7070,
|
||||
'o' => 0o7007,
|
||||
'a' => 0o7777,
|
||||
_ => break
|
||||
};
|
||||
pos += 1;
|
||||
}
|
||||
if pos == 0 {
|
||||
mask = 0o7777; // default to 'a'
|
||||
}
|
||||
(mask, pos)
|
||||
}
|
||||
|
||||
fn parse_op(mode: &str, default: Option<char>) -> Result<(char, usize), String> {
|
||||
match mode.chars().next() {
|
||||
Some(ch) => match ch {
|
||||
'+' | '-' | '=' => Ok((ch, 1)),
|
||||
_ => match default {
|
||||
Some(ch) => Ok((ch, 0)),
|
||||
None => Err(format!("invalid operator (expected +, -, or =, but found {})", ch))
|
||||
}
|
||||
},
|
||||
None => Err("unexpected end of mode".to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_change(mode: &str, fperm: u32, considering_dir: bool) -> (u32, usize) {
|
||||
let mut srwx = fperm & 0o7000;
|
||||
let mut pos = 0;
|
||||
for ch in mode.chars() {
|
||||
match ch {
|
||||
'r' => srwx |= 0o444,
|
||||
'w' => srwx |= 0o222,
|
||||
'x' => srwx |= 0o111,
|
||||
'X' => {
|
||||
if considering_dir || (fperm & 0o0111) != 0 {
|
||||
srwx |= 0o111
|
||||
}
|
||||
}
|
||||
's' => srwx |= 0o4000 | 0o2000,
|
||||
't' => srwx |= 0o1000,
|
||||
'u' => srwx = (fperm & 0o700) | ((fperm >> 3) & 0o070) | ((fperm >> 6) & 0o007),
|
||||
'g' => srwx = ((fperm << 3) & 0o700) | (fperm & 0o070) | ((fperm >> 3) & 0o007),
|
||||
'o' => srwx = ((fperm << 6) & 0o700) | ((fperm << 3) & 0o070) | (fperm & 0o007),
|
||||
_ => break
|
||||
};
|
||||
pos += 1;
|
||||
}
|
||||
if pos == 0 {
|
||||
srwx = 0;
|
||||
}
|
||||
(srwx, pos)
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
* (c) Arcterus <arcterus@mail.com>
|
||||
* (c) Alex Lyon <arcterus@mail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
|
|
@ -17,7 +17,7 @@ extern crate uucore;
|
|||
use getopts::{Matches, Options};
|
||||
use std::ascii::AsciiExt;
|
||||
use std::fs::File;
|
||||
use std::io::{stdin, BufRead, BufReader, Read, Write};
|
||||
use std::io::{stdin, BufRead, BufReader, Read};
|
||||
use std::path::Path;
|
||||
use std::result::Result as StdResult;
|
||||
use std::str::from_utf8;
|
||||
|
|
|
@ -15,7 +15,6 @@ use uucore::utmpx::{self, time, Utmpx};
|
|||
use uucore::libc::{STDIN_FILENO, ttyname, S_IWGRP};
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::io::prelude::*;
|
||||
use std::ffi::CStr;
|
||||
use std::path::PathBuf;
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
|
|
|
@ -17,7 +17,6 @@ extern crate getopts;
|
|||
extern crate uucore;
|
||||
|
||||
use getopts::Options;
|
||||
use std::io::Write;
|
||||
|
||||
mod platform;
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@ extern crate getopts;
|
|||
extern crate uucore;
|
||||
|
||||
use getopts::Options;
|
||||
use std::io::Write;
|
||||
|
||||
static NAME: &'static str = "yes";
|
||||
static VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
||||
|
@ -57,5 +56,5 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
}
|
||||
|
||||
pub fn exec(string: &str) {
|
||||
while pipe_println!("{}", string) { }
|
||||
loop { println!("{}", string) }
|
||||
}
|
||||
|
|
|
@ -116,7 +116,7 @@ fn test_install_mode_failing() {
|
|||
at.touch(file);
|
||||
at.mkdir(dir);
|
||||
assert!(ucmd.arg(file).arg(dir).arg(mode_arg)
|
||||
.fails().stderr.contains("Invalid mode string: numeric parsing error"));
|
||||
.fails().stderr.contains("Invalid mode string: invalid digit found in string"));
|
||||
|
||||
let dest_file = &format!("{}/{}", dir, file);
|
||||
assert!(at.file_exists(file));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue