From 5f405498380105544d867f832288a89a6f219110 Mon Sep 17 00:00:00 2001 From: Florian MARGAINE Date: Wed, 24 Feb 2016 22:17:44 +0100 Subject: [PATCH 1/3] 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 --- lib/fs.js | 21 +++++++++++++++++++++ src/node_file.cc | 26 ++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/lib/fs.js b/lib/fs.js index 1fd40b9f4fcada..f73e5179eb7219 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -2138,3 +2138,24 @@ SyncWriteStream.prototype.destroy = function() { }; SyncWriteStream.prototype.destroySoon = SyncWriteStream.prototype.destroy; + +fs.mkdtemp = function(prefix, callback) { + if (typeof callback !== 'function') { + throw new TypeError('"callback" argument must be a function'); + } + + if (!nullCheck(prefix, callback)) { + return; + } + + var req = new FSReqWrap(); + req.oncomplete = callback; + + binding.mkdtemp(prefix + 'XXXXXX', req); +}; + +fs.mkdtempSync = function(prefix) { + nullCheck(prefix); + + return binding.mkdtemp(prefix + 'XXXXXX'); +}; diff --git a/src/node_file.cc b/src/node_file.cc index 57e5168ab2c2b9..f51c29dd464a7d 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -200,6 +200,11 @@ static void After(uv_fs_t *req) { static_cast(req->ptr)); break; + case UV_FS_MKDTEMP: + argv[1] = String::NewFromUtf8(env->isolate(), + static_cast(req->path)); + break; + case UV_FS_READLINK: argv[1] = String::NewFromUtf8(env->isolate(), static_cast(req->ptr)); @@ -1291,6 +1296,25 @@ static void FUTimes(const FunctionCallbackInfo& args) { } } +static void Mkdtemp(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + + if (args.Length() < 1) + return TYPE_ERROR("template is required"); + if (!args[0]->IsString()) + return TYPE_ERROR("template must be a string"); + + node::Utf8Value tmpl(env->isolate(), args[0]); + + if (args[1]->IsObject()) { + ASYNC_CALL(mkdtemp, args[1], *tmpl); + } else { + SYNC_CALL(mkdtemp, *tmpl, *tmpl); + args.GetReturnValue().Set(String::NewFromUtf8(env->isolate(), + SYNC_REQ.path)); + } +} + void FSInitialize(const FunctionCallbackInfo& args) { Local stats_constructor = args[0].As(); CHECK(stats_constructor->IsFunction()); @@ -1344,6 +1368,8 @@ void InitFs(Local target, env->SetMethod(target, "utimes", UTimes); env->SetMethod(target, "futimes", FUTimes); + env->SetMethod(target, "mkdtemp", Mkdtemp); + StatWatcher::Initialize(env, target); // Create FunctionTemplate for FSReqWrap From 2acd5984bbf19677dc17d413cd1e551fcaf381fa Mon Sep 17 00:00:00 2001 From: Florian MARGAINE Date: Wed, 24 Feb 2016 22:19:33 +0100 Subject: [PATCH 2/3] doc: add fs.mkdtemp() and fs.mkdtempSync() --- doc/api/fs.markdown | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/doc/api/fs.markdown b/doc/api/fs.markdown index 0740fda91b110b..8ae4dbf309f5d0 100644 --- a/doc/api/fs.markdown +++ b/doc/api/fs.markdown @@ -522,6 +522,30 @@ to the completion callback. `mode` defaults to `0o777`. Synchronous mkdir(2). Returns `undefined`. +## fs.mkdtemp(prefix, callback) + +Creates a unique temporary directory. + +Generates six random characters to be appended behind a required +`prefix` to create a unique temporary directory. + +The created folder path is passed as a string to the callback's second +parameter. + +Example: + +```js +fs.mkdtemp('/tmp/foo-', (err, folder) => { + console.log(folder); + // Prints: /tmp/foo-itXde2 +}); +``` + +## fs.mkdtempSync(template) + +The synchronous version of [`fs.mkdtemp()`][]. Returns the created +folder path. + ## fs.open(path, flags[, mode], callback) Asynchronous file open. See open(2). `flags` can be: From d56a3df5a80d4ae1d47921f495773cae8d679de7 Mon Sep 17 00:00:00 2001 From: Florian MARGAINE Date: Wed, 24 Feb 2016 22:19:47 +0100 Subject: [PATCH 3/3] test: add fs.mkdtemp() and fs.mkdtempSync() tests --- test/parallel/test-fs-mkdtemp.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 test/parallel/test-fs-mkdtemp.js diff --git a/test/parallel/test-fs-mkdtemp.js b/test/parallel/test-fs-mkdtemp.js new file mode 100644 index 00000000000000..ad8a6cb46e02eb --- /dev/null +++ b/test/parallel/test-fs-mkdtemp.js @@ -0,0 +1,27 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const fs = require('fs'); +const path = require('path'); +const Buffer = require('buffer').Buffer; + +common.refreshTmpDir(); + +const tmpFolder = fs.mkdtempSync(path.join(common.tmpDir, 'foo.')); + +assert(path.basename(tmpFolder).length === 'foo.XXXXXX'.length); +assert(common.fileExists(tmpFolder)); + +const utf8 = fs.mkdtempSync(path.join(common.tmpDir, '\u0222abc.')); +assert.equal(Buffer.byteLength(path.basename(utf8)), + Buffer.byteLength('\u0222abc.XXXXXX')); +assert(common.fileExists(utf8)); + +fs.mkdtemp( + path.join(common.tmpDir, 'bar.'), + common.mustCall(function(err, folder) { + assert.ifError(err); + assert(common.fileExists(folder)); + }) +);