1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- 'use strict'
- const fs = require('fs')
- const path = require('path')
- /* istanbul ignore next */
- const LCHOWN = fs.lchown ? 'lchown' : 'chown'
- /* istanbul ignore next */
- const LCHOWNSYNC = fs.lchownSync ? 'lchownSync' : 'chownSync'
- // 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)
- const chownrKid = (p, child, uid, gid, cb) => {
- if (typeof child === 'string')
- return fs.lstat(path.resolve(p, child), (er, stats) => {
- if (er)
- return cb(er)
- stats.name = child
- chownrKid(p, stats, uid, gid, cb)
- })
- if (child.isDirectory()) {
- chownr(path.resolve(p, child.name), uid, gid, er => {
- if (er)
- return cb(er)
- fs[LCHOWN](path.resolve(p, child.name), uid, gid, cb)
- })
- } else
- fs[LCHOWN](path.resolve(p, child.name), uid, gid, cb)
- }
- const chownr = (p, uid, gid, cb) => {
- readdir(p, { withFileTypes: true }, (er, children) => {
- // any error other than ENOTDIR or ENOTSUP means it's not readable,
- // or doesn't exist. give up.
- if (er && er.code !== 'ENOTDIR' && er.code !== 'ENOTSUP')
- return cb(er)
- if (er || !children.length) return fs[LCHOWN](p, uid, gid, 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[LCHOWN](p, uid, gid, cb)
- }
- children.forEach(child => chownrKid(p, child, uid, gid, then))
- })
- }
- const chownrKidSync = (p, child, uid, gid) => {
- if (typeof child === 'string') {
- const stats = fs.lstatSync(path.resolve(p, child))
- stats.name = child
- child = stats
- }
- if (child.isDirectory())
- chownrSync(path.resolve(p, child.name), uid, gid)
- fs[LCHOWNSYNC](path.resolve(p, child.name), uid, gid)
- }
- const chownrSync = (p, uid, gid) => {
- let children
- try {
- children = readdirSync(p, { withFileTypes: true })
- } catch (er) {
- if (er && er.code === 'ENOTDIR' && er.code !== 'ENOTSUP')
- return fs[LCHOWNSYNC](p, uid, gid)
- throw er
- }
- if (children.length)
- children.forEach(child => chownrKidSync(p, child, uid, gid))
- return fs[LCHOWNSYNC](p, uid, gid)
- }
- module.exports = chownr
- chownr.sync = chownrSync
|