2016-11-28 10:42:58 +00:00
|
|
|
/**
|
|
|
|
* Operating system operations.
|
|
|
|
*
|
|
|
|
* @author n1474335 [n1474335@gmail.com]
|
|
|
|
* @copyright Crown Copyright 2016
|
|
|
|
* @license Apache-2.0
|
|
|
|
*
|
|
|
|
* @namespace
|
|
|
|
*/
|
2016-11-29 00:22:34 +00:00
|
|
|
const OS = {
|
2016-11-28 10:42:58 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Parse UNIX file permissions operation.
|
|
|
|
*
|
|
|
|
* @param {string} input
|
|
|
|
* @param {Object[]} args
|
|
|
|
* @returns {string}
|
|
|
|
*/
|
2016-11-29 00:22:34 +00:00
|
|
|
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) {
|
2016-11-28 10:42:58 +00:00
|
|
|
// Input is octal
|
2016-11-29 00:22:34 +00:00
|
|
|
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) {
|
2016-11-28 10:42:58 +00:00
|
|
|
// Input is textual
|
2016-11-29 00:22:34 +00:00
|
|
|
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;
|
2016-11-28 10:42:58 +00:00
|
|
|
}
|
2016-11-29 00:22:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2016-11-28 10:42:58 +00:00
|
|
|
}
|
2016-11-29 00:22:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2016-11-28 10:42:58 +00:00
|
|
|
}
|
2016-11-29 00:22:34 +00:00
|
|
|
}
|
|
|
|
} 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';
|
|
|
|
}
|
|
|
|
|
2016-11-28 10:42:58 +00:00
|
|
|
// sticky bit
|
2016-11-29 00:22:34 +00:00
|
|
|
if (perms.sb) {
|
|
|
|
output += '\nThe sticky bit is set';
|
|
|
|
}
|
|
|
|
|
2016-11-28 10:42:58 +00:00
|
|
|
// Permission matrix
|
2016-11-29 00:22:34 +00:00
|
|
|
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;
|
|
|
|
},
|
|
|
|
|
|
|
|
|
2016-11-28 10:42:58 +00:00
|
|
|
/**
|
|
|
|
* Given a permissions object dictionary, generates a textual permissions string.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @param {Object} perms
|
|
|
|
* @returns {string}
|
|
|
|
*/
|
2016-11-29 00:22:34 +00:00
|
|
|
_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;
|
|
|
|
},
|
|
|
|
|
|
|
|
|
2016-11-28 10:42:58 +00:00
|
|
|
/**
|
|
|
|
* Given a permissions object dictionary, generates an octal permissions string.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @param {Object} perms
|
|
|
|
* @returns {string}
|
|
|
|
*/
|
2016-11-29 00:22:34 +00:00
|
|
|
_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();
|
|
|
|
},
|
|
|
|
|
|
|
|
|
2016-11-28 10:42:58 +00:00
|
|
|
/**
|
|
|
|
* Given a permissions object dictionary, returns the file type.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @param {Object} perms
|
|
|
|
* @returns {string}
|
|
|
|
*/
|
2016-11-29 00:22:34 +00:00
|
|
|
_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';
|
|
|
|
},
|
|
|
|
|
2016-11-28 10:42:58 +00:00
|
|
|
};
|
2016-11-29 01:58:58 +00:00
|
|
|
|
|
|
|
export default OS;
|