Author: wmb Date: 2007-05-20 06:32:57 +0200 (Sun, 20 May 2007) New Revision: 404
Modified: ofw/fs/jffs2/jffs2.fth Log: JFFS2 - reduce memory usage for dirents.
Modified: ofw/fs/jffs2/jffs2.fth =================================================================== --- ofw/fs/jffs2/jffs2.fth 2007-05-20 04:31:54 UTC (rev 403) +++ ofw/fs/jffs2/jffs2.fth 2007-05-20 04:32:57 UTC (rev 404) @@ -31,10 +31,12 @@ variable 'next-dirent \ Pointer into dirent buffer : next-dirent ( -- val ) 'next-dirent @ ;
-\ 0 ( instance ) value minodes \ Buffer for per-file inode list +\ minodes is an area that is used for constructing dynamic lists +\ that don't persist between opens + variable 'next-minode \ Pointer into per-file inode list -: next-minode 'next-minode @ ; -: minodes next-inode ; \ Start the inode pointer list after the inodes +: next-minode ( -- adr ) 'next-minode @ ; +: minodes ( -- adr ) next-inode ; \ Start the inode pointer list after the inodes
0 instance value file-buf \ Buffer for constructing file 0 instance value file-size \ Actual size of file @@ -49,49 +51,12 @@ 0 instance value the-page# 0 instance value the-eblock#
-\ In-memory inode structure - \ Access a field within a JFFS2 FLASH data structure : j@ ( adr offset -- value ) la+ l@ ; : j! ( adr offset -- value ) la+ l! ;
-\ Access fields within the memory data structure for volume inodes -\ Based on struct jffs2_sum_inode_flash, with "nodetype" replaced -\ by the eblock number. This is not the complete inode data, just -\ the part that is in the summary node. It is just enough information -\ to let us create the list of inodes associated with a given file. -\ Having created that list, we can get the full inodes from FLASH. -\ Storing it in this form saves space and time, because we only have -\ to read the full inodes for the few files that we actually access. +: pack-offset ( offset -- n ) the-eblock# /eblock * + ;
-instance variable splices 0 splices ! - -: pack-offset ( offset block -- n ) the-eblock# /eblock * + ; - -: minum@ ( adr -- inode# ) 0 j@ ; -: mversion@ ( adr -- version ) 1 j@ ; -: moffset@ ( adr -- block+offset ) 2 j@ ; -\ : moffset/block@ ( adr -- offset block ) moffset@ /eblock /mod ; -\ : meblock@ ( adr -- eblock# ) 0 j@ ; -\ : moffset@ ( adr -- offset ) 3 j@ ; -\ 4 /l* constant /mem-inode -3 /l* constant /mem-inode -\ : mtotlen@ ( adr -- offset ) 4 j@ ; -\ 5 /l* constant /mem-inode - -\ Fields within in-memory directory entry data structure. -\ Based on struct jffs2_sum_dirent_flash, without the -\ "nodetype", "totlen", and "offset" fields. - -: pino@ ( adr -- parent ) 0 j@ ; -: version@ ( adr -- version ) 1 j@ ; \ $find-name and insert-dirent -: dirino@ ( adr -- inode ) 2 j@ ; -: ftype@ ( adr -- type ) d# 13 + c@ ; -: fname$ ( node-adr -- adr len ) - dup d# 14 + ( node-adr name-adr ) - swap d# 12 + c@ ( name-adr name-len ) -; - \ Access fields in per-file raw inode structure - based on \ struct jffs2_raw_inode : riinode@ ( adr -- inode# ) 3 j@ ; @@ -114,22 +79,6 @@ \ see forth/lib/crc32.fth and cpu/x86/crc32.fth : crc ( adr len -- crc ) 0 crctab 2swap ($crc) ;
-: set-sizes ( -- ) - -1 to file-size - - " block-size" $call-parent to /page - - " erase-size" ['] $call-parent ( adr len xt ) - catch if 2drop h# 20000 then ( n ) - to /eblock - - /eblock /page / to pages/eblock - - " size" $call-parent ( d ) - /page um/mod to pages/chip ( rem ) - drop -; - : dma-alloc ( len -- adr ) " dma-alloc" $call-parent ; : dma-free ( len -- adr ) " dma-free" $call-parent ;
@@ -232,8 +181,15 @@ \ 0 instance variable cur-vers \ 0 instance variable cur-offset
-: init-curvars ( -- ) curinum 3 /n* erase ; +instance variable dirent-offset +instance variable cur-pino
+: init-curvars ( -- ) + h# -100000 dup dirent-offset ! curoffs ! + 0 curinum ! + 0 curvers ! +; + 1 [if] code aencode-inode ( version inum offset 'curinum 'next-inode -- ) dx pop \ dx: 'next-inode @@ -448,20 +404,60 @@ d# 18 ( len ) ;
+: encode-dirent ( boffset pino adr len -- ) + 2 pick >r ( boffset pino adr len r: pino ) + crctab -rot ($crc) ( boffset hash ) + next-dirent ! ( boffset ) + + pack-offset ( offset ) + + dup dirent-offset @ - 2 rshift ( offset delta ) + dup h# 10000 < ( offset delta short-offset? ) + r@ cur-pino @ = and ( offset delta short-encode? ) + + if ( offset delta ) + next-dirent na1+ w! ( offset ) + 6 ( offset de-len ) + else ( offset ) + drop 0 next-dirent na1+ w! ( offset ) + r@ next-dirent 6 + ! ( offset ) \ Encode pino + dup next-dirent d# 10 + ! ( offset ) \ Encode offset + d# 14 ( offset de-len ) + then ( offset r: pino ) + r> cur-pino ! ( offset de-len ) + 'next-dirent +! ( offset ) + dirent-offset ! ( ) +; + +: w@+ ( adr -- w adr' ) dup w@ swap wa1+ ; +: l@+ ( adr -- l adr' ) dup l@ swap la1+ ; + +: decode-dirent ( adr -- false | adr' offset pino hash true ) + dup next-dirent >= if drop false exit then + l@+ ( hash adr' ) + w@+ ( hash w adr' ) + swap ?dup if ( hash adr' w ) \ Short form + swap -rot ( adr' hash w ) + /l* dirent-offset +! ( adr' hash ) + dirent-offset @ ( adr' hash offset ) + cur-pino @ rot ( adr' offset pino hash ) + else ( hash adr' ) \ Long form + l@+ over cur-pino ! ( hash pino adr' ) + l@+ over dirent-offset ! ( hash pino offset adr' ) + swap 2swap swap ( adr' offset pino hash ) + then + true +; + \ Copy summary dirent from FLASH to memory \ Summary dirent: w.nodetype l.totlen l.offset l.pino l.version \ l.ino c.nsize c.type name : scan-sum-dirent ( adr -- len ) - d# 10 + ( offset-adr ) - next-dirent ( offset-adr dst-adr ) - over d# 12 + c@ d# 14 + ( src dst len ) - dup >r ( src dst len r: len ) - move ( ) - - r@ 'next-dirent +! ( offset-adr ) - - \ 10 is the length of the fields that were skipped, not copied - r> d# 10 + ( len ) + 2+ >r + r@ 1 j@ r@ 2 j@ ( offset pino ) + r@ d# 22 + r> 5 la+ c@ ( offset pino adr namelen ) + dup >r encode-dirent ( r: namelen ) + r> d# 24 + ( len ) ;
[ifdef] notdef @@ -493,9 +489,6 @@ 2drop ; : no-summary? ( page# -- flag ) -\ drop true - -\ dup h# 47100 = if debug-me then dup pages/eblock + 1- 1 read-pages if ( page# ) drop true exit then ( page# ) @@ -550,22 +543,11 @@ : rdnsize@ ( adr -- nsize ) 7 la+ c@ ; : rdtype@ ( adr -- type ) 7 la+ 1+ c@ ; : >rdname ( adr -- adr' ) d# 10 la+ ; +: rdname$ ( adr -- adr len ) dup >rdname swap rdnsize@ ;
: scan-raw-dirent ( adr -- adr ) -\ XXX dup 1 j@ 4 round-up ( adr len ) -\ XXX 2dup next-dirent swap move ( adr len ) - \ - next-dirent - over rdpino@ l+! - over rdversion@ l+! - over rdinode@ l+! ( adr iadr' ) - over rdnsize@ c+! ( adr iadr' ) - over rdtype@ c+! ( adr iadr' ) - over >rdname swap ( adr str-adr iadr ) - 2 pick rdnsize@ move ( adr ) - dup rdnsize@ d# 14 + ( adr dirent-len ) - - 'next-dirent +! ( adr ) + dup >r + r@ block-buf - r@ rdpino@ r> rdname$ encode-dirent ;
\ Copy the raw inode information to memory in summary inode form @@ -574,8 +556,6 @@ \ we actually access. : scan-raw-inode ( adr -- ) >r r@ riversion@ r@ riinode@ r> block-buf - pack-offset ( version inum offset ) -\ store-inode -\ encode-inode curinum 'next-inode aencode-inode \ false to cleanmark? ; @@ -640,6 +620,11 @@ ;
0 [if] +\ This is some unfinished filesystem consistency checking code +\ It was started for debugging a crash that turned out to be +\ caused by overflow of the memory tables, leading to a rewrite +\ to use much less memory. + /eblock value summary-start
: .eb ( -- ) @@ -722,7 +707,7 @@ crc swap ridcrc@ = ;
-: get-inode ( offset -- adr ) /eblock /mod read-eblock block-buf + ; +: get-node ( offset -- adr ) /eblock /mod read-eblock block-buf + ;
\ This is a brute-force, no tricks, insertion sort. \ Insertion sort is bad for large numbers of elements, but in this @@ -758,7 +743,7 @@ \ and if it is valid, replace the existing one. We will \ end up with only the last good one in the slot. drop ( offset ) - dup get-inode inode-good? if ( offset ) + dup get-node inode-good? if ( offset ) i na1+ ! ( ) else ( offset ) drop ( ) @@ -773,23 +758,25 @@ ;
-\ Also used by insert-dirent -: place-node ( node where -- ) - ! - /n 'next-minode +! ( ) -; +\ Information that we need about the working file/directory +\ The working file changes at each level of a path search
-\ This is used for symlinks and directory inodes where there -\ can only be one of them. --1 value max-version \ Local variable for latest-node and $find-name -\ -1 value the-inode \ Local variable for latest-node +0 instance value wd-inum \ Inumber of directory +0 instance value wf-inum \ Inumber of file or directory +0 instance value wf-type \ Type - 4 for directory, d# 10 for symlink, etc + +: set-root ( -- ) 1 to wd-inum 1 to wf-inum 4 to wf-type ; + +\ latest-node is for symlinks and directories, which have only one data node. + +-1 value max-version \ Local variable for latest-node -1 value the-offset \ Local variable for latest-node -: latest-node ( inum -- true | offset false ) - init-curvars - -1 to max-version + +: latest-node ( inum -- true | rinode false ) + init-curvars -1 to max-version ( inum ) inodes begin next-inode curinum amatch-inode while ( inum inode' offset version ) -\ inodes begin match-inode while ( inum inode' offset version ) - over get-inode inode-good? if ( inum inode' offset version ) +\ inodes begin match-inode while ( inum inode' offset version ) + over get-node inode-good? if ( inum inode' offset version ) dup max-version > if ( inum inode' offset version ) to max-version ( inum inode' offset ) to the-offset ( inum inode' ) @@ -802,10 +789,13 @@ repeat ( inum ) drop max-version -1 = if true exit then - the-offset false + the-offset get-node false ;
-: collect-nodes ( inum -- any? ) +\ collect-node is for ordinary files which can have many data nodes + +: collect-nodes ( -- any? ) + wf-inum init-curvars minodes 'next-minode ! \ Empty the list
@@ -877,20 +867,12 @@ r> outpos @ ?outlen ( ) ;
-: .inode ( inode - ) - ." tot " dup riisize@ 8 u.r space - ." len " dup ridsize@ 8 u.r space - ." extent " dup rioffset@ over ridsize@ + 8 u.r space - ." comp " ricompr@ 3 u.r - cr -; : (play-inode) ( inode -- ) dup inode-good? 0= if ( inode ) debug-scan? if ." Skipping bad inode." cr then drop exit then
- debug-scan? if dup .inode cr then >r r@ riisize@ r@ rioffset@ r@ ridsize@ + set-length
@@ -910,22 +892,14 @@ -1 to the-eblock# -1 to have-eblock# 0 to file-size - next-minode minodes ?do i na1+ @ get-inode (play-inode) 8 +loop + next-minode minodes ?do i na1+ @ get-node (play-inode) 8 +loop
release-inflater ; : ?play-log ( -- ) file-size -1 = if play-log then ;
-: .ftype ( adr -- ) - ftype@ 2/ 0 max " / @=" rot min + c@ emit -; +: +dirent ( adr -- adr' ) na1+ dup w@ 0= if 2 na+ then wa1+ ;
-: .fname ( dirent -- ) - dup fname$ space space type space .ftype -; - -: +dirent ( adr -- adr' ) 3 la+ dup c@ + 2+ ; - : #dirents ( -- n ) 0 next-dirent dirents ( n endadr adr ) @@ -935,164 +909,175 @@
char \ instance value delimiter
-create root-dirent - 0 , \ pino - 0 , \ version - 1 , \ ino - 0 c, \ nsize - 4 c, \ type +defer $resolve-path +d# 1024 constant /symlink \ Max length of a symbolic link
--1 instance value pwd -: set-root ( -- dirent ) root-dirent dup to pwd ; - -: strip\ ( name$ dirent -- name$' dirent' ) - -rot - dup 0<> if ( dirent name$ ) - over c@ delimiter = if ( dirent name$ ) - 1 /string ( dirent name$ ) - rot drop set-root -rot ( dirent name$ ) - then ( dirent name$ ) - then ( dirent name$ ) - rot +: strip\ ( name$ -- name$' ) + dup 0<> if ( name$ ) + over c@ delimiter = if ( name$ ) + 1 /string ( name$ ) + set-root ( name$ ) + then ( name$ ) + then ( name$ ) ;
-: dir-match? ( name$ par adr -- flag ) - tuck pino@ <> if ( name$ adr ) - 3drop false ( false ) - else ( name$ adr ) - fname$ $= ( flag ) - then +0 instance value my-vers \ Highest version number - local to $find-name + +: ?update-dirent ( offset name$ -- ) + rot get-node >r ( name$ r: rdirent ) + r@ rdname$ $= if ( r: rdirent ) + wd-inum r@ rdpino@ = if ( r: rdirent ) + r@ rdversion@ my-vers > if ( r: rdirent ) + r@ rdversion@ to my-vers ( r: rdirent ) + r@ rdinode@ to wf-inum ( r: rdirent ) + r@ rdtype@ to wf-type ( r: rdirent ) + then ( r: rdirent ) + then ( r: rdirent ) + then ( r: rdirent ) + r> drop ( ) ;
--1 ( instance ) value the-dirent \ Local variable for $find-name -: $find-name ( name$ dirent -- true | dirent false ) - -1 to max-version - dirino@ ( name$ parent-inode ) - dirents ( name$ parent-inode adr ) - begin dup next-dirent u< while ( $ par adr ) +: $find-name ( name$ -- error? ) + -1 to my-vers ( name$ ) + wd-inum crctab 2over ($crc) >r ( name$ r: hash )
- \ Look for a directory type dirent with the right name and parent - 2over 2over dir-match? if ( $ par adr ) - - \ If this is the latest version, record its inode - dup version@ max-version > if - dup version@ to max-version - dup to the-dirent - then - then - +dirent - repeat ( name$ parent adr ) - 4drop - max-version 0< if true exit then - the-dirent false + 0 dirent-offset ! + dirents begin decode-dirent while ( name$ adr' offset pino' hash' ) + nip ( name$ adr offset hash' ) + \ Check for a hash match + r@ = if ( name$ adr offset ) + 2over ?update-dirent ( name$ adr ) + else ( name$ adr offset ) + drop ( name$ adr ) + then ( name$ adr ) + repeat ( name$ adr r: hash ) + 2drop r> drop ( ) + my-vers 0< if true exit then ( ) + wf-type 4 = if wf-inum to wd-inum then + false ;
-defer $resolve-path -d# 1024 constant /symlink \ Max length of a symbolic link - -\ The input dirent is for a symlink. Resolve it to a new dirent -: dir-link ( dirent -- true | dirent' false ) +\ The work file is a symlink. Resolve it to a new dirent +: dir-link ( -- error? ) delimiter >r [char] / to delimiter + + \ Allocate temporary space for the symlink value (new name) /symlink alloc-mem >r
- dirino@ latest-node if ( ) + wf-inum latest-node if ( ) true - else ( offset ) - get-inode ( rinode ) + else ( rinode ) dup >ridata swap ridsize@ ( adr len ) tuck r@ swap move ( len ) - r@ swap pwd $resolve-path ( true | dirent false ) + r@ swap $resolve-path ( error? ) then
r> /symlink free-mem r> to delimiter ;
-: $find-path ( path$ dirent -- true | dirent' false ) - begin strip\ over while ( path$ dirent' ) - dup ftype@ case ( path$ dirent c: type ) +: ($resolve-path) ( path$ -- error? ) + 4 to wf-type + begin strip\ dup while ( path$ ) + wf-type case ( path$ c: type ) + 4 of \ Directory ( path$ ) + delimiter left-parse-string ( rem$' head$ ) + $find-name if 2drop true exit then ( rem$ ) + endof ( rem$ )
- 4 of \ Directory ( path$ dirent ) - dup to pwd ( path$ dirent ) - >r delimiter left-parse-string r> ( rem$' head$ dirent ) - $find-name if ( rem$' ) - 2drop true exit - then ( rem$ dirent ) - endof ( rem$ dirent ) + d# 10 of \ symlink ( rem$ ) + dir-link if 2drop true exit then ( rem$ ) + endof ( rem$ ) + ( default ) ( rem$ c: type )
- d# 10 of ( rem$ dirent ) - dir-link if ( rem$ ) - 2drop true exit - then ( rem$ dirent ) - endof ( rem$ dirent ) \ symlink - ( default ) ( rem$ dirent c: type ) - \ The parent is an ordinary file or something else that \ can't be treated as a directory - 4drop true exit - endcase ( rem$ dirent ) - repeat ( rem$ dirent ) - nip nip false ( dirent ) + 3drop true exit + endcase ( rem$ ) + repeat ( rem$ ) + 2drop false ( false ) ; -' $find-path to $resolve-path
-\ Leaves pwd set to the containing directory -: $chdir ( path$ -- error? ) - $find-path if true exit then ( inode ) - ftype@ 4 <> \ Return false (no error) if it's a directory -; +\ Leaves the-wd set to the containing directory +\ : $chdir ( path$ -- error? ) +\ \ XXX should save wf-* and restore them on failure +\ $resolve-path if true exit then ( dirent ) +\ wf-type 4 <> \ Return true (error) if it's not a directory +\ ;
-: advance-dirent ( dirent -- false | dirent' true ) - pwd dirino@ swap ( parent-inode dirent ) - begin dup next-dirent u< while ( par dirent ) - 2dup pino@ = if ( par dirent ) - nip true exit - then ( par dirent ) - +dirent ( par dirent' ) - repeat ( par dirent' ) - 2drop false +' ($resolve-path) to $resolve-path + +\ "tdirent" section + +\ This section makes a list of directory entries for a given directory. +\ It is used only by "next-file-info". It scans the in-memory abbreviated +\ directory list, looking for entries whose parent inum matches that of +\ the current directory. It checks for duplicate names, superseding +\ older versions and removing unlinked ones. + +: tdinum@ ( tdirent -- inum ) l@ ; +: tdversion@ ( tdirent -- vers ) la1+ l@ ; +: tdname$ ( tdirent -- name$ ) 2 la+ count ; +: tdlen ( tdirent -- len ) dup tdname$ + swap - ; + +\ Move down all the following tdirents to overwrite the current one. + +: remove-tdirent ( tdirent -- ) + dup tdlen ( tdirent len ) + 2dup + ( tdirent len next-tdirent ) + rot ( len next-tdirent tdirent ) + next-minode 2 pick - ( len next-tdirent tdirent move-len ) + move ( len ) + negate 'next-minode +! ( ) +; +: replace-tdirent ( rdirent tdirent -- ) + over rdinode@ over l! ( rdirent tdirent' ) \ Inum + swap rdversion@ swap la1+ l! ( ) \ Version ;
-: insert-dirent ( dirent -- ) - minodes begin dup next-minode u< while ( dirent listadr ) - over fname$ 2 pick @ fname$ $= if ( dirent listadr ) - over version@ over @ version@ > if ( dirent listadr ) - ! ( ) - else ( dirent listadr ) - 2drop ( ) - then ( ) - exit - then ( dirent listadr ) - na1+ ( dirent listadr' ) - repeat ( dirent listadr ) - place-node ( ) +: place-tdirent ( rdirent -- ) + next-minode ( rdirent tdirent ) + over rdinode@ l+! ( rdirent tdirent' ) + over rdversion@ l+! ( rdirent tdirent' ) + swap rdname$ ( tdirent name$ ) + rot pack ( tdirent ) + count + 'next-minode ! ( ) ;
-\ Having collected the list of directory entries for the current -\ target directory, we must prune the list to remove unlinked ones. -: remove-unlinks ( -- ) - minodes begin dup next-minode < while ( minode ) - dup @ dirino@ if ( minode ) - na1+ ( minode' ) - else ( minode ) - \ Deleted, remove from list - -1 /n* 'next-minode +! ( minode ) - dup na1+ over ( minode src dst ) - next-minode over - move ( minode ) - then ( minode' ) - repeat ( minode' ) - drop ( ) +: insert-dirent ( offset -- ) + get-node ( rdirent ) + next-minode minodes ?do ( rdirent ) + dup rdname$ i tdname$ $= if ( rdirent ) \ Same name + dup rdversion@ i tdversion@ > if ( rdirent ) \ New version + dup rdinode@ if ( rdirent ) + dup i replace-tdirent ( rdirent ) \ Not unlinked + else ( rdirent ) + i remove-tdirent ( rdirent ) \ Unlinked + then ( rdirent ) + then ( rdirent ) + drop unloop exit + then ( rdirent ) + i tdlen ( rdirent ) + +loop ( rdirent ) + place-tdirent ( ) ; + : prep-dirents ( -- ) minodes 'next-minode ! \ Empty the list - dirents - begin advance-dirent while - dup insert-dirent - +dirent - repeat - remove-unlinks + dirents begin decode-dirent while ( adr offset pino hash ) + drop wd-inum = if ( adr offset ) + insert-dirent ( adr ) + else ( adr offset ) + drop ( adr ) + then ( adr ) + repeat ( ) ;
+\ End of "tdirent" section + +false [if] +\ "delete file" section + \ For now, just 0 the modify time, since we only support deleting : now-seconds ( -- secs ) 0 ;
@@ -1145,15 +1130,18 @@ 1 <> if ." JFFS2: write failed" then ( ) ;
-\ pwd is the parent dirent +\ the-wd is the parent dirent : $delete ( adr len -- error? ) - pwd $resolve-path dup if true exit then ( dirent' ) - >r r@ pino@ r@ version@ 1+ r> fname$ ( parent-ino new-version name$ ) + $resolve-path if true exit then ( dirent' ) + >r r@ xxpino@ r@ xxversion@ 1+ r> xxfname$ ( parent-ino new-version name$ ) 0 0 make-raw-dirent ( adr len ) find-empty-page ( adr len page# ) put-node ;
+\ End of "delete file" section +[then] + decimal
headerless @@ -1167,6 +1155,22 @@ : update-ptr ( len' -- len' ) dup seek-ptr + to seek-ptr ; : 'base-adr ( -- adr ) seek-ptr file-buf + ;
+: set-sizes ( -- ) + -1 to file-size + + " block-size" $call-parent to /page + + " erase-size" ['] $call-parent ( adr len xt ) + catch if 2drop h# 20000 then ( n ) + to /eblock + + /eblock /page / to pages/eblock + + " size" $call-parent ( d ) + /page um/mod to pages/chip ( rem ) + drop +; + headers external : seek ( d.offset -- status ) @@ -1196,21 +1200,20 @@
my-args " <NoFile>" $= if true exit then
- my-args set-root $resolve-path if false ?release exit then ( dirent ) + my-args set-root $resolve-path if false ?release exit then ( )
begin \ We now have the dirent for the file at the end of the string - dup ftype@ case ( dirent ) - 4 of to pwd true exit endof \ Directory - 8 of dirino@ collect-nodes ?release exit endof \ Regular file - d# 10 of \ Link - dir-link if false ?release exit then ( dirent ) - endof + wf-type case + 4 of wf-inum to wd-inum true exit endof \ Directory + 8 of collect-nodes ?release exit endof \ Regular file + d# 10 of dir-link if false ?release exit then endof \ Link ( default ) \ Anything else (special file) is error - 2drop false ?release exit - endcase ( dirent ) + drop false ?release exit + endcase again ; + : close ( -- ) release-buffers ;
: size ( -- d.size ) ?play-log file-size 0 ; @@ -1264,104 +1267,25 @@ \ End of common code
: next-file-info ( id -- false | id' s m h d m y len attributes name$ true ) - dup 0= if drop prep-dirents minodes then ( minode ) - dup next-minode = if drop false exit then ( minode ) - dup @ >r na1+ ( id' r: dirent ) - r@ dirino@ latest-node if ( id' r: dirent ) - 0 0 0 0 0 0 ( id' s m h d m y r: dirent ) - 0 ( ... len r: dirent ) - 0 ( ... attributes r: dirent ) - else ( id' offset r: dirent ) - get-inode >r ( id' r: dirent rinode ) - r@ rimtime@ sec>time&date ( id' s m h d m y r: dirent rinode ) - r@ riisize@ ( id' s m h d m y len r: dirent rinode ) - r> rimode@ ( id' s m h d m y len mode r: dirent ) + dup 0= if drop prep-dirents minodes then ( tdirent ) + dup next-minode = if drop false exit then ( tdirent ) + dup >r dup tdlen + ( id' r: tdirent ) + r@ tdinum@ latest-node if ( id' r: tdirent ) +." Can't find data node" cr + 0 0 0 0 0 0 ( id' s m h d m y r: tdirent ) + 0 ( ... len r: tdirent ) + 0 ( ... attributes r: tdirent ) + else ( id' rinode r: tdirent ) + >r ( id' r: tdirent rinode ) + r@ rimtime@ sec>time&date ( id' s m h d m y r: tdirent rinode ) + r@ riisize@ ( id' s m h d m y len r: tdirent rinode ) + r> rimode@ ( id' s m h d m y len mode r: tdirent ) then - r> fname$ true + r> tdname$ true ;
: free-bytes ( -- d.#bytes ) 0 0 ;
- -\ create debug-jffs -[ifdef] debug-jffs -\needs mcr : mcr cr exit? if abort then ; - -\ Tools for dumping the dirent table, for debugging -: .ldirent-hdr ( -- ) - ." Inode Version Eblock Offs Parent Name" cr -; -: .ldirent ( adr -- adr' ) - dup dirino@ 8 u.r \ Inode - dup version@ 8 u.r \ Version - dup eblock@ 7 u.r \ Eblock# - dup offset@ 6 u.r \ Offset on eblock - dup pino@ 7 u.r \ Parent Inode - dup .fname mcr - +dirent -; - -: .dirents ( -- ) - .ldirent-hdr - next-dirent dirents ( endadr adr ) - begin 2dup > while .ldirent repeat ( endadr adr ) - 2drop -; - - -: .inode-hdr ( -- ) ." Inode Version Eblock Offs" cr ; -: .inode ( adr ) - dup minum@ 8 u.r \ Inode - dup mversion@ 8 u.r \ Version - dup moffset@ /eblock /mod 7 u.r 6 u.r \ Eblock#, offset on eblock -\ dup mtotlen@ 8 u.r \ Total length - mcr - /mem-inode + -; - -: .inodes ( -- ) - .inode-hdr - next-inode inodes ( endadr adr ) - begin 2dup > while .inode repeat ( endadr adr ) - 2drop -; - -: .dirent ( adr parent -- adr' ) - over pino@ = if ( adr ) \ Check Parent Inode -\ dup version@ 8 u.r \ Version - dup dirino@ 8 u.r \ Inode - dup .fname mcr - then ( adr ) - +dirent ( adr' ) -; - -: .dir ( parent-inode -- ) - >r - next-dirent dirents ( endadr adr ) - begin 2dup > while r@ .dirent repeat ( endadr adr ) - 2drop - r> drop -; - -: $fdir ( path$ -- ) - $resolve-path abort" Not found" ( dirent ) - dup ftype@ 4 = if - dirino@ .dir - else - dup dirino@ . .fname cr - then -; - -: dir parse-word set-root $fdir ; - -: expand-file ( inum -- ) - collect-nodes 0= abort" none" - play-log -; -[then] - - - \ LICENSE_BEGIN \ Copyright (c) 2006 FirmWorks \