| 'use strict' | 
|   | 
| const util = require('util') | 
|   | 
| const chownr = util.promisify(require('chownr')) | 
| const mkdirp = require('mkdirp') | 
| const inflight = require('promise-inflight') | 
| const inferOwner = require('infer-owner') | 
|   | 
| // Memoize getuid()/getgid() calls. | 
| // patch process.setuid/setgid to invalidate cached value on change | 
| const self = { uid: null, gid: null } | 
| const getSelf = () => { | 
|   if (typeof self.uid !== 'number') { | 
|     self.uid = process.getuid() | 
|     const setuid = process.setuid | 
|     process.setuid = (uid) => { | 
|       self.uid = null | 
|       process.setuid = setuid | 
|       return process.setuid(uid) | 
|     } | 
|   } | 
|   if (typeof self.gid !== 'number') { | 
|     self.gid = process.getgid() | 
|     const setgid = process.setgid | 
|     process.setgid = (gid) => { | 
|       self.gid = null | 
|       process.setgid = setgid | 
|       return process.setgid(gid) | 
|     } | 
|   } | 
| } | 
|   | 
| module.exports.chownr = fixOwner | 
|   | 
| function fixOwner (cache, filepath) { | 
|   if (!process.getuid) { | 
|     // This platform doesn't need ownership fixing | 
|     return Promise.resolve() | 
|   } | 
|   | 
|   getSelf() | 
|   if (self.uid !== 0) { | 
|     // almost certainly can't chown anyway | 
|     return Promise.resolve() | 
|   } | 
|   | 
|   return Promise.resolve(inferOwner(cache)).then((owner) => { | 
|     const { uid, gid } = owner | 
|   | 
|     // No need to override if it's already what we used. | 
|     if (self.uid === uid && self.gid === gid) | 
|       return | 
|   | 
|     return inflight('fixOwner: fixing ownership on ' + filepath, () => | 
|       chownr( | 
|         filepath, | 
|         typeof uid === 'number' ? uid : self.uid, | 
|         typeof gid === 'number' ? gid : self.gid | 
|       ).catch((err) => { | 
|         if (err.code === 'ENOENT') | 
|           return null | 
|   | 
|         throw err | 
|       }) | 
|     ) | 
|   }) | 
| } | 
|   | 
| module.exports.chownr.sync = fixOwnerSync | 
|   | 
| function fixOwnerSync (cache, filepath) { | 
|   if (!process.getuid) { | 
|     // This platform doesn't need ownership fixing | 
|     return | 
|   } | 
|   const { uid, gid } = inferOwner.sync(cache) | 
|   getSelf() | 
|   if (self.uid !== 0) { | 
|     // almost certainly can't chown anyway | 
|     return | 
|   } | 
|   | 
|   if (self.uid === uid && self.gid === gid) { | 
|     // No need to override if it's already what we used. | 
|     return | 
|   } | 
|   try { | 
|     chownr.sync( | 
|       filepath, | 
|       typeof uid === 'number' ? uid : self.uid, | 
|       typeof gid === 'number' ? gid : self.gid | 
|     ) | 
|   } catch (err) { | 
|     // only catch ENOENT, any other error is a problem. | 
|     if (err.code === 'ENOENT') | 
|       return null | 
|   | 
|     throw err | 
|   } | 
| } | 
|   | 
| module.exports.mkdirfix = mkdirfix | 
|   | 
| function mkdirfix (cache, p, cb) { | 
|   // we have to infer the owner _before_ making the directory, even though | 
|   // we aren't going to use the results, since the cache itself might not | 
|   // exist yet.  If we mkdirp it, then our current uid/gid will be assumed | 
|   // to be correct if it creates the cache folder in the process. | 
|   return Promise.resolve(inferOwner(cache)).then(() => { | 
|     return mkdirp(p) | 
|       .then((made) => { | 
|         if (made) | 
|           return fixOwner(cache, made).then(() => made) | 
|       }) | 
|       .catch((err) => { | 
|         if (err.code === 'EEXIST') | 
|           return fixOwner(cache, p).then(() => null) | 
|   | 
|         throw err | 
|       }) | 
|   }) | 
| } | 
|   | 
| module.exports.mkdirfix.sync = mkdirfixSync | 
|   | 
| function mkdirfixSync (cache, p) { | 
|   try { | 
|     inferOwner.sync(cache) | 
|     const made = mkdirp.sync(p) | 
|     if (made) { | 
|       fixOwnerSync(cache, made) | 
|       return made | 
|     } | 
|   } catch (err) { | 
|     if (err.code === 'EEXIST') { | 
|       fixOwnerSync(cache, p) | 
|       return null | 
|     } else | 
|       throw err | 
|   } | 
| } |