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::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::convert::TryFrom;
|
||||||
use std::ffi::{CString, OsStr};
|
use std::ffi::{CString, OsStr};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::os::unix::ffi::OsStrExt;
|
use std::os::unix::ffi::OsStrExt;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
use chrono::{Utc, offset::TimeZone};
|
||||||
use failure::*;
|
use failure::*;
|
||||||
|
use nix::sys::stat::{Mode, SFlag};
|
||||||
|
|
||||||
use proxmox::api::{cli::*, *};
|
use proxmox::api::{cli::*, *};
|
||||||
use proxmox::sys::linux::tty;
|
use proxmox::sys::linux::tty;
|
||||||
@ -313,21 +316,92 @@ fn stat_command(path: String) -> Result<(), Error> {
|
|||||||
let path = ctx.canonical_path(&path)?;
|
let path = ctx.canonical_path(&path)?;
|
||||||
let item = ctx.lookup(&path)?;
|
let item = ctx.lookup(&path)?;
|
||||||
let mut out = std::io::stdout();
|
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(item.filename.as_bytes())?;
|
||||||
out.write_all(&[b'\n'])?;
|
out.write_all(b"\n")?;
|
||||||
out.write_all(format!("Size: {}\n", item.size).as_bytes())?;
|
out.write_all(format!(" Size:\t{}\t\t", item.size).as_bytes())?;
|
||||||
out.write_all(b"Type: ")?;
|
out.write_all(b"Type:\t")?;
|
||||||
match item.entry.mode as u32 & libc::S_IFMT {
|
|
||||||
libc::S_IFDIR => out.write_all(b"directory\n")?,
|
let mut mode_out = vec![b'-'; 10];
|
||||||
libc::S_IFREG => out.write_all(b"regular file\n")?,
|
match SFlag::from_bits_truncate(item.entry.mode as u32) {
|
||||||
libc::S_IFLNK => out.write_all(b"symbolic link\n")?,
|
SFlag::S_IFDIR => {
|
||||||
libc::S_IFBLK => out.write_all(b"block special file\n")?,
|
mode_out[0] = b'd';
|
||||||
libc::S_IFCHR => out.write_all(b"character special file\n")?,
|
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(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()?;
|
out.flush()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user