From 09937b66b99d42c53170605a739637091e202bf8 Mon Sep 17 00:00:00 2001 From: kwantam Date: Mon, 27 Apr 2015 17:31:53 -0400 Subject: [PATCH 1/5] fix `whoami` --- src/whoami/platform/mod.rs | 20 +++++++++++++ src/whoami/platform/unix.rs | 24 ++++++++++++++++ src/whoami/platform/windows.rs | 27 ++++++++++++++++++ src/whoami/whoami.rs | 52 ++++------------------------------ 4 files changed, 77 insertions(+), 46 deletions(-) create mode 100644 src/whoami/platform/mod.rs create mode 100644 src/whoami/platform/unix.rs create mode 100644 src/whoami/platform/windows.rs diff --git a/src/whoami/platform/mod.rs b/src/whoami/platform/mod.rs new file mode 100644 index 000000000..12d85ec08 --- /dev/null +++ b/src/whoami/platform/mod.rs @@ -0,0 +1,20 @@ +/* + * This file is part of the uutils coreutils package. + * + * (c) Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +#[cfg(unix)] +pub use self::unix::getusername; + +#[cfg(windows)] +pub use self::windows::getusername; + +#[cfg(unix)] +mod unix; + +#[cfg(windows)] +mod windows; diff --git a/src/whoami/platform/unix.rs b/src/whoami/platform/unix.rs new file mode 100644 index 000000000..e69034bfe --- /dev/null +++ b/src/whoami/platform/unix.rs @@ -0,0 +1,24 @@ +/* + * This file is part of the uutils coreutils package. + * + * (c) Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use ::libc; +use self::c_types::{c_passwd, getpwuid}; + +#[path = "../../common/c_types.rs"] mod c_types; + +extern { + pub fn geteuid() -> libc::uid_t; +} + +pub unsafe fn getusername() -> String { + let passwd: *const c_passwd = getpwuid(geteuid()); + + let pw_name: *const libc::c_char = (*passwd).pw_name; + String::from_utf8_lossy(::std::ffi::CStr::from_ptr(pw_name).to_bytes()).to_string() +} diff --git a/src/whoami/platform/windows.rs b/src/whoami/platform/windows.rs new file mode 100644 index 000000000..a67ab9091 --- /dev/null +++ b/src/whoami/platform/windows.rs @@ -0,0 +1,27 @@ +/* + * This file is part of the uutils coreutils package. + * + * (c) Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use ::libc; +use std::mem; +use std::io::Write; + +extern "system" { + pub fn GetUserNameA(out: *mut libc::c_char, len: *mut libc::uint32_t) -> libc::uint8_t; +} + +#[allow(unused_unsafe)] +pub unsafe fn getusername() -> String { + // XXX: it may be possible that this isn't long enough. I don't know + let mut buffer: [libc::c_char; 2048] = mem::uninitialized(); + + if !GetUserNameA(buffer.as_mut_ptr(), &mut (buffer.len() as libc::uint32_t)) == 0 { + crash!(1, "username is too long"); + } + String::from_utf8_lossy(::std::ffi::CStr::from_ptr(buffer.as_ptr()).to_bytes()).to_string() +} diff --git a/src/whoami/whoami.rs b/src/whoami/whoami.rs index b29e0a5f8..b1e6d76a8 100644 --- a/src/whoami/whoami.rs +++ b/src/whoami/whoami.rs @@ -1,5 +1,5 @@ #![crate_name = "whoami"] -#![feature(collections, core, old_io, rustc_private, std_misc)] +#![feature(rustc_private)] /* * This file is part of the uutils coreutils package. @@ -12,62 +12,22 @@ /* last synced with: whoami (GNU coreutils) 8.21 */ -#![allow(non_camel_case_types)] - extern crate getopts; extern crate libc; -use std::old_io::print; +use std::io::Write; #[path = "../common/util.rs"] #[macro_use] mod util; - -#[cfg(unix)] -mod platform { - use super::libc; - use self::c_types::{c_passwd, getpwuid}; - - #[path = "../../common/c_types.rs"] mod c_types; - - extern { - pub fn geteuid() -> libc::uid_t; - } - - pub unsafe fn getusername() -> String { - let passwd: *const c_passwd = getpwuid(geteuid()); - - let pw_name: *const libc::c_char = (*passwd).pw_name; - String::from_utf8_lossy(::std::ffi::CStr::from_ptr(pw_name).to_bytes()).to_string() - } -} - -#[cfg(windows)] -mod platform { - pub use super::libc; - use std::mem; - - extern "system" { - pub fn GetUserNameA(out: *mut libc::c_char, len: *mut libc::uint32_t) -> libc::uint8_t; - } - - #[allow(unused_unsafe)] - pub unsafe fn getusername() -> String { - let mut buffer: [libc::c_char; 2048] = mem::uninitialized(); // XXX: it may be possible that this isn't long enough. I don't know - if !GetUserNameA(buffer.as_mut_ptr(), &mut (buffer.len() as libc::uint32_t)) == 0 { - crash!(1, "username is too long"); - } - String::from_utf8_lossy(::std::ffi::CStr::from_ptr(buffer.as_ptr()).to_bytes()).to_string() - } -} +mod platform; static NAME: &'static str = "whoami"; pub fn uumain(args: Vec) -> i32 { - let program = args[0].as_slice(); let opts = [ getopts::optflag("h", "help", "display this help and exit"), getopts::optflag("V", "version", "output version information and exit"), ]; - let matches = match getopts::getopts(args.tail(), &opts) { + let matches = match getopts::getopts(&args[1..], &opts) { Ok(m) => m, Err(f) => crash!(1, "{}", f), }; @@ -75,9 +35,9 @@ pub fn uumain(args: Vec) -> i32 { println!("whoami 1.0.0"); println!(""); println!("Usage:"); - println!(" {}", program); + println!(" {}", args[0]); println!(""); - print(getopts::usage("print effective userid", &opts).as_slice()); + println!("{}", getopts::usage("print effective userid", &opts)); return 0; } if matches.opt_present("version") { From 143aea72ee512b7998789d62d1bb264b9d475002 Mon Sep 17 00:00:00 2001 From: kwantam Date: Mon, 27 Apr 2015 17:38:39 -0400 Subject: [PATCH 2/5] fix `users` --- src/users/users.rs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/users/users.rs b/src/users/users.rs index ccc2ad699..8a13dcf2b 100644 --- a/src/users/users.rs +++ b/src/users/users.rs @@ -1,5 +1,5 @@ #![crate_name = "users"] -#![feature(collections, core, old_io, rustc_private, std_misc)] +#![feature(rustc_private)] /* * This file is part of the uutils coreutils package. @@ -13,13 +13,12 @@ /* last synced with: whoami (GNU coreutils) 8.22 */ // Allow dead code here in order to keep all fields, constants here, for consistency. -#![allow(dead_code, non_camel_case_types)] +#![allow(dead_code)] extern crate getopts; extern crate libc; use std::ffi::{CStr, CString}; -use std::old_io::print; use std::mem; use std::ptr; use utmpx::*; @@ -53,13 +52,12 @@ unsafe extern fn utmpxname(_file: *const libc::c_char) -> libc::c_int { static NAME: &'static str = "users"; pub fn uumain(args: Vec) -> i32 { - let program = args[0].as_slice(); let opts = [ getopts::optflag("h", "help", "display this help and exit"), getopts::optflag("V", "version", "output version information and exit"), ]; - let matches = match getopts::getopts(args.tail(), &opts) { + let matches = match getopts::getopts(&args[1..], &opts) { Ok(m) => m, Err(f) => panic!("{}", f), }; @@ -68,9 +66,9 @@ pub fn uumain(args: Vec) -> i32 { println!("users 1.0.0"); println!(""); println!("Usage:"); - println!(" {} [OPTION]... [FILE]", program); + println!(" {} [OPTION]... [FILE]", args[0]); println!(""); - print(getopts::usage("Output who is currently logged in according to FILE.", &opts).as_slice()); + println!("{}", getopts::usage("Output who is currently logged in according to FILE.", &opts)); return 0; } @@ -79,10 +77,11 @@ pub fn uumain(args: Vec) -> i32 { return 0; } - let mut filename = DEFAULT_FILE; - if matches.free.len() > 0 { - filename = matches.free[0].as_slice(); - } + let filename = if matches.free.len() > 0 { + matches.free[0].as_ref() + } else { + DEFAULT_FILE + }; exec(filename); From a122849e7cacd4d574db2dd343ba047240148727 Mon Sep 17 00:00:00 2001 From: kwantam Date: Mon, 27 Apr 2015 18:19:56 -0400 Subject: [PATCH 3/5] fix `wc` --- src/wc/wc.rs | 61 +++++++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/src/wc/wc.rs b/src/wc/wc.rs index 840da2be7..7ed4fd65d 100644 --- a/src/wc/wc.rs +++ b/src/wc/wc.rs @@ -1,5 +1,5 @@ #![crate_name = "wc"] -#![feature(collections, old_io, old_path, rustc_private, str_words)] +#![feature(rustc_private, path_ext)] /* * This file is part of the uutils coreutils package. @@ -13,15 +13,15 @@ extern crate getopts; extern crate libc; -use std::ascii::AsciiExt; -use std::str::from_utf8; -use std::old_io::{print, File, BufferedReader}; -use std::old_io::fs::PathExtensions; -use std::old_io::stdio::stdin_raw; -use std::result::Result as StdResult; -use std::borrow::IntoCow; use getopts::Matches; +use std::ascii::AsciiExt; +use std::fs::{File, PathExt}; +use std::io::{stdin, BufRead, BufReader, Read, Write}; +use std::path::Path; +use std::result::Result as StdResult; +use std::str::from_utf8; + #[path = "../common/util.rs"] #[macro_use] mod util; @@ -49,7 +49,7 @@ pub fn uumain(args: Vec) -> i32 { getopts::optflag("V", "version", "output version information and exit"), ]; - let matches = match getopts::getopts(args.tail(), &opts) { + let mut matches = match getopts::getopts(&args[1..], &opts) { Ok(m) => m, Err(f) => { crash!(1, "Invalid options\n{}", f) @@ -60,8 +60,7 @@ pub fn uumain(args: Vec) -> i32 { println!("Usage:"); println!(" {0} [OPTION]... [FILE]...", program); println!(""); - print(&getopts::usage("Print newline, word and byte counts for each FILE", &opts)[..]); - println!(""); + println!("{}", getopts::usage("Print newline, word and byte counts for each FILE", &opts)); println!("With no FILE, or when FILE is -, read standard input."); return 0; } @@ -71,13 +70,11 @@ pub fn uumain(args: Vec) -> i32 { return 0; } - let files = if matches.free.is_empty() { - vec!["-".to_string()].into_cow() - } else { - matches.free[..].into_cow() - }; + if matches.free.is_empty() { + matches.free.push("-".to_string()); + } - match wc(&files[..], &matches) { + match wc(&matches) { Ok(()) => ( /* pass */ ), Err(e) => return e } @@ -97,7 +94,7 @@ fn is_word_seperator(byte: u8) -> bool { byte == SPACE || byte == TAB || byte == CR || byte == SYN || byte == FF } -pub fn wc(files: &[String], matches: &Matches) -> StdResult<(), i32> { +pub fn wc(matches: &Matches) -> StdResult<(), i32> { let mut total_line_count: usize = 0; let mut total_word_count: usize = 0; let mut total_char_count: usize = 0; @@ -107,7 +104,7 @@ pub fn wc(files: &[String], matches: &Matches) -> StdResult<(), i32> { let mut results = vec!(); let mut max_str_len: usize = 0; - for path in files.iter() { + for path in matches.free.iter() { let mut reader = try!(open(&path[..])); let mut line_count: usize = 0; @@ -115,10 +112,18 @@ pub fn wc(files: &[String], matches: &Matches) -> StdResult<(), i32> { let mut byte_count: usize = 0; let mut char_count: usize = 0; let mut longest_line_length: usize = 0; + let mut raw_line = Vec::new(); // reading from a TTY seems to raise a condition on, rather than return Some(0) like a file. // hence the option wrapped in a result here - while let Ok(raw_line) = reader.read_until(LF) { + while match reader.read_until(LF, &mut raw_line) { + Ok(n) if n > 0 => true, + Err(ref e) if raw_line.len() > 0 => { + show_warning!("Error while reading {}: {}", path, e); + raw_line.len() > 0 + }, + _ => false, + } { // GNU 'wc' only counts lines that end in LF as lines if *raw_line.last().unwrap() == LF { line_count += 1; @@ -130,7 +135,7 @@ pub fn wc(files: &[String], matches: &Matches) -> StdResult<(), i32> { let current_char_count; match from_utf8(&raw_line[..]) { Ok(line) => { - word_count += line.words().count(); + word_count += line.split_whitespace().count(); current_char_count = line.chars().count(); }, Err(..) => { @@ -145,6 +150,8 @@ pub fn wc(files: &[String], matches: &Matches) -> StdResult<(), i32> { // matches GNU 'wc' behaviour longest_line_length = current_char_count - 1; } + + raw_line.truncate(0); } results.push(Result { @@ -173,7 +180,7 @@ pub fn wc(files: &[String], matches: &Matches) -> StdResult<(), i32> { print_stats(&result.filename[..], result.lines, result.words, result.chars, result.bytes, result.max_line_length, matches, max_str_len); } - if files.len() > 1 { + if matches.free.len() > 1 { print_stats("total", total_line_count, total_word_count, total_char_count, total_byte_count, total_longest_line_length, matches, max_str_len); } @@ -217,10 +224,10 @@ fn print_stats(filename: &str, line_count: usize, word_count: usize, char_count: } } -fn open(path: &str) -> StdResult>, i32> { +fn open(path: &str) -> StdResult>, i32> { if "-" == path { - let reader = Box::new(stdin_raw()) as Box; - return Ok(BufferedReader::new(reader)); + let reader = Box::new(stdin()) as Box; + return Ok(BufReader::new(reader)); } let fpath = Path::new(path); @@ -229,8 +236,8 @@ fn open(path: &str) -> StdResult>, i32> { } match File::open(&fpath) { Ok(fd) => { - let reader = Box::new(fd) as Box; - Ok(BufferedReader::new(reader)) + let reader = Box::new(fd) as Box; + Ok(BufReader::new(reader)) } Err(e) => { show_error!("wc: {}: {}", path, e); From 1d62f35b45dcdf32039f39209ece4ae2a7c1632e Mon Sep 17 00:00:00 2001 From: kwantam Date: Mon, 27 Apr 2015 22:00:19 -0400 Subject: [PATCH 4/5] fix `uptime` --- src/uptime/uptime.rs | 57 ++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/src/uptime/uptime.rs b/src/uptime/uptime.rs index c6a4a1845..580576c2f 100644 --- a/src/uptime/uptime.rs +++ b/src/uptime/uptime.rs @@ -1,5 +1,5 @@ #![crate_name = "uptime"] -#![feature(collections, core, old_io, old_path, rustc_private, std_misc, str_words)] +#![feature(rustc_private)] /* * This file is part of the uutils coreutils package. @@ -12,15 +12,14 @@ /* last synced with: cat (GNU coreutils) 8.13 */ -#![allow(non_camel_case_types)] - extern crate getopts; extern crate libc; extern crate time as rtime; use std::ffi::CString; +use std::fs::File; +use std::io::{Read, Write}; use std::mem::transmute; -use std::old_io::{print, File}; use std::ptr::null; use libc::{time_t, c_double, c_int, c_char}; use utmpx::*; @@ -61,7 +60,7 @@ pub fn uumain(args: Vec) -> i32 { getopts::optflag("v", "version", "output version information and exit"), getopts::optflag("h", "help", "display this help and exit"), ]; - let matches = match getopts::getopts(args.tail(), &opts) { + let matches = match getopts::getopts(&args[1..], &opts) { Ok(m) => m, Err(f) => crash!(1, "Invalid options\n{}", f) }; @@ -73,9 +72,9 @@ pub fn uumain(args: Vec) -> i32 { println!("Usage:"); println!(" {0} [OPTION]", program); println!(""); - print(getopts::usage("Print the current time, the length of time the system has been up,\n\ + println!("{}", getopts::usage("Print the current time, the length of time the system has been up,\n\ the number of users on the system, and the average number of jobs\n\ - in the run queue over the last 1, 5 and 15 minutes.", &opts).as_slice()); + in the run queue over the last 1, 5 and 15 minutes.", &opts)); return 0; } @@ -98,7 +97,7 @@ fn print_loadavg() { } else { print!("load average: "); - for n in range(0, loads) { + for n in 0..loads { print!("{:.2}{}", avg[n as usize], if n == loads - 1 { "\n" } else { ", " } ); } @@ -164,27 +163,23 @@ fn print_time() { #[cfg(unix)] fn get_uptime(boot_time: Option) -> i64 { - let proc_uptime = File::open(&Path::new("/proc/uptime")) - .read_to_string(); + let mut proc_uptime = String::new(); - let uptime_text = match proc_uptime { - Ok(s) => s, - _ => return match boot_time { - Some(t) => { - let now = rtime::get_time().sec; - let time = t as i64; - ((now - time) * 100) as i64 // Return in ms - }, - _ => -1 - } - }; - - match uptime_text.as_slice().words().next() { - Some(s) => match s.replace(".", "").as_slice().parse() { - Ok(n) => n, - Err(_) => -1 - }, - None => -1 + if let Some(n) = + File::open("/proc/uptime").ok() + .and_then(|mut f| f.read_to_string(&mut proc_uptime).ok()) + .and_then(|_| proc_uptime.split_whitespace().next()) + .and_then(|s| s.replace(".", "").parse().ok()) { + n + } else { + match boot_time { + Some(t) => { + let now = rtime::get_time().sec; + let time = t as i64; + ((now - time) * 100) + }, + _ => -1, + } } } @@ -198,12 +193,12 @@ fn print_uptime(upsecs: i64) { let uphours = (upsecs - (updays * 86400)) / 3600; let upmins = (upsecs - (updays * 86400) - (uphours * 3600)) / 60; if updays == 1 { - print!("up {:1} day, {:2}:{:02}, ", updays, uphours, upmins); + print!("up {:1} day, {:2}:{:02}, ", updays, uphours, upmins); } else if updays > 1 { - print!("up {:1} days, {:2}:{:02}, ", updays, uphours, upmins); + print!("up {:1} days, {:2}:{:02}, ", updays, uphours, upmins); } else { - print!("up {:2}:{:02}, ", uphours, upmins); + print!("up {:2}:{:02}, ", uphours, upmins); } } From 2e237dd6bbff68addaf7af03dd7fa9ea4c79e951 Mon Sep 17 00:00:00 2001 From: kwantam Date: Mon, 27 Apr 2015 22:06:19 -0400 Subject: [PATCH 5/5] fix `uname` --- src/uname/uname.rs | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/uname/uname.rs b/src/uname/uname.rs index 33e601d9d..18cc80f67 100644 --- a/src/uname/uname.rs +++ b/src/uname/uname.rs @@ -1,5 +1,5 @@ #![crate_name = "uname"] -#![feature(collections, core, old_io, rustc_private, std_misc)] +#![feature(rustc_private)] /* * This file is part of the uutils coreutils package. @@ -12,20 +12,18 @@ /* last synced with: uname (GNU coreutils) 8.21 */ -#![allow(non_camel_case_types)] - extern crate getopts; extern crate libc; use std::ffi::CStr; +use std::io::Write; use std::mem::uninitialized; -use std::old_io::print; use c_types::utsname; #[path = "../common/util.rs"] #[macro_use] mod util; #[path = "../common/c_types.rs"] mod c_types; -struct utsrust { +struct Uts { sysname: String, nodename: String, release: String, @@ -41,10 +39,10 @@ unsafe fn string_from_c_str(ptr: *const i8) -> String { String::from_utf8_lossy(CStr::from_ptr(ptr).to_bytes()).to_string() } -unsafe fn getuname() -> utsrust { +unsafe fn getuname() -> Uts { let mut uts: utsname = uninitialized(); uname(&mut uts); - utsrust { + Uts { sysname: string_from_c_str(uts.sysname.as_ptr() as *const i8), nodename: string_from_c_str(uts.nodename.as_ptr() as *const i8), release: string_from_c_str(uts.release.as_ptr() as *const i8), @@ -57,7 +55,6 @@ unsafe fn getuname() -> utsrust { static NAME: &'static str = "uname"; pub fn uumain(args: Vec) -> i32 { - let program = args[0].as_slice(); let opts = [ getopts::optflag("h", "help", "display this help and exit"), getopts::optflag("a", "all", "Behave as though all of the options -mnrsv were specified."), @@ -68,7 +65,7 @@ pub fn uumain(args: Vec) -> i32 { getopts::optflag("s", "sysname", "print the operating system name."), getopts::optflag("v", "version", "print the operating system version."), ]; - let matches = match getopts::getopts(args.tail(), &opts) { + let matches = match getopts::getopts(&args[1..], &opts) { Ok(m) => m, Err(f) => crash!(1, "{}", f), }; @@ -76,36 +73,36 @@ pub fn uumain(args: Vec) -> i32 { println!("uname 1.0.0"); println!(""); println!("Usage:"); - println!(" {}", program); + println!(" {}", args[0]); println!(""); - print(getopts::usage("The uname utility writes symbols representing one or more system characteristics to the standard output.", &opts).as_slice()); + println!("{}", getopts::usage("The uname utility writes symbols representing one or more system characteristics to the standard output.", &opts)); return 0; } let uname = unsafe { getuname() }; let mut output = String::new(); if matches.opt_present("sysname") || matches.opt_present("all") || !matches.opts_present(&["nodename".to_string(), "release".to_string(), "version".to_string(), "machine".to_string()]) { - output.push_str(uname.sysname.as_slice()); + output.push_str(uname.sysname.as_ref()); output.push_str(" "); } if matches.opt_present("nodename") || matches.opt_present("all") { - output.push_str(uname.nodename.as_slice()); + output.push_str(uname.nodename.as_ref()); output.push_str(" "); } if matches.opt_present("release") || matches.opt_present("all") { - output.push_str(uname.release.as_slice()); + output.push_str(uname.release.as_ref()); output.push_str(" "); } if matches.opt_present("version") || matches.opt_present("all") { - output.push_str(uname.version.as_slice()); + output.push_str(uname.version.as_ref()); output.push_str(" "); } if matches.opt_present("machine") || matches.opt_present("all") { - output.push_str(uname.machine.as_slice()); + output.push_str(uname.machine.as_ref()); output.push_str(" "); } - println!("{}", output.as_slice().trim()); + println!("{}", output.trim()); 0 }