use std::io;
use std::path::Path;
pub fn sync_directory(path: &Path) -> io::Result<()> {
#[cfg(unix)]
{
std::fs::File::open(path)?.sync_all()
}
#[cfg(windows)]
{
use std::os::windows::ffi::OsStrExt;
use windows_sys::Win32::Foundation::{
CloseHandle, GENERIC_READ, GENERIC_WRITE, INVALID_HANDLE_VALUE,
};
use windows_sys::Win32::Storage::FileSystem::{
CreateFileW, FlushFileBuffers, FILE_FLAG_BACKUP_SEMANTICS, FILE_SHARE_DELETE,
FILE_SHARE_READ, FILE_SHARE_WRITE, OPEN_EXISTING,
};
let path = path
.as_os_str()
.encode_wide()
.chain(std::iter::once(0))
.collect::<Vec<_>>();
let handle = unsafe {
CreateFileW(
path.as_ptr(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
std::ptr::null(),
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
std::ptr::null_mut(),
)
};
if handle == INVALID_HANDLE_VALUE {
return Err(io::Error::last_os_error());
}
let flushed = unsafe { FlushFileBuffers(handle) };
let flush_error = (flushed == 0).then(io::Error::last_os_error);
let closed = unsafe { CloseHandle(handle) };
if let Some(error) = flush_error {
return Err(error);
}
if closed == 0 {
return Err(io::Error::last_os_error());
}
Ok(())
}
#[cfg(not(any(unix, windows)))]
{
let _ = path;
Err(io::Error::new(
io::ErrorKind::Unsupported,
"directory synchronization is unsupported on this platform",
))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn syncs_directory() {
sync_directory(&std::env::current_dir().unwrap()).unwrap();
}
}