1
Fork 0
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:
Knight 2016-06-05 11:33:58 +08:00
parent 580667295c
commit ad3c984afd
2 changed files with 111 additions and 117 deletions

View file

@ -11,7 +11,6 @@ path = "stat.rs"
getopts = "*" getopts = "*"
libc = "*" libc = "*"
time = "*" time = "*"
users = "*"
uucore = { path="../uucore" } uucore = { path="../uucore" }
[[bin]] [[bin]]

View file

@ -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;
} }
} }