1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-27 19:17:43 +00:00

stat: find mount point

This commit is contained in:
Knight 2016-06-01 14:47:37 +08:00
parent de4a95accb
commit e125118510

View file

@ -21,10 +21,12 @@ use fsext::*;
extern crate uucore; extern crate uucore;
use std::{fs, iter, cmp}; 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::borrow::Cow;
// use std::error::Error;
use std::os::unix::fs::{FileTypeExt, MetadataExt}; use std::os::unix::fs::{FileTypeExt, MetadataExt};
use std::path::Path;
use std::convert::AsRef;
#[cfg(test)] #[cfg(test)]
mod test_stat; mod test_stat;
@ -92,13 +94,14 @@ macro_rules! print_adjusted {
static NAME: &'static str = "stat"; static NAME: &'static str = "stat";
static VERSION: &'static str = env!("CARGO_PKG_VERSION"); static VERSION: &'static str = env!("CARGO_PKG_VERSION");
pub const F_ALTER: u8 = 0b1; const MOUNT_INFO: &'static str = "/etc/mtab";
pub const F_ZERO: u8 = 0b10; pub const F_ALTER: u8 = 1;
pub const F_LEFT: u8 = 0b100; pub const F_ZERO: u8 = 1 << 1;
pub const F_SPACE: u8 = 0b1000; pub const F_LEFT: u8 = 1 << 2;
pub const F_SIGN: u8 = 0b10000; pub const F_SPACE: u8 = 1 << 3;
pub const F_SIGN: u8 = 1 << 4;
// unused at present // unused at present
pub const F_GROUP: u8 = 0b100000; pub const F_GROUP: u8 = 1 << 5;
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum OutputType { pub enum OutputType {
@ -151,6 +154,7 @@ pub struct Stater {
showfs: bool, showfs: bool,
from_user: bool, from_user: bool,
files: Vec<String>, files: Vec<String>,
mount_list: Vec<String>,
default_tokens: Vec<Token>, default_tokens: Vec<Token>,
default_dev_tokens: Vec<Token>, default_dev_tokens: Vec<Token>,
} }
@ -292,7 +296,7 @@ impl Stater {
'-' => flag |= F_LEFT, '-' => flag |= F_LEFT,
' ' => flag |= F_SPACE, ' ' => flag |= F_SPACE,
'+' => flag |= F_SIGN, '+' => flag |= F_SIGN,
//'\'' => flag |= F_GROUP, // '\'' => flag |= F_GROUP,
'\'' => unimplemented!(), '\'' => unimplemented!(),
'I' => unimplemented!(), 'I' => unimplemented!(),
_ => break, _ => break,
@ -406,6 +410,15 @@ impl Stater {
use_printf) use_printf)
.unwrap(); .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::<Vec<String>>();
mount_list.sort_by(|a, b| b.cmp(a));
Ok(Stater { Ok(Stater {
follow: matches.opt_present("dereference"), follow: matches.opt_present("dereference"),
showfs: showfs, showfs: showfs,
@ -413,17 +426,32 @@ impl Stater {
files: matches.free, files: matches.free,
default_tokens: default_tokens, default_tokens: default_tokens,
default_dev_tokens: default_dev_tokens, default_dev_tokens: default_dev_tokens,
mount_list: mount_list,
}) })
} }
fn exec(&self) -> i32 { fn find_mount_point<P: AsRef<Path>>(&self, p: P) -> Option<String> {
for f in &self.files { let path = match p.as_ref().canonicalize() {
self.do_stat(f.as_str()); 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] #[inline]
fn get_grp_name(gid: u32) -> String { fn get_grp_name(gid: u32) -> String {
@ -535,11 +563,9 @@ impl Stater {
otype = OutputType::Unsigned; otype = OutputType::Unsigned;
} }
// string // mount point
// FIXME:
'm' => { 'm' => {
// mount point arg = self.find_mount_point(file).unwrap();
arg = "/".to_owned();
otype = OutputType::Str; otype = OutputType::Str;
} }
@ -651,7 +677,7 @@ impl Stater {
} }
Err(e) => { Err(e) => {
show_info!("cannot stat '{}': {}", file, e); show_info!("cannot stat '{}': {}", file, e);
return; return 1;
} }
} }
} else { } else {
@ -740,10 +766,11 @@ impl Stater {
} }
Err(e) => { Err(e) => {
show_info!("cannot stat '{}': {}", file, e); show_info!("cannot stat '{}': {}", file, e);
return; return 1;
} }
} }
} }
0
} }
// taken from coreutils/src/stat.c // taken from coreutils/src/stat.c
@ -751,7 +778,6 @@ impl Stater {
// SELinux related format is *ignored* // SELinux related format is *ignored*
// 36 is taken randomly
let mut fmtstr = String::with_capacity(36); let mut fmtstr = String::with_capacity(36);
if showfs { if showfs {
if terse { if terse {
@ -814,11 +840,10 @@ pub fn uumain(args: Vec<String>) -> i32 {
} }
match Stater::new(matches) { match Stater::new(matches) {
// FIXME: Handle error
Ok(stater) => stater.exec(), Ok(stater) => stater.exec(),
Err(e) => { Err(e) => {
show_info!("{}", e); show_info!("{}", e);
return 1; 1
} }
} }
} }