duskos

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

commit 79c0f79e7d3f0a1bc4d053dcd3a410fec232434a
parent 2f03a9049f488bde7e9b893adafd4b99c9ff732d
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Wed, 20 Jul 2022 07:17:34 -0400

sys/file: implement chdir findpathdir and findpath

This will allow to offload complexity from FS implementations.

Diffstat:
Mfs/doc/file.txt | 18++++++++++++++++++
Mfs/fs/fatlo.fs | 12+++++++-----
Mfs/sys/file.fs | 26+++++++++++++++++++++++---
Mfs/tests/fs/fat.fs | 8--------
Mfs/tests/sys/all.fs | 3++-
Afs/tests/sys/file.fs | 16++++++++++++++++
Mfs/xcomp/glue2.fs | 1+
7 files changed, 67 insertions(+), 17 deletions(-)

diff --git a/fs/doc/file.txt b/fs/doc/file.txt @@ -35,6 +35,24 @@ fnewfile ( dirid name -- id ) Create a new empty file named "name" in "dirid" and return the ID of the new file. Aborts on error. +## Common API + +On top of those words, the File subsystem implements those words: + +chdir ( path -- ) + Change current directory to path. In subsequent path finds, if the path + doesn't start with "/", the search will start from this directory. + Aborts if path is not found. + +findpathdir ( path -- dirid? name-or-0 ) + Find FS ID corresponding to the directory part of the path. + Returns the id of the directory as well as the name of the last part of the + path. If dir is not found, name is 0 and dirid is not on PS. + "name" becomes invalid on the next findpathdir call. + +findpath ( path -- id-or-0 ) + Find FS ID corresponding to path or 0 if not found. + ## File ID design considerations When we refer to a file or directory ID, we refer to a single 32-bit number diff --git a/fs/fs/fatlo.fs b/fs/fs/fatlo.fs @@ -95,7 +95,9 @@ here const )fnbuf : upcase ( c -- c ) dup 'a' - 26 < if $df and then ; : fnbufclr fnbuf( FNAMESZ SPC fill ; : fnbuf! ( name -- ) - A>r fnbufclr c@+ >r >A fnbuf( begin ( dst ) + fnbufclr dup S" ." s= over S" .." s= or if + c@+ ( a len ) fnbuf( swap move exit then + A>r c@+ >r >A fnbuf( begin ( dst ) Ac@+ dup '.' = if 2drop fnbuf( 8 + else upcase swap c!+ then ( dst+1 ) @@ -110,8 +112,8 @@ here const )fnbuf \ Find current fnbuf( in current dir buffer and return a dir entry. : findindir ( -- direntry ) begin - _ ?dup not while nextsector? not if abort" file not found" then - repeat ; + _ ?dup not while nextsector? while + repeat ( not found ) 0 then ; \ Read specified "direntry" in fatbuf( : readdir ( direntry -- ) @@ -129,8 +131,8 @@ here const )fnbuf \ Get ID for direntry : getid ( direntry -- id ) fatbuf( - bufsec BPB_BytsPerSec * + ; -: fatchild ( dirid name -- id ) - fnbuf! getdirentry readdir findindir getid ; +: fatchild ( dirid name -- id-or-0 ) + fnbuf! getdirentry readdir findindir dup if getid then ; \ Find the parent directory of "path", that is, go up directories in path until \ the last element is reached, but don't look for that last element, return diff --git a/fs/sys/file.fs b/fs/sys/file.fs @@ -3,14 +3,34 @@ ?f<< /lib/with.fs ?f<< /lib/io.fs +0 value curdir +create _buf $100 allot + +: findpathdir ( path -- dirid? name-or-0 ) + A>r 0 _buf c!+ >A c@+ ( a len ) + over c@ '/' = if 1- >r 1+ 0 ( root ) else >r curdir then swap + begin ( dirid a ) + c@+ dup '/' = if ( dirid a c ) + drop swap _buf fchild ( a dirid ) + ?dup not if drop 0 r~ r>A exit then swap ( dirid a ) + 0 _buf c!+ >A + else ( dirid a c ) + Ac!+ _buf c@ 1+ _buf c! then + next ( dirid a ) drop _buf r>A ; + +: findpath ( path -- id-or-0 ) + findpathdir ?dup if fchild else 0 then ; + +: chdir ( path -- ) findpath ?dup if to curdir else abort" not found" then ; + +: fseek ( pos hdl -- ) dup 12 + @ execute ; +: fclose ( hdl -- ) dup 16 + @ execute ; + \ We need a private scratchpad here because some cursors can be quite \ long-lived. If we use the system scratchpad, short-lived data will overwrite \ 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/tests/fs/fat.fs b/fs/tests/fs/fat.fs @@ -18,14 +18,6 @@ $ffd over fatseek dup fatgetc 'E' #eq dup fatgetc 'O' #eq dup fatgetc 'F' #eq dup fatgetc -1 #eq fatclose -\ test chdir and relative find -S" lib" fatchdir -S" str.fs" fatfindpath # \ found! -S" /lib/str.fs" fatfindpath # \ found! -\ can we come back one level? -S" .." fatchdir -S" lib/str.fs" fatfindpath # \ found! -S" /lib/str.fs" fatfindpath # \ found! \ can we create a new file? S" newfile" fatnewfile # S" /newfile" fatfindpath # \ found! diff --git a/fs/tests/sys/all.fs b/fs/tests/sys/all.fs @@ -1,2 +1,3 @@ \ Run all sys test suites -f<< tests/sys/drive.fs +f<< /tests/sys/drive.fs +f<< /tests/sys/file.fs diff --git a/fs/tests/sys/file.fs b/fs/tests/sys/file.fs @@ -0,0 +1,16 @@ +?f<< tests/harness.fs +?f<< sys/file.fs +testbegin +\ Tests for sys/file +\ test chdir and relative find +S" lib" chdir +S" str.fs" findpath # \ found! +S" /lib/str.fs" findpath # \ found! +\ can we come back one level? +S" .." chdir +S" lib/str.fs" findpath # \ found! +S" /lib/str.fs" findpath # \ found! +\ what if it doesn't exist? +S" lib/nope.fs" findpath not # \ not found! +S" /nope.fs" findpath not # \ not found! +testend diff --git a/fs/xcomp/glue2.fs b/fs/xcomp/glue2.fs @@ -1,3 +1,4 @@ bootfile xcomp/glue2.fs \ Glue code that goes between the filesystem part and boothi alias fatopenlo fopen +alias fatchild fchild