From e1251185105a7ba9e209b7801c7746ec00123737 Mon Sep 17 00:00:00 2001 From: Knight Date: Wed, 1 Jun 2016 14:47:37 +0800 Subject: [PATCH] stat: find mount point --- src/stat/stat.rs | 71 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 23 deletions(-) diff --git a/src/stat/stat.rs b/src/stat/stat.rs index 9c90da125..15e1366af 100644 --- a/src/stat/stat.rs +++ b/src/stat/stat.rs @@ -21,10 +21,12 @@ use fsext::*; extern crate uucore; use std::{fs, iter, cmp}; -use std::io::Write; +use std::fs::File; +use std::io::{Write, BufReader, BufRead}; use std::borrow::Cow; -// use std::error::Error; use std::os::unix::fs::{FileTypeExt, MetadataExt}; +use std::path::Path; +use std::convert::AsRef; #[cfg(test)] mod test_stat; @@ -92,13 +94,14 @@ macro_rules! print_adjusted { static NAME: &'static str = "stat"; static VERSION: &'static str = env!("CARGO_PKG_VERSION"); -pub const F_ALTER: u8 = 0b1; -pub const F_ZERO: u8 = 0b10; -pub const F_LEFT: u8 = 0b100; -pub const F_SPACE: u8 = 0b1000; -pub const F_SIGN: u8 = 0b10000; +const MOUNT_INFO: &'static str = "/etc/mtab"; +pub const F_ALTER: u8 = 1; +pub const F_ZERO: u8 = 1 << 1; +pub const F_LEFT: u8 = 1 << 2; +pub const F_SPACE: u8 = 1 << 3; +pub const F_SIGN: u8 = 1 << 4; // unused at present -pub const F_GROUP: u8 = 0b100000; +pub const F_GROUP: u8 = 1 << 5; #[derive(Debug, PartialEq)] pub enum OutputType { @@ -151,6 +154,7 @@ pub struct Stater { showfs: bool, from_user: bool, files: Vec, + mount_list: Vec, default_tokens: Vec, default_dev_tokens: Vec, } @@ -292,7 +296,7 @@ impl Stater { '-' => flag |= F_LEFT, ' ' => flag |= F_SPACE, '+' => flag |= F_SIGN, - //'\'' => flag |= F_GROUP, + // '\'' => flag |= F_GROUP, '\'' => unimplemented!(), 'I' => unimplemented!(), _ => break, @@ -406,6 +410,15 @@ impl Stater { use_printf) .unwrap(); + let reader = BufReader::new(File::open(MOUNT_INFO).expect("Failed to read /etc/mtab")); + let mut mount_list = reader.lines() + .filter_map(|s| s.ok()) + .filter_map(|line| { + line.split_whitespace().nth(1).map(|s| s.to_owned()) + }) + .collect::>(); + mount_list.sort_by(|a, b| b.cmp(a)); + Ok(Stater { follow: matches.opt_present("dereference"), showfs: showfs, @@ -413,17 +426,32 @@ impl Stater { files: matches.free, default_tokens: default_tokens, default_dev_tokens: default_dev_tokens, + mount_list: mount_list, }) } - fn exec(&self) -> i32 { - for f in &self.files { - self.do_stat(f.as_str()); + fn find_mount_point>(&self, p: P) -> Option { + let path = match p.as_ref().canonicalize() { + Ok(s) => s, + Err(_) => return None, + }; + for root in (&self.mount_list).into_iter() { + if path.starts_with(root) { + return Some(root.clone()); + } } - 0 + None } - fn do_stat(&self, file: &str) { + fn exec(&self) -> i32 { + let mut ret = 0; + for f in &self.files { + ret |= self.do_stat(f.as_str()); + } + ret + } + + fn do_stat(&self, file: &str) -> i32 { #[inline] fn get_grp_name(gid: u32) -> String { @@ -535,11 +563,9 @@ impl Stater { otype = OutputType::Unsigned; } - // string - // FIXME: + // mount point 'm' => { - // mount point - arg = "/".to_owned(); + arg = self.find_mount_point(file).unwrap(); otype = OutputType::Str; } @@ -651,7 +677,7 @@ impl Stater { } Err(e) => { show_info!("cannot stat '{}': {}", file, e); - return; + return 1; } } } else { @@ -740,10 +766,11 @@ impl Stater { } Err(e) => { show_info!("cannot stat '{}': {}", file, e); - return; + return 1; } } } + 0 } // taken from coreutils/src/stat.c @@ -751,7 +778,6 @@ impl Stater { // SELinux related format is *ignored* - // 36 is taken randomly let mut fmtstr = String::with_capacity(36); if showfs { if terse { @@ -814,11 +840,10 @@ pub fn uumain(args: Vec) -> i32 { } match Stater::new(matches) { - // FIXME: Handle error Ok(stater) => stater.exec(), Err(e) => { show_info!("{}", e); - return 1; + 1 } } }