|
|
@ -469,132 +469,119 @@ var path = require('path'); |
|
|
|
var normalize = path.normalize; |
|
|
|
var normalizeArray = path.normalizeArray; |
|
|
|
|
|
|
|
fs.realpathSync = function (path) { |
|
|
|
var seen_links = {}, knownHards = {}, buf, i = 0, part, x, stats; |
|
|
|
if (path.charAt(0) !== '/') { |
|
|
|
var cwd = process.cwd().split('/'); |
|
|
|
path = cwd.concat(path.split('/')); |
|
|
|
path = normalizeArray(path); |
|
|
|
i = cwd.length; |
|
|
|
buf = [].concat(cwd); |
|
|
|
} else { |
|
|
|
path = normalizeArray(path.split('/')); |
|
|
|
buf = ['']; |
|
|
|
} |
|
|
|
for (; i<path.length; i++) { |
|
|
|
part = path.slice(0, i+1).join('/'); |
|
|
|
if (part.length !== 0) { |
|
|
|
if (part in knownHards) { |
|
|
|
buf.push(path[i]); |
|
|
|
} else { |
|
|
|
stats = fs.lstatSync(part); |
|
|
|
if (stats.isSymbolicLink()) { |
|
|
|
x = stats.dev.toString(32)+":"+stats.ino.toString(32); |
|
|
|
if (x in seen_links) |
|
|
|
throw new Error("cyclic link at "+part); |
|
|
|
seen_links[x] = true; |
|
|
|
part = fs.readlinkSync(part); |
|
|
|
if (part.charAt(0) === '/') { |
|
|
|
// absolute
|
|
|
|
path = normalizeArray(part.split('/')); |
|
|
|
buf = ['']; |
|
|
|
i = 0; |
|
|
|
} else { |
|
|
|
// relative
|
|
|
|
Array.prototype.splice.apply(path, [i, 1].concat(part.split('/'))); |
|
|
|
part = normalizeArray(path); |
|
|
|
var y = 0, L = Math.max(path.length, part.length), delta; |
|
|
|
for (; y<L && path[y] === part[y]; y++); |
|
|
|
if (y !== L) { |
|
|
|
path = part; |
|
|
|
delta = i-y; |
|
|
|
i = y-1; |
|
|
|
if (delta > 0) buf.splice(y, delta); |
|
|
|
} else { |
|
|
|
i--; |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
buf.push(path[i]); |
|
|
|
knownHards[buf.join('/')] = true; |
|
|
|
} |
|
|
|
} |
|
|
|
// realpath
|
|
|
|
// Not using realpath(2) because it's bad.
|
|
|
|
// See: http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html
|
|
|
|
fs.realpathSync = realpathSync; |
|
|
|
fs.realpath = realpath; |
|
|
|
function realpathSync (p) { |
|
|
|
if (p.charAt(0) !== '/') { |
|
|
|
p = path.join(process.cwd(), p); |
|
|
|
} |
|
|
|
p = p.split('/'); |
|
|
|
var buf = [ '' ]; |
|
|
|
var seenLinks = {}; |
|
|
|
var knownHard = {}; |
|
|
|
// walk down the path, swapping out linked pathparts for their real
|
|
|
|
// values, and pushing non-link path bits onto the buffer.
|
|
|
|
// then return the buffer.
|
|
|
|
// NB: path.length changes.
|
|
|
|
for (var i = 0; i < p.length; i ++) { |
|
|
|
// skip over empty path parts.
|
|
|
|
if (p[i] === '') continue; |
|
|
|
var part = buf.join('/')+'/'+p[i]; |
|
|
|
if (knownHard[part]) { |
|
|
|
buf.push( p[i] ); |
|
|
|
continue; |
|
|
|
} |
|
|
|
var stat = fs.lstatSync(part); |
|
|
|
if (!stat.isSymbolicLink()) { |
|
|
|
// not a symlink. easy.
|
|
|
|
knownHard[ part ] = true; |
|
|
|
buf.push(p[i]); |
|
|
|
continue; |
|
|
|
} |
|
|
|
var id = stat.dev.toString(32)+':'+stat.ino.toString(32); |
|
|
|
if (seenLinks[id]) throw new Error("cyclic link at "+part); |
|
|
|
seenLinks[id] = true; |
|
|
|
var target = fs.readlinkSync(part); |
|
|
|
if (target.charAt(0) === '/') { |
|
|
|
// absolute. Start over.
|
|
|
|
buf = ['']; |
|
|
|
p = path.normalizeArray(target.split('/')); |
|
|
|
i = 0; |
|
|
|
continue; |
|
|
|
} |
|
|
|
// not absolute. join and splice.
|
|
|
|
target = target.split('/'); |
|
|
|
Array.prototype.splice.apply(p, [i, 1].concat(target)); |
|
|
|
p = path.normalizeArray(p); |
|
|
|
i = 0; |
|
|
|
buf = ['']; |
|
|
|
} |
|
|
|
return buf.join('/'); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fs.realpath = function (path, callback) { |
|
|
|
var seen_links = {}, knownHards = {}, buf = [''], i = 0, part, x; |
|
|
|
if (path.charAt(0) !== '/') { |
|
|
|
// assumes cwd is canonical
|
|
|
|
var cwd = process.cwd().split('/'); |
|
|
|
path = cwd.concat(path.split('/')); |
|
|
|
path = normalizeArray(path); |
|
|
|
i = cwd.length-1; |
|
|
|
buf = [].concat(cwd); |
|
|
|
} else { |
|
|
|
path = normalizeArray(path.split('/')); |
|
|
|
} |
|
|
|
function done(err) { |
|
|
|
if (callback) { |
|
|
|
if (!err) callback(err, buf.join('/')); |
|
|
|
else callback(err); |
|
|
|
function realpath (p, cb) { |
|
|
|
if (p.charAt(0) !== '/') { |
|
|
|
p = path.join(process.cwd(), p); |
|
|
|
} |
|
|
|
p = p.split('/'); |
|
|
|
var buf = [ '' ]; |
|
|
|
var seenLinks = {}; |
|
|
|
var knownHard = {}; |
|
|
|
// walk down the path, swapping out linked pathparts for their real
|
|
|
|
// values, and pushing non-link path bits onto the buffer.
|
|
|
|
// then return the buffer.
|
|
|
|
// NB: path.length changes.
|
|
|
|
var i = 0; |
|
|
|
var part; |
|
|
|
LOOP(); |
|
|
|
function LOOP () { |
|
|
|
i ++; |
|
|
|
if (!(i < p.length)) return exit(); |
|
|
|
// skip over empty path parts.
|
|
|
|
if (p[i] === '') return process.nextTick(LOOP); |
|
|
|
part = buf.join('/')+'/'+p[i]; |
|
|
|
if (knownHard[part]) { |
|
|
|
buf.push( p[i] ); |
|
|
|
return process.nextTick(LOOP); |
|
|
|
} |
|
|
|
} |
|
|
|
function next() { |
|
|
|
if (++i === path.length) return done(); |
|
|
|
part = path.slice(0, i+1).join('/'); |
|
|
|
if (part.length === 0) return next(); |
|
|
|
if (part in knownHards) { |
|
|
|
buf.push(path[i]); |
|
|
|
next(); |
|
|
|
} else { |
|
|
|
fs.lstat(part, function(err, stats){ |
|
|
|
if (err) return done(err); |
|
|
|
if (stats.isSymbolicLink()) { |
|
|
|
x = stats.dev.toString(32)+":"+stats.ino.toString(32); |
|
|
|
if (x in seen_links) |
|
|
|
return done(new Error("cyclic link at "+part)); |
|
|
|
seen_links[x] = true; |
|
|
|
fs.readlink(part, function(err, npart){ |
|
|
|
if (err) return done(err); |
|
|
|
part = npart; |
|
|
|
if (part.charAt(0) === '/') { |
|
|
|
// absolute
|
|
|
|
path = normalizeArray(part.split('/')); |
|
|
|
buf = ['']; |
|
|
|
i = 0; |
|
|
|
} else { |
|
|
|
// relative
|
|
|
|
Array.prototype.splice.apply(path, [i, 1].concat(part.split('/'))); |
|
|
|
part = normalizeArray(path); |
|
|
|
var y = 0, L = Math.max(path.length, part.length), delta; |
|
|
|
for (; y<L && path[y] === part[y]; y++); |
|
|
|
if (y !== L) { |
|
|
|
path = part; |
|
|
|
delta = i-y; |
|
|
|
i = y-1; // resolve new node if needed
|
|
|
|
if (delta > 0) buf.splice(y, delta); |
|
|
|
} |
|
|
|
else { |
|
|
|
i--; // resolve new node if needed
|
|
|
|
} |
|
|
|
} |
|
|
|
next(); |
|
|
|
}); // binding.readlink
|
|
|
|
} |
|
|
|
else { |
|
|
|
buf.push(path[i]); |
|
|
|
knownHards[buf.join('/')] = true; |
|
|
|
next(); |
|
|
|
} |
|
|
|
}); // binding.lstat
|
|
|
|
return fs.lstat(part, gotStat); |
|
|
|
} |
|
|
|
function gotStat (er, stat) { |
|
|
|
if (er) return cb(er); |
|
|
|
if (!stat.isSymbolicLink()) { |
|
|
|
// not a symlink. easy.
|
|
|
|
knownHard[ part ] = true; |
|
|
|
buf.push(p[i]); |
|
|
|
return process.nextTick(LOOP); |
|
|
|
} |
|
|
|
var id = stat.dev.toString(32)+':'+stat.ino.toString(32); |
|
|
|
if (seenLinks[id]) return cb(new Error("cyclic link at "+part)); |
|
|
|
seenLinks[id] = true; |
|
|
|
fs.readlink(part, gotTarget); |
|
|
|
} |
|
|
|
function gotTarget (er, target) { |
|
|
|
if (er) return cb(er); |
|
|
|
if (target.charAt(0) === '/') { |
|
|
|
// absolute. Start over.
|
|
|
|
buf = ['']; |
|
|
|
p = path.normalizeArray(target.split('/')); |
|
|
|
i = 0; |
|
|
|
return process.nextTick(LOOP); |
|
|
|
} |
|
|
|
// not absolute. join and splice.
|
|
|
|
target = target.split('/'); |
|
|
|
Array.prototype.splice.apply(p, [i, 1].concat(target)); |
|
|
|
p = path.normalizeArray(p); |
|
|
|
i = 0; |
|
|
|
buf = ['']; |
|
|
|
return process.nextTick(LOOP); |
|
|
|
} |
|
|
|
next(); |
|
|
|
}; |
|
|
|
function exit () { |
|
|
|
cb(null, buf.join('/') || '/'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
var pool; |
|
|
|
function allocNewPool () { |
|
|
|