duskos

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

commit 693a08ac9610a5e34e03592de960cba425596111
parent 620a31659e9f880cbf5f1cefa88649909a8cd21a
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Sat, 13 May 2023 21:35:19 -0400

fs/fat: consolidate

Diffstat:
Mfs/fs/fat.fs | 90++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mfs/fs/fatlo.fs | 41++++++++++++++++++-----------------------
2 files changed, 63 insertions(+), 68 deletions(-)

diff --git a/fs/fs/fat.fs b/fs/fs/fat.fs @@ -142,47 +142,6 @@ $e5 const DIRFREE swap r@ :FirstSectorOfCluster ( dst sec ) swap r@ secpercluster swap r> writesectors ; -: fatflush ( hdl -- ) >r - r@ FATFile :dirty? not if rdrop exit then ( ) - \ save buffer - r@ FATFile cluster r@ FATFile :buf( r@ FATFile fat writecluster ( ) - \ save size to direntry - r@ FATFile :dirent r@ FATFile size swap to DirEntry filesize ( ) - r@ FATFile fat writecursector - \ undirty the cursor - r@ FATFile flags $fffffffd and to r> FATFile flags ; - -0 structbind FATFile self -\ grow fcursor to newsz, if needed -: fatgrow ( newsz self -- ) ['] self rebind - dup self size <= if drop exit then ( newsz ) - to self size self :cluster0 ( cluster0 ) - \ special case: if :cluster0 is zero, we have an empty file. We need to - \ update its direntry to record the file's first cluster. - ?dup not if self fat allocatecluster then ( cluster0 ) - self :dirent 2dup to DirEntry cluster ( custer0 dirent ) - self size swap to DirEntry filesize self fat writecursector ( cluster0 ) - self size self fat :ClusterSize / ?dup if - for ( cluster ) self fat FAT@+ next then ( cluster ) drop ; - -: fatwritebuf ( buf n self -- n ) - dup FATFile :free? if 2drop drop 0 exit then ( buf n self ) - dup >r File pos over + r@ fatgrow ( src n ) - \ TODO: this seek below doesn't seem right. The buffer should be at all times - \ positioned properly w.r.t. pos. - r@ File pos r@ FATFile :seek - r@ FATFile flags 2 or ( dirty ) r@ to FATFile flags - r@ FATFile :)buf r@ FATFile :ptr - ( src n nmax ) - min ( src n ) r@ FATFile :ptr swap ( src dst n ) - dup >r move r> ( n ) r@ File pos over + r> File :seek ; - -\ TODO: deallocate truncated FATs if appropriate -: fattruncate ( self -- ) - dup FATFile pos ( self pos ) - 2dup swap to FATFile size ( self pos ) - over FATFile :dirent to DirEntry filesize ( self ) - FATFile fat writecursector ; - : fatinfo ( id self -- info ) FATInfo :read ; \ TODO: deallocate the chain before clearing the entry @@ -208,10 +167,6 @@ $e5 const DIRFREE : :patchlo ( fs -- ) >r \ V1=fs ['] fatinfo r@ 12 + ! ['] fatiter r@ 20 + ! ['] fatnewfile r@ 24 + ! ['] fatnewdir r@ 28 + ! ['] fatremove r@ 32 + ! - ['] fatwritebuf FATFile EmptyCursor 8 + ! - ['] fatflush FATFile EmptyCursor 12 + ! - ['] fatflush FATFile EmptyCursor 12 + ! - ['] fattruncate FATFile EmptyCursor 40 + ! 1 r> to flags ; : :mountvolume ( drv -- fs ) FAT :mountvolume dup :patchlo ; @@ -250,3 +205,48 @@ create _FATTemplate $fffff0 here ! ( drv ) fatopts rsvdsec here rot Drive :sec! 2rdrop ; ]struct + +struct+[ FATFile + : _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 ; + current ' :flush realias + + \ grow fcursor to newsz, if needed + : _grow ( newsz self -- ) + 2dup size <= if 2drop exit then + r! to size V1 :cluster0 ( cluster0 ) \ V1=self + \ special case: if :cluster0 is zero, we have an empty file. We need to + \ update its direntry to record the file's first cluster. + ?dup not if V1 :fat allocatecluster then ( cluster0 ) + V1 :dirent 2dup to DirEntry cluster ( custer0 dirent ) + V1 size swap to DirEntry filesize V1 :fat writecursector ( cluster0 ) + V1 size V1 :fat :ClusterSize / ?dup if + for ( cluster ) V1 :fat FAT@+ next then ( cluster ) drop rdrop ; + + : _writebuf ( buf n self -- n ) + dup :free? if 2drop drop 0 exit then ( buf n self ) + dup >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 ) + dup >r move r> ( n ) r@ pos over + r> :seek ; + current ' :writebuf realias + + \ TODO: deallocate truncated FATs if appropriate + : _truncate ( self -- ) + dup pos ( self pos ) + 2dup swap to size ( self pos ) + over :dirent to DirEntry filesize ( self ) + :fat writecursector ; + current ' :truncate realias +]struct diff --git a/fs/fs/fatlo.fs b/fs/fs/fatlo.fs @@ -162,51 +162,46 @@ extends File struct[ FATFile : :dirent ( self -- dirent ) bi entryoff | :fat :getdirentry ; : :cluster0 ( self -- cl ) :dirent DirEntry cluster ; + alias abort :writebuf + 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. - : :fatseek ( pos self -- ) + : :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 IO :flush V1 _poscluster dup V1 to clusteridx ( idx ) + 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 ; - : :fatreadbuf ( n self -- a? n ) + : :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@ :fatseek ( n ) + r@ pos r@ :seek ( n ) r@ :ptr r@ :)buf over - ( n a nmax ) rot min ( a n ) dup r> to+ pos ( a n ) ; - : :fatclose ( self -- ) dup :flush :release ; - - \ these words below are "static" words not called with "self" as an argument, - \ but "fat". - : :cursorsize ( fat -- sz ) FAT :ClusterSize SZ + ; + : :close ( self -- ) dup :flush :release ; - create EmptyCursor - 0 ( putback ) , ' :fatreadbuf , ' abort , ' drop , ' :fatclose , - 0 ( pos ) , 0 ( size ) , 0 ( bufptr ) , 0 ( bufsz ) , ' :fatseek , - ' abort ( truncate ) , 0 ( fat ) , 0 ( flags ) , 0 ( cluster ) , + : :new ( fat -- hdl ) + 0 align4 dup to' FAT lastcursor lladd ( fat newll ) drop here >r + 0 ( putback ) , ['] :readbuf , ['] :writebuf , ['] :flush , ['] :close , + 0 ( pos ) , 0 ( size ) , 0 ( bufptr ) , dup FAT :ClusterSize ( bufsz ) , + ['] :seek , ['] :truncate , ( fat ) , 0 ( flags ) , 0 ( cluster ) , -1 ( clusteridx ) , 0 ( entryoff ) , - - : :createcursor ( fat -- hdl ) - 0 align4 dup to' FAT lastcursor lladd ( fat newll ) - swap :cursorsize allot ( newll ) CELLSZ + ( hdl ) dup :release ; + here r@ to bufptr r@ bufsz allot r> ; : :findfreecursor ( fat -- hdl ) - r! FAT lastcursor begin ( ll ) \ V1=fat + dup FAT lastcursor begin ( fat ll ) ?dup while dup CELLSZ + :free? not while llnext repeat - CELLSZ + else r@ :createcursor then - EmptyCursor over SZ move ( hdl ) - r@ FAT :ClusterSize over to bufsz - dup SZ + over to bufptr - r> over to fat ; + nip CELLSZ + else :new then + 0 over to pos -1 over to clusteridx ; ]struct struct+[ FAT