You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							128 lines
						
					
					
						
							3.2 KiB
						
					
					
				
			
		
		
	
	
							128 lines
						
					
					
						
							3.2 KiB
						
					
					
				'use strict' | 
						|
 | 
						|
const BB = require('bluebird') | 
						|
 | 
						|
const chownr = BB.promisify(require('chownr')) | 
						|
const mkdirp = BB.promisify(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 BB.resolve() | 
						|
  } | 
						|
 | 
						|
  getSelf() | 
						|
  if (self.uid !== 0) { | 
						|
    // almost certainly can't chown anyway | 
						|
    return BB.resolve() | 
						|
  } | 
						|
 | 
						|
  return BB.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({ code: 'ENOENT' }, () => null) | 
						|
    ) | 
						|
  }) | 
						|
} | 
						|
 | 
						|
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 === 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 BB.resolve(inferOwner(cache)).then(() => { | 
						|
    return mkdirp(p).then(made => { | 
						|
      if (made) { | 
						|
        return fixOwner(cache, made).then(() => made) | 
						|
      } | 
						|
    }).catch({ code: 'EEXIST' }, () => { | 
						|
      // There's a race in mkdirp! | 
						|
      return fixOwner(cache, p).then(() => null) | 
						|
    }) | 
						|
  }) | 
						|
} | 
						|
 | 
						|
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 | 
						|
    } | 
						|
  } | 
						|
}
 | 
						|
 |