duskos

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

commit 79f180c3e50925f3cf8dcb2c335ca01e7622c0a9
parent c9a368e3c99fab8e6f5d8299332b8bff1563357d
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Fri, 19 Aug 2022 15:32:39 -0400

Add Filesystem :remove

This allows tests that write to the filesystem to cleanly run on the host
machine, so I could move some of these tests from tests/fs/fat to
tests/sys/file.

Diffstat:
Mfs/fs/fatlo.fs | 1+
Mfs/sys/file.fs | 1+
Mfs/tests/fs/fat.fs | 5-----
Mfs/tests/sys/file.fs | 18++++++++++++++++++
Mfs/xcomp/bootlo.fs | 1+
Mposix/glue.fs | 11+++++------
Mposix/vm.c | 105++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
7 files changed, 111 insertions(+), 31 deletions(-)

diff --git a/fs/fs/fatlo.fs b/fs/fs/fatlo.fs @@ -254,6 +254,7 @@ extends _FAT struct[ FATLO : :mountvolume ( drv -- fs ) align4 here >r dup , ( drv R:fs ) ['] :child , ['] abort , ['] :fatopen , ['] abort , ['] abort , ['] abort , + ['] abort , 0 , 0 , 0 , 0 , ( drv ) \ At this point, "here" points to the FAT-header-to-be. Read the first sector \ directly in "here": we'll have the header right here! diff --git a/fs/sys/file.fs b/fs/sys/file.fs @@ -38,6 +38,7 @@ struct[ Path : :next ( self -- path-or-0 ) >r r@ fs Filesystem :next ( id ) dup if r> fs swap :new else rdrop then ; + : :remove ( self -- ) dup id swap fs Filesystem :remove ; : :root ( self -- path ) fs 0 :new ; diff --git a/fs/tests/fs/fat.fs b/fs/tests/fs/fat.fs @@ -16,9 +16,4 @@ FSInfo name S" FOO.FS" #s= myfile FATFile :cluster0 0 #eq \ no cluster allocated yet S" 42" c@+ myfile File :write myfile File :close S" /foo.fs" myroot :find# Path :fload 42 #eq -\ let's copy that file -S" foo.fs" myroot :find# value mysrc -S" bar.fs" myroot :newfile value mydst -mydst mysrc Path :copyfile -mydst Path :fload 42 #eq testend diff --git a/fs/tests/sys/file.fs b/fs/tests/sys/file.fs @@ -25,4 +25,22 @@ myinfo FSInfo size # \ let's just test for nonzero size... myinfo FSInfo dir? not # S" /lib" curpath :find Path :info value myinfo myinfo FSInfo dir? # +\ test write, copy remove +S" atabus" sysdict find [if] + \ The ATA driver doesn't support writing yet and it breaks tests below. + \ TODO: add writing support to ATA drivers + testend \s [then] +S" foo.fs" curpath :newfile dup # dup Path id .x +( path ) Path :open value myfile myfile .x +S" 42" c@+ myfile File :write myfile File :close +S" /foo.fs" curpath :find# Path :fload 42 #eq +\ let's copy that file +S" foo.fs" curpath :find# value mysrc +S" bar.fs" curpath :newfile value mydst +mydst mysrc Path :copyfile +mydst Path :fload 42 #eq +mysrc Path :remove +mydst Path :remove +S" /foo.fs" curpath :find not # +S" /bar.fs" curpath :find not # testend diff --git a/fs/xcomp/bootlo.fs b/fs/xcomp/bootlo.fs @@ -247,6 +247,7 @@ struct[ Filesystem smethod :newfile smethod :iter smethod :next + smethod :remove : :drv compile drv [compile] Drive ; immediate ]struct \ bootfs holds a reference to boot FS. This is used until the full sys/file diff --git a/posix/glue.fs b/posix/glue.fs @@ -1,16 +1,15 @@ -: _:child ( 'data ) drop _fchild ; -: _:open ( 'data ) drop _fopen ; -: _:info ( 'data ) drop _finfo ; -: _:iter ( 'data ) drop _fiter ; -: _:next ( 'data ) drop _fnext ; +: _ doer ' , does> nip @ execute ; +_ _:child _fchild _ _:open _fopen _ _:info _finfo _ _:newfile _fnewfile +_ _:iter _fiter _ _:next _fnext _ _:remove _fremove create _POSIXFS ' abort , ' _:child , ' _:info , ' _:open , - ' abort , + ' _:newfile , ' _:iter , ' _:next , + ' _:remove , _POSIXFS to bootfs diff --git a/posix/vm.c b/posix/vm.c @@ -15,6 +15,7 @@ The VM is little endian. #include <fcntl.h> #include <libgen.h> #include <dirent.h> +#include <stdlib.h> #undef FOPEN // some platforms' fcntl.h define FOPEN which clashes below. #define MEMSZ 0x100000 // 1MB @@ -759,17 +760,26 @@ static char* getpathfromid(dword fsid) { return fsids[fsid]; } +static char* pathcat(char *p1, dword s) { + static char buf1[MAXPATHSZ] = {0}; + static char buf2[MAXPATHSZ] = {0}; + byte len = gb(s++); + if (!memchk(s+len)) return NULL; + strcpy(buf1, p1); + strcat(buf1, "/"); + strncat(buf1, (char*)&vm.mem[s], len); + realpath(buf1, buf2); + return buf2; +} + static void FCHILD () { // op: 5d dword s = ppop(); - byte len = gb(s++); dword parent = ppop(); - char path[MAXPATHSZ] = {0}; + char *path; dword res; - if (!memchk(s+len)) return; - strcpy(path, getpathfromid(parent)); - strcat(path, "/"); - strncat(path, (char*)&vm.mem[s], len); + path = pathcat(getpathfromid(parent), s); + if (!path) return; res = findpath(path); if (!res) { // Verify if path actually exists in FS, then create a new ID @@ -792,7 +802,7 @@ static void FOPEN () { // op: 5e int fd; int filesize; path = getpathfromid(fsid); - fd = open(path, 0); + fd = open(path, O_RDWR); if (fd < 0) { printf("Can't open %s\n", path); vm.PC = gd(ABORT); @@ -802,8 +812,8 @@ static void FOPEN () { // op: 5e lseek(fd, 0, SEEK_SET); ppush(here()); // File cursor we're about to create dwrite(find("_freadbuf")); - dwrite(find("abort")); // writebuf - dwrite(find("drop")); // flush + dwrite(find("_fwritebuf")); + dwrite(find("drop")); dwrite(0); // pos dwrite(filesize); dwrite(find("2drop")); // seek @@ -812,7 +822,7 @@ static void FOPEN () { // op: 5e dwrite((int64_t)fd>>32); } -static void FREADBUF () { // op: 5f +static void FREADBUF() { // op: 5f dword hdl = ppop(); dword n = ppop(); int res; @@ -837,7 +847,26 @@ static void FREADBUF () { // op: 5f ppush((dword)res); } -static void FCLOSE() { // op: 60 +static void FWRITEBUF() { // op: 60 + dword hdl = ppop(); + dword n = ppop(); + dword a = ppop(); + int res; + int fd = getfiledesc(hdl); + if (!fd) { + ppush(0); + return; + } + res = write(fd, &vm.mem[a], n); + if (res < 0) { + printf("I/O writebuf error\n"); + vm.PC = gd(ABORT); + return; + } + ppush((dword)res); +} + +static void FCLOSE() { // op: 61 dword hdl = ppop(); int fd = getfiledesc(hdl); if (fd) { @@ -848,7 +877,7 @@ static void FCLOSE() { // op: 60 } // ( id -- info ) -static void FINFO() { // op: 61 +static void FINFO() { // op: 62 dword fsid = ppop(); dword dst = find("_fsinfobuf"); char *path = getpathfromid(fsid); @@ -867,10 +896,32 @@ static void FINFO() { // op: 61 memcpy(&vm.mem[dst+13], name, strlen(name)); } +static void FNEWFILE() { // op: 63 + dword s = ppop(); + dword parent = ppop(); + char *path; + dword res; + int fd; + + path = pathcat(getpathfromid(parent), s); + if (!path) return; + fd = creat(path, 0600); + if (fd == -1) { + printf("Can't create %s\n", path); + vm.PC = gd(ABORT); + return; + } + close(fd); + res = 0; + while (fsids[++res][0]); + strcpy(fsids[res], path); + ppush(res); +} + static dword iterid = 0; static DIR *dirp = NULL; -static void FNEXT() { // op: 62 +static void FNEXT() { // op: 64 struct dirent *d; char path[MAXPATHSZ] = {0}; dword res; @@ -897,7 +948,7 @@ static void FNEXT() { // op: 62 ppush(res); } -static void FITER() { // op: 63 +static void FITER() { // op: 65 iterid = ppop(); char *path = getpathfromid(iterid); if (dirp) closedir(dirp); @@ -909,8 +960,19 @@ static void FITER() { // op: 63 vm.PC = gd(ABORT); } } + +static void FREMOVE() { // op: 66 + dword fsid = ppop(); + char *path = getpathfromid(fsid); + if (remove(path) == -1) { + printf("Can't remove %s\n", path); + vm.PC = gd(ABORT); + } + fsids[fsid][0] = 0; +} + // ( imgname -- ) -static void MOUNTDRV() { // op: 64 +static void MOUNTDRV() { // op: 67 char buf[64] = {0}; dword str = ppop(); byte slen = gb(str++); @@ -928,7 +990,7 @@ static void MOUNTDRV() { // op: 64 #define SECSZ 512 // ( sec dst drv -- ) -static void DRVRD() { // op: 65 +static void DRVRD() { // op: 68 DROP(); dword dst = ppop(); dword sec = ppop(); @@ -937,7 +999,7 @@ static void DRVRD() { // op: 65 } // ( sec src drv -- ) -static void DRVWR() { // op: 66 +static void DRVWR() { // op: 69 DROP(); dword src = ppop(); dword sec = ppop(); @@ -945,7 +1007,7 @@ static void DRVWR() { // op: 66 fwrite(&vm.mem[src], SECSZ, 1, fp); } -#define OPCNT 0x67 +#define OPCNT 0x6a static void (*ops[OPCNT])() = { JUMP, CALL, RET, LIT, BYE, BYEFAIL, QUIT, ABORT_, EXECUTE, CELL, VAL, ALIAS, DOES, SLIT, BR, CBR, @@ -959,7 +1021,8 @@ static void (*ops[OPCNT])() = { RSHIFT, LITN, EXECUTEWR, EXITWR, MOVE, MOVEWR, RTYPE, WNF, STACKCHK, MAYBEWORD, WORD, PARSE, REQ, FIND, APOS, COMPILING, SWR, STARTCOMP, STOPCOMP, RUNWORD, EXIT, FCHILD, FOPEN, FREADBUF, - FCLOSE, FINFO, FNEXT, FITER, MOUNTDRV, DRVRD, DRVWR}; + FWRITEBUF, FCLOSE, FINFO, FNEWFILE, FNEXT, FITER, FREMOVE, MOUNTDRV, + DRVRD, DRVWR}; static char *opnames[OPCNT] = { NULL, NULL, NULL, NULL, "bye", "byefail", "quit", "(abort)", @@ -974,7 +1037,9 @@ static char *opnames[OPCNT] = { "rshift", "litn", "execute,", "exit,", "move", "move,", "rtype", "(wnf)", "stack?", "maybeword", "word", "parse", "[]=", "find", "'", "compiling", ",\"", "]", "[", "runword", "exit", "_fchild", "_fopen", "_freadbuf", - "_fclose", "_finfo", "_fnext", "_fiter", "_mountdrv", "_drv@", "_drv!"}; + "_fwritebuf", "_fclose", "_finfo", "_fnewfile", "_fnext", "_fiter", + "_fremove", "_mountdrv", + "_drv@", "_drv!"}; static void oprun1() { // run next op if (!memchk(vm.PC)) return;