basant307/AI_Governance_Project
048
1'use strict'2const fs = require('fs')3const path = require('path')4 5/* istanbul ignore next */6const LCHOWN = fs.lchown ? 'lchown' : 'chown'7/* istanbul ignore next */8const LCHOWNSYNC = fs.lchownSync ? 'lchownSync' : 'chownSync'9 10/* istanbul ignore next */11const needEISDIRHandled = fs.lchown &&12 !process.version.match(/v1[1-9]+\./) &&13 !process.version.match(/v10\.[6-9]/)14 15const lchownSync = (path, uid, gid) => {16 try {17 return fs[LCHOWNSYNC](path, uid, gid)18 } catch (er) {19 if (er.code !== 'ENOENT')20 throw er21 }22}23 24/* istanbul ignore next */25const chownSync = (path, uid, gid) => {26 try {27 return fs.chownSync(path, uid, gid)28 } catch (er) {29 if (er.code !== 'ENOENT')30 throw er31 }32}33 34/* istanbul ignore next */35const handleEISDIR =36 needEISDIRHandled ? (path, uid, gid, cb) => er => {37 // Node prior to v10 had a very questionable implementation of38 // fs.lchown, which would always try to call fs.open on a directory39 // Fall back to fs.chown in those cases.40 if (!er || er.code !== 'EISDIR')41 cb(er)42 else43 fs.chown(path, uid, gid, cb)44 }45 : (_, __, ___, cb) => cb46 47/* istanbul ignore next */48const handleEISDirSync =49 needEISDIRHandled ? (path, uid, gid) => {50 try {51 return lchownSync(path, uid, gid)52 } catch (er) {53 if (er.code !== 'EISDIR')54 throw er55 chownSync(path, uid, gid)56 }57 }58 : (path, uid, gid) => lchownSync(path, uid, gid)59 60// fs.readdir could only accept an options object as of node v661const nodeVersion = process.version62let readdir = (path, options, cb) => fs.readdir(path, options, cb)63let readdirSync = (path, options) => fs.readdirSync(path, options)64/* istanbul ignore next */65if (/^v4\./.test(nodeVersion))66 readdir = (path, options, cb) => fs.readdir(path, cb)67 68const chown = (cpath, uid, gid, cb) => {69 fs[LCHOWN](cpath, uid, gid, handleEISDIR(cpath, uid, gid, er => {70 // Skip ENOENT error71 cb(er && er.code !== 'ENOENT' ? er : null)72 }))73}74 75const chownrKid = (p, child, uid, gid, cb) => {76 if (typeof child === 'string')77 return fs.lstat(path.resolve(p, child), (er, stats) => {78 // Skip ENOENT error79 if (er)80 return cb(er.code !== 'ENOENT' ? er : null)81 stats.name = child82 chownrKid(p, stats, uid, gid, cb)83 })84 85 if (child.isDirectory()) {86 chownr(path.resolve(p, child.name), uid, gid, er => {87 if (er)88 return cb(er)89 const cpath = path.resolve(p, child.name)90 chown(cpath, uid, gid, cb)91 })92 } else {93 const cpath = path.resolve(p, child.name)94 chown(cpath, uid, gid, cb)95 }96}97 98 99const chownr = (p, uid, gid, cb) => {100 readdir(p, { withFileTypes: true }, (er, children) => {101 // any error other than ENOTDIR or ENOTSUP means it's not readable,102 // or doesn't exist. give up.103 if (er) {104 if (er.code === 'ENOENT')105 return cb()106 else if (er.code !== 'ENOTDIR' && er.code !== 'ENOTSUP')107 return cb(er)108 }109 if (er || !children.length)110 return chown(p, uid, gid, cb)111 112 let len = children.length113 let errState = null114 const then = er => {115 if (errState)116 return117 if (er)118 return cb(errState = er)119 if (-- len === 0)120 return chown(p, uid, gid, cb)121 }122 123 children.forEach(child => chownrKid(p, child, uid, gid, then))124 })125}126 127const chownrKidSync = (p, child, uid, gid) => {128 if (typeof child === 'string') {129 try {130 const stats = fs.lstatSync(path.resolve(p, child))131 stats.name = child132 child = stats133 } catch (er) {134 if (er.code === 'ENOENT')135 return136 else137 throw er138 }139 }140 141 if (child.isDirectory())142 chownrSync(path.resolve(p, child.name), uid, gid)143 144 handleEISDirSync(path.resolve(p, child.name), uid, gid)145}146 147const chownrSync = (p, uid, gid) => {148 let children149 try {150 children = readdirSync(p, { withFileTypes: true })151 } catch (er) {152 if (er.code === 'ENOENT')153 return154 else if (er.code === 'ENOTDIR' || er.code === 'ENOTSUP')155 return handleEISDirSync(p, uid, gid)156 else157 throw er158 }159 160 if (children && children.length)161 children.forEach(child => chownrKidSync(p, child, uid, gid))162 163 return handleEISDirSync(p, uid, gid)164}165 166module.exports = chownr167chownr.sync = chownrSync168 