[openfirmware] r1377 - ofw/fs/cifs

svn at openfirmware.info svn at openfirmware.info
Thu Sep 24 12:22:16 CEST 2009


Author: wmb
Date: 2009-09-24 12:22:16 +0200 (Thu, 24 Sep 2009)
New Revision: 1377

Modified:
   ofw/fs/cifs/netbios.fth
   ofw/fs/cifs/smb.fth
Log:
CIFS - implemented next-file-info for dir command.


Modified: ofw/fs/cifs/netbios.fth
===================================================================
--- ofw/fs/cifs/netbios.fth	2009-09-24 06:14:06 UTC (rev 1376)
+++ ofw/fs/cifs/netbios.fth	2009-09-24 10:22:16 UTC (rev 1377)
@@ -1,3 +1,5 @@
+\ See license at end of file
+purpose: Netbios session layer of CIFS file system code
 
 d# 4096 constant max-data
 d# 4356 constant my-max-buf
@@ -213,3 +215,27 @@
       2drop false                  ( false )
    then                            ( error? )
 ;
+
+\ LICENSE_BEGIN
+\ Copyright (c) 2009 FirmWorks
+\ 
+\ Permission is hereby granted, free of charge, to any person obtaining
+\ a copy of this software and associated documentation files (the
+\ "Software"), to deal in the Software without restriction, including
+\ without limitation the rights to use, copy, modify, merge, publish,
+\ distribute, sublicense, and/or sell copies of the Software, and to
+\ permit persons to whom the Software is furnished to do so, subject to
+\ the following conditions:
+\ 
+\ The above copyright notice and this permission notice shall be
+\ included in all copies or substantial portions of the Software.
+\ 
+\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+\ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+\ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+\ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+\
+\ LICENSE_END

Modified: ofw/fs/cifs/smb.fth
===================================================================
--- ofw/fs/cifs/smb.fth	2009-09-24 06:14:06 UTC (rev 1376)
+++ ofw/fs/cifs/smb.fth	2009-09-24 10:22:16 UTC (rev 1377)
@@ -1,3 +1,15 @@
+\ See license at end of file
+purpose: Server Message Block layer of CIFS file system code
+
+\ This lets you access Windows shares from OFW
+
+\ TODO:
+\ fix opening dir when \ missing from end of URL
+\ next-file-info needs to merge pathname$ into search string
+\ test with other servers
+\ get password and username from config variables if they exist and not specified in URL
+
+
 char \ constant delim
 
 0. instance 2value share$
@@ -3,4 +15,6 @@
 0. instance 2value server$
 0. instance 2value password$
+0. instance 2value pathname$
+0. instance 2value tail$
 
 0. instance 2value account$
