mirror of
https://gitlab.com/arnekeller/df.git
synced 2024-11-23 08:44:57 +00:00
Initial commit
This commit is contained in:
commit
da3eabaf8f
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/target
|
69
Cargo.lock
generated
Normal file
69
Cargo.lock
generated
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "ascii_table"
|
||||||
|
version = "3.0.2"
|
||||||
|
source = "git+https://gitlab.com/arnekeller/ascii-table.git?rev=7fffb5d93b8c63283fc1359ee3c6dbfcf12ed90b#7fffb5d93b8c63283fc1359ee3c6dbfcf12ed90b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "df"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"ascii_table",
|
||||||
|
"libc",
|
||||||
|
"procinfo",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.91"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nom"
|
||||||
|
version = "2.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf51a729ecf40266a2368ad335a5fdde43471f545a967109cd62146ecf8b66ff"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "procinfo"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6ab1427f3d2635891f842892dda177883dca0639e05fe66796a62c9d2f23b49c"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"libc",
|
||||||
|
"nom",
|
||||||
|
"rustc_version",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc_version"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||||
|
dependencies = [
|
||||||
|
"semver",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||||
|
dependencies = [
|
||||||
|
"semver-parser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver-parser"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
13
Cargo.toml
Normal file
13
Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "df"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Arne Keller <arne.keller@posteo.de>"]
|
||||||
|
license = "GPL-3.0-or-later"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
ascii_table = { git = "https://gitlab.com/arnekeller/ascii-table.git", rev = "7fffb5d93b8c63283fc1359ee3c6dbfcf12ed90b" }
|
||||||
|
libc = "0.2.91"
|
||||||
|
procinfo = "0.4.2"
|
91
src/main.rs
Normal file
91
src/main.rs
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
use libc::{c_char, statvfs64, strerror_r};
|
||||||
|
use procinfo::pid::mountinfo_self;
|
||||||
|
use ascii_table::{Align, AsciiTable, Column};
|
||||||
|
|
||||||
|
use std::{array::IntoIter, ffi::CString, fs, mem::MaybeUninit};
|
||||||
|
use std::os::unix::ffi::OsStrExt;
|
||||||
|
|
||||||
|
const IGNORED_FS: &'static [&'static str] = &["proc", "sysfs", "securityfs", "bpf", "cgroup", "cgroup2", "fusectl", "efivarfs", "debugfs"];
|
||||||
|
const IGNORED_FS2: &'static [(&'static str, &'static str)] = &[];//("fuse", "portal")];
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut rows = Vec::new();
|
||||||
|
let mut devices = Vec::new();
|
||||||
|
for mount in mountinfo_self().unwrap() {
|
||||||
|
if IGNORED_FS.contains(&&*mount.fs_type.0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if let Some(second) = mount.fs_type.1.as_ref() {
|
||||||
|
if IGNORED_FS2.contains(&(&mount.fs_type.0, second)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// skip multiple FS on the same partition
|
||||||
|
let device = (mount.major, mount.minor);
|
||||||
|
if devices.contains(&device) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
devices.push(device);
|
||||||
|
let mut data = MaybeUninit::<statvfs64>::uninit();
|
||||||
|
let path = CString::new(mount.mount_point.as_os_str().as_bytes()).unwrap();
|
||||||
|
let mut res = unsafe { statvfs64(path.as_ptr(), data.as_mut_ptr()) };
|
||||||
|
if res != 0 {
|
||||||
|
if res < 0 {
|
||||||
|
res = unsafe { *libc::__errno_location() };
|
||||||
|
}
|
||||||
|
let mut error_buffer = vec![0 as c_char; 256];
|
||||||
|
let error: String = unsafe {
|
||||||
|
let result = strerror_r(res, error_buffer.as_mut_ptr(), error_buffer.len());
|
||||||
|
if result != 0 {
|
||||||
|
eprintln!("fail {}", result);
|
||||||
|
res.to_string().into()
|
||||||
|
} else {
|
||||||
|
error_buffer.into_iter().take_while(|&x| x != 0).map(|x| x as u8 as char).collect()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
eprintln!("df: {}: {}", mount.mount_point.display(), error);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let data = unsafe { data.assume_init() };
|
||||||
|
if data.f_blocks == 0 {
|
||||||
|
continue; // metadata is useless
|
||||||
|
}
|
||||||
|
|
||||||
|
let typ = match mount.mount_src.as_deref() {
|
||||||
|
Some(path) if path.starts_with('/') => {
|
||||||
|
fs::canonicalize(path).unwrap().display().to_string()
|
||||||
|
},
|
||||||
|
_ => mount.fs_type.0
|
||||||
|
};
|
||||||
|
rows.push((typ, data.f_blocks, data.f_bfree, mount.mount_point));
|
||||||
|
}
|
||||||
|
let mut ascii_table = AsciiTable::default();
|
||||||
|
ascii_table.draw_lines = false;
|
||||||
|
|
||||||
|
for (i, &(header, align)) in [
|
||||||
|
("Filesystem", Align::Left),
|
||||||
|
("Blocks", Align::Right),
|
||||||
|
("Used", Align::Right),
|
||||||
|
("Free", Align::Right),
|
||||||
|
("Use%", Align::Right),
|
||||||
|
("Mounted on", Align::Left)
|
||||||
|
].iter().enumerate() {
|
||||||
|
let mut column = Column::default();
|
||||||
|
column.header = header.to_owned();
|
||||||
|
column.align = align;
|
||||||
|
ascii_table.columns.insert(i, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
ascii_table.print(rows.into_iter().map(
|
||||||
|
|(typ, blocks, free, path)| IntoIter::new(
|
||||||
|
[
|
||||||
|
typ,
|
||||||
|
blocks.to_string(),
|
||||||
|
(blocks-free).to_string(),
|
||||||
|
free.to_string(),
|
||||||
|
format!("{:.0}%", ((blocks-free) as f64 * 100.0 / blocks as f64).ceil()),
|
||||||
|
path.display().to_string()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
));
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user