Skip to content

Commit

Permalink
Stop unsymlinking destinations that are symlinks
Browse files Browse the repository at this point in the history
Fixes: #5
  • Loading branch information
iarna committed Jan 6, 2017
1 parent 629265c commit f90c7dd
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 0 deletions.
10 changes: 10 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ module.exports = function writeFile (filename, data, options, callback) {
options = null
}
if (!options) options = {}
fs.realpath(filename, function (_, realname) {
_writeFile(realname || filename, data, options, callback)
})
}
function _writeFile (filename, data, options, callback) {
var tmpfile = getTmpname(filename)

if (options.mode && options.chown) {
Expand Down Expand Up @@ -51,6 +56,11 @@ module.exports = function writeFile (filename, data, options, callback) {

module.exports.sync = function writeFileSync (filename, data, options) {
if (!options) options = {}
try {
filename = fs.realpathSync(filename)
} catch (ex) {
// it's ok, it'll happen on a not yet existing file
}
var tmpfile = getTmpname(filename)

try {
Expand Down
6 changes: 6 additions & 0 deletions test/basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ var test = require('tap').test
var requireInject = require('require-inject')
var writeFileAtomic = requireInject('../index', {
'graceful-fs': {
realpath: function (filename, cb) {
return cb(null, filename)
},
writeFile: function (tmpfile, data, options, cb) {
if (/nowrite/.test(tmpfile)) return cb(new Error('ENOWRITE'))
cb()
Expand All @@ -27,6 +30,9 @@ var writeFileAtomic = requireInject('../index', {
if (/nostat/.test(tmpfile)) return cb(new Error('ENOSTAT'))
cb()
},
realpathSync: function (filename, cb) {
return filename
},
writeFileSync: function (tmpfile, data, options) {
if (/nowrite/.test(tmpfile)) throw new Error('ENOWRITE')
},
Expand Down
26 changes: 26 additions & 0 deletions test/integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,20 @@ test('writes simple file (async)', function (t) {
})
})

test('writes to symlinks without clobbering (async)', function (t) {
t.plan(5)
var file = tmpFile()
var link = tmpFile()
fs.writeFileSync(file, '42')
fs.symlinkSync(file, link)
didWriteFileAtomic(t, currentUser(), link, '43', function (err) {
t.ifError(err, 'no error')
t.is(readFile(file), '43', 'target content ok')
t.is(readFile(link), '43', 'link content ok')
t.ok(fs.lstatSync(link).isSymbolicLink(), 'link is link')
})
})

test('runs chown on given file (async)', function (t) {
var file = tmpFile()
didWriteFileAtomic(t, {uid: 42, gid: 43}, file, '42', { chown: { uid: 42, gid: 43 } }, function (err) {
Expand Down Expand Up @@ -156,6 +170,18 @@ test('writes simple file (sync)', function (t) {
t.is(readFile(file), '42')
})

test('writes to symlinks without clobbering (sync)', function (t) {
t.plan(4)
var file = tmpFile()
var link = tmpFile()
fs.writeFileSync(file, '42')
fs.symlinkSync(file, link)
didWriteFileAtomicSync(t, currentUser(), link, '43')
t.is(readFile(file), '43', 'target content ok')
t.is(readFile(link), '43', 'link content ok')
t.ok(fs.lstatSync(link).isSymbolicLink(), 'link is link')
})

test('runs chown on given file (sync)', function (t) {
t.plan(1)
var file = tmpFile()
Expand Down

0 comments on commit f90c7dd

Please sign in to comment.