trying atomic rename thing
[rust-lightning] / lightning-persister / src / util.rs
index 004bc5d67def63864f5365b08b42b99b4e76e421..7d63a41565bac14edca10707f62499544caef96e 100644 (file)
@@ -1,6 +1,14 @@
+
+#[cfg(target_os = "windows")]
+extern crate winapi;
+
 use std::fs;
 use std::path::{Path, PathBuf};
-
+#[cfg(target_os = "windows")]
+       use {
+               std::ffi::OsStr,
+               std::os::windows::ffi::OsStrExt
+               };
 #[cfg(not(target_os = "windows"))]
 use std::os::unix::io::AsRawFd;
 
@@ -13,12 +21,34 @@ pub(crate) fn get_full_filepath(filepath: String, filename: String) -> String {
        path.push(filename);
        path.to_str().unwrap().to_string()
 }
+#[cfg(target_os = "windows")]
+macro_rules! call {
+       ($e: expr) => (
+               if $e != 0 {
+                       return Ok(())
+               } else {
+                       return Err(std::io::Error::last_os_error())
+               }
+       )
+}
+
+#[cfg(target_os = "windows")]
+fn path_to_windows_str<T: AsRef<OsStr>>(x: T) -> Vec<winapi::shared::ntdef::WCHAR> {
+       x.as_ref().encode_wide().chain(Some(0)).collect()
+}
 
 #[allow(bare_trait_objects)]
 pub(crate) fn write_to_file<D: DiskWriteable>(path: String, filename: String, data: &D) -> std::io::Result<()> {
        println!("VMW: creating dir");
        fs::create_dir_all(path.clone())?;
        println!("VMW: created dir");
+
+       println!("VMW: entries in dir:");
+       let dir = PathBuf::from(path.clone());
+       for entry in fs::read_dir(dir).unwrap() {
+               let entry = entry.unwrap();
+               println!("VMW: entry in dir: {:?}", entry.path());
+       }
        // Do a crazy dance with lots of fsync()s to be overly cautious here...
        // We never want to end up in a state where we've lost the old data, or end up using the
        // old data on power loss after we've returned.
@@ -38,16 +68,25 @@ pub(crate) fn write_to_file<D: DiskWriteable>(path: String, filename: String, da
                f.sync_all()?;
                println!("VMW: sync'd all");
        }
-       println!("VMW: about to rename");
-       fs::rename(&tmp_filename, &filename_with_path)?;
-       println!("VMW: renamed");
        // Fsync the parent directory on Unix.
        #[cfg(not(target_os = "windows"))]
        {
+               fs::rename(&tmp_filename, &filename_with_path)?;
                let path = Path::new(&filename_with_path).parent().unwrap();
                let dir_file = fs::OpenOptions::new().read(true).open(path)?;
                unsafe { libc::fsync(dir_file.as_raw_fd()); }
        }
+       #[cfg(target_os = "windows")]
+       {
+               println!("VMW: about to rename");
+               let src = PathBuf::from(tmp_filename);
+               let dst = PathBuf::from(filename_with_path);
+               call!(unsafe {winapi::um::winbase::MoveFileExW(
+                       path_to_windows_str(src).as_ptr(), path_to_windows_str(dst).as_ptr(),
+                       winapi::um::winbase::MOVEFILE_WRITE_THROUGH | winapi::um::winbase::MOVEFILE_REPLACE_EXISTING
+               )});
+               println!("VMW: renamed");
+       }
        Ok(())
 }