module.exports = chownr
chownr.sync = chownrSync

var fs = require("fs")
, path = require("path")

function chownr (p, uid, gid, cb) {
  fs.readdir(p, function (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 || !children.length) return fs.chown(p, uid, gid, cb)

    var len = children.length
    , errState = null
    children.forEach(function (child) {
      var pathChild = path.resolve(p, child);
      fs.lstat(pathChild, function(er, stats) {
        if (er)
          return cb(er)
        if (!stats.isSymbolicLink())
          chownr(pathChild, uid, gid, then)
        else
          then()
        })
    })
    function then (er) {
      if (errState) return
      if (er) return cb(errState = er)
      if (-- len === 0) return fs.chown(p, uid, gid, cb)
    }
  })
}

function chownrSync (p, uid, gid) {
  var children
  try {
    children = fs.readdirSync(p)
  } catch (er) {
    if (er && er.code === "ENOTDIR") return fs.chownSync(p, uid, gid)
    throw er
  }
  if (!children.length) return fs.chownSync(p, uid, gid)

  children.forEach(function (child) {
    var pathChild = path.resolve(p, child)
    var stats = fs.lstatSync(pathChild)
    if (!stats.isSymbolicLink())
      chownrSync(pathChild, uid, gid)
  })
  return fs.chownSync(p, uid, gid)
}

'use strict'
const fs = require('fs')
const path = require('path')

const chownr = (p, uid, gid, cb) => {
  fs.readdir(p, (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 || !children.length) return fs.chown(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.chown(p, uid, gid, cb)
    }

    children.forEach(child => {
      const pathChild = path.resolve(p, child)
      fs.lstat(pathChild, (er, stats) => {
        if (er)
          return cb(er)
        if (!stats.isSymbolicLink())
          chownr(pathChild, uid, gid, then)
        else
          then()
        })
    })
  })
}

const chownrSync = (p, uid, gid) => {
  let children
  try {
    children = fs.readdirSync(p)
  } catch (er) {
    if (er && er.code === 'ENOTDIR') return fs.chownSync(p, uid, gid)
    throw er
  }
  if (!children.length) return fs.chownSync(p, uid, gid)

  children.forEach(child => {
    const pathChild = path.resolve(p, child)
    const stats = fs.lstatSync(pathChild)
    if (!stats.isSymbolicLink())
      chownrSync(pathChild, uid, gid)
  })

  return fs.chownSync(p, uid, gid)
}

module.exports = chownr
chownr.sync = chownrSync

use modern JavaScript