@@ -46,70 +60,23 @@
          over c@  delim =  if       ( filename$ tail$ )
             \ We found a \\         ( filename$ tail$ )
             2swap  2 pick - 1-      ( rem$ filename$' ) \ Remove tail
+            to pathname$            ( rem$ )
             exit
          then                       ( filename$ tail$ )
       then                          ( filename$ tail$ )
    repeat                           ( filename$ tail$ )
-   2swap                            ( null-rem$ filename$ )
+   2swap to pathname$               ( null-rem$ )
 ;
 
 : parse-share  ( share+path$ -- /path$ )
    delim split-string  2swap to share$  ( /path$ )
 ;
 
-\ If the filename itself contains "//", split it around that, returning
-\ filename$' as the portion preceding the "//" and "rem$" as the trailing
-\ portion beginning with the second "/" of the pair.
-\ For example, "/foo/bar//oof/rab" parses to "/oof/rab" "/foo/bar"
-: parse-filename  ( filename$ -- rem$ filename$' )
-   2dup                             ( filename$ test$ )
-   begin  dup  while                ( filename$ test$ )
-      delim split-string            ( filename$ head$ tail$ )
-      2swap 2drop                   ( filename$ tail$ )
-      dup  if  1 /string  then      ( filename$ tail$' )  \ Remove first "/"
-      dup  if                       ( filename$ tail$ )
-         over c@  delim =  if       ( filename$ tail$ )
-            \ We found a //         ( filename$ tail$ )
-            2swap  2 pick - 1-      ( rem$ filename$' ) \ Remove tail
-            exit
-         then                       ( filename$ tail$ )
-      then                          ( filename$ tail$ )
-   repeat                           ( filename$ tail$ )
-   2swap                            ( null-rem$ filename$ )
-;
-
 headers
 : set-server  ( server$ -- )
    dup  if  " $set-host" $call-parent  else  2drop  then
 ;
-: old-parse-server  ( server+share$ -- server$ )
-   \ If the string is shorter than 2 characters, the server portion is null
-   dup 2 <  if  " " exit  then             ( ss$ )
 
-   \ If the string doesn't start with \\, the server portion is null
-   over  " \\" comp  if  " " exit  then    ( ss$ )
-
-   2 /string                               ( server\share$ )
-   delim split-string                      ( server$ share$ )
-   2drop                                   ( server$ )
-;
-
-: old-parse-share  ( url$ -- rem$ server+share$ )
-   \ If the string is shorter than 2 characters, the server portion is null
-   dup 2 <  if  " " exit  then             ( url$ )
-
-   \ If the string doesn't start with \\, the server portion is null
-   over  " \\" comp  if  " " exit  then    ( url$ )
-
-   2dup 2 /string                          ( url$ $1 )  \ $1 omits the leading \\
-   delim left-parse-string                 ( url$ share+path$ server$ )
-   2drop                                   ( url$ share+path$ )
-   delim split-string                      ( url$ share$ path$ )
-   2nip                                    ( url$ path$ )
-   2swap                                   ( path$ url$ )
-   third -                                 ( path$ server+share$ )
-;
-
 8 instance buffer: signature
 h# c001 constant smb-flags
 h# c05c constant my-capabilities \ LargeRd, LargeWr, NTStat, NT SMBs, Large files, Unicode
@@ -117,6 +84,7 @@
 0 instance value tid
 0 instance value uid
 0 instance value mid
+0 instance value sid  \ Search ID
 0 instance value msg#
 
 0 instance value last-command
@@ -488,6 +456,13 @@
    }smb  empty-response       ( error? )
 ;
 
+: $getattr  ( path$ -- true | attr false )
+   8 smb{ +path}smb  if  true exit  then
+   d# 10 expect-wcnt    ( rem$' )
+   -xw                  ( rem$' attr )
+   nip nip  false
+;
+
 : flush  ( -- error? )
    5 smb{  fid +xw  --bytes--  }smb  empty-response
 ;
@@ -580,7 +555,195 @@
    2drop
 ;
 
+\ template
 0 [if]
+: transact  ( timeout oneway #setup #retdata #retparm #data #param -- )
+   h# 32 smb{
+   #param     +xw
+   #data      +xw
+   #retparm   +xw
+   #retdata   +xw
+   #setupdata +xb
+   0 +xb  \ Reserved
+   oneway     +xw
+   timeout    +xl
+   0 +xw  \ Reserved
+   parmcnt    +xw
+   parmoffset +xw
+   datacnt    +xw
+   dataoffset +xw
+   setupcnt   +xb
+   0 +xb  \ Reserved
+   [ setupcnt * +xw ]
+   --bytes--
+   " " +unicode$  \ Name (NULL for TRANSACTION2)
+   pad +xb    \ Pad to short or long
+   [ parmcnt * +xb ]
+   pad +xb    \ Pad to short or long
+   [ datacnt * +xb ]
+   }smb
+;
+
+[then]
+
+: continue-search  ( resumekey -- true | rem$ false )
+   1-            ( resumekey' )  \ We bias it by 1 because 0 is special to OFW
+   h# 32 smb{
+   d# 14    +xw  \ #param
+   0        +xw  \ #data
+   d# 10    +xw  \ #retparm
+   max-data +xw  \ #retdata
+   0        +xb  \ #setupdata
+   0        +xb  \ Reserved
+   0        +xw  \ flags - two way, no disconnect
+   0        +xl  \ timeout - return immediately
+   0        +xw  \ Reserved
+   d# 14    +xw  \ parmcnt
+   d# 66    +xw  \ parmoffset
+   0        +xw  \ datacnt
+   0        +xw  \ dataoffset
+   1        +xb  \ setupcnt
+   0        +xb  \ Reserved
+
+   2        +xw  \ Setup[0] = Subcommand FIND_NEXT2
+   --bytes--
+   0        +xb  \ Pad to align
+   sid      +xw  \ Search ID
+   d# 1     +xw  \ Search count
+   \  h# 101   +xw  \ This value returns a 64-bit date in 100 nS unit since the Gregorian epoch
+   h# 001   +xw  \ Get info in DOS format for now, so we can decode the time
+   ( resumekey )
+            +xl
+   h# e     +xw  \ Search flags - pick up where left off 8, return resume keys 4, close on end 2
+   " "      +unicode$  \ Search pattern
+   }smb
+;
+
+: start-search  ( -- true | rem$ false )
+   h# 32 smb{
+   d# 18    +xw  \ #param
+   0        +xw  \ #data
+   d# 10    +xw  \ #retparm
+   max-data +xw  \ #retdata
+   0        +xb  \ #setupdata
+   0        +xb  \ Reserved
+   0        +xw  \ flags - two way, no disconnect
+   0        +xl  \ timeout - return immediately
+   0        +xw  \ Reserved
+   d# 18    +xw  \ parmcnt    \ Actually d# 12 plus pattern length (unicode, null terminated)
+   d# 66    +xw  \ parmoffset
+   0        +xw  \ datacnt
+   0        +xw  \ dataoffset
+   1        +xb  \ setupcnt
+   0        +xb  \ Reserved
+
+   1        +xw  \ Setup[0] = Subcommand FIND_FIRST2
+   --bytes--
+   0        +xb  \ Pad to align
+   h# 17    +xw  \ Search attributes - include dir 10, system 4, hidden 2, RO 1
+   d# 1     +xw  \ Search count
+   6        +xw  \ Search flags - return resume keys 4, close on end 2
+   \  h# 101   +xw  \ This value returns a 64-bit date in 100 nS unit since the Gregorian epoch
+   h# 001   +xw  \ Get info in DOS format for now, so we can decode the time
+   0        +xl  \ Storage type
+   " \*"    +unicode$  \ Search pattern
+   }smb
+;
+
+: >hms  ( dos-packed-time -- secs mins hours )
+   dup h#   1f and      2*   swap  ( secs packed )
+   dup h# 07e0 and      5 >> swap  ( secs mins packed )
+       h# f800 and  d# 11 >>       ( secs mins hours )
+;  
+: >dmy  ( dos-packed-date -- day month year )
+   dup h#   1f and          swap   ( day packed )
+   dup h# 01e0 and  5 >>    swap   ( day month packed )
+       h# fe00 and  9 >> d# 1980 + ( day month year )
+;  
+\ Convert DOS file attributes to the firmware encoding
+\ see showdir.fth for a description of the firmware encoding
+: >canonical-attrs  ( dos-attrs -- canon-attrs )
+   >r
+   \ Access permissions
+   r@     1 and  if  o# 666  else  o# 777  then \ rwxrwxrwx
+
+   \ Bits that are independent of one another
+   r@     2 and  if  h# 10000 or  then		\ hidden
+   r@     4 and  if  h# 20000 or  then		\ system
+   r@ h# 20 and  if  h# 40000 or  then		\ archive
+
+   \ Mutually-exclusive file types
+   r@     8 and  if  h#  3000 or  then		\ Volume label
+   r> h# 10 and  if  h#  4000 or  then		\ Subdirectory
+   dup h# f000 and  0=  if  h# 8000 or  then	\ Ordinary file	
+;
+
+: unicode>ascii  ( adr -- adr len )
+   dup dup                        ( adr aadr uadr )
+   begin                          ( adr aadr uadr )
+      dup le-w@                   ( adr aadr uadr uchar )
+      rot 2dup c!                 ( adr uadr uchar aadr )
+      ca1+ -rot                   ( adr aadr uadr uchar )
+      swap wa1+ swap              ( adr aadr uadr uchar )
+  0= until                        ( adr aadr uadr )
+  drop                            ( adr aadr )
+  over - 1-                       ( adr len )
+;
+
+0 instance value parm-cnt
+0 instance value smb-base
+0 instance value parm-base
+0 instance value data-base
+: parse-search  ( rem$ -- false | file info .. true )
+   over d# 32 - to smb-base
+   d# 10 expect-wcnt
+   drop-w  \ Total parameter count
+   drop-w  \ Total data count
+   drop-w  \ reserved
+   -xw to parm-cnt
+   -xw smb-base + to parm-base
+   drop-w  \ Parameter displacement
+   drop-w  \ # of data bytes
+   -xw smb-base + to data-base
+   2drop
+   \ At this point we stop deserializing and just go straight to the info
+   \ id s m h d m y len attr name$ true 
+   parm-cnt d# 10 =  if
+      parm-base le-w@ to sid
+      2   ( search-count-offset )
+   else   ( )
+      0   ( search-count-offset )
+   then   ( search-count-offset )
+   parm-base + le-w@  0=  if  false  exit  then
+
+   data-base le-l@ 1+                        ( id' )
+   data-base d# 14 + le-w@ >hms              ( id s m h )
+   data-base d# 12 + le-w@ >dmy              ( id s m h d m y )
+   data-base d# 16 + le-l@                   ( id s m h d m y len )
+   data-base d# 24 + le-w@ >canonical-attrs  ( id s m h d m y len attr )
+   data-base d# 28 + unicode>ascii           ( id s m h d m y len attr name$ )
+   true
+;
+
+: next-file-info  ( id -- false | id' s m h d m y len attributes name$ true )
+   dup -1 =  if  drop false  exit  then                 ( id )
+   ?dup  if  continue-search  else  start-search  then  ( true | adr len false )
+   if  false  exit  then                                ( rem$ )
+   parse-search
+;
+
+: free-bytes  ( -- d.#bytes )
+   h# 80 smb{ --bytes-- }smb  if  0. exit  then
+   -wcnt                   ( rem$ )
+   drop-w                  ( rem$ )
+   -xw >r   \ Blocks/unit  ( rem$ )
+   -xw >r   \ bytes/block  ( rem$ )
+   -xw >r   \ free-unit    ( rem$ )
+   2drop                   ( )
+   r> r> u*  r> um*        ( d.#bytes )
+;
+
+0 [if]
 : send-create-andx  ( path$ access flags -- )
    h# a2 smb{
    words{
@@ -615,30 +778,49 @@
    my-args dup 0=  if  2drop true exit  then       ( arg$ )
    allocate-buffers                                ( arg$ )
 
-   parse-server parse-share                        ( rem$ )
-   server$ set-server                              ( rem$ )
-   d# 139 " connect" $call-parent  0=  if  2drop false exit  then
-   " OFW" " *SMBSERVER " start-session if  2drop false exit  then
-   negotiate      if  free-buffers  4drop false exit  then   ( rem$ )
-   password$ set-password  compute-password                  ( rem$ )
-   session-setup  if  free-buffers  4drop false exit  then   ( rem$ )
-   share$ server$  " \\\\%s\\%s" sprintf                     ( rem$ server+share$ )
-   tree-connect   if  free-buffers  2drop false exit  then   ( rem$ )
+   parse-server parse-share parse-pathname to tail$
+   server$ set-server
+   d# 139 " connect" $call-parent  0=  if  false exit  then
+   " OFW " " *SMBSERVER " start-session if  false exit  then
+   negotiate      if  free-buffers  false exit  then   ( )
+   password$ set-password  compute-password            ( )
+   session-setup  if  free-buffers  false exit  then   ( )
+   share$ server$  " \\\\%s\\%s" sprintf               ( server+share$ )
+   tree-connect   if  free-buffers  false exit  then   ( )
 
-   parse-filename  2 open-file  if                 ( rem$ )
-      free-buffers  2drop false exit
-   then                                            ( rem$ )
+   \ If we just opened the share without a path, return success now
+   pathname$ nip  0=  if             ( )
+      " \" to pathname$              ( )
+      true exit
+   then                              ( )
 
+   \ Otherwise determine if the path refers to a directory or a file
+   pathname$ $getattr  if            ( )
+      ." Bad CIFS pathname" cr       ( )
+      free-buffers  false exit
+   then                              ( attr )
+
+   \ If the 10 bit is set it's a directory, so we just return success
+   h# 10 and  if  true exit  then    ( )
+
+   \ It's a file, so open it - first try to open read/write.
+   pathname$ 2 open-file  if         ( )
+      \ Failing that, try to open read-only            
+      pathname$ 0 open-file  if      ( )
+         free-buffers  false exit
+      then                           ( )
+   then                              ( )
+
    \ If any arguments remain, assume we are dealing with a ZIP
    \ archive and interpose the ZIP handler 
-   dup  if                                         ( rem$ )
-      " zip-file-system" $interpose                ( okay? )
-   else                                            ( rem$ )
-      2drop true                                   ( okay? )
-   then                                            ( okay? )
+   tail$  dup if                     ( tail$ )
+      " zip-file-system" $interpose  ( okay? )
+   else                              ( tail$ )
+      2drop true                     ( okay? )
+   then                              ( okay? )
 ;
 : close  ( -- )
-   close-file drop
+   fid  if  close-file drop  then
    tree-disconnect drop
    free-buffers
 ;
@@ -647,3 +829,27 @@
 : dma-free  ( adr #bytes -- )  free-mem  ;
 
 : load  ( adr -- len )  size drop  read  ;
+
+\ LICENSE_BEGIN
+\ Copyright (c) 2009 FirmWorks
+\ 
+\ Permission is hereby granted, free of charge, to any person obtaining
+\ a copy of this software and associated documentation files (the
+\ "Software"), to deal in the Software without restriction, including
+\ without limitation the rights to use, copy, modify, merge, publish,
+\ distribute, sublicense, and/or sell copies of the Software, and to
+\ permit persons to whom the Software is furnished to do so, subject to
+\ the following conditions:
+\ 
+\ The above copyright notice and this permission notice shall be
+\ included in all copies or substantial portions of the Software.
+\ 
+\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+\ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+\ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+\ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+\
+\ LICENSE_END




More information about the openfirmware mailing list