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" name = "seq"
path = "seq/seq.rs" path = "seq/seq.rs"
[[bin]]
name = "shuf"
path = "shuf/shuf.rs"
[[bin]] [[bin]]
name = "sleep" name = "sleep"
path = "sleep/sleep.rs" path = "sleep/sleep.rs"

View file

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

View file

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

View file

@ -92,9 +92,9 @@ pub fn uumain(args: Vec<String>) -> int {
} }
fn decode(input: &mut Reader, ignore_garbage: bool) { 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, Ok(m) => m,
Err(f) => fail!(f.to_str()) Err(f) => fail!(f.to_string())
}; };
to_decode = str::replace(to_decode.as_slice(), "\n", ""); 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()) { match out.write(bytes.as_slice()) {
Ok(_) => {} Ok(_) => {}
Err(f) => { crash!(1, "{}", f.to_str()); } Err(f) => { crash!(1, "{}", f.to_string()); }
} }
match out.flush() { match out.flush() {
Ok(_) => {} Ok(_) => {}
Err(f) => { crash!(1, "{}", f.to_str()); } Err(f) => { crash!(1, "{}", f.to_string()); }
} }
} }
Err(s) => { Err(s) => {
error!("error: {}", s.to_str()); error!("error: {}", s.to_string());
fail!() fail!()
} }
} }
@ -137,7 +137,7 @@ fn encode(input: &mut Reader, line_wrap: uint) {
}; };
let to_encode = match input.read_to_end() { let to_encode = match input.read_to_end() {
Ok(m) => m, 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); 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)) { match File::open(&std::path::Path::new(path)) {
Ok(f) => Some((box f as Box<Reader>, false)), Ok(f) => Some((box f as Box<Reader>, false)),
Err(e) => { 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 None
}, },
} }

View file

