mirror of https://github.com/nodejs/node.git
Fix fs.realpath to work on Windows
1. Make the isRoot check valid 2. Don't cache results based on dev/ino, since those are alwasy 0 on windows.pull/24503/head
parent
6332a4cf00
commit
424bca15c8
55
lib/fs.js
55
lib/fs.js
|
@ -897,6 +897,11 @@ var normalize = pathModule.normalize;
|
|||
// result is [base_with_slash, base], e.g. ['somedir/', 'somedir']
|
||||
var nextPartRe = /(.*?)(?:[\/]+|$)/g;
|
||||
|
||||
// Regex to split a windows path into three parts: [*, device, slash,
|
||||
// tail] windows-only
|
||||
var splitDeviceRe =
|
||||
/^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?([\\\/])?([\s\S]*?)$/;
|
||||
|
||||
fs.realpathSync = function realpathSync(p, cache) {
|
||||
// make p is absolute
|
||||
p = pathModule.resolve(p);
|
||||
|
@ -931,7 +936,15 @@ fs.realpathSync = function realpathSync(p, cache) {
|
|||
pos = nextPartRe.lastIndex;
|
||||
|
||||
// continue if not a symlink, or if root
|
||||
if (!base || knownHard[base] || (cache && cache[base] === base)) {
|
||||
var isRoot = !base;
|
||||
if (isWindows) {
|
||||
// if it doens't have a tail, then it's the root.
|
||||
var split = base.match(splitDeviceRe);
|
||||
if (split) {
|
||||
isRoot = !split[2];
|
||||
}
|
||||
}
|
||||
if (isRoot || knownHard[base] || (cache && cache[base] === base)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -948,13 +961,21 @@ fs.realpathSync = function realpathSync(p, cache) {
|
|||
}
|
||||
|
||||
// read the link if it wasn't read before
|
||||
var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
|
||||
if (!seenLinks[id]) {
|
||||
// dev/ino always return 0 on windows, so skip the check.
|
||||
var linkTarget;
|
||||
if (!isWindows) {
|
||||
var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
|
||||
if (seenLinks[id]) {
|
||||
linkTarget = seenLinks[id];
|
||||
}
|
||||
}
|
||||
if (!linkTarget) {
|
||||
fs.statSync(base);
|
||||
seenLinks[id] = fs.readlinkSync(base);
|
||||
resolvedLink = pathModule.resolve(previous, seenLinks[id]);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1014,8 +1035,16 @@ fs.realpath = function realpath(p, cache, cb) {
|
|||
base = previous + result[1];
|
||||
pos = nextPartRe.lastIndex;
|
||||
|
||||
// continue if known to be hard or if root or in cache already.
|
||||
if (!base || knownHard[base] || (cache && cache[base] === base)) {
|
||||
// continue if not a symlink, or if root
|
||||
var isRoot = !base;
|
||||
if (isWindows) {
|
||||
// if it doens't have a tail, then it's the root.
|
||||
var split = base.match(splitDeviceRe);
|
||||
if (split) {
|
||||
isRoot = !split[2];
|
||||
}
|
||||
}
|
||||
if (isRoot || knownHard[base] || (cache && cache[base] === base)) {
|
||||
return process.nextTick(LOOP);
|
||||
}
|
||||
|
||||
|
@ -1039,15 +1068,19 @@ fs.realpath = function realpath(p, cache, cb) {
|
|||
|
||||
// stat & read the link if not read before
|
||||
// call gotTarget as soon as the link target is known
|
||||
var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
|
||||
if (seenLinks[id]) {
|
||||
return gotTarget(null, seenLinks[id], base);
|
||||
// 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]) {
|
||||
return gotTarget(null, seenLinks[id], base);
|
||||
}
|
||||
}
|
||||
fs.stat(base, function(err) {
|
||||
if (err) return cb(err);
|
||||
|
||||
fs.readlink(base, function(err, target) {
|
||||
gotTarget(err, seenLinks[id] = target);
|
||||
if (!isWindows) seenLinks[id] = target;
|
||||
gotTarget(err, target);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue