commit eac0ad4b5e4ec27c53d6084ab12561c020ac7184
parent e7388dbd184971836e2c0a92173ca5d46280683a
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Mon, 18 Jul 2022 20:51:26 -0400
fs/fat: fix shady business with read/write pos increases
Diffstat:
3 files changed, 33 insertions(+), 28 deletions(-)
diff --git a/fs/fs/fat.fs b/fs/fs/fat.fs
@@ -100,7 +100,7 @@ current to fatflush
\ Write c to fcursor and advance the position by one, growing the file if
\ needed.
: fatputc ( c fcursor -- )
- dup >r FCUR_pos 1+ dup 1+ r@ fatgrow ( c newpos R:fcursor )
+ dup >r FCUR_pos dup 1+ r@ fatgrow ( c newpos R:fcursor )
r@ fatseek
r@ FCUR_flags 2 or ( dirty ) r@ FCUR_flags! ( c R:fcursor )
- r> FCUR_bufpos c! ;
+ r@ FCUR_bufpos c! 1 r> FCUR_pos+ ;
diff --git a/fs/fs/fatlo.fs b/fs/fs/fatlo.fs
@@ -146,27 +146,31 @@ here const )fnbuf
\ b1 = buffer is dirty
\ 4b current cluster in buf 0=nothing. the cluster is not actually read
\ until the first position of the cluster is needed.
+\ 4b current cluster index, -1=nothing.
\ 4b offset, on disk, of direntry
\ 4b cur pos (offset from beginning of file)
\ 4b file size
\ Xb current cluster X=ClusterSize
10 const FCURSORCNT \ maximum number of opened files
-: FCursorSize ClusterSize 20 + ;
+: FCursorSize ClusterSize 24 + ;
: FCUR_flags ( fcur -- n ) @ ;
: FCUR_free? ( fcur -- f ) FCUR_flags not ;
: FCUR_dirty? ( fcur -- f ) FCUR_flags 2 and ;
: FCUR_flags! ( n fcur -- ) ! ;
: FCUR_cluster ( fcur -- n ) 4 + @ ;
: FCUR_cluster! ( n fcur -- ) 4 + ! ;
-: FCUR_pos ( fcur -- n ) 12 + @ ;
-: FCUR_pos! ( n fcur -- n ) 12 + ! ;
-: FCUR_size ( fcur -- n ) 16 + @ ;
-: FCUR_size! ( n fcur -- ) 16 + ! ;
-: FCUR_buf( ( fcur -- a ) 20 + ;
+: FCUR_clusteridx ( fcur -- n ) 8 + @ ;
+: FCUR_clusteridx! ( n fcur -- n ) 8 + ! ;
+: FCUR_pos ( fcur -- n ) 16 + @ ;
+: FCUR_pos! ( n fcur -- n ) 16 + ! ;
+: FCUR_pos+ ( n fcur -- ) 16 + +! ;
+: FCUR_size ( fcur -- n ) 20 + @ ;
+: FCUR_size! ( n fcur -- ) 20 + ! ;
+: FCUR_buf( ( fcur -- a ) 24 + ;
: FCUR_)buf ( fcur -- a ) FCUR_buf( ClusterSize + ;
: FCUR_bufpos ( fcur -- a ) dup FCUR_pos ClusterSize mod swap FCUR_buf( + ;
: FCUR_dirent ( fcur -- dirent )
- 8 + @ BPB_BytsPerSec /mod ( offset sec ) 1 readsector ( off ) fatbuf( + ;
+ 12 + @ BPB_BytsPerSec /mod ( offset sec ) 1 readsector ( off ) fatbuf( + ;
: FCUR_cluster0 ( fcur -- cl ) FCUR_dirent DIR_Cluster ;
create fcursors( FCursorSize FCURSORCNT * allot0
@@ -190,8 +194,9 @@ create fcursors( FCursorSize FCURSORCNT * allot0
: openfile ( direntry -- fcursor )
findfreecursor >r
0 r@ FCUR_cluster! ( dirent ) 1 r@ FCUR_flags!
- dup fatbuf( - bufsec BPB_BytsPerSec * + ( dirent doffset ) r@ 8 + !
- -1 r@ 12 + ! DIR_FileSize r@ 16 + ! ( ) r> ;
+ dup fatbuf( - bufsec BPB_BytsPerSec * + ( dirent doffset ) r@ 12 + !
+ -1 r@ FCUR_clusteridx! 0 r@ FCUR_pos!
+ DIR_FileSize r@ FCUR_size! ( ) r> ;
: fatopen ( path -- fcursor ) fatfindpath openfile ;
@@ -205,22 +210,22 @@ alias drop fatflush ( fcursor -- )
\ pos, flush current buffer and read a new sector from disk.
: fatseek ( pos fcursor -- )
over 0< if abort" can't seek to negative pos" then
- over ClusterSize / over FCUR_pos ClusterSize / = not if \ cluster change!
- dup fatflush ( pos fcursor )
- over ClusterSize / over FCUR_cluster0 ( pos fc clcnt cl )
- swap ?dup if >r begin ( pos fc cl ) FAT@ next then ( pos fc cl )
- 2dup swap FCUR_buf( readcluster ( pos fc cl )
- over FCUR_cluster! ( pos fc )
+ over ClusterSize / over FCUR_clusteridx = not if
+ dup fatflush >r ( pos )
+ dup ClusterSize / dup r@ FCUR_clusteridx! ( pos idx )
+ r@ FCUR_cluster0 ( pos idx cl )
+ swap ?dup if >r begin ( pos cl ) FAT@ next then ( pos cl )
+ dup r@ FCUR_buf( readcluster ( pos cl )
+ r@ FCUR_cluster! r> ( pos fc )
then ( pos fcursor ) FCUR_pos! ;
-\ TODO: this whole business about advancing the cursor *before* reading is
-\ shady. Fix this, read should happen at current cursor pos, post-inc.
-\ Also, this is broken for n!=1
: fatreadbuf ( n fcursor -- a? n )
- dup FCUR_pos 1+ over FCUR_size over <= if \ EOF!
- drop 2drop 0 exit then ( n fc pos )
- over fatseek ( n fcursor )
- dup FCUR_bufpos swap FCUR_)buf over - ( n pos nmax )
- rot min ( pos n ) ;
+ dup >r FCUR_size r@ FCUR_pos - ( n maxn )
+ dup 1- 0< if ( EOF ) 2drop r~ 0 exit then
+ min ( n ) \ make sure that n doesn't go over size
+ r@ FCUR_pos r@ fatseek ( n )
+ r@ FCUR_bufpos r@ FCUR_)buf over - ( n a nmax )
+ rot min ( a n )
+ dup r> FCUR_pos+ ( a n ) ;
: fatclose ( fcursor ) dup fatflush 0 swap FCUR_flags! ;
diff --git a/fs/tests/fs/fat.fs b/fs/tests/fs/fat.fs
@@ -10,11 +10,11 @@ testbegin
\ Tests for fs/fat
S" tests/fattest" fatfindpath ( dirent )
openfile ( fcursor ) dup fatgetc 'T' #eq
-$ff over fatseek \ TODO: make cursor post-inc. see fatlo.fs
+$100 over fatseek
dup fatgetc 'f' #eq dup fatgetc 'o' #eq dup fatgetc 'o' #eq
-$1ff over fatseek
+$200 over fatseek
dup fatgetc 'b' #eq
-$ffc over fatseek
+$ffd over fatseek
dup fatgetc 'E' #eq dup fatgetc 'O' #eq dup fatgetc 'F' #eq
dup fatgetc -1 #eq
fatclose