commit c9a368e3c99fab8e6f5d8299332b8bff1563357d
parent 0a67a1747bd363c6b0921e7d7bd795c8ded0a456
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Fri, 19 Aug 2022 09:31:12 -0400
sys/file: add Path :listdir
For now, :iter and :next are only implemented in POSIX FS.
Diffstat:
5 files changed, 67 insertions(+), 7 deletions(-)
diff --git a/fs/fs/fatlo.fs b/fs/fs/fatlo.fs
@@ -253,7 +253,7 @@ extends _FAT struct[ FATLO
: :mountvolume ( drv -- fs )
align4 here >r dup , ( drv R:fs )
- ['] :child , ['] abort , ['] :fatopen , ['] abort , ( drv )
+ ['] :child , ['] abort , ['] :fatopen , ['] 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
@@ -33,6 +33,11 @@ struct[ Path
dup if r> fs swap :new else rdrop then ;
: :newfile ( name self -- path ) >r
r@ id swap r@ fs Filesystem :newfile ( id ) r> fs swap :new ;
+ : :iter ( self -- path ) >r
+ r@ id r@ fs Filesystem :iter ( id ) r> fs swap :new ;
+ : :next ( self -- path-or-0 ) >r
+ r@ fs Filesystem :next ( id )
+ dup if r> fs swap :new else rdrop then ;
: :root ( self -- path ) fs 0 :new ;
@@ -73,6 +78,12 @@ struct[ Path
:open ['] _src rebind :open ['] _dst rebind begin ( )
_src size _src :readbuf ?dup while ( a n ) _dst :self IO :write repeat
_dst :close _src :close ;
+
+ : :listdir ( self -- ) >r
+ r@ :iter begin ( path-or-0 ) ?dup while
+ :info FSInfo name stype nl>
+ r@ :next repeat
+ rdrop ;
]struct
Path _curpath structbind Path curpath
diff --git a/fs/xcomp/bootlo.fs b/fs/xcomp/bootlo.fs
@@ -245,6 +245,8 @@ struct[ Filesystem
smethod :info
smethod :open
smethod :newfile
+ smethod :iter
+ smethod :next
: :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,12 +1,16 @@
: _:child ( 'data ) drop _fchild ;
: _:open ( 'data ) drop _fopen ;
: _:info ( 'data ) drop _finfo ;
+: _:iter ( 'data ) drop _fiter ;
+: _:next ( 'data ) drop _fnext ;
create _POSIXFS
' abort ,
' _:child ,
' _:info ,
' _:open ,
' abort ,
+ ' _:iter ,
+ ' _:next ,
_POSIXFS to bootfs
diff --git a/posix/vm.c b/posix/vm.c
@@ -14,6 +14,7 @@ The VM is little endian.
#include <sys/stat.h>
#include <fcntl.h>
#include <libgen.h>
+#include <dirent.h>
#undef FOPEN // some platforms' fcntl.h define FOPEN which clashes below.
#define MEMSZ 0x100000 // 1MB
@@ -866,8 +867,50 @@ static void FINFO() { // op: 61
memcpy(&vm.mem[dst+13], name, strlen(name));
}
+static dword iterid = 0;
+static DIR *dirp = NULL;
+
+static void FNEXT() { // op: 62
+ struct dirent *d;
+ char path[MAXPATHSZ] = {0};
+ dword res;
+ if (!dirp) {
+ printf("Calling next without an iter first!");
+ vm.PC = gd(ABORT);
+ return;
+ }
+ do {
+ d = readdir(dirp);
+ } while (d && ((strcmp(d->d_name, ".") == 0) || (strcmp(d->d_name, "..") == 0)));
+ if (!d) {
+ ppush(0);
+ return;
+ }
+ strcpy(path, getpathfromid(iterid));
+ strcat(path, "/");
+ strcat(path, d->d_name);
+ res = findpath(path);
+ if (!res) {
+ while (fsids[++res][0]);
+ strcpy(fsids[res], path);
+ }
+ ppush(res);
+}
+
+static void FITER() { // op: 63
+ iterid = ppop();
+ char *path = getpathfromid(iterid);
+ if (dirp) closedir(dirp);
+ dirp = opendir(path);
+ if (dirp) {
+ FNEXT();
+ } else {
+ printf("Couldn't open dir %s\n", path);
+ vm.PC = gd(ABORT);
+ }
+}
// ( imgname -- )
-static void MOUNTDRV() { // op: 62
+static void MOUNTDRV() { // op: 64
char buf[64] = {0};
dword str = ppop();
byte slen = gb(str++);
@@ -885,7 +928,7 @@ static void MOUNTDRV() { // op: 62
#define SECSZ 512
// ( sec dst drv -- )
-static void DRVRD() { // op: 63
+static void DRVRD() { // op: 65
DROP();
dword dst = ppop();
dword sec = ppop();
@@ -894,7 +937,7 @@ static void DRVRD() { // op: 63
}
// ( sec src drv -- )
-static void DRVWR() { // op: 64
+static void DRVWR() { // op: 66
DROP();
dword src = ppop();
dword sec = ppop();
@@ -902,7 +945,7 @@ static void DRVWR() { // op: 64
fwrite(&vm.mem[src], SECSZ, 1, fp);
}
-#define OPCNT 0x65
+#define OPCNT 0x67
static void (*ops[OPCNT])() = {
JUMP, CALL, RET, LIT, BYE, BYEFAIL, QUIT, ABORT_,
EXECUTE, CELL, VAL, ALIAS, DOES, SLIT, BR, CBR,
@@ -916,7 +959,7 @@ 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, MOUNTDRV, DRVRD, DRVWR};
+ FCLOSE, FINFO, FNEXT, FITER, MOUNTDRV, DRVRD, DRVWR};
static char *opnames[OPCNT] = {
NULL, NULL, NULL, NULL, "bye", "byefail", "quit", "(abort)",
@@ -931,7 +974,7 @@ 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", "_mountdrv", "_drv@", "_drv!"};
+ "_fclose", "_finfo", "_fnext", "_fiter", "_mountdrv", "_drv@", "_drv!"};
static void oprun1() { // run next op
if (!memchk(vm.PC)) return;