Giter Club home page Giter Club logo

node-tmp's Introduction

Tmp

A simple temporary file and directory creator for node.js.

Build Status Dependencies npm version API documented Known Vulnerabilities

About

This is a widely used library to create temporary files and directories in a node.js environment.

Tmp offers both an asynchronous and a synchronous API. For all API calls, all the parameters are optional. There also exists a promisified version of the API, see tmp-promise.

Tmp uses crypto for determining random file names, or, when using templates, a six letter random identifier. And just in case that you do not have that much entropy left on your system, Tmp will fall back to pseudo random numbers.

You can set whether you want to remove the temporary file on process exit or not.

If you do not want to store your temporary directories and files in the standard OS temporary directory, then you are free to override that as well.

An Important Note on Previously Undocumented Breaking Changes

All breaking changes that had been introduced, i.e.

  • tmpdir must be located under the system defined tmpdir root.
  • Spaces being collapsed into single spaces
  • Removal of all single and double quote characters

have been reverted in v0.2.2 and tmp should now behave as it did before the introduction of these breaking changes.

Other breaking changes, i.e.

  • template must be relative to tmpdir
  • name must be relative to tmpdir
  • dir option must be relative to tmpdir

are still in place.

In order to override the system's tmpdir, you will have to use the newly introduced tmpdir option.

An Important Note on Compatibility

See the CHANGELOG for more information.

Version 0.2.3

  • Node version <= 14.4 has been dropped.
  • rimraf has been dropped from the dependencies

Version 0.2.2

Since version 0.2.2, all support for node version <= 14 has been dropped.

Version 0.1.0

Since version 0.1.0, all support for node versions < 0.10.0 has been dropped.

Most importantly, any support for earlier versions of node-tmp was also dropped.

If you still require node versions < 0.10.0, then you must limit your node-tmp dependency to versions below 0.1.0.

Version 0.0.33

Since version 0.0.33, all support for node versions < 0.8 has been dropped.

If you still require node version 0.8, then you must limit your node-tmp dependency to version 0.0.33.

For node versions < 0.8 you must limit your node-tmp dependency to versions < 0.0.33.

How to install

npm install tmp

Usage

Please also check API docs.

Graceful cleanup

If graceful cleanup is set, tmp will remove all controlled temporary objects on process exit, otherwise the temporary objects will remain in place, waiting to be cleaned up on system restart or otherwise scheduled temporary object removal.

To enforce this, you can call the setGracefulCleanup() method:

const tmp = require('tmp');

tmp.setGracefulCleanup();

Asynchronous file creation

Simple temporary file creation, the file will be closed and unlinked on process exit.

const tmp = require('tmp');

tmp.file(function _tempFileCreated(err, path, fd, cleanupCallback) {
  if (err) throw err;

  console.log('File: ', path);
  console.log('Filedescriptor: ', fd);
  
  // If we don't need the file anymore we could manually call the cleanupCallback
  // But that is not necessary if we didn't pass the keep option because the library
  // will clean after itself.
  cleanupCallback();
});

Synchronous file creation

A synchronous version of the above.

const tmp = require('tmp');

const tmpobj = tmp.fileSync();
console.log('File: ', tmpobj.name);
console.log('Filedescriptor: ', tmpobj.fd);
  
// If we don't need the file anymore we could manually call the removeCallback
// But that is not necessary if we didn't pass the keep option because the library
// will clean after itself.
tmpobj.removeCallback();

Note that this might throw an exception if either the maximum limit of retries for creating a temporary name fails, or, in case that you do not have the permission to write to the directory where the temporary file should be created in.

Asynchronous directory creation

Simple temporary directory creation, it will be removed on process exit.

If the directory still contains items on process exit, then it won't be removed.

const tmp = require('tmp');

tmp.dir(function _tempDirCreated(err, path, cleanupCallback) {
  if (err) throw err;

  console.log('Dir: ', path);
  
  // Manual cleanup
  cleanupCallback();
});

If you want to cleanup the directory even when there are entries in it, then you can pass the unsafeCleanup option when creating it.

Synchronous directory creation

A synchronous version of the above.

const tmp = require('tmp');

const tmpobj = tmp.dirSync();
console.log('Dir: ', tmpobj.name);
// Manual cleanup
tmpobj.removeCallback();

Note that this might throw an exception if either the maximum limit of retries for creating a temporary name fails, or, in case that you do not have the permission to write to the directory where the temporary directory should be created in.

Asynchronous filename generation

It is possible with this library to generate a unique filename in the specified directory.

const tmp = require('tmp');

tmp.tmpName(function _tempNameGenerated(err, path) {
    if (err) throw err;

    console.log('Created temporary filename: ', path);
});

Synchronous filename generation

A synchronous version of the above.

const tmp = require('tmp');

const name = tmp.tmpNameSync();
console.log('Created temporary filename: ', name);

Advanced usage

Asynchronous file creation

Creates a file with mode 0644, prefix will be prefix- and postfix will be .txt.

const tmp = require('tmp');

tmp.file({ mode: 0o644, prefix: 'prefix-', postfix: '.txt' }, function _tempFileCreated(err, path, fd) {
  if (err) throw err;

  console.log('File: ', path);
  console.log('Filedescriptor: ', fd);
});

Synchronous file creation

A synchronous version of the above.

