From 131a67e7efa2c3010578d9f5fc06ac6f0529af76 Mon Sep 17 00:00:00 2001 From: isaacs Date: Sat, 9 Jun 2012 00:33:25 -0700 Subject: [PATCH] Fix #3394 fs.realpath: Properly cache symlink targets --- lib/fs.js | 16 ++++++++-------- test/simple/test-fs-realpath.js | 34 +++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/lib/fs.js b/lib/fs.js index f0cd903cbc4..65df0be35f1 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -962,21 +962,21 @@ fs.realpathSync = function realpathSync(p, cache) { // read the link if it wasn't read before // dev/ino always return 0 on windows, so skip the check. - var linkTarget; + var linkTarget = null; if (!isWindows) { var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); - if (seenLinks[id]) { + if (seenLinks.hasOwnProperty(id)) { linkTarget = seenLinks[id]; } } - if (!linkTarget) { + if (linkTarget === null) { fs.statSync(base); linkTarget = fs.readlinkSync(base); - resolvedLink = pathModule.resolve(previous, linkTarget); - // track this, if given a cache. - if (cache) cache[base] = resolvedLink; - if (!isWindows) seenLinks[id] = linkTarget; } + resolvedLink = pathModule.resolve(previous, linkTarget); + // track this, if given a cache. + if (cache) cache[base] = resolvedLink; + if (!isWindows) seenLinks[id] = linkTarget; } // resolve the link, then start over @@ -1071,7 +1071,7 @@ fs.realpath = function realpath(p, cache, cb) { // dev/ino always return 0 on windows, so skip the check. if (!isWindows) { var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); - if (seenLinks[id]) { + if (seenLinks.hasOwnProperty(id)) { return gotTarget(null, seenLinks[id], base); } } diff --git a/test/simple/test-fs-realpath.js b/test/simple/test-fs-realpath.js index b2c8e9b0109..8741aac69cc 100644 --- a/test/simple/test-fs-realpath.js +++ b/test/simple/test-fs-realpath.js @@ -349,6 +349,40 @@ var uponeActual = fs.realpathSync('..'); assert.equal(upone, uponeActual, 'realpathSync("..") expected: ' + upone + ' actual:' + uponeActual); + +// going up with .. multiple times +// . +// `-- a/ +// |-- b/ +// | `-- e -> .. +// `-- d -> .. +// realpath(a/b/e/d/a/b/e/d/a) ==> a +function test_up_multiple(cb) { + fs.mkdirSync(common.tmpDir + '/a', 0755); + fs.mkdirSync(common.tmpDir + '/a/b', 0755); + fs.symlinkSync(common.tmpDir + '/a/d', '..'); + fs.symlinkSync(common.tmpDir + '/a/b/e', '..'); + + var abedabed = tmp('abedabed'.split('').join('/')); + var abedabeda_real = tmp(''); + + var abedabeda = tmp('abedabeda'.split('').join('/')); + var abedabeda_real = tmp('a'); + + assert.equal(fs.realpathSync(abedabeda), abedabeda_real); + assert.equal(fs.realpathSync(abedabed), abedabed_real); + fs.realpath(abedabeda, function (er, real) { + if (er) throw er; + assert.equal(abedabeda_real, real); + fs.realpath(abedabed, function (er, real) { + if (er) throw er; + assert.equal(abedabed_real, real); + cb(); + }); + }); +} + + // absolute symlinks with children. // . // `-- a/