|
|
|
module.exports = chmodr
|
|
|
|
chmodr.sync = chmodrSync
|
|
|
|
|
|
|
|
var fs = require("fs")
|
|
|
|
var path = require("path")
|
|
|
|
|
|
|
|
function chmodr (p, mode, cb) {
|
|
|
|
fs.lstat(p, function (er, stats) {
|
|
|
|
if (er)
|
|
|
|
return cb(er)
|
|
|
|
if (stats.isSymbolicLink())
|
|
|
|
return cb()
|
|
|
|
if (stats.isDirectory())
|
|
|
|
return chmodrDir(p, mode, cb)
|
|
|
|
return fs.chmod(p, mode, cb)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
function chmodrDir (p, mode, cb) {
|
|
|
|
fs.readdir(p, function (er, children) {
|
|
|
|
if (er)
|
|
|
|
return cb(er)
|
|
|
|
|
|
|
|
if (!children.length)
|
|
|
|
return fs.chmod(p, dirMode(mode), cb)
|
|
|
|
|
|
|
|
var len = children.length
|
|
|
|
var errState = null
|
|
|
|
children.forEach(function (child) {
|
|
|
|
chmodr(path.resolve(p, child), mode, then)
|
|
|
|
})
|
|
|
|
|
|
|
|
// return first error, but not until all are finished,
|
|
|
|
// so we don't keep performing FS operations after the cb
|
|
|
|
function then (er) {
|
|
|
|
len = len - 1
|
|
|
|
if (er && !errState)
|
|
|
|
errState = er
|
|
|
|
if (len === 0) {
|
|
|
|
if (errState)
|
|
|
|
return cb(errState)
|
|
|
|
else
|
|
|
|
return fs.chmod(p, dirMode(mode), cb)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
function chmodrSync (p, mode) {
|
|
|
|
var stats = fs.lstatSync(p)
|
|
|
|
if (stats.isSymbolicLink())
|
|
|
|
return
|
|
|
|
if (stats.isDirectory())
|
|
|
|
return chmodrDirSync(p, mode)
|
|
|
|
else
|
|
|
|
return fs.chmodSync(p, mode)
|
|
|
|
}
|
|
|
|
|
|
|
|
function chmodrDirSync (p, mode) {
|
|
|
|
fs.readdirSync(p).forEach(function (child) {
|
|
|
|
chmodrSync(path.resolve(p, child), mode)
|
|
|
|
})
|
|
|
|
return fs.chmodSync(p, dirMode(mode))
|
|
|
|
}
|
|
|
|
|
|
|
|
// If a party has r, add x
|
|
|
|
// so that dirs are listable
|
|
|
|
function dirMode(mode) {
|
|
|
|
if (mode & 0400)
|
|
|
|
mode |= 0100
|
|
|
|
if (mode & 040)
|
|
|
|
mode |= 010
|
|
|
|
if (mode & 04)
|
|
|
|
mode |= 01
|
|
|
|
return mode
|
|
|
|
}
|