const tmp = require('tmp');

const tmpobj = tmp.fileSync({ mode: 0o644, prefix: 'prefix-', postfix: '.txt' });
console.log('File: ', tmpobj.name);
console.log('Filedescriptor: ', tmpobj.fd);

Controlling the Descriptor

As a side effect of creating a unique file tmp gets a file descriptor that is returned to the user as the fd parameter. The descriptor may be used by the application and is closed when the removeCallback is invoked.

In some use cases the application does not need the descriptor, needs to close it without removing the file, or needs to remove the file without closing the descriptor. Two options control how the descriptor is managed:

  • discardDescriptor - if true causes tmp to close the descriptor after the file is created. In this case the fd parameter is undefined.
  • detachDescriptor - if true causes tmp to return the descriptor in the fd parameter, but it is the application's responsibility to close it when it is no longer needed.
const tmp = require('tmp');

tmp.file({ discardDescriptor: true }, function _tempFileCreated(err, path, fd, cleanupCallback) {
  if (err) throw err;
  // fd will be undefined, allowing application to use fs.createReadStream(path)
  // without holding an unused descriptor open.
});
const tmp = require('tmp');

tmp.file({ detachDescriptor: true }, function _tempFileCreated(err, path, fd, cleanupCallback) {
  if (err) throw err;

  cleanupCallback();
  // Application can store data through fd here; the space used will automatically
  // be reclaimed by the operating system when the descriptor is closed or program
  // terminates.
});

Asynchronous directory creation

Creates a directory with mode 0755, prefix will be myTmpDir_.

const tmp = require('tmp');

tmp.dir({ mode: 0o750, prefix: 'myTmpDir_' }, function _tempDirCreated(err, path) {
  if (err) throw err;

  console.log('Dir: ', path);
});

Synchronous directory creation

Again, a synchronous version of the above.

const tmp = require('tmp');

const tmpobj = tmp.dirSync({ mode: 0750, prefix: 'myTmpDir_' });
console.log('Dir: ', tmpobj.name);

mkstemp like, asynchronously

Creates a new temporary directory with mode 0700 and filename like /tmp/tmp-nk2J1u.

IMPORTANT NOTE: template no longer accepts a path. Use the dir option instead if you require tmp to create your temporary filesystem object in a different place than the default tmp.tmpdir.

const tmp = require('tmp');

tmp.dir({ template: 'tmp-XXXXXX' }, function _tempDirCreated(err, path) {
  if (err) throw err;

  console.log('Dir: ', path);
});

mkstemp like, synchronously

This will behave similarly to the asynchronous version.

const tmp = require('tmp');

const tmpobj = tmp.dirSync({ template: 'tmp-XXXXXX' });
console.log('Dir: ', tmpobj.name);

Asynchronous filename generation

Using tmpName() you can create temporary file names asynchronously. The function accepts all standard options, e.g. prefix, postfix, dir, and so on.

You can also leave out the options altogether and just call the function with a callback as first parameter.

const tmp = require('tmp');

const options = {};

tmp.tmpName(options, function _tempNameGenerated(err, path) {
    if (err) throw err;

    console.log('Created temporary filename: ', path);
});

Synchronous filename generation

The tmpNameSync() function works similarly to tmpName(). Again, you can leave out the options altogether and just invoke the function without any parameters.

const tmp = require('tmp');
const options = {};
const tmpname = tmp.tmpNameSync(options);
console.log('Created temporary filename: ', tmpname);

Options

All options are optional :)

  • name: a fixed name that overrides random name generation, the name must be relative and must not contain path segments
  • mode: the file mode to create with, falls back to 0o600 on file creation and 0o700 on directory creation
  • prefix: the optional prefix, defaults to tmp
  • postfix: the optional postfix
  • template: mkstemp like filename template, no default, must include XXXXXX once for random name generation, e.g. 'foo-bar-XXXXXX'.
  • dir: the optional temporary directory that must be relative to the system's default temporary directory. absolute paths are fine as long as they point to a location under the system's default temporary directory. Any directories along the so specified path must exist, otherwise a ENOENT error will be thrown upon access, as tmp will not check the availability of the path, nor will it establish the requested path for you.
  • tmpdir: allows you to override the system's root tmp directory
  • tries: how many times should the function try to get a unique filename before giving up, default 3
  • keep: signals that the temporary file or directory should not be deleted on exit, default is false
    • In order to clean up, you will have to call the provided cleanupCallback function manually.
  • unsafeCleanup: recursively removes the created temporary directory, even when it's not empty. default is false
  • detachDescriptor: detaches the file descriptor, caller is responsible for closing the file, tmp will no longer try closing the file during garbage collection
  • discardDescriptor: discards the file descriptor (closes file, fd is -1), tmp will no longer try closing the file during garbage collection

node-tmp's People

Contributors

addaleax avatar amilajack avatar ari-h avatar binki avatar bmeck avatar dnicolson avatar foxel avatar gcampax avatar gutte avatar joliss avatar joscha avatar jtknox91 avatar kerimdzhanov avatar kevinoid avatar lightsofapollo avatar madnight avatar matsev avatar mbargiel avatar mcollina avatar olliv avatar pabigot avatar pdehaan avatar poppinlp avatar raszi avatar scottweinstein avatar shime avatar silkentrance avatar vhain avatar voltrevo avatar wibblymat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

