Server IP : 127.0.0.2 / Your IP : 18.217.93.250 Web Server : Apache/2.4.18 (Ubuntu) System : User : www-data ( ) PHP Version : 7.0.33-0ubuntu0.16.04.16 Disable Function : disk_free_space,disk_total_space,diskfreespace,dl,exec,fpaththru,getmyuid,getmypid,highlight_file,ignore_user_abord,leak,listen,link,opcache_get_configuration,opcache_get_status,passthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,php_uname,phpinfo,posix_ctermid,posix_getcwd,posix_getegid,posix_geteuid,posix_getgid,posix_getgrgid,posix_getgrnam,posix_getgroups,posix_getlogin,posix_getpgid,posix_getpgrp,posix_getpid,posix,_getppid,posix_getpwnam,posix_getpwuid,posix_getrlimit,posix_getsid,posix_getuid,posix_isatty,posix_kill,posix_mkfifo,posix_setegid,posix_seteuid,posix_setgid,posix_setpgid,posix_setsid,posix_setuid,posix_times,posix_ttyname,posix_uname,pclose,popen,proc_open,proc_close,proc_get_status,proc_nice,proc_terminate,shell_exec,source,show_source,system,virtual MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /usr/share/npm/lib/utils/ |
Upload File : |
// only remove the thing if it's a symlink into a specific folder. This is // a very common use-case of npm's, but not so common elsewhere. exports = module.exports = gentlyRm var resolve = require('path').resolve var dirname = require('path').dirname var normalize = require('path').normalize var validate = require('aproba') var log = require('npmlog') var lstat = require('graceful-fs').lstat var readlink = require('graceful-fs').readlink var isInside = require('path-is-inside') var vacuum = require('fs-vacuum') var chain = require('slide').chain var asyncMap = require('slide').asyncMap var readCmdShim = require('read-cmd-shim') var iferr = require('iferr') var npm = require('../npm.js') function gentlyRm (target, gently, base, cb) { if (!cb) { cb = base base = undefined } if (!cb) { cb = gently gently = false } log.silly( 'gentlyRm', target, 'is being', gently ? 'gently removed' : 'purged', base ? 'from base ' + base : '' ) // never rm the root, prefix, or bin dirs // // globals included because of `npm link` -- as far as the package // requesting the link is concerned, the linked package is always // installed globally var prefixes = [ npm.prefix, npm.globalPrefix, npm.dir, npm.root, npm.globalDir, npm.bin, npm.globalBin ] var targetPath = normalize(resolve(npm.prefix, target)) if (prefixes.indexOf(targetPath) !== -1) { log.verbose('gentlyRm', targetPath, "is part of npm and can't be removed") return cb(new Error('May not delete: ' + targetPath)) } var options = { log: log.silly.bind(log, 'vacuum-fs') } if (npm.config.get('force') || !gently) options.purge = true if (base) options.base = normalize(resolve(npm.prefix, base)) if (!gently) { log.verbose('gentlyRm', "don't care about contents; nuking", targetPath) return vacuum(targetPath, options, cb) } var parent = options.base = options.base || normalize(npm.prefix) // Do all the async work we'll need to do in order to tell if this is a // safe operation chain([ [isEverInside, parent, prefixes], [readLinkOrShim, targetPath], [isEverInside, targetPath, prefixes], [isEverInside, targetPath, [parent]] ], function (er, results) { if (er) { if (er.code === 'ENOENT') return cb() return cb(er) } var parentInfo = { path: parent, managed: results[0] } var targetInfo = { path: targetPath, symlink: results[1], managed: results[2], inParent: results[3] } isSafeToRm(parentInfo, targetInfo, iferr(cb, thenRemove)) function thenRemove (toRemove, removeBase) { if (!toRemove) return cb() if (removeBase) options.base = removeBase log.verbose('gentlyRm', options.purge ? 'Purging' : 'Vacuuming', toRemove, 'up to', options.base) return vacuum(toRemove, options, cb) } }) } exports._isSafeToRm = isSafeToRm function isSafeToRm (parent, target, cb) { log.silly('gentlyRm', 'parent.path =', parent.path) log.silly('gentlyRm', 'parent.managed =', parent.managed && parent.managed.target + ' is in ' + parent.managed.path) log.silly('gentlyRm', 'target.path = ', target.path) log.silly('gentlyRm', 'target.symlink =', target.symlink) log.silly('gentlyRm', 'target.managed =', target.managed && target.managed.target + ' is in ' + target.managed.path) log.silly('gentlyRm', 'target.inParent = ', target.inParent) // The parent directory or something it symlinks to must eventually be in // a folder that npm maintains. if (!parent.managed) { log.verbose('gentlyRm', parent.path, 'is not contained in any diretory npm is known to control or ' + 'any place they link to') return cb(clobberFail(target.path, 'containing path ' + parent.path + " isn't under npm's control")) } // The target or something it symlinks to must eventually be in the parent // or something the parent symlinks to if (target.inParent) { var actualTarget = target.inParent.target var targetsParent = target.inParent.path // if the target.path was what we found in some version of parent, remove // using that parent as the base if (target.path === actualTarget) { return cb(null, target.path, targetsParent) } else { // If something the target.path links to was what was found, just // remove target.path in the location it was found. return cb(null, target.path, dirname(target.path)) } } // If the target is in a managed directory and is in a symlink, but was // not in our parent that usually means someone else installed a bin file // with the same name as one of our bin files. if (target.managed && target.symlink) { log.warn('gentlyRm', 'not removing', target.path, "as it wasn't installed by", parent.path) return cb() } if (target.symlink) { return cb(clobberFail(target.path, target.symlink + ' symlink target is not controlled by npm ' + parent.path)) } else { return cb(clobberFail(target.path, 'is outside ' + parent.path + ' and not a link')) } } function clobberFail (target, msg) { validate('SS', arguments) var er = new Error('Refusing to delete ' + target + ': ' + msg) er.code = 'EEXIST' er.path = target return er } exports._isEverInside = isEverInside // return the first of path, where target (or anything it symlinks to) // isInside the path (or anything it symlinks to) function isEverInside (target, paths, cb) { validate('SAF', arguments) function skipENOENT (er) { if (er.code === 'ENOENT') return cb(null, false) return cb(er) } asyncMap(paths, readAllLinks, iferr(skipENOENT, function (resolvedPaths) { readAllLinks(target, iferr(skipENOENT, function (targets) { cb(null, areAnyInsideAny(targets, resolvedPaths)) })) })) } exports._areAnyInsideAny = areAnyInsideAny // Return the first path found that any target is inside function areAnyInsideAny (targets, paths) { validate('AA', arguments) var toCheck = [] paths.forEach(function (path) { targets.forEach(function (target) { toCheck.push([target, path]) }) }) for (var ii = 0; ii < toCheck.length; ++ii) { var target = toCheck[ii][0] var path = toCheck[ii][1] var inside = isInside(target, path) if (!inside) log.silly('isEverInside', target, 'is not inside', path) if (inside && path) return inside && path && {target: target, path: path} } return false } exports._readAllLinks = readAllLinks // resolves chains of symlinks of unlimited depth, returning a list of paths // it's seen in the process when it hits either a symlink cycle or a // non-symlink function readAllLinks (path, cb) { validate('SF', arguments) var seen = {} _readAllLinks(path) function _readAllLinks (path) { if (seen[path]) return cb(null, Object.keys(seen)) seen[path] = true resolveSymlink(path, iferr(cb, _readAllLinks)) } } exports._resolveSymlink = resolveSymlink var resolvedPaths = {} function resolveSymlink (symlink, cb) { validate('SF', arguments) var cached = resolvedPaths[symlink] if (cached) return cb(null, cached) readLinkOrShim(symlink, iferr(cb, function (symlinkTarget) { if (symlinkTarget) { resolvedPaths[symlink] = resolve(dirname(symlink), symlinkTarget) } else { resolvedPaths[symlink] = symlink } return cb(null, resolvedPaths[symlink]) })) } exports._readLinkOrShim = readLinkOrShim function readLinkOrShim (path, cb) { validate('SF', arguments) lstat(path, iferr(cb, function (stat) { if (stat.isSymbolicLink()) { readlink(path, cb) } else { readCmdShim(path, function (er, source) { if (!er) return cb(null, source) // lstat wouldn't return an error on these, so we don't either. if (er.code === 'ENOTASHIM' || er.code === 'EISDIR') { return cb(null, null) } else { return cb(er) } }) } })) }