diff --git a/README.md b/README.md
index 1e98cee..6c1d046 100644
--- a/README.md
+++ b/README.md
@@ -329,6 +329,7 @@ var fs = new Filer.FileSystem();
* [fs.rmdir(path, callback)](#rmdir)
* [fs.mkdir(path, [mode], callback)](#mkdir)
* [fs.access(path, [mode], callback)](#access)
+* [fs.mkdtemp(path, [options], callback)](#mkdtemp)
* [fs.readdir(path, callback)](#readdir)
* [fs.close(fd, callback)](#close)
* [fs.open(path, flags, [mode], callback)](#open)
@@ -731,6 +732,26 @@ fs.access(file, fs.constants.F_OK, function(err) {
});
```
+#### fs.mkdtemp(prefix, options, callback)
+
+Makes a temporary directory with prefix supplied in `path` argument. Method will append six random characters directly to the prefix. Asynchronous. Callback gets `(error, path)`, where path is the path to the created directory.
+
+NOTE: Filer allows for, but ignores the optional `options` argument used in node.js.
+
+Example:
+
+```javascript
+// Create tmp directory with prefix foo
+fs.mkdtemp("/foo-", function (error, path) {
+ // A new folder foo-xxxxxx will be created. Path contains a path to created folder.
+});
+
+fs.mkdtemp("/myDir/tmp", function (error, path) {
+ // Will create a new folder tmpxxxxxx inside myDir directory.
+ // Will throw error if myDir does not exist
+});
+```
+
#### fs.readdir(path, callback)
Reads the contents of a directory. Asynchronous [readdir(3)](http://pubs.opengroup.org/onlinepubs/009695399/functions/readdir.html).
diff --git a/src/filesystem/implementation.js b/src/filesystem/implementation.js
index dc70c8f..586656c 100644
--- a/src/filesystem/implementation.js
+++ b/src/filesystem/implementation.js
@@ -4,6 +4,7 @@ var dirname = Path.dirname;
var basename = Path.basename;
var isAbsolutePath = Path.isAbsolute;
var isNullPath = Path.isNull;
+var shared = require('../shared.js');
var Constants = require('../constants.js');
var NODE_TYPE_FILE = Constants.NODE_TYPE_FILE;
@@ -1693,6 +1694,21 @@ function access(fs, context, path, mode, callback) {
access_file(context, path, mode, callback);
}
+function mkdtemp(fs, context, prefix, options, callback) {
+ callback = arguments[arguments.length - 1];
+ if(!prefix) {
+ return callback(new Error('filename prefix is required'));
+ }
+
+ let random = shared.randomChars(6);
+ var path = prefix + '-' + random;
+
+ if(!pathCheck(path, callback)) return;
+ make_directory(context, path, function(error) {
+ callback(error, path);
+ });
+}
+
function rmdir(fs, context, path, callback) {
if(!pathCheck(path, callback)) return;
remove_directory(context, path, callback);
@@ -2428,6 +2444,7 @@ module.exports = {
close: close,
mknod: mknod,
mkdir: mkdir,
+ mkdtemp: mkdtemp,
rmdir: rmdir,
unlink: unlink,
stat: stat,
diff --git a/src/filesystem/interface.js b/src/filesystem/interface.js
index bd21b9a..a1a0030 100644
--- a/src/filesystem/interface.js
+++ b/src/filesystem/interface.js
@@ -279,6 +279,7 @@ function FileSystem(options, callback) {
{ name: 'close' },
{ name: 'mknod', promises: true },
{ name: 'mkdir', promises: true },
+ { name: 'mkdtemp', promises: true },
{ name: 'rmdir', promises: true },
{ name: 'stat', promises: true },
{ name: 'fstat' },
diff --git a/src/shared.js b/src/shared.js
index 5c3337b..e595420 100644
--- a/src/shared.js
+++ b/src/shared.js
@@ -1,13 +1,27 @@
-function guid() {
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+function generateRandom(template) {
+ return template.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
- }).toUpperCase();
+ });
+}
+
+function guid() {
+ return generateRandom('xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx').toUpperCase();
+}
+
+/**
+ * Generate a string of n random characters. Defaults to n=6.
+ */
+function randomChars(n) {
+ n = n || 6;
+ var template = 'x'.repeat(n);
+ return generateRandom(template);
}
function nop() {}
module.exports = {
guid: guid,
- nop: nop
+ nop: nop,
+ randomChars: randomChars
};
diff --git a/tests/index.js b/tests/index.js
index 1bf41a4..a459aa1 100644
--- a/tests/index.js
+++ b/tests/index.js
@@ -16,6 +16,7 @@ require('./spec/fs.lstat.spec');
require('./spec/fs.exists.spec');
require('./spec/fs.mknod.spec');
require('./spec/fs.mkdir.spec');
+require('./spec/fs.mkdtemp.spec');
require('./spec/fs.readdir.spec');
require('./spec/fs.rmdir.spec');
require('./spec/fs.open.spec');
diff --git a/tests/spec/fs.mkdtemp.spec.js b/tests/spec/fs.mkdtemp.spec.js
new file mode 100644
index 0000000..3527e6d
--- /dev/null
+++ b/tests/spec/fs.mkdtemp.spec.js
@@ -0,0 +1,52 @@
+var util = require('../lib/test-utils.js');
+var expect = require('chai').expect;
+
+describe('fs.mkdtemp', function() {
+ beforeEach(util.setup);
+ afterEach(util.cleanup);
+
+ it('should be a function', function() {
+ var fs = util.fs();
+ expect(fs.mkdtemp).to.be.a('function');
+ });
+
+ it('should craete temp dir with specified prefix', function(done) {
+ var fs = util.fs();
+ fs.mkdtemp('/foo', function(error, path) {
+ expect(error).not.to.exist;
+ expect(path).to.match(/foo-\w{6}/);
+ done();
+ });
+ });
+
+ it('should craete temp dir inside existing directory', function(done) {
+ var fs = util.fs();
+ fs.mkdir('/myDir', (error) => {
+ expect(error).not.to.exist;
+ fs.mkdtemp('/myDir/foo', function(error, path) {
+ expect(error).not.to.exist;
+ expect(path).to.match(/foo.{6}/);
+ done();
+ });
+ });
+ });
+
+ it('should not create temp dir without prefix', function(done) {
+ var fs = util.fs();
+ fs.mkdtemp('', function(error, path) {
+ expect(error).to.exist;
+ expect(path).not.to.exist;
+ done();
+ });
+ });
+
+ it('should not create temp dir inside non existing dir', function(done) {
+ var fs = util.fs();
+ fs.mkdtemp('/doesNotExists/foo', function(error, path) {
+ expect(error).to.exist;
+ expect(error.code).to.be.equal('ENOENT');
+ expect(path).to.exist;
+ done();
+ });
+ });
+});
\ No newline at end of file