Skip to content

Commit 80155d3

Browse files
raltevanlucas
authored andcommitted
fs: add the fs.mkdtemp() function.
This uses libuv's mkdtemp function to provide a way to create a temporary folder, using a prefix as the path. The prefix is appended six random characters. The callback function will receive the name of the folder that was created. Usage example: fs.mkdtemp('/tmp/foo-', function(err, folder) { console.log(folder); // Prints: /tmp/foo-Tedi42 }); The fs.mkdtempSync version is also provided. Usage example: console.log(fs.mkdtemp('/tmp/foo-')); // Prints: tmp/foo-Tedi42 This pull request also includes the relevant documentation changes and tests. PR-URL: #5333 Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com> Reviewed-By: Trevor Norris <trev.norris@gmail.com> Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 731f7b8 commit 80155d3

File tree

4 files changed

+98
-0
lines changed

4 files changed

+98
-0
lines changed

doc/api/fs.markdown

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,30 @@ to the completion callback. `mode` defaults to `0o777`.
532532

533533
Synchronous mkdir(2). Returns `undefined`.
534534

535+
## fs.mkdtemp(prefix, callback)
536+
537+
Creates a unique temporary directory.
538+
539+
Generates six random characters to be appended behind a required
540+
`prefix` to create a unique temporary directory.
541+
542+
The created folder path is passed as a string to the callback's second
543+
parameter.
544+
545+
Example:
546+
547+
```js
548+
fs.mkdtemp('/tmp/foo-', (err, folder) => {
549+
console.log(folder);
550+
// Prints: /tmp/foo-itXde2
551+
});
552+
```
553+
554+
## fs.mkdtempSync(template)
555+
556+
The synchronous version of [`fs.mkdtemp()`][]. Returns the created
557+
folder path.
558+
535559
## fs.open(path, flags[, mode], callback)
536560

537561
Asynchronous file open. See open(2). `flags` can be:

lib/fs.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2078,3 +2078,24 @@ SyncWriteStream.prototype.destroy = function() {
20782078
};
20792079

20802080
SyncWriteStream.prototype.destroySoon = SyncWriteStream.prototype.destroy;
2081+
2082+
fs.mkdtemp = function(prefix, callback) {
2083+
if (typeof callback !== 'function') {
2084+
throw new TypeError('"callback" argument must be a function');
2085+
}
2086+
2087+
if (!nullCheck(prefix, callback)) {
2088+
return;
2089+
}
2090+
2091+
var req = new FSReqWrap();
2092+
req.oncomplete = callback;
2093+
2094+
binding.mkdtemp(prefix + 'XXXXXX', req);
2095+
};
2096+
2097+
fs.mkdtempSync = function(prefix) {
2098+
nullCheck(prefix);
2099+
2100+
return binding.mkdtemp(prefix + 'XXXXXX');
2101+
};

src/node_file.cc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,11 @@ static void After(uv_fs_t *req) {
200200
static_cast<const uv_stat_t*>(req->ptr));
201201
break;
202202

203+
case UV_FS_MKDTEMP:
204+
argv[1] = String::NewFromUtf8(env->isolate(),
205+
static_cast<const char*>(req->path));
206+
break;
207+
203208
case UV_FS_READLINK:
204209
argv[1] = String::NewFromUtf8(env->isolate(),
205210
static_cast<const char*>(req->ptr));
@@ -1291,6 +1296,25 @@ static void FUTimes(const FunctionCallbackInfo<Value>& args) {
12911296
}
12921297
}
12931298

1299+
static void Mkdtemp(const FunctionCallbackInfo<Value>& args) {
1300+
Environment* env = Environment::GetCurrent(args);
1301+
1302+
if (args.Length() < 1)
1303+
return TYPE_ERROR("template is required");
1304+
if (!args[0]->IsString())
1305+
return TYPE_ERROR("template must be a string");
1306+
1307+
node::Utf8Value tmpl(env->isolate(), args[0]);
1308+
1309+
if (args[1]->IsObject()) {
1310+
ASYNC_CALL(mkdtemp, args[1], *tmpl);
1311+
} else {
1312+
SYNC_CALL(mkdtemp, *tmpl, *tmpl);
1313+
args.GetReturnValue().Set(String::NewFromUtf8(env->isolate(),
1314+
SYNC_REQ.path));
1315+
}
1316+
}
1317+
12941318
void FSInitialize(const FunctionCallbackInfo<Value>& args) {
12951319
Local<Function> stats_constructor = args[0].As<Function>();
12961320
CHECK(stats_constructor->IsFunction());
@@ -1344,6 +1368,8 @@ void InitFs(Local<Object> target,
13441368
env->SetMethod(target, "utimes", UTimes);
13451369
env->SetMethod(target, "futimes", FUTimes);
13461370

1371+
env->SetMethod(target, "mkdtemp", Mkdtemp);
1372+
13471373
StatWatcher::Initialize(env, target);
13481374

13491375
// Create FunctionTemplate for FSReqWrap

test/parallel/test-fs-mkdtemp.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('assert');
5+
const fs = require('fs');
6+
const path = require('path');
7+
const Buffer = require('buffer').Buffer;
8+
9+
common.refreshTmpDir();
10+
11+
const tmpFolder = fs.mkdtempSync(path.join(common.tmpDir, 'foo.'));
12+
13+
assert(path.basename(tmpFolder).length === 'foo.XXXXXX'.length);
14+
assert(common.fileExists(tmpFolder));
15+
16+
const utf8 = fs.mkdtempSync(path.join(common.tmpDir, '\u0222abc.'));
17+
assert.equal(Buffer.byteLength(path.basename(utf8)),
18+
Buffer.byteLength('\u0222abc.XXXXXX'));
19+
assert(common.fileExists(utf8));
20+
21+
fs.mkdtemp(
22+
path.join(common.tmpDir, 'bar.'),
23+
common.mustCall(function(err, folder) {
24+
assert.ifError(err);
25+
assert(common.fileExists(folder));
26+
})
27+
);

0 commit comments

Comments
 (0)