1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 20:17:45 +00:00
This commit is contained in:
benhirsch24 2014-07-10 13:50:13 -07:00
commit 2b8602fd4d
24 changed files with 514 additions and 121 deletions

View file

@ -151,6 +151,10 @@ path = "rmdir/rmdir.rs"
name = "seq"
path = "seq/seq.rs"
[[bin]]
name = "shuf"
path = "shuf/shuf.rs"
[[bin]]
name = "sleep"
path = "sleep/sleep.rs"

View file

@ -37,6 +37,7 @@ PROGS := \
sleep \
split \
seq \
shuf \
sum \
sync \
tac \

View file

@ -153,7 +153,6 @@ To do
- runcon
- setuidgid
- shred
- shuf
- sort
- split
- stat

View file

@ -92,9 +92,9 @@ pub fn uumain(args: Vec<String>) -> int {
}
fn decode(input: &mut Reader, ignore_garbage: bool) {
let mut to_decode = match input.read_to_str() {
let mut to_decode = match input.read_to_string() {
Ok(m) => m,
Err(f) => fail!(f.to_str())
Err(f) => fail!(f.to_string())
};
to_decode = str::replace(to_decode.as_slice(), "\n", "");
@ -112,15 +112,15 @@ fn decode(input: &mut Reader, ignore_garbage: bool) {
match out.write(bytes.as_slice()) {
Ok(_) => {}
Err(f) => { crash!(1, "{}", f.to_str()); }
Err(f) => { crash!(1, "{}", f.to_string()); }
}
match out.flush() {
Ok(_) => {}
Err(f) => { crash!(1, "{}", f.to_str()); }
Err(f) => { crash!(1, "{}", f.to_string()); }
}
}
Err(s) => {
error!("error: {}", s.to_str());
error!("error: {}", s.to_string());
fail!()
}
}
@ -137,7 +137,7 @@ fn encode(input: &mut Reader, line_wrap: uint) {
};
let to_encode = match input.read_to_end() {
Ok(m) => m,
Err(f) => fail!(f.to_str())
Err(f) => fail!(f.to_string())
};
let encoded = to_encode.as_slice().to_base64(b64_conf);

View file

@ -284,7 +284,7 @@ fn open(path: &str) -> Option<(Box<Reader>, bool)> {
match File::open(&std::path::Path::new(path)) {
Ok(f) => Some((box f as Box<Reader>, false)),
Err(e) => {
(writeln!(stderr(), "cat: {0:s}: {1:s}", path, e.to_str())).unwrap();
(writeln!(stderr(), "cat: {0:s}: {1:s}", path, e.to_string())).unwrap();
None
},
}

View file

@ -59,7 +59,7 @@ macro_rules! crash_if_err(
($exitcode:expr, $exp:expr) => (
match $exp {
Ok(m) => m,
Err(f) => crash!($exitcode, "{}", f.to_str())
Err(f) => crash!($exitcode, "{}", f.to_string())
}
)
)
@ -69,7 +69,7 @@ macro_rules! safe_write(
($fd:expr, $($args:expr),+) => (
match write!($fd, $($args),+) {
Ok(_) => {}
Err(f) => { fail!(f.to_str()); }
Err(f) => { fail!(f.to_string()); }
}
)
)
@ -79,7 +79,7 @@ macro_rules! safe_writeln(
($fd:expr, $($args:expr),+) => (
match writeln!($fd, $($args),+) {
Ok(_) => {}
Err(f) => { fail!(f.to_str()); }
Err(f) => { fail!(f.to_string()); }
}
)
)
@ -89,7 +89,7 @@ macro_rules! safe_unwrap(
($exp:expr) => (
match $exp {
Ok(m) => m,
Err(f) => crash!(1, "{}", f.to_str())
Err(f) => crash!(1, "{}", f.to_string())
}
)
)

View file

@ -102,15 +102,15 @@ fn copy(matches: getopts::Matches) {
Err(e) => if e.kind == io::FileNotFound {
false
} else {
error!("error: {:s}", e.to_str());
error!("error: {:s}", e.to_string());
fail!()
}
};
if same_file {
error!("error: \"{:s}\" and \"{:s}\" are the same file",
source.display().to_str(),
dest.display().to_str());
source.display().to_string(),
dest.display().to_string());
fail!();
}
@ -118,7 +118,7 @@ fn copy(matches: getopts::Matches) {
if io_result.is_err() {
let err = io_result.unwrap_err();
error!("error: {:s}", err.to_str());
error!("error: {:s}", err.to_string());
fail!();
}
} else {
@ -129,7 +129,7 @@ fn copy(matches: getopts::Matches) {
for source in sources.iter() {
if fs::stat(source).unwrap().kind != io::TypeFile {
error!("error: \"{:s}\" is not a file", source.display().to_str());
error!("error: \"{:s}\" is not a file", source.display().to_string());
continue;
}
@ -137,13 +137,13 @@ fn copy(matches: getopts::Matches) {
full_dest.push(source.filename_str().unwrap());
println!("{:s}", full_dest.display().to_str());
println!("{:s}", full_dest.display().to_string());
let io_result = fs::copy(source, &full_dest);
if io_result.is_err() {
let err = io_result.unwrap_err();
error!("error: {:s}", err.to_str());
error!("error: {:s}", err.to_string());
fail!()
}
}

134
cut/buffer.rs Normal file
View file

@ -0,0 +1,134 @@
use std;
use std::io::{IoResult, IoError};
pub struct BufReader<R> {
reader: R,
buffer: [u8, ..4096],
start: uint,
end: uint, // exclusive
}
pub mod Bytes {
pub trait Select {
fn select<'a>(&'a mut self, bytes: uint) -> Selected<'a>;
}
pub enum Selected<'a> {
NewlineFound(&'a [u8]),
Complete(&'a [u8]),
Partial(&'a [u8]),
EndOfFile,
}
}
impl<R: Reader> BufReader<R> {
pub fn new(reader: R) -> BufReader<R> {
let empty_buffer = unsafe {
std::mem::uninitialized::<[u8, ..4096]>()
};
BufReader {
reader: reader,
buffer: empty_buffer,
start: 0,
end: 0,
}
}
fn read(&mut self) -> IoResult<uint> {
let buf_len = self.buffer.len();
let buffer_fill = self.buffer.mut_slice(self.end, buf_len);
match self.reader.read(buffer_fill) {
Ok(nread) => {
self.end += nread;
Ok(nread)
}
error => error
}
}
#[inline]
fn maybe_fill_buf(&mut self) -> IoResult<uint> {
if self.end == self.start {
self.start = 0;
self.end = 0;
}
if self.end <= 2048 { self.read() } else { Ok(0) }
}
pub fn consume_line(&mut self) -> uint {
let mut bytes_consumed = 0;
loop {
match self.maybe_fill_buf() {
Err(IoError { kind: std::io::EndOfFile, .. }) => (),
Err(err) => fail!("read error: {}", err.desc),
_ => ()
}
let buffer_used = self.end - self.start;
if buffer_used == 0 { return bytes_consumed; }
for idx in range(self.start, self.end) {
if self.buffer[idx] == b'\n' {
self.start = idx + 1;
return bytes_consumed + idx + 1;
}
}
bytes_consumed += buffer_used;
self.start = 0;
self.end = 0;
}
}
}
impl<R: Reader> Bytes::Select for BufReader<R> {
fn select<'a>(&'a mut self, bytes: uint) -> Bytes::Selected<'a> {
match self.maybe_fill_buf() {
Err(IoError { kind: std::io::EndOfFile, .. }) => (),
Err(err) => fail!("read error: {}", err.desc),
_ => ()
}
let buffer_used = self.end - self.start;
if buffer_used == 0 { return Bytes::EndOfFile; }
let (complete, max_segment_len) = {
if bytes < buffer_used {
(true, bytes + 1)
} else {
(false, buffer_used)
}
};
for idx in range(self.start, self.start + max_segment_len) {
if self.buffer[idx] == b'\n' {
let segment = self.buffer.slice(self.start, idx + 1);
self.start = idx + 1;
return Bytes::NewlineFound(segment);
}
}
if complete {
let segment = self.buffer.slice(self.start,
self.start + bytes);
self.start += bytes;
Bytes::Complete(segment)
} else {
let segment = self.buffer.slice(self.start, self.end);
self.start = 0;
self.end = 0;
Bytes::Partial(segment)
}
}
}

View file

@ -14,7 +14,7 @@
extern crate getopts;
extern crate libc;
use std::io::{File, BufferedWriter, BufferedReader, stdin, print};
use std::io::{stdio, File, BufferedWriter, BufferedReader, print};
use getopts::{optopt, optflag, getopts, usage};
use ranges::Range;
@ -22,6 +22,7 @@ use ranges::Range;
#[path = "../common/util.rs"]
mod util;
mod ranges;
mod buffer;
static NAME: &'static str = "cut";
static VERSION: &'static str = "1.0.0";
@ -50,67 +51,94 @@ fn list_to_ranges(list: &str, complement: bool) -> Result<Vec<Range>, String> {
}
}
fn cut_bytes<T: Reader>(mut reader: BufferedReader<T>,
fn cut_bytes<R: Reader>(reader: R,
ranges: &Vec<Range>,
opts: &Options) -> int {
let mut out = BufferedWriter::new(std::io::stdio::stdout_raw());
let (use_delim, out_delim) = match opts.out_delim.clone() {
Some(delim) => (true, delim),
None => (false, "".to_str())
};
use buffer::Bytes::{Select, NewlineFound, Complete, Partial, EndOfFile};
let mut buf_read = buffer::BufReader::new(reader);
let mut out = BufferedWriter::new(stdio::stdout_raw());
'newline: loop {
let line = match reader.read_until(b'\n') {
Ok(line) => line,
Err(std::io::IoError { kind: std::io::EndOfFile, .. }) => break,
_ => fail!(),
};
let line_len = line.len();
let mut cur_pos = 1;
let mut print_delim = false;
for &Range { low: low, high: high } in ranges.iter() {
if low > line_len { break; }
// skip upto low
let orig_pos = cur_pos;
loop {
match buf_read.select(low - cur_pos) {
NewlineFound(_) => {
out.write(&[b'\n']).unwrap();
continue 'newline
}
Complete(bytes) => {
cur_pos += bytes.len();
break
}
Partial(bytes) => cur_pos += bytes.len(),
EndOfFile => {
if orig_pos != cur_pos {
out.write(&[b'\n']).unwrap();
}
if use_delim {
if print_delim {
out.write_str(out_delim.as_slice()).unwrap();
break 'newline
}
}
print_delim = true;
}
if high >= line_len {
let segment = line.slice(low - 1, line_len);
out.write(segment).unwrap();
if *line.get(line_len - 1) == b'\n' {
continue 'newline
match opts.out_delim {
Some(ref delim) => {
if print_delim {
out.write(delim.as_bytes()).unwrap();
}
print_delim = true;
}
} else {
let segment = line.slice(low - 1, high);
None => ()
}
out.write(segment).unwrap();
// write out from low to high
loop {
match buf_read.select(high - cur_pos + 1) {
NewlineFound(bytes) => {
out.write(bytes).unwrap();
continue 'newline
}
Complete(bytes) => {
out.write(bytes).unwrap();
cur_pos = high + 1;
break
}
Partial(bytes) => {
cur_pos += bytes.len();
out.write(bytes).unwrap();
}
EndOfFile => {
if cur_pos != low || low == high {
out.write(&[b'\n']).unwrap();
}
break 'newline
}
}
}
}
out.write(&[b'\n']).unwrap();
buf_read.consume_line();
out.write([b'\n']).unwrap();
}
0
}
fn cut_characters<T: Reader>(mut reader: BufferedReader<T>,
fn cut_characters<R: Reader>(reader: R,
ranges: &Vec<Range>,
opts: &Options) -> int {
let mut out = BufferedWriter::new(std::io::stdio::stdout_raw());
let (use_delim, out_delim) = match opts.out_delim.clone() {
Some(delim) => (true, delim),
None => (false, "".to_str())
};
let mut buf_in = BufferedReader::new(reader);
let mut out = BufferedWriter::new(stdio::stdout_raw());
'newline: loop {
let line = match reader.read_line() {
let line = match buf_in.read_line() {
Ok(line) => line,
Err(std::io::IoError { kind: std::io::EndOfFile, .. }) => break,
_ => fail!(),
@ -126,11 +154,14 @@ fn cut_characters<T: Reader>(mut reader: BufferedReader<T>,
None => break
};
if use_delim {
if print_delim {
out.write_str(out_delim.as_slice()).unwrap();
match opts.out_delim {
Some(ref delim) => {
if print_delim {
out.write(delim.as_bytes()).unwrap();
}
print_delim = true;
}
print_delim = true;
None => ()
}
match char_indices.nth(high - low) {
@ -204,15 +235,16 @@ impl<'a> Iterator<(uint, uint)> for Searcher<'a> {
}
}
fn cut_fields_delimiter<T: Reader>(mut reader: BufferedReader<T>,
fn cut_fields_delimiter<R: Reader>(reader: R,
ranges: &Vec<Range>,
delim: &String,
only_delimited: bool,
out_delim: &String) -> int {
let mut out = BufferedWriter::new(std::io::stdio::stdout_raw());
let mut buf_in = BufferedReader::new(reader);
let mut out = BufferedWriter::new(stdio::stdout_raw());
'newline: loop {
let line = match reader.read_until(b'\n') {
let line = match buf_in.read_until(b'\n') {
Ok(line) => line,
Err(std::io::IoError { kind: std::io::EndOfFile, .. }) => break,
_ => fail!(),
@ -279,7 +311,7 @@ fn cut_fields_delimiter<T: Reader>(mut reader: BufferedReader<T>,
0
}
fn cut_fields<T: Reader>(mut reader: BufferedReader<T>,
fn cut_fields<R: Reader>(reader: R,
ranges: &Vec<Range>,
opts: &FieldOptions) -> int {
match opts.out_delimeter {
@ -290,10 +322,11 @@ fn cut_fields<T: Reader>(mut reader: BufferedReader<T>,
None => ()
}
let mut out = BufferedWriter::new(std::io::stdio::stdout_raw());
let mut buf_in = BufferedReader::new(reader);
let mut out = BufferedWriter::new(stdio::stdout_raw());
'newline: loop {
let line = match reader.read_until(b'\n') {
let line = match buf_in.read_until(b'\n') {
Ok(line) => line,
Err(std::io::IoError { kind: std::io::EndOfFile, .. }) => break,
_ => fail!(),
@ -363,21 +396,21 @@ fn cut_files(mut filenames: Vec<String>, mode: Mode) -> int {
let mut stdin_read = false;
let mut exit_code = 0;
if filenames.len() == 0 { filenames.push("-".to_str()); }
if filenames.len() == 0 { filenames.push("-".to_string()); }
for filename in filenames.iter() {
if filename.as_slice() == "-" {
if stdin_read { continue; }
if stdin_read { continue }
exit_code |= match mode {
Bytes(ref ranges, ref opts) => {
cut_bytes(stdin(), ranges, opts)
cut_bytes(stdio::stdin_raw(), ranges, opts)
}
Characters(ref ranges, ref opts) => {
cut_characters(stdin(), ranges, opts)
cut_characters(stdio::stdin_raw(), ranges, opts)
}
Fields(ref ranges, ref opts) => {
cut_fields(stdin(), ranges, opts)
cut_fields(stdio::stdin_raw(), ranges, opts)
}
};
@ -387,11 +420,11 @@ fn cut_files(mut filenames: Vec<String>, mode: Mode) -> int {
if ! path.exists() {
show_error!("{}: No such file or directory", filename);
continue;
continue
}
let buf_file = match File::open(&path) {
Ok(file) => BufferedReader::new(file),
let file = match File::open(&path) {
Ok(f) => f,
Err(e) => {
show_error!("{}: {}", filename, e.desc);
continue
@ -399,13 +432,11 @@ fn cut_files(mut filenames: Vec<String>, mode: Mode) -> int {
};
exit_code |= match mode {
Bytes(ref ranges, ref opts) => cut_bytes(buf_file, ranges, opts),
Bytes(ref ranges, ref opts) => cut_bytes(file, ranges, opts),
Characters(ref ranges, ref opts) => {
cut_characters(buf_file, ranges, opts)
}
Fields(ref ranges, ref opts) => {
cut_fields(buf_file, ranges, opts)
cut_characters(file, ranges, opts)
}
Fields(ref ranges, ref opts) => cut_fields(file, ranges, opts)
};
}
}
@ -486,7 +517,7 @@ pub fn uumain(args: Vec<String>) -> int {
match matches.opt_str("delimiter") {
Some(delim) => {
if delim.as_slice().char_len() != 1 {
Err("the delimiter must be a single character".to_str())
Err("the delimiter must be a single character".to_string())
} else {
Ok(Fields(ranges,
FieldOptions {
@ -498,7 +529,7 @@ pub fn uumain(args: Vec<String>) -> int {
}
None => Ok(Fields(ranges,
FieldOptions {
delimiter: "\t".to_str(),
delimiter: "\t".to_string(),
out_delimeter: out_delim,
only_delimited: only_delimited
}))
@ -507,9 +538,9 @@ pub fn uumain(args: Vec<String>) -> int {
)
}
(ref b, ref c, ref f) if b.is_some() || c.is_some() || f.is_some() => {
Err("only one type of list may be specified".to_str())
Err("only one type of list may be specified".to_string())
}
_ => Err("you must specify a list of bytes, characters, or fields".to_str())
_ => Err("you must specify a list of bytes, characters, or fields".to_string())
};
match mode_parse {

View file

@ -52,7 +52,6 @@ pub enum Mode {
}
pub fn uumain(args: Vec<String>) -> int {
let opts = [
optflag("h", "help", "display this help and exit"),
optflag("V", "version", "output version information and exit"),
@ -63,6 +62,7 @@ pub fn uumain(args: Vec<String>) -> int {
let usage = usage("[options] <pid> [...]", opts);
let (args, obs_signal) = handle_obsolete(args);
let matches = match getopts(args.tail(), opts) {
Ok(m) => m,
@ -72,7 +72,6 @@ pub fn uumain(args: Vec<String>) -> int {
},
};
let mode = if matches.opt_present("version") {
Version
} else if matches.opt_present("help") {
@ -86,7 +85,7 @@ pub fn uumain(args: Vec<String>) -> int {
};
match mode {
Kill => kill(matches.opt_str("signal").unwrap_or("9".to_string()).as_slice(), matches.free),
Kill => return kill(matches.opt_str("signal").unwrap_or(obs_signal.unwrap_or("9".to_string())).as_slice(), matches.free),
Table => table(),
List => list(matches.opt_str("list")),
Help => help(NAME, usage.as_slice()),
@ -100,8 +99,29 @@ fn version() {
println!("{} {}", NAME, VERSION);
}
fn table() {
fn handle_obsolete(mut args: Vec<String>) -> (Vec<String>, Option<String>) {
let mut i = 0;
while i < args.len() {
// this is safe because slice is valid when it is referenced
let slice: &str = unsafe { std::mem::transmute(args.get(i).as_slice()) };
if slice.char_at(0) == '-' && slice.len() > 1 && slice.char_at(1).is_digit() {
let val = slice.slice_from(1);
match from_str(val) {
Some(num) => {
if signals::is_signal(num) {
args.remove(i);
return (args, Some(val.to_string()));
}
}
None => break /* getopts will error out for us */
}
}
i += 1;
}
(args, None)
}
fn table() {
let mut name_width = 0;
/* Compute the maximum width of a signal name. */
for s in ALL_SIGNALS.iter() {
@ -125,7 +145,7 @@ fn print_signal(signal_name_or_value: &str) {
if signal.name == signal_name_or_value || (format!("SIG{}", signal.name).as_slice()) == signal_name_or_value {
println!("{}", signal.value)
exit!(EXIT_OK as i32)
} else if signal_name_or_value == signal.value.to_str().as_slice() {
} else if signal_name_or_value == signal.value.to_string().as_slice() {
println!("{}", signal.name);
exit!(EXIT_OK as i32)
}
@ -169,14 +189,15 @@ fn signal_by_name_or_value(signal_name_or_value: &str) -> Option<uint> {
}
for signal in ALL_SIGNALS.iter() {
let long_name = format!("SIG{}", signal.name);
if signal.name == signal_name_or_value || (signal_name_or_value == signal.value.to_str().as_slice()) || (long_name.as_slice() == signal_name_or_value) {
if signal.name == signal_name_or_value || (signal_name_or_value == signal.value.to_string().as_slice()) || (long_name.as_slice() == signal_name_or_value) {
return Some(signal.value);
}
}
None
}
fn kill(signalname: &str, pids: std::vec::Vec<String>) {
fn kill(signalname: &str, pids: std::vec::Vec<String>) -> int {
let mut status = 0;
let optional_signal_value = signal_by_name_or_value(signalname);
let signal_value = match optional_signal_value {
Some(x) => x,
@ -187,11 +208,15 @@ fn kill(signalname: &str, pids: std::vec::Vec<String>) {
Some(x) => {
let result = Process::kill(x, signal_value as int);
match result {
Ok(_) => (),
Err(_) => ()
Ok(_) => (),
Err(f) => {
show_error!("{}", f);
status = 1;
}
};
},
None => crash!(EXIT_ERR, "failed to parse argument {}", signalname)
None => crash!(EXIT_ERR, "failed to parse argument {}", pid)
};
}
status
}

View file

@ -138,3 +138,8 @@ pub static ALL_SIGNALS:[Signal<'static>, ..31] = [
Signal{ name: "USR1", value:30 },
Signal{ name: "USR2", value:31 },
];
#[inline(always)]
pub fn is_signal(num: uint) -> bool {
num < ALL_SIGNALS.len()
}

View file

@ -157,7 +157,7 @@ fn mkdir(path: &Path, mode: FilePermission) {
match fs::mkdir(path, mode) {
Ok(_) => {},
Err(e) => {
crash!(1, "test {}", e.to_str());
crash!(1, "test {}", e.to_string());
}
}
}

View file

@ -39,7 +39,7 @@ fn main() {
// XXX: this all just assumes that the IO works correctly
let mut out = File::open_mode(&Path::new(outfile), Truncate, Write).unwrap();
let mut input = File::open(&Path::new("uutils/uutils.rs")).unwrap();
let main = input.read_to_str().unwrap().replace("@CRATES@", crates.as_slice()).replace("@UTIL_MAP@", util_map.as_slice());
let main = input.read_to_string().unwrap().replace("@CRATES@", crates.as_slice()).replace("@UTIL_MAP@", util_map.as_slice());
match out.write(main.as_bytes()) {
Err(e) => fail!("{}", e),

View file

@ -158,9 +158,9 @@ pub fn uumain(args: Vec<String>) -> int {
// nl implements the main functionality for an individual buffer.
fn nl<T: Reader> (reader: &mut BufferedReader<T>, settings: &Settings) {
let mut line_no = settings.starting_line_number;
// The current line number's width as a string. Using to_str is inefficient
// The current line number's width as a string. Using to_string is inefficient
// but since we only do it once, it should not hurt.
let mut line_no_width = line_no.to_str().len();
let mut line_no_width = line_no.to_string().len();
let line_no_width_initial = line_no_width;
// Stores the smallest integer with one more digit than line_no, so that
// when line_no >= line_no_threshold, we need to use one more digit.

View file

@ -66,7 +66,7 @@ fn paste(filenames: Vec<String>, serial: bool, delimiters: &str) {
}
)
).collect();
let delimiters: Vec<String> = delimiters.chars().map(|x| x.to_str()).collect();
let delimiters: Vec<String> = delimiters.chars().map(|x| x.to_string()).collect();
let mut delim_count = 0;
if serial {
for file in files.mut_iter() {
@ -80,7 +80,7 @@ fn paste(filenames: Vec<String>, serial: bool, delimiters: &str) {
Err(f) => if f.kind == io::EndOfFile {
break
} else {
crash!(1, "{}", f.to_str())
crash!(1, "{}", f.to_string())
}
}
delim_count += 1;
@ -102,7 +102,7 @@ fn paste(filenames: Vec<String>, serial: bool, delimiters: &str) {
*eof.get_mut(i) = true;
eof_count += 1;
} else {
crash!(1, "{}", f.to_str());
crash!(1, "{}", f.to_string());
}
}
}

View file

@ -136,7 +136,7 @@ fn remove(files: Vec<String>, force: bool, interactive: InteractiveMode, one_fs:
let walk_dir = match fs::walk_dir(&file) {
Ok(m) => m,
Err(f) => {
crash!(1, "{}", f.to_str());
crash!(1, "{}", f.to_string());
}
};
r = remove(walk_dir.map(|x| x.as_str().unwrap().to_string()).collect(), force, interactive, one_fs, preserve_root, recursive, dir, verbose).and(r);
@ -177,7 +177,7 @@ fn remove_dir(path: &Path, name: &str, interactive: InteractiveMode, verbose: bo
match fs::rmdir(path) {
Ok(_) => if verbose { println!("Removed '{}'", name); },
Err(f) => {
show_error!("{}", f.to_str());
show_error!("{}", f.to_string());
return Err(1);
}
}
@ -197,7 +197,7 @@ fn remove_file(path: &Path, name: &str, interactive: InteractiveMode, verbose: b
match fs::unlink(path) {
Ok(_) => if verbose { println!("Removed '{}'", name); },
Err(f) => {
show_error!("{}", f.to_str());
show_error!("{}", f.to_string());
return Err(1);
}
}

View file

@ -90,7 +90,7 @@ fn remove_dir(path: &Path, dir: &str, ignore: bool, parents: bool, verbose: bool
let mut walk_dir = match fs::walk_dir(path) {
Ok(m) => m,
Err(f) => {
show_error!("{}", f.to_str());
show_error!("{}", f.to_string());
return Err(1);
}
};
@ -111,7 +111,7 @@ fn remove_dir(path: &Path, dir: &str, ignore: bool, parents: bool, verbose: bool
}
}
Err(f) => {
show_error!("{}", f.to_str());
show_error!("{}", f.to_string());
r = Err(1);
}
}

View file

@ -24,7 +24,7 @@ macro_rules! pipe_write(
if f.kind == io::BrokenPipe {
return
} else {
fail!("{}", f.to_str())
fail!("{}", f.to_string())
}
}
)
@ -232,7 +232,7 @@ fn print_seq(first: f64, step: f64, last: f64, largest_dec: uint, separator: Str
let mut i = 0i;
let mut value = first + i as f64 * step;
while !done_printing(value, step, last) {
let istr = value.to_str();
let istr = value.to_string();
let ilen = istr.len();
let before_dec = istr.as_slice().find('.').unwrap_or(ilen);
if pad && before_dec < padding {

192
shuf/shuf.rs Normal file
View file

@ -0,0 +1,192 @@
#![crate_name = "shuf"]
/*
* This file is part of the uutils coreutils package.
*
* (c) Arcterus <arcterus@mail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
#![feature(macro_rules)]
extern crate getopts;
extern crate libc;
use std::cmp;
use std::from_str::from_str;
use std::io;
use std::io::IoResult;
use std::iter::{range_inclusive, RangeInclusive};
use std::rand;
use std::uint;
#[path = "../common/util.rs"]
mod util;
enum Mode {
Default,
Echo,
InputRange(RangeInclusive<uint>)
}
static NAME: &'static str = "shuf";
static VERSION: &'static str = "0.0.1";
pub fn uumain(args: Vec<String>) -> int {
let program = args.get(0).clone();
let opts = [
getopts::optflag("e", "echo", "treat each ARG as an input line"),
getopts::optopt("i", "input-range", "treat each number LO through HI as an input line", "LO-HI"),
getopts::optopt("n", "head-count", "output at most COUNT lines", "COUNT"),
getopts::optopt("o", "output", "write result to FILE instead of standard output", "FILE"),
getopts::optopt("", "random-source", "get random bytes from FILE", "FILE"),
getopts::optflag("r", "repeat", "output lines can be repeated"),
getopts::optflag("z", "zero-terminated", "end lines with 0 byte, not newline"),
getopts::optflag("h", "help", "display this help and exit"),
getopts::optflag("V", "version", "output version information and exit")
];
let mut matches = match getopts::getopts(args.tail(), opts) {
Ok(m) => m,
Err(f) => {
crash!(1, "{}", f)
}
};
if matches.opt_present("help") {
println!("{name} v{version}
Usage:
{prog} [OPTION]... [FILE]
{prog} -e [OPTION]... [ARG]...
{prog} -i LO-HI [OPTION]...\n
{usage}
With no FILE, or when FILE is -, read standard input.",
name = NAME, version = VERSION, prog = program,
usage = getopts::usage("Write a random permutation of the input lines to standard output.", opts));
} else if matches.opt_present("version") {
println!("{} v{}", NAME, VERSION);
} else {
let echo = matches.opt_present("echo");
let mode = match matches.opt_str("input-range") {
Some(range) => {
if echo {
show_error!("cannot specify more than one mode");
return 1;
}
match parse_range(range) {
Ok(m) => InputRange(m),
Err((msg, code)) => {
show_error!("{}", msg);
return code;
}
}
}
None => {
if echo {
Echo
} else {
if matches.free.len() == 0 {
matches.free.push("-".to_string());
}
Default
}
}
};
let repeat = matches.opt_present("repeat");
let zero = matches.opt_present("zero-terminated");
let count = match matches.opt_str("head-count") {
Some(cnt) => match from_str::<uint>(cnt.as_slice()) {
Some(val) => val,
None => {
show_error!("'{}' is not a valid count", cnt);
return 1;
}
},
None => uint::MAX
};
let output = matches.opt_str("output");
let random = matches.opt_str("random-source");
match shuf(matches.free, mode, repeat, zero, count, output, random) {
Err(f) => {
show_error!("{}", f);
return 1;
},
_ => {}
}
}
0
}
fn shuf(input: Vec<String>, mode: Mode, repeat: bool, zero: bool, count: uint, output: Option<String>, random: Option<String>) -> IoResult<()> {
match mode {
Echo => shuf_lines(input, repeat, zero, count, output, random),
InputRange(range) => shuf_lines(range.map(|num| num.to_string()).collect(), repeat, zero, count, output, random),
Default => {
let lines: Vec<String> = input.move_iter().flat_map(|filename| {
let slice = filename.as_slice();
let mut file_buf;
let mut stdin_buf;
let mut file = io::BufferedReader::new(
if slice == "-" {
stdin_buf = io::stdio::stdin_raw();
&mut stdin_buf as &mut Reader
} else {
file_buf = crash_if_err!(1, io::File::open(&Path::new(slice)));
&mut file_buf as &mut Reader
}
);
let mut lines = vec!();
for line in file.lines() {
let mut line = crash_if_err!(1, line);
line.pop_char();
lines.push(line);
}
lines.move_iter()
}).collect();
shuf_lines(lines, repeat, zero, count, output, random)
}
}
}
fn shuf_lines(mut lines: Vec<String>, repeat: bool, zero: bool, count: uint, outname: Option<String>, random: Option<String>) -> IoResult<()> {
let mut output = match outname {
Some(name) => box io::BufferedWriter::new(try!(io::File::create(&Path::new(name)))) as Box<Writer>,
None => box io::stdout() as Box<Writer>
};
let mut rng = match random {
Some(name) => box rand::reader::ReaderRng::new(try!(io::File::open(&Path::new(name)))) as Box<rand::Rng>,
None => box rand::task_rng() as Box<rand::Rng>
};
let mut len = lines.len();
let max = if repeat { count } else { cmp::min(count, len) };
for _ in range(0, max) {
let idx = rng.next_u32() as uint % len;
try!(write!(output, "{}{}", lines.get(idx), if zero { '\0' } else { '\n' }));
if !repeat {
lines.remove(idx);
len -= 1;
}
}
Ok(())
}
fn parse_range(input_range: String) -> Result<RangeInclusive<uint>, (String, int)> {
let split: Vec<&str> = input_range.as_slice().split('-').collect();
if split.len() != 2 {
Err(("invalid range format".to_string(), 1))
} else {
let begin = match from_str::<uint>(*split.get(0)) {
Some(m) => m,
None => return Err((format!("{} is not a valid number", split.get(0)), 1))
};
let end = match from_str::<uint>(*split.get(1)) {
Some(m) => m,
None => return Err((format!("{} is not a valid number", split.get(1)), 1))
};
Ok(range_inclusive(begin, end))
}
}

View file

@ -78,7 +78,7 @@ fn tac(filenames: Vec<String>, before: bool, _: bool, separator: &str) {
box crash_if_err!(1, io::File::open(&Path::new(filename))) as Box<Reader>
}
);
let mut data = crash_if_err!(1, file.read_to_str());
let mut data = crash_if_err!(1, file.read_to_string());
if data.as_slice().ends_with("\n") {
// removes blank line that is inserted otherwise
let mut buf = data.into_string();

View file

@ -144,7 +144,7 @@ impl Reader for NamedReader {
fn with_path<T>(path: &Path, cb: || -> IoResult<T>) -> IoResult<T> {
match cb() {
Err(f) => { warn(format!("{}: {}", path.display(), f.to_str()).as_slice()); Err(f) }
Err(f) => { warn(format!("{}: {}", path.display(), f.to_string()).as_slice()); Err(f) }
okay => okay
}
}

View file

@ -105,13 +105,13 @@ fn truncate(no_create: bool, _: bool, reference: Option<String>, size: Option<St
let rfile = match File::open(&Path::new(rfilename.clone())) {
Ok(m) => m,
Err(f) => {
crash!(1, "{}", f.to_str())
crash!(1, "{}", f.to_string())
}
};
match fs::stat(rfile.path()) {
Ok(stat) => (stat.size, Reference),
Err(f) => {
show_error!("{}", f.to_str());
show_error!("{}", f.to_string());
return Err(1);
}
}
@ -127,7 +127,7 @@ fn truncate(no_create: bool, _: bool, reference: Option<String>, size: Option<St
let fsize = match fs::stat(file.path()) {
Ok(stat) => stat.size,
Err(f) => {
show_warning!("{}", f.to_str());
show_warning!("{}", f.to_string());
continue;
}
};
@ -143,13 +143,13 @@ fn truncate(no_create: bool, _: bool, reference: Option<String>, size: Option<St
match file.truncate(tsize as i64) {
Ok(_) => {}
Err(f) => {
show_error!("{}", f.to_str());
show_error!("{}", f.to_string());
return Err(1);
}
}
}
Err(f) => {
show_error!("{}", f.to_str());
show_error!("{}", f.to_string());
return Err(1);
}
}

View file

@ -154,7 +154,7 @@ fn print_time() {
fn get_uptime(boot_time: Option<time_t>) -> i64 {
let proc_uptime = File::open(&Path::new("/proc/uptime"))
.read_to_str();
.read_to_string();
let uptime_text = match proc_uptime {
Ok(s) => s,

View file

@ -15,7 +15,8 @@ extern crate getopts;
extern crate libc;
use std::str::from_utf8;
use std::io::{print, stdin, File, BufferedReader};
use std::io::{print, File, BufferedReader};
use std::io::stdio::stdin_raw;
use StdResult = std::result::Result;
use getopts::Matches;
@ -87,6 +88,7 @@ static TAB: u8 = '\t' as u8;
static SYN: u8 = 0x16 as u8;
static FF: u8 = 0x0C as u8;
#[inline(always)]
fn is_word_seperator(byte: u8) -> bool {
byte == SPACE || byte == TAB || byte == CR || byte == SYN || byte == FF
}
@ -177,7 +179,7 @@ pub fn wc(files: Vec<String>, matches: &Matches) -> StdResult<(), int> {
}
// used for formatting
max_str_len = total_byte_count.to_str().len();
max_str_len = total_byte_count.to_string().len();
}
for result in results.iter() {
@ -230,7 +232,7 @@ fn print_stats(filename: &str, line_count: uint, word_count: uint, char_count: u
fn open(path: String) -> StdResult<BufferedReader<Box<Reader>>, int> {
if "-" == path.as_slice() {
let reader = box stdin() as Box<Reader>;
let reader = box stdin_raw() as Box<Reader>;
return Ok(BufferedReader::new(reader));
}
@ -240,7 +242,7 @@ fn open(path: String) -> StdResult<BufferedReader<Box<Reader>>, int> {
Ok(BufferedReader::new(reader))
},
Err(e) => {
show_error!("wc: {0:s}: {1:s}", path, e.desc.to_str());
show_error!("wc: {0:s}: {1:s}", path, e.desc.to_string());
Err(1)
}
}