Skip to content
This repository
Browse code

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...
commit 424bca15c8e227a9170cfe00f9ba7d9daae6fb03 1 parent 6332a4c
Isaac Z. Schlueter isaacs authored

Showing 1 changed file with 44 additions and 11 deletions. Show diff stats Hide diff stats

  1. +44 11 lib/fs.js
55 lib/fs.js
@@ -897,6 +897,11 @@ var normalize = pathModule.normalize;
897 897 // result is [base_with_slash, base], e.g. ['somedir/', 'somedir']
898 898 var nextPartRe = /(.*?)(?:[\/]+|$)/g;
899 899
  900 +// Regex to split a windows path into three parts: [*, device, slash,
  901 +// tail] windows-only
  902 +var splitDeviceRe =
  903 + /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?([\\\/])?([\s\S]*?)$/;
  904 +
900 905 fs.realpathSync = function realpathSync(p, cache) {
901 906 // make p is absolute
902 907 p = pathModule.resolve(p);
@@ -931,7 +936,15 @@ fs.realpathSync = function realpathSync(p, cache) {
931 936 pos = nextPartRe.lastIndex;
932 937
933 938 // continue if not a symlink, or if root
934   - if (!base || knownHard[base] || (cache && cache[base] === base)) {
  939 + var isRoot = !base;
  940 + if (isWindows) {
  941 + // if it doens't have a tail, then it's the root.
  942 + var split = base.match(splitDeviceRe);
  943 + if (split) {
  944 + isRoot = !split[2];
  945 + }
  946 + }
  947 + if (isRoot || knownHard[base] || (cache && cache[base] === base)) {
935 948 continue;
936 949 }
937 950
@@ -948,13 +961,21 @@ fs.realpathSync = function realpathSync(p, cache) {
948 961 }
949 962
950 963 // read the link if it wasn't read before
951   - var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
952   - if (!seenLinks[id]) {
  964 + // dev/ino always return 0 on windows, so skip the check.
  965 + var linkTarget;
  966 + if (!isWindows) {
  967 + var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
  968 + if (seenLinks[id]) {
  969 + linkTarget = seenLinks[id];
  970 + }
  971 + }
  972 + if (!linkTarget) {
953 973 fs.statSync(base);
954   - seenLinks[id] = fs.readlinkSync(base);
955   - resolvedLink = pathModule.resolve(previous, seenLinks[id]);
  974 + linkTarget = fs.readlinkSync(base);
  975 + resolvedLink = pathModule.resolve(previous, linkTarget);
956 976 // track this, if given a cache.
957 977 if (cache) cache[base] = resolvedLink;
  978 + if (!isWindows) seenLinks[id] = linkTarget;
958 979 }
959 980 }
960 981
@@ -1014,8 +1035,16 @@ fs.realpath = function realpath(p, cache, cb) {
1014 1035 base = previous + result[1];
1015 1036 pos = nextPartRe.lastIndex;
1016 1037
1017   - // continue if known to be hard or if root or in cache already.
1018   - if (!base || knownHard[base] || (cache && cache[base] === base)) {
  1038 + // continue if not a symlink, or if root
  1039 + var isRoot = !base;
  1040 + if (isWindows) {
  1041 + // if it doens't have a tail, then it's the root.
  1042 + var split = base.match(splitDeviceRe);
  1043 + if (split) {
  1044 + isRoot = !split[2];
  1045 + }
  1046 + }
  1047 + if (isRoot || knownHard[base] || (cache && cache[base] === base)) {
1019 1048 return process.nextTick(LOOP);
1020 1049 }
1021 1050
@@ -1039,15 +1068,19 @@ fs.realpath = function realpath(p, cache, cb) {
1039 1068
1040 1069 // stat & read the link if not read before
1041 1070 // call gotTarget as soon as the link target is known
1042   - var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
1043   - if (seenLinks[id]) {
1044   - return gotTarget(null, seenLinks[id], base);
  1071 + // dev/ino always return 0 on windows, so skip the check.
  1072 + if (!isWindows) {
  1073 + var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
  1074 + if (seenLinks[id]) {
  1075 + return gotTarget(null, seenLinks[id], base);
  1076 + }
1045 1077 }
1046 1078 fs.stat(base, function(err) {
1047 1079 if (err) return cb(err);
1048 1080
1049 1081 fs.readlink(base, function(err, target) {
1050   - gotTarget(err, seenLinks[id] = target);
  1082 + if (!isWindows) seenLinks[id] = target;
  1083 + gotTarget(err, target);
1051 1084 });
1052 1085 });
1053 1086 }

0 comments on commit 424bca1

Please sign in to comment.
Something went wrong with that request. Please try again.