/** * Operating system operations. * * @author n1474335 [n1474335@gmail.com] * @copyright Crown Copyright 2016 * @license Apache-2.0 * * @namespace */ const OS = { /** * Parse UNIX file permissions operation. * * @param {string} input * @param {Object[]} args * @returns {string} */ run_parse_unix_perms(input, args) { let perms = { d: false, // directory sl: false, // symbolic link np: false, // named pipe s: false, // socket cd: false, // character device bd: false, // block device dr: false, // door sb: false, // sticky bit su: false, // setuid sg: false, // setgid ru: false, // read user wu: false, // write user eu: false, // execute user rg: false, // read group wg: false, // write group eg: false, // execute group ro: false, // read other wo: false, // write other eo: false, // execute other }, d = 0, u = 0, g = 0, o = 0, output = '', octal = null, textual = null; if (input.search(/\s*[0-7]{1,4}\s*/i) === 0) { // Input is octal octal = input.match(/\s*([0-7]{1,4})\s*/i)[1]; if (octal.length == 4) { d = parseInt(octal[0], 8); u = parseInt(octal[1], 8); g = parseInt(octal[2], 8); o = parseInt(octal[3], 8); } else { if (octal.length > 0) u = parseInt(octal[0], 8); if (octal.length > 1) g = parseInt(octal[1], 8); if (octal.length > 2) o = parseInt(octal[2], 8); } perms.su = d >> 2 & 0x1; perms.sg = d >> 1 & 0x1; perms.sb = d & 0x1; perms.ru = u >> 2 & 0x1; perms.wu = u >> 1 & 0x1; perms.eu = u & 0x1; perms.rg = g >> 2 & 0x1; perms.wg = g >> 1 & 0x1; perms.eg = g & 0x1; perms.ro = o >> 2 & 0x1; perms.wo = o >> 1 & 0x1; perms.eo = o & 0x1; } else if (input.search(/\s*[dlpcbDrwxsStT-]{1,10}\s*/) === 0) { // Input is textual textual = input.match(/\s*([dlpcbDrwxsStT-]{1,10})\s*/)[1]; switch (textual[0]) { case 'd': perms.d = true; break; case 'l': perms.sl = true; break; case 'p': perms.np = true; break; case 's': perms.s = true; break; case 'c': perms.cd = true; break; case 'b': perms.bd = true; break; case 'D': perms.dr = true; break; } if (textual.length > 1) perms.ru = textual[1] == 'r'; if (textual.length > 2) perms.wu = textual[2] == 'w'; if (textual.length > 3) { switch (textual[3]) { case 'x': perms.eu = true; break; case 's': perms.eu = true; perms.su = true; break; case 'S': perms.su = true; break; } } if (textual.length > 4) perms.rg = textual[4] == 'r'; if (textual.length > 5) perms.wg = textual[5] == 'w'; if (textual.length > 6) { switch (textual[6]) { case 'x': perms.eg = true; break; case 's': perms.eg = true; perms.sg = true; break; case 'S': perms.sg = true; break; } } if (textual.length > 7) perms.ro = textual[7] == 'r'; if (textual.length > 8) perms.wo = textual[8] == 'w'; if (textual.length > 9) { switch (textual[9]) { case 'x': perms.eo = true; break; case 't': perms.eo = true; perms.sb = true; break; case 'T': perms.sb = true; break; } } } else { return 'Invalid input format.\nPlease enter the permissions in either octal (e.g. 755) or textual (e.g. drwxr-xr-x) format.'; } output += `Textual representation: ${OS._perms_to_str(perms)}`; output += `\nOctal representation: ${OS._perms_to_octal(perms)}`; // File type if (textual) { output += `\nFile type: ${OS._ft_from_perms(perms)}`; } // setuid, setgid if (perms.su) { output += '\nThe setuid flag is set'; } if (perms.sg) { output += '\nThe setgid flag is set'; } // sticky bit if (perms.sb) { output += '\nThe sticky bit is set'; } // Permission matrix output += `${'\n\n +---------+-------+-------+-------+\n' + ' | | User | Group | Other |\n' + ' +---------+-------+-------+-------+\n' + ' | Read | '}${perms.ru ? 'X' : ' '} | ${perms.rg ? 'X' : ' '} | ${perms.ro ? 'X' : ' '} |\n` + ' +---------+-------+-------+-------+\n' + ` | Write | ${perms.wu ? 'X' : ' '} | ${perms.wg ? 'X' : ' '} | ${perms.wo ? 'X' : ' '} |\n` + ' +---------+-------+-------+-------+\n' + ` | Execute | ${perms.eu ? 'X' : ' '} | ${perms.eg ? 'X' : ' '} | ${perms.eo ? 'X' : ' '} |\n` + ' +---------+-------+-------+-------+\n'; return output; }, /** * Given a permissions object dictionary, generates a textual permissions string. * * @private * @param {Object} perms * @returns {string} */ _perms_to_str(perms) { let str = '', type = '-'; if (perms.d) type = 'd'; if (perms.sl) type = 'l'; if (perms.np) type = 'p'; if (perms.s) type = 's'; if (perms.cd) type = 'c'; if (perms.bd) type = 'b'; if (perms.dr) type = 'D'; str = type; str += perms.ru ? 'r' : '-'; str += perms.wu ? 'w' : '-'; if (perms.eu && perms.su) { str += 's'; } else if (perms.su) { str += 'S'; } else if (perms.eu) { str += 'x'; } else { str += '-'; } str += perms.rg ? 'r' : '-'; str += perms.wg ? 'w' : '-'; if (perms.eg && perms.sg) { str += 's'; } else if (perms.sg) { str += 'S'; } else if (perms.eg) { str += 'x'; } else { str += '-'; } str += perms.ro ? 'r' : '-'; str += perms.wo ? 'w' : '-'; if (perms.eo && perms.sb) { str += 't'; } else if (perms.sb) { str += 'T'; } else if (perms.eo) { str += 'x'; } else { str += '-'; } return str; }, /** * Given a permissions object dictionary, generates an octal permissions string. * * @private * @param {Object} perms * @returns {string} */ _perms_to_octal(perms) { let d = 0, u = 0, g = 0, o = 0; if (perms.su) d += 4; if (perms.sg) d += 2; if (perms.sb) d += 1; if (perms.ru) u += 4; if (perms.wu) u += 2; if (perms.eu) u += 1; if (perms.rg) g += 4; if (perms.wg) g += 2; if (perms.eg) g += 1; if (perms.ro) o += 4; if (perms.wo) o += 2; if (perms.eo) o += 1; return d.toString() + u.toString() + g.toString() + o.toString(); }, /** * Given a permissions object dictionary, returns the file type. * * @private * @param {Object} perms * @returns {string} */ _ft_from_perms(perms) { if (perms.d) return 'Directory'; if (perms.sl) return 'Symbolic link'; if (perms.np) return 'Named pipe'; if (perms.s) return 'Socket'; if (perms.cd) return 'Character device'; if (perms.bd) return 'Block device'; if (perms.dr) return 'Door'; return 'Regular file'; }, };