summaryrefslogtreecommitdiff
path: root/deps/npm/lib/cache/get-stat.js
blob: 45b60ce7936fd4914b93bbd7296f4b98e230d29b (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
var mkdir = require("mkdirp")
  , fs = require("graceful-fs")
  , log = require("npmlog")
  , chownr = require("chownr")
  , npm = require("../npm.js")
  , inflight = require("inflight")

// to maintain the cache dir's permissions consistently.
var cacheStat = null
module.exports = function getCacheStat (cb) {
  if (cacheStat) return cb(null, cacheStat)

  fs.stat(npm.cache, function (er, st) {
    if (er) return makeCacheDir(cb)
    if (!st.isDirectory()) {
      log.error("getCacheStat", "invalid cache dir %j", npm.cache)
      return cb(er)
    }
    return cb(null, cacheStat = st)
  })
}

function makeCacheDir (cb) {
  cb = inflight("makeCacheDir", cb)
  if (!cb) return log.verbose("getCacheStat", "cache creation already in flight; waiting")
  log.verbose("getCacheStat", "cache creation not in flight; initializing")

  if (!process.getuid) return mkdir(npm.cache, function (er) {
    return cb(er, {})
  })

  var uid = +process.getuid()
    , gid = +process.getgid()

  if (uid === 0) {
    if (process.env.SUDO_UID) uid = +process.env.SUDO_UID
    if (process.env.SUDO_GID) gid = +process.env.SUDO_GID
  }
  if (uid !== 0 || !process.env.HOME) {
    cacheStat = {uid: uid, gid: gid}
    return mkdir(npm.cache, afterMkdir)
  }

  fs.stat(process.env.HOME, function (er, st) {
    if (er) {
      log.error("makeCacheDir", "homeless?")
      return cb(er)
    }
    cacheStat = st
    log.silly("makeCacheDir", "cache dir uid, gid", [st.uid, st.gid])
    return mkdir(npm.cache, afterMkdir)
  })

  function afterMkdir (er, made) {
    if (er || !cacheStat || isNaN(cacheStat.uid) || isNaN(cacheStat.gid)) {
      return cb(er, cacheStat)
    }

    if (!made) return cb(er, cacheStat)

    // ensure that the ownership is correct.
    chownr(made, cacheStat.uid, cacheStat.gid, function (er) {
      return cb(er, cacheStat)
    })
  }
}