whichdisk 0.3.1

Cross-platform disk/volume resolver — given a path, tells you which disk it's on, its mount point, and the relative path
Documentation

Cross-platform disk/volume resolver — given a path, tells you which disk it's on, its mount point, and the relative path

Installation

As a library

[dependencies]
whichdisk = "0.3"

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 json

Default output:

device="/dev/disk3s5"
mount_point="/System/Volumes/Data"
relative_path="Users/user/Develop/personal/whichdisk"

JSON output (-o json):

{
  "device": "/dev/disk3s5",
  "mount_point": "/System/Volumes/Data",
  "relative_path": "Users/user/Develop/personal/whichdisk"
}

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 yaml

Default output:

mount_point="/" device="/dev/disk3s1s1"

JSON output (list -o json):

[
  {
    "device": "/dev/disk3s1s1",
    "mount_point": "/",
    "is_ejectable": false
  }
]

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());

    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(())
}

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

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 memchr for null-terminator and newline searches in the BSD statfs buffers 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.