convert file permissions to using bitwise integer values

This commit is contained in:
Lisa Milne 2023-12-16 13:13:04 +10:00
parent f333734f97
commit af1942daa1
5 changed files with 492 additions and 172 deletions

View file

@ -78,13 +78,14 @@ Options:
}else{
d = time.strftime('%b %d %H:%M',tm);
}
var ms = clite.strmode(st.st_mode);
if (st.type == stdio.types.FT_LINK) {
var lp = stdio.readAll(fd);
if (!lp)
lp = '?';
stdio.printf('%s%12s%12s%14s%12s -> %s\n',st.perms,uname,gname,d,st.name,lp);
stdio.printf('%s%12s%12s%14s%12s -> %s\n',ms,uname,gname,d,st.name,lp);
}else{
stdio.printf('%s%12s%12s%14s%12s\n',st.perms,uname,gname,d,st.name);
stdio.printf('%s%12s%12s%14s%12s\n',ms,uname,gname,d,st.name);
}
}else if (one) {
stdio.printf('%s\n',st.name);
@ -931,6 +932,90 @@ Options:
return modmask.join('');
}
function getMode(mode,isdir) {
if (modmask[0] == 'r') {
mode |= stdio.modes.S_IRUSR;
}else if (modmask[0] == '-') {
mode &= ~stdio.modes.S_IRUSR;
}
if (modmask[1] == 'w') {
mode |= stdio.modes.S_IWUSR;
}else if (modmask[1] == '-') {
mode &= ~stdio.modes.S_IWUSR;
}
if (modmask[2] == 'x' || (isdir && modmask[2] == 'X')) {
mode |= stdio.modes.S_IXUSR;
mode &= ~stdio.modes.S_ISUID;
}else if (modmask[2] == 's') {
mode |= stdio.modes.S_IXUSR;
mode |= stdio.modes.S_ISUID;
}else if (modmask[2] == 'S') {
mode &= ~stdio.modes.S_IXUSR;
mode |= stdio.modes.S_ISUID;
}else if (modmask[2] == '-' || (isdir && modmask[2] == 'Y')) {
mode &= ~stdio.modes.S_IXUSR;
mode &= ~stdio.modes.S_ISUID;
}
if (modmask[3] == 'r') {
mode |= stdio.modes.S_IRGRP;
}else if (modmask[3] == '-') {
mode &= ~stdio.modes.S_IRGRP;
}
if (modmask[4] == 'w') {
mode |= stdio.modes.S_IWGRP;
}else if (modmask[4] == '-') {
mode &= ~stdio.modes.S_IWGRP;
}
if (modmask[5] == 'x' || (isdir && modmask[5] == 'X')) {
mode |= stdio.modes.S_IXGRP;
mode &= ~stdio.modes.S_ISGID;
}else if (modmask[5] == 's') {
mode |= stdio.modes.S_IXGRP;
mode |= stdio.modes.S_ISGID;
}else if (modmask[5] == 'S') {
mode &= ~stdio.modes.S_IXGRP;
mode |= stdio.modes.S_ISGID;
}else if (modmask[5] == '-' || (isdir && modmask[5] == 'Y')) {
mode &= ~stdio.modes.S_IXGRP;
mode &= ~stdio.modes.S_ISGID;
}
if (modmask[6] == 'r') {
mode |= stdio.modes.S_IROTH;
}else if (modmask[6] == '-') {
mode &= ~stdio.modes.S_IROTH;
}
if (modmask[7] == 'w') {
mode |= stdio.modes.S_IWOTH;
}else if (modmask[7] == '-') {
mode &= ~stdio.modes.S_IWOTH;
}
if (!isdir) {
if (modmask[8] == 'x') {
mode |= stdio.modes.S_IXOTH;
}else if (modmask[8] == '-') {
mode &= ~stdio.modes.S_IXOTH;
}
}else{
if (modmask[8] == 'x' || modmask[8] == 'X') {
mode |= stdio.modes.S_IXOTH;
mode &= ~stdio.modes.S_ISVTX;
}else if (modmask[8] == 't') {
mode |= stdio.modes.S_IXOTH;
mode |= stdio.modes.S_ISVTX;
}else if (modmask[8] == 'T') {
mode &= ~stdio.modes.S_IXOTH;
mode |= stdio.modes.S_ISVTX;
}else if (modmask[8] == '-' || modmask[8] == 'Y') {
mode &= ~stdio.modes.S_IXOTH;
mode &= ~stdio.modes.S_ISVTX;
}
}
return mode;
}
function getPerms(str,isdir) {
var n = str.substring(1);
for (var i=0; i<9; i++) {
@ -1001,9 +1086,9 @@ Options:
return 1;
}
var perms = getPerms(st.perms,(st.type == stdio.types.FT_DIR));
var mode = getMode(st.st_mode,(st.type == stdio.types.FT_DIR));
if (!stdio.chmod(file,perms)) {
if (!stdio.chmod(file,mode)) {
stdio.fprintf(io.stderr,'cannot write file: %s\n',short);
return 1;
}
@ -1608,36 +1693,6 @@ Options:
`);
}
// TODO: this
// -rwxrwxrwx
function checkReadable(fuid,fgid,perms) {
if (perms[7] == 'r')
return true;
if (perms[4] == 'r' && fgid == stdlib.getgid())
return true;
if (perms[1] == 'r' && fuid == stdlib.getuid())
return true;
return false;
}
function checkWritable(fuid,fgid,perms) {
if (perms[8] == 'w')
return true;
if (perms[5] == 'w' && fgid == stdlib.getgid())
return true;
if (perms[2] == 'w' && fuid == stdlib.getuid())
return true;
return false;
}
function checkExecutable(fuid,fgid,perms) {
if (perms[9] == 'x')
return true;
if (perms[6] == 'x' && fgid == stdlib.getgid())
return true;
if (perms[3] == 'x' && fuid == stdlib.getuid())
return true;
return false;
}
function main(args) {
var negate = false;
if (args.length == 1)
@ -1777,12 +1832,16 @@ Options:
break;
case '-r':
var p = clite.resolvePath(uargs[1]);
var st = stdio.stat(p);
if (!st || !checkReadable(st.st_uid,st.st_gid,st.perms)) {
var fd = stdio.open(p,stdio.flags.O_RDONLY|stdio.flags.O_SYNC);
if (!fd || !stdio.isreadable(fd)) {
if (fd)
stdio.close(fd);
if (negate)
return 0;
return 1;
}
if (fd)
stdio.close(fd);
if (negate)
return 1;
return 0;
@ -1846,24 +1905,32 @@ Options:
break;
case '-w':
var p = clite.resolvePath(uargs[1]);
var st = stdio.stat(p);
if (!st || !checkWritable(st.st_uid,st.st_gid,st.perms)) {
var fd = stdio.open(p,stdio.flags.O_RDONLY|stdio.flags.O_SYNC);
if (!fd || !stdio.iswritable(fd)) {
if (fd)
stdio.close(fd);
if (negate)
return 0;
return 1;
}
if (fd)
stdio.close(fd);
if (negate)
return 1;
return 0;
break;
case '-x':
var p = clite.resolvePath(uargs[1]);
var st = stdio.stat(p);
if (!st || !checkExecutable(st.st_uid,st.st_gid,st.perms)) {
var fd = stdio.open(p,stdio.flags.O_RDONLY|stdio.flags.O_SYNC);
if (!fd || !stdio.isexecutable(fd)) {
if (fd)
stdio.close(fd);
if (negate)
return 0;
return 1;
}
if (fd)
stdio.close(fd);
if (negate)
return 1;
return 0;

View file

@ -135,7 +135,7 @@ var clite = {
return true;
}
};
n.perms = 'crw-rw-rw-';
n.mode = clite.lib.modestr('crw-rw-rw-');
n.data.isdev = true;
}
// /dev/null - writing to it goes nowhere, reading from it is always null
@ -154,7 +154,7 @@ var clite = {
return true;
}
};
n.perms = 'crw-rw-rw-';
n.mode = clite.lib.modestr('crw-rw-rw-');
n.data.isdev = true;
}
// /dev/random - writing to it goes nowhere, reading from it returns a stringified random number (integer)
@ -171,7 +171,7 @@ var clite = {
},
write:null
};
n.perms = 'crw-rw-rw-';
n.mode = clite.lib.modestr('crw-rw-rw-');
n.data.isdev = true;
}
// /dev/initctl - writing to it sets the runlevel, reading from it returns the current runlevel
@ -214,7 +214,7 @@ var clite = {
return false;
}
};
n.perms = 'crw-rw-rw-';
n.mode = clite.lib.modestr('crw-rw-rw-');
n.data.isdev = true;
}
// /dev/console - an interface for the system console - required by posix/sus, currently no op
@ -229,7 +229,7 @@ var clite = {
read:clite.console.read,
write:clite.console.write
};
n.perms = 'crw-rw-rw-';
n.mode = clite.lib.modestr('crw-rw-rw-');
n.data.isdev = true;
}
// /dev/tty - virtual device that always acts like the controlling terminal
@ -244,7 +244,7 @@ var clite = {
read:clite.tty.read,
write:clite.tty.write
};
n.perms = 'crw-rw-rw-';
n.mode = clite.lib.modestr('crw-rw-rw-');
n.data.isdev = true;
n.data.istty = true;
}
@ -262,7 +262,7 @@ var clite = {
},
write:null
};
n.perms = 'crw-rw-rw-';
n.mode = clite.lib.modestr('crw-rw-rw-');
n.data.isdev = true;
}
return true;
@ -279,7 +279,7 @@ var clite = {
n.data.content = `
PATH=/bin
`;
n.perms = '-rw-r--r--';
n.mode = clite.lib.modestr('-rw-r--r--');
// /etc/passwd contains user account details
vfsapi.mkFile(0,'/etc/passwd');
var n = vfsapi.getNode(0,'/etc/passwd');
@ -292,7 +292,7 @@ root:x:0:0:root:/root:/bin/sh
guest:x:1:1:guest:/usr/home/guest:/bin/sh
`;
// TODO: check cookies for a local user
n.perms = '-rw-r--r--';
n.mode = clite.lib.modestr('-rw-r--r--');
// /etc/passwd contains user account details
vfsapi.mkFile(0,'/etc/group');
var n = vfsapi.getNode(0,'/etc/group');
@ -305,7 +305,7 @@ root:x:0:
guest:x:1:
`;
// TODO: check cookies for a local user
n.perms = '-rw-r--r--';
n.mode = clite.lib.modestr('-rw-r--r--');
// /etc/greeting is displayed by the shell after login
vfsapi.mkFile(0,'/etc/greeting');
var n = vfsapi.getNode(0,'/etc/greeting');
@ -321,7 +321,7 @@ guest:x:1:
| |____| |____ _| |_| || __/
\\_____|______|_____|\\__\\___|
`;
n.perms = '-rw-r--r--';
n.mode = clite.lib.modestr('-rw-r--r--');
// /etc/shrc shell startup file
vfsapi.mkFile(0,'/etc/shrc');
var n = vfsapi.getNode(0,'/etc/shrc');
@ -332,7 +332,7 @@ guest:x:1:
n.data.content =`#!/bin/sh
cat /etc/greeting
`;
n.perms = '-rwxr-xr-x';
n.mode = clite.lib.modestr('-rwxr-xr-x');
}
function loadCommands(nextfn) {
@ -343,13 +343,13 @@ cat /etc/greeting
var f = vfsapi.getNode(0,'/bin/'+name);
if (!f)
return;
f.perms = '-rwxr-xr-x';
f.mode = clite.lib.modestr('-rwxr-xr-x');
f.data.content = fn;
vfsapi.mkFile(0,'/usr/src/'+name+'.js');
f = vfsapi.getNode(0,'/usr/src/'+name+'.js');
if (!f)
return;
f.perms = '-rw-rw-r--';
f.mode = clite.lib.modestr('-rw-rw-r--');
f.data.content = 'function main'+fn.toString().substring(8);
}
}
@ -383,13 +383,13 @@ cat /etc/greeting
var f = vfsapi.getNode(0,'/lib/'+name+'.so');
if (!f)
return;
f.perms = '-rw-r--r--';
f.mode = clite.lib.modestr('-rw-r--r--');
f.data.content = fn;
vfsapi.mkFile(0,'/usr/src/libs/'+name+'.js');
f = vfsapi.getNode(0,'/usr/src/libs/'+name+'.js');
if (!f)
return;
f.perms = '-rw-rw-r--';
f.mode = clite.lib.modestr('-rw-rw-r--');
f.data.content = 'function init'+fn.toString().substring(8);
clite.libs.index.push({header:header,file:name});
}
@ -452,7 +452,7 @@ license.txt:/etc/license:0:0:-rw-r--r--`;
return;
}
n.data.content = data;
n.perms = 'cr--r--r--';
n.mode = clite.lib.modestr('cr--r--r--');
n.data.isdev = true;
var fd = clite.io.open(0,'/dev/wfs',clite.io.flags.O_RDONLY|clite.io.flags.O_SYNC);
var l;
@ -481,7 +481,7 @@ license.txt:/etc/license:0:0:-rw-r--r--`;
}
if (!fn)
continue;
fn.perms = perms;
fn.mode = clite.lib.modestr(perms);
fn.uid = uid;
fn.gid = gid;
fn.name = clite.lib.basename(path);
@ -913,7 +913,7 @@ clite.user = {
vfsapi.mkDir(0,'/usr/home/guest');
var n = vfsapi.getNode(0,'/usr/home/guest');
if (n) {
n.perms = '-rwx------';
n.mode = clite.lib.modestr('drwx------');
n.uid = 1;
n.gid = 1;
}
@ -923,7 +923,7 @@ clite.user = {
n = vfsapi.getNode(1,'/usr/home/guest/.shrc');
if (!n)
return;
n.perms = '-rwx------';
n.mode = clite.lib.modestr('-rwx------');
n.uid = 1;
n.gid = 1;
n.data.content = `#!/bin/sh
@ -995,40 +995,6 @@ clite.io = {
init:function() {
var vfsapi = clite.vfs.getApi();
var perms = {
// -rwxrwxrwx user1-3,group4-6,other7-9
checkReadable:function(p,nuid,ngid,pid) {
var uid = clite.proc.getUID(pid);
if (p[7] == 'r')
return true;
if (clite.user.checkGID(uid,ngid) && p[4] == 'r')
return true;
if (nuid == uid && p[1] == 'r')
return true;
return false;
},
checkWritable:function(p,nuid,ngid,pid) {
var uid = clite.proc.getUID(pid);
if (p[8] == 'w')
return true;
if (clite.user.checkGID(uid,ngid) && p[5] == 'w')
return true;
if (nuid == uid && p[2] == 'w')
return true;
return false;
},
checkExecutable:function(p,nuid,ngid,pid) {
var uid = clite.proc.getUID(pid);
if (p[9] == 'x')
return true;
if (clite.user.checkGID(uid,ngid) && p[6] == 'x')
return true;
if (nuid == uid && p[3] == 'x')
return true;
return false;
}
};
function getFileDesPre(pid,path,link) {
var uid = clite.proc.getUID(pid);
var n = vfsapi.getNode(uid,path);
@ -1048,9 +1014,9 @@ clite.io = {
callback:null
}
});
fd.canread = perms.checkReadable(fd.node.perms,fd.node.uid,fd.node.gid,pid);
fd.canwrite = perms.checkWritable(fd.node.perms,fd.node.uid,fd.node.gid,pid);
fd.canexec = perms.checkExecutable(fd.node.perms,fd.node.uid,fd.node.gid,pid);
fd.canread = clite.lib.checkNodeReadable(fd.node,pid);
fd.canwrite = clite.lib.checkNodeWritable(fd.node,pid);
fd.canexec = clite.lib.checkNodeExecutable(fd.node,pid);
return fd;
}
@ -1400,7 +1366,7 @@ clite.io = {
type:clite.lib.getFileType(fd),
st_dev:0,
st_ino:0,
st_mode:0,
st_mode:fd.node.mode,
st_nlink:0,
st_uid:fd.node.uid,
st_gid:fd.node.gid,
@ -1416,8 +1382,7 @@ clite.io = {
st_ctim:{
tv_sec:fd.node.time.change,
tv_nsec:0
},
perms:fd.node.perms
}
});
if (stat.type == clite.io.types.FT_TEXT || stat.type == clite.io.types.FT_SCRIPT)
@ -1426,43 +1391,31 @@ clite.io = {
return stat;
},
clite.io.fchmod = function(pid,fd,mode) {
if (typeof mode != 'number')
return false;
var uid = clite.proc.getUID(pid);
if (fd.node.uid != uid)
return false;
if (typeof mode !== 'string')
return false;
if (mode.length == 9) {
var c = fd.node.perms[0];
fd.node.perms = c+mode;
}else if (mode.length != 10) {
return false;
}
if (fd.node.data.isdev) {
fd.node.perms = 'c'+mode.substring(1);
}else if (fd.node.data.isdir) {
fd.node.perms = 'd'+mode.substring(1);
}else if (fd.node.data.islink) {
fd.node.perms = 'l'+mode.substring(1);
}else{
fd.node.perms = '-'+mode.substring(0);
}
mode &= ~clite.io.modes.S_IFMT;
mode |= (fd.node.mode&clite.io.modes.S_IFMT);
fd.node.mode = mode;
fd.node.time.change = clite.time.sec();
return true;
}
clite.io.chmod = function(pid,path,mode) {
var fd = getFileDes(pid,path,true,false);
var fd = getFileDesPre(pid,path,true);
return clite.io.fchmod(pid,fd,mode);
}
clite.io.isatty = function(pid,fd) {
return fd.node.data.istty;
}
clite.io.mkdir = function(pid,path,mode) {
if (typeof mode !== 'string' || mode.length < 9 || mode.length > 10)
mode = 'drwxr-xr-x';
if (mode.length == 9)
mode = 'd'+mode;
if (mode[0] != 'd')
mode = 'd'+mode.substring(0,9);
if (typeof mode != 'number')
return false;
mode &= ~clite.io.modes.S_IFMT;
mode |= clite.io.modes.S_IFDIR;
var uid = clite.proc.getUID(pid);
var r = vfsapi.mkDir(uid,path);
if (!r)
@ -1470,7 +1423,7 @@ clite.io = {
var n = vfsapi.getNode(uid,path);
if (!n)
return false;
n.perms = mode;
n.mode = mode;
return true;
}
@ -1871,6 +1824,33 @@ clite.io = {
O_TRUNC: parseInt('0x000100',16), // set file size to 0 before writing, requires O_RDWR or O_WRONLY
O_TTY_INIT: parseInt('0x0',16) // no op
},
modes:{
// permissions
S_IRWXU: parseInt('00700',8), // Read, write, execute/search by owner.
S_IRUSR: parseInt('00400',8), // Read permission, owner.
S_IWUSR: parseInt('00200',8), // Write permission, owner.
S_IXUSR: parseInt('00100',8), // Execute/search permission, owner.
S_IRWXG: parseInt('00070',8), // Read, write, execute/search by group.
S_IRGRP: parseInt('00040',8), // Read permission, group.
S_IWGRP: parseInt('00020',8), // Write permission, group.
S_IXGRP: parseInt('00010',8), // Execute/search permission, group.
S_IRWXO: parseInt('00007',8), // Read, write, execute/search by others.
S_IROTH: parseInt('00004',8), // Read permission, others.
S_IWOTH: parseInt('00002',8), // Write permission, others.
S_IXOTH: parseInt('00001',8), // Execute/search permission, others.
S_ISUID: parseInt('04000',8), // Set-user-ID on execution.
S_ISGID: parseInt('02000',8), // Set-group-ID on execution.
S_ISVTX: parseInt('01000',8), // On directories, restricted deletion flag.
// file types
S_IFMT: parseInt('110000',8), // format (file type) mask
S_IFBLK: parseInt('010000',8), // Block special
S_IFCHR: parseInt('020000',8), // Character special
S_IFIFO: parseInt('040000',8), // FIFO special
S_IFREG: parseInt('000000',8), // Regular file
S_IFDIR: parseInt('100000',8), // Directory
S_IFLNK: parseInt('200000',8), // Symbolic link
S_IFSOCK: parseInt('400000',8), // Socket
},
creat:null,
open:null,
close:null,
@ -1910,22 +1890,22 @@ clite.vfs = {
function checkCanOpen(uid,node) {
if (!uid)
return true;
if (node.perms[7] == 'r')
if ((node.mode&clite.io.modes.S_IROTH) == clite.io.modes.S_IROTH)
return true;
if (clite.user.checkGID(uid,node.gid) && node.perms[4] == 'r')
if (clite.user.checkGID(uid,node.gid) && (node.mode&clite.io.modes.S_IRGRP) == clite.io.modes.S_IRGRP)
return true;
if (node.uid == uid && node.perms[1] == 'r')
if (node.uid == uid && (node.mode&clite.io.modes.S_IRUSR) == clite.io.modes.S_IRUSR)
return true;
return false;
}
function checkCanWrite(uid,node) {
if (!uid)
return true;
if (node.perms[8] == 'w')
if ((node.mode&clite.io.modes.S_IWOTH) == clite.io.modes.S_IWOTH)
return true;
if (clite.user.checkGID(uid,node.gid) && node.perms[5] == 'w')
if (clite.user.checkGID(uid,node.gid) && (node.mode&clite.io.modes.S_IWGRP) == clite.io.modes.S_IWGRP)
return true;
if (node.uid == uid && node.perms[2] == 'w')
if (node.uid == uid && (node.mode&clite.io.modes.S_IWUSR) == clite.io.modes.S_IWUSR)
return true;
return false;
}
@ -1934,7 +1914,7 @@ clite.vfs = {
name: '',
uid: 0,
gid: 0,
perms:'-rw-r--r--',
mode:clite.io.modes.S_IRUSR|clite.io.modes.S_IWUSR|clite.io.modes.S_IRGRP|clite.io.modes.S_IROTH,
time:{
access:clite.time.sec(),
modify:clite.time.sec(),
@ -1957,7 +1937,7 @@ clite.vfs = {
vfsdata.fs = mkNode();
vfsdata.fs.data.content = [];
vfsdata.fs.data.isdir = true;
vfsdata.fs.perms = 'drwxr-xr-x';
vfsdata.fs.mode = clite.lib.modestr('drwxr-xr-x');
clite.vfs.getApi = function() {
if (clite.state.runlevel == 1)
@ -2015,7 +1995,7 @@ clite.vfs = {
n.data.parent = parent;
n.data.content = [];
n.data.isdir = true;
n.perms = 'drwxr-xr-x';
n.mode = clite.lib.modestr('drwxr-xr-x');
n.uid = uid;
n.gid = clite.user.getGID(uid);
parent.data.content.push(n);
@ -2039,7 +2019,7 @@ clite.vfs = {
n.name = name;
n.data.parent = parent;
n.data.content = '';
n.perms = '-rw-r--r--';
n.mode = clite.lib.modestr('-rw-r--r--');
n.uid = uid;
n.gid = clite.user.getGID(uid);
parent.data.content.push(n);
@ -2064,7 +2044,7 @@ clite.vfs = {
n.data.parent = parent;
n.data.islink = true;
n.data.content = target;
n.perms = 'lrw-r--r--';
n.mode = clite.lib.modestr('lrw-r--r--');
n.uid = uid;
n.gid = clite.user.getGID(uid);
parent.data.content.push(n);
@ -2127,7 +2107,7 @@ clite.vfs = {
var n = vfsdata.api.getNode(0,'/tmp');
if (n)
n.perms = 'drwxrwxrwx';
n.mode = clite.lib.modestr('drwxrwxrwt');
clite.io.init();
vfsdata.api.isinit = true;
@ -2311,7 +2291,7 @@ clite.tty = {
read:function(cb) {return clite.tty.read(n.data.content.ttyid,cb);},
write:function(data) {return clite.tty.write(n.data.content.ttyid,data);}
};
n.perms = 'crw-rw-rw-';
n.mode = clite.lib.modestr('crw-rw-rw-');
n.data.isdev = true;
n.data.istty = true;
@ -2683,6 +2663,216 @@ clite.lib = {
}
return clite.io.types.FT_UNKOWN;
},
checkNodeReadable:function(node,pid) {
var uid = clite.proc.getUID(pid);
if ((node.mode&clite.io.modes.S_IROTH) == clite.io.modes.S_IROTH)
return true;
if (clite.user.checkGID(uid,node.gid) && (node.mode&clite.io.modes.S_IRGRP) == clite.io.modes.S_IRGRP)
return true;
if (node.uid == uid && (node.mode&clite.io.modes.S_IRUSR) == clite.io.modes.S_IRUSR)
return true;
return false;
},
checkNodeWritable:function(node,pid) {
var uid = clite.proc.getUID(pid);
if (node.uid == uid && (node.mode&clite.io.modes.S_IWUSR) == clite.io.modes.S_IWUSR)
return true;
// check for directory sticky bit on parent
if (node.parent && (node.parent.mode&clite.io.modes.S_ISVTX) == clite.io.modes.S_ISVTX && node.uid != uid)
return false;
if ((node.mode&clite.io.modes.S_IWOTH) == clite.io.modes.S_IWOTH)
return true;
if (clite.user.checkGID(uid,node.gid) && (node.mode&clite.io.modes.S_IWGRP) == clite.io.modes.S_IWGRP)
return true;
return false;
},
checkNodeExecutable:function(node,pid) {
var uid = clite.proc.getUID(pid);
if ((node.mode&clite.io.modes.S_IXOTH) == clite.io.modes.S_IXOTH)
return true;
if (clite.user.checkGID(uid,node.gid) && (node.mode&clite.io.modes.S_IXGRP) == clite.io.modes.S_IXGRP)
return true;
if (node.uid == uid && (node.mode&clite.io.modes.S_IXUSR) == clite.io.modes.S_IXUSR)
return true;
return false;
},
// creates a string from a file mode (0777 -> -rwxrwxrwx)
strmode:function(mode) {
var str = mode.toString(8);
var t = '0';
var s = '0';
var su = false;
var sg = false;
var sd = false;
var p = '';
var perms = ['---','---','---'];
str = str.padStart(3,'0');
if (str.length > 4) {
t = str.substring(0,str.length-4);
str = str.substring(t.length);
}
t = t.padStart(2,'0');
if (str.length == 4) {
s = str.substring(0,1);
str = str.substring(1);
}
if (s != '0') {
var si = parseInt(s.padEnd(4,'0'),8);
if ((si & clite.io.modes.S_ISUID) == clite.io.modes.S_ISUID)
su = true;
if ((si & clite.io.modes.S_ISGID) == clite.io.modes.S_ISGID)
sg = true;
if ((si & clite.io.modes.S_ISVTX) == clite.io.modes.S_ISVTX)
sd = true;
}
switch (t) {
case '01':
p = 'b';
break;
case '02':
p = 'c';
break;
case '04':
p = 'f';
break;
case '10':
p = 'd';
break;
case '20':
p = 'l';
break;
case '40':
p = 's';
break;
case '00':
default:
p = '-';
}
for (var i=0; i<str.length; i++) {
switch(str[i]) {
case '0':
perms[i] = '---';
break;
case '1':
perms[i] = '--x';
break;
case '2':
perms[i] = '-w-';
break;
case '3':
perms[i] = '-wx';
break;
case '4':
perms[i] = 'r--';
break;
case '5':
perms[i] = 'r-x';
break;
case '6':
perms[i] = 'rw-';
break;
case '7':
perms[i] = 'rwx';
break;
}
}
if (su) {
if (perms[0][2] == 'x') {
perms[0] = perms[0].substring(0,2)+'s';
}else{
perms[0] = perms[0].substring(0,2)+'S';
}
}
if (sg) {
if (perms[1][2] == 'x') {
perms[1] = perms[1].substring(0,2)+'s';
}else{
perms[1] = perms[1].substring(0,2)+'S';
}
}
if (sd) {
if (perms[2][2] == 'x') {
perms[2] = perms[2].substring(0,2)+'t';
}else{
perms[2] = perms[2].substring(0,2)+'T';
}
}
return p+perms.join('');
},
// creates a file mode from a string (-rwxrwxrwx -> 0777)
modestr:function(perms) {
var m = 0;
perms = perms.padStart(10,'-');
if (perms[0] != '-') {
switch (perms[0]) {
case 'b':
m |= clite.io.modes.S_IFBLK;
break;
case 'c':
m |= clite.io.modes.S_IFCHR;
break;
case 'f':
m |= clite.io.modes.S_IFIFO;
break;
case 'd':
m |= clite.io.modes.S_IFDIR;
break;
case 'l':
m |= clite.io.modes.S_IFLNK;
break;
case 's':
m |= clite.io.modes.S_IFSOCK;
break;
default:;
}
}
if (perms[1] == 'r')
m |= clite.io.modes.S_IRUSR;
if (perms[2] == 'w')
m |= clite.io.modes.S_IWUSR;
if (perms[3] == 'x')
m |= clite.io.modes.S_IXUSR;
if (perms[3] == 'S')
m |= clite.io.modes.S_ISUID;
if (perms[3] == 's') {
m |= clite.io.modes.S_IXUSR;
m |= clite.io.modes.S_ISUID;
}
if (perms[4] == 'r')
m |= clite.io.modes.S_IRGRP;
if (perms[5] == 'w')
m |= clite.io.modes.S_IWGRP;
if (perms[6] == 'x')
m |= clite.io.modes.S_IXGRP;
if (perms[6] == 'S')
m |= clite.io.modes.S_ISGID;
if (perms[6] == 's') {
m |= clite.io.modes.S_IXGRP;
m |= clite.io.modes.S_ISGID;
}
if (perms[7] == 'r')
m |= clite.io.modes.S_IROTH;
if (perms[8] == 'w')
m |= clite.io.modes.S_IWOTH;
if (perms[9] == 'x')
m |= clite.io.modes.S_IXOTH;
if (perms[9] == 'T')
m |= clite.io.modes.S_ISVTX;
if (perms[9] == 't') {
m |= clite.io.modes.S_IXOTH;
m |= clite.io.modes.S_ISVTX;
}
return m;
},
fork:function(env,io,call) {
var pid = clite.proc.add(io.pid,call);
if (!pid)

View file

@ -128,6 +128,13 @@ return Object.create({
if (typeof ptr.value === 'undefined')
return null;
return ptr.value;
},
strmode:function(mode) {
return clite.lib.strmode(mode);
},
modestr:function(perms) {
return clite.lib.modestr(perms);
}
});

View file

@ -10,6 +10,7 @@ return Object.create({
types:clite.io.types,
flags:clite.io.flags,
modes:clite.io.modes,
creat:function(path,type) {
return clite.io.creat(io.pid,path,type);
@ -92,6 +93,15 @@ return Object.create({
isatty:function(fd) {
return clite.io.isatty(io.pid,fd);
},
isreadable(fd) {
return clite.lib.checkNodeReadable(fd.node,io.pid);
},
iswritable(fd) {
return clite.lib.checkNodeWritable(fd.node,io.pid);
},
isexecutable(fd) {
return clite.lib.checkNodeExecutable(fd.node,io.pid);
},
mkdir:function(path,mode) {
return clite.io.mkdir(io.pid,path,mode);

View file

@ -131,6 +131,52 @@ clite (libclite.so): io.include('clite')
clite.strToArgs('ls -l /var') -> ['ls','-l','var']
strmode(mode)
returns a string representation of a file mode such as '-rw-rw-r--';
modestr('string')
returns a file mode generated from a permissions string.
The permission string is a 9 or 10 character string describing the
file permissions. The optional first character describes the
file type, and cannot be changed by calls to chmod(). Attempting
to change the first character will not cause the function to
fail, but only the permissions will be changed.
10 character string: -rwxrwxrwx
9 character string: rwxrwxrwx
After the optional first character, the mode string is comprised
of 3 sets of permissions for Read, Write, and eXecute, one each
for the user, group, and others.
- file type
rwx permissions for the file's owner
rwx permissions for users in the file's group
rwx permissions for other users
Replacing any of the permissions with a dash '-' indicate the
permission is not set:
-rwxr-xr--
The user has all permissions, the group has read and execute
permissions, others have only read permissions.
setuid, setgid are represented by an 's' in the respective
execute field:
-rwsr-sr-x
The file is executable by all, and the new process will run with
uid and gid set to the file's owner and group ids.
Sticky bits on directories are represented by a 't' in the other
execute field:
drwxrwxrwt
The directory is readable, writable, and searchable by all, but
only the file's owner may delete a file in the directory.
stdio (libio.so): io.include('stdio')
Provides access to io functions and types for file access
@ -166,6 +212,34 @@ stdio (libio.so): io.include('stdio')
O_TRUNC: set file size to 0 before writing, requires O_RDWR or O_WRONLY
O_TTY_INIT: no op
stdio.modes:
object containing values for creating file modes (permissions)
These values may be combined via bitwise OR to create the file permission
S_IRWXU: Read, write, execute/search by owner.
S_IRUSR: Read permission, owner.
S_IWUSR: Write permission, owner.
S_IXUSR: Execute/search permission, owner.
S_IRWXG: Read, write, execute/search by group.
S_IRGRP: Read permission, group.
S_IWGRP: Write permission, group.
S_IXGRP: Execute/search permission, group.
S_IRWXO: Read, write, execute/search by others.
S_IROTH: Read permission, others.
S_IWOTH: Write permission, others.
S_IXOTH: Execute/search permission, others.
S_ISUID: Set-user-ID on execution.
S_ISGID: Set-group-ID on execution.
S_ISVTX: On directories, restricted deletion flag.
A mode may contain one of these values to indicate the file type
S_IFMT: format (file type) mask
S_IFBLK: Block special
S_IFCHR: Character special
S_IFIFO: FIFO special
S_IFREG: Regular file
S_IFDIR: Directory
S_IFLNK: Symbolic link
S_IFSOCK: Socket
creat('path','-')
creates a new file at path
returns true on success
@ -298,18 +372,11 @@ stdio (libio.so): io.include('stdio')
var st = stdio.fstatat(fd,0);
Stat object contents:
st.name: string containing the file name
st.type: file type identifier, see stdio.types above for more info
st.uid: numeric id of the file owner
st.gid: numeric id of the file group
st.size: file size, or 0 for non text files
st.perms: the permissions string for the file, see chmod below.
st.name: string containing the file namefd.node.name,
st.type: file type identifier, see stdio.types above for more info
st.st_dev: device id, always 0
st.st_ino: file serial number, always 0
st.st_mode: future integer mode (permission) value
st.st_mode: integer mode (permissions) value
st.st_nlink: number of hard links to the file, always 0
st.st_uid: numeric id of the file owner
st.st_gid: numeric id of the file group
@ -317,36 +384,15 @@ stdio (libio.so): io.include('stdio')
st.st_atim: timeval object, the file's last access time
st.st_mtim: timeval object, the file's last modify time
st.st_ctim: timeval object, the file's last change time
st.perms: the permissions string for the file, see chmod below.
chmod('path','mode')
fchmod(fd,'mode')
chmod('path',mode)
fchmod(fd,mode)
Change a file's mode (permissions).
Returns true on success.
The mode string is a 9 or 10 character string describing the
file permissions. The optional first character describes the
file type, and cannot be changed. Attempting to change the first
character will not cause the function to fail, but only the
permissions will be changed.
10 character string: -rwxrwxrwx
9 character string: rwxrwxrwx
After the option first character, the mode string is comprised of
3 sets of permissions for Read, Write, and eXecute, one each for
the user, group, and others.
rwx permissions for the file's owner
rwx permissions for users in the file's group
rwx permissions for other users
Replacing any of the permissions with a dash '-' will remove that
permission from that set:
rwxr-xr--
The user has all permissions, the group has read and execute
permissions, others have only read permissions.
mode is an integer value made from a bitwise OR of values in
stdio.modes. Alternatively, the mode can be generated by passing
a permissions string to clite.modestr().
isatty(fd)
returns true if fd refers to a tty.