Files

Disk space

Free and total space of the disk a path is on, for health checks, refusing uploads before the disk fills, and admin pages.

Version 1.0.0 · 3 functions · 1 crate

#files#health#admin#uploads

Functions

What use disk_space.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use disk_space, disk_space_enough from disk_space (Quillo 0.6).

disk_space(path: str) → anyor an error

The disk that path (a file or a folder) is on: { total, free, available, used, used_percent }, in bytes. available is what this program may still write; free can be more, as some is kept for the system.

disk_space_enough(path: str, bytes: int, keep_percent: float) → boolor an error

Whether bytes more can be written on the disk of path and still leave keep_percent of it free (5.0 is a fair margin): check it before saving an upload or a backup.

disk_space_format(bytes: int) → str

A size in bytes as people read it, in powers of 1,024: 1536 is "1.5 KB", 0 is "0 B".

Get it

$ quillo install disk_space               # disk_space.qwer into this folder$ quillo install disk_space --example     # and its example, disk_space.qwe

Or with curl:

$ curl -O https://quillolang.org/plugins/files/disk_space.qwer$ curl -O https://quillolang.org/plugins/files/disk_space.qwe

Then, in your program, all of it or only what you call:

main.qwe
use disk_space.qweruse disk_space, disk_space_enough from disk_space      // Quillo 0.6: only these

It uses this crate, which cargo fetches the first time the plugin is built:

[dependencies]
fs4 = { version = "0.13", default-features = false, features = ["sync"] }

Example

disk_space.qwe
// A health check that warns before the disk fills, and an upload that is refused when it would.////   quillo run disk_space.qwe      then open http://localhost:8080/healthuse "disk_space.qwer"route GET /health {    let d = disk_space(".")?    {        status: d.used_percent > 95 ? "disk almost full" : "ok",        free: disk_space_format(d.available),        total: disk_space_format(d.total),        used_percent: d.used_percent,    }}route POST /upload {    let f = request.files.file ?? reply 400 "Choose a file"    if !disk_space_enough("data", f.size, 5.0)? { reply 507 "The server is out of space" }    { saved: save_upload(f, `data/uploads/${uuid()}`)? }}route GET /sizes = [0, 1023, 1536, 5_000_000, 3_221_225_472] | map(disk_space_format)
$ quillo run disk_space.qwe$ curl 'localhost:8080/health'$ curl 'localhost:8080/sizes'

Source

disk_space.qwer
//! Free and total space of the disk a path is on: for health checks, refusing uploads before the disk fills, and admin pages.//! version: 1.0.0//!//! [dependencies]//! fs4 = { version = "0.13", default-features = false, features = ["sync"] }use serde_json::{json, Value};fn stats(path: &str) -> Result<fs4::FsStats, String> {    let p = if path.is_empty() { "." } else { path };    fs4::statvfs(p).map_err(|e| format!("{}: {}", p, e))}/// The disk that `path` (a file or a folder) is on: `{ total, free, available, used, used_percent }`, in bytes./// `available` is what this program may still write; `free` can be more, as some is kept for the system.pub fn disk_space(path: &str) -> Result<Value, String> {    let s = stats(path)?;    let (total, free, avail) = (s.total_space(), s.free_space(), s.available_space());    let used = total.saturating_sub(free);    let pct = if total > 0 { (used as f64 / total as f64 * 1000.0).round() / 10.0 } else { 0.0 };    Ok(json!({ "total": total, "free": free, "available": avail, "used": used, "used_percent": pct }))}/// Whether `bytes` more can be written on the disk of `path` and still leave `keep_percent` of it free (5.0 is a fair margin): check it before saving an upload or a backup.pub fn disk_space_enough(path: &str, bytes: i64, keep_percent: f64) -> Result<bool, String> {    let s = stats(path)?;    let keep = (s.total_space() as f64 * keep_percent.clamp(0.0, 100.0) / 100.0) as u64;    Ok(s.available_space() >= (bytes.max(0) as u64).saturating_add(keep))}/// A size in bytes as people read it, in powers of 1,024: 1536 is "1.5 KB", 0 is "0 B".pub fn disk_space_format(bytes: i64) -> String {    let units = ["B", "KB", "MB", "GB", "TB", "PB", "EB"];    let mut v = bytes.max(0) as f64;    let mut i = 0;    while v >= 1024.0 && i < units.len() - 1 {        v /= 1024.0;        i += 1;    }    if i == 0 { format!("{} B", bytes.max(0)) } else if v < 10.0 { format!("{:.1} {}", v, units[i]).replace(".0 ", " ") } else { format!("{:.0} {}", v, units[i]) }}
Thread
88Useful? Like it, or add to its thread below.

Thread 0 posts

On Disk space: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.