catalog: shell: Improve output of stat command.
Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
This commit is contained in:
parent
6dea60aa9f
commit
03f779c6f5
@ -1,11 +1,14 @@
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
use std::ffi::{CString, OsStr};
|
||||
use std::io::Write;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::path::Path;
|
||||
|
||||
use chrono::{Utc, offset::TimeZone};
|
||||
use failure::*;
|
||||
use nix::sys::stat::{Mode, SFlag};
|
||||
|
||||
use proxmox::api::{cli::*, *};
|
||||
use proxmox::sys::linux::tty;
|
||||
@ -313,21 +316,92 @@ fn stat_command(path: String) -> Result<(), Error> {
|
||||
let path = ctx.canonical_path(&path)?;
|
||||
let item = ctx.lookup(&path)?;
|
||||
let mut out = std::io::stdout();
|
||||
out.write_all(b"File: ")?;
|
||||
out.write_all(b" File:\t")?;
|
||||
out.write_all(item.filename.as_bytes())?;
|
||||
out.write_all(&[b'\n'])?;
|
||||
out.write_all(format!("Size: {}\n", item.size).as_bytes())?;
|
||||
out.write_all(b"Type: ")?;
|
||||
match item.entry.mode as u32 & libc::S_IFMT {
|
||||
libc::S_IFDIR => out.write_all(b"directory\n")?,
|
||||
libc::S_IFREG => out.write_all(b"regular file\n")?,
|
||||
libc::S_IFLNK => out.write_all(b"symbolic link\n")?,
|
||||
libc::S_IFBLK => out.write_all(b"block special file\n")?,
|
||||
libc::S_IFCHR => out.write_all(b"character special file\n")?,
|
||||
out.write_all(b"\n")?;
|
||||
out.write_all(format!(" Size:\t{}\t\t", item.size).as_bytes())?;
|
||||
out.write_all(b"Type:\t")?;
|
||||
|
||||
let mut mode_out = vec![b'-'; 10];
|
||||
match SFlag::from_bits_truncate(item.entry.mode as u32) {
|
||||
SFlag::S_IFDIR => {
|
||||
mode_out[0] = b'd';
|
||||
out.write_all(b"directory\n")?;
|
||||
}
|
||||
SFlag::S_IFREG => {
|
||||
mode_out[0] = b'-';
|
||||
out.write_all(b"regular file\n")?;
|
||||
}
|
||||
SFlag::S_IFLNK => {
|
||||
mode_out[0] = b'l';
|
||||
out.write_all(b"symbolic link\n")?;
|
||||
}
|
||||
SFlag::S_IFBLK => {
|
||||
mode_out[0] = b'b';
|
||||
out.write_all(b"block special file\n")?;
|
||||
}
|
||||
SFlag::S_IFCHR => {
|
||||
mode_out[0] = b'c';
|
||||
out.write_all(b"character special file\n")?;
|
||||
}
|
||||
_ => out.write_all(b"unknown\n")?,
|
||||
};
|
||||
out.write_all(format!("Uid: {}\n", item.entry.uid).as_bytes())?;
|
||||
out.write_all(format!("Gid: {}\n", item.entry.gid).as_bytes())?;
|
||||
|
||||
let mode = Mode::from_bits_truncate(item.entry.mode as u32);
|
||||
if mode.contains(Mode::S_IRUSR) {
|
||||
mode_out[1] = b'r';
|
||||
}
|
||||
if mode.contains(Mode::S_IWUSR) {
|
||||
mode_out[2] = b'w';
|
||||
}
|
||||
match (mode.contains(Mode::S_IXUSR), mode.contains(Mode::S_ISUID)) {
|
||||
(false, false) => mode_out[3] = b'-',
|
||||
(true, false) => mode_out[3] = b'x',
|
||||
(false, true) => mode_out[3] = b'S',
|
||||
(true, true) => mode_out[3] = b's',
|
||||
}
|
||||
|
||||
if mode.contains(Mode::S_IRGRP) {
|
||||
mode_out[4] = b'r';
|
||||
}
|
||||
if mode.contains(Mode::S_IWGRP) {
|
||||
mode_out[5] = b'w';
|
||||
}
|
||||
match (mode.contains(Mode::S_IXGRP), mode.contains(Mode::S_ISGID)) {
|
||||
(false, false) => mode_out[6] = b'-',
|
||||
(true, false) => mode_out[6] = b'x',
|
||||
(false, true) => mode_out[6] = b'S',
|
||||
(true, true) => mode_out[6] = b's',
|
||||
}
|
||||
|
||||
if mode.contains(Mode::S_IROTH) {
|
||||
mode_out[7] = b'r';
|
||||
}
|
||||
if mode.contains(Mode::S_IWOTH) {
|
||||
mode_out[8] = b'w';
|
||||
}
|
||||
match (mode.contains(Mode::S_IXOTH), mode.contains(Mode::S_ISVTX)) {
|
||||
(false, false) => mode_out[9] = b'-',
|
||||
(true, false) => mode_out[9] = b'x',
|
||||
(false, true) => mode_out[9] = b'T',
|
||||
(true, true) => mode_out[9] = b't',
|
||||
}
|
||||
|
||||
if !item.xattr.xattrs.is_empty() {
|
||||
mode_out.push(b'+');
|
||||
}
|
||||
|
||||
out.write_all(b"Access:\t")?;
|
||||
out.write_all(&mode_out)?;
|
||||
out.write_all(b"\t")?;
|
||||
out.write_all(format!(" Uid:\t{}\t", item.entry.uid).as_bytes())?;
|
||||
out.write_all(format!("Gid:\t{}\n", item.entry.gid).as_bytes())?;
|
||||
|
||||
let time = i64::try_from(item.entry.mtime)?;
|
||||
let sec = time / 1_000_000_000;
|
||||
let nsec = u32::try_from(time % 1_000_000_000)?;
|
||||
let dt = Utc.timestamp(sec, nsec);
|
||||
out.write_all(format!("Modify:\t{}\n", dt.to_rfc2822()).as_bytes())?;
|
||||
out.flush()?;
|
||||
Ok(())
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user