@ -59,7 +59,7 @@ macro_rules! crash_if_err(
($exitcode:expr, $exp:expr) => ( ($exitcode:expr, $exp:expr) => (
match $exp { match $exp {
Ok(m) => m, 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),+) => ( ($fd:expr, $($args:expr),+) => (
match write!($fd, $($args),+) { match write!($fd, $($args),+) {
Ok(_) => {} 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),+) => ( ($fd:expr, $($args:expr),+) => (
match writeln!($fd, $($args),+) { match writeln!($fd, $($args),+) {
Ok(_) => {} Ok(_) => {}
Err(f) => { fail!(f.to_str()); } Err(f) => { fail!(f.to_string()); }
} }
) )
) )
@ -89,7 +89,7 @@ macro_rules! safe_unwrap(
($exp:expr) => ( ($exp:expr) => (
match $exp { match $exp {
Ok(m) => m, 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 { Err(e) => if e.kind == io::FileNotFound {
false false
} else { } else {
error!("error: {:s}", e.to_str()); error!("error: {:s}", e.to_string());
fail!() fail!()
} }
}; };
if same_file { if same_file {
error!("error: \"{:s}\" and \"{:s}\" are the same file", error!("error: \"{:s}\" and \"{:s}\" are the same file",
source.display().to_str(), source.display().to_string(),
dest.display().to_str()); dest.display().to_string());
fail!(); fail!();
} }
@ -118,7 +118,7 @@ fn copy(matches: getopts::Matches) {
if io_result.is_err() { if io_result.is_err() {
let err = io_result.unwrap_err(); let err = io_result.unwrap_err();
error!("error: {:s}", err.to_str()); error!("error: {:s}", err.to_string());
fail!(); fail!();
} }
} else { } else {
@ -129,7 +129,7 @@ fn copy(matches: getopts::Matches) {
for source in sources.iter() { for source in sources.iter() {
if fs::stat(source).unwrap().kind != io::TypeFile { 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; continue;
} }
@ -137,13 +137,13 @@ fn copy(matches: getopts::Matches) {
full_dest.push(source.filename_str().unwrap()); 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); let io_result = fs::copy(source, &full_dest);
if io_result.is_err() { if io_result.is_err() {
let err = io_result.unwrap_err(); let err = io_result.unwrap_err();
error!("error: {:s}", err.to_str()); error!("error: {:s}", err.to_string());
fail!() 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 getopts;
extern crate libc; 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 getopts::{optopt, optflag, getopts, usage};
use ranges::Range; use ranges::Range;
@ -22,6 +22,7 @@ use ranges::Range;
#[path = "../common/util.rs"] #[path = "../common/util.rs"]
mod util; mod util;
mod ranges; mod ranges;
mod buffer;
static NAME: &'static str = "cut"; static NAME: &'static str = "cut";
static VERSION: &'static str = "1.0.0"; 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>, ranges: &Vec<Range>,
opts: &Options) -> int { opts: &Options) -> int {
let mut out = BufferedWriter::new(std::io::stdio::stdout_raw()); use buffer::Bytes::{Select, NewlineFound, Complete, Partial, EndOfFile};
let (use_delim, out_delim) = match opts.out_delim.clone() {
Some(delim) => (true, delim), let mut buf_read = buffer::BufReader::new(reader);
None => (false, "".to_str()) let mut out = BufferedWriter::new(stdio::stdout_raw());
};
'newline: loop { 'newline: loop {
let line = match reader.read_until(b'\n') { let mut cur_pos = 1;
Ok(line) => line,
Err(std::io::IoError { kind: std::io::EndOfFile, .. }) => break,
_ => fail!(),
};
let line_len = line.len();
let mut print_delim = false; let mut print_delim = false;
for &Range { low: low, high: high } in ranges.iter() { 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 { break 'newline
if print_delim { }
out.write_str(out_delim.as_slice()).unwrap();
} }
print_delim = true;
} }
if high >= line_len { match opts.out_delim {
let segment = line.slice(low - 1, line_len); Some(ref delim) => {
if print_delim {
out.write(segment).unwrap(); out.write(delim.as_bytes()).unwrap();
}
if *line.get(line_len - 1) == b'\n' { print_delim = true;
continue 'newline
} }
} else { None => ()
let segment = line.slice(low - 1, high); }
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 0
} }
fn cut_characters<T: Reader>(mut reader: BufferedReader<T>, fn cut_characters<R: Reader>(reader: R,
ranges: &Vec<Range>, ranges: &Vec<Range>,
opts: &Options) -> int { opts: &Options) -> int {
let mut out = BufferedWriter::new(std::io::stdio::stdout_raw()); let mut buf_in = BufferedReader::new(reader);
let (use_delim, out_delim) = match opts.out_delim.clone() { let mut out = BufferedWriter::new(stdio::stdout_raw());
Some(delim) => (true, delim),
None => (false, "".to_str())
};
'newline: loop { 'newline: loop {
let line = match reader.read_line() { let line = match buf_in.read_line() {
Ok(line) => line, Ok(line) => line,
Err(std::io::IoError { kind: std::io::EndOfFile, .. }) => break, Err(std::io::IoError { kind: std::io::EndOfFile, .. }) => break,
_ => fail!(), _ => fail!(),
@ -126,11 +154,14 @@ fn cut_characters<T: Reader>(mut reader: BufferedReader<T>,
None => break None => break
}; };
if use_delim { match opts.out_delim {
if print_delim { Some(ref delim) => {
out.write_str(out_delim.as_slice()).unwrap(); if print_delim {
out.write(delim.as_bytes()).unwrap();
}
print_delim = true;
} }
print_delim = true; None => ()
} }
match char_indices.nth(high - low) { 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>, ranges: &Vec<Range>,
delim: &String, delim: &String,
only_delimited: bool, only_delimited: bool,
out_delim: &String) -> int { 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 { 'newline: loop {
let line = match reader.read_until(b'\n') { let line = match buf_in.read_until(b'\n') {
Ok(line) => line, Ok(line) => line,
Err(std::io::IoError { kind: std::io::EndOfFile, .. }) => break, Err(std::io::IoError { kind: std::io::EndOfFile, .. }) => break,
_ => fail!(), _ => fail!(),
@ -279,7 +311,7 @@ fn cut_fields_delimiter<T: Reader>(mut reader: BufferedReader<T>,
0 0
} }
fn cut_fields<T: Reader>(mut reader: BufferedReader<T>, fn cut_fields<R: Reader>(reader: R,
ranges: &Vec<Range>, ranges: &Vec<Range>,
opts: &FieldOptions) -> int { opts: &FieldOptions) -> int {
match opts.out_delimeter { match opts.out_delimeter {
@ -290,10 +322,11 @@ fn cut_fields<T: Reader>(mut reader: BufferedReader<T>,
None => () 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 { 'newline: loop {
let line = match reader.read_until(b'\n') { let line = match buf_in.read_until(b'\n') {
Ok(line) => line, Ok(line) => line,
Err(std::io::IoError { kind: std::io::EndOfFile, .. }) => break, Err(std::io::IoError { kind: std::io::EndOfFile, .. }) => break,
_ => fail!(), _ => fail!(),
@ -363,21 +396,21 @@ fn cut_files(mut filenames: Vec<String>, mode: Mode) -> int {
let mut stdin_read = false; let mut stdin_read = false;
let mut exit_code = 0; 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() { for filename in filenames.iter() {
if filename.as_slice() == "-" { if filename.as_slice() == "-" {
if stdin_read { continue; } if stdin_read { continue }
exit_code |= match mode { exit_code |= match mode {
Bytes(ref ranges, ref opts) => { Bytes(ref ranges, ref opts) => {
cut_bytes(stdin(), ranges, opts) cut_bytes(stdio::stdin_raw(), ranges, opts)
} }
Characters(ref ranges, ref opts) => { Characters(ref ranges, ref opts) => {
cut_characters(stdin(), ranges, opts) cut_characters(stdio::stdin_raw(), ranges, opts)
} }
Fields(ref ranges, ref 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() { if ! path.exists() {
show_error!("{}: No such file or directory", filename); show_error!("{}: No such file or directory", filename);
continue; continue
} }
let buf_file = match File::open(&path) { let file = match File::open(&path) {
Ok(file) => BufferedReader::new(file), Ok(f) => f,
Err(e) => { Err(e) => {
show_error!("{}: {}", filename, e.desc); show_error!("{}: {}", filename, e.desc);
continue continue
@ -399,13 +432,11 @@ fn cut_files(mut filenames: Vec<String>, mode: Mode) -> int {
}; };
exit_code |= match mode { 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) => { Characters(ref ranges, ref opts) => {
cut_characters(buf_file, ranges, opts) cut_characters(file, ranges, opts)
}
Fields(ref ranges, ref opts) => {
cut_fields(buf_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") { match matches.opt_str("delimiter") {
Some(delim) => { Some(delim) => {
if delim.as_slice().char_len() != 1 { 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 { } else {
Ok(Fields(ranges, Ok(Fields(ranges,
FieldOptions { FieldOptions {
@ -498,7 +529,7 @@ pub fn uumain(args: Vec<String>) -> int {
} }
None => Ok(Fields(ranges, None => Ok(Fields(ranges,
FieldOptions { FieldOptions {
delimiter: "\t".to_str(), delimiter: "\t".to_string(),
out_delimeter: out_delim, out_delimeter: out_delim,
only_delimited: only_delimited 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() => { (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 { match mode_parse {

View file

@ -52,7 +52,6 @@ pub enum Mode {
} }
pub fn uumain(args: Vec<String>) -> int { pub fn uumain(args: Vec<String>) -> int {
let opts = [ let opts = [
optflag("h", "help", "display this help and exit"), optflag("h", "help", "display this help and exit"),
optflag("V", "version", "output version information 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 usage = usage("[options] <pid> [...]", opts);
let (args, obs_signal) = handle_obsolete(args);
let matches = match getopts(args.tail(), opts) { let matches = match getopts(args.tail(), opts) {
Ok(m) => m, Ok(m) => m,
@ -72,7 +72,6 @@ pub fn uumain(args: Vec<String>) -> int {
}, },
}; };
let mode = if matches.opt_present("version") { let mode = if matches.opt_present("version") {
Version Version
} else if matches.opt_present("help") { } else if matches.opt_present("help") {
@ -86,7 +85,7 @@ pub fn uumain(args: Vec<String>) -> int {
}; };
match mode { 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(), Table => table(),
List => list(matches.opt_str("list")), List => list(matches.opt_str("list")),
Help => help(NAME, usage.as_slice()), Help => help(NAME, usage.as_slice()),
@ -100,8 +99,29 @@ fn version() {
println!("{} {}", NAME, 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; let mut name_width = 0;
/* Compute the maximum width of a signal name. */ /* Compute the maximum width of a signal name. */
for s in ALL_SIGNALS.iter() { for s in ALL_SIGNALS.iter() {
@ -113,7 +133,7 @@ fn table() {
for (idx, signal) in ALL_SIGNALS.iter().enumerate() { for (idx, signal) in ALL_SIGNALS.iter().enumerate() {
print!("{0: >#2} {1: <#8}", idx+1, signal.name); print!("{0: >#2} {1: <#8}", idx+1, signal.name);
//TODO: obtain max signal width here //TODO: obtain max signal width here
if (idx+1) % 7 == 0 { if (idx+1) % 7 == 0 {
println!(""); println!("");
} }
@ -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 { if signal.name == signal_name_or_value || (format!("SIG{}", signal.name).as_slice()) == signal_name_or_value {
println!("{}", signal.value) println!("{}", signal.value)
exit!(EXIT_OK as i32) 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); println!("{}", signal.name);
exit!(EXIT_OK as i32) exit!(EXIT_OK as i32)
} }
@ -144,7 +164,7 @@ fn print_signals() {
} else { } else {
pos += 1; pos += 1;
print!(" "); print!(" ");
} }
} }
} }
@ -169,14 +189,15 @@ fn signal_by_name_or_value(signal_name_or_value: &str) -> Option<uint> {
} }
for signal in ALL_SIGNALS.iter() { for signal in ALL_SIGNALS.iter() {
let long_name = format!("SIG{}", signal.name); 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); return Some(signal.value);
} }
} }
None 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 optional_signal_value = signal_by_name_or_value(signalname);
let signal_value = match optional_signal_value { let signal_value = match optional_signal_value {
Some(x) => x, Some(x) => x,
@ -187,11 +208,15 @@ fn kill(signalname: &str, pids: std::vec::Vec<String>) {
Some(x) => { Some(x) => {
let result = Process::kill(x, signal_value as int); let result = Process::kill(x, signal_value as int);
match result { match result {
Ok(_) => (), Ok(_) => (),
Err(_) => () 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: "USR1", value:30 },
Signal{ name: "USR2", value:31 }, 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) { match fs::mkdir(path, mode) {
Ok(_) => {}, Ok(_) => {},
Err(e) => { 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 // XXX: this all just assumes that the IO works correctly
let mut out = File::open_mode(&Path::new(outfile), Truncate, Write).unwrap(); let mut out = File::open_mode(&Path::new(outfile), Truncate, Write).unwrap();
let mut input = File::open(&Path::new("uutils/uutils.rs")).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()) { match out.write(main.as_bytes()) {
Err(e) => fail!("{}", e), 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. // nl implements the main functionality for an individual buffer.
fn nl<T: Reader> (reader: &mut BufferedReader<T>, settings: &Settings) { fn nl<T: Reader> (reader: &mut BufferedReader<T>, settings: &Settings) {
let mut line_no = settings.starting_line_number; 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. // 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; let line_no_width_initial = line_no_width;
// Stores the smallest integer with one more digit than line_no, so that // 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. // 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(); ).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; let mut delim_count = 0;
if serial { if serial {
for file in files.mut_iter() { 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 { Err(f) => if f.kind == io::EndOfFile {
break break
} else { } else {
crash!(1, "{}", f.to_str()) crash!(1, "{}", f.to_string())
} }
} }
delim_count += 1; delim_count += 1;
@ -102,7 +102,7 @@ fn paste(filenames: Vec<String>, serial: bool, delimiters: &str) {
*eof.get_mut(i) = true; *eof.get_mut(i) = true;
eof_count += 1; eof_count += 1;
} else { } 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) { let walk_dir = match fs::walk_dir(&file) {
Ok(m) => m, Ok(m) => m,
Err(f) => { 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); 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) { match fs::rmdir(path) {
Ok(_) => if verbose { println!("Removed '{}'", name); }, Ok(_) => if verbose { println!("Removed '{}'", name); },
Err(f) => { Err(f) => {
show_error!("{}", f.to_str()); show_error!("{}", f.to_string());
return Err(1); return Err(1);
} }
} }
@ -197,7 +197,7 @@ fn remove_file(path: &Path, name: &str, interactive: InteractiveMode, verbose: b
match fs::unlink(path) { match fs::unlink(path) {
Ok(_) => if verbose { println!("Removed '{}'", name); }, Ok(_) => if verbose { println!("Removed '{}'", name); },
Err(f) => { Err(f) => {
show_error!("{}", f.to_str()); show_error!("{}", f.to_string());
return Err(1); 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) { let mut walk_dir = match fs::walk_dir(path) {
Ok(m) => m, Ok(m) => m,
Err(f) => { Err(f) => {
show_error!("{}", f.to_str()); show_error!("{}", f.to_string());
return Err(1); return Err(1);
} }
}; };
@ -111,7 +111,7 @@ fn remove_dir(path: &Path, dir: &str, ignore: bool, parents: bool, verbose: bool
} }
} }
Err(f) => { Err(f) => {
show_error!("{}", f.to_str()); show_error!("{}", f.to_string());
r = Err(1); r = Err(1);
} }
} }

View file

@ -24,7 +24,7 @@ macro_rules! pipe_write(
if f.kind == io::BrokenPipe { if f.kind == io::BrokenPipe {
return return
} else { } 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 i = 0i;
let mut value = first + i as f64 * step; let mut value = first + i as f64 * step;
while !done_printing(value, step, last) { while !done_printing(value, step, last) {
let istr = value.to_str(); let istr = value.to_string();
let ilen = istr.len(); let ilen = istr.len();
let before_dec = istr.as_slice().find('.').unwrap_or(ilen); let before_dec = istr.as_slice().find('.').unwrap_or(ilen);
if pad && before_dec < padding { 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> 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") { if data.as_slice().ends_with("\n") {
// removes blank line that is inserted otherwise // removes blank line that is inserted otherwise
let mut buf = data.into_string(); 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> { fn with_path<T>(path: &Path, cb: || -> IoResult<T>) -> IoResult<T> {
match cb() { 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 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())) { let rfile = match File::open(&Path::new(rfilename.clone())) {
Ok(m) => m, Ok(m) => m,
Err(f) => { Err(f) => {
crash!(1, "{}", f.to_str()) crash!(1, "{}", f.to_string())
} }
}; };
match fs::stat(rfile.path()) { match fs::stat(rfile.path()) {
Ok(stat) => (stat.size, Reference), Ok(stat) => (stat.size, Reference),
Err(f) => { Err(f) => {
show_error!("{}", f.to_str()); show_error!("{}", f.to_string());
return Err(1); 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()) { let fsize = match fs::stat(file.path()) {
Ok(stat) => stat.size, Ok(stat) => stat.size,
Err(f) => { Err(f) => {
show_warning!("{}", f.to_str()); show_warning!("{}", f.to_string());
continue; continue;
} }
}; };
@ -143,13 +143,13 @@ fn truncate(no_create: bool, _: bool, reference: Option<String>, size: Option<St
match file.truncate(tsize as i64) { match file.truncate(tsize as i64) {
Ok(_) => {} Ok(_) => {}
Err(f) => { Err(f) => {
show_error!("{}", f.to_str()); show_error!("{}", f.to_string());
return Err(1); return Err(1);
} }
} }
} }
Err(f) => { Err(f) => {
show_error!("{}", f.to_str()); show_error!("{}", f.to_string());
return Err(1); return Err(1);
} }
} }

View file

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

View file

@ -15,7 +15,8 @@ extern crate getopts;
extern crate libc; extern crate libc;
use std::str::from_utf8; 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 StdResult = std::result::Result;
use getopts::Matches; use getopts::Matches;
@ -87,6 +88,7 @@ static TAB: u8 = '\t' as u8;
static SYN: u8 = 0x16 as u8; static SYN: u8 = 0x16 as u8;
static FF: u8 = 0x0C as u8; static FF: u8 = 0x0C as u8;
#[inline(always)]
fn is_word_seperator(byte: u8) -> bool { fn is_word_seperator(byte: u8) -> bool {
byte == SPACE || byte == TAB || byte == CR || byte == SYN || byte == FF 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 // 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() { 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> { fn open(path: String) -> StdResult<BufferedReader<Box<Reader>>, int> {
if "-" == path.as_slice() { if "-" == path.as_slice() {
let reader = box stdin() as Box<Reader>; let reader = box stdin_raw() as Box<Reader>;
return Ok(BufferedReader::new(reader)); return Ok(BufferedReader::new(reader));
} }
@ -240,7 +242,7 @@ fn open(path: String) -> StdResult<BufferedReader<Box<Reader>>, int> {
Ok(BufferedReader::new(reader)) Ok(BufferedReader::new(reader))
}, },
Err(e) => { 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) Err(1)
} }
} }