1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

Fix du, which closes #46, and id when not compiling on Linux

This commit is contained in:
Arcterus 2014-02-18 17:10:32 -08:00
parent cca19911ad
commit 63f6c9719b
3 changed files with 76 additions and 63 deletions

103
du/du.rs
View file

@ -1,4 +1,4 @@
#[link(name="du", vers="1.0.0", author="Derek Chiang")]; #[crate_id(name="du", vers="1.0.0", author="Derek Chiang")];
/* /*
* This file is part of the uutils coreutils package. * This file is part of the uutils coreutils package.
@ -9,19 +9,24 @@
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
extern mod extra; #[feature(macro_rules)];
extern crate extra;
extern crate getopts;
extern crate sync;
use std::os; use std::os;
use std::io::stderr;
use std::io::fs; use std::io::fs;
use std::io::FileStat; use std::io::FileStat;
use std::option::Option; use std::option::Option;
use std::path::Path; use std::path::Path;
use extra::arc::Arc;
use extra::future::Future;
use extra::getopts::groups;
use extra::time::Timespec; use extra::time::Timespec;
use sync::{Arc, Future};
#[path = "../util.rs"]
mod util;
static NAME: &'static str = "du";
static VERSION: &'static str = "1.0.0"; static VERSION: &'static str = "1.0.0";
struct Options { struct Options {
@ -35,12 +40,12 @@ fn du(path: &Path, options_arc: Arc<Options>, depth: uint) -> ~[Arc<FileStat>] {
let mut stats = ~[]; let mut stats = ~[];
let mut futures = ~[]; let mut futures = ~[];
let options = options_arc.get(); let options = options_arc.get();
let mut my_stat = path.stat(); let mut my_stat = safe_unwrap!(path.stat());
for f in fs::readdir(path).move_iter() { for f in safe_unwrap!(fs::readdir(path)).move_iter() {
match f.is_file() { match f.is_file() {
true => { true => {
let stat = f.stat(); let stat = safe_unwrap!(f.stat());
my_stat.size += stat.size; my_stat.size += stat.size;
my_stat.unstable.blocks += stat.unstable.blocks; my_stat.unstable.blocks += stat.unstable.blocks;
if options.all { if options.all {
@ -49,7 +54,7 @@ fn du(path: &Path, options_arc: Arc<Options>, depth: uint) -> ~[Arc<FileStat>] {
} }
false => { false => {
let oa_clone = options_arc.clone(); let oa_clone = options_arc.clone();
futures.push(do Future::spawn { du(&f, oa_clone, depth + 1) }) futures.push(Future::spawn(proc() { du(&f, oa_clone, depth + 1) }))
} }
} }
} }
@ -77,88 +82,86 @@ fn main() {
let program = args[0].clone(); let program = args[0].clone();
let opts = ~[ let opts = ~[
// In task // In task
groups::optflag("a", "all", " write counts for all files, not just directories"), getopts::optflag("a", "all", " write counts for all files, not just directories"),
// In main // In main
groups::optflag("", "apparent-size", "print apparent sizes, rather than disk usage; getopts::optflag("", "apparent-size", "print apparent sizes, rather than disk usage;
although the apparent size is usually smaller, it may be larger due to holes although the apparent size is usually smaller, it may be larger due to holes
in ('sparse') files, internal fragmentation, indirect blocks, and the like"), in ('sparse') files, internal fragmentation, indirect blocks, and the like"),
// In main // In main
groups::optopt("B", "block-size", "scale sizes by SIZE before printing them. getopts::optopt("B", "block-size", "scale sizes by SIZE before printing them.
E.g., '-BM' prints sizes in units of 1,048,576 bytes. See SIZE format below.", E.g., '-BM' prints sizes in units of 1,048,576 bytes. See SIZE format below.",
"SIZE"), "SIZE"),
// In main // In main
groups::optflag("b", "bytes", "equivalent to '--apparent-size --block-size=1'"), getopts::optflag("b", "bytes", "equivalent to '--apparent-size --block-size=1'"),
// In main // In main
groups::optflag("c", "total", "produce a grand total"), getopts::optflag("c", "total", "produce a grand total"),
// In task // In task
// groups::optflag("D", "dereference-args", "dereference only symlinks that are listed // getopts::optflag("D", "dereference-args", "dereference only symlinks that are listed
// on the command line"), // on the command line"),
// In main // In main
// groups::optopt("", "files0-from", "summarize disk usage of the NUL-terminated file // getopts::optopt("", "files0-from", "summarize disk usage of the NUL-terminated file
// names specified in file F; // names specified in file F;
// If F is - then read names from standard input", "F"), // If F is - then read names from standard input", "F"),
// // In task // // In task
// groups::optflag("H", "", "equivalent to --dereference-args (-D)"), // getopts::optflag("H", "", "equivalent to --dereference-args (-D)"),
// In main // In main
groups::optflag("h", "human-readable", "print sizes in human readable format (e.g., 1K 234M 2G)"), getopts::optflag("h", "human-readable", "print sizes in human readable format (e.g., 1K 234M 2G)"),
// In main // In main
groups::optflag("", "si", "like -h, but use powers of 1000 not 1024"), getopts::optflag("", "si", "like -h, but use powers of 1000 not 1024"),
// In main // In main
groups::optflag("k", "", "like --block-size=1K"), getopts::optflag("k", "", "like --block-size=1K"),
// In task // In task
groups::optflag("l", "count-links", "count sizes many times if hard linked"), getopts::optflag("l", "count-links", "count sizes many times if hard linked"),
// // In main // // In main
groups::optflag("m", "", "like --block-size=1M"), getopts::optflag("m", "", "like --block-size=1M"),
// // In task // // In task
// groups::optflag("L", "dereference", "dereference all symbolic links"), // getopts::optflag("L", "dereference", "dereference all symbolic links"),
// // In task // // In task
// groups::optflag("P", "no-dereference", "don't follow any symbolic links (this is the default)"), // getopts::optflag("P", "no-dereference", "don't follow any symbolic links (this is the default)"),
// // In main // // In main
groups::optflag("0", "null", "end each output line with 0 byte rather than newline"), getopts::optflag("0", "null", "end each output line with 0 byte rather than newline"),
// In main // In main
groups::optflag("S", "separate-dirs", "do not include size of subdirectories"), getopts::optflag("S", "separate-dirs", "do not include size of subdirectories"),
// In main // In main
groups::optflag("s", "summarize", "display only a total for each argument"), getopts::optflag("s", "summarize", "display only a total for each argument"),
// // In task // // In task
// groups::optflag("x", "one-file-system", "skip directories on different file systems"), // getopts::optflag("x", "one-file-system", "skip directories on different file systems"),
// // In task // // In task
// groups::optopt("X", "exclude-from", "exclude files that match any pattern in FILE", "FILE"), // getopts::optopt("X", "exclude-from", "exclude files that match any pattern in FILE", "FILE"),
// // In task // // In task
// groups::optopt("", "exclude", "exclude files that match PATTERN", "PATTERN"), // getopts::optopt("", "exclude", "exclude files that match PATTERN", "PATTERN"),
// In main // In main
groups::optopt("d", "max-depth", "print the total for a directory (or file, with --all) getopts::optopt("d", "max-depth", "print the total for a directory (or file, with --all)
only if it is N or fewer levels below the command only if it is N or fewer levels below the command
line argument; --max-depth=0 is the same as --summarize", "N"), line argument; --max-depth=0 is the same as --summarize", "N"),
// In main // In main
groups::optflagopt("", "time", "show time of the last modification of any file in the getopts::optflagopt("", "time", "show time of the last modification of any file in the
directory, or any of its subdirectories. If WORD is given, show time as WORD instead of modification time: directory, or any of its subdirectories. If WORD is given, show time as WORD instead of modification time:
atime, access, use, ctime or status", "WORD"), atime, access, use, ctime or status", "WORD"),
// In main // In main
groups::optopt("", "time-style", "show times using style STYLE: getopts::optopt("", "time-style", "show times using style STYLE:
full-iso, long-iso, iso, +FORMAT FORMAT is interpreted like 'date'", "STYLE"), full-iso, long-iso, iso, +FORMAT FORMAT is interpreted like 'date'", "STYLE"),
groups::optflag("", "help", "display this help and exit"), getopts::optflag("", "help", "display this help and exit"),
groups::optflag("", "version", "output version information and exit"), getopts::optflag("", "version", "output version information and exit"),
]; ];
let matches = match groups::getopts(args.tail(), opts) { let matches = match getopts::getopts(args.tail(), opts) {
Ok(m) => m, Ok(m) => m,
Err(f) => { Err(f) => {
writeln!(&mut stderr() as &mut Writer, show_error!(1, "Invalid options\n{}", f.to_err_msg());
"Invalid options\n{}", f.to_err_msg());
os::set_exit_status(1);
return return
} }
}; };
if matches.opt_present("help") { if matches.opt_present("help") {
println("du " + VERSION + " - estimate file space usage"); println!("du {} - estimate file space usage", VERSION);
println(""); println!("");
println("Usage:"); println!("Usage:");
println!(" {0:s} [OPTION]... [FILE]...", program); println!(" {0:s} [OPTION]... [FILE]...", program);
println!(" {0:s} [OPTION]... --files0-from=F", program); println!(" {0:s} [OPTION]... --files0-from=F", program);
println(""); println!("");
println(groups::usage("Summarize disk usage of each FILE, recursively for directories.", opts)); println!("{}", getopts::usage("Summarize disk usage of each FILE, recursively for directories.", opts));
println("Display values are in units of the first available SIZE from println!("Display values are in units of the first available SIZE from
--block-size, and the DU_BLOCK_SIZE, BLOCK_SIZE and BLOCKSIZE environ --block-size, and the DU_BLOCK_SIZE, BLOCK_SIZE and BLOCKSIZE environ
ment variables. Otherwise, units default to 1024 bytes (or 512 if ment variables. Otherwise, units default to 1024 bytes (or 512 if
POSIXLY_CORRECT is set). POSIXLY_CORRECT is set).
@ -277,7 +280,7 @@ ers of 1000).");
"long-iso" => "%Y-%m-%d %H:%M", "long-iso" => "%Y-%m-%d %H:%M",
"iso" => "%Y-%m-%d", "iso" => "%Y-%m-%d",
_ => { _ => {
println(" println!("
du: invalid argument 'awdwa' for 'time style' du: invalid argument 'awdwa' for 'time style'
Valid arguments are: Valid arguments are:
- 'full-iso' - 'full-iso'
@ -319,7 +322,7 @@ Try 'du --help' for more information.");
"created" => stat.created, "created" => stat.created,
"modified" => stat.modified, "modified" => stat.modified,
_ => { _ => {
println("du: invalid argument 'modified' for '--time' println!("du: invalid argument 'modified' for '--time'
Valid arguments are: Valid arguments are:
- 'accessed', 'created', 'modified' - 'accessed', 'created', 'modified'
Try 'du --help' for more information."); Try 'du --help' for more information.");
@ -337,7 +340,7 @@ Try 'du --help' for more information.");
} else { } else {
print!("{:<10} {}", convert_size(size), stat.path.display()); print!("{:<10} {}", convert_size(size), stat.path.display());
} }
print(line_separator); print!("{}", line_separator);
if options.total && index == (len - 1) { if options.total && index == (len - 1) {
// The last element will be the total size of the the path under // The last element will be the total size of the the path under
// path_str. We add it to the grand total. // path_str. We add it to the grand total.
@ -348,6 +351,6 @@ Try 'du --help' for more information.");
if options.total { if options.total {
print!("{:<10} total", convert_size(grand_total)); print!("{:<10} total", convert_size(grand_total));
print(line_separator); print!("{}", line_separator);
} }
} }

View file

@ -41,27 +41,27 @@ struct c_group {
#[cfg(not(target_os = "linux"))] #[cfg(not(target_os = "linux"))]
mod audit { mod audit {
pub use std::unstable::intrinsic::uninit; pub use std::unstable::intrinsics::uninit;
use std::libc::{pid_t, c_uint, uint64_t, dev_t}; use std::libc::{uid_t, pid_t, c_int, c_uint, uint64_t, dev_t};
type au_id_t = uid_t; pub type au_id_t = uid_t;
type au_asid_t = pid_t; pub type au_asid_t = pid_t;
type au_event_t = c_uint; pub type au_event_t = c_uint;
type au_emod_t = c_uint; pub type au_emod_t = c_uint;
type au_class_t = c_int; pub type au_class_t = c_int;
struct au_mask { pub struct au_mask {
am_success: c_uint, am_success: c_uint,
am_failure: c_uint am_failure: c_uint
} }
type au_mask_t = au_mask; pub type au_mask_t = au_mask;
struct au_tid_addr { pub struct au_tid_addr {
port: dev_t, port: dev_t,
} }
type au_tid_addr_t = au_tid_addr; pub type au_tid_addr_t = au_tid_addr;
struct c_auditinfo_addr { pub struct c_auditinfo_addr {
ai_auid: au_id_t, /* Audit user ID */ ai_auid: au_id_t, /* Audit user ID */
ai_mask: au_mask_t, /* Audit masks. */ ai_mask: au_mask_t, /* Audit masks. */
ai_termid: au_tid_addr_t, /* Terminal ID. */ ai_termid: au_tid_addr_t, /* Terminal ID. */

10
util.rs
View file

@ -45,3 +45,13 @@ macro_rules! safe_writeln(
} }
) )
) )
#[macro_export]
macro_rules! safe_unwrap(
($exp:expr) => (
match $exp {
Ok(m) => m,
Err(f) => crash!(1, "{}", f.to_str())
}
)
)