Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
isaacs committed Jun 9, 2012
1 parent 6332a4c commit 424bca1
Showing 1 changed file with 44 additions and 11 deletions.
55 changes: 44 additions & 11 deletions lib/fs.js
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
}
}

Expand Down Expand Up @@ -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);
}

Expand All @@ -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);
});
});
}
Expand Down

0 comments on commit 424bca1

Please sign in to comment.