duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

commit 8299f1f50b3197849fdc756af9ce50045e916720
parent 211e202c9e1348e82a7ddaa229bb5fb1e501ee8f
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Thu,  4 Aug 2022 09:05:12 -0400

cvm: add FS support

Diffstat:
Mposix/tmpboot.fs | 3+--
Mposix/vm.c | 121+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
2 files changed, 113 insertions(+), 11 deletions(-)

diff --git a/posix/tmpboot.fs b/posix/tmpboot.fs @@ -125,5 +125,4 @@ alias noop [then] \ doc comment placeholder alias \ \\ -: foo S" Bootlo compiles!" stype ; -foo bye +0 S" lib" fchild S" nfmt.fs" fchild fopen 20 over _freadbuf rtype _fclose bye diff --git a/posix/vm.c b/posix/vm.c @@ -11,6 +11,8 @@ The VM is little endian. #include <stdio.h> #include <unistd.h> #include <string.h> +#include <sys/stat.h> +#include <fcntl.h> #define MEMSZ 0x100000 // 1MB #define STACKSZ 0x800 @@ -25,7 +27,8 @@ The VM is little endian. #define EMIT (INRD+4) #define ABORT (EMIT+4) #define CURWORD (ABORT+4) -#define HEREMAX SYSVARS +#define IOBUF (SYSVARS-0x400) +#define HEREMAX IOBUF typedef uint8_t byte; @@ -115,9 +118,9 @@ static void toexec(dword a) { } // Operations -/* The VM works in a simple manner. PC starts at 0. The VM reads the byte -where PC points to in memory, increases PC by 1 and executes the corresponding -function in the function list below. As simple as this. */ +/* The VM works in a simple manner. The VM reads the byte where PC points to in +memory, increases PC by 1 and executes the corresponding function in the +function list below. As simple as this. */ static void JUMP() { // op: 00 vm.PC = gpc(); @@ -697,7 +700,106 @@ static void EXIT() { // op: 5c rpop(); } -#define OPCNT 0x5d +/* Filesystem + +At POSIX level, we don't have access to the underlying FS structure such as +inodes, making Dusk's 32-bit "ID" system a bit awkward. What we're going to do +here is have a buffer of all requested paths, and the index in that buffer will +be our ID. +*/ +#define MAXPATHSZ 0x100 +#define FSIDCNT 0x200 +static char fsids[FSIDCNT][MAXPATHSZ] = {0}; + +static dword findpath(char *path) { + for (dword i=0; i<FSIDCNT; i++) { + if (strcmp(path, fsids[i]) == 0) return i; + } + return 0; +} + +static int getfiledesc(dword hdl) { + return (int)(gd(hdl+20)|(((int64_t)gd(hdl+24))<<32)); +} + +static void FCHILD () { // op: 5d + dword s = ppop(); + byte len = gb(s++); + dword parent = ppop(); + char path[MAXPATHSZ] = {0}; + dword res; + if ((parent >= FSIDCNT) || !fsids[parent][0]) { + printf("Out of bounds FSID\n"); + vm.PC = gd(ABORT); + return; + } + strcpy(path, fsids[parent]); + strcat(path, "/"); + strncat(path, (char*)&vm.mem[s], len); + res = findpath(path); + if (!res) { + // Verify if path actually exists in FS, then create a new ID + struct stat sb; + if (stat(path, &sb) != 0) { // does not exist + ppush(0); + return; + } + while (fsids[++res][0]); + strcpy(fsids[res], path); + } + ppush(res); +} + +// Our handles are simply the regular IO/File preludes followed by the POSIX +// file descriptor, a 64bit int. +static void FOPEN () { // op: 5e + dword fsid = ppop(); + char *path; + int fd; + if ((fsid >= FSIDCNT) || !fsids[fsid][0]) { + printf("Out of bounds FSID\n"); + vm.PC = gd(ABORT); + return; + } + path = fsids[fsid]; + fd = open(path, 0); + if (fd == -1) { + printf("Can't open %s\n", path); + vm.PC = gd(ABORT); + return; + } + ppush(here()); // File cursor we're about to create + dwrite(find("_freadbuf")); + dwrite(find("abort")); // writebuf + dwrite(find("drop")); // flush + dwrite(find("2drop")); // seek + dwrite(find("_fclose")); // close + dwrite(fd); + dwrite((int64_t)fd>>32); +} + +static void FREADBUF () { // op: 5f + dword hdl = ppop(); + dword n = ppop(); + int res; + int fd = getfiledesc(hdl); + res = read(fd, &vm.mem[IOBUF], n); + if (res < 0) { + printf("I/O readbuf error\n"); + vm.PC = gd(ABORT); + return; + } + if (n) ppush(IOBUF); + ppush((dword)n); +} + +static void FCLOSE () { // op: 60 + dword hdl = ppop(); + int fd = getfiledesc(hdl); + close(fd); +} + +#define OPCNT 0x61 static void (*ops[OPCNT])() = { JUMP, CALL, RET, LIT, BYE, BYEFAIL, QUIT, ABORT_, EXECUTE, CELL, VAL, ALIAS, DOES, SLIT, BR, CBR, @@ -710,7 +812,8 @@ static void (*ops[OPCNT])() = { OR, XOR, BOOL, NOT, LT, SHLC, SHRC, LSHIFT, RSHIFT, LITN, EXECUTEWR, EXITWR, MOVE, MOVEWR, RTYPE, WNF, STACKCHK, MAYBEWORD, WORD, PARSE, REQ, FIND, APOS, ENTRY, - XTCOMP, DOCOL, STOPCOL, RUNWORD, EXIT}; + XTCOMP, DOCOL, STOPCOL, RUNWORD, EXIT, FCHILD, FOPEN, FREADBUF, + FCLOSE}; static char *opnames[OPCNT] = { NULL, NULL, NULL, NULL, "bye", "bytefail", "quit", "(abort)", @@ -724,7 +827,8 @@ static char *opnames[OPCNT] = { "or", "xor", "bool", "not", "<", "<<c", ">>c", "lshift", "rshift", "litn", "execute,", "exit,", "move", "move,", "rtype", "(wnf)", "stack?", "maybeword", "word", "parse", "[]=", "find", "'", "entry", - "xtcomp", ":", ";", "runword", "exit"}; + "xtcomp", ":", ";", "runword", "exit", "fchild", "fopen", "_freadbuf", + "_fclose"}; static void oprun1() { // run next op byte opcode = vm.mem[vm.PC++]; @@ -798,8 +902,7 @@ static void buildsysdict() { // Interpret loop int main() { - vm.PSP = PSTOP; - vm.RSP = RSTOP; + strcpy(fsids[0], "fs"); // Set FS root path bootfp = fopen("posix/tmpboot.fs", "r"); if (!bootfp) { printf("Can't open boot file.\n");