use std::fs::File;
use std::io;
use std::path::Path;
#[cfg(target_os = "macos")]
pub fn durable_sync(file: &File) -> io::Result<()> {
use std::os::unix::io::AsRawFd;
let ret = unsafe { libc::fcntl(file.as_raw_fd(), libc::F_FULLFSYNC) };
if ret == -1 {
Err(io::Error::last_os_error())
} else {
Ok(())
}
}
#[cfg(not(target_os = "macos"))]
pub fn durable_sync(file: &File) -> io::Result<()> {
file.sync_data()
}
#[cfg(unix)]
pub fn sync_dir(path: &Path) -> io::Result<()> {
let dir = File::open(path)?;
durable_sync(&dir)
}
#[cfg(not(unix))]
pub fn sync_dir(_path: &Path) -> io::Result<()> {
Ok(())
}
#[cfg(windows)]
pub fn rename_with_retry(from: &Path, to: &Path) -> io::Result<()> {
use std::thread;
use std::time::Duration;
let delays = [50, 100, 200];
let mut last_err = None;
for (attempt, delay_ms) in std::iter::once(&0u64).chain(delays.iter()).enumerate() {
if attempt > 0 {
thread::sleep(Duration::from_millis(*delay_ms));
}
match std::fs::rename(from, to) {
Ok(()) => return Ok(()),
Err(e) => {
if e.raw_os_error() == Some(32) {
last_err = Some(e);
continue;
}
return Err(e);
}
}
}
Err(last_err
.unwrap_or_else(|| io::Error::new(io::ErrorKind::Other, "rename failed after retries")))
}
#[cfg(not(windows))]
pub fn rename_with_retry(from: &Path, to: &Path) -> io::Result<()> {
std::fs::rename(from, to)
}
pub fn resolve_symlinks(path: &Path) -> io::Result<std::path::PathBuf> {
std::fs::canonicalize(path)
}