diff options
author | isaacs <i@izs.me> | 2012-03-29 05:22:24 +0400 |
---|---|---|
committer | isaacs <i@izs.me> | 2012-03-29 05:22:24 +0400 |
commit | 37c8f97f58ba0283819ab8e4409ce3d12900974b (patch) | |
tree | 3b68c2f33b0e599667cc13abfe2de364b82efe46 | |
parent | 5002c00d63ed9d1cd80eabc69e7972e4894a1848 (diff) |
Update to use mkdirp and chownr modules
-rw-r--r-- | lib/cache.js | 42 | ||||
-rw-r--r-- | lib/install.js | 4 | ||||
-rw-r--r-- | lib/npm.js | 6 | ||||
-rw-r--r-- | lib/utils/cmd-shim.js | 2 | ||||
-rw-r--r-- | lib/utils/completion/file-completion.js | 2 | ||||
-rw-r--r-- | lib/utils/fetch.js | 5 | ||||
-rw-r--r-- | lib/utils/link.js | 2 | ||||
-rw-r--r-- | lib/utils/mkdir-p.js | 191 | ||||
-rw-r--r-- | lib/utils/npm-registry-client/get.js | 7 | ||||
-rw-r--r-- | lib/utils/tar.js | 19 |
10 files changed, 64 insertions, 216 deletions
diff --git a/lib/cache.js b/lib/cache.js index a57ff308f..b62e82dd1 100644 --- a/lib/cache.js +++ b/lib/cache.js @@ -31,7 +31,7 @@ exports.read = read exports.clean = clean exports.unpack = unpack -var mkdir = require("./utils/mkdir-p.js") +var mkdir = require("mkdirp") , exec = require("./utils/exec.js") , fetch = require("./utils/fetch.js") , npm = require("./npm.js") @@ -49,6 +49,7 @@ var mkdir = require("./utils/mkdir-p.js") , tar = require("./utils/tar.js") , fileCompletion = require("./utils/completion/file-completion.js") , url = require("url") + , chownr = require("chownr") cache.usage = "npm cache add <tarball file>" + "\nnpm cache add <folder>" @@ -633,7 +634,7 @@ function getCacheStat (cb) { } function makeCacheDir (cb) { - if (!process.getuid) return mkdir(npm.cache, npm.modes.exec, cb) + if (!process.getuid) return mkdir(npm.cache, cb) var uid = +process.getuid() , gid = +process.getgid() @@ -644,18 +645,28 @@ function makeCacheDir (cb) { } if (uid !== 0 || !process.env.HOME) { cacheStat = {uid: uid, gid: gid} - return mkdir(npm.cache, npm.modes.exec, uid, gid, function (er) { - return cb(er, cacheStat) - }) + return mkdir(npm.cache, afterMkdir) } + fs.stat(process.env.HOME, function (er, st) { if (er) return log.er(cb, "homeless?")(er) cacheStat = st log.silly([st.uid, st.gid], "uid, gid for cache dir") - return mkdir(npm.cache, npm.modes.exec, st.uid, st.gid, function (er) { + return mkdir(npm.cache, afterMkdir) + }) + + function afterMkdir (er, made) { + if (er || !cacheStat || isNaN(cacheStat.uid) || isNaN(cacheStat.gid)) { + return cb(er, cacheStat) + } + + if (!made) return cb(er, cacheStat) + + // ensure that the ownership is correct. + chownr(made, cacheStat.uid, cacheStat.gid, function (er) { return cb(er, cacheStat) }) - }) + } } @@ -733,9 +744,20 @@ function addLocalDirectory (p, name, cb) { , tgz = placeDirect ? placed : tmptgz , doFancyCrap = p.indexOf(npm.tmp) !== 0 && p.indexOf(npm.cache) !== 0 - tar.pack(tgz, p, data, doFancyCrap, function (er) { - if (er) return log.er(cb,"couldn't pack "+p+ " to "+tgz)(er) - addLocalTarball(tgz, name, cb) + getCacheStat(function (er, cs) { + mkdir(path.dirname(tgz), function (er, made) { + if (er) return cb(er) + tar.pack(tgz, p, data, doFancyCrap, function (er) { + if (er) return log.er(cb,"couldn't pack "+p+ " to "+tgz)(er) + + if (er || !cs || isNaN(cs.uid) || isNaN(cs.gid)) return cb() + + chownr(made || tgz, cs.uid, cs.gid, function (er) { + if (er) return cb(er) + addLocalTarball(tgz, name, cb) + }) + }) + }) }) }) } diff --git a/lib/install.js b/lib/install.js index 0daf0bc50..4da66d338 100644 --- a/lib/install.js +++ b/lib/install.js @@ -67,7 +67,7 @@ var npm = require("./npm.js") , relativize = require("./utils/relativize.js") , output , url = require("url") - , mkdir = require("./utils/mkdir-p.js") + , mkdir = require("mkdirp") , lifecycle = require("./utils/lifecycle.js") , archy = require("archy") @@ -107,7 +107,7 @@ function install (args, cb_) { }) } - mkdir(where, function (er) { + mkdir(where, function (er, made) { if (er) return cb(er) // install dependencies locally by default, // or install current folder globally diff --git a/lib/npm.js b/lib/npm.js index c314b3ec2..456948a29 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -26,7 +26,7 @@ var EventEmitter = require("events").EventEmitter , semver = require("semver") , findPrefix = require("./utils/find-prefix.js") , getUid = require("uid-number") - , mkdir = require("./utils/mkdir-p.js") + , mkdir = require("mkdirp") , slide = require("slide") , chain = slide.chain @@ -286,7 +286,7 @@ function loadPrefix (npm, conf, cb) { }) // the prefix MUST exist, or else nothing works. if (!npm.config.get("global")) { - mkdir(p, npm.modes.exec, null, null, true, next) + mkdir(p, next) } else { next(er) } @@ -299,7 +299,7 @@ function loadPrefix (npm, conf, cb) { , enumerable : true }) // the prefix MUST exist, or else nothing works. - mkdir(gp, npm.modes.exec, null, null, true, next) + mkdir(gp, next) }) var i = 2 diff --git a/lib/utils/cmd-shim.js b/lib/utils/cmd-shim.js index f53ab3cf8..e24da36f6 100644 --- a/lib/utils/cmd-shim.js +++ b/lib/utils/cmd-shim.js @@ -14,7 +14,7 @@ cmdShim.ifExists = cmdShimIfExists var fs = require("graceful-fs") , chain = require("slide").chain - , mkdir = require("./mkdir-p.js") + , mkdir = require("mkdirp") , rm = require("rimraf") , log = require("./log.js") , path = require("path") diff --git a/lib/utils/completion/file-completion.js b/lib/utils/completion/file-completion.js index 427efefb4..c1c241d68 100644 --- a/lib/utils/completion/file-completion.js +++ b/lib/utils/completion/file-completion.js @@ -1,7 +1,7 @@ module.exports = fileCompletion var find = require("../find.js") - , mkdir = require("../mkdir-p.js") + , mkdir = require("mkdirp") , path = require("path") function fileCompletion (root, req, depth, cb) { diff --git a/lib/utils/fetch.js b/lib/utils/fetch.js index 935e82039..0ece53cab 100644 --- a/lib/utils/fetch.js +++ b/lib/utils/fetch.js @@ -8,7 +8,8 @@ var request = require("request") , url = require("url") , log = require("./log.js") , path = require("path") - , mkdir = require("./mkdir-p.js") + , mkdir = require("mkdirp") + , chownr = require("chownr") , regHost module.exports = fetch @@ -16,7 +17,7 @@ module.exports = fetch function fetch (remote, local, headers, cb) { if (typeof cb !== "function") cb = headers, headers = {} log.verbose(local, "fetch to") - mkdir(path.dirname(local), function (er) { + mkdir(path.dirname(local), function (er, made) { if (er) return cb(er) fetch_(remote, local, headers, cb) }) diff --git a/lib/utils/link.js b/lib/utils/link.js index 918481068..7fa80d5e1 100644 --- a/lib/utils/link.js +++ b/lib/utils/link.js @@ -4,7 +4,7 @@ link.ifExists = linkIfExists var fs = require("graceful-fs") , chain = require("slide").chain - , mkdir = require("./mkdir-p.js") + , mkdir = require("mkdirp") , rm = require("./gently-rm.js") , log = require("./log.js") , path = require("path") diff --git a/lib/utils/mkdir-p.js b/lib/utils/mkdir-p.js deleted file mode 100644 index 2d9b9ee9f..000000000 --- a/lib/utils/mkdir-p.js +++ /dev/null @@ -1,191 +0,0 @@ - -var log = require("./log.js") - , fs = require("graceful-fs") - , path = require("path") - , npm = require("../npm.js") - , exec = require("./exec.js") - , uidNumber = require("uid-number") - , umask = process.umask() - , umaskOrig = umask - , addedUmaskExit = false - , mkdirCache = {} - -module.exports = mkdir -function mkdir (ensure, mode, uid, gid, noChmod, cb_) { - if (typeof cb_ !== "function") cb_ = noChmod, noChmod = null - if (typeof cb_ !== "function") cb_ = gid, gid = null - if (typeof cb_ !== "function") cb_ = uid, uid = null - if (typeof cb_ !== "function") cb_ = mode, mode = npm.modes.exec - - if (mode & umask) { - log.verbose(mode.toString(8), "umasking from "+umask.toString(8)) - process.umask(umask = 0) - if (!addedUmaskExit) { - addedUmaskExit = true - process.on("exit", function () { process.umask(umask = umaskOrig) }) - } - } - - ensure = path.resolve(ensure).replace(/\/+$/, '') - - // mkdir("/") should not do anything, since that always exists. - if (!ensure - || ( process.platform === "win32" - && ensure.match(/^[a-zA-Z]:(\\|\/)?$/))) { - return cb_() - } - - if (mkdirCache.hasOwnProperty(ensure)) { - return mkdirCache[ensure].push(cb_) - } - mkdirCache[ensure] = [cb_] - - function cb (er) { - var cbs = mkdirCache[ensure] - delete mkdirCache[ensure] - cbs.forEach(function (c) { c(er) }) - } - - if (uid === null && gid === null) { - return mkdir_(ensure, mode, uid, gid, noChmod, cb) - } - - uidNumber(uid, gid, function (er, uid, gid) { - if (er) return cb(er) - mkdir_(ensure, mode, uid, gid, noChmod, cb) - }) -} - -function mkdir_ (ensure, mode, uid, gid, noChmod, cb) { - // if it's already a dir, then just check the bits and owner. - fs.stat(ensure, function (er, s) { - if (s && s.isDirectory()) { - // check mode, uid, and gid. - if ((noChmod || (s.mode & mode) === mode) - && (typeof uid !== "number" || s.uid === uid) - && (typeof gid !== "number" || s.gid === gid)) return cb() - return done(ensure, mode, uid, gid, noChmod, cb) - } - return walkDirs(ensure, mode, uid, gid, noChmod, cb) - }) -} - -function done (ensure, mode, uid, gid, noChmod, cb) { - // now the directory has been created. - // chown it to the desired uid/gid - // Don't chown the npm.root dir, though, in case we're - // in unsafe-perm mode. - log.verbose("done: "+ensure+" "+mode.toString(8), "mkdir") - - // only chmod if noChmod isn't set. - var d = done_(ensure, mode, uid, gid, cb) - if (noChmod) return d() - fs.chmod(ensure, mode, d) -} - -function done_ (ensure, mode, uid, gid, cb) { - return function (er) { - if (er - || ensure === npm.dir - || typeof uid !== "number" - || typeof gid !== "number" - || npm.config.get("unsafe-perm")) return cb(er) - uid = Math.floor(uid) - gid = Math.floor(gid) - fs.chown(ensure, uid, gid, cb) - } -} - -var pathSplit = process.platform === "win32" ? /\/|\\/ : "/" -function walkDirs (ensure, mode, uid, gid, noChmod, cb) { - var dirs = ensure.split(pathSplit) - , walker = [] - , foundUID = null - , foundGID = null - - // gobble the "/" or C: first - walker.push(dirs.shift()) - - // The loop that goes through and stats each dir. - ;(function S (d) { - // no more directory steps left. - if (d === undefined) { - // do the chown stuff - return done(ensure, mode, uid, gid, noChmod, cb) - } - - // get the absolute dir for the next piece being stat'd - walker.push(d) - var dir = walker.join(path.SPLIT_CHAR) - - // stat callback lambda - fs.stat(dir, function STATCB (er, s) { - if (er) { - // the stat failed - directory does not exist. - - log.verbose(er.message, "mkdir (expected) error") - - // use the same uid/gid as the nearest parent, if not set. - if (foundUID !== null) uid = foundUID - if (foundGID !== null) gid = foundGID - - // make the directory - fs.mkdir(dir, mode, function MKDIRCB (er) { - // since stat and mkdir are done as two separate syscalls, - // operating on a path rather than a file descriptor, it's - // possible that the directory didn't exist when we did - // the stat, but then *did* exist when we go to to the mkdir. - // If we didn't care about uid/gid, we could just mkdir - // repeatedly, failing on any error other than "EEXIST". - if (er && er.message.indexOf("EEXIST") === 0) { - return fs.stat(dir, STATCB) - } - - // any other kind of error is not saveable. - if (er) return cb(er) - - // at this point, we've just created a new directory successfully. - - // if we care about permissions - if (!npm.config.get("unsafe-perm") // care about permissions - // specified a uid and gid - && uid !== null - && gid !== null ) { - // set the proper ownership - return fs.chown(dir, uid, gid, function (er) { - if (er) return cb(er) - // attack the next portion of the path. - S(dirs.shift()) - }) - } else { - // either we don't care about ownership, or it's already right. - S(dirs.shift()) - } - }) // mkdir - - } else { - // the stat succeeded. - if (s.isDirectory()) { - // if it's a directory, that's good. - // if the uid and gid aren't already set, then try to preserve - // the ownership on up the tree. Things in ~ remain owned by - // the user, things in / remain owned by root, etc. - if (uid === null && typeof s.uid === "number") foundUID = s.uid - if (gid === null && typeof s.gid === "number") foundGID = s.gid - - // move onto next portion of path - S(dirs.shift()) - - } else { - // the stat succeeded, but it's not a directory - log.verbose(dir, "mkdir exists") - log.silly(s, "stat("+dir+")") - log.verbose(s.isDirectory(), "isDirectory()") - cb(new Error("Failed to mkdir "+dir+": File exists")) - }// if (isDirectory) else - } // if (stat failed) else - }) // stat - - // start the S function with the first item in the list of directories. - })(dirs.shift()) -} diff --git a/lib/utils/npm-registry-client/get.js b/lib/utils/npm-registry-client/get.js index 49a8b4cc0..e0902f027 100644 --- a/lib/utils/npm-registry-client/get.js +++ b/lib/utils/npm-registry-client/get.js @@ -6,8 +6,9 @@ var GET = require("./request.js").GET , npm = require("../../npm.js") , path = require("path") , log = require("../log.js") - , mkdir = require("../mkdir-p.js") + , mkdir = require("mkdirp") , cacheStat = null + , chownr = require("chownr") function get (project, version, timeout, nofollow, staleOk, cb) { if (typeof cb !== "function") cb = staleOk, staleOk = false @@ -173,13 +174,13 @@ function saveToCache (cache, data, saved) { } function saveToCache_ (cache, data, uid, gid, saved) { - mkdir(path.dirname(cache), npm.modes.exec, uid, gid, function (er) { + mkdir(path.dirname(cache), function (er, made) { if (er) return saved() fs.writeFile(cache, JSON.stringify(data), function (er) { if (er || uid === null || gid === null) { return saved() } - fs.chown(cache, uid, gid, saved) + chownr(made || cache, uid, gid, saved) }) }) } diff --git a/lib/utils/tar.js b/lib/utils/tar.js index 355b988ca..415eb7f9e 100644 --- a/lib/utils/tar.js +++ b/lib/utils/tar.js @@ -128,6 +128,13 @@ function gunzTarPerm (tarball, target, dMode, fMode, uid, gid, cb_) { var extractOpts = { type: "Directory", path: target, strip: 1 } + if (process.platform !== "win32" && + typeof uid === "number" && + typeof gid === "number") { + extractOpts.uid = uid + extractOpts.gid = gid + } + extractOpts.filter = function () { // symbolic links are not allowed in packages. if (this.type.match(/^.*Link$/)) { @@ -149,7 +156,6 @@ function gunzTarPerm (tarball, target, dMode, fMode, uid, gid, cb_) { if (c[0] === 0x1F && c[1] === 0x8B && c[2] === 0x08) { - var extracter = tar.Extract(extractOpts) fst .pipe(zlib.Unzip()) .on("error", log.er(cb, "unzip error "+tarball)) @@ -166,8 +172,17 @@ function gunzTarPerm (tarball, target, dMode, fMode, uid, gid, cb_) { .on("close", cb) } else { // naked js file + var jsOpts = { path: path.resolve(target, "index.js") } + + if (process.platform !== "win32" && + typeof uid === "number" && + typeof gid === "number") { + jsOpts.uid = uid + jsOpts.gid = gid + } + fst - .pipe(fstream.Writer({ path: path.resolve(target, "index.js") })) + .pipe(fstream.Writer(jsOpts)) .on("error", log.er(cb, "copy error "+tarball)) .on("close", function () { var j = path.resolve(target, "package.json") |