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:
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;