How to find out if the disk that my current process uses is ssd?

Hello I would like to ask for some good example of how to find out in rust if the disk of my current process is ssd? I know you need an elevated prompt for some disk information but if I want to find out if my disk is ssd just somehow know if it supports trim.

You haven't specified what operating system you are using? I ask this as I don't believe the rust STD has any functionality to specifically query the disk type, and thus you will need to call into the OS to find out.

If this is on Windows, as suggested by mentioning an elevated prompt, you will need to implement something like Raymond Chen’s code from How can I tell whether a file is on an SSD? or from Stack Overflow. If you use windows-sys it looks like all the APIs and constants are available there.

If it’s not clear how to do this then I could have a go at converting the code for you, and for my edification.

1 Like

i am using windows currently

2022-05-25 2:17 GMT+02:00, g-radam via The Rust Programming Language
Forum notifications@rust-lang.discoursemail.com:

Yes this was good solution because windows sys don't need elevated
prompt and you can get ssd if you see disk trim.

2022-05-25 3:07 GMT+02:00, Carey Evans via The Rust Programming
Language Forum notifications@rust-lang.discoursemail.com:

For Google and other readers, this is what I came up with tonight:

use std::env;
use std::fs::File;
use std::iter::once;
use std::mem::{size_of, MaybeUninit};
use std::os::windows::prelude::{AsRawHandle, FromRawHandle, OsStrExt, RawHandle};
use std::path::{Path, PathBuf};
use std::ptr;

use windows_sys::Win32::Foundation::{GetLastError, INVALID_HANDLE_VALUE, MAX_PATH, WIN32_ERROR};
use windows_sys::Win32::Storage::FileSystem::{
    CreateFileW, GetVolumePathNameW, FILE_FLAG_BACKUP_SEMANTICS, FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE,
    OPEN_EXISTING,
};
use windows_sys::Win32::System::Ioctl::{
    PropertyStandardQuery, StorageDeviceSeekPenaltyProperty, DEVICE_SEEK_PENALTY_DESCRIPTOR, IOCTL_STORAGE_QUERY_PROPERTY,
    STORAGE_PROPERTY_QUERY,
};
use windows_sys::Win32::System::IO::DeviceIoControl;

fn get_volume_handle_for_file(path: &Path) -> Result<File, WIN32_ERROR> {
    let s_path: Vec<u16> = path.as_os_str().encode_wide().chain(once(0)).collect();
    let mut buf = [0u16; MAX_PATH as usize];
    if unsafe { GetVolumePathNameW(s_path.as_ptr(), buf.as_mut_ptr(), MAX_PATH) } == 0 {
        return Err(unsafe { GetLastError() });
    }
    match buf.iter_mut().rfind(|&&mut c| c != 0) {
        Some(c) if *c == b'\\'.into() => *c = 0,
        _ => {}
    }
    let handle = unsafe {
        CreateFileW(
            buf.as_ptr(),
            0,
            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
            ptr::null(),
            OPEN_EXISTING,
            FILE_FLAG_BACKUP_SEMANTICS,
            0,
        )
    };
    if handle == INVALID_HANDLE_VALUE {
        return Err(unsafe { GetLastError() });
    }
    Ok(unsafe { File::from_raw_handle(handle as RawHandle) })
}

fn is_volume_ssd(volume: &File) -> Result<bool, WIN32_ERROR> {
    let query = STORAGE_PROPERTY_QUERY {
        PropertyId: StorageDeviceSeekPenaltyProperty,
        QueryType: PropertyStandardQuery,
        AdditionalParameters: [0],
    };
    let mut result = MaybeUninit::<DEVICE_SEEK_PENALTY_DESCRIPTOR>::uninit();
    let mut bytes_returned = MaybeUninit::<u32>::uninit();
    let ok = unsafe {
        DeviceIoControl(
            volume.as_raw_handle() as _,
            IOCTL_STORAGE_QUERY_PROPERTY,
            (&query as *const STORAGE_PROPERTY_QUERY).cast(),
            size_of::<STORAGE_PROPERTY_QUERY>().try_into().unwrap(),
            result.as_mut_ptr().cast(),
            size_of::<DEVICE_SEEK_PENALTY_DESCRIPTOR>().try_into().unwrap(),
            bytes_returned.as_mut_ptr(),
            ptr::null_mut(),
        )
    };
    if ok == 0 {
        return Err(unsafe { GetLastError() });
    }
    let result = unsafe { result.assume_init() };
    Ok(result.IncursSeekPenalty == 0)
}

fn main() {
    let path = PathBuf::from(env::args_os().next().unwrap()).canonicalize().unwrap();
    let volume = get_volume_handle_for_file(&path).unwrap();
    if is_volume_ssd(&volume).unwrap() {
        println!("{} is on an SSD.", path.display());
    } else {
        println!("{} is not on an SSD.", path.display());
    }
}

is your code usable without elevated prompt? if yes then this is good idea

2022-05-25 13:37 GMT+02:00, Carey Evans via The Rust Programming
Language Forum notifications@rust-lang.discoursemail.com:

I was pleased to see that this works without needing any special access.

yes i will try to test your functions and if that will work then i
will try to figure out how to detect rpm on normal hard drives

2022-05-25 22:12 GMT+02:00, Carey Evans via The Rust Programming
Language Forum notifications@rust-lang.discoursemail.com:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.