duskos

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

commit 5a04a16383b93ba58379508ad79a2c3a1ce5e861
parent 390e7ad95703cdc81eb1eab80360f599ea6eb91a
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Fri, 13 Jan 2023 13:18:42 -0500

sys/file: add "file" and "dstfile" structbinds

See doc/sys/file. For now, it's not of much use, but I think it will grow to
a powerful tool.

Diffstat:
Mfs/doc/sys/file.txt | 61++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Mfs/sys/file.fs | 14+++++++++++---
Mfs/tests/emul/cos/cvm.fs | 2+-
Mfs/tests/fs/blob.fs | 12++++++------
Mfs/tests/sys/file.fs | 6+++---
5 files changed, 75 insertions(+), 20 deletions(-)

diff --git a/fs/doc/sys/file.txt b/fs/doc/sys/file.txt @@ -193,13 +193,6 @@ Does it mean that Dusk couldn't read them? No, only that file/dir enumeration would have to go through FS-specific tools. I think that this inconvenience is worth it if it means an overall simpler API. -## Path literals - -There are 2 words for Path/File shortcuts: p" and f". - -p" foo" is a shortcut for S" foo" curpath :find# and f" foo" is a shortcut for -p" foo" Path :open. - ## MemFile MemFile is a structure that extends File and provides read/write/seek @@ -230,3 +223,57 @@ one units and we don't want to load these pieces of code twice. To this end, whenever a file is loaded, we record its ID in a linked list to remember we loaded it. If you use the "?f<<" word instead of "f<<", the specified file will be loaded only if it wasn't already loaded. + +## Handle management and global structbinds + +When we open a file, the filesystem returns a handle. The management of the +memory required to service these handles is specific to the filesystem +implementation, but we typically require significant memory space for each +handle for the contents buffer. Therefore, it's important to close handles when +we don't use them anymore so that this memory space can be used for another +file. + +Handles opened directly by the system operator can be combersome to manage and +forgetting to close them is easy. To help with this, sys/file defines two global +structbinds, "file" and "dstfile" with accompanying helper words listed below. + +The idea with those structbinds is that they're easily accessible to the sysop +and also implicitly close themselves when being overwritten. This way, the sysop +doesn't have to remember to close those handles as long as she use those +structbinds. + +Also, those structbinds serve as a kind of "stdio, but for seekable contents". +That is, some words will use them to simplify their API (you don't have to pass +them a handle, just have the structbinds properly set). + +Words that use "file" and "dstfile" are expected to never set them themselves. +They can seek, read, write to it, but the binding to the handles themselves is +the domain of the sysop. + +file Structbind to File, defaults to 0 +dstfile Structbind to File, defaults to 0 + +: file$ ( -- ) + Reset "file" and "dstfile", closing them if necessary. + +: >file ( hdl -- ) + Close current "file" and rebind it to "hdl". + +: >dstfile ( hdl -- ) + Close current "dstfile" and rebind it to "hdl". + +: file>dstfile ( -- ) + Close current "dstfile", set it to "file" and reset "file". + +## Path literals + +There are 2 words for Path/File shortcuts: p" and f". + +p" foo" is a shortcut for: + + S" foo" curpath :find# + +f" foo" is a shortcut for: + + p" foo" Path :open >file + diff --git a/fs/sys/file.fs b/fs/sys/file.fs @@ -120,8 +120,6 @@ struct[ Path ]struct Path _curpath structbind Path curpath -: p" [compile] S" curpath :find# ; immediate -: f" [compile] p" Path :open ; immediate : f<< word curpath :find# Path :fload ; : ?f<< word curpath :find# dup Path :floaded? if drop else Path :fload then ; @@ -132,6 +130,17 @@ Path _curpath structbind Path curpath to@! stdio readio >r execute r> to stdio readio r> File :close ; +0 structbind File file +0 structbind File dstfile + +: >file ( hdl -- ) file :self if file :close then ['] file rebind ; +: >dstfile ( hdl -- ) dstfile :self if dstfile :close then ['] dstfile rebind ; +: file>dstfile ( -- ) file :self >dstfile 0 ['] file rebind ; +: file$ 0 >dstfile 0 >file ; + +: p" [compile] S" curpath :find# ; immediate +: f" [compile] p" Path :open >file ; immediate + extends File struct[ MemFile SZ &+ :buf( : :)buf dup :buf( swap size + ; @@ -148,4 +157,3 @@ extends File struct[ MemFile 0 ( putback ) , ['] _readbuf , ['] _writebuf , ['] drop , ['] drop , 0 ( pos ) , dup ( size ) , ['] _seek , ( sz ) allot ; ]struct - diff --git a/fs/tests/emul/cos/cvm.fs b/fs/tests/emul/cos/cvm.fs @@ -8,7 +8,7 @@ testbegin 0 value myres COS_init vm structbind COSVM vm -vm mem f" /tests/emul/cos/dummy.bin" File :readall +vm mem f" /tests/emul/cos/dummy.bin" file :readall : iowr00 to myres ; ' iowr00 vm iowr ! vm running # diff --git a/fs/tests/fs/blob.fs b/fs/tests/fs/blob.fs @@ -7,13 +7,13 @@ testbegin 512 TOTSEC RAMDrive :new value mydrv mydrv BlobFS :mount value myfs myfs filesystems CELLSZ + ! \ register it as "B:" -p" B:/foobar" Path :open value myfile \ any subpath works -S" hello" myfile File :puts -512 myfile File :seek -S" world!" myfile File :puts -0 myfile File :seek +f" B:/foobar" \ any subpath works +S" hello" file :puts +512 file :seek +S" world!" file :puts +0 file :seek create expected ," hello" -here 5 myfile File :read +here 5 file :read here expected 5 []= # mydrv RAMDrive :buf( expected 5 []= # create expected ," world!" diff --git a/fs/tests/sys/file.fs b/fs/tests/sys/file.fs @@ -42,9 +42,9 @@ S" foo.fs" myroot :newfile # S" /foo.fs" myroot :find# ( path ) \ found! dup Path :info ( path info ) FSInfo name S" FOO.FS" #s= -( path ) Path :open value myfile -myfile FATFile :cluster0 0 #eq \ no cluster allocated yet -S" 42" c@+ myfile File :write myfile File :close +( path ) Path :open >file +file :self FATFile :cluster0 0 #eq \ no cluster allocated yet +S" 42" c@+ file :write file :flush S" /foo.fs" myroot :find# Path :fload 42 #eq \ how about a directory? S" bar" myroot :newdir dup # value mydir