commit 99ce90d831c4bc3677defc17a55abe7bbd0b8583
parent dd2c554111461575aaa24c8c17538d9cdb7c37d1
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Tue, 19 Jul 2022 17:36:22 -0400
Propagate the "prelude" concept to the File API
Diffstat:
5 files changed, 48 insertions(+), 47 deletions(-)
diff --git a/fs/doc/file.txt b/fs/doc/file.txt
@@ -1,12 +1,28 @@
-# File subsystem
+# File API
-This subsystems defines a "filesystem" protocol and upon it defines convenience
-word around files. To be able to plug into this subsystem, a filesystem needs
-to have these words (not with the same name, the words will plug into the
-subsystem's aliases):
+The File API is a specialization of the I/O API (doc/io) for accessing files in
+a filesystem. It also works with "handles", which we call File handle. Of
+course, it starts with the I/O prelude, but then adds its own prelude:
-fopen ( path -- fcursor )
- Open file at path and return a cursor through which other file-related word
+(I/O prelude)
+fseek
+fclose
+
+These words have the following meaning:
+
+fseek ( pos hdl -- )
+ Place the handle at offset "pos" (in bytes).
+
+fclose ( hdl -- )
+ Close handle and free its resources.
+
+## Global aliases
+
+On top of that, the File API also define global aliases in which the current
+active filesystem will plug itself:
+
+fopen ( path -- hdl )
+ Open file at path and return a handle through which other file-related word
identify the target file. Once a file isn't used anymore, it should be
closed with fclose. Aborts on error.
@@ -14,23 +30,3 @@ fnewfile ( path -- direntry )
Create a new empty file at path. Errors out if path's parent is unreachabe or
if path already exists.
-fclose ( fcursor -- )
- Close cursor fcursor and free its resources.
-
-fseek ( pos fcursor -- )
- Place the cursor at offset "pos" (in bytes).
-
-freadbuf ( n fcursor -- a? read-n )
- Try to read "n" bytes from file from current position. Unless end of file is
- reached, at least 1 byte must be read, but otherwise "read-n" can be lower
- than n, even if that doesn't take the cursor to the end of the file. The idea
- is to take the cursor, at most, to the end of its buffer. Return the number of
- bytes read and, if it was nonzero, return an address to the beginning of that
- buffer.
-
-fwritebuf ( a n fcursor -- written-n )
- Try to write "n" bytes from buffer "a" to file from current position, growing
- the file if needed. The idea is the same as with freadbuf: the filesystem can
- proceed as is best for its implementation, as long as it writes at least 1
- byte.
-
diff --git a/fs/fs/fatlo.fs b/fs/fs/fatlo.fs
@@ -141,7 +141,8 @@ here const )fnbuf
fatfindpath ( dentry ) curdir( DIRENTRYSZ move ;
\ File cursor
-\ 12b IO handler prelude
+\ 12b IO handle prelude
+\ 8b File handle prelude
\ 4b flags. all zeroes = free cursor
\ b0 = used
\ b1 = buffer is dirty
@@ -153,25 +154,25 @@ here const )fnbuf
\ 4b file size
\ Xb current cluster X=ClusterSize
10 const FCURSORCNT \ maximum number of opened files
-: FCursorSize ClusterSize 36 + ;
-: FCUR_flags ( fcur -- n ) 12 + @ ;
+: FCursorSize ClusterSize 44 + ;
+: FCUR_flags ( fcur -- n ) 20 + @ ;
: FCUR_free? ( fcur -- f ) FCUR_flags not ;
: FCUR_dirty? ( fcur -- f ) FCUR_flags 2 and ;
-: FCUR_flags! ( n fcur -- ) 12 + ! ;
-: FCUR_cluster ( fcur -- n ) 16 + @ ;
-: FCUR_cluster! ( n fcur -- ) 16 + ! ;
-: FCUR_clusteridx ( fcur -- n ) 20 + @ ;
-: FCUR_clusteridx! ( n fcur -- n ) 20 + ! ;
-: FCUR_pos ( fcur -- n ) 28 + @ ;
-: FCUR_pos! ( n fcur -- n ) 28 + ! ;
-: FCUR_pos+ ( n fcur -- ) 28 + +! ;
-: FCUR_size ( fcur -- n ) 32 + @ ;
-: FCUR_size! ( n fcur -- ) 32 + ! ;
-: FCUR_buf( ( fcur -- a ) 36 + ;
+: FCUR_flags! ( n fcur -- ) 20 + ! ;
+: FCUR_cluster ( fcur -- n ) 24 + @ ;
+: FCUR_cluster! ( n fcur -- ) 24 + ! ;
+: FCUR_clusteridx ( fcur -- n ) 28 + @ ;
+: FCUR_clusteridx! ( n fcur -- n ) 28 + ! ;
+: FCUR_pos ( fcur -- n ) 36 + @ ;
+: FCUR_pos! ( n fcur -- n ) 36 + ! ;
+: FCUR_pos+ ( n fcur -- ) 36 + +! ;
+: FCUR_size ( fcur -- n ) 40 + @ ;
+: FCUR_size! ( n fcur -- ) 40 + ! ;
+: FCUR_buf( ( fcur -- a ) 44 + ;
: FCUR_)buf ( fcur -- a ) FCUR_buf( ClusterSize + ;
: FCUR_bufpos ( fcur -- a ) dup FCUR_pos ClusterSize mod swap FCUR_buf( + ;
: FCUR_dirent ( fcur -- dirent )
- 24 + @ BPB_BytsPerSec /mod ( offset sec ) 1 readsector ( off ) fatbuf( + ;
+ 32 + @ BPB_BytsPerSec /mod ( offset sec ) 1 readsector ( off ) fatbuf( + ;
: FCUR_cluster0 ( fcur -- cl ) FCUR_dirent DIR_Cluster ;
create fcursors( FCursorSize FCURSORCNT * allot0
@@ -212,16 +213,18 @@ create fcursors( FCursorSize FCURSORCNT * allot0
rot min ( a n )
dup r> FCUR_pos+ ( a n ) ;
+: fatclose ( fcursor ) dup dup 8 + @ ( 'flush ) execute 0 swap FCUR_flags! ;
+
\ Open the specified "path" into one of the free cursors and return that
\ cursor. This is the "low" part. Complete open is finalized in fs/fat
: fatopenlo ( path -- fcursor )
fatfindpath findfreecursor >r
\ write IO handle prelude: readbuf, writebuf, flush
['] fatreadbuf r@ ! ['] abort r@ 4 + ! ['] drop r@ 8 + !
+ \ write File handle prelude: fseek fclose
+ ['] fatseek r@ 12 + ! ['] fatclose r@ 16 + !
\ write the rest
0 r@ FCUR_cluster! ( dirent ) 1 r@ FCUR_flags!
- dup fatbuf( - bufsec BPB_BytsPerSec * + ( dirent doffset ) r@ 24 + !
+ dup fatbuf( - bufsec BPB_BytsPerSec * + ( dirent doffset ) r@ 32 + !
-1 r@ FCUR_clusteridx! 0 r@ FCUR_pos!
DIR_FileSize r@ FCUR_size! ( ) r> ;
-
-: fatclose ( fcursor ) dup dup 8 + @ ( 'flush ) execute 0 swap FCUR_flags! ;
diff --git a/fs/sys/file.fs b/fs/sys/file.fs
@@ -8,6 +8,9 @@
\ our cursors.
$200 scratchpad$ filespad
+: fseek ( pos hdl -- ) dup 12 + @ execute ;
+: fclose ( hdl -- ) dup 16 + @ execute ;
+
\ This creates a "f<" reader with the file descriptor embedded in it. This
\ allows for a straightforward override of input/output words.
: [f<] ( curfd -- word )
diff --git a/fs/xcomp/boothi.fs b/fs/xcomp/boothi.fs
@@ -9,7 +9,7 @@ bootfile xcomp/boothi.fs
floaded 4 + fopen to curhdl
to' in< @ >r ['] f< to in<
begin maybeword ?dup if runword 0 else 1 then until
- r> to in< curhdl fclose r> to curhdl ;
+ r> to in< curhdl dup 16 + @ ( 'fclose ) execute r> to curhdl ;
: f<< word fload ;
\ TODO: record absolute paths or some kind of unique ID here. "lib/str.fs" and
\ "/lib/str.fs" are considered different.
diff --git a/fs/xcomp/glue2.fs b/fs/xcomp/glue2.fs
@@ -1,4 +1,3 @@
bootfile xcomp/glue2.fs
\ Glue code that goes between the filesystem part and boothi
alias fatopenlo fopen
-alias fatclose fclose