update open() to work as it should with flags

This commit is contained in:
Lisa Milne 2023-12-04 21:18:35 +10:00
parent c674ca0015
commit bd75d0b3c9
6 changed files with 195 additions and 67 deletions

View file

@ -96,7 +96,7 @@ Options:
dirs.forEach(function(dir,index) {
if (dirs.length > 1)
stdio.printf(dir+':');
var fd = stdio.open(dir,false);
var fd = stdio.open(dir,stdio.flags.O_RDONLY|stdio.flags.O_SYNC);
if (!fd) {
stdio.write(io.stderr,'cannot open directory: '+dir);
return;
@ -116,7 +116,7 @@ Options:
while ((e = stdio.read(fd)) != null) {
if (e[0] == '.' && !all)
continue;
var efd = stdio.open(dir+'/'+e,false,true);
var efd = stdio.open(dir+'/'+e,stdio.flags.O_RDONLY|stdio.flags.O_NOFOLLOW|stdio.flags.O_SYNC);
if (!efd) {
stdio.write(io.stderr,'cannot read contents: '+dir);
break;
@ -211,7 +211,7 @@ Options:
var d = stdio.readAll(fd);
if (d != null) {
if (download) {
var ld = stdio.open('/dev/local',false);
var ld = stdio.open('/dev/local',stdio.flags.O_WRONLY);
if (ld) {
stdio.write(ld,{name:st.name,data:d});
stdio.close(ld);
@ -248,7 +248,7 @@ Options:
pending--;
return;
}
var fd = stdio.open(file,fcb);
var fd = stdio.open(file,stdio.flags.O_RDONLY,fcb);
if (!fd) {
stdio.write(io.stderr,'cannot open file: '+file);
pending--;
@ -311,7 +311,7 @@ Options:
}
if (!stdio.creat(file)) {
var fd = stdio.open(file,loadRemote);
var fd = stdio.open(file,stdio.flags.O_RDONLY,loadRemote);
return null;
}
@ -411,7 +411,7 @@ Options:
}
fd = io.stdin;
}else{
fd = stdio.open(file,prepFile);
fd = stdio.open(file,stdio.flags.O_RDONLY,prepFile);
if (!fd) {
stdio.write(io.stderr,'could not open file: '+file);
return 1;
@ -544,7 +544,7 @@ Options:
return 1;
}
var fd = stdio.open(path,false,true);
var fd = stdio.open(path,stdio.flags.O_RDONLY|stdio.flags.O_NOFOLLOW|stdio.flags.O_SYNC);
if (!fd) {
stdio.fprintf(io.stderr,'permission denied: %s',path);
return 1;
@ -1089,7 +1089,7 @@ Options:
}
}
var fd = stdio.open('/dev/initctl',false);
var fd = stdio.open('/dev/initctl',stdio.flags.O_WRONLY|stdio.flags.O_SYNC);
if (!fd)
return 1;
stdio.write(fd,'6'); // switch to runlevel 6, reboot
@ -1196,6 +1196,10 @@ clite.commands.load('test',function(args,env,io) {
io.exit(0);
}
var fd = clite.io.openp(io.pid,'/var/logs',stdio.flags.O_RDONLY,function(fd) {
alert(fd.node.data.content);
});
stdio.read(io.stdin,rcb);
return null;

View file

@ -410,7 +410,7 @@ readme.txt:/usr/clite/readme:0:0:-rw-r--r--`;
n.data.content = data;
n.perms = 'cr--r--r--';
n.data.isdev = true;
var fd = clite.io.open(0,'/dev/wfs');
var fd = clite.io.open(0,'/dev/wfs',clite.io.flags.O_RDONLY|clite.io.flags.O_SYNC);
var l;
while ((l = clite.io.readLine(0,fd)) != null) {
if (l.length <1 || l[0] == '#')
@ -466,7 +466,7 @@ readme.txt:/usr/clite/readme:0:0:-rw-r--r--`;
return;
}
var fd = clite.io.open(0,'/dev/initctl',false);
var fd = clite.io.open(0,'/dev/initctl',clite.io.flags.O_WRONLY);
if (fd) {
clite.io.write(0,fd,'3');
clite.io.close(0,fd);
@ -484,9 +484,9 @@ readme.txt:/usr/clite/readme:0:0:-rw-r--r--`;
var env = clite.user.getEnv(1);
var io = {
pid:0,
stdin:clite.io.open(1,'/dev/tty',false),
stdout:clite.io.open(1,'/dev/tty',false),
stderr:clite.io.open(1,'/dev/tty',false),
stdin:clite.io.open(1,'/dev/tty',clite.io.flags.O_RDONLY),
stdout:clite.io.open(1,'/dev/tty',clite.io.flags.O_WRONLY),
stderr:clite.io.open(1,'/dev/tty',clite.io.flags.O_WRONLY),
exit:null, // filled in by fork()
include:null, // filled in by fork()
};
@ -630,7 +630,7 @@ clite.proc = {
// special case, reboot if pid 1 exits
if (pid == 1) {
clite.core.execSafeAsync(function() {
var fd = clite.io.open(0,'/dev/initctl',false);
var fd = clite.io.open(0,'/dev/initctl',clite.io.flags.O_WRONLY);
if (!fd) {
clite.core.reboot();
return;
@ -906,7 +906,7 @@ clite.io = {
}
};
function getFileDes(pid,path,link,cb) {
function getFileDesPre(pid,path,link) {
var uid = clite.proc.getUID(pid);
var n = vfsapi.getNode(uid,path);
if (!n)
@ -922,28 +922,39 @@ clite.io = {
canexec:false,
remote:{
ispending:p,
callback:cb
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);
if (cb == false) {
fd.remote.callback = null;
}else if (p) {
clite.core.load.file(n.data.remote,function(d) {
n.data.content = d;
fd.remote.ispending = false;
try{
fd.remote.callback(fd);
} catch(err) {}
});
}
if (!p && fd.remote.callback != null) {
clite.core.execSafeAsync(function() {fd.remote.callback(fd);});
return fd;
}
function getFileDesPost(fd,cb) {
if (typeof cb === 'function') {
fd.remote.callback = cb;
if (fd.remote.ispending) {
clite.core.load.file(n.data.remote,function(d) {
n.data.content = d;
fd.remote.ispending = false;
try{
fd.remote.callback(fd);
} catch(err) {}
});
}else{
clite.core.execSafeAsync(function() {fd.remote.callback(fd);});
}
}
return fd;
}
function getFileDes(pid,path,link,cb) {
var fd = getFileDesPre(pid,path,link);
if (!fd)
return null;
return getFileDesPost(fd,cb);
}
clite.io.creat = function(pid,path,type) {
var uid = clite.proc.getUID(pid);
switch (type) {
@ -957,12 +968,108 @@ clite.io = {
return vfsapi.mkFile(uid,path);
}
}
clite.io.open = function(pid,path,cb,open_link) {
if (typeof cb === 'undefined')
// TODO: get rid of this
//clite.io.open = function(pid,path,cb,open_link) {
//if (typeof cb === 'undefined')
//cb = false;
//if (typeof open_link === 'undefined')
//open_link = false;
//return getFileDes(pid,path,open_link,cb);
//}
clite.io.open = function(pid,path,flags,cb) {
var read = false;
var write = false;
var exec = false;
var search = false;
var append = false;
var create = false;
var directory = false;
var excl = false;
var nofollow = false;
var nonblock = false;
var trunc = false;
if ((flags&clite.io.flags.O_RDONLY) == clite.io.flags.O_RDONLY)
read = true;
if ((flags&clite.io.flags.O_WRONLY) == clite.io.flags.O_WRONLY)
write = true;
if ((flags&clite.io.flags.O_EXEC) == clite.io.flags.O_EXEC)
exec = true;
if ((flags&clite.io.flags.O_SEARCH) == clite.io.flags.O_SEARCH)
search = true;
// must have one of these set at least
if (!read && !write && !exec && !search)
return null;
if ((flags&clite.io.flags.O_APPEND) == clite.io.flags.O_APPEND) {
if (!read)
return null;
append = true;
}
if ((flags&clite.io.flags.O_CREAT) == clite.io.flags.O_CREAT)
create = true;
if ((flags&clite.io.flags.O_DIRECTORY) == clite.io.flags.O_DIRECTORY)
directory = true;
if ((flags&clite.io.flags.O_EXCL) == clite.io.flags.O_EXCL)
excl = true;
if ((flags&clite.io.flags.O_NOFOLLOW) == clite.io.flags.O_NOFOLLOW)
nofollow = true;
if ((flags&clite.io.flags.O_SYNC) == clite.io.flags.O_SYNC)
cb = false;
if (typeof open_link === 'undefined')
open_link = false;
return getFileDes(pid,path,open_link,cb);
if ((flags&clite.io.flags.O_TRUNC) == clite.io.flags.O_TRUNC)
trunc = true;
var fd = getFileDesPre(pid,path,nofollow);
if (!fd) {
if (create) {
if (directory) {
if (!clite.io.mkdir(pid,path))
return null;
}else{
if (!clite.io.creat(pid,path,'-'))
return null;
}
fd = getFileDesPre(pid,path,nofollow);
}
if (!fd)
return null;
}else if (create && excl) {
return null;
}
var type = clite.lib.getFileType(fd);
if (directory) {
if (type != clite.io.types.FT_DIR)
return null;
if (read || search) {
if (!fd.canread || !fd.canexec)
return null
}else{
fd.canread = false;
}
if (write)
return null;
return getFileDesPost(fd,cb);
}
// check again (search is only for directories, and is basically read)
if (!read && !write && !exec)
return null;
if (trunc && write) {
if (type == clite.io.types.FT_SCRIPT || type == clite.io.types.FT_TEXT) {
fd.node.data.content = '';
}else if (type == clite.io.types.FT_REMOTE) {
return null; // cannot truncate unloaded remote data
}
}
return getFileDesPost(fd,cb);
}
clite.io.close = function(pid,fd) {
try{
@ -1553,7 +1660,6 @@ clite.io = {
})
str = str.replace(/&percnt;/g,'%');
// TODO: actually support formatting
return clite.io.write(pid,fd,str);
}
},
@ -1579,6 +1685,26 @@ clite.io = {
FT_IMAGE:8,
FT_LIBRARY:9
},
flags:{
// at least one of these
O_EXEC: parseInt('0x010000',16), // open for executing only, no op on directories
O_RDONLY: parseInt('0x020000',16), // open for reading only
O_RDWR: parseInt('0x060000',16), // open for reading and writing
O_SEARCH: parseInt('0x080000',16), // open for directory search only, no op on non-directories
O_WRONLY: parseInt('0x040000',16), // open for writing only
// any of these
O_APPEND: parseInt('0x000001',16), // append to the file, sets pos to content.length, requires O_RDONLY or O_RDWR
O_CLOEXEC: parseInt('0x000002',16), // close on exec
O_CREAT: parseInt('0x000004',16), // create if file does not exist
O_DIRECTORY: parseInt('0x000008',16), // only open if directory
O_EXCL: parseInt('0x000010',16), // if O_CREAT is set, fail if file exists
O_NOCTTY: parseInt('0x0',16), // no op
O_NOFOLLOW: parseInt('0x000020',16), // if file is a symlink, don't follow it
O_NONBLOCK: parseInt('0x000040',16), // no callbacks, return immediately
O_SYNC: parseInt('0x000080',16), // write immediately (may fail on remote data)
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
},
creat:null,
open:null,
close:null,
@ -2228,7 +2354,7 @@ clite.lib = {
if (file == '')
return null;
var fd = clite.io.open(0,'/lib/'+file+'.so',false);
var fd = clite.io.open(0,'/lib/'+file+'.so',clite.io.flags.O_RDONLY);
if (!fd)
return null;
@ -2247,7 +2373,7 @@ clite.lib = {
return pid;
},
exec:function(path,args,env,io) {
var fd = clite.io.open(io.pid,path,false);
var fd = clite.io.open(io.pid,path,clite.io.flags.O_RDONLY|clite.io.flags.O_EXEC|clite.io.flags.O_SYNC);
if (!fd)
return -1;

View file

@ -5,13 +5,14 @@ clite.libs.load('libio','stdio',function(io,env) {
return Object.create({
types:clite.io.types,
flags:clite.io.flags,
creat:function(path,type) {
return clite.io.creat(io.pid,path,type);
},
open:function(path,cb,open_link) {
return clite.io.open(io.pid,path,cb,open_link);
open:function(path,flags,cb) {
return clite.io.open(io.pid,path,flags,cb);
},
close:function(fd) {

View file

@ -17,11 +17,12 @@ clite.commands.load('sh',function(args,env,io) {
if (args.length > 1) {
dir = clite.resolvePath(args[1]);
}
var fd = stdio.open(dir,false);
var fd = stdio.open(dir,stdio.flags.O_SEARCH|stdio.flags.O_DIRECTORY);
if (!fd) {
stdio.write(io.stderr,'invalid directory: '+dir);
return;
}
// shouldn't need this now
if (!fd.node.data.isdir) {
stdio.write(io.stderr,'invalid directory: '+dir);
return;
@ -140,9 +141,8 @@ clite.commands.load('sh',function(args,env,io) {
if (path)
return;
var rp = clite.resolvePath(txt,p);
var fd = stdio.open(rp,false);
if (fd) {
stdio.close(fd);
var st = stdio.stat(rp);//open(rp,stdio.flags.O_RDONLY|stdio.flags.O_SYNC);
if (st) {
path = rp;
}
});
@ -223,7 +223,7 @@ clite.commands.load('sh',function(args,env,io) {
pparts.forEach(function(pp) {
if (add != '')
return;
var fd = stdio.open('/bin',false);
var fd = stdio.open('/bin',stdio.flags.O_SEARCH|stdio.flags.O_DIRECTORY);
var f;
while (add == '' && (f = stdio.read(fd)) != null) {
if (f.substring(0,a.length) == a) {
@ -382,12 +382,12 @@ clite.commands.load('sh',function(args,env,io) {
// otherwise we have an interactive shell
// so run /etc/shrc and ~/.shrc
}else{
var fd = stdio.open('/etc/shrc',false);
var fd = stdio.open('/etc/shrc',stdio.flags.O_RDONLY|stdio.flags.O_SYNC);
if (fd) {
parseScript(fd);
stdio.close(fd);
}
fd = stdio.open(env.HOME+'/.shrc',false);
fd = stdio.open(env.HOME+'/.shrc',stdio.flags.O_RDONLY|stdio.flags.O_SYNC);
if (fd) {
parseScript(fd);
stdio.close(fd);

View file

@ -150,7 +150,7 @@ Options:
}
function writeFile(force) {
var fd = stdio.open(file,false);
var fd = stdio.open(file,stdio.flags.O_WRONLY|stdio.flags.O_TRUNC,stdio.flags.O_SYNC);
if (!fd)
return;
var data = '';
@ -249,17 +249,10 @@ Options:
return 1;
}
var fd = stdio.open(file,prepFile);
var fd = stdio.open(file,stdio.flags.O_RDONLY|stdio.flags.O_CREAT,prepFile);
if (!fd) {
if (!stdio.creat(file,'-')) {
stdio.write(io.stderr,'could not open file: '+file);
return 1;
}
fd = stdio.open(file,prepFile);
if (!fd) {
stdio.write(io.stderr,'could not open file: '+file);
return 1;
}
stdio.write(io.stderr,'could not open file: '+file);
return 1;
}
curses.initscr();

View file

@ -8,7 +8,7 @@ var stdio = io.include('stdio');
This returns a reference to the library which can be stored in a variable as
seen above. Calls to library functions can then be made using that reference:
stdio.open('/path/to/file');
var fd = stdio.open('/path/to/file',stdio.flags.O_RDONLY);
There is no need to name the variable the same as the library name, however
this is considered good practice.
@ -130,25 +130,29 @@ stdio (libio.so): io.include('stdio')
FT_SCRIPT: 7 Plain text file beginning with #!
FT_IMAGE: 8 Image file, specifically a javascript Image object
stdio.flags:
object containing flags for use in io functions
creat('path','-')
creates a new file at path
returns true on success
open('path',callback,open_link)
open('path',flags,callback)
Open the file at path, returns a file descriptor.
On error returns null, and calls callback(null) if set.
If callback is set, will call the function at callback with the
file descriptor, this allows remote data to be loaded for the
file before beginning read or write operations.
If callback is false, open will return directly, without loading
remote data.
If open_link is set and true, and 'path' is a symbolic link, the
returned file descriptor is for the link, not the file pointed to.
If callback is false or not set, open will return directly, without loading
remote data. this is equivalent to setting stdio.flags.O_SYNC in flags.
flags is a bitwise or group of flags from stdio.flags.O_*. Consisting
of at least one mode (O_RDONLY/O_RDWR/O_WRONLY/O_SEARCH/O_EXEC),
and any other flag or flags.
var fd = stdio.open('path',false); // opens the file without loading data
var fd = stdio.open('path',callback); // calls callback(fd) when data is loaded
var fd = stdio.open('path',callback,true); // as above, but will not follow a link
var fd = stdio.open('path'); // as a general rule, don't do this
var fd = stdio.open('path',stdio.flags.O_RDONLY|stdio.flags.O_SYNC); // opens the file without loading data
var fd = stdio.open('path',stdio.flags.O_RDONLY,callback); // calls callback(fd) when data is loaded
var fd = stdio.open('path',stdio.flags.O_RDONLY|stdio.flags.O_NOFOLLOW,callback); // as above, but will not follow a link
var fd = stdio.open('path'); // fails without a valid mode (O_RDONLY/O_RDWR/O_WRONLY/O_SEARCH/O_EXEC)
close(fd)
Closes a file opened with open()