Rollup merge of #113876 - darklyspaced:master, r=cuviper

fix docs & example for `std::os::unix::prelude::FileExt::write_at`

 Changelog:
 * used `File::create` instead of `File::read` to get a writeable file
 * explicity mentioned the bug with `pwrite64` in docs

Unfortunately, I don't think that there is really much we can do about this since the feature has already been stabilised.

We could potentially add a clippy lint warning people on Linux that using `write_at` with the `O_APPEND` flag does not exhibit the behaviour that they would have assumed.

fixes #113627
This commit is contained in:
Matthias Krüger 2023-07-22 11:48:54 +02:00 committed by GitHub
commit 746d507c72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -149,7 +149,36 @@ fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> {
/// Note that similar to [`File::write`], it is not an error to return a
/// short write.
///
/// # Bug
/// On some systems, `write_at` utilises [`pwrite64`] to write to files.
/// However, this syscall has a [bug] where files opened with the `O_APPEND`
/// flag fail to respect the offset parameter, always appending to the end
/// of the file instead.
///
/// It is possible to inadvertantly set this flag, like in the example below.
/// Therefore, it is important to be vigilant while changing options to mitigate
/// unexpected behaviour.
///
/// ```no_run
/// use std::fs::File;
/// use std::io;
/// use std::os::unix::prelude::FileExt;
///
/// fn main() -> io::Result<()> {
/// // Open a file with the append option (sets the `O_APPEND` flag)
/// let file = File::options().append(true).open("foo.txt")?;
///
/// // We attempt to write at offset 10; instead appended to EOF
/// file.write_at(b"sushi", 10)?;
///
/// // foo.txt is 5 bytes long instead of 15
/// Ok(())
/// }
/// ```
///
/// [`File::write`]: fs::File::write
/// [`pwrite64`]: https://man7.org/linux/man-pages/man2/pwrite.2.html
/// [bug]: https://man7.org/linux/man-pages/man2/pwrite.2.html#BUGS
///
/// # Examples
///
@ -159,7 +188,7 @@ fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> {
/// use std::os::unix::prelude::FileExt;
///
/// fn main() -> io::Result<()> {
/// let file = File::open("foo.txt")?;
/// let file = File::create("foo.txt")?;
///
/// // We now write at the offset 10.
/// file.write_at(b"sushi", 10)?;