From 5761ba9f68f6ce079d1804e0c4b500150091cbf9 Mon Sep 17 00:00:00 2001 From: Hrvoje Niksic Date: Thu, 8 Feb 2024 12:25:30 +0100 Subject: [PATCH] Correct usage note on OpenOptions::append() --- library/std/src/fs.rs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 80d369eb067d4..fcc0c17248c62 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -971,15 +971,18 @@ 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 [seek]([SeekFrom]::[End](0))` 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 atomicity of `write()` in append mode is less useful than it + /// appears at first. 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 written out in full. Unless + /// the data to append consists of a single byte, you can't append atomically without + /// external locking. /// /// 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 @@ -995,6 +998,7 @@ impl OpenOptions { /// [`flush()`]: Write::flush "io::Write::flush" /// [seek]: Seek::seek "io::Seek::seek" /// [Current]: SeekFrom::Current "io::SeekFrom::Current" + /// [End]: SeekFrom::End "io::SeekFrom::End" /// /// # Examples ///