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:
parent
de4a95accb
commit
e125118510
1 changed files with 48 additions and 23 deletions
|
@ -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>,
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
// FIXME:
|
|
||||||
'm' => {
|
|
||||||
// mount point
|
// mount point
|
||||||
arg = "/".to_owned();
|
'm' => {
|
||||||
|
arg = self.find_mount_point(file).unwrap();
|
||||||
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue