Skip to content

Add note about append not implying write #26103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/libstd/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,11 @@ impl OpenOptions {
/// This option, when true, means that writes will append to a file instead
/// of overwriting previous contents.
///
/// Note that this isn't the same as `write` with the cursor starting at
/// the end of the file; this mode only allows writing to the end of the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I thought that this was basically the same as a write with the cursor starting at the end of the file? According to the manpage at least:

          The  file  is opened in append mode.  Before each write(2), the file
          offset is positioned at the end of the file, as  if  with  lseek(2).
          O_APPEND may lead to corrupted files on NFS filesystems if more than
          one process appends data to a file at once.   This  is  because  NFS
          does  not  support  appending to a file, so the client kernel has to
          simulate it, which can't be done without a race condition.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this is what I thought, too. If search for "bad file descriptor" in the cited post, you will see my experience with this issue.

I might have also been misunderstanding things.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I guess I may have been too. I thought this was setting the mode, as I mentioned here: http://www.reddit.com/r/rust/comments/391unl/a_simple_web_app_in_rust_part_2b/crzna4l which is consistent with the behavior Joel saw.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I think the append mode on files is definitely separate from this. I believe the confusion derives from the title of this PR (append doesn't imply write), but that just means that if you want to write to the file you also need to say write(true). Perhaps that could be mentioned in these docs?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I'm not sure of the right way to word it, you're suggesting dropping the 'cursor' bit, I guess? Because appending to a file is still writing to it...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The part I don't understand is:

Note that this isn't the same as write with the cursor starting at the end of the file

I would claim that append is the exact same as the cursor starting at the end of the file

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@steveklabnik if I understand what is going on, it seems like there must be some difference between writing and appending as a file operation, and this is what cat would be using in your example. This is news to me, if it is the case; is there a method in Rust somewhere that implements this append operation that I was missing?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The difference is that if O_APPEND is set, the kernel will atomically (except on NFS which is broken) do a seek() to the end of the file then the write. It doesn't only affect the initial position of the cursor, the cursor will jump back on each write. It is more than a common way to do log file, it is the only way to write log files without races.

Either way, append makes no sense if write isn't specified (the cursor behavior happens on write, so if you can't write...). In my opinion append should DEFINITELY imply write, as the current behavior only lead to errors. This is also what libc's fopen does. This shouldn't break existing code because code doing append without write is definitely not working.

Interestingly truncate also needs write (O_TRUNC; POSIX says behavior is undefined otherwise, which is bad), create doesn't.

/// file, but not changing any of its previous contents. This is common for
/// things like log files.
///
/// # Examples
///
/// ```no_run
Expand Down