-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
fs: track file offset in writeFile of fs/promises #23136
Conversation
If the file offset is not tracked with `position` in the `write` calls all the data will be always written at the end of the file. This is problematic when we pass file descriptors to `writeFile` because the the file offset will not be updated. So, if some string is written to the FD with `writeFile` and if some other string is written to the same FD with `writeFile` without closing and reopening the file, the contents will be appended instead of writing from the beginning.
cc @nodejs/fs @vsemozhetbyt If this change gets in, I'll propose a fix for #22554 |
This might just be me and my unix background, but the current behaviour seems right to me (both here and in #23181)… |
@addaleax Either way, one of the examples is not correct, right? Quoting the example from #22554 'use strict';
const fs = require('fs');
const fileName = 'test.txt';
fs.writeFileSync(fileName, '123');
fs.writeFileSync(fileName, '0');
console.log(fs.readFileSync(fileName, 'utf8'));
// 0
fs.unlinkSync(fileName);
const fd = fs.openSync(fileName, 'w');
fs.writeFileSync(fd, '123');
fs.writeFileSync(fd, '0');
fs.closeSync(fd);
console.log(fs.readFileSync(fileName, 'utf8'));
// 023
fs.unlinkSync(fileName); Another possibility is that we can update the documentation about the file descriptor case. Personally, I have always expected |
@thefourtheye A file descriptor is more than a reference to a file, it’s a reference to a file and a position in that file (if the file supports positioning)… but yeah, let’s see what other people think. |
@nodejs/fs PTAL. |
Bump @nodejs/fs |
do { | ||
const { bytesWritten } = | ||
await write(filehandle, buffer, 0, | ||
Math.min(16384, buffer.length)); | ||
Math.min(16384, buffer.length), position); |
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.
Positional writes don't work on streams, try running this variant of writeFile to stdout.
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.
Agreed, if we cannot seek the position in fd, it will fail. Wouldn't that be the expected behaviour in this case?
This issue was beaten to death in the past. Seeking to position 0 on a fd provided to writeFile may seem like the obviously right thing to do... but doesn't work on pipes. Pleas read #10853 (comment) for some history, and the ensuing conversation, its about readFile but the issues are the same. Summary: I believe current behaviour is intended, and if you could get agreement on the behaviour around unseekable fds, changing it would be semver-major. |
Today, we define
So, if the If we cannot seek to a particular position in the file with a file descriptor, then an error would be the expected behaviour I believe. Maybe we can explicitly mention in the docs. Other option would be to explicitly introduce a check in these functions to make sure that the fd actually corresponds to a file. I understand that all these are breaking changes. |
@sam-github This PR is not semver-major as the fs promises APIs are still experimental, I believe. The actual PR to fix the behaviour of |
@thefourtheye Did you read the history in #10853? Some people expected seeking, some people did not. One node test at that time, perhaps accidently, required readFile to work on a stdin. It would be sensible if the equivalent test existed for writeFile, but it possibly does not. Quoting the docs is not enormously compelling, they were not sufficiently updated when the fd capability was shoe-horned into the existing API. I don't have a strong opinion on seek or not anymore, both alternatives have valid use-cases, but I do have one strong opinion: if writeFile seeks, so should readFile. Please do not make them diverge. Note: I don't know if this PR does or not, I haven't gone to check the current state of readFile. |
@sam-github Thanks, I read the history from #10853 and the linked issues. We'll make sure that the behaviour is consistent with both
Neither of these PRs change the |
This will need to land by Saturday in order to make it into 11.0.0. |
@thefourtheye Is the hope to still land this? Or has this been superseded by other things? |
As per the decision in #23433, the current behaviour is expected. So closing this. |
If the file offset is not tracked with
position
in thewrite
callsall the data will be always written at the end of the file.
This is problematic when we pass file descriptors to
writeFile
becausethe the file offset will not be updated. So, if some string is written
to the FD with
writeFile
and if some other string is written to thesame FD with
writeFile
without closing and reopening the file, thecontents will be appended instead of writing from the beginning.
Simple Reproduction of the Bug
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes