~vdupras/duskos

2e0d6f71ebc7994b028ddd77772c007a68deed34 — Virgil Dupras a month ago 18d3f30
fs/boot: add findpath
2 files changed, 26 insertions(+), 9 deletions(-)

M fs/fs/boot.fs
M fs/tests/fs/boot.fs
M fs/fs/boot.fs => fs/fs/boot.fs +25 -7
@@ 48,22 48,28 @@ here value )FAT16
\ can have more than BPB_RootEntCnt entries.
create dirbuf( RootDirSectors BPB_BytsPerSec * allot
here const )dirbuf
create fnbuf FNAMESZ allot
create fnbuf( FNAMESZ allot
here const )fnbuf

: upcase ( c -- c ) dup 'a' - 26 < if $df and then ;
: fnbufclr fnbuf( FNAMESZ SPC fill ;

\ we assume a 8.3 name. Don't call this with an inadequate name.
: _tofnbuf ( fname -- )
  A>r >A Ac@+ >r fnbuf FNAMESZ SPC fill fnbuf begin ( a )
    Ac@+ dup '.' = if ( a c ) 2drop fnbuf 8 + else upcase swap c!+ then
  A>r >A Ac@+ >r fnbufclr fnbuf( begin ( a )
    Ac@+ dup '.' = if ( a c ) 2drop fnbuf( 8 + else upcase swap c!+ then
    next drop r>A ;
\ Search in directory that is currently loaded in dirbuf.
\ Return address of directory entry, abort if not found.
: findindir ( fname -- direntry ) _tofnbuf

: _findindir ( -- direntry )
  dirbuf( begin ( a )
    dup )dirbuf < while ( a )
    fnbuf over DIR_Name []= not while ( a ) DIRENTRYSZ + repeat
    fnbuf( over DIR_Name []= not while ( a ) DIRENTRYSZ + repeat
    ( success ) else ( not found ) abort" file not found" then ( a ) ;

\ Search in directory that is currently loaded in dirbuf.
\ Return address of directory entry, abort if not found.
: findindir ( fname -- direntry ) _tofnbuf _findindir ;

\ Make the current dir the root
: readroot FirstRootDirSecNum RootDirSectors dirbuf( readsectors ;



@@ 85,6 91,18 @@ create fnbuf FNAMESZ allot
    ClusterSize + swap nextcluster swap repeat ( cluster buf )
  2drop ;


: findpath ( path -- direntry )
  A>r fnbufclr fnbuf( >A c@+ >r readroot begin ( a )
    c@+ dup emit case
      '.' of = fnbuf( 8 + >A endof
      '/' of = _findindir readdir fnbufclr fnbuf( >A endof
      r@ upcase Ac!+ A> )fnbuf = if abort" filename too long!" then
    endcase
  next drop
  \ at the point, the correct subdir is read and the final filename is in fnbuf(
  _findindir r>A ;

\ File cursor
\ 2b first cluster 0=free cursor
\ 2b current cluster in buf

M fs/tests/fs/boot.fs => fs/tests/fs/boot.fs +1 -2
@@ 10,8 10,7 @@ testbegin
\ Tests for fs/boot
readFAT
readroot
S" tests" findindir readdir
S" fattest" findindir ( dirent )
S" tests/fattest" findpath ( dirent )
openfile ( fcursor ) dup fat16getc 'T' #eq
dup $ff readN ( fcursor )
dup fat16getc 'f' #eq dup fat16getc 'o' #eq dup fat16getc 'o' #eq