duskos

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

commit 39864c9c0d6429a549c5746130c6cdf613a02615
parent 6a091fb48d5b9e58f35c15536d4eaae564cd6fb9
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Tue, 16 May 2023 12:24:36 -0400

fs/fat: use SectorWindow in FATFile

That :flush bug was quite something...

Diffstat:
Mfs/fs/fat.fs | 43++++++++++++-------------------------------
Mfs/fs/fatlo.fs | 58++++++++++++++++++++++------------------------------------
2 files changed, 34 insertions(+), 67 deletions(-)

diff --git a/fs/fs/fat.fs b/fs/fs/fat.fs @@ -77,7 +77,7 @@ $e5 const DIRFREE : FAT! ( entry cluster self -- ) dup :FAT12? if FAT12! else FAT16! then ; : zerocluster ( cluster self -- ) - r! :FirstSectorOfCluster V1 secpercluster V1 :dirwin :move \ V1=self + r! :clustersec V1 secpercluster V1 :dirwin :move \ V1=self 0 V1 :dirwin :seek 0 fill V1 secpercluster for V1 :dirwin sec i + V1 :dirwin :buf( V1 :drv :sec! next rdrop ; @@ -124,24 +124,13 @@ $e5 const DIRFREE V2 over to DirEntry cluster V1 writecursector ( dirent ) V1 :getid ( id ) V1 bufcluster >r \ V3=parentcl \ Cluster allocated, now let's initialize it with "." and ".." - V2 V1 :FirstSectorOfCluster 1 V1 :readsector + V2 V1 :clustersec 1 V1 :readsector V1 :dirwin :buf( dup DirEntry NAMESZ SPC fill '.' over c! _makedir ( id buf ) V2 over to DirEntry cluster ( id buf ) DirEntry SZ + dup DirEntry NAMESZ SPC fill '.' over c!+ '.' swap c! ( id buf ) _makedir ( id buf ) V3 swap to DirEntry cluster 2rdrop r> writecursector ( id ) ; -\ write multiple sectors from buf -: writesectors ( sec u buf self -- ) >r \ V1=self - rot >r swap for ( buf ) \ V2=sec - V2 over V1 :drv :sec! to1+ V2 V1 :drv secsz + next ( buf ) - drop 2rdrop ; - -: writecluster ( cluster src self -- ) >r - over 2 - $fff6 > if abort" cluster out of range!" then - swap r@ :FirstSectorOfCluster ( dst sec ) - swap r@ secpercluster swap r> writesectors ; - :realias info ( id self -- info ) FATInfo :read ; \ TODO: deallocate the chain before clearing the entry @@ -204,15 +193,11 @@ create _FATTemplate ]struct struct+[ FATFile - :realias flush ( hdl -- ) - r! :dirty? not if rdrop exit then ( ) - \ save buffer - r@ cluster r@ :buf( r@ :fat writecluster ( ) - \ save size to direntry - r@ :dirent r@ size swap to DirEntry filesize ( ) - r@ :fat writecursector - \ undirty the cursor - r@ flags $fffffffd and to r> flags ; + \ Warning: we *can't* use :realias below because we might be sourcing this + \ very file while being on fatlo, which means :flush will be called before + \ we're finished compiling it! Debugging this was mind-bending... + : _flush ( hdl -- ) :secwin :flush ; + current ' flush realias \ grow fcursor to newsz, if needed : _grow ( newsz self -- ) @@ -227,16 +212,12 @@ struct+[ FATFile for ( cluster ) V1 :fat FAT@+ next then ( cluster ) drop rdrop ; :realias writebuf ( buf n self -- n ) - dup :free? if 2drop drop 0 exit then ( buf n self ) + dup :free? if _ioerr then r! pos over + r@ _grow ( src n ) - \ TODO: this seek below doesn't seem right. The buffer should be at all times - \ positioned properly w.r.t. pos. - r@ pos r@ :seek - r@ flags 2 or ( dirty ) r@ to flags - r@ :)buf r@ :ptr - ( src n nmax ) - min ( src n ) r@ :ptr swap ( src dst n ) - r! move r> ( n ) r@ pos over + r> :seek ; - + r@ _place r@ _clpos drop ( src n subpos ) + r@ :secwin :seek dup if ( src n a n ) + rot min r! move r> dup r@ to+ pos r> :secwin :dirty! + else ( src n 0 ) nip nip rdrop then ; \ TODO: deallocate truncated FATs if appropriate :realias truncate ( self -- ) dup pos ( self pos ) diff --git a/fs/fs/fatlo.fs b/fs/fs/fatlo.fs @@ -79,7 +79,7 @@ $18 const HDRSZ : :FAT12? :CountOfClusters 4085 < ; : cl# ( n -- ) not if abort" cluster out of range" then ; -: :FirstSectorOfCluster ( n self -- sec ) >r +: :clustersec ( n self -- sec ) >r dup << r@ secsz r@ FATsz * < cl# 2 - r@ secpercluster * r> :FirstDataSector + ; @@ -98,7 +98,7 @@ $18 const HDRSZ : :nextcluster? ( self -- f ) bi+ bufcluster | :FAT@ swap 2dup :EOC? if 2drop 0 else ( cl self ) - 2dup to bufcluster tuck :FirstSectorOfCluster ( self sec ) + 2dup to bufcluster tuck :clustersec ( self sec ) over secpercluster rot :readsector 1 then ; :iterator :iterdirentry ( self -- ) @@ -115,7 +115,7 @@ $18 const HDRSZ \ Read specified "direntry" in :buf( : :readdir ( direntry self -- ) >r DirEntry cluster ?dup if \ not root entry - dup r@ :FirstSectorOfCluster r@ secpercluster else \ root entry + dup r@ :clustersec r@ secpercluster else \ root entry 0 r@ :FirstRootDirSecNum r@ :RootDirSectors then ( cluster sec cnt ) r@ :readsector ( cluster ) to r> bufcluster ; @@ -127,16 +127,6 @@ $18 const HDRSZ : :getid ( direntry self -- id ) r! :dirwin :buf( - r@ :dirwin sec r> secsz * + ; -\ read multiple sectors in buf -: :readsectors ( sec u buf self -- ) >r \ V1=self - rot >r swap for ( buf ) \ V2=sec - V2 over V1 :drv :sec@ to1+ V2 V1 secsz + next ( buf ) drop 2rdrop ; - -: :readcluster ( cluster dst self -- ) >r - over 2 - $fff6 > if abort" cluster out of range!" then - swap r@ :FirstSectorOfCluster ( dst sec ) - swap r@ secpercluster swap r> :readsectors ; - : child ( dirid name self -- id-or-0 ) >r fnbuf! r@ :getdirentry r@ :readdir r@ :findindir dup if r@ :getid then rdrop ; @@ -145,6 +135,7 @@ $18 const HDRSZ \ File cursor extends File struct[ FATFile sfield fat + sfield secwin \ all zeroes = free cursor \ b0 = used \ b1 = buffer is dirty @@ -155,10 +146,10 @@ extends File struct[ FATFile sfield clusteridx \ current cluster index, -1=nothing. sfield entryoff : :fat [compile] fat [compile] FAT ; immediate + : :secwin [compile] secwin [compile] SectorWindow ; immediate : :free? ( self -- f ) flags not ; : :hold ( self -- ) 1 swap to flags ; : :release ( self -- ) 0 swap to flags ; - : :dirty? ( self -- f ) flags 2 and bool ; : :dirent ( self -- dirent ) bi entryoff | :fat :getdirentry ; : :cluster0 ( self -- cl ) :dirent DirEntry cluster ; @@ -166,26 +157,20 @@ extends File struct[ FATFile alias drop flush alias abort truncate - : _poscluster ( self -- idx ) bi pos | bufsz / ; - : _inbounds? ( self -- f ) bi _poscluster | clusteridx = ; - \ set self to pos. If new pos crosses cluster boundaries compared to current - \ pos, flush current buffer and read a new sector from disk. - : seek ( pos self -- ) - dup :free? if 2drop exit then >r ( pos ) \ V1=self - dup 0< if abort" can't seek to negative pos" then - V1 to pos V1 _inbounds? not if - V1 :flush V1 _poscluster dup V1 to clusteridx ( idx ) - V1 :cluster0 ( idx cl ) swap for ( cl ) V1 :fat :FAT@ next ( cl ) - dup V1 :buf( V1 :fat :readcluster ( cl ) V1 to cluster then rdrop ; + : seek to pos ; + : _clpos ( self -- subpos clidx ) bi pos | :fat :ClusterSize /mod ; + \ Can't be called with pos >= size + : _place ( self -- ) + dup _clpos nip over clusteridx over = if 2drop else ( self clidx ) + swap r! :flush dup V1 to clusteridx \ ( clidx ) V1=self + V1 :cluster0 swap for ( cl ) V1 :fat :FAT@ next ( cl ) + V1 :fat :clustersec V1 :fat :ClusterSize r> :secwin :move then ; : readbuf ( n self -- a? n ) - dup :free? if 2drop 0 exit then ( n self ) - bi+ size | pos - ( n self maxn ) - dup 1- 0< if ( EOF ) 2drop drop 0 exit then swap >r ( n maxn ) \ V1=self - min ( n ) \ make sure that n doesn't go over size - r@ pos r@ :seek ( n ) - r@ :ptr r@ :)buf over - ( n a nmax ) - rot min ( a n ) dup r> to+ pos ( a n ) ; + bi+ pos | size >= over :free? or if 2drop 0 else + r! size V1 pos - min >r \ V1=self V2=n + V1 _place V1 _clpos drop ( subpos ) + V1 :secwin :seek r> min dup r> to+ pos then ; : close ( self -- ) dup :flush :release ; : :open ( direntry self -- ) @@ -194,12 +179,13 @@ extends File struct[ FATFile 0 to r@ pos -1 to r> clusteridx ; : :new ( fat -- hdl ) - 0 align4 dup to' FAT lastcursor lladd drop ( fat ) - File :new >r S[ :[methods] ]S c@+ -move, ( fat ) \ V1=hdl + dup FAT drv SectorWindow :new + over to' FAT lastcursor lladd drop ( fat secwin ) + File :new >r S[ :[methods] ]S c@+ -move, \ V1=hdl S[ IO :[methods] ]S c@+ r@ IO :methods( swap move - dup ( fat ) , 0 ( flags ) , 0 ( cluster ) , + swap ( fat ) , ( secwin ) , 0 ( flags ) , 0 ( cluster ) , -1 ( clusteridx ) , 0 ( entryoff ) , - here r@ to bufptr FAT :ClusterSize dup allot r@ to bufsz r> ; + r@ :secwin :buf( r@ to bufptr r@ :fat :drv secsz r@ to bufsz r> ; ]struct struct+[ FAT