Bring over dev/inode pair changes from bootandy's repo

This commit is contained in:
Joe Ardent
2018-03-21 23:47:37 -07:00
parent e75a666a4c
commit c127580057
2 changed files with 66 additions and 22 deletions
+8 -2
View File
@@ -10,7 +10,7 @@ use clap::{App, AppSettings, Arg};
static DEFAULT_NUMBER_OF_LINES: &'static str = "15";
fn main() {
let options = App::new("Trailing args example")
let options = App::new("Dust")
.setting(AppSettings::TrailingVarArg)
.arg(
Arg::with_name("number_of_lines")
@@ -19,6 +19,11 @@ fn main() {
.takes_value(true)
.default_value(DEFAULT_NUMBER_OF_LINES),
)
.arg(
Arg::with_name("use_apparent_size")
.short("s")
.help("If set will use file length. Otherwise we use blocks"),
)
.arg(Arg::with_name("inputs").multiple(true))
.get_matches();
@@ -29,8 +34,9 @@ fn main() {
}
};
let number_of_lines = value_t!(options.value_of("number_of_lines"), usize).unwrap();
let use_apparent_size = options.is_present("use_apparent_size");
let (permissions, results) = get_dir_tree(&filenames);
let (permissions, results) = get_dir_tree(&filenames, use_apparent_size);
let slice_it = find_big_ones(&results, number_of_lines);
display(permissions, &slice_it);
}
+58 -20
View File
@@ -10,7 +10,7 @@ use dust::{DirEnt, Node};
extern crate ansi_term;
use self::ansi_term::Colour::Fixed;
pub fn get_dir_tree(filenames: &Vec<&str>) -> (bool, Vec<Node>) {
pub fn get_dir_tree(filenames: &Vec<&str>, apparent_size: bool) -> (bool, Vec<Node>) {
let mut permissions = true;
let mut results = vec![];
for &b in filenames {
@@ -18,58 +18,93 @@ pub fn get_dir_tree(filenames: &Vec<&str>) -> (bool, Vec<Node>) {
while new_name.chars().last() == Some('/') && new_name.len() != 1 {
new_name.pop();
}
let (hp, data) = examine_dir_str(&new_name);
let (hp, data) = examine_dir_str(&new_name, apparent_size);
permissions = permissions && hp;
results.push(data);
}
(permissions, results)
}
fn examine_dir_str(loc: &str) -> (bool, Node) {
let mut inodes: HashSet<u64> = HashSet::new();
let (hp, result) = examine_dir(fs::read_dir(loc), &mut inodes);
fn examine_dir_str(loc: &str, apparent_size: bool) -> (bool, Node) {
let mut inodes: HashSet<(u64, u64)> = HashSet::new();
let (hp, result) = examine_dir(fs::read_dir(loc), apparent_size, &mut inodes);
// This needs to be folded into the below recursive call somehow
let new_size = result.iter().fold(0, |a, b| a + b.entry().size());
(hp, Node::new(DirEnt::new(loc, new_size), result))
}
#[cfg(not(target_os = "macos"))]
fn get_block_size() -> u64 {
1024
}
#[cfg(target_os = "macos")]
fn get_block_size() -> u64 {
512
}
#[cfg(target_os = "linux")]
fn get_metadata_blocks_and_inode(d: &std::fs::DirEntry) -> Option<(u64, u64)> {
fn get_metadata(d: &std::fs::DirEntry, s: bool) -> Option<(u64, Option<(u64, u64)>)> {
use std::os::linux::fs::MetadataExt;
match d.metadata().ok() {
Some(md) => Some((md.len(), md.st_ino())),
Some(md) => {
let inode = Some((md.st_ino(), md.st_dev()));
if s {
Some((md.len(), inode))
} else {
Some((md.st_blocks() * get_block_size(), inode))
}
}
None => None,
}
}
#[cfg(target_os = "unix")]
fn get_metadata_blocks_and_inode(d: &std::fs::DirEntry) -> Option<(u64, u64)> {
fn get_metadata(d: &std::fs::DirEntry, s: bool) -> Option<(u64, Option<(u64, u64)>)> {
use std::os::unix::fs::MetadataExt;
match d.metadata().ok() {
Some(md) => Some((md.len(), md.ino())),
Some(md) => {
let inode = Some((md.ino(), md.dev()));
if s {
Some((md.len(), inode))
} else {
Some((md.blocks() * get_block_size(), inode))
}
}
None => None,
}
}
#[cfg(target_os = "macos")]
fn get_metadata_blocks_and_inode(d: &std::fs::DirEntry) -> Option<(u64, u64)> {
fn get_metadata(d: &std::fs::DirEntry, s: bool) -> Option<(u64, Option<(u64, u64)>)> {
use std::os::macos::fs::MetadataExt;
match d.metadata().ok() {
Some(md) => Some((md.len(), md.st_ino())),
Some(md) => {
let inode = Some((md.st_ino(), md.st_dev()));
if s {
Some((md.len(), inode))
} else {
Some((md.st_blocks() * get_block_size(), inode))
}
}
None => None,
}
}
#[cfg(not(any(target_os = "linux", target_os = "unix", target_os = "macos")))]
fn get_metadata_blocks_and_inode(_d: &std::fs::DirEntry) -> Option<(u64, u64)> {
match _d.metadata().ok() {
Some(md) => Some((md.len(), 0)), //move to option not 0
fn get_metadata(d: &std::fs::DirEntry, _apparent: bool) -> Option<(u64, Option<(u64, u64)>)> {
match d.metadata().ok() {
Some(md) => Some((md.len(), None)),
None => None,
}
}
fn examine_dir(a_dir: io::Result<ReadDir>, inodes: &mut HashSet<u64>) -> (bool, Vec<Node>) {
fn examine_dir(
a_dir: io::Result<ReadDir>,
apparent_size: bool,
inodes: &mut HashSet<(u64, u64)>,
) -> (bool, Vec<Node>) {
let mut result = vec![];
let mut have_permission = true;
@@ -79,18 +114,21 @@ fn examine_dir(a_dir: io::Result<ReadDir>, inodes: &mut HashSet<u64>) -> (bool,
match dd {
Ok(d) => {
let file_type = d.file_type().ok();
let maybe_size_and_inode = get_metadata_blocks_and_inode(&d);
let maybe_size_and_inode = get_metadata(&d, apparent_size);
match (file_type, maybe_size_and_inode) {
(Some(file_type), Some((size, inode))) => {
let s = d.path().to_string_lossy().to_string();
if inodes.contains(&inode) {
continue;
if let Some(inode_dev_pair) = inode {
if inodes.contains(&inode_dev_pair) {
continue;
}
inodes.insert(inode_dev_pair);
}
inodes.insert(inode);
if d.path().is_dir() && !file_type.is_symlink() {
let (hp, recursive) = examine_dir(fs::read_dir(d.path()), inodes);
let (hp, recursive) =
examine_dir(fs::read_dir(d.path()), apparent_size, inodes);
have_permission = have_permission && hp;
let new_size =
recursive.iter().fold(size, |a, b| a + b.entry().size());