Comparing version
144
chmodr.js
@@ -1,76 +0,100 @@ | ||
module.exports = chmodr | ||
chmodr.sync = chmodrSync | ||
'use strict' | ||
const fs = require('fs') | ||
const path = require('path') | ||
var fs = require("fs") | ||
var path = require("path") | ||
/* istanbul ignore next */ | ||
const LCHMOD = fs.lchmod ? 'lchmod' : 'chmod' | ||
/* istanbul ignore next */ | ||
const LCHMODSYNC = fs.lchmodSync ? 'lchmodSync' : 'chmodSync' | ||
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) | ||
}) | ||
// fs.readdir could only accept an options object as of node v6 | ||
const nodeVersion = process.version | ||
let readdir = (path, options, cb) => fs.readdir(path, options, cb) | ||
let readdirSync = (path, options) => fs.readdirSync(path, options) | ||
/* istanbul ignore next */ | ||
if (/^v4\./.test(nodeVersion)) | ||
readdir = (path, options, cb) => fs.readdir(path, cb) | ||
// If a party has r, add x | ||
// so that dirs are listable | ||
const dirMode = mode => { | ||
if (mode & 0o400) | ||
mode |= 0o100 | ||
if (mode & 0o40) | ||
mode |= 0o10 | ||
if (mode & 0o4) | ||
mode |= 0o1 | ||
return mode | ||
} | ||
function chmodrDir (p, mode, cb) { | ||
fs.readdir(p, function (er, children) { | ||
if (er) | ||
return cb(er) | ||
const chmodrKid = (p, child, mode, cb) => { | ||
if (typeof child === 'string') | ||
return fs.lstat(path.resolve(p, child), (er, stats) => { | ||
if (er) | ||
return cb(er) | ||
stats.name = child | ||
chmodrKid(p, stats, mode, cb) | ||
}) | ||
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) | ||
if (child.isDirectory()) { | ||
chmodr(path.resolve(p, child.name), mode, er => { | ||
if (er) | ||
return cb(er) | ||
fs.chmod(path.resolve(p, child.name), dirMode(mode), cb) | ||
}) | ||
} else | ||
fs[LCHMOD](path.resolve(p, child.name), mode, cb) | ||
} | ||
// 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) | ||
} | ||
const chmodr = (p, mode, cb) => { | ||
readdir(p, { withFileTypes: true }, (er, children) => { | ||
// any error other than ENOTDIR means it's not readable, or | ||
// doesn't exist. give up. | ||
if (er && er.code !== 'ENOTDIR') return cb(er) | ||
if (er) return fs[LCHMOD](p, mode, cb) | ||
if (!children.length) return fs.chmod(p, dirMode(mode), cb) | ||
let len = children.length | ||
let errState = null | ||
const then = er => { | ||
if (errState) return | ||
if (er) return cb(errState = er) | ||
if (-- len === 0) return fs.chmod(p, dirMode(mode), cb) | ||
} | ||
children.forEach(child => chmodrKid(p, child, mode, then)) | ||
}) | ||
} | ||
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) | ||
const chmodrKidSync = (p, child, mode) => { | ||
if (typeof child === 'string') { | ||
const stats = fs.lstatSync(path.resolve(p, child)) | ||
stats.name = child | ||
child = stats | ||
} | ||
if (child.isDirectory()) { | ||
chmodrSync(path.resolve(p, child.name), mode) | ||
fs.chmodSync(path.resolve(p, child.name), dirMode(mode)) | ||
} else | ||
fs[LCHMODSYNC](path.resolve(p, child.name), mode) | ||
} | ||
function chmodrDirSync (p, mode) { | ||
fs.readdirSync(p).forEach(function (child) { | ||
chmodrSync(path.resolve(p, child), mode) | ||
}) | ||
const chmodrSync = (p, mode) => { | ||
let children | ||
try { | ||
children = readdirSync(p, { withFileTypes: true }) | ||
} catch (er) { | ||
if (er && er.code === 'ENOTDIR') return fs[LCHMODSYNC](p, mode) | ||
throw er | ||
} | ||
if (children.length) | ||
children.forEach(child => chmodrKidSync(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 | ||
} | ||
module.exports = chmodr | ||
chmodr.sync = chmodrSync |
@@ -5,3 +5,3 @@ { | ||
"description": "like `chmod -R`", | ||
"version": "1.0.2", | ||
"version": "1.1.0", | ||
"repository": { | ||
@@ -15,6 +15,9 @@ "type": "git", | ||
"rimraf": "", | ||
"tap": "^1.3.2" | ||
"tap": "^12.0.1" | ||
}, | ||
"scripts": { | ||
"test": "tap test/*.js" | ||
"test": "tap test/*.js --cov", | ||
"preversion": "npm test", | ||
"postversion": "npm publish", | ||
"postpublish": "git push origin --all; git push origin --tags" | ||
}, | ||
@@ -21,0 +24,0 @@ "license": "ISC", |
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
4109
40.82%85
26.87%