mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
stat: get rid of crate users
This commit is contained in:
parent
580667295c
commit
ad3c984afd
2 changed files with 111 additions and 117 deletions
|
@ -11,7 +11,6 @@ path = "stat.rs"
|
||||||
getopts = "*"
|
getopts = "*"
|
||||||
libc = "*"
|
libc = "*"
|
||||||
time = "*"
|
time = "*"
|
||||||
users = "*"
|
|
||||||
uucore = { path="../uucore" }
|
uucore = { path="../uucore" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
|
195
src/stat/stat.rs
195
src/stat/stat.rs
|
@ -8,8 +8,6 @@
|
||||||
// that was distributed with this source code.
|
// that was distributed with this source code.
|
||||||
//
|
//
|
||||||
|
|
||||||
extern crate users;
|
|
||||||
|
|
||||||
extern crate getopts;
|
extern crate getopts;
|
||||||
use getopts::Options;
|
use getopts::Options;
|
||||||
|
|
||||||
|
@ -44,7 +42,6 @@ macro_rules! fill_string {
|
||||||
iter::repeat($c).take($cnt).map(|c| $str.push(c)).all(|_| true)
|
iter::repeat($c).take($cnt).map(|c| $str.push(c)).all(|_| true)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! extend_digits {
|
macro_rules! extend_digits {
|
||||||
($str: ident, $min: expr) => (
|
($str: ident, $min: expr) => (
|
||||||
if $min > $str.len() {
|
if $min > $str.len() {
|
||||||
|
@ -57,7 +54,6 @@ macro_rules! extend_digits {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! pad_and_print {
|
macro_rules! pad_and_print {
|
||||||
($result: ident, $str: ident, $left: expr, $width: expr, $padding: expr) => (
|
($result: ident, $str: ident, $left: expr, $width: expr, $padding: expr) => (
|
||||||
if $str.len() < $width {
|
if $str.len() < $width {
|
||||||
|
@ -135,14 +131,10 @@ impl ScanUtil for str {
|
||||||
{
|
{
|
||||||
let mut chars = self.chars();
|
let mut chars = self.chars();
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
if let Some(c) = chars.next() {
|
match chars.next() {
|
||||||
match c {
|
Some('-') | Some('+') | Some('0'...'9') => i += 1,
|
||||||
'-' | '+' | '0' ... '9' => i += 1,
|
|
||||||
_ => return None,
|
_ => return None,
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
while let Some(c) = chars.next() {
|
while let Some(c) = chars.next() {
|
||||||
match c {
|
match c {
|
||||||
'0'...'9' => i += 1,
|
'0'...'9' => i += 1,
|
||||||
|
@ -157,16 +149,18 @@ impl ScanUtil for str {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scan_char(&self, radix: u32) -> Option<(char, usize)> {
|
fn scan_char(&self, radix: u32) -> Option<(char, usize)> {
|
||||||
let mut chars = self.chars();
|
|
||||||
let mut i = 0;
|
|
||||||
let count = match radix {
|
let count = match radix {
|
||||||
8 => 3_usize,
|
8 => 3_usize,
|
||||||
16 => 2,
|
16 => 2,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
let mut chars = self.chars().enumerate();
|
||||||
let mut res = 0_u32;
|
let mut res = 0_u32;
|
||||||
while i < count {
|
let mut offset = 0_usize;
|
||||||
if let Some(c) = chars.next() {
|
while let Some((i, c)) = chars.next() {
|
||||||
|
if i >= count {
|
||||||
|
break;
|
||||||
|
}
|
||||||
match c.to_digit(radix) {
|
match c.to_digit(radix) {
|
||||||
Some(digit) => {
|
Some(digit) => {
|
||||||
let tmp = res * radix + digit;
|
let tmp = res * radix + digit;
|
||||||
|
@ -178,13 +172,10 @@ impl ScanUtil for str {
|
||||||
}
|
}
|
||||||
None => break,
|
None => break,
|
||||||
}
|
}
|
||||||
} else {
|
offset = i + 1;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
i += 1;
|
if offset > 0 {
|
||||||
}
|
Some((res as u8 as char, offset))
|
||||||
if i > 0 {
|
|
||||||
Some((res as u8 as char, i))
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -304,6 +295,31 @@ fn print_it(arg: &str, otype: OutputType, flag: u8, width: usize, precision: i32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
use std::ptr;
|
||||||
|
use std::ffi::CStr;
|
||||||
|
use uucore::c_types::{getpwuid, getgrgid};
|
||||||
|
fn get_grp_name(gid: u32) -> String {
|
||||||
|
let p = unsafe { getgrgid(gid) };
|
||||||
|
if !p.is_null() {
|
||||||
|
unsafe { CStr::from_ptr(ptr::read(p).gr_name).to_string_lossy().into_owned() }
|
||||||
|
} else {
|
||||||
|
"UNKNOWN".to_owned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn get_usr_name(uid: u32) -> String {
|
||||||
|
let p = unsafe { getpwuid(uid) };
|
||||||
|
if !p.is_null() {
|
||||||
|
unsafe {
|
||||||
|
CStr::from_ptr(ptr::read(p).pw_name)
|
||||||
|
.to_string_lossy()
|
||||||
|
.into_owned()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
"UNKNOWN".to_owned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Stater {
|
impl Stater {
|
||||||
pub fn generate_tokens(fmtstr: &str, use_printf: bool) -> Result<Vec<Token>, String> {
|
pub fn generate_tokens(fmtstr: &str, use_printf: bool) -> Result<Vec<Token>, String> {
|
||||||
|
|
||||||
|
@ -501,24 +517,6 @@ impl Stater {
|
||||||
|
|
||||||
fn do_stat(&self, file: &str) -> i32 {
|
fn do_stat(&self, file: &str) -> i32 {
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn get_grp_name(gid: u32) -> String {
|
|
||||||
if let Some(g) = users::get_group_by_gid(gid) {
|
|
||||||
g.name().to_owned()
|
|
||||||
} else {
|
|
||||||
"UNKNOWN".to_owned()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn get_usr_name(uid: u32) -> String {
|
|
||||||
if let Some(g) = users::get_user_by_uid(uid) {
|
|
||||||
g.name().to_owned()
|
|
||||||
} else {
|
|
||||||
"UNKNOWN".to_owned()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !self.showfs {
|
if !self.showfs {
|
||||||
let result = if self.follow {
|
let result = if self.follow {
|
||||||
fs::metadata(file)
|
fs::metadata(file)
|
||||||
|
@ -534,7 +532,6 @@ impl Stater {
|
||||||
} else {
|
} else {
|
||||||
&self.default_dev_tokens
|
&self.default_dev_tokens
|
||||||
};
|
};
|
||||||
let is_symlink = ftype.is_symlink();
|
|
||||||
|
|
||||||
for t in tokens.into_iter() {
|
for t in tokens.into_iter() {
|
||||||
match t {
|
match t {
|
||||||
|
@ -545,23 +542,23 @@ impl Stater {
|
||||||
let otype: OutputType;
|
let otype: OutputType;
|
||||||
|
|
||||||
match format {
|
match format {
|
||||||
// unsigned oct
|
// access rights in octal
|
||||||
'a' => {
|
'a' => {
|
||||||
arg = format!("{:o}", 0o7777 & meta.mode());
|
arg = format!("{:o}", 0o7777 & meta.mode());
|
||||||
otype = OutputType::UnsignedOct;
|
otype = OutputType::UnsignedOct;
|
||||||
}
|
}
|
||||||
// string
|
// access rights in human readable form
|
||||||
'A' => {
|
'A' => {
|
||||||
arg = pretty_access(meta.mode());
|
arg = pretty_access(meta.mode() as mode_t);
|
||||||
otype = OutputType::Str;
|
otype = OutputType::Str;
|
||||||
}
|
}
|
||||||
// unsigned
|
// number of blocks allocated (see %B)
|
||||||
'b' => {
|
'b' => {
|
||||||
arg = format!("{}", meta.blocks());
|
arg = format!("{}", meta.blocks());
|
||||||
otype = OutputType::Unsigned;
|
otype = OutputType::Unsigned;
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsigned
|
// the size in bytes of each block reported by %b
|
||||||
// FIXME: blocksize differs on various platform
|
// FIXME: blocksize differs on various platform
|
||||||
// See coreutils/gnulib/lib/stat-size.h ST_NBLOCKSIZE
|
// See coreutils/gnulib/lib/stat-size.h ST_NBLOCKSIZE
|
||||||
'B' => {
|
'B' => {
|
||||||
|
@ -570,42 +567,42 @@ impl Stater {
|
||||||
otype = OutputType::Unsigned;
|
otype = OutputType::Unsigned;
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsigned
|
// device number in decimal
|
||||||
'd' => {
|
'd' => {
|
||||||
arg = format!("{}", meta.dev());
|
arg = format!("{}", meta.dev());
|
||||||
otype = OutputType::Unsigned;
|
otype = OutputType::Unsigned;
|
||||||
}
|
}
|
||||||
// unsigned hex
|
// device number in hex
|
||||||
'D' => {
|
'D' => {
|
||||||
arg = format!("{:x}", meta.dev());
|
arg = format!("{:x}", meta.dev());
|
||||||
otype = OutputType::UnsignedHex;
|
otype = OutputType::UnsignedHex;
|
||||||
}
|
}
|
||||||
// unsigned hex
|
// raw mode in hex
|
||||||
'f' => {
|
'f' => {
|
||||||
arg = format!("{:x}", meta.mode());
|
arg = format!("{:x}", meta.mode());
|
||||||
otype = OutputType::UnsignedHex;
|
otype = OutputType::UnsignedHex;
|
||||||
}
|
}
|
||||||
// string
|
// file type
|
||||||
'F' => {
|
'F' => {
|
||||||
arg = pretty_filetype(meta.mode(), meta.len()).to_owned();
|
arg = pretty_filetype(meta.mode(), meta.len()).to_owned();
|
||||||
otype = OutputType::Str;
|
otype = OutputType::Str;
|
||||||
}
|
}
|
||||||
// unsigned
|
// group ID of owner
|
||||||
'g' => {
|
'g' => {
|
||||||
arg = format!("{}", meta.gid());
|
arg = format!("{}", meta.gid());
|
||||||
otype = OutputType::Unsigned;
|
otype = OutputType::Unsigned;
|
||||||
}
|
}
|
||||||
// string
|
// group name of owner
|
||||||
'G' => {
|
'G' => {
|
||||||
arg = get_grp_name(meta.gid());
|
arg = get_grp_name(meta.gid());
|
||||||
otype = OutputType::Str;
|
otype = OutputType::Str;
|
||||||
}
|
}
|
||||||
// unsigned
|
// number of hard links
|
||||||
'h' => {
|
'h' => {
|
||||||
arg = format!("{}", meta.nlink());
|
arg = format!("{}", meta.nlink());
|
||||||
otype = OutputType::Unsigned;
|
otype = OutputType::Unsigned;
|
||||||
}
|
}
|
||||||
// unsigned
|
// inode number
|
||||||
'i' => {
|
'i' => {
|
||||||
arg = format!("{}", meta.ino());
|
arg = format!("{}", meta.ino());
|
||||||
otype = OutputType::Unsigned;
|
otype = OutputType::Unsigned;
|
||||||
|
@ -617,14 +614,14 @@ impl Stater {
|
||||||
otype = OutputType::Str;
|
otype = OutputType::Str;
|
||||||
}
|
}
|
||||||
|
|
||||||
// string
|
// file name
|
||||||
'n' => {
|
'n' => {
|
||||||
arg = file.to_owned();
|
arg = file.to_owned();
|
||||||
otype = OutputType::Str;
|
otype = OutputType::Str;
|
||||||
}
|
}
|
||||||
// string
|
// quoted file name with dereference if symbolic link
|
||||||
'N' => {
|
'N' => {
|
||||||
if is_symlink {
|
if ftype.is_symlink() {
|
||||||
arg = format!("'{}' -> '{}'",
|
arg = format!("'{}' -> '{}'",
|
||||||
file,
|
file,
|
||||||
fs::read_link(file)
|
fs::read_link(file)
|
||||||
|
@ -635,42 +632,42 @@ impl Stater {
|
||||||
}
|
}
|
||||||
otype = OutputType::Str;
|
otype = OutputType::Str;
|
||||||
}
|
}
|
||||||
// unsigned
|
// optimal I/O transfer size hint
|
||||||
'o' => {
|
'o' => {
|
||||||
arg = format!("{}", meta.blksize());
|
arg = format!("{}", meta.blksize());
|
||||||
otype = OutputType::Unsigned;
|
otype = OutputType::Unsigned;
|
||||||
}
|
}
|
||||||
// int
|
// total size, in bytes
|
||||||
's' => {
|
's' => {
|
||||||
arg = format!("{}", meta.len());
|
arg = format!("{}", meta.len());
|
||||||
otype = OutputType::Integer;
|
otype = OutputType::Integer;
|
||||||
}
|
}
|
||||||
// unsigned hex
|
// major device type in hex, for character/block device special
|
||||||
|
// files
|
||||||
't' => {
|
't' => {
|
||||||
arg = format!("{:x}", meta.rdev() >> 8);
|
arg = format!("{:x}", meta.rdev() >> 8);
|
||||||
otype = OutputType::UnsignedHex;
|
otype = OutputType::UnsignedHex;
|
||||||
}
|
}
|
||||||
// unsigned hex
|
// minor device type in hex, for character/block device special
|
||||||
|
// files
|
||||||
'T' => {
|
'T' => {
|
||||||
arg = format!("{:x}", meta.rdev() & 0xff);
|
arg = format!("{:x}", meta.rdev() & 0xff);
|
||||||
otype = OutputType::UnsignedHex;
|
otype = OutputType::UnsignedHex;
|
||||||
}
|
}
|
||||||
// unsigned
|
// user ID of owner
|
||||||
'u' => {
|
'u' => {
|
||||||
arg = format!("{}", meta.uid());
|
arg = format!("{}", meta.uid());
|
||||||
otype = OutputType::Unsigned;
|
otype = OutputType::Unsigned;
|
||||||
}
|
}
|
||||||
// string
|
// user name of owner
|
||||||
'U' => {
|
'U' => {
|
||||||
arg = get_usr_name(meta.uid());
|
arg = get_usr_name(meta.uid());
|
||||||
otype = OutputType::Str;
|
otype = OutputType::Str;
|
||||||
}
|
}
|
||||||
|
|
||||||
// string
|
|
||||||
'w' => {
|
|
||||||
// time of file birth, human-readable; - if unknown
|
// time of file birth, human-readable; - if unknown
|
||||||
arg = if let Some(elapsed) = meta.created()
|
'w' => {
|
||||||
.ok()
|
arg = if let Ok(elapsed) = meta.created()
|
||||||
.map(|t| {
|
.map(|t| {
|
||||||
t.elapsed().unwrap()
|
t.elapsed().unwrap()
|
||||||
}) {
|
}) {
|
||||||
|
@ -682,11 +679,9 @@ impl Stater {
|
||||||
otype = OutputType::Str;
|
otype = OutputType::Str;
|
||||||
}
|
}
|
||||||
|
|
||||||
// int
|
|
||||||
'W' => {
|
|
||||||
// time of file birth, seconds since Epoch; 0 if unknown
|
// time of file birth, seconds since Epoch; 0 if unknown
|
||||||
arg = if let Some(elapsed) = meta.created()
|
'W' => {
|
||||||
.ok()
|
arg = if let Ok(elapsed) = meta.created()
|
||||||
.map(|t| {
|
.map(|t| {
|
||||||
t.elapsed().unwrap()
|
t.elapsed().unwrap()
|
||||||
}) {
|
}) {
|
||||||
|
@ -697,32 +692,32 @@ impl Stater {
|
||||||
otype = OutputType::Integer;
|
otype = OutputType::Integer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// string
|
// time of last access, human-readable
|
||||||
'x' => {
|
'x' => {
|
||||||
arg = pretty_time(meta.atime(), meta.atime_nsec());
|
arg = pretty_time(meta.atime(), meta.atime_nsec());
|
||||||
otype = OutputType::Str;
|
otype = OutputType::Str;
|
||||||
}
|
}
|
||||||
// int
|
// time of last access, seconds since Epoch
|
||||||
'X' => {
|
'X' => {
|
||||||
arg = format!("{}", meta.atime());
|
arg = format!("{}", meta.atime());
|
||||||
otype = OutputType::Integer;
|
otype = OutputType::Integer;
|
||||||
}
|
}
|
||||||
// string
|
// time of last data modification, human-readable
|
||||||
'y' => {
|
'y' => {
|
||||||
arg = pretty_time(meta.mtime(), meta.mtime_nsec());
|
arg = pretty_time(meta.mtime(), meta.mtime_nsec());
|
||||||
otype = OutputType::Str;
|
otype = OutputType::Str;
|
||||||
}
|
}
|
||||||
// int
|
// time of last data modification, seconds since Epoch
|
||||||
'Y' => {
|
'Y' => {
|
||||||
arg = format!("{}", meta.mtime());
|
arg = format!("{}", meta.mtime());
|
||||||
otype = OutputType::Str;
|
otype = OutputType::Str;
|
||||||
}
|
}
|
||||||
// string
|
// time of last status change, human-readable
|
||||||
'z' => {
|
'z' => {
|
||||||
arg = pretty_time(meta.ctime(), meta.ctime_nsec());
|
arg = pretty_time(meta.ctime(), meta.ctime_nsec());
|
||||||
otype = OutputType::Str;
|
otype = OutputType::Str;
|
||||||
}
|
}
|
||||||
// int
|
// time of last status change, seconds since Epoch
|
||||||
'Z' => {
|
'Z' => {
|
||||||
arg = format!("{}", meta.ctime());
|
arg = format!("{}", meta.ctime());
|
||||||
otype = OutputType::Integer;
|
otype = OutputType::Integer;
|
||||||
|
@ -745,7 +740,7 @@ impl Stater {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match statfs(file) {
|
match statfs(file) {
|
||||||
Ok(data) => {
|
Ok(meta) => {
|
||||||
let tokens = &self.default_tokens;
|
let tokens = &self.default_tokens;
|
||||||
|
|
||||||
for t in tokens.into_iter() {
|
for t in tokens.into_iter() {
|
||||||
|
@ -756,64 +751,64 @@ impl Stater {
|
||||||
let arg: String;
|
let arg: String;
|
||||||
let otype: OutputType;
|
let otype: OutputType;
|
||||||
match format {
|
match format {
|
||||||
// int
|
// free blocks available to non-superuser
|
||||||
'a' => {
|
'a' => {
|
||||||
arg = format!("{}", data.f_bavail);
|
arg = format!("{}", meta.avail_blocks());
|
||||||
otype = OutputType::Integer;
|
otype = OutputType::Integer;
|
||||||
}
|
}
|
||||||
// int
|
// total data blocks in file system
|
||||||
'b' => {
|
'b' => {
|
||||||
arg = format!("{}", data.f_blocks);
|
arg = format!("{}", meta.total_blocks());
|
||||||
otype = OutputType::Integer;
|
otype = OutputType::Integer;
|
||||||
}
|
}
|
||||||
// unsigned
|
// total file nodes in file system
|
||||||
'c' => {
|
'c' => {
|
||||||
arg = format!("{}", data.f_files);
|
arg = format!("{}", meta.total_fnodes());
|
||||||
otype = OutputType::Unsigned;
|
otype = OutputType::Unsigned;
|
||||||
}
|
}
|
||||||
// int
|
// free file nodes in file system
|
||||||
'd' => {
|
'd' => {
|
||||||
arg = format!("{}", data.f_ffree);
|
arg = format!("{}", meta.free_fnodes());
|
||||||
otype = OutputType::Integer;
|
otype = OutputType::Integer;
|
||||||
}
|
}
|
||||||
// int
|
// free blocks in file system
|
||||||
'f' => {
|
'f' => {
|
||||||
arg = format!("{}", data.f_bfree);
|
arg = format!("{}", meta.free_blocks());
|
||||||
otype = OutputType::Integer;
|
otype = OutputType::Integer;
|
||||||
}
|
}
|
||||||
// hex unsigned
|
// file system ID in hex
|
||||||
'i' => {
|
'i' => {
|
||||||
arg = format!("{:x}", data.f_fsid);
|
arg = format!("{:x}", meta.fsid());
|
||||||
otype = OutputType::UnsignedHex;
|
otype = OutputType::UnsignedHex;
|
||||||
}
|
}
|
||||||
// unsigned
|
// maximum length of filenames
|
||||||
'l' => {
|
'l' => {
|
||||||
arg = format!("{}", data.f_namelen);
|
arg = format!("{}", meta.namelen());
|
||||||
otype = OutputType::Unsigned;
|
otype = OutputType::Unsigned;
|
||||||
}
|
}
|
||||||
// string
|
// file name
|
||||||
'n' => {
|
'n' => {
|
||||||
arg = file.to_owned();
|
arg = file.to_owned();
|
||||||
otype = OutputType::Str;
|
otype = OutputType::Str;
|
||||||
}
|
}
|
||||||
// unsigned
|
// block size (for faster transfers)
|
||||||
's' => {
|
's' => {
|
||||||
arg = format!("{}", data.f_bsize);
|
arg = format!("{}", meta.iosize());
|
||||||
otype = OutputType::Unsigned;
|
otype = OutputType::Unsigned;
|
||||||
}
|
}
|
||||||
// unsigned
|
// fundamental block size (for block counts)
|
||||||
'S' => {
|
'S' => {
|
||||||
arg = format!("{}", data.f_frsize);
|
arg = format!("{}", meta.blksize());
|
||||||
otype = OutputType::Unsigned;
|
otype = OutputType::Unsigned;
|
||||||
}
|
}
|
||||||
// hex unsigned
|
// file system type in hex
|
||||||
't' => {
|
't' => {
|
||||||
arg = format!("{:x}", data.f_type);
|
arg = format!("{:x}", meta.fs_type());
|
||||||
otype = OutputType::UnsignedHex;
|
otype = OutputType::UnsignedHex;
|
||||||
}
|
}
|
||||||
// string
|
// file system type in human readable form
|
||||||
'T' => {
|
'T' => {
|
||||||
arg = pretty_fstype(data.f_type).into_owned();
|
arg = pretty_fstype(meta.fs_type()).into_owned();
|
||||||
otype = OutputType::Str;
|
otype = OutputType::Str;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -828,7 +823,7 @@ impl Stater {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
show_info!("cannot stat '{}': {}", file, e);
|
show_info!("cannot read file system information for '{}': {}", file, e);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue