Files
node/lib/internal/vfs
Philipp Dunkel 2d9c861a15 vfs: align virtual file handles with open(2)
A file descriptor obtained on a mounted path answers several `node:fs`
calls differently from one on a real file, in both providers:

* `writeFileSync(path, data, { flag: 'r+' })` replaces the whole file
  instead of overwriting bytes from offset 0 and keeping the tail.
* Numeric open flags are mapped by treating any write-ish bit as "w":
  `O_WRONLY` alone truncates, and `O_RDONLY | O_CREAT` opens the file
  write-only and truncates it.
* A handle opened with "a+" starts its read offset at the end of the
  file, so the first read returns nothing; O_APPEND only affects writes.

The ZipProvider handle additionally:

* throws EISDIR instead of EBADF when reading a write-only handle or
  writing a read-only one;
* leaves stale bytes in place when `ftruncate` grows a file that was
  previously shrunk, where real files read back as zeros;
* rejects a BigInt `position` with a TypeError from mixing number and
  BigInt arithmetic.

This adds a test that runs the same sequence of calls against a memory
mount and a ZIP mount and expects the real-fs result, so every
divergence shows up as its own failing case.

Proposed solution: decode numeric flags bit by bit (O_TRUNC decides
truncation, O_CREAT decides creation, O_WRONLY/O_RDWR decide access)
instead of collapsing them to a flag string; keep the read offset at 0
for append handles and only force writes to the end; make the handle
`writeFile` for non-truncating flags write at offset 0 without
shrinking; in the ZIP handle use EBADF for access-mode violations,
zero-fill on growth in `#doTruncate`, and coerce `position` with
`Number()` as the memory handle does.

Signed-off-by: Philipp Dunkel <pip@pipobscure.com>
PR-URL: https://github.com/nodejs/node/pull/65854
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2026-09-08 11:35:41 +00:00
..
…
…