• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// make sure that bins are executable, and that they don't have
2// windows line-endings on the hashbang line.
3const {
4  chmod,
5  open,
6  readFile,
7} = require('fs/promises')
8
9const execMode = 0o777 & (~process.umask())
10
11const writeFileAtomic = require('write-file-atomic')
12
13const isWindowsHashBang = buf =>
14  buf[0] === '#'.charCodeAt(0) &&
15  buf[1] === '!'.charCodeAt(0) &&
16  /^#![^\n]+\r\n/.test(buf.toString())
17
18const isWindowsHashbangFile = file => {
19  const FALSE = () => false
20  return open(file, 'r').then(fh => {
21    const buf = Buffer.alloc(2048)
22    return fh.read(buf, 0, 2048, 0)
23      .then(
24        () => {
25          const isWHB = isWindowsHashBang(buf)
26          return fh.close().then(() => isWHB, () => isWHB)
27        },
28        // don't leak FD if read() fails
29        () => fh.close().then(FALSE, FALSE)
30      )
31  }, FALSE)
32}
33
34const dos2Unix = file =>
35  readFile(file, 'utf8').then(content =>
36    writeFileAtomic(file, content.replace(/^(#![^\n]+)\r\n/, '$1\n')))
37
38const fixBin = (file, mode = execMode) => chmod(file, mode)
39  .then(() => isWindowsHashbangFile(file))
40  .then(isWHB => isWHB ? dos2Unix(file) : null)
41
42module.exports = fixBin
43