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