@@ -12,6 +12,8 @@ pub use winver::*;
1212
1313use std:: {
1414 collections:: HashMap ,
15+ fs:: { create_dir_all, File } ,
16+ io:: Write ,
1517 path:: { Path , PathBuf } ,
1618 sync:: { atomic:: AtomicBool , Arc , LazyLock } ,
1719 time:: { Duration , Instant , SystemTime , UNIX_EPOCH } ,
@@ -26,6 +28,23 @@ use windows::{
2628
2729use crate :: { error:: Result , get_tokio_handle} ;
2830
31+ /// Writes `content` to `path` atomically: writes to a sibling `.tmp` file first,
32+ /// syncs to disk, then renames into place. This guarantees the target file is
33+ /// never left empty or partially written, even if the process is killed mid-write.
34+ pub fn atomic_write_file ( path : & Path , content : & [ u8 ] ) -> Result < ( ) > {
35+ let dir = path. parent ( ) . ok_or ( "Path has no parent directory" ) ?;
36+ create_dir_all ( dir) ?;
37+
38+ let tmp_path = path. with_extension ( "tmp" ) ;
39+ let mut file = File :: create ( & tmp_path) ?;
40+ file. write_all ( content) ?;
41+ file. flush ( ) ?;
42+ file. sync_all ( ) ?;
43+ drop ( file) ; // must close before rename on Windows
44+ std:: fs:: rename ( & tmp_path, path) ?;
45+ Ok ( ( ) )
46+ }
47+
2948pub fn pcwstr ( s : & str ) -> windows:: core:: PCWSTR {
3049 windows:: core:: PCWSTR :: from_raw ( s. encode_utf16 ( ) . chain ( Some ( 0 ) ) . collect_vec ( ) . as_ptr ( ) )
3150}
0 commit comments