use crate::error::Error;
use std::{fs::File, io, path::Path};
use urma_io::Access;
#[cfg(unix)]
pub(crate) fn file_identity(path: &Path) -> Result<(u64, u128), Error> {
use std::os::unix::fs::MetadataExt;
let metadata = std::fs::metadata(path)?;
Ok((metadata.dev(), u128::from(metadata.ino())))
}
#[cfg(windows)]
pub(crate) fn file_identity(path: &Path) -> Result<(u64, u128), Error> {
use std::os::windows::io::AsRawHandle;
use windows_sys::Win32::Storage::FileSystem::{
FILE_ID_INFO, FileIdInfo, GetFileInformationByHandleEx,
};
let file = File::open(path)?;
let mut info = FILE_ID_INFO::default();
let size = u32::try_from(size_of::<FILE_ID_INFO>()).map_err(io::Error::other)?;
let filled = unsafe {
GetFileInformationByHandleEx(
file.as_raw_handle(),
FileIdInfo,
std::ptr::from_mut(&mut info).cast(),
size,
)
};
if filled == 0 {
return Err(io::Error::last_os_error().into());
}
Ok((
info.VolumeSerialNumber,
u128::from_le_bytes(info.FileId.Identifier),
))
}
pub(crate) fn append_private(path: &Path) -> Result<File, Error> {
match urma_io::create_file(path, Access::Private) {
Ok(file) => Ok(file),
Err(cause) if cause.kind() == io::ErrorKind::AlreadyExists => {
Ok(urma_io::open_private_append(path)?)
}
Err(cause) => Err(cause.into()),
}
}
#[cfg(not(windows))]
pub(crate) fn sync_landed(directory: &Path) -> Result<(), Error> {
urma_io::sync_directory(directory)?;
Ok(())
}
#[cfg(windows)]
pub(crate) fn sync_landed(directory: &Path) -> Result<(), Error> {
match urma_io::sync_directory(directory) {
Ok(()) => {}
Err(cause) => tracing::warn!(
error = %cause,
directory = %directory.display(),
"data landed; directory flush unsupported here"
),
}
Ok(())
}