Skip to content

Commit 734684e

Browse files
committed
dirext: make atomic_* really atomic
Also update documentation. Signed-off-by: Etienne Champetier <[email protected]>
1 parent 36a1e22 commit 734684e

File tree

1 file changed

+24
-6
lines changed

1 file changed

+24
-6
lines changed

src/dirext.rs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -157,11 +157,18 @@ pub trait CapStdExtDirExt {
157157
/// This uses [`cap_tempfile::TempFile`], which is wrapped in a [`std::io::BufWriter`]
158158
/// and passed to the closure.
159159
///
160+
/// # Atomicity
161+
///
162+
/// The function takes care of:
163+
/// - flushing the BufWriter
164+
/// - calling sync_all() on the TempFile
165+
/// - calling sync_all() on the parent directory (after the rename)
166+
///
160167
/// # Existing files and metadata
161168
///
162169
/// If the target path already exists and is a regular file (not a symbolic link or directory),
163170
/// then its access permissions (Unix mode) will be preserved. However, other metadata
164-
/// such as extended attributes will *not* be preserved automatically. To do this will
171+
/// such as extended attributes will *not* be preserved automatically. To do this will
165172
/// require a higher level wrapper which queries the existing file and gathers such metadata
166173
/// before replacement.
167174
///
@@ -296,11 +303,18 @@ pub trait CapStdExtDirExtUtf8 {
296303
/// This uses [`cap_tempfile::TempFile`], which is wrapped in a [`std::io::BufWriter`]
297304
/// and passed to the closure.
298305
///
306+
/// # Atomicity
307+
///
308+
/// The function takes care of:
309+
/// - flushing the BufWriter
310+
/// - calling sync_all() on the TempFile
311+
/// - calling sync_all() on the parent directory (after the rename)
312+
///
299313
/// # Existing files and metadata
300314
///
301315
/// If the target path already exists and is a regular file (not a symbolic link or directory),
302316
/// then its access permissions (Unix mode) will be preserved. However, other metadata
303-
/// such as extended attributes will *not* be preserved automatically. To do this will
317+
/// such as extended attributes will *not* be preserved automatically. To do this will
304318
/// require a higher level wrapper which queries the existing file and gathers such metadata
305319
/// before replacement.
306320
///
@@ -719,10 +733,14 @@ impl CapStdExtDirExt for Dir {
719733
let mut bufw = std::io::BufWriter::new(t);
720734
// Call the provided closure to generate the file content
721735
let r = f(&mut bufw)?;
722-
// Flush the buffer, and rename the temporary file into place
723-
bufw.into_inner()
724-
.map_err(From::from)
725-
.and_then(|t| t.replace(name))?;
736+
// Flush the buffer, get the TempFile
737+
t = bufw.into_inner().map_err(From::from)?;
738+
// fsync the TempFile
739+
t.as_file().sync_all()?;
740+
// rename the TempFile
741+
t.replace(name)?;
742+
// fsync the directory
743+
d.open(".")?.sync_all()?;
726744
Ok(r)
727745
}
728746

0 commit comments

Comments
 (0)