This file is indexed.

/usr/lib/nodejs/mutate-fs/index.js is in node-mutate-fs 2.1.1-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
'use strict'
// evil-fs: a module to make node's fs util a bit of a jerk.
// XXX this should be its own npm package
//
// All of these functions return the de-mutating restore function

const fs = require('fs')

// zenoRead()
// Make fs.read() calls return half as much data, zeno's paradox style
const zenoRead = exports.zenoRead = _ => {
  return mutateArgs('read', (args) => {
    const cb = typeof args[args.length - 1] === 'function' ? args.pop() : null
    const fd = args.shift()
    const buffer = args.shift()
    const offset = args.shift()
    const length = args.shift()
    const position = args.shift()
    const zlen = length > 1 ? Math.floor(length / 2) : length
    return [fd, buffer, offset, zlen, position, cb]
  })
}

const constants = require('constants')
// should always be set, but standard values are here just in case.
/* istanbul ignore next */
const S_IFMT   = constants.S_IFMT   || 0o170000
/* istanbul ignore next */
const S_IFREG  = constants.S_IFREG  || 0o100000
/* istanbul ignore next */
const S_IFDIR  = constants.S_IFDIR  || 0o040000
/* istanbul ignore next */
const S_IFCHR  = constants.S_IFCHR  || 0o020000
/* istanbul ignore next */
const S_IFBLK  = constants.S_IFBLK  || 0o060000
/* istanbul ignore next */
const S_IFIFO  = constants.S_IFIFO  || 0o010000
/* istanbul ignore next */
const S_IFLNK  = constants.S_IFLNK  || 0o120000
/* istanbul ignore next */
const S_IFSOCK = constants.S_IFSOCK || 0o140000

// statType(type)
// mutate stat/fstat/lstat calls to always return the specified type
// only mutates if there is no error returned by the stat call.
// Takes a type to match the `isBlank()` stat methods
// File, Directory, CharacterDevice, BlockDevice, FIFO, SymbolicLink, Socket
const statType = exports.statType = type => {
  const mode = type === 'File' ? S_IFREG
             : type === 'Directory' ? S_IFDIR
             : type === 'CharacterDevice' ? S_IFCHR
             : type === 'BlockDevice' ? S_IFBLK
             : type === 'FIFO' ? S_IFIFO
             : type === 'SymbolicLink' ? S_IFLNK
             : type === 'Socket' ? S_IFSOCK
             : null
  if (!mode)
    throw new TypeError('invalid type: ' + type)
  return statMutate((error, stat) => {
    if (stat)
      stat.mode = stat.mode & (S_IFMT ^ 0o777777) | mode
  })
}

const statFail = exports.statFail = error => {
  const unfail = fail('stat', error)
  const unfaill = fail('lstat', error)
  const unfailf = fail('fstat', error)
  return _ => unfail(unfaill(unfailf()))
}

// pass(methodName, data)
// Cause fs[methodName] and fs[methodName + 'Sync'] to
// automatically pass with the data provided.
// Returns restore method
const pass = exports.pass = (method, data) => {
  const orig = fs[method]
  const origSync = fs[method + 'Sync']

  fs[method] = function () {
    const cb = arguments[arguments.length - 1]
    setTimeout(_ => cb(null, data))
  }

  fs[method + 'Sync'] = _ => {
    return data
  }

  return _ => {
    fs[method] = orig
    fs[method + 'Sync'] = origSync
  }
}

// fail(methodName, error)
// Cause specified fs method to fail with the provided error
const fail = exports.fail = (method, error) => {
  const orig = fs[method]
  const origSync = fs[method + 'Sync']

  fs[method] = function () {
    const cb = arguments[arguments.length - 1]
    const callstack = new Error('trace').stack
    setTimeout(_ => {
      Object.defineProperty(error, 'callstack', {
        get: _ => callstack,
        configurable: true
      })
      cb(error)
    })
  }

  fs[method + 'Sync'] = _ => {
    const callstack = new Error('trace').stack
    Object.defineProperty(error, 'callstack', {
      get: _ => callstack,
      configurable: true
    })
    throw error
  }

  return _ => {
    fs[method] = orig
    fs[method + 'Sync'] = origSync
  }
}

// statMutate(fn)
// Mutate all stat functions at once
const statMutate = exports.statMutate = fn => {
  const unmutate = mutate('stat', fn)
  const unmutatel = mutate('lstat', fn)
  const unmutatef = mutate('fstat', fn)

  return _ => unmutate(unmutatel(unmutatef()))
}

// mutateArgs(method, fn)
// Pass in the arguments to method to fn(), which returns a mutated
// set of arguments that the function will be called with
const mutateArgs = exports.mutateArgs = (method, fn) => {
  const orig = fs[method]
  const origSync = fs[method + 'Sync']

  fs[method] = function () {
    orig.apply(fs, fn(Array.from(arguments)))
  }

  fs[method + 'Sync'] = function () {
    return origSync.apply(fn, fn(Array.from(arguments)))
  }

  return _ => {
    fs[method] = orig
    fs[method + 'Sync'] = origSync
  }
}

// mutate(method, fn)
// Apply fn(error, data) to return values from fs[method]
// If the function returns an array, it should be [newError, newData]
// If the function does not return a value, use (mutated in place) values
const mutate = exports.mutate = (method, fn) => {
  const orig = fs[method]
  const origSync = fs[method + 'Sync']

  fs[method] = function () {
    const cb = arguments[arguments.length - 1]
    arguments[arguments.length - 1] = (error, data) => {
      const mutated = fn(error, data)
      if (!mutated) // just mutate objects in-place is fine
        cb(error, data)
      else
        cb(mutated[0], mutated[1])
    }
    orig.apply(fs, arguments)
  }

  fs[method + 'Sync'] = function () {
    let result, error
    try {
      result = origSync.apply(fs, arguments)
    } catch (er) {
      error = er
    }
    const mutated = fn(error, result)
    if (mutated) {
      error = mutated[0]
      result = mutated[1]
    }
    if (error)
      throw error
    return result
  }

  return _ => {
    fs[method] = orig
    fs[method + 'Sync'] = origSync
  }
}

const delay = exports.delay = (method, ms) => {
  const orig = fs[method]
  const origSync = fs[method + 'Sync']
  fs[method] = function () {
    const cb = arguments[arguments.length - 1]
    const end = Date.now() + ms
    arguments[arguments.length - 1] = (error, data) =>
      setTimeout(_ => cb(error, data), end - Date.now())
    orig.apply(fs, arguments)
  }

  fs[method + 'Sync'] = function () {
    const end = Date.now() + ms
    try {
      return origSync.apply(this, arguments)
    } finally {
      while (end > Date.now()) {
        fs.readFileSync(__filename)
      }
    }
  }

  return _ => {
    fs[method] = orig
    fs[method + 'Sync'] = origSync
  }
}