You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					304 lines
				
				8.3 KiB
			
		
		
			
		
	
	
					304 lines
				
				8.3 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								// Copyright Joyent, Inc. and other Node contributors.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Permission is hereby granted, free of charge, to any person obtaining a
							 | 
						||
| 
								 | 
							
								// copy of this software and associated documentation files (the
							 | 
						||
| 
								 | 
							
								// "Software"), to deal in the Software without restriction, including
							 | 
						||
| 
								 | 
							
								// without limitation the rights to use, copy, modify, merge, publish,
							 | 
						||
| 
								 | 
							
								// distribute, sublicense, and/or sell copies of the Software, and to permit
							 | 
						||
| 
								 | 
							
								// persons to whom the Software is furnished to do so, subject to the
							 | 
						||
| 
								 | 
							
								// following conditions:
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// The above copyright notice and this permission notice shall be included
							 | 
						||
| 
								 | 
							
								// in all copies or substantial portions of the Software.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
							 | 
						||
| 
								 | 
							
								// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
							 | 
						||
| 
								 | 
							
								// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
							 | 
						||
| 
								 | 
							
								// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
							 | 
						||
| 
								 | 
							
								// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
							 | 
						||
| 
								 | 
							
								// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
							 | 
						||
| 
								 | 
							
								// USE OR OTHER DEALINGS IN THE SOFTWARE.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var pathModule = require('path');
							 | 
						||
| 
								 | 
							
								var isWindows = process.platform === 'win32';
							 | 
						||
| 
								 | 
							
								var fs = require('fs');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// JavaScript implementation of realpath, ported from node pre-v6
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function rethrow() {
							 | 
						||
| 
								 | 
							
								  // Only enable in debug mode. A backtrace uses ~1000 bytes of heap space and
							 | 
						||
| 
								 | 
							
								  // is fairly slow to generate.
							 | 
						||
| 
								 | 
							
								  var callback;
							 | 
						||
| 
								 | 
							
								  if (DEBUG) {
							 | 
						||
| 
								 | 
							
								    var backtrace = new Error;
							 | 
						||
| 
								 | 
							
								    callback = debugCallback;
							 | 
						||
| 
								 | 
							
								  } else
							 | 
						||
| 
								 | 
							
								    callback = missingCallback;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return callback;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function debugCallback(err) {
							 | 
						||
| 
								 | 
							
								    if (err) {
							 | 
						||
| 
								 | 
							
								      backtrace.message = err.message;
							 | 
						||
| 
								 | 
							
								      err = backtrace;
							 | 
						||
| 
								 | 
							
								      missingCallback(err);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function missingCallback(err) {
							 | 
						||
| 
								 | 
							
								    if (err) {
							 | 
						||
| 
								 | 
							
								      if (process.throwDeprecation)
							 | 
						||
| 
								 | 
							
								        throw err;  // Forgot a callback but don't know where? Use NODE_DEBUG=fs
							 | 
						||
| 
								 | 
							
								      else if (!process.noDeprecation) {
							 | 
						||
| 
								 | 
							
								        var msg = 'fs: missing callback ' + (err.stack || err.message);
							 | 
						||
| 
								 | 
							
								        if (process.traceDeprecation)
							 | 
						||
| 
								 | 
							
								          console.trace(msg);
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								          console.error(msg);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function maybeCallback(cb) {
							 | 
						||
| 
								 | 
							
								  return typeof cb === 'function' ? cb : rethrow();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var normalize = pathModule.normalize;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Regexp that finds the next partion of a (partial) path
							 | 
						||
| 
								 | 
							
								// result is [base_with_slash, base], e.g. ['somedir/', 'somedir']
							 | 
						||
| 
								 | 
							
								if (isWindows) {
							 | 
						||
| 
								 | 
							
								  var nextPartRe = /(.*?)(?:[\/\\]+|$)/g;
							 | 
						||
| 
								 | 
							
								} else {
							 | 
						||
| 
								 | 
							
								  var nextPartRe = /(.*?)(?:[\/]+|$)/g;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Regex to find the device root, including trailing slash. E.g. 'c:\\'.
							 | 
						||
| 
								 | 
							
								if (isWindows) {
							 | 
						||
| 
								 | 
							
								  var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/;
							 | 
						||
| 
								 | 
							
								} else {
							 | 
						||
| 
								 | 
							
								  var splitRootRe = /^[\/]*/;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								exports.realpathSync = function realpathSync(p, cache) {
							 | 
						||
| 
								 | 
							
								  // make p is absolute
							 | 
						||
| 
								 | 
							
								  p = pathModule.resolve(p);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
							 | 
						||
| 
								 | 
							
								    return cache[p];
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  var original = p,
							 | 
						||
| 
								 | 
							
								      seenLinks = {},
							 | 
						||
| 
								 | 
							
								      knownHard = {};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // current character position in p
							 | 
						||
| 
								 | 
							
								  var pos;
							 | 
						||
| 
								 | 
							
								  // the partial path so far, including a trailing slash if any
							 | 
						||
| 
								 | 
							
								  var current;
							 | 
						||
| 
								 | 
							
								  // the partial path without a trailing slash (except when pointing at a root)
							 | 
						||
| 
								 | 
							
								  var base;
							 | 
						||
| 
								 | 
							
								  // the partial path scanned in the previous round, with slash
							 | 
						||
| 
								 | 
							
								  var previous;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  start();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function start() {
							 | 
						||
| 
								 | 
							
								    // Skip over roots
							 | 
						||
| 
								 | 
							
								    var m = splitRootRe.exec(p);
							 | 
						||
| 
								 | 
							
								    pos = m[0].length;
							 | 
						||
| 
								 | 
							
								    current = m[0];
							 | 
						||
| 
								 | 
							
								    base = m[0];
							 | 
						||
| 
								 | 
							
								    previous = '';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // On windows, check that the root exists. On unix there is no need.
							 | 
						||
| 
								 | 
							
								    if (isWindows && !knownHard[base]) {
							 | 
						||
| 
								 | 
							
								      fs.lstatSync(base);
							 | 
						||
| 
								 | 
							
								      knownHard[base] = true;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // walk down the path, swapping out linked pathparts for their real
							 | 
						||
| 
								 | 
							
								  // values
							 | 
						||
| 
								 | 
							
								  // NB: p.length changes.
							 | 
						||
| 
								 | 
							
								  while (pos < p.length) {
							 | 
						||
| 
								 | 
							
								    // find the next part
							 | 
						||
| 
								 | 
							
								    nextPartRe.lastIndex = pos;
							 | 
						||
| 
								 | 
							
								    var result = nextPartRe.exec(p);
							 | 
						||
| 
								 | 
							
								    previous = current;
							 | 
						||
| 
								 | 
							
								    current += result[0];
							 | 
						||
| 
								 | 
							
								    base = previous + result[1];
							 | 
						||
| 
								 | 
							
								    pos = nextPartRe.lastIndex;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // continue if not a symlink
							 | 
						||
| 
								 | 
							
								    if (knownHard[base] || (cache && cache[base] === base)) {
							 | 
						||
| 
								 | 
							
								      continue;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    var resolvedLink;
							 | 
						||
| 
								 | 
							
								    if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
							 | 
						||
| 
								 | 
							
								      // some known symbolic link.  no need to stat again.
							 | 
						||
| 
								 | 
							
								      resolvedLink = cache[base];
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      var stat = fs.lstatSync(base);
							 | 
						||
| 
								 | 
							
								      if (!stat.isSymbolicLink()) {
							 | 
						||
| 
								 | 
							
								        knownHard[base] = true;
							 | 
						||
| 
								 | 
							
								        if (cache) cache[base] = base;
							 | 
						||
| 
								 | 
							
								        continue;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // read the link if it wasn't read before
							 | 
						||
| 
								 | 
							
								      // dev/ino always return 0 on windows, so skip the check.
							 | 
						||
| 
								 | 
							
								      var linkTarget = null;
							 | 
						||
| 
								 | 
							
								      if (!isWindows) {
							 | 
						||
| 
								 | 
							
								        var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
							 | 
						||
| 
								 | 
							
								        if (seenLinks.hasOwnProperty(id)) {
							 | 
						||
| 
								 | 
							
								          linkTarget = seenLinks[id];
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      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;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // resolve the link, then start over
							 | 
						||
| 
								 | 
							
								    p = pathModule.resolve(resolvedLink, p.slice(pos));
							 | 
						||
| 
								 | 
							
								    start();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (cache) cache[original] = p;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return p;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								exports.realpath = function realpath(p, cache, cb) {
							 | 
						||
| 
								 | 
							
								  if (typeof cb !== 'function') {
							 | 
						||
| 
								 | 
							
								    cb = maybeCallback(cache);
							 | 
						||
| 
								 | 
							
								    cache = null;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // make p is absolute
							 | 
						||
| 
								 | 
							
								  p = pathModule.resolve(p);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
							 | 
						||
| 
								 | 
							
								    return process.nextTick(cb.bind(null, null, cache[p]));
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  var original = p,
							 | 
						||
| 
								 | 
							
								      seenLinks = {},
							 | 
						||
| 
								 | 
							
								      knownHard = {};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // current character position in p
							 | 
						||
| 
								 | 
							
								  var pos;
							 | 
						||
| 
								 | 
							
								  // the partial path so far, including a trailing slash if any
							 | 
						||
| 
								 | 
							
								  var current;
							 | 
						||
| 
								 | 
							
								  // the partial path without a trailing slash (except when pointing at a root)
							 | 
						||
| 
								 | 
							
								  var base;
							 | 
						||
| 
								 | 
							
								  // the partial path scanned in the previous round, with slash
							 | 
						||
| 
								 | 
							
								  var previous;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  start();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function start() {
							 | 
						||
| 
								 | 
							
								    // Skip over roots
							 | 
						||
| 
								 | 
							
								    var m = splitRootRe.exec(p);
							 | 
						||
| 
								 | 
							
								    pos = m[0].length;
							 | 
						||
| 
								 | 
							
								    current = m[0];
							 | 
						||
| 
								 | 
							
								    base = m[0];
							 | 
						||
| 
								 | 
							
								    previous = '';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // On windows, check that the root exists. On unix there is no need.
							 | 
						||
| 
								 | 
							
								    if (isWindows && !knownHard[base]) {
							 | 
						||
| 
								 | 
							
								      fs.lstat(base, function(err) {
							 | 
						||
| 
								 | 
							
								        if (err) return cb(err);
							 | 
						||
| 
								 | 
							
								        knownHard[base] = true;
							 | 
						||
| 
								 | 
							
								        LOOP();
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      process.nextTick(LOOP);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // walk down the path, swapping out linked pathparts for their real
							 | 
						||
| 
								 | 
							
								  // values
							 | 
						||
| 
								 | 
							
								  function LOOP() {
							 | 
						||
| 
								 | 
							
								    // stop if scanned past end of path
							 | 
						||
| 
								 | 
							
								    if (pos >= p.length) {
							 | 
						||
| 
								 | 
							
								      if (cache) cache[original] = p;
							 | 
						||
| 
								 | 
							
								      return cb(null, p);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // find the next part
							 | 
						||
| 
								 | 
							
								    nextPartRe.lastIndex = pos;
							 | 
						||
| 
								 | 
							
								    var result = nextPartRe.exec(p);
							 | 
						||
| 
								 | 
							
								    previous = current;
							 | 
						||
| 
								 | 
							
								    current += result[0];
							 | 
						||
| 
								 | 
							
								    base = previous + result[1];
							 | 
						||
| 
								 | 
							
								    pos = nextPartRe.lastIndex;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // continue if not a symlink
							 | 
						||
| 
								 | 
							
								    if (knownHard[base] || (cache && cache[base] === base)) {
							 | 
						||
| 
								 | 
							
								      return process.nextTick(LOOP);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
							 | 
						||
| 
								 | 
							
								      // known symbolic link.  no need to stat again.
							 | 
						||
| 
								 | 
							
								      return gotResolvedLink(cache[base]);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return fs.lstat(base, gotStat);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function gotStat(err, stat) {
							 | 
						||
| 
								 | 
							
								    if (err) return cb(err);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // if not a symlink, skip to the next path part
							 | 
						||
| 
								 | 
							
								    if (!stat.isSymbolicLink()) {
							 | 
						||
| 
								 | 
							
								      knownHard[base] = true;
							 | 
						||
| 
								 | 
							
								      if (cache) cache[base] = base;
							 | 
						||
| 
								 | 
							
								      return process.nextTick(LOOP);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // stat & read the link if not read before
							 | 
						||
| 
								 | 
							
								    // call gotTarget as soon as the link target is known
							 | 
						||
| 
								 | 
							
								    // 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.hasOwnProperty(id)) {
							 | 
						||
| 
								 | 
							
								        return gotTarget(null, seenLinks[id], base);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    fs.stat(base, function(err) {
							 | 
						||
| 
								 | 
							
								      if (err) return cb(err);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      fs.readlink(base, function(err, target) {
							 | 
						||
| 
								 | 
							
								        if (!isWindows) seenLinks[id] = target;
							 | 
						||
| 
								 | 
							
								        gotTarget(err, target);
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function gotTarget(err, target, base) {
							 | 
						||
| 
								 | 
							
								    if (err) return cb(err);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    var resolvedLink = pathModule.resolve(previous, target);
							 | 
						||
| 
								 | 
							
								    if (cache) cache[base] = resolvedLink;
							 | 
						||
| 
								 | 
							
								    gotResolvedLink(resolvedLink);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function gotResolvedLink(resolvedLink) {
							 | 
						||
| 
								 | 
							
								    // resolve the link, then start over
							 | 
						||
| 
								 | 
							
								    p = pathModule.resolve(resolvedLink, p.slice(pos));
							 | 
						||
| 
								 | 
							
								    start();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 |