use std::fs::{File, OpenOptions};
use std::path::{Path, PathBuf};
use std::fs::read_dir;
use std::os::unix::io::*;
use ::nix::*;
use crate::storage::*;
pub fn open_file_direct<P: AsRef<Path>>(file_path: P, write_access: bool) -> IoResult<File> {
let file = OpenOptions::new()
.create(false)
.append(false)
.write(write_access)
.read(true)
.truncate(false)
.open(file_path.as_ref())?;
unsafe {
let fd = file.as_raw_fd();
nix::libc::fcntl(fd, nix::libc::F_NOCACHE, 1);
}
Ok(file)
}
pub fn get_block_device_size(fd: libc::c_int) -> u64 {
ioctl_read!(dk_get_block_size, b'd', 24, u32); ioctl_read!(dk_get_block_count, b'd', 25, u64);
unsafe {
let mut block_size: u32 = std::mem::zeroed();
let mut block_count: u64 = std::mem::zeroed();
dk_get_block_size(fd, &mut block_size).unwrap();
dk_get_block_count(fd, &mut block_count).unwrap();
(block_size as u64) * block_count
}
}
pub fn is_trim_supported(fd: RawFd) -> bool {
ioctl_read!(dk_get_features, b'd', 76, u32);
unsafe {
let mut features: u32 = std::mem::zeroed();
dk_get_features(fd, &mut features)
.map(|_| (features & 0x00000010) > 0) .unwrap_or(false)
}
}
pub fn get_storage_devices() -> IoResult<Vec<FileRef>> {
discover_file_based_devices(
"/dev",
|p| p.to_str().unwrap().contains("/dev/rdisk"),
|_m| true
)
}
fn discover_file_based_devices<P: AsRef<Path>>(
root: P,
path_filter: fn(&PathBuf) -> bool,
meta_filter: fn(&StorageDetails) -> bool
) -> IoResult<Vec<FileRef>> {
let rd = read_dir(&root)?;
let mut refs = rd.filter_map(std::io::Result::ok)
.map(|de| de.path())
.filter(|path|
(path_filter)(&path.to_path_buf())
)
.flat_map(FileRef::new)
.filter(|r|
(meta_filter)(&r.details)
)
.collect::<Vec<_>>();
refs.sort_by(|a, b| a.path.to_str().cmp(&b.path.to_str()));
Ok(refs)
}