Expand description
whichdisk
Cross-platform disk/volume resolver — given a path, tells you which disk it’s on, its mount point, relative path, disk usage, and per-volume capabilities (case-sensitivity, filesystem type)
§Installation
§As a library
[dependencies]
whichdisk = "0.5"§As a CLI tool
cargo install whichdisk --features cli§CLI Usage
§Resolve a path
# Resolve the current working directory
whichdisk
# Resolve a specific path
whichdisk -p /home/user/documents
# Output as JSON
whichdisk -o json
# Output as YAML
whichdisk -o yaml
# Combine options
whichdisk -p /tmp -o jsonDefault output:
device="/dev/disk3s5"
mount_point="/System/Volumes/Data"
relative_path="Users/user/Develop/personal/whichdisk"
total=926.35 GiB
available=701.81 GiB
used=224.55 GiBJSON output (-o json):
{
"device": "/dev/disk3s5",
"mount_point": "/System/Volumes/Data",
"relative_path": "Users/user/Develop/personal/whichdisk",
"total_bytes": 994662584320,
"available_bytes": 753886154752,
"used_bytes": 240776429568
}§List mounted volumes
# List all mounted volumes
whichdisk list
# Shorthand
whichdisk l
# Skip ejectable/removable volumes (show only internal disks)
whichdisk list --skip-ejectable
# Skip non-ejectable volumes (show only removable disks)
whichdisk list --skip-non-ejectable
# Output as JSON
whichdisk list -o json
# Output as YAML
whichdisk list -o yamlDefault output:
mount_point="/" device="/dev/disk3s1s1" total=926.35 GiB available=701.81 GiB used=224.55 GiBJSON output (list -o json):
[
{
"device": "/dev/disk3s1s1",
"mount_point": "/",
"is_ejectable": false,
"total_bytes": 994662584320,
"available_bytes": 753886154752,
"used_bytes": 240776429568
}
]§Library Usage
§Resolve a path to its disk
use whichdisk::resolve;
fn main() -> std::io::Result<()> {
let info = resolve("/home/user/documents/report.pdf")?;
println!("Mount point: {}", info.mount_point().display());
println!("Device: {:?}", info.device());
println!("Relative path: {}", info.relative_path().display());
println!("Ejectable: {}", info.is_ejectable());
println!("Total: {} bytes", info.total_bytes());
println!("Available: {} bytes", info.available_bytes());
println!("Used: {} bytes", info.used_bytes());
Ok(())
}§Get the root filesystem
use whichdisk::root;
fn main() -> std::io::Result<()> {
let info = root()?;
println!("Root mount: {}", info.mount_point().display());
println!("Root device: {:?}", info.device());
Ok(())
}§List mounted volumes
use whichdisk::{list, list_with, list_ejectable, list_non_ejectable, ListOptions};
fn main() -> std::io::Result<()> {
// List all real (non-virtual) volumes
for m in list()? {
println!("{:?} -> {:?} (ejectable: {})",
m.device(), m.mount_point(), m.is_ejectable());
}
// List only ejectable/removable volumes
for m in list_ejectable()? {
println!("Removable: {:?}", m.mount_point());
}
// List only non-ejectable volumes
for m in list_non_ejectable()? {
println!("Internal: {:?}", m.mount_point());
}
// Using ListOptions
let opts = ListOptions::all().set_ejectable_only(true);
let removable = list_with(opts)?;
Ok(())
}§Volume capabilities
Every MountPoint / PathLocation also reports the volume’s case-sensitivity, case-preservation, and filesystem type. Capability values are Option<bool> where None means “unknown on this platform/filesystem” — never conflated with Some(false).
use whichdisk::resolve;
fn main() -> std::io::Result<()> {
let info = resolve("/some/path")?;
println!("Filesystem: {}", info.fs_type());
println!("Case-sensitive: {:?}", info.case_sensitive()); // Option<bool>
println!("Case-preserving: {:?}", info.case_preserving()); // Option<bool>
Ok(())
}§Feature Flags
| Feature | Default? | Description |
|---|---|---|
disk-usage | Yes | Enables total_bytes(), available_bytes(), and used_bytes() |
list | Yes | Enables list(), list_with(), and ListOptions |
cli | No | Builds the whichdisk CLI binary |
To use only the core resolve() API with minimal dependencies:
[dependencies]
whichdisk = { version = "0.5", default-features = false }§Supported Platforms
| Platform | Resolve backend | List backend | Ejectable detection |
|---|---|---|---|
| macOS, iOS, watchOS, tvOS, visionOS | statfs via rustix | NSFileManager via objc2-foundation | NSURLVolumeIsEjectableKey / NSURLVolumeIsRemovableKey |
| FreeBSD, OpenBSD, DragonFlyBSD | statfs via rustix | getmntinfo via libc | /dev/da* or /dev/cd* device prefix |
| NetBSD | statvfs via libc | getmntinfo via libc | /dev/sd* or /dev/cd* device prefix |
| Linux | /proc/self/mountinfo parsing | /proc/self/mountinfo parsing | /dev/disk/by-id/usb-* |
| Windows | GetVolumePathNameW via windows-sys | FindFirstVolumeW / FindNextVolumeW | GetDriveTypeW = DRIVE_REMOVABLE |
Volume capabilities (case_sensitive() / case_preserving() / fs_type()) are sourced per-OS: Apple via getattrlist (VOL_CAP_FMT_CASE_SENSITIVE / VOL_CAP_FMT_CASE_PRESERVING), Windows via GetVolumeInformationW, and elsewhere from the filesystem type. They follow a None-means-unknown contract — Some(..) only when the platform or filesystem type definitively proves the answer.
§Performance
- Thread-local cache — repeated lookups for paths on the same device skip the underlying syscall/file read entirely
- Small-buffer optimization — mount points and device names (typically < 56 bytes) are stored inline on the stack; longer values use reference-counted
bytes::Bytes(clone is a pointer copy) - SIMD-accelerated scanning — uses
memchrfor null-terminator and newline searches in the BSDstatfsbuffers and Linux mountinfo parsing
§MSRV
The minimum supported Rust version is 1.85.
§License
whichdisk is under the terms of both the MIT license and the
Apache License (Version 2.0).
See LICENSE-APACHE, LICENSE-MIT for details.
Copyright (c) 2026 Al Liu.
Structs§
- List
Options list - Options for listing mounted volumes.
- Mount
Point - Information about a mount point (device, path, capacity, capabilities, and whether it’s ejectable).
- Path
Location - Information about the disk/volume a specific file path resides on.
- Volume
Capabilities - Case-handling and filesystem-type capabilities of a volume.
Functions§
- list
list - Lists all real (non-virtual) mounted volumes.
- list_
ejectable list - Lists only ejectable/removable mounted volumes.
- list_
non_ ejectable list - Lists only non-ejectable/non-removable mounted volumes (internal drives, etc.).
- list_
with list - Lists mounted volumes with the given options.
- resolve
- Given a path, resolves which disk/volume it resides on.
- root
DragonFly BSD or FreeBSD or iOS or Linux or macOS or NetBSD or OpenBSD or tvOS or visionOS or watchOS or Windows - Returns the
PathLocationof the system drive root.