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

Conversation

steveklabnik
Copy link
Member

Hopefully this will reduce the kind of confusion @joelmccracken repots in
http://joelmccracken.github.io/entries/a-simple-web-app-in-rust-pt-2b/

@rust-highfive
Copy link
Contributor

r? @huonw

(rust_highfive has picked a reviewer for you, use r? to override)

@@ -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.

@remram44
Copy link
Contributor

It looks to me that append(true) definitely should imply write(true). If for some reason this is not acceptable, make open() fail on append-but-not-write, because this doesn't make any sense.

Doc for append() is definitely wrong

bors added a commit that referenced this pull request Jun 28, 2015
…crichton

Setting append without write doesn't give you a writeable file. Showing it as an example in the docs is confusing at best ([reddit](https://www.reddit.com/r/rust/comments/3bbz8w/why_is_writing_a_file_not_working_for_me/))

Using truncate (O_TRUNC) on a read-only file is an error on POSIX systems ("unspecified"). Note however that using create (O_CREAT) with read-only flags is fine.

Related: #26103 (which IMHO is wrong; saying "append is different than write" when should simply be "append needs write". My vote is to make append imply write)
@steveklabnik
Copy link
Member Author

Given that #26642 is merged, I'm considering this addressed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants