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(); | ||
|  |   } | ||
|  | }; |