1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 03:27:44 +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,7 +13,7 @@ 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]";

View file

@ -15,7 +15,7 @@ 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]";

View file

@ -12,7 +12,6 @@
#[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";

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,12 +16,12 @@ 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.
@ -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,7 +18,7 @@ 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;

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,7 +14,7 @@
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;

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) {

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,9 +13,8 @@ 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;

View file

@ -12,7 +12,7 @@
#[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)]
@ -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!("")
} }

4
src/env/env.rs vendored
View file

@ -17,7 +17,7 @@
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";
@ -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,7 +13,7 @@
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]...";

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,7 +21,6 @@ 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]";

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,7 +15,7 @@ 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> [...]";

View file

@ -13,7 +13,6 @@
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;

View file

@ -14,7 +14,7 @@
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};

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)

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";

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;

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

@ -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));