commit 631b02f502a29fdca53ce35fa214f89b8035e048
parent a70c4f5510032143bb0e0100fac5aecafca079a1
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Sun, 21 Aug 2022 11:26:37 -0400
fs/fat: implement :iter and :next
Also, fix an edge case bug in FSInfo :read where we wouldn't properly handle
filenames using all 11 characters in the name field.
Diffstat:
3 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/fs/fs/fat.fs b/fs/fs/fat.fs
@@ -22,17 +22,19 @@
?f<< /lib/str.fs
extends FSInfo struct[ FATInfo
- create _buf DirEntry NAMESZ 1+ 1+ allot
+ DirEntry NAMESZ 2 + const BUFSZ \ 1 for the '.' and 1 for len
+ create _buf BUFSZ allot
+ SPC c, \ always have a SPC suffix
create _struct _buf ( name ) , 0 ( size ) , 0 ( dir? ) ,
create _rootname 6 c, ," (root)"
create _root _rootname , 0 , 1 ,
- : spcidx ( name -- idx ) SPC swap DirEntry NAMESZ [c]? ;
+ : spcidx ( name -- idx ) SPC swap BUFSZ [c]? ;
: :read ( id fat -- info )
over not if 2drop _root exit then
- _buf DirEntry NAMESZ 1+ SPC fill
+ _buf BUFSZ SPC fill
_FAT :getdirentry dup _buf 1+ DirEntry EXTIDX move ( dirent )
_buf 1+ spcidx ( dirent namelen )
- over DirEntry EXTIDX + c@ SPC = not if ( dirent namelen )
+ over DirEntry EXTIDX + c@ SPC <> if ( dirent namelen )
over DirEntry EXTIDX + swap _buf + 1+ '.' swap c!+ ( dir src dst )
DirEntry EXTSZ move else drop then ( dirent )
_buf 1+ spcidx ( dirent len ) _buf c! ( dirent )
diff --git a/fs/fs/fatlo.fs b/fs/fs/fatlo.fs
@@ -23,6 +23,9 @@ struct[ DirEntry
26 &+w@ cluster
: cluster! ( n self -- ) 26 + w! ;
28 field filesize
+ : :lastentry? ( self -- f ) c@ not ;
+ : :valid? ( self -- f ) dup :lastentry? not swap c@ $e5 <> and ;
+ : :iterable? ( self -- f ) dup :valid? swap c@ '.' <> and ;
]struct
\ Just a dummy entry so that we can reference the root directory as a "direntry"
@@ -184,7 +187,6 @@ extends File struct[ FATFile
: :dirent ( self -- dirent ) dup entryoff swap :fat :getdirentry ;
: :cluster0 ( self -- cl ) :dirent DirEntry cluster ;
- \ TODO _dst :seek is broken for FAT when file is empty. fix.
0 value self
\ set self to pos. If new pos crosses cluster boundaries compared to current
\ pos, flush current buffer and read a new sector from disk.
@@ -239,6 +241,21 @@ extends File struct[ FATFile
]struct
extends _FAT struct[ FATLO
+ 0 value _dirent
+ : :next ( self -- id-or-0 )
+ _dirent not if abort" invalid iterator" then >r
+ DirEntry SZ to+ _dirent _dirent r@ _FAT :)buf = if
+ r@ _FAT :nextsector? not if
+ rootdirentry( to _dirent else \ parses as "lastentry"
+ r@ _FAT :buf( to _dirent then then
+ _dirent DirEntry :lastentry? if rdrop 0 to _dirent 0 else
+ _dirent DirEntry :iterable? if _dirent r> _FAT :getid else r> :next then
+ then ;
+
+ : :iter ( dirid self -- id-or-0 ) >r
+ r@ _FAT :getdirentry r@ _FAT :readdir
+ r@ _FAT :buf( DirEntry SZ - to _dirent r> :next ;
+
: :child ( dirid name self -- id-or-0 ) >r
fnbuf! r@ _FAT :getdirentry r@ _FAT :readdir r@ _FAT :findindir
dup if r@ _FAT :getid then rdrop ;
@@ -256,7 +273,7 @@ extends _FAT struct[ FATLO
: :mountvolume ( drv -- fs )
align4 here >r dup , ( drv R:fs ) 0 ( flags ) ,
- ['] :child , ['] abort , ['] :fatopen , ['] abort , ['] abort , ['] abort ,
+ ['] :child , ['] abort , ['] :fatopen , ['] :iter , ['] :next , ['] abort ,
['] abort , ['] abort ,
0 , 0 , 0 , 0 , ( drv )
\ At this point, "here" points to the FAT-header-to-be. Read the first sector
diff --git a/fs/xcomp/bootlo.fs b/fs/xcomp/bootlo.fs
@@ -47,6 +47,7 @@ code : ] code ] ;
: 0>= 0< not ;
: >= < not ;
: <= > not ;
+: <> = not ;
: -^ swap - ;
: / /mod nip ;
: mod /mod drop ;