From f0e25e5537d06d176c0b9827da02b12b893f9261 Mon Sep 17 00:00:00 2001 From: bootandy Date: Tue, 13 Mar 2018 15:45:23 -0400 Subject: [PATCH 1/3] Fix edgecase for du on mac When du encounters a file that cannot be read it logs an error and continues to analysise the rest of the directory. This behaviour brings it inline with the original du. --- src/du/du.rs | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/du/du.rs b/src/du/du.rs index eda6755eb..59d3bb022 100644 --- a/src/du/du.rs +++ b/src/du/du.rs @@ -91,16 +91,23 @@ fn du(mut my_stat: Stat, options: &Options, depth: usize) -> Box match fs::symlink_metadata(entry.path()) { + Ok(_) => { + let this_stat = Stat::new(entry.path()); + if this_stat.is_dir { + futures.push(du(this_stat, options, depth + 1)); + } else { + my_stat.size += this_stat.size; + my_stat.blocks += this_stat.blocks; + if options.all { + stats.push(this_stat); + } + } + } + Err(error) => show_error!("{}", error), + }, + Err(error) => show_error!("{}", error), } } } From be79a705722ee100e498db0f0bdd0b93fd7db464 Mon Sep 17 00:00:00 2001 From: bootandy Date: Wed, 14 Mar 2018 16:26:22 -0400 Subject: [PATCH 2/3] Refactor Stat::new to return Result This was to remove the double call to fs::symlink_metadata --- src/du/du.rs | 148 +++++++++++++++++++++++++++------------------------ 1 file changed, 78 insertions(+), 70 deletions(-) diff --git a/src/du/du.rs b/src/du/du.rs index 59d3bb022..67d3cb3db 100644 --- a/src/du/du.rs +++ b/src/du/du.rs @@ -16,7 +16,7 @@ extern crate uucore; use std::fs; use std::iter; -use std::io::{stderr, Write}; +use std::io::{stderr, Result, Write}; use std::os::unix::fs::MetadataExt; use std::path::PathBuf; use time::Timespec; @@ -54,17 +54,21 @@ struct Stat { } impl Stat { - fn new(path: PathBuf) -> Stat { - let metadata = safe_unwrap!(fs::symlink_metadata(&path)); - Stat { - path: path, - is_dir: metadata.is_dir(), - size: metadata.len(), - blocks: metadata.blocks() as u64, - nlink: metadata.nlink() as u64, - created: metadata.mtime() as u64, - accessed: metadata.atime() as u64, - modified: metadata.mtime() as u64, + fn new(path: PathBuf) -> Result { + match fs::symlink_metadata(&path) { + Ok(metadata) => { + return Ok(Stat { + path: path, + is_dir: metadata.is_dir(), + size: metadata.len(), + blocks: metadata.blocks() as u64, + nlink: metadata.nlink() as u64, + created: metadata.mtime() as u64, + accessed: metadata.atime() as u64, + modified: metadata.mtime() as u64, + }) + } + Err(e) => Err(e), } } } @@ -92,9 +96,8 @@ fn du(mut my_stat: Stat, options: &Options, depth: usize) -> Box match fs::symlink_metadata(entry.path()) { - Ok(_) => { - let this_stat = Stat::new(entry.path()); + Ok(entry) => match Stat::new(entry.path()) { + Ok(this_stat) => { if this_stat.is_dir { futures.push(du(this_stat, options, depth + 1)); } else { @@ -334,67 +337,72 @@ Try '{} --help' for more information.", let mut grand_total = 0; for path_str in strs.into_iter() { let path = PathBuf::from(path_str); - let iter = du(Stat::new(path), &options, 0).into_iter(); - let (_, len) = iter.size_hint(); - let len = len.unwrap(); - for (index, stat) in iter.enumerate() { - let size = if matches.opt_present("apparent-size") { - stat.nlink * stat.size - } else { - // C's stat is such that each block is assume to be 512 bytes - // See: http://linux.die.net/man/2/stat - stat.blocks * 512 - }; - if matches.opt_present("time") { - let tm = { - let (secs, nsecs) = { - let time = match matches.opt_str("time") { - Some(s) => match &s[..] { - "accessed" => stat.accessed, - "created" => stat.created, - "modified" => stat.modified, - _ => { - show_error!( - "invalid argument 'modified' for '--time' + match Stat::new(path) { + Ok(stat) => { + let iter = du(stat, &options, 0).into_iter(); + let (_, len) = iter.size_hint(); + let len = len.unwrap(); + for (index, stat) in iter.enumerate() { + let size = if matches.opt_present("apparent-size") { + stat.nlink * stat.size + } else { + // C's stat is such that each block is assume to be 512 bytes + // See: http://linux.die.net/man/2/stat + stat.blocks * 512 + }; + if matches.opt_present("time") { + let tm = { + let (secs, nsecs) = { + let time = match matches.opt_str("time") { + Some(s) => match &s[..] { + "accessed" => stat.accessed, + "created" => stat.created, + "modified" => stat.modified, + _ => { + show_error!( + "invalid argument 'modified' for '--time' Valid arguments are: - 'accessed', 'created', 'modified' Try '{} --help' for more information.", - NAME - ); - return 1; - } - }, - None => stat.modified, + NAME + ); + return 1; + } + }, + None => stat.modified, + }; + ((time / 1000) as i64, (time % 1000 * 1000000) as i32) + }; + time::at(Timespec::new(secs, nsecs)) }; - ((time / 1000) as i64, (time % 1000 * 1000000) as i32) - }; - time::at(Timespec::new(secs, nsecs)) - }; - if !summarize || (summarize && index == len - 1) { - let time_str = tm.strftime(time_format_str).unwrap(); - print!( - "{}\t{}\t{}{}", - convert_size(size), - time_str, - stat.path.display(), - line_separator - ); - } - } else { - if !summarize || (summarize && index == len - 1) { - print!( - "{}\t{}{}", - convert_size(size), - stat.path.display(), - line_separator - ); + if !summarize || (summarize && index == len - 1) { + let time_str = tm.strftime(time_format_str).unwrap(); + print!( + "{}\t{}\t{}{}", + convert_size(size), + time_str, + stat.path.display(), + line_separator + ); + } + } else { + if !summarize || (summarize && index == len - 1) { + print!( + "{}\t{}{}", + convert_size(size), + stat.path.display(), + line_separator + ); + } + } + if options.total && index == (len - 1) { + // The last element will be the total size of the the path under + // path_str. We add it to the grand total. + grand_total += size; + } } } - if options.total && index == (len - 1) { - // The last element will be the total size of the the path under - // path_str. We add it to the grand total. - grand_total += size; - } + Err(error) => show_error!("{}", error), } } From 8f67c8fef27e1b79408d7f048de941dc3da4a3eb Mon Sep 17 00:00:00 2001 From: bootandy Date: Thu, 15 Mar 2018 14:56:21 -0400 Subject: [PATCH 3/3] du: refactor to use ? shortcut --- src/du/du.rs | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/du/du.rs b/src/du/du.rs index 67d3cb3db..e87308952 100644 --- a/src/du/du.rs +++ b/src/du/du.rs @@ -55,21 +55,17 @@ struct Stat { impl Stat { fn new(path: PathBuf) -> Result { - match fs::symlink_metadata(&path) { - Ok(metadata) => { - return Ok(Stat { - path: path, - is_dir: metadata.is_dir(), - size: metadata.len(), - blocks: metadata.blocks() as u64, - nlink: metadata.nlink() as u64, - created: metadata.mtime() as u64, - accessed: metadata.atime() as u64, - modified: metadata.mtime() as u64, - }) - } - Err(e) => Err(e), - } + let metadata = fs::symlink_metadata(&path)?; + Ok(Stat { + path: path, + is_dir: metadata.is_dir(), + size: metadata.len(), + blocks: metadata.blocks() as u64, + nlink: metadata.nlink() as u64, + created: metadata.mtime() as u64, + accessed: metadata.atime() as u64, + modified: metadata.mtime() as u64, + }) } }