mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-11-04 03:17:00 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			302 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			302 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/* istanbul ignore file - tested in node */
 | 
						|
// 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();
 | 
						|
}
 | 
						|
 | 
						|
// 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();
 | 
						|
  }
 | 
						|
}; |