D
Deno

help

Getting free disk space without using child_process.

Pptrxyz8/28/2023
Hello everyone! I would like to create a small CLI tool using Typescript and Deno. I would like to monitor the free disk space on several disks. How can I get the free disk space on a Linux machine without forking a separate process (like exec --> df and the like)? In addition, I would like to deno compile my little program later, so I am not sure if Node's gyp is an option then.
MMrcool8/29/2023
I don't think deno runtime exposés this I would just strace df to see how it does it, it probably boils down to a Linux syscall since it finishes immediately In that case you'll need ffi
Pptrxyz8/29/2023
I found a npm packae doing exactly that but it's based on gyp. can i somehow "convert" that? or is deno gyp compatible?
EEsente8/30/2023
No, there is no equivalent to gyp in Deno Maybe there is some WASM implementation out there for this.
Pptrxyz8/30/2023
ok, thanks.
MMrcool8/30/2023
the program needs to issue statfs syscall, you can't do that in a javascript runtime, your options is to either run df or bind to a library with ffi that does this , i think both options are equivalent really If you want to see an implementation example, you can checkout https://github.com/uutils/coreutils/tree/main/src/uu/df (its also crossplatform) Also here is the simplest program in rust (for linux)
use libc::statfs;
use std::ffi::CString;

fn main() {
for path in get_mount_points() {
let mut stat: statfs = unsafe { std::mem::zeroed() };

let result = unsafe {
let path = CString::new(path.clone()).unwrap();
let path = path.as_ptr();
statfs(path, &mut stat as *mut _)
};
if stat.f_blocks == 0 {
continue;
}
dbg!(&path);

if result == 0 {
print_statfs_info(&stat);
} else {
eprintln!("Error getting filesystem information");
}
}
}

fn get_mount_points() -> Vec<String> {
let raw = std::fs::read_to_string("/proc/self/mountinfo").unwrap();
raw.lines()
.map(|line| line.split_whitespace().nth(4).unwrap().to_owned())
.collect()
}

fn print_statfs_info(stat: &statfs) {
let block_size = stat.f_bsize as u64;
let total_blocks = stat.f_blocks as u64;
let free_blocks = stat.f_bfree as u64;
let available_blocks = stat.f_bavail as u64;

let total_space = block_size * total_blocks;
let used_space = total_space - (block_size * free_blocks);
let avail_space = block_size * available_blocks;
let used_percent = (used_space * 100) / total_space;

println!("Size: {}", format_size(total_space));
println!("Used: {}", format_size(used_space));
println!("Available: {}", format_size(avail_space));
println!("Use%: {}%", used_percent);
}

fn format_size(size: u64) -> String {
const KB: u64 = 1024;
const MB: u64 = KB * 1024;
const GB: u64 = MB * 1024;

if size >= GB {
format!("{:.2} GB", size as f64 / GB as f64)
} else if size >= MB {
format!("{:.2} MB", size as f64 / MB as f64)
} else if size >= KB {
format!("{:.2} KB", size as f64 / KB as f64)
} else {
format!("{} bytes", size)
}
}
use libc::statfs;
use std::ffi::CString;

fn main() {
for path in get_mount_points() {
let mut stat: statfs = unsafe { std::mem::zeroed() };

let result = unsafe {
let path = CString::new(path.clone()).unwrap();
let path = path.as_ptr();
statfs(path, &mut stat as *mut _)
};
if stat.f_blocks == 0 {
continue;
}
dbg!(&path);

if result == 0 {
print_statfs_info(&stat);
} else {
eprintln!("Error getting filesystem information");
}
}
}

fn get_mount_points() -> Vec<String> {
let raw = std::fs::read_to_string("/proc/self/mountinfo").unwrap();
raw.lines()
.map(|line| line.split_whitespace().nth(4).unwrap().to_owned())
.collect()
}

fn print_statfs_info(stat: &statfs) {
let block_size = stat.f_bsize as u64;
let total_blocks = stat.f_blocks as u64;
let free_blocks = stat.f_bfree as u64;
let available_blocks = stat.f_bavail as u64;

let total_space = block_size * total_blocks;
let used_space = total_space - (block_size * free_blocks);
let avail_space = block_size * available_blocks;
let used_percent = (used_space * 100) / total_space;

println!("Size: {}", format_size(total_space));
println!("Used: {}", format_size(used_space));
println!("Available: {}", format_size(avail_space));
println!("Use%: {}%", used_percent);
}

fn format_size(size: u64) -> String {
const KB: u64 = 1024;
const MB: u64 = KB * 1024;
const GB: u64 = MB * 1024;

if size >= GB {
format!("{:.2} GB", size as f64 / GB as f64)
} else if size >= MB {
format!("{:.2} MB", size as f64 / MB as f64)
} else if size >= KB {
format!("{:.2} KB", size as f64 / KB as f64)
} else {
format!("{} bytes", size)
}
}
Pptrxyz9/6/2023
Thanks a bunch! I figured it out basing my code on the FFI examples and the diskusage npm package.

Looking for more? Join the community!

Recommended Posts
test --filter a stepCan I only run a certain step in the test?fastwebsockets how to end client calls and avoid Error in websocket connection Unexpected EOFWhat is the issue in this client code that causes the error? ```rust pub async fn connect() -> Resuldeno compile --include argumentIn `deno compile`, how can i include a whole directory instead of just a file? Also, is there a way `deno run` as a library`deno run` does a lot of useful things behind the scenes, many of which are not exposed as a libraryPermissions with npm/node importsI'm trying to run a command and it's like I need to add `--allow-read` permissions because of the `nBroadcastChannelWhen using BroadcastChannel api, in the background does deno send the broadcast to every instance orIs it possible to create a TCP server on Deno Deploy?Is it possible to create a TCP server on Deno Deploy?oak server can't accept requests from another server?hi, I'm trying out deno with oak to make a simple server. I set up cors(x/cors), it accepts requestsaddEventListener for keydown in terminal via deno?Is there something like `addEventlistener("keydown")` in deno, so i can capture terminal inputs?Deno KV Type ErrorWhen I run await (await kv.get<typeThing>(["example"])).id (the value is an object), it returns a tyHow to improve seo ?https://deno.land/x/blog My question is when you use tool like this that work with md, how can i do Hashbang with TS file (without .ts extension)Hi y'all, I have a few convenience scripts written in Typescript for Deno that all have a wrapper scAstro + Deno - Remote ImportsFirst of all thanks a lot for the nice template, it looks great !! I followed the guide posted hereDebugging test in VSCode always breaks on line 54 of colors.tsWhen debugging tests in VSCode the debugger always breaks on line 54 of colors.ts. This behavior is Building from `src` offline?Hey guys! I'm new to Deno (and web dev as well to be honest), so could you help me here please. I'Any plan to fix Deno.listenTls() timing out a WebSocket connection?Any plan to fix Deno.listenTls() timing out a WebSocket connection? ``` {code: 1001, reason: 'No rePlaying sound from fileHow can i play the sound from a local file using deno?Deno with the --inspect-wait arg doesn't expose /json/protocol - should it?I'm testing out connecting to a Deno process via the v8 inspector protocol: https://deno.land/manual