[OpenBIOS] r404 - ofw/fs/jffs2

svn at openbios.org svn at openbios.org
Sun May 20 06:32:57 CEST 2007


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 at +  ( adr -- w adr' )  dup w@ swap wa1+  ;
+: l at +  ( 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 at +                          ( hash adr' )
+   w at +                          ( 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 at + over cur-pino !       ( hash pino adr' )
+      l at + 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
 \ 




More information about the OpenBIOS mailing list