duskos

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

commit dc330e12167168504f6ef5f3d531e9d5f725e014
parent 6edf52ea71bbfd6f2f8f25796458e3ef25e823e2
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Wed,  6 Jul 2022 16:11:09 -0400

fs/fat: tweak cluster reading logic during getc

Previously, the first cluster of a file was read on fopen and the fetching of
next clusters happened after having read the last byte of a cluster. This meant
that our cluster buffer was always one step ahead.

This was problematic for empty files (no cluster allocated) and allocation logic
when it comes to writing.

Now, cluster reading happens "just-in-time", that is, we check *before* reading
the char whether we need to load a new cluster. Also, we don't read a cluster
during fopen.

Diffstat:
Mfs/fs/fatlo.fs | 43+++++++++++++++++++++----------------------
1 file changed, 21 insertions(+), 22 deletions(-)

diff --git a/fs/fs/fatlo.fs b/fs/fs/fatlo.fs @@ -135,27 +135,27 @@ here const )fnbuf fatfindpath ( dentry ) curdir( DIRENTRYSZ move ; \ File cursor -\ 2b first cluster 0=free cursor -\ 2b current cluster in buf +\ 4b current cluster in buf 0=free cursor. the cluster is not actually read +\ until the first position of the cluster is needed. +\ 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 12 + ; -: FCUR_cluster0 ( fcur -- n ) w@ ; -: FCUR_cluster ( fcur -- n ) 2 + w@ ; -: FCUR_cluster! ( n fcur -- ) 2 + w! ; -: FCUR_pos ( fcur -- n ) 4 + @ ; +: FCursorSize ClusterSize 16 + ; +: FCUR_cluster ( fcur -- n ) @ ; +: FCUR_cluster! ( n fcur -- ) ! ; +: FCUR_pos ( fcur -- n ) 8 + @ ; \ return pos and post-inc it -: FCUR_pos+ ( fcur -- n ) 4 + dup @ 1 rot +! ; -: FCUR_size ( fcur -- n ) 8 + @ ; -: FCUR_buf( ( fcur -- a ) 12 + ; +: FCUR_pos+ ( fcur -- n ) 8 + dup @ 1 rot +! ; +: FCUR_size ( fcur -- n ) 12 + @ ; +: FCUR_buf( ( fcur -- a ) 16 + ; create fcursors( FCursorSize FCURSORCNT * allot0 : findfreecursor ( -- fcursor ) FCURSORCNT >r fcursors( begin ( a ) - dup FCUR_cluster0 not if ( found! ) r~ exit then FCursorSize + next + dup FCUR_cluster not if ( found! ) r~ exit then FCursorSize + next abort" out of file cursors!" ; \ read multiple sectors in buf @@ -170,21 +170,20 @@ create fcursors( FCursorSize FCURSORCNT * allot0 \ cursor. : openfile ( direntry -- fcursor ) findfreecursor >r - dup DIR_Cluster ( dirent cluster ) dup r@ FCUR_buf( readcluster - ( dirent cluster ) dup r@ w! r@ FCUR_cluster! ( dirent ) - 0 r@ 4 + ! DIR_FileSize r@ 8 + ! ( ) r> ; + dup DIR_Cluster ( dirent cluster ) + ( dirent cluster ) r@ FCUR_cluster! ( dirent ) + dup fatbuf( - bufsec BPB_BytsPerSec * + ( dirent doffset ) r@ 4 + ! + 0 r@ 8 + ! DIR_FileSize r@ 12 + ! ( ) r> ; : fatopen ( path -- fcursor ) fatfindpath openfile ; : fatgetc ( fcursor -- c ) dup FCUR_pos over FCUR_size = if drop -1 exit then - dup FCUR_pos+ ClusterSize mod over FCUR_buf( + c@ ( fc c ) - over FCUR_pos ClusterSize mod not if ( fc c ) \ end of cluster, read next - over FCUR_cluster FAT@ ( fc c cluster ) - dup EOC? if drop else - dup 2 < if abort" cluster out of range" then - rot 2dup FCUR_cluster! ( c cluster fc ) - tuck FCUR_buf( readcluster ( c fc ) swap then - then ( fc c ) nip ; + dup FCUR_pos ClusterSize mod not if ( fc ) \ end of cluster, read next + dup FCUR_cluster ( fc cluster ) + dup 2 < if abort" cluster out of range" then + 2dup swap FCUR_buf( readcluster ( fc cluster ) + FAT@ over FCUR_cluster! then ( fc ) + dup FCUR_pos+ ClusterSize mod swap FCUR_buf( + c@ ( c ) ; : fatclose ( fcursor ) 0 swap w! ;