Skip to content

Commit 2269d7d

Browse files
raltMylesBorins
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>
1 parent 5824522 commit 2269d7d

File tree

4 files changed

+98
-0
lines changed

4 files changed

+98
-0
lines changed

doc/api/fs.md

+24
Original file line numberDiff line numberDiff line change
@@ -851,6 +851,30 @@ added: v0.1.21
851851

852852
Synchronous mkdir(2). Returns `undefined`.
853853

854+
## fs.mkdtemp(prefix, callback)
855+
856+
Creates a unique temporary directory.
857+
858+
Generates six random characters to be appended behind a required
859+
`prefix` to create a unique temporary directory.
860+
861+
The created folder path is passed as a string to the callback's second
862+
parameter.
863+
864+
Example:
865+
866+
```js
867+
fs.mkdtemp('/tmp/foo-', (err, folder) => {
868+
console.log(folder);
869+
// Prints: /tmp/foo-itXde2
870+
});
871+
```
872+
873+
## fs.mkdtempSync(template)
874+
875+
The synchronous version of [`fs.mkdtemp()`][]. Returns the created
876+
folder path.
877+
854878
## fs.open(path, flags[, mode], callback)
855879
<!-- YAML
856880
added: v0.0.2

lib/fs.js

+21
Original file line numberDiff line numberDiff line change
@@ -1990,3 +1990,24 @@ SyncWriteStream.prototype.destroy = function() {
19901990
};
19911991

19921992
SyncWriteStream.prototype.destroySoon = SyncWriteStream.prototype.destroy;
1993+
1994+
fs.mkdtemp = function(prefix, callback) {
1995+
if (typeof callback !== 'function') {
1996+
throw new TypeError('"callback" argument must be a function');
1997+
}
1998+
1999+
if (!nullCheck(prefix, callback)) {
2000+
return;
2001+
}
2002+
2003+
var req = new FSReqWrap();
2004+
req.oncomplete = callback;
2005+
2006+
binding.mkdtemp(prefix + 'XXXXXX', req);
2007+
};
2008+
2009+
fs.mkdtempSync = function(prefix) {
2010+
nullCheck(prefix);
2011+
2012+
return binding.mkdtemp(prefix + 'XXXXXX');
2013+
};

src/node_file.cc

+26
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));
@@ -1264,6 +1269,25 @@ static void FUTimes(const FunctionCallbackInfo<Value>& args) {
12641269
}
12651270
}
12661271

1272+
static void Mkdtemp(const FunctionCallbackInfo<Value>& args) {
1273+
Environment* env = Environment::GetCurrent(args);
1274+
1275+
if (args.Length() < 1)
1276+
return TYPE_ERROR("template is required");
1277+
if (!args[0]->IsString())
1278+
return TYPE_ERROR("template must be a string");
1279+
1280+
node::Utf8Value tmpl(env->isolate(), args[0]);
1281+
1282+
if (args[1]->IsObject()) {
1283+
ASYNC_CALL(mkdtemp, args[1], *tmpl);
1284+
} else {
1285+
SYNC_CALL(mkdtemp, *tmpl, *tmpl);
1286+
args.GetReturnValue().Set(String::NewFromUtf8(env->isolate(),
1287+
SYNC_REQ.path));
1288+
}
1289+
}
1290+
12671291
void FSInitialize(const FunctionCallbackInfo<Value>& args) {
12681292
Local<Function> stats_constructor = args[0].As<Function>();
12691293
CHECK(stats_constructor->IsFunction());
@@ -1317,6 +1341,8 @@ void InitFs(Local<Object> target,
13171341
env->SetMethod(target, "utimes", UTimes);
13181342
env->SetMethod(target, "futimes", FUTimes);
13191343

1344+
env->SetMethod(target, "mkdtemp", Mkdtemp);
1345+
13201346
StatWatcher::Initialize(env, target);
13211347

13221348
// Create FunctionTemplate for FSReqWrap

test/parallel/test-fs-mkdtemp.js

+27
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)