1
Fork 0
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:
mpkh 2017-12-11 10:40:11 +04:00 committed by GitHub
commit 7967f3aec7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
78 changed files with 298 additions and 673 deletions

View file

@ -13,11 +13,11 @@ extern crate uucore;
use uucore::encoding::{Data, Format, wrap_print}; use uucore::encoding::{Data, Format, wrap_print};
use std::fs::File; use std::fs::File;
use std::io::{BufReader, Read, stdin, Write}; use std::io::{BufReader, Read, stdin};
use std::path::Path; use std::path::Path;
static SYNTAX: &'static str = "[OPTION]... [FILE]"; static SYNTAX: &'static str = "[OPTION]... [FILE]";
static SUMMARY: &'static str = "Base32 encode or decode FILE, or standard input, to standard output."; static SUMMARY: &'static str = "Base32 encode or decode FILE, or standard input, to standard output.";
static LONG_HELP: &'static str = " static LONG_HELP: &'static str = "
With no FILE, or when FILE is -, read standard input. 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)", "wrap encoded lines after COLS character (default 76, 0 to disable wrapping)",
"COLS") "COLS")
.parse(args); .parse(args);
let line_wrap = match matches.opt_str("wrap") { let line_wrap = match matches.opt_str("wrap") {
Some(s) => { Some(s) => {
match s.parse() { match s.parse() {

View file

@ -15,11 +15,11 @@ extern crate uucore;
use uucore::encoding::{Data, Format, wrap_print}; use uucore::encoding::{Data, Format, wrap_print};
use std::fs::File; use std::fs::File;
use std::io::{BufReader, Read, stdin, Write}; use std::io::{BufReader, Read, stdin};
use std::path::Path; use std::path::Path;
static SYNTAX: &'static str = "[OPTION]... [FILE]"; static SYNTAX: &'static str = "[OPTION]... [FILE]";
static SUMMARY: &'static str = "Base64 encode or decode FILE, or standard input, to standard output."; static SUMMARY: &'static str = "Base64 encode or decode FILE, or standard input, to standard output.";
static LONG_HELP: &'static str = " static LONG_HELP: &'static str = "
With no FILE, or when FILE is -, read standard input. With no FILE, or when FILE is -, read standard input.

View file

@ -12,13 +12,12 @@
#[macro_use] #[macro_use]
extern crate uucore; extern crate uucore;
use std::io::Write;
use std::path::{is_separator, PathBuf}; use std::path::{is_separator, PathBuf};
static NAME: &'static str = "basename"; 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 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 = ""; static LONG_HELP: &'static str = "";
pub fn uumain(args: Vec<String>) -> i32 { pub fn uumain(args: Vec<String>) -> i32 {

View file

@ -17,7 +17,6 @@ use uucore::fs::resolve_relative_path;
extern crate walkdir; extern crate walkdir;
use walkdir::WalkDir; use walkdir::WalkDir;
use std::io::prelude::*;
use std::io::Result as IOResult; use std::io::Result as IOResult;
use std::io::Error as IOError; use std::io::Error as IOError;

View file

@ -3,7 +3,7 @@
/* /*
* This file is part of the uutils coreutils package. * 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 * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. * file that was distributed with this source code.
@ -16,16 +16,16 @@ extern crate walker;
#[macro_use] #[macro_use]
extern crate uucore; extern crate uucore;
use std::error::Error;
use std::fs; use std::fs;
use std::io::Write;
use std::os::unix::fs::{MetadataExt, PermissionsExt}; use std::os::unix::fs::{MetadataExt, PermissionsExt};
use std::path::Path; use std::path::Path;
use walker::Walker; use walker::Walker;
#[cfg(not(windows))]
use uucore::mode;
const NAME: &'static str = "chmod"; const NAME: &'static str = "chmod";
static SUMMARY: &'static str = "Change the mode of each FILE to MODE. 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 = " static LONG_HELP: &'static str = "
Each MODE is of the form '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+'. 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 arr: &[char] = &['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
let result = let result =
if mode.contains(arr) { if mode.contains(arr) {
self.parse_numeric(fperm, mode) mode::parse_numeric(fperm, mode)
} else { } else {
self.parse_symbolic(fperm, mode, file) mode::parse_symbolic(fperm, mode, file.is_dir())
}; };
match result { match result {
Ok(mode) => { Ok(mode) => {
@ -220,126 +220,6 @@ impl Chmoder {
Ok(()) 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> { fn change_file(&self, fperm: u32, mode: u32, file: &Path, path: &str) -> Result<(), i32> {
if fperm == mode { if fperm == mode {
if self.verbose && !self.changes { if self.verbose && !self.changes {

View file

@ -23,7 +23,7 @@ use walkdir::WalkDir;
use std::fs::{self, Metadata}; use std::fs::{self, Metadata};
use std::os::unix::fs::MetadataExt; use std::os::unix::fs::MetadataExt;
use std::io::{self, Write}; use std::io;
use std::io::Result as IOResult; use std::io::Result as IOResult;
use std::path::Path; use std::path::Path;

View file

@ -18,18 +18,18 @@ use uucore::libc::{self, setgid, setuid, chroot, setgroups};
use uucore::entries; use uucore::entries;
use std::ffi::CString; use std::ffi::CString;
use std::io::{Error, Write}; use std::io::Error;
use std::iter::FromIterator; use std::iter::FromIterator;
use std::path::Path; use std::path::Path;
use std::process::Command; use std::process::Command;
static NAME: &'static str = "chroot"; static NAME: &'static str = "chroot";
static SYNTAX: &'static str = "[OPTION]... NEWROOT [COMMAND [ARG]...]"; static SYNTAX: &'static str = "[OPTION]... NEWROOT [COMMAND [ARG]...]";
static SUMMARY: &'static str = "Run COMMAND with root directory set to NEWROOT."; static SUMMARY: &'static str = "Run COMMAND with root directory set to NEWROOT.";
static LONG_HELP: &'static str = " static LONG_HELP: &'static str = "
If COMMAND is not specified, it defaults to '$(SHELL) -i'. If COMMAND is not specified, it defaults to '$(SHELL) -i'.
If $(SHELL) is not set, /bin/sh is used. If $(SHELL) is not set, /bin/sh is used.
"; ";
pub fn uumain(args: Vec<String>) -> i32 { pub fn uumain(args: Vec<String>) -> i32 {
let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP) let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP)

View file

@ -1,7 +1,7 @@
/* /*
* This file is part of the uutils coreutils package. * 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> * (c) Michael Gehring <mg@ebfe.org>
* *
* For the full copyright and license information, please view the LICENSE * For the full copyright and license information, please view the LICENSE

View file

@ -14,16 +14,16 @@
extern crate uucore; extern crate uucore;
use std::fs::File; use std::fs::File;
use std::io::{self, stdin, Read, Write, BufReader}; use std::io::{self, stdin, Read, BufReader};
#[cfg(not(windows))] #[cfg(not(windows))]
use std::mem; use std::mem;
use std::path::Path; use std::path::Path;
include!(concat!(env!("OUT_DIR"), "/crc_table.rs")); include!(concat!(env!("OUT_DIR"), "/crc_table.rs"));
static SYNTAX: &'static str = "[OPTIONS] [FILE]..."; static SYNTAX: &'static str = "[OPTIONS] [FILE]...";
static SUMMARY: &'static str = "Print CRC and size for each file"; static SUMMARY: &'static str = "Print CRC and size for each file";
static LONG_HELP: &'static str = ""; static LONG_HELP: &'static str = "";
#[inline] #[inline]
fn crc_update(crc: u32, input: u8) -> u32 { fn crc_update(crc: u32, input: u8) -> u32 {

View file

@ -39,7 +39,7 @@ use clap::{Arg, App, ArgMatches};
use quick_error::ResultExt; use quick_error::ResultExt;
use std::collections::HashSet; use std::collections::HashSet;
use std::fs; use std::fs;
use std::io::{BufReader, BufRead, stdin, Write}; use std::io::{BufReader, BufRead, stdin, stdout, Write};
use std::io; use std::io;
use std::path::{Path, PathBuf, StripPrefixError}; use std::path::{Path, PathBuf, StripPrefixError};
use std::str::FromStr; use std::str::FromStr;
@ -114,9 +114,9 @@ macro_rules! or_continue(
/// answered yes. /// answered yes.
macro_rules! prompt_yes( macro_rules! prompt_yes(
($($args:tt)+) => ({ ($($args:tt)+) => ({
pipe_write!(&mut ::std::io::stdout(), $($args)+); print!($($args)+);
pipe_write!(&mut ::std::io::stdout(), " [y/N]: "); print!(" [y/N]: ");
pipe_flush!(); crash_if_err!(1, stdout().flush());
let mut s = String::new(); let mut s = String::new();
match BufReader::new(stdin()).read_line(&mut s) { match BufReader::new(stdin()).read_line(&mut s) {
Ok(_) => match s.char_indices().nth(0) { Ok(_) => match s.char_indices().nth(0) {
@ -573,7 +573,7 @@ impl Options {
attributes.push(Attribute::Xattr); attributes.push(Attribute::Xattr);
attributes.push(Attribute::Links); attributes.push(Attribute::Links);
break; break;
} else { } else {
attributes.push(Attribute::from_str(attribute_str)?); attributes.push(Attribute::from_str(attribute_str)?);
} }
} }

View file

@ -136,7 +136,7 @@ impl<R: Read> self::Bytes::Select for ByteReader<R> {
}; };
match out { 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 => (), None => (),
} }
(res, consume_val) (res, consume_val)

View file

@ -150,7 +150,7 @@ fn cut_bytes<R: Read>(reader: R, ranges: &[Range], opts: &Options) -> i32 {
loop { loop {
match buf_read.select(low - cur_pos, None::<&mut Stdout>) { match buf_read.select(low - cur_pos, None::<&mut Stdout>) {
NewlineFound => { NewlineFound => {
pipe_crash_if_err!(1, out.write_all(&[newline_char])); crash_if_err!(1, out.write_all(&[newline_char]));
continue 'newline continue 'newline
} }
Complete(len) => { Complete(len) => {
@ -160,7 +160,7 @@ fn cut_bytes<R: Read>(reader: R, ranges: &[Range], opts: &Options) -> i32 {
Partial(len) => cur_pos += len, Partial(len) => cur_pos += len,
EndOfFile => { EndOfFile => {
if orig_pos != cur_pos { 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 break 'newline
@ -171,7 +171,7 @@ fn cut_bytes<R: Read>(reader: R, ranges: &[Range], opts: &Options) -> i32 {
match opts.out_delim { match opts.out_delim {
Some(ref delim) => { Some(ref delim) => {
if print_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; print_delim = true;
} }
@ -189,7 +189,7 @@ fn cut_bytes<R: Read>(reader: R, ranges: &[Range], opts: &Options) -> i32 {
} }
EndOfFile => { EndOfFile => {
if cur_pos != low || low == high { 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 break 'newline
@ -199,7 +199,7 @@ fn cut_bytes<R: Read>(reader: R, ranges: &[Range], opts: &Options) -> i32 {
} }
buf_read.consume_line(); buf_read.consume_line();
pipe_crash_if_err!(1, out.write_all(&[newline_char])); crash_if_err!(1, out.write_all(&[newline_char]));
} }
0 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 delim_search.peek().is_none() {
if ! only_delimited { 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 { 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 { for _ in 0..high - low + 1 {
if print_delim { 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() { match delim_search.next() {
Some((high_idx, next_low_idx)) => { Some((high_idx, next_low_idx)) => {
let segment = &line[low_idx..high_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; print_delim = true;
@ -266,7 +266,7 @@ fn cut_fields_delimiter<R: Read>(reader: R, ranges: &[Range], delim: &str, only_
None => { None => {
let segment = &line[low_idx..]; 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 { if line[line.len() - 1] == newline_char {
continue 'newline 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 0
@ -318,9 +318,9 @@ fn cut_fields<R: Read>(reader: R, ranges: &[Range], opts: &FieldOptions) -> i32
if delim_search.peek().is_none() { if delim_search.peek().is_none() {
if ! opts.only_delimited { 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 { 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)) => { Some((high_idx, next_low_idx)) => {
let segment = &line[low_idx..high_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; print_delim = true;
low_idx = next_low_idx; low_idx = next_low_idx;
@ -354,7 +354,7 @@ fn cut_fields<R: Read>(reader: R, ranges: &[Range], opts: &FieldOptions) -> i32
None => { None => {
let segment = &line[low_idx..line.len()]; 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 { if line[line.len() - 1] == newline_char {
continue 'newline 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 0

View file

@ -13,19 +13,18 @@ extern crate glob;
#[macro_use] #[macro_use]
extern crate uucore; extern crate uucore;
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader, Write}; use std::io::{BufRead, BufReader};
use std::borrow::Borrow; use std::borrow::Borrow;
use std::env; use std::env;
static SYNTAX: &'static str = "[OPTION]... [FILE]"; 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 = " static LONG_HELP: &'static str = "
If FILE is specified, read it to determine which colors to use for which If FILE is specified, read it to determine which colors to use for which
file types and extensions. Otherwise, a precompiled database is used. file types and extensions. Otherwise, a precompiled database is used.
For details on the format of these files, run 'dircolors --print-database' For details on the format of these files, run 'dircolors --print-database'
"; ";
mod colors; mod colors;
use colors::INTERNAL_DB; use colors::INTERNAL_DB;

View file

@ -12,12 +12,12 @@
#[macro_use] #[macro_use]
extern crate uucore; extern crate uucore;
use std::io::Write; use std::io::{Write, stdout};
use std::str::from_utf8; use std::str::from_utf8;
#[allow(dead_code)] #[allow(dead_code)]
static SYNTAX: &'static str = "[OPTIONS]... [STRING]..."; static SYNTAX: &'static str = "[OPTIONS]... [STRING]...";
static SUMMARY: &'static str = "display a line of text"; static SUMMARY: &'static str = "display a line of text";
static LONG_HELP: &'static str = r#" static LONG_HELP: &'static str = r#"
Echo the STRING(s) to standard output. Echo the STRING(s) to standard output.
If -e is in effect, the following sequences are recognized: If -e is in effect, the following sequences are recognized:
@ -34,7 +34,7 @@ static LONG_HELP: &'static str = r#"
\\v vertical tab \\v vertical tab
\\0NNN byte with octal value NNN (1 to 3 digits) \\0NNN byte with octal value NNN (1 to 3 digits)
\\xHH byte with hexadecimal value HH (1 to 2 digits) \\xHH byte with hexadecimal value HH (1 to 2 digits)
"#; "#;
#[derive(Clone)] #[derive(Clone)]
struct EchoOptions { struct EchoOptions {
@ -173,7 +173,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
} }
if options.newline { if options.newline {
pipe_flush!(); return_if_err!(1, stdout().flush())
} else { } else {
println!("") println!("")
} }

14
src/env/env.rs vendored
View file

@ -17,15 +17,15 @@
extern crate uucore; extern crate uucore;
use std::env; use std::env;
use std::io::Write; use std::io::{Write, stdout};
use std::process::Command; use std::process::Command;
static NAME: &'static str = "env"; static NAME: &'static str = "env";
static SYNTAX: &'static str = "[OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]"; 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 SUMMARY: &'static str = "Set each NAME to VALUE in the environment and run COMMAND";
static LONG_HELP: &'static str = " static LONG_HELP: &'static str = "
A mere - implies -i. If no COMMAND, print the resulting environment A mere - implies -i. If no COMMAND, print the resulting environment
"; ";
struct options { struct options {
ignore_env: bool, 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") 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") .optflag("0", "null", "end each output line with a 0 byte rather than newline")
.optopt("u", "unset", "remove variable from the environment", "NAME"); .optopt("u", "unset", "remove variable from the environment", "NAME");
let mut opts = Box::new(options { let mut opts = Box::new(options {
ignore_env: false, ignore_env: false,
null: false, null: false,
@ -189,7 +189,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
} else { } else {
// no program provided // no program provided
print_env(opts.null); print_env(opts.null);
pipe_flush!(); return_if_err!(1, stdout().flush());
} }
0 0

View file

@ -16,8 +16,6 @@ extern crate onig;
mod tokens; mod tokens;
mod syntax_tree; mod syntax_tree;
use std::io::{Write};
static NAME: &'static str = "expr"; static NAME: &'static str = "expr";
static VERSION: &'static str = env!("CARGO_PKG_VERSION"); static VERSION: &'static str = env!("CARGO_PKG_VERSION");

View file

@ -21,7 +21,7 @@ extern crate uucore;
use numeric::*; use numeric::*;
use rand::distributions::{Range, IndependentSample}; use rand::distributions::{Range, IndependentSample};
use std::cmp::{max, min}; use std::cmp::{max, min};
use std::io::{stdin, BufRead, BufReader, Write}; use std::io::{stdin, BufRead, BufReader};
use std::num::Wrapping; use std::num::Wrapping;
use std::mem::swap; use std::mem::swap;

View file

@ -3,7 +3,7 @@
/* /*
* This file is part of the uutils coreutils package. * 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 * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. * file that was distributed with this source code.
@ -13,13 +13,13 @@
extern crate uucore; extern crate uucore;
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader, Read, stdin, Write}; use std::io::{BufRead, BufReader, Read, stdin};
use std::path::Path; use std::path::Path;
static SYNTAX: &'static str = "[OPTION]... [FILE]..."; static SYNTAX: &'static str = "[OPTION]... [FILE]...";
static SUMMARY: &'static str = "Writes each file (or standard input if no files are given) static SUMMARY: &'static str = "Writes each file (or standard input if no files are given)
to standard output whilst breaking long lines"; to standard output whilst breaking long lines";
static LONG_HELP: &'static str = ""; static LONG_HELP: &'static str = "";
pub fn uumain(args: Vec<String>) -> i32 { pub fn uumain(args: Vec<String>) -> i32 {
let (args, obs_width) = handle_obsolete(&args[..]); let (args, obs_width) = handle_obsolete(&args[..]);

View file

@ -13,7 +13,6 @@
#[macro_use] #[macro_use]
extern crate uucore; extern crate uucore;
use uucore::entries::{Passwd, Locate, get_groups, gid2grp}; use uucore::entries::{Passwd, Locate, get_groups, gid2grp};
use std::io::Write;
static SYNTAX: &'static str = "[user]"; static SYNTAX: &'static str = "[user]";
static SUMMARY: &'static str = "display current group names"; static SUMMARY: &'static str = "display current group names";

View file

@ -3,7 +3,7 @@
/* /*
* This file is part of the uutils coreutils package. * 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) Vsevolod Velichko <torkvemada@sorokdva.net>
* (c) Gil Cottle <gcottle@redtown.org> * (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 sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512, Shake128, Shake256};
use std::ascii::AsciiExt; use std::ascii::AsciiExt;
use std::fs::File; 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; use std::path::Path;
static NAME: &'static str = "hashsum"; static NAME: &'static str = "hashsum";
@ -232,7 +232,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
} }
fn version() { fn version() {
pipe_println!("{} {}", NAME, VERSION); println!("{} {}", NAME, VERSION);
} }
fn usage(program: &str, binary_name: &str, opts: &getopts::Options) { fn usage(program: &str, binary_name: &str, opts: &getopts::Options) {
@ -251,7 +251,7 @@ Usage:
Compute and check message digests.", NAME, VERSION, spec); 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> { 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(); .to_ascii_lowercase();
if sum == real_sum { if sum == real_sum {
if !quiet { if !quiet {
pipe_println!("{}: OK", ck_filename); println!("{}: OK", ck_filename);
} }
} else { } else {
if !status { if !status {
pipe_println!("{}: FAILED", ck_filename); println!("{}: FAILED", ck_filename);
} }
failed += 1; failed += 1;
} }
@ -337,9 +337,9 @@ fn hashsum(algoname: &str, mut digest: Box<Digest>, files: Vec<String>, binary:
} else { } else {
let sum = safe_unwrap!(digest_reader(&mut digest, &mut file, binary, output_bits)); let sum = safe_unwrap!(digest_reader(&mut digest, &mut file, binary, output_bits));
if tag { if tag {
pipe_println!("{} ({}) = {}", algoname, filename, sum); println!("{} ({}) = {}", algoname, filename, sum);
} else { } else {
pipe_println!("{} {}{}", sum, binary_marker, filename); println!("{} {}{}", sum, binary_marker, filename);
} }
} }
} }

View file

@ -14,7 +14,7 @@
#[macro_use] #[macro_use]
extern crate uucore; extern crate uucore;
use std::io::{BufRead, BufReader, Read, stdin, Write}; use std::io::{BufRead, BufReader, Read, stdin};
use std::fs::File; use std::fs::File;
use std::path::Path; use std::path::Path;
use std::str::from_utf8; use std::str::from_utf8;
@ -115,8 +115,8 @@ pub fn uumain(args: Vec<String>) -> i32 {
for file in &files { for file in &files {
if settings.verbose { if settings.verbose {
if !firstime { pipe_println!(""); } if !firstime { println!(""); }
pipe_println!("==> {} <==", file); println!("==> {} <==", file);
} }
firstime = false; firstime = false;
@ -171,16 +171,12 @@ fn head<T: Read>(reader: &mut BufReader<T>, settings: &Settings) -> bool {
match settings.mode { match settings.mode {
FilterMode::Bytes(count) => { FilterMode::Bytes(count) => {
for byte in reader.bytes().take(count) { for byte in reader.bytes().take(count) {
if !pipe_print!("{}", byte.unwrap() as char) { print!("{}", byte.unwrap() as char);
return false;
}
} }
}, },
FilterMode::Lines(count) => { FilterMode::Lines(count) => {
for line in reader.lines().take(count) { for line in reader.lines().take(count) {
if !pipe_println!("{}", line.unwrap()) { println!("{}", line.unwrap());
return false;
}
} }
} }
} }

View file

@ -21,12 +21,11 @@ extern crate uucore;
use std::collections::hash_set::HashSet; use std::collections::hash_set::HashSet;
use std::iter::repeat; use std::iter::repeat;
use std::str; use std::str;
use std::io::Write;
use std::net::ToSocketAddrs; use std::net::ToSocketAddrs;
static SYNTAX: &'static str = "[OPTION]... [HOSTNAME]"; static SYNTAX: &'static str = "[OPTION]... [HOSTNAME]";
static SUMMARY: &'static str = "Print or set the system's host name."; static SUMMARY: &'static str = "Print or set the system's host name.";
static LONG_HELP: &'static str = ""; static LONG_HELP: &'static str = "";
extern { extern {
fn gethostname(name: *mut libc::c_char, namelen: libc::size_t) -> libc::c_int; fn gethostname(name: *mut libc::c_char, namelen: libc::size_t) -> libc::c_int;

View file

@ -22,7 +22,6 @@ pub use uucore::libc;
use uucore::libc::{getlogin, uid_t}; use uucore::libc::{getlogin, uid_t};
use uucore::entries::{self, Passwd, Group, Locate}; use uucore::entries::{self, Passwd, Group, Locate};
use uucore::process::{getgid, getuid, getegid, geteuid}; use uucore::process::{getgid, getuid, getegid, geteuid};
use std::io::Write;
use std::ffi::CStr; use std::ffi::CStr;
macro_rules! cstr2cow { macro_rules! cstr2cow {

View file

@ -18,7 +18,6 @@ mod mode;
extern crate uucore; extern crate uucore;
use std::fs; use std::fs;
use std::io::Write;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::result::Result; use std::result::Result;

View file

@ -1,8 +1,9 @@
extern crate libc; extern crate libc;
use std::io::Write;
use std::path::Path; use std::path::Path;
use std::fs; use std::fs;
#[cfg(not(windows))]
use uucore::mode;
/// Takes a user-supplied string and tries to parse to u16 mode bitmask. /// 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> { 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. // Passing 000 as the existing permissions seems to mirror GNU behaviour.
if mode_string.contains(numbers) { if mode_string.contains(numbers) {
chmod_rs::parse_numeric(0, mode_string) mode::parse_numeric(0, mode_string)
} else { } 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 // chmod on Windows only sets the readonly flag, which isn't even honored on directories
Ok(()) 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)
}
}

View file

@ -15,12 +15,12 @@ extern crate libc;
extern crate uucore; extern crate uucore;
use libc::{c_int, pid_t}; use libc::{c_int, pid_t};
use std::io::{Error, Write}; use std::io::Error;
use uucore::signals::ALL_SIGNALS; use uucore::signals::ALL_SIGNALS;
static SYNTAX: &'static str = "[options] <pid> [...]"; static SYNTAX: &'static str = "[options] <pid> [...]";
static SUMMARY: &'static str = ""; static SUMMARY: &'static str = "";
static LONG_HELP: &'static str = ""; static LONG_HELP: &'static str = "";
static EXIT_OK: i32 = 0; static EXIT_OK: i32 = 0;
static EXIT_ERR: i32 = 1; static EXIT_ERR: i32 = 1;

View file

@ -13,13 +13,12 @@
extern crate uucore; extern crate uucore;
use std::fs::hard_link; use std::fs::hard_link;
use std::io::Write;
use std::path::Path; use std::path::Path;
use std::io::Error; use std::io::Error;
static SYNTAX: &'static str = "[OPTIONS] FILE1 FILE2"; static SYNTAX: &'static str = "[OPTIONS] FILE1 FILE2";
static SUMMARY: &'static str = "Create a link named FILE2 to FILE1"; static SUMMARY: &'static str = "Create a link named FILE2 to FILE1";
static LONG_HELP: &'static str = ""; static LONG_HELP: &'static str = "";
pub fn normalize_error_message(e: Error) -> String { pub fn normalize_error_message(e: Error) -> String {
match e.raw_os_error() { match e.raw_os_error() {

View file

@ -14,13 +14,13 @@
extern crate uucore; extern crate uucore;
use std::fs; 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(unix)] use std::os::unix::fs::symlink;
#[cfg(windows)] use std::os::windows::fs::{symlink_file,symlink_dir}; #[cfg(windows)] use std::os::windows::fs::{symlink_file,symlink_dir};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
static NAME: &'static str = "ln"; static NAME: &'static str = "ln";
static SUMMARY: &'static str = ""; static SUMMARY: &'static str = "";
static LONG_HELP: &'static str = " static LONG_HELP: &'static str = "
In the 1st form, create a link to TARGET with the name LINK_NAME. 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. 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 When creating hard links, each TARGET must exist. Symbolic links
can hold arbitrary text; if later resolved, a relative link is can hold arbitrary text; if later resolved, a relative link is
interpreted in relation to its parent directory. interpreted in relation to its parent directory.
"; ";
pub struct Settings { pub struct Settings {
overwrite: OverwriteMode, overwrite: OverwriteMode,

View file

@ -17,7 +17,6 @@ extern crate libc;
extern crate uucore; extern crate uucore;
use std::ffi::CStr; use std::ffi::CStr;
use std::io::Write;
extern { extern {
// POSIX requires using getlogin (or equivalent code) // POSIX requires using getlogin (or equivalent code)
@ -35,9 +34,9 @@ fn get_userlogin() -> Option<String> {
} }
} }
static SYNTAX: &'static str = ""; static SYNTAX: &'static str = "";
static SUMMARY: &'static str = "Print user's login name"; static SUMMARY: &'static str = "Print user's login name";
static LONG_HELP: &'static str = ""; static LONG_HELP: &'static str = "";
pub fn uumain(args: Vec<String>) -> i32 { pub fn uumain(args: Vec<String>) -> i32 {
new_coreopts!(SYNTAX, SUMMARY, LONG_HELP).parse(args); new_coreopts!(SYNTAX, SUMMARY, LONG_HELP).parse(args);

View file

@ -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;
use std::fs::{DirEntry, FileType, Metadata}; use std::fs::{DirEntry, FileType, Metadata};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::io::Write;
use std::cmp::Reverse; use std::cmp::Reverse;
#[cfg(unix)] #[cfg(unix)]
use std::collections::HashMap; use std::collections::HashMap;

View file

@ -16,7 +16,6 @@ extern crate libc;
extern crate uucore; extern crate uucore;
use std::fs; use std::fs;
use std::io::Write;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
static NAME: &'static str = "mkdir"; static NAME: &'static str = "mkdir";

View file

@ -17,7 +17,7 @@ extern crate uucore;
use libc::mkfifo; use libc::mkfifo;
use std::ffi::CString; use std::ffi::CString;
use std::io::{Error, Write}; use std::io::Error;
static NAME: &'static str = "mkfifo"; static NAME: &'static str = "mkfifo";
static VERSION: &'static str = env!("CARGO_PKG_VERSION"); static VERSION: &'static str = env!("CARGO_PKG_VERSION");

View file

@ -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 libc::{S_IRUSR, S_IWUSR, S_IRGRP, S_IWGRP, S_IROTH, S_IWOTH, S_IFIFO, S_IFBLK, S_IFCHR};
use getopts::Options; use getopts::Options;
use std::io::Write;
use std::ffi::CString; use std::ffi::CString;

View file

@ -1,124 +1,23 @@
extern crate libc; extern crate libc;
use libc::{mode_t, S_IRGRP, S_IWGRP, S_IROTH, S_IWOTH, S_IRUSR, S_IWUSR}; 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) { use uucore::mode;
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)
}
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> { 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; let fperm = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
if let Some(mode) = mode { if let Some(mode) = mode {
let arr: &[char] = &['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; let arr: &[char] = &['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
let result = if mode.contains(arr) { let result = if mode.contains(arr) {
parse_numeric(fperm, mode.as_str()) mode::parse_numeric(fperm, mode.as_str())
} else { } else {
parse_symbolic(fperm, mode.as_str()) mode::parse_symbolic(fperm, mode.as_str(), true)
}; };
result result.map(|mode| mode as mode_t)
} else { } else {
Ok(fperm) Ok(fperm)
} }
} }
#[test] #[test]
fn symbolic_modes() { fn symbolic_modes() {
assert_eq!(parse_mode(Some("u+x".to_owned())).unwrap(), 0o766); assert_eq!(parse_mode(Some("u+x".to_owned())).unwrap(), 0o766);

View file

@ -17,7 +17,6 @@ extern crate rand;
extern crate uucore; extern crate uucore;
use std::env; use std::env;
use std::io::Write;
use std::path::{PathBuf, is_separator}; use std::path::{PathBuf, is_separator};
use std::mem::forget; use std::mem::forget;
use std::iter; use std::iter;

View file

@ -16,7 +16,7 @@ extern crate uucore;
use std::fs; use std::fs;
use std::env; use std::env;
use std::io::{BufRead, BufReader, Result, stdin, Write}; use std::io::{BufRead, BufReader, Result, stdin};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
static NAME: &'static str = "mv"; static NAME: &'static str = "mv";

View file

@ -3,7 +3,7 @@
/* /*
* This file is part of the uutils coreutils package. * 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 * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. * file that was distributed with this source code.
@ -17,7 +17,7 @@ extern crate uucore;
use libc::{c_char, c_int, execvp}; use libc::{c_char, c_int, execvp};
use std::ffi::CString; use std::ffi::CString;
use std::io::{Error, Write}; use std::io::Error;
const NAME: &'static str = "nice"; const NAME: &'static str = "nice";
const VERSION: &'static str = env!("CARGO_PKG_VERSION"); const VERSION: &'static str = env!("CARGO_PKG_VERSION");

View file

@ -20,7 +20,7 @@ extern crate regex;
extern crate uucore; extern crate uucore;
use std::fs::File; 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::iter::repeat;
use std::path::Path; use std::path::Path;

View file

@ -19,7 +19,7 @@ use libc::{c_char, signal, dup2, execvp};
use libc::{SIG_IGN, SIGHUP}; use libc::{SIG_IGN, SIGHUP};
use std::ffi::CString; use std::ffi::CString;
use std::fs::{File, OpenOptions}; use std::fs::{File, OpenOptions};
use std::io::{Error, Write}; use std::io::Error;
use std::os::unix::prelude::*; use std::os::unix::prelude::*;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::env; use std::env;

View file

@ -18,7 +18,6 @@ extern crate libc;
#[macro_use] #[macro_use]
extern crate uucore; extern crate uucore;
use std::io::Write;
use std::env; use std::env;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]

View file

@ -2,7 +2,6 @@ use std;
use std::io; use std::io;
use std::io::BufReader; use std::io::BufReader;
use std::fs::File; use std::fs::File;
use std::io::Write;
use std::vec::Vec; use std::vec::Vec;
pub enum InputSource<'a> { pub enum InputSource<'a> {

View file

@ -34,7 +34,6 @@ mod output_info;
mod mockstream; mod mockstream;
use std::cmp; use std::cmp;
use std::io::Write;
use byteorder_io::*; use byteorder_io::*;
use multifilereader::*; use multifilereader::*;
use partialreader::*; use partialreader::*;

View file

@ -3,7 +3,7 @@
/* /*
* This file is part of the uutils coreutils package. * 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 * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. * file that was distributed with this source code.
@ -14,7 +14,7 @@ extern crate getopts;
#[macro_use] #[macro_use]
extern crate uucore; extern crate uucore;
use std::io::{BufRead, BufReader, Read, stdin, Write}; use std::io::{BufRead, BufReader, Read, stdin};
use std::iter::repeat; use std::iter::repeat;
use std::fs::File; use std::fs::File;
use std::path::Path; use std::path::Path;

View file

@ -16,7 +16,6 @@ extern crate getopts;
#[macro_use] #[macro_use]
extern crate uucore; extern crate uucore;
use std::io::Write;
use std::env; use std::env;
static NAME: &'static str = "printenv"; static NAME: &'static str = "printenv";
@ -40,7 +39,7 @@ Usage:
{0} [VARIABLE]... [OPTION]... {0} [VARIABLE]... [OPTION]...
Prints the given environment VARIABLE(s), otherwise prints them all.", NAME, VERSION); Prints the given environment VARIABLE(s), otherwise prints them all.", NAME, VERSION);
print!("{}", opts.usage(&msg)); print!("{}", opts.usage(&msg));
return 0; return 0;
} }
if matches.opt_present("version") { if matches.opt_present("version") {

View file

@ -14,7 +14,6 @@ extern crate getopts;
#[macro_use] #[macro_use]
extern crate uucore; extern crate uucore;
use std::io::Write;
use std::env; use std::env;
static NAME: &'static str = "pwd"; static NAME: &'static str = "pwd";

View file

@ -15,7 +15,7 @@ extern crate getopts;
extern crate uucore; extern crate uucore;
use std::fs; use std::fs;
use std::io::Write; use std::io::{Write, stdout};
use std::path::PathBuf; use std::path::PathBuf;
use uucore::fs::{canonicalize, CanonicalizeMode}; use uucore::fs::{canonicalize, CanonicalizeMode};
@ -121,7 +121,7 @@ fn show(path: &PathBuf, no_newline: bool, use_zero: bool) {
} else { } else {
println!("{}", path); println!("{}", path);
} }
pipe_flush!(); crash_if_err!(1, stdout().flush());
} }
fn show_usage(opts: &getopts::Options) { fn show_usage(opts: &getopts::Options) {

View file

@ -15,7 +15,6 @@ extern crate getopts;
extern crate uucore; extern crate uucore;
use std::fs; use std::fs;
use std::io::Write;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use uucore::fs::{canonicalize, CanonicalizeMode}; use uucore::fs::{canonicalize, CanonicalizeMode};

View file

@ -15,7 +15,6 @@ extern crate getopts;
extern crate uucore; extern crate uucore;
use std::env; use std::env;
use std::io::Write;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use uucore::fs::{canonicalize, CanonicalizeMode}; use uucore::fs::{canonicalize, CanonicalizeMode};

View file

@ -3,7 +3,7 @@
/* /*
* This file is part of the uutils coreutils package. * 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 * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. * file that was distributed with this source code.

View file

@ -3,7 +3,7 @@
/* /*
* This file is part of the uutils coreutils package. * 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 * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. * file that was distributed with this source code.
@ -15,7 +15,6 @@ extern crate getopts;
extern crate uucore; extern crate uucore;
use std::fs; use std::fs;
use std::io::Write;
use std::path::Path; use std::path::Path;
static NAME: &'static str = "rmdir"; static NAME: &'static str = "rmdir";

View file

@ -9,7 +9,7 @@ extern crate getopts;
extern crate uucore; extern crate uucore;
use std::cmp; use std::cmp;
use std::io::Write; use std::io::{Write, stdout};
static NAME: &'static str = "seq"; static NAME: &'static str = "seq";
static VERSION: &'static str = env!("CARGO_PKG_VERSION"); 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); let before_dec = istr.find('.').unwrap_or(ilen);
if pad && before_dec < padding { if pad && before_dec < padding {
for _ in 0..(padding - before_dec) { for _ in 0..(padding - before_dec) {
if !pipe_print!("0") { print!("0");
return;
}
} }
} }
pipe_print!("{}", istr); print!("{}", istr);
i += 1; i += 1;
value = first + i as f64 * step; value = first + i as f64 * step;
if !done_printing(value, step, last) { if !done_printing(value, step, last) {
if !pipe_print!("{}", separator) { print!("{}", separator);
return;
}
} }
} }
if (first >= last && step < 0f64) || (first <= last && step > 0f64) { if (first >= last && step < 0f64) || (first <= last && step > 0f64) {
pipe_print!("{}", terminator); print!("{}", terminator);
} }
pipe_flush!(); crash_if_err!(1, stdout().flush());
} }

View file

@ -3,7 +3,7 @@
/* /*
* This file is part of the uutils coreutils package. * 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 * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. * file that was distributed with this source code.

View file

@ -3,7 +3,7 @@
/* /*
* This file is part of the uutils coreutils package. * 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 * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. * file that was distributed with this source code.
@ -14,8 +14,7 @@ extern crate getopts;
#[macro_use] #[macro_use]
extern crate uucore; extern crate uucore;
use std::io::Write; use std::thread;
use std::thread::{self};
use std::time::Duration; use std::time::Duration;
static NAME: &'static str = "sleep"; static NAME: &'static str = "sleep";

View file

@ -21,7 +21,7 @@ use uucore::entries;
use std::{fs, iter, cmp}; use std::{fs, iter, cmp};
use std::fs::File; use std::fs::File;
use std::io::{Write, BufReader, BufRead}; use std::io::{BufReader, BufRead};
use std::borrow::Cow; use std::borrow::Cow;
use std::os::unix::fs::{FileTypeExt, MetadataExt}; use std::os::unix::fs::{FileTypeExt, MetadataExt};
use std::path::Path; use std::path::Path;

View file

@ -5,7 +5,6 @@ extern crate uucore;
use libc::{c_int, size_t, c_char, FILE, _IOFBF, _IONBF, _IOLBF}; use libc::{c_int, size_t, c_char, FILE, _IOFBF, _IONBF, _IOLBF};
use std::env; use std::env;
use std::io::Write;
use std::ptr; use std::ptr;
extern { extern {

View file

@ -15,7 +15,7 @@ extern crate getopts;
extern crate uucore; extern crate uucore;
use getopts::{Matches, Options}; use getopts::{Matches, Options};
use std::io::{self, Write}; use std::io;
use std::os::unix::process::ExitStatusExt; use std::os::unix::process::ExitStatusExt;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::Command; use std::process::Command;
@ -23,7 +23,7 @@ use uucore::fs::{canonicalize, CanonicalizeMode};
static NAME: &'static str = "stdbuf"; static NAME: &'static str = "stdbuf";
static VERSION: &'static str = env!("CARGO_PKG_VERSION"); static VERSION: &'static str = env!("CARGO_PKG_VERSION");
static LIBSTDBUF: &'static str = "libstdbuf"; static LIBSTDBUF: &'static str = "libstdbuf";
enum BufferType { enum BufferType {
Default, Default,
@ -49,17 +49,17 @@ enum OkMsg {
} }
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
fn preload_strings() -> (&'static str, &'static str) { fn preload_strings() -> (&'static str, &'static str) {
("LD_PRELOAD", ".so") ("LD_PRELOAD", ".so")
} }
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
fn preload_strings() -> (&'static str, &'static str) { fn preload_strings() -> (&'static str, &'static str) {
("DYLD_LIBRARY_PATH", ".dylib") ("DYLD_LIBRARY_PATH", ".dylib")
} }
#[cfg(not(any(target_os = "linux", target_os = "macos")))] #[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!") crash!(1, "Command not supported for this operating system!")
} }
@ -68,10 +68,10 @@ fn print_version() {
} }
fn print_usage(opts: &Options) { fn print_usage(opts: &Options) {
let brief = let brief =
"Run COMMAND, with modified buffering operations for its standard streams\n \ "Run COMMAND, with modified buffering operations for its standard streams\n \
Mandatory arguments to long options are mandatory for short options too."; 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 \ "If MODE is 'L' the corresponding stream will be line buffered.\n \
This option is invalid with standard input.\n\n \ This option is invalid with standard input.\n\n \
If MODE is '0' the corresponding stream will be unbuffered.\n\n \ If MODE is '0' the corresponding stream will be unbuffered.\n\n \

View file

@ -15,7 +15,7 @@ extern crate getopts;
extern crate uucore; extern crate uucore;
use std::fs::File; use std::fs::File;
use std::io::{Read, Result, stdin, Write}; use std::io::{Read, Result, stdin};
use std::path::Path; use std::path::Path;
static NAME: &'static str = "sum"; static NAME: &'static str = "sum";

View file

@ -3,7 +3,7 @@
/* /*
* This file is part of the uutils coreutils package. * 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 * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. * file that was distributed with this source code.

View file

@ -11,7 +11,6 @@
extern crate getopts; extern crate getopts;
#[macro_use]
extern crate uucore; extern crate uucore;
use std::fs::OpenOptions; use std::fs::OpenOptions;

View file

@ -3,7 +3,7 @@
/* /*
* This file is part of the uutils coreutils package. * 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 * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. * file that was distributed with this source code.
@ -16,7 +16,7 @@ extern crate time;
#[macro_use] #[macro_use]
extern crate uucore; extern crate uucore;
use std::io::{ErrorKind, Write}; use std::io::ErrorKind;
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
use std::time::Duration; use std::time::Duration;
use uucore::process::ChildExt; use uucore::process::ChildExt;

View file

@ -18,7 +18,7 @@ extern crate uucore;
use filetime::*; use filetime::*;
use std::fs::{self, File}; use std::fs::{self, File};
use std::io::{self, Error, Write}; use std::io::{self, Error};
use std::path::Path; use std::path::Path;
static NAME: &'static str = "touch"; static NAME: &'static str = "touch";

View file

@ -3,7 +3,7 @@
/* /*
* This file is part of the uutils coreutils package. * 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 * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. * file that was distributed with this source code.
@ -16,7 +16,7 @@ extern crate uucore;
use std::ascii::AsciiExt; use std::ascii::AsciiExt;
use std::fs::{File, metadata, OpenOptions}; use std::fs::{File, metadata, OpenOptions};
use std::io::{Result, Write}; use std::io::Result;
use std::path::Path; use std::path::Path;
#[derive(Eq, PartialEq)] #[derive(Eq, PartialEq)]

View file

@ -17,7 +17,7 @@ extern crate uucore;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader, Read, stdin, Write}; use std::io::{BufRead, BufReader, Read, stdin};
use std::path::Path; use std::path::Path;
static NAME: &'static str = "tsort"; static NAME: &'static str = "tsort";

View file

@ -18,7 +18,6 @@ extern crate libc;
extern crate uucore; extern crate uucore;
use std::ffi::CStr; use std::ffi::CStr;
use std::io::Write;
use uucore::fs::is_stdin_interactive; use uucore::fs::is_stdin_interactive;
extern { extern {

View file

@ -249,7 +249,7 @@ fn unexpand(options: Options) {
scol = col; // now printed up to this column 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); write_tabs(&mut output, ts, scol, col, pctype == Tab, init, options.aflag);
init = false; // no longer at the start of a line init = false; // no longer at the start of a line
col = if ctype == Other { // use computed width col = if ctype == Other { // use computed width
@ -273,5 +273,5 @@ fn unexpand(options: Options) {
buf.truncate(0); // clear out the buffer buf.truncate(0); // clear out the buffer
} }
} }
pipe_flush!(output); crash_if_err!(1, output.flush())
} }

View file

@ -20,7 +20,7 @@ extern crate uucore;
use getopts::Options; use getopts::Options;
use libc::{S_IFMT, S_IFLNK, S_IFREG}; use libc::{S_IFMT, S_IFLNK, S_IFREG};
use libc::{lstat, unlink, c_char, stat}; use libc::{lstat, unlink, c_char, stat};
use std::io::{Error, ErrorKind, Write}; use std::io::{Error, ErrorKind};
use std::mem::uninitialized; use std::mem::uninitialized;
static NAME: &'static str = "unlink"; static NAME: &'static str = "unlink";

View file

@ -23,7 +23,7 @@ pub use uucore::libc;
use getopts::Options; use getopts::Options;
use std::fs::File; use std::fs::File;
use std::io::{Read, Write}; use std::io::Read;
use std::mem::transmute; use std::mem::transmute;
static NAME: &'static str = "uptime"; static NAME: &'static str = "uptime";

View file

@ -17,13 +17,14 @@ fs = ["libc"]
utf8 = [] utf8 = []
encoding = ["data-encoding"] encoding = ["data-encoding"]
parse_time = [] parse_time = []
mode = ["libc"]
utmpx = ["time", "libc"] utmpx = ["time", "libc"]
process = ["libc"] process = ["libc"]
signals = [] signals = []
entries = ["libc"] entries = ["libc"]
wide = [] wide = []
utsname = ["libc"] 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] [lib]
path = "lib.rs" path = "lib.rs"

View file

@ -1,5 +1,4 @@
extern crate getopts; extern crate getopts;
use std::io::Write;
pub struct HelpText<'a> { pub struct HelpText<'a> {
pub name : &'a str, pub name : &'a str,
@ -53,8 +52,8 @@ impl<'a> CoreOptions<'a> {
let matches = match self.options.parse(&args[1..]) { let matches = match self.options.parse(&args[1..]) {
Ok(m) => { Some(m) }, Ok(m) => { Some(m) },
Err(f) => { Err(f) => {
pipe_write!(&mut ::std::io::stderr(), "{}: error: ", self.help_text.name); eprint!("{}: error: ", self.help_text.name);
pipe_writeln!(&mut ::std::io::stderr(), "{}", f); eprintln!("{}", f);
::std::process::exit(1); ::std::process::exit(1);
} }
}.unwrap(); }.unwrap();

View file

@ -18,6 +18,8 @@ pub mod encoding;
#[cfg(feature = "parse_time")] #[cfg(feature = "parse_time")]
pub mod parse_time; pub mod parse_time;
#[cfg(all(not(windows), feature = "mode"))]
pub mod mode;
#[cfg(all(unix, not(target_os = "fuchsia"), feature = "utmpx"))] #[cfg(all(unix, not(target_os = "fuchsia"), feature = "utmpx"))]
pub mod utmpx; pub mod utmpx;
#[cfg(all(unix, feature = "utsname"))] #[cfg(all(unix, feature = "utsname"))]

View file

@ -1,7 +1,7 @@
/* /*
* This file is part of the uutils coreutils package. * 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 * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. * file that was distributed with this source code.
@ -22,46 +22,36 @@ macro_rules! executable(
#[macro_export] #[macro_export]
macro_rules! show_error( macro_rules! show_error(
($($args:tt)+) => ({ ($($args:tt)+) => ({
pipe_write!(&mut ::std::io::stderr(), "{}: error: ", executable!()); eprint!("{}: error: ", executable!());
pipe_writeln!(&mut ::std::io::stderr(), $($args)+); eprintln!($($args)+);
}) })
); );
#[macro_export] #[macro_export]
macro_rules! show_warning( macro_rules! show_warning(
($($args:tt)+) => ({ ($($args:tt)+) => ({
pipe_write!(&mut ::std::io::stderr(), "{}: warning: ", executable!()); eprint!("{}: warning: ", executable!());
pipe_writeln!(&mut ::std::io::stderr(), $($args)+); eprintln!($($args)+);
}) })
); );
#[macro_export] #[macro_export]
macro_rules! show_info( macro_rules! show_info(
($($args:tt)+) => ({ ($($args:tt)+) => ({
pipe_write!(&mut ::std::io::stderr(), "{}: ", executable!()); eprint!("{}: ", executable!());
pipe_writeln!(&mut ::std::io::stderr(), $($args)+); eprintln!($($args)+);
}) })
); );
#[macro_export] #[macro_export]
macro_rules! disp_err( macro_rules! disp_err(
($($args:tt)+) => ({ ($($args:tt)+) => ({
pipe_write!(&mut ::std::io::stderr(), "{}: ", executable!()); eprint!("{}: ", executable!());
pipe_writeln!(&mut ::std::io::stderr(), $($args)+); eprintln!($($args)+);
pipe_writeln!(&mut ::std::io::stderr(), "Try '{} --help' for more information.", executable!()); 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_export]
macro_rules! crash( macro_rules! crash(
($exitcode:expr, $($args:tt)+) => ({ ($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_export]
macro_rules! return_if_err( macro_rules! return_if_err(
($exitcode:expr, $exp:expr) => ( ($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_export]
macro_rules! safe_write( macro_rules! safe_write(
($fd:expr, $($args:tt)+) => ( ($fd:expr, $($args:tt)+) => (

129
src/uucore/mode.rs Normal file
View 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)
}

View file

@ -1,7 +1,7 @@
/* /*
* This file is part of the uutils coreutils package. * 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 * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. * file that was distributed with this source code.

View file

@ -17,7 +17,7 @@ extern crate uucore;
use getopts::{Matches, Options}; use getopts::{Matches, Options};
use std::ascii::AsciiExt; use std::ascii::AsciiExt;
use std::fs::File; 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::path::Path;
use std::result::Result as StdResult; use std::result::Result as StdResult;
use std::str::from_utf8; use std::str::from_utf8;

View file

@ -15,7 +15,6 @@ use uucore::utmpx::{self, time, Utmpx};
use uucore::libc::{STDIN_FILENO, ttyname, S_IWGRP}; use uucore::libc::{STDIN_FILENO, ttyname, S_IWGRP};
use std::borrow::Cow; use std::borrow::Cow;
use std::io::prelude::*;
use std::ffi::CStr; use std::ffi::CStr;
use std::path::PathBuf; use std::path::PathBuf;
use std::os::unix::fs::MetadataExt; use std::os::unix::fs::MetadataExt;

View file

@ -17,7 +17,6 @@ extern crate getopts;
extern crate uucore; extern crate uucore;
use getopts::Options; use getopts::Options;
use std::io::Write;
mod platform; mod platform;

View file

@ -17,7 +17,6 @@ extern crate getopts;
extern crate uucore; extern crate uucore;
use getopts::Options; use getopts::Options;
use std::io::Write;
static NAME: &'static str = "yes"; static NAME: &'static str = "yes";
static VERSION: &'static str = env!("CARGO_PKG_VERSION"); static VERSION: &'static str = env!("CARGO_PKG_VERSION");
@ -57,5 +56,5 @@ pub fn uumain(args: Vec<String>) -> i32 {
} }
pub fn exec(string: &str) { pub fn exec(string: &str) {
while pipe_println!("{}", string) { } loop { println!("{}", string) }
} }

View file

@ -116,7 +116,7 @@ fn test_install_mode_failing() {
at.touch(file); at.touch(file);
at.mkdir(dir); at.mkdir(dir);
assert!(ucmd.arg(file).arg(dir).arg(mode_arg) 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); let dest_file = &format!("{}/{}", dir, file);
assert!(at.file_exists(file)); assert!(at.file_exists(file));