about summary refs log tree commit diff
diff options
context:
space:
mode:
authorHrvoje Niksic <hniksic@gmail.com>2024-02-08 12:25:30 +0100
committerHrvoje Niksic <hniksic@gmail.com>2024-04-16 14:07:48 +0200
commitd8745f934650115821b2af5755871e9c4df408fd (patch)
tree17904d58c4f0d530611417c3cfa57534b12ea796
parentad18fe08de03fbb459c05475bddee22707b4f0ec (diff)
downloadrust-d8745f934650115821b2af5755871e9c4df408fd.tar.gz
rust-d8745f934650115821b2af5755871e9c4df408fd.zip
Update usage note on OpenOptions::append()
Avoid implying that concatenating data before passing it to `write()` (with
or without `BufWriter`) ensures atomicity.
-rw-r--r--library/std/src/fs.rs27
1 files changed, 18 insertions, 9 deletions
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 8a24949631c..1293abddaf3 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -980,15 +980,21 @@ impl OpenOptions {
     /// Note that setting `.write(true).append(true)` has the same effect as
     /// setting only `.append(true)`.
     ///
-    /// For most filesystems, the operating system guarantees that all writes are
-    /// atomic: no writes get mangled because another process writes at the same
-    /// time.
-    ///
-    /// One maybe obvious note when using append-mode: make sure that all data
-    /// that belongs together is written to the file in one operation. This
-    /// can be done by concatenating strings before passing them to [`write()`],
-    /// or using a buffered writer (with a buffer of adequate size),
-    /// and calling [`flush()`] when the message is complete.
+    /// Append mode guarantees that writes will be positioned at the current end of file,
+    /// even when there are other processes or threads appending to the same file. This is
+    /// unlike <code>[seek]\([SeekFrom]::[End]\(0))</code> followed by `write()`, which
+    /// has a race between seeking and writing during which another writer can write, with
+    /// our `write()` overwriting their data.
+    ///
+    /// Keep in mind that this does not necessarily guarantee that data appended by
+    /// different processes or threads does not interleave. The amount of data accepted a
+    /// single `write()` call depends on the operating system and file system. A
+    /// successful `write()` is allowed to write only part of the given data, so even if
+    /// you're careful to provide the whole message in a single call to `write()`, there
+    /// is no guarantee that it will be written out in full. If you rely on the filesystem
+    /// accepting the message in a single write, make sure that all data that belongs
+    /// together is written in one operation. This can be done by concatenating strings
+    /// before passing them to [`write()`].
     ///
     /// If a file is opened with both read and append access, beware that after
     /// opening, and after every write, the position for reading may be set at the
@@ -1003,6 +1009,9 @@ impl OpenOptions {
     /// [`write()`]: Write::write "io::Write::write"
     /// [`flush()`]: Write::flush "io::Write::flush"
     /// [stream_position]: Seek::stream_position "io::Seek::stream_position"
+    /// [seek]: Seek::seek "io::Seek::seek"
+    /// [Current]: SeekFrom::Current "io::SeekFrom::Current"
+    /// [End]: SeekFrom::End "io::SeekFrom::End"
     ///
     /// # Examples
     ///