Welcome to mirror list, hosted at ThFree Co, Russian Federation.

fix-owner.js « util « lib « cacache « node_modules - github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 90ffece524f54b3399d24756f68146a552ea4809 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
'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
  }
}