Repository navigation
fs: add mkstemp() - #66484
fs: add mkstemp()#66484
Conversation
Add fs.mkstemp(), fs.mkstempSync() and fsPromises.mkstemp(), which create and open a unique temporary file in one operation. They expose uv_fs_mkstemp(), the file counterpart of the function behind fs.mkdtemp(). The callback and sync versions return the path and a file descriptor, the promise version returns the path and a FileHandle. libuv clears the path of the request when mkstemp() fails, so the template is saved in the request and used for the path of the error. The functions are also supported on mounted virtual file systems. Refs: nodejs#33549 Refs: nodejs#33890 Refs: nodejs#5332 Signed-off-by: marcopiraccini <marco.piraccini@gmail.com>
|
Review requested:
|
Signed-off-by: marcopiraccini <marco.piraccini@gmail.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #66484 +/- ##
==========================================
+ Coverage 90.42% 90.45% +0.02%
==========================================
Files 790 791 +1
Lines 275435 276851 +1416
Branches 52825 53169 +344
==========================================
+ Hits 249074 250424 +1350
- Misses 16772 16818 +46
- Partials 9589 9609 +20
🚀 New features to boost your workflow:
|
Signed-off-by: marcopiraccini <marco.piraccini@gmail.com>
|
Looks very interesting, I wonder if we could have an API such as {
await using fd = await mkstemp();
await fd.writeFile(/* … */);
await someOtherAPIThatReadsTheFile(fd);
} // file is automatically deleted on collectionI'm not sure how practical that would be, but it seems worse keeping that door open. Can you mark that API as experimental to allow it to evoluate without being semver-major? |
Signed-off-by: marcopiraccini <marco.piraccini@gmail.com>
Commit Queue failedThis pull request has multiple commits, but no landing policy was selected. Add
commit-queue-squash
The pull request was removed from the Commit Queue and labeled
commit-queue-failed
Full Commit Queue output |
|
Landed in 1a885ca |
This adds an API to create a unique temporary file, the file counterpart of
fs.mkdtemp():The file is created and opened in one operation, so there is no window between choosing a name and opening it. Today the alternatives are a random name with
open(..., 'wx')and a hand-written retry loop, ormkdtemp()plus a file inside the directory. libuv has haduv_fs_mkstemp()since 1.34.0 and Node.js already uses it internally for the compile cache; this exposes it.prefixandoptions.encodingbehave as forfs.mkdtemp(): six random characters are appended,prefixmay be a string,BufferorURL, and aBufferprefix returns aBufferpath.Naming
The name follows the POSIX function
mkstemp(3)that it wraps, in the same way asfs.mkdtemp()followsmkdtemp(3). It is also the name libuv uses (uv_fs_mkstemp()) and the name used in #33549.History
This is the API of #33549, which was approved in 2020 but did not land and was closed in 2023 with "Anyone feel free to take this over". It stalled on the
pathof the error on AIX: after a failedmkstemp()the template buffer is unspecified. libuv now clears it on every platform, so the async forms would report an empty path. Here the template is saved in the request before calling libuv and used to build the error. The sync, callback and promise forms all reportmkstemp '<prefix>XXXXXX', and the test checks it.The implementation is new, since the code around it changed a lot in the meantime.
Notes for reviewers
fs.readandfs.write, with the same helperfs.open()uses forO_RDWR | O_CREAT | O_EXCL.mkstempis added totest-permission-fs-supported.jsand to thefs-readandfs-writefixtures.fs.open(), so they are closed when a worker exits and closing them does not warn. TheFileHandleof the promise form manages its own descriptor.mkstempSync,mkstempandpromises.mkstempare added toVirtualFileSystem, and thenode:fsfunctions route mounted paths to them. The hooks run after argument validation. There is no retry on a name collision, which matches the vfsmkdtemp.mkdtemp: the code that appendsXXXXXXmoved to a helper shared withmkstemp. No behavior change.mkstemp()as well.fs.mkdtempDisposableSync(). I would leave it for a follow-up, to keep this PR to the plain API.Refs: #33549
Refs: #33890
Refs: #5332