use std::io;
use std::path::Path;
use crate::platform::resources::InodeCapacity;
const WSAEMFILE: i32 = 10024;
const ERROR_TOO_MANY_OPEN_FILES: i32 = 4;
const ERROR_NO_SYSTEM_RESOURCES: i32 = 1450;
const ERROR_HANDLE_DISK_FULL: i32 = 39;
const ERROR_DISK_FULL: i32 = 112;
pub fn signals_fd_exhaustion(error: &io::Error) -> bool {
matches!(
error.raw_os_error(),
Some(WSAEMFILE | ERROR_TOO_MANY_OPEN_FILES | ERROR_NO_SYSTEM_RESOURCES)
)
}
pub fn signals_storage_exhaustion(error: &io::Error) -> bool {
if matches!(error.kind(), io::ErrorKind::StorageFull) {
return true;
}
matches!(
error.raw_os_error(),
Some(ERROR_HANDLE_DISK_FULL | ERROR_DISK_FULL)
)
}
pub fn fd_exhaustion_error() -> io::Error {
io::Error::from_raw_os_error(WSAEMFILE)
}
pub fn storage_exhaustion_error() -> io::Error {
io::Error::from_raw_os_error(ERROR_DISK_FULL)
}
pub fn inode_capacity(path: &Path) -> io::Result<Option<InodeCapacity>> {
let _ = path;
Ok(None)
}
pub fn total_space(path: &Path) -> io::Result<u64> {
Ok(disk_free_space(path)?.1)
}
pub fn available_space(path: &Path) -> io::Result<u64> {
Ok(disk_free_space(path)?.0)
}
fn disk_free_space(path: &Path) -> io::Result<(u64, u64)> {
use std::os::windows::ffi::OsStrExt as _;
use windows_sys::Win32::Storage::FileSystem::GetDiskFreeSpaceExW;
let wide: Vec<u16> = path
.as_os_str()
.encode_wide()
.chain(std::iter::once(0))
.collect();
let mut available_to_caller: u64 = 0;
let mut total: u64 = 0;
let mut total_free: u64 = 0;
let ok = unsafe {
GetDiskFreeSpaceExW(
wide.as_ptr(),
&mut available_to_caller,
&mut total,
&mut total_free,
)
};
if ok == 0 {
Err(io::Error::last_os_error())
} else {
Ok((available_to_caller, total))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn inode_usage_is_not_applicable_on_windows() {
let probed =
inode_capacity(&std::env::temp_dir()).expect("the probe never fails on Windows");
assert_eq!(probed, None);
}
}