node-tmp's Issues

License inconsistency

Package.json states that the package is licensed under MIT license, but the header in the lib/tmp.js file tells that the code is under GPLv2.

Could you set a single license for all the code?

ENOENT error in Appveyor NodeJS v0.10.39

I'm getting the following issue, only on v0.10.39 under Windows in a module that uses tmp in a test suite:

> [email protected] prepublish C:\projects\resin-image-manager
> gulp build

[15:47:40] Requiring external module coffee-script/register
[15:47:40] Using gulpfile C:\projects\resin-image-manager\gulpfile.coffee
[15:47:40] Starting 'lint'...
[15:47:41] Starting 'test'...
[15:47:41] Starting 'coffee'...
๏ฟฝ[2J๏ฟฝ[1;3H[15:47:42] 'test' errored after 1.22 s
[15:47:42] Error in plugin 'gulp-mocha'
Message:
    ENOENT, open 'C:\Users\appveyor\AppData\Local\Temp\1\tmp-2156tKPc2tEDYtRU.tmp'
Details:
    errno: 34
    code: ENOENT
    path: C:\Users\appveyor\AppData\Local\Temp\1\tmp-2156tKPc2tEDYtRU.tmp
    domainEmitter: [object Object]
    domain: [object Object]
    domainThrown: false
Stack:
Error: ENOENT, open 'C:\Users\appveyor\AppData\Local\Temp\1\tmp-2156tKPc2tEDYtRU.tmp'



  22 passing (360ms)

[15:47:42] Finished 'coffee' after 1.51 s
[15:47:42] Finished 'lint' after 1.56 s

npm ERR! [email protected] prepublish: `gulp build`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] prepublish script.
npm ERR! This is most likely a problem with the resin-image-manager package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     gulp build
npm ERR! You can get their info via:
npm ERR!     npm owner ls resin-image-manager
npm ERR! There is likely additional logging output above.
npm ERR! System Windows_NT 6.2.9200
npm ERR! command "C:\\Program Files (x86)\\nodejs\\\\node.exe" "C:\\Program Files (x86)\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install"
npm ERR! cwd C:\projects\resin-image-manager
npm ERR! node -v v0.10.39
npm ERR! npm -v 1.4.28
npm ERR! code ELIFECYCLE
Command exited with code 1

Notice that the test suite passes (22 passing (360ms)), however the ENOENT error prevents npm to consider it a success.

The error is being thrown in Appveyor CI (http://www.appveyor.com), however I've been unable to reproduce in a Windows 8 PC with the exact same NodeJS version.

The build works on Appveyor in version 0.11 and 0.12.

Luckily, Appveyor build histories seem to be publicly available, so you can more closely inspect the logs here: https://ci.appveyor.com/project/jviotti/resin-image-manager.

If you want to try to reproduce, run the test suite of the following module: https://github.com/resin-io/resin-image-manager.

The error message doesn't say much, so not sure if I should be asking the Appveyor support team instead.

_rmdirRecursiveSync as a user level function

It would be nice if I could call "_rmdirRecursiveSync(myTempDir)" in some cases by myself instead of a call at exit. My program does not exit over many days, but create temp dirs, which are importend only for some seconds.

...Rolf

Allow alt fs libraries

I'd like to be able to use node-tmp with alt fs libraries. In my case I want it for s3fs which allows me to access Amazon S3 as if it were a local disk.

Can we add this?

unneeded dependency

tmp.js does require('os') but then never uses it. (Since it's been replaced with theos-tmpdir` ponyfill.) Can we drop that line?

create withTmpName that automatically cleans up after callback

I would like to have another version of tmpName that automatically cleans up the temporary file (if created) after the callback completes. It would prevent temporary files from building up during long running processes and could look something like this:

function withTmpName(options, callback) {
  var
    args = _parseArguments(options, callback),
    opts = args[0],
    cb = args[1];

  return _getTmpName(opts, function (error, name) {
    try {
      cb(error, name);
    }
    finally {
      child_process.execFile('rm', ['--recursive', '--force', name]);
    }
  });
}

I was going to create a pull request but couldn't figure out how to test this properly using Vows.

proposed enhancement: nofd option

Would you be interested in a patch that adds an option nofd which, if present, avoids opening a file descriptor corresponding to the created temporary file? The corresponding fd parameter in the callback would then be undefined.

The use case I have in mind is where the name will be used in an API like fs.createReadStream() where the pre-opened descriptor consumes system resources for no value. Looking at the tmp.js code I don't believe I can just fs.close(fd) and continue to use the name, because at the point cleanupCallback() is invoked the original fd will be closed even if it's no longer associated with the temporary file.

tmp.file have responsibility to close file, not only unlink file

If we do like below:

tmp.file(function(err, path, fd, cleanupCallback) {
  doSomethingWithPath(path, function(err) {
    !cleanupCallback || cleanupCallback();
  });
});

tmp.file use fs.open to create file, which requires fs.close to be called later, but it is not documented.

If not, iNode will not be deleted and below circumstance may occur even if we execute cleanupCallback() clearly:
screen shot 2014-08-29 at 2 36 28 pm
(deleted) iNode hell

_garbageCollector leaks if keep is false

_removeObjects never gets cleaned up if you call a cleanup function. it only ever gets appended to, this causes leaks for long lived processes that create many temporary file/dirs. when cleanup functions are called they should remove their temp file from _removedObjects.

the workaround right now is to always set keep:true and assume you are doing cleanup yourself

Uncaught errors are "absorbed"

In you recent commits, you removed the re-throw of errors. This is not desirable since errors are absorbed, causing the process to not die when an exception occurs.

Reproducible in node 0.8.x.

Garbage collection doesn't remove all objects

Test code to reproduce the problem:

const tmp = require('tmp');

tmp.fileSync({ dir: './', postfix: '.1' });
tmp.fileSync({ dir: './', postfix: '.2' });
tmp.fileSync({ dir: './', postfix: '.3' });
tmp.fileSync({ dir: './', postfix: '.4' });
tmp.fileSync({ dir: './', postfix: '.5' });
tmp.fileSync({ dir: './', postfix: '.6' });

Running that code leaves files with postfixes 1, 3, and 5 unremoved.

The problem in the code is that _garbageCollector loops through _removeObjects array, but at the same time calls to _cleanupCallback modify (splice) the array. As a result some of the _removeObjects functions will get removed before they have been called. (And _garbageCollector tries to invoke call for unexisting array indexes, but because of the empty catch block that is ignored.)

cleanup should accept a callback for composition

right now cleanup is a synchronous function which cannot wrap a callback, this means you need to wrap any node convention callbacks like so:

// fs.writeFile...
function onFileWrite(err) {
  cleanup();
  return cb.apply(this, arguments);
}

or just a simple way to avoid having this liter code.

Running inside Electron

Hello,

I am using this module, but running it from Electron's (v0.36.7) renderer process throws:

Uncaught TypeError: existsSync is not a function

I have made little hackfix, but is there a way to somehow shadow default fs module with require('remote').require('fs')?

jacob-faber@04f2d1d

Cleaning up tmp directory throws an error

The error is

Error: ENOTEMPTY: directory not empty, rmdir '/tmp/tmp-96377PyPfMXvxq0t'

and it's pretty obvious what it's complaining about. I wrote to the temporary directory and now it doesn't want to clean it up because something is inside. In rm terms, I should use -f.

The problem I have with this is that there's probably always something inside this temporary directory. Shouldn't the library clean this up regardless?

Test suite failure

I'd like to send a minor fix for something, but the test suite isn't passing for me on master. I'm using Node v4.1.2 on Ubuntu 14.04.

$ npm test

> [email protected] test /home/ubuntu/src/node-tmp
> vows test/*-test.js

ยทยทยทยทยทยทยทยทยทยทยทยทยทโœ—โœ—โœ—ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทโœ—โœ—โœ—โœ—ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท


    when using name
      โœ— should return with a name
      Error: Could not get a unique tmp filename, max tries reached
      at _getTmpNameSync (/home/ubuntu/src/node-tmp/lib/tmp.js:198:9)
      at Object._createTmpDirSync [as dirSync] (/home/ubuntu/src/node-tmp/lib/tmp.js:328:14)
      at Object.vows.describe.addBatch.when using name.topic (/home/ubuntu/src/node-tmp/test/dir-sync-test.js:68:18)
      at run (/home/ubuntu/src/node-tmp/node_modules/vows/lib/vows/suite.js:134:35)
      at EventEmitter.<anonymous> (/home/ubuntu/src/node-tmp/node_modules/vows/lib/vows/suite.js:234:40)
      at emitOne (events.js:82:20)
      at EventEmitter.emit (events.js:169:7)
      at EventEmitter.options.Emitter.emit (/home/ubuntu/src/node-tmp/node_modules/vows/lib/vows.js:237:24)
      at /home/ubuntu/src/node-tmp/node_modules/vows/lib/vows/suite.js:169:45
      at doNTCallback0 (node.js:408:9)

      โœ— should have the provided name
      Error: Could not get a unique tmp filename, max tries reached
      at _getTmpNameSync (/home/ubuntu/src/node-tmp/lib/tmp.js:198:9)
      at Object._createTmpDirSync [as dirSync] (/home/ubuntu/src/node-tmp/lib/tmp.js:328:14)
      at Object.vows.describe.addBatch.when using name.topic (/home/ubuntu/src/node-tmp/test/dir-sync-test.js:68:18)
      at run (/home/ubuntu/src/node-tmp/node_modules/vows/lib/vows/suite.js:134:35)
      at EventEmitter.<anonymous> (/home/ubuntu/src/node-tmp/node_modules/vows/lib/vows/suite.js:234:40)
      at emitOne (events.js:82:20)
      at EventEmitter.emit (events.js:169:7)
      at EventEmitter.options.Emitter.emit (/home/ubuntu/src/node-tmp/node_modules/vows/lib/vows.js:237:24)
      at /home/ubuntu/src/node-tmp/node_modules/vows/lib/vows/suite.js:169:45
      at doNTCallback0 (node.js:408:9)

      โœ— should be a directory
        ยป should exist // dir-sync-test.js:15

      โœ— should not return with an error
        ยป expected null, got { stack: 'Error: Could not get a unique tmp filename, max tries reached /tmp/using-name\n    at _pathExists (/home/ubuntu/src/node-tmp/lib/tmp.js:164:19)\n    at FSReqWrap.cb [as oncomplete] (fs.js:212:19)', message: 'Could not get a unique tmp filename, max tries reached /tmp/using-name' } // vows.js:132

      โœ— should return with a name
        ยป expected undefined to be a String // base.js:90

      โœ— should be a directory
        ยป should exist // dir-test.js:15

      โœ— should have the provided name
        ยป should have the provided name // base.js:104
  โœ— Errored ยป 202 honored โˆ™ 5 broken โˆ™ 2 errored (0.625s)
  npm ERR! Test failed.  See above for more details.
$ npm ls
[email protected] /home/ubuntu/src/node-tmp
โ”œโ”€โ”€ [email protected]
โ””โ”€โ”ฌ [email protected]
  โ”œโ”€โ”€ [email protected]
  โ””โ”€โ”€ [email protected]

Is there anything I can do to debug this further?

Update Readme

The latest merges, namely the one that introduced crypto in replacement of Math.random, might be worth mentioning in the readme, don't you think?

Please publish 0.0.29

We got hit by a crash in production today.

> /usr/local/delivery-service/.tmp/nar-delivery-service-v2.8.1-bin-1473056064807/node_modules/tmp/lib/tmp.js:355
>       if (e.errno != -_c.EBADF && e.errno != -c.ENOENT) {
>                                               ^
> 
> ReferenceError: c is not defined

The fix for it was done in 058fe4c however there hasn't been a release since it was fixed. I understand you don't want to do a 1.0.0 (#75), but perhaps you could release a 0.0.29 with the current code?

Choose a Better Name

tmp is not a very good module name.

The Problem

Node Modules come with a lot of junk files, such as "changelog.md", ".travis.yml", etc. When a project has a lot of modules (say, Bower, for example), it becomes necessary to clean up this junk. Otherwise, we commit hundreds or thousands of junk files to our repos and end up distributing them in our final products.

Of course, we automate the cleanup process. We write a script and give it a list of all the files and folders to delete. You know what's junk in every other module? A folder named tmp. You know what every basic cleanup script is going to delete? Your entire module.

_createTmpDir(...) erroneous configuration for the remove callback

While working on a synchronous API for this, I stumbled over this bugger...

In here, you call upon _prepareRemoveCallback without providing a proper remove function as the first parameter causing it to subsequently fail to actually remove the temporary folder.

308       var removeCallback = _prepareRemoveCallback(
309         opts.unsafeCleanup
310           ? _rmdirRecursiveSync
311           : fs.rmdirSync.bind(fs),
312         name
313       );

Would it not be more correct to call it like so

308       var removeCallback = _prepareRemoveCallback(function () {
309         opts.unsafeCleanup
310           ? _rmdirRecursiveSync(name)
311           : fs.rmdirSync(name)},
312         name
313       );

I could prepare a PR if you will.

using temp file with gm module

tmp.js:260
throw err;
^
Error: spawn ENOENT
at errnoException (child_process.js:980:11)
at Process.ChildProcess._handle.onexit (child_process.js:771:34)

EventEmitter memory leak error

 Building(node) warning: possible EventEmitter memory leak detected. 11 exit listeners added. Use emitter.setMaxListeners() to increase limit.
Trace
    at process.addListener (events.js:239:17)
    at Object.<anonymous> (/Users/me/myproject/node_modules/ember-cli-babel/node_modules/broccoli-babel-transpiler/node_modules/broccoli-merge-trees/node_modules/can-symlink/node_modules/tmp/lib/tmp.js:449:9)
    at Module._compile (module.js:409:26)
    at Object.Module._extensions..js (module.js:416:10)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Module.require (module.js:353:17)
    at require (internal/module.js:12:17)
    at Object.<anonymous> (/Users/me/myproject/node_modules/ember-cli-babel/node_modules/broccoli-babel-transpiler/node_modules/broccoli-merge-trees/node_modules/can-symlink/index.js:1:73)
    at Module._compile (module.js:409:26)

Seems like it's returned as an error, not just a warning, which it's mean't to be.
Using node 4.4.5.

_rmdirRecursiveSync Race condition on windows

_rmdirRecursiveSync causes a race condition in windows (nodejs domains) that causes:

{ message: 'ENOTEMPTY, directory not empty 'C:\Users\ec2-user\AppData\Local\Temp\2\tmp-2068nvmg128'',
stack: 'Error: ENOTEMPTY, directory not empty 'C:\Users\ec2-user\AppData\Local\Temp\2\tmp-2068nvmg128'\n
at Object.fs.rmdirSync (fs.js:624:18)\n at _rmdirRecursiveSync (C:\Users\ec2-user\cps-mailin\node_modules\tmp
\lib\tmp.js:201:6)\n at C:\Users\ec2-user\cps-mailin\node_modules\tmp\lib\tmp.js:218:5\n at C:\Users\ec2
-user\cps-mailin\lib\cps-rene.js:155:24\n at Object.cmdTypes.AdjustXmlImport (C:\Users\ec2-user\cps-mailin\lib
\cps-rene.js:17:1)\n at C:\Users\ec2-user\cps-mailin\lib\cps-rene.js:154:28\n at C:\Users\ec2-user\cps-ma
ilin\node_modules\async\lib\async.js:254:17\n at done (C:\Users\ec2-user\cps-mailin\node_modules\async\lib
\async.js:135:19)\n at C:\Users\ec2-user\cps-mailin\node_modules\async\lib\async.js:32:16\n at C:\Users\e
c2-user\cps-mailin\node_modules\async\lib\async.js:251:21' } }

strict mode fail: Octal literals are not allowed

please fix.

zixia:~/workspace (master) $ node --use-strict node_modules/tmp/lib/tmp.js                        
/home/ubuntu/workspace/node_modules/tmp/lib/tmp.js:167
    fs.open(name, _c.O_CREAT | _c.O_EXCL | _c.O_RDWR, opts.mode || 0600, function _fileCreated(err, fd) {
                                                                   ^^^^
SyntaxError: Octal literals are not allowed in strict mode.

there also another 0700.

change to this would fix:

parseInt('0600', 8)

Function like `tmp.open` to create write stream.

tmp.file has some nice advantages (implicit mode and exclusive) but code using the file descriptor from fs.open is rare nowadays.

An alternate version that would return a stream made with fs.createWriteStream would be nice.

Latest release breaks Bower

Hi there!

The line in question is: 1bc5c91#diff-4f99eaef47493ba13b06879592d2a1c4R251

This change appears to have broken Bower :). This is happening on my local machine AND on my Travis build - so it's not just a single-system issue. Here are the details:

  1. Update bower to the latest (to get 0.24 of this library)
  2. The bug doesn't appear on all bower deps, but here is a list you can use to recreate:
{
  "dependencies": {
    "font-awesome": "~4.0.3",
    "bootstrap-sass-official": "~3.1.1",
    "bootstrap": "~3.1.1",
    "jquery.smooth-scroll": "~1.4.13"
  }
}
  1. The error you will receive is: Arguments to path.join must be strings from GitHubResolver.js line 54 in Bower.

  2. The issue actually comes from here: https://github.com/bower/bower/blob/master/lib/core/resolvers/Resolver.js#L165

The call to tmp.dir causes dir on the next then to be an array, whereas it used to be a string. Ultimately, this causes this._tempDir to be an array, which blows up in GitHubResolver (again, seemingly only for some deps, perhaps because only some use GitHubResolver.

I'm not a node expert, so I apologize if anything is unclear or just plain wrong. But I can confirm that removing the third argument here un-breaks bower.

Thanks!

export garbageCollector for times when gracefulCleanup doesn't fire

It might be helpful to note that setGracefulCleanup does not always mean files will be cleaned up. For example if the user hits control-c the cleanup code won't run.

I'm seeing other cases that will cause graceful cleanup to not happen. My tmp directory has hundreds of these tmp-generated directories. I haven't figured out why they are left behind. Maybe something to do with running from Grunt and a task fails?

option to avoid random characters and pid in path

Sometimes it's best to have a predictable temp file path.

For example Bower is currently creating new temp directories every time a package is requested, even if it already downloaded the exact same package earlier in the same process.

Creating multiple directories in a tmp dir causes cleanup to fail

To reproduce:

var tmp = require('tmp');
var fs = require('fs');

tmp.dir({ template: '/tmp/tmp-XXXXXX', unsafeCleanup: true }, function _tempDirCreated(err, path) {
  if (err) {
    throw err;
  }
  fs.mkdirSync(path + '/child1');
  fs.mkdirSync(path + '/child2');
});

It appears that the order that the directories are pushed on to the removal queue are unordered so when the top-level tmp directory is removed, child1/child2 directories still remain in the "to be removed" queue.

The tmp dir will not be cleaned up as there is an uncaught exception thrown when fs.rmdirSync(dir) tries to remove the directories that no longer exists.

Synchronous interface

I wonder if there was any need for a synchronous interface to node-tmp. I for my part definitely want such an interface ๐Ÿ˜„

Please see the follow up PR for an initial stab at such an alternate interface that introduces synchronous versions of the existing API calls.

The PR still has some unresolved issues (failing tests, name clashes), but before continuing implementing the required test cases I wanted to know whether the API and its implementation is something you would like to have in node-tmp.

cleanup does not seem to be working.

So I have the following script:

#!/usr/bin/env node

const path = require('path');
const tmp = require('tmp');
const yargs = require('yargs').argv;
const ghpages = require('gh-pages');

//tmp.setGracefulCleanup();

tmp.dir({unsafeCleanup: true, template: '../tmp-XXXXXX'}, function _tempDirCreated(err, tmpDir, cleanupCallback) {

  if (err) throw err;

  console.log(tmpDir, process.cwd(), yargs.directory, yargs.branch);

  ghpages.publish(path.join(process.cwd(), yargs.directory), {
    branch: yargs.branch,
    clone: tmpDir 
  }, err => {
    if(err) console.log(err);
  });  

  cleanupCallback();
});

Which works but the ../tmp-XXXXX is not being removed? Have tried both unsafeCleanup: true and tmp.setGracefulCleanup(); neither seems to work.

Cheers.

Octal literals are not allowed in strict mode.

I'm using tmp in a karma test file, and the inclusion of 'use strict;' at the top of the file is causing me to get this error:
Uncaught SyntaxError: Octal literals are not allowed in strict mode.

The backtrace sends me to the line where I create the tempfile:

tmp.file({ mode: 0644, prefix: 'prefix-', postfix: '.pdf' }, function _tempFileCreated(err, path, fd) {

Does tmp use octal literals? If so, can I avoid them somehow?

Please export _getTmpName

Hello there,

I am currently working on a module for node.js that runs an external process - this external process needs to get passed a file name to store its results in (until I read them from there and delete that file).
Currently I am using require('tmp').tmpdir and generate the file name myself, but your _getTmpName method does exactly this, so I would love to reuse it. Would it be possible to include it in the exports?

Cheers,
Joscha

Uncaught exception

I noticed that node-tmp is not cleaning the temporary directories if node dies on an uncaught exception.
This could be fixed with:

process.on('uncaughtException', function (err) {
  // Cleanup here
  throw err;
});

Any reasons for not doing so?

Tmp files left open after clean up

Hello!

I wrote small test:

exports.test = function(req, res) {
    tmp.file(function(err, path, fd, cleanupCb) {
        if (!err) {
            console.log("tmp file: " + path);
            cleanupCb();
        } else
            console.error(err); 
        res.send(200);
    });
}

After several HTTP requests I run lsof | grep pgrep node`` and see this:

node 11001 root 14u REG 252,0 0 1048588 /tmp/tmp-11001edg7x80.tmp (deleted)
node 11001 root 15u REG 252,0 0 1048589 /tmp/tmp-11001op2r768.tmp (deleted)
node 11001 root 16u REG 252,0 0 1048590 /tmp/tmp-110013qclg7k.tmp (deleted)
node 11001 root 17u REG 252,0 0 1048591 /tmp/tmp-110011t9lx5c.tmp (deleted)
node 11001 root 18u REG 252,0 0 1048592 /tmp/tmp-11001lrluw8g.tmp (deleted)
node 11001 root 19u REG 252,0 0 1048593 /tmp/tmp-110015f9wkow.tmp (deleted)
node 11001 root 20u REG 252,0 0 1048594 /tmp/tmp-11001sswb6gg.tmp (deleted)
node 11001 root 21u REG 252,0 0 1048595 /tmp/tmp-11001irf0scg.tmp (deleted)
node 11001 root 22u REG 252,0 0 1048596 /tmp/tmp-11001lqrm9zk.tmp (deleted)
node 11001 root 23u REG 252,0 0 1048597 /tmp/tmp-11001n0bgvfk.tmp (deleted)

All temp files deleted, but open by node process. It looks like bug, but probably it is behavior expected.

PS If I additionally call fs.close(fd) everything is ok.

Thank you.

Promises

Hi,

Can we add an option to use promises instead of callbacks given its incorporation into ES6?

Thanks,
Marc

Cleanup fails

When I use the default parameters, and then call the cleanup callback when I'm done, I get the following error:

  1)  "after all" hook:
     Error: ENOTEMPTY, directory not empty 'C:\Users\Oliver\AppData\Local\Temp\tmp-17520mURkNFVU7XQ6'
      at Object.fs.rmdirSync (fs.js:624:18)
      at C:\Users\Oliver\prj\cli\test\prepare.js:39:3
      at Array.forEach (native)
      at Context.<anonymous> (C:\Users\Oliver\prj\cli\test\prepare.js:38:13)

I'm copying temporary files to that directory, so this wasn't surprising. I then set unsafeCleanup to true and now I get this result:

  1)  "after all" hook:
     Error: ENOENT, no such file or directory 'C:\Users\Oliver\AppData\Local\Temp\tmp-396iEctJyHwBoYu\corePath'
      at Object.fs.readdirSync (fs.js:666:18)
      at C:\Users\Oliver\prj\cli\test\prepare.js:39:3
      at Array.forEach (native)
      at Context.<anonymous> (C:\Users\Oliver\prj\cli\test\prepare.js:38:13)

The weirdest part is, the temporary directory is actually deleted just fine.

Duplicate delete in `_rmdirRecursiveSync`

The iterative solution to _rmdirRecursiveSync introduced a bug:

function _rmdirRecursiveSync(root) {
  var dirs = [root];

  do {
    var
      dir = dirs.pop(),
      canRemove = true,
      files = fs.readdirSync(dir);

    for (var i = 0, length = files.length; i < length; i++) {
      var
        file = path.join(dir, files[i]),
        stat = fs.lstatSync(file); // lstat so we don't recurse into symlinked directories

      if (stat.isDirectory()) {                                                                                                                      
        canRemove = false;

        // ------ Added Commentary ------
        // Re-adding the directory here so it is deleted later. However, we keep doing
        // this for every sub-directory. This ultimately leads to a duplicate delete and
        // fs throws an exception.
        dirs.push(dir);

        dirs.push(file);
      } else {
        fs.unlinkSync(file);
      }  
    }  

    if (canRemove) {
      fs.rmdirSync(dir);
    }  
  } while (dirs.length !== 0);
}

You can see this happen with the following structure:

$ find removeDir
removeDir
removeDir/bar
removeDir/bar/baz.txt
removeDir/foo
removeDir/foo/baz.txt

To see this happen with minimal effort, I placed _rmdirRecursiveSync in a standalone script:

'use strict';                                                                                                                                        

var fs = require('fs');
var path = require('path');

function _rmdirRecursiveSync(root) {
  var dirs = [root];

  do {
    var
      dir = dirs.pop(),
      canRemove = true,
      files = fs.readdirSync(dir);

    for (var i = 0, length = files.length; i < length; i++) {
      var
        file = path.join(dir, files[i]),
        stat = fs.lstatSync(file); // lstat so we don't recurse into symlinked directories

      if (stat.isDirectory()) {
        canRemove = false;
        dirs.push(dir);
        dirs.push(file);
      } else {
        fs.unlinkSync(file);
      }  
    }  

    if (canRemove) {
      fs.rmdirSync(dir);
    }  
  } while (dirs.length !== 0);
}

_rmdirRecursiveSync('./removeDir');

Which for me (OSX Yosemite, node 0.12.2) results in this error:

fs.js:761
  return binding.readdir(pathModule._makeLong(path));
                 ^
Error: ENOENT, no such file or directory 'removeDir/bar'
    at Error (native)
    at Object.fs.readdirSync (fs.js:761:18)
    at _rmdirRecursiveSync (/Users/andrew/workspaces/repo-checker/tmpRmdirIssue/broken/script.js:13:18)
    at Object.<anonymous> (/Users/andrew/workspaces/repo-checker/tmpRmdirIssue/broken/script.js:35:1)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)
    at startup (node.js:129:16)

This can be avoided with a check that makes sure that the directory is re-added only once. Here is an equivalent script:

'use strict';                                                                                                                                        

var fs = require('fs');
var path = require('path');

function _rmdirRecursiveSync(root) {
  var dirs = [root];

  do {
    var
      dir = dirs.pop(),
      deferred = false,
      files = fs.readdirSync(dir);

    for (var i = 0, length = files.length; i < length; i++) {
      var
        file = path.join(dir, files[i]),
        stat = fs.lstatSync(file); // lstat so we don't recurse into symlinked directories

      if (stat.isDirectory()) {
        if (!deferred) {
          deferred = true;
          dirs.push(dir);
        }  
        dirs.push(file);
      } else {
        fs.unlinkSync(file);
      }  
    }  

    if (!deferred) {
      fs.rmdirSync(dir);
    }  
  } while (dirs.length !== 0);
}

_rmdirRecursiveSync('./removeDir');

I don't really understand how the original recursive solution was blowing the stack. Shouldn't the recursion have only been as deep as the directory structure? To blow the stack you'd need a crazy deep directory structure and that's probably the real issue.

In any case, I'll submit a PR to make this iterative fix.

removeCallback can close descriptor belonging to another file system operation

This bug motivated the enhancement proposed in issue #88, which I've now taken the time to confirm.

Because the removeCallback() captures the descriptor opened when the tmpFile was created, any operation that closes that descriptor while not removing the tmpFile releases the descriptor for use in other operations. When the original tmpFile is removed the descriptor is closed even though it now belongs to another activity.

This behavior makes the fd parameter extremely dangerous to use.

The example program below demonstrates the problem.

'use strict';

const tmp = require('tmp');
const fs = require('fs');

tmp.file((err, name1, fd1, removeCallback1) => {
  console.log(`file1 ${name1} descriptor ${fd1}`);
  fs.close(fd1, err => {
    console.log(`closed ${fd1}`);
    tmp.file((err, name2, fd2, removeCallback2) => {
      console.log(`file2 ${name2} descriptor ${fd2}`);
      fs.fstat(fd2, (err, stat) => {
        if (err) {
          return console.log('fd2 bad to begin', err);
        }
        console.log('fd2 is valid');
        removeCallback1();
        console.log('removed tmp1');
        fs.fstat(fd2, (err, stat) => {
          if (err) {
            return console.log('fd2 is broken', err);
          }
          console.log('fd2 ok', stat);
        });
      });
    });
  });
})

Output on my system:

file1 /tmp/tmp-32363NIXdmdAsP1uJ.tmp descriptor 9
closed 9
file2 /tmp/tmp-3236365hcFJMjvC6c.tmp descriptor 9
fd2 is valid
removed tmp1
fd2 is broken { [Error: EBADF: bad file descriptor, fstat] errno: -9, code: 'EBADF', syscall: 'fstat' }

errno constants aren't properly defined in node 6

node-tmp uses the internal 'constants' module to define error codes, such as EBADF and ENOENT which should be caught during cleanup. In node 6, error codes have been removed from the 'constants' module.

So, in node 6:

> process.binding('constants').EBADF
undefined
> process.binding('constants').ENOENT
undefined
> process.binding('constants').os.errno.EBADF
9
> process.binding('constants').os.errno.ENOENT
2

in node 4:

> process.binding('constants').EBADF                                                                                                                                                                                                                                                            
9                                                                                                                                                                                                                                                                                       
> process.binding('constants').ENOENT                                                                                                                                                                                                                                                           
2   
> process.binding('constants').os
undefined
> process.binding('constants').os
undefined

It seems that _c.ENOENT should be replaced by _c.os.errno.ENOENT etc. in node 6.

And _c = require('constants') should be replaced by _c = process.binding('constants')... not really sure why the two aren't equal.

Alternately, constants can be generated from require('os').constants.errno and require('fs').constants in node 6.

Although using process.binding isn't recommended (see nodejs/node#2768 etc.), I'm using it for compatibility between node 4 and 6

Please publish a 1.0.0

I think this has reached 1.0.0-worthy.

The current 0.0.x versioning is also a slight PITA because npm install --save tmp will save an exact version, rather than using the user's designated semver prefix e.g. ~ or ^.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.