-
Notifications
You must be signed in to change notification settings - Fork 13.4k
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
Conversation
Hopefully this will reduce the kind of confusion @joelmccracken repots in http://joelmccracken.github.io/entries/a-simple-web-app-in-rust-pt-2b/
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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
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 |
…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)
Given that #26642 is merged, I'm considering this addressed. |
Hopefully this will reduce the kind of confusion @joelmccracken repots in
http://joelmccracken.github.io/entries/a-simple-web-app-in-rust-pt-2b/