12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 |
- // XXX use infer-owner or gentle-fs.mkdir here
- const npm = require('../npm.js')
- const path = require('path')
- const chownr = require('chownr')
- const writeFileAtomic = require('write-file-atomic')
- const mkdirp = require('mkdirp')
- const fs = require('graceful-fs')
- let cache = null
- let cacheUid = null
- let cacheGid = null
- let needChown = typeof process.getuid === 'function'
- const getCacheOwner = () => {
- let st
- try {
- st = fs.lstatSync(cache)
- } catch (er) {
- if (er.code !== 'ENOENT') {
- throw er
- }
- st = fs.lstatSync(path.dirname(cache))
- }
- cacheUid = st.uid
- cacheGid = st.gid
- needChown = st.uid !== process.getuid() ||
- st.gid !== process.getgid()
- }
- const writeOrAppend = (method, file, data) => {
- if (!cache) {
- cache = npm.config.get('cache')
- }
- // redundant if already absolute, but prevents non-absolute files
- // from being written as if they're part of the cache.
- file = path.resolve(cache, file)
- if (cacheUid === null && needChown) {
- getCacheOwner()
- }
- const dir = path.dirname(file)
- const firstMade = mkdirp.sync(dir)
- if (!needChown) {
- return method(file, data)
- }
- let methodThrew = true
- try {
- method(file, data)
- methodThrew = false
- } finally {
- // always try to leave it in the right ownership state, even on failure
- // let the method error fail it instead of the chownr error, though
- if (!methodThrew) {
- chownr.sync(firstMade || file, cacheUid, cacheGid)
- } else {
- try {
- chownr.sync(firstMade || file, cacheUid, cacheGid)
- } catch (_) {}
- }
- }
- }
- exports.append = (file, data) => writeOrAppend(fs.appendFileSync, file, data)
- exports.write = (file, data) => writeOrAppend(writeFileAtomic.sync, file, data)
|