1 #
   2 # CDDL HEADER START
   3 #
   4 # The contents of this file are subject to the terms of the
   5 # Common Development and Distribution License (the "License").
   6 # You may not use this file except in compliance with the License.
   7 #
   8 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9 # or http://www.opensolaris.org/os/licensing.
  10 # See the License for the specific language governing permissions
  11 # and limitations under the License.
  12 #
  13 # When distributing Covered Code, include this CDDL HEADER in each
  14 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15 # If applicable, add the following below this CDDL HEADER, with the
  16 # fields enclosed by brackets "[]" replaced with your own identifying
  17 # information: Portions Copyright [yyyy] [name of copyright owner]
  18 #
  19 # CDDL HEADER END
  20 #
  21 
  22 #
  23 # Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  24 # Use is subject to license terms.
  25 #
  26 
  27 NFS Version 4 Test Client
  28 =========================
  29 
  30 The "nfsh" program provides a Tcl environment extended with the
  31 following commands:
  32 
  33 
  34 connect
  35 
  36         [ -p port ] [ -t transport] [-s security mechanisms] <hostname> 
  37                 -> (null)
  38 
  39         Creates an RPC client handle to the named server.
  40         By default the connection is established over a
  41         TCP connection to port 2049 with AUTH_SYS.
  42         
  43         The -p and -t options can be used to modify the port 
  44         number or to provide an alternative transport: currently
  45         "udp" or "tcp".  
  46         
  47         The -s option is used to specify the security mechanisms:
  48         currently "sys", "krb5", "krb5i" or "krb5p".  The "nfsh"
  49         needs to enable the "KRB5=_RPCGSS" flag in the Makefile.master
  50         before compilation; and requires RPCSEC_GSS library.
  51 
  52         The connection persists until the script completes, or 
  53         the "disconnect" command is used, or a new connection 
  54         is created with "connect".
  55 
  56 disconnect
  57 
  58         (null) -> (null)
  59 
  60         Disconnects a connection established by the "connect"
  61         command. If the connection is over TCP, the client
  62         will actively drop the TCP connection.
  63 
  64 exit
  65         Exit the nfsv4shell.
  66 
  67 compound
  68         { op ; op ; ... } -> { {result} {result} ...}
  69 
  70         The compound command accepts a list of compound
  71         operations and returns a list of results. The
  72         operations are listed below, each with their result.
  73         On completion of the compound operation, the Tcl
  74         variable "status" is set to the overall status
  75         value for the v4 operation - normally "OK".
  76         The compound command sets the compound "tag" string
  77         to the contents of the Tcl "tag" variable.
  78 
  79         Each op uses the same naming convention as the
  80         operation, but with the first character capitalized.
  81 
  82         Currently, the following compound ops are implemented:
  83 
  84         Access
  85                 { rlmtdxi } -> { supported access }
  86 
  87                 The argument is any of the "r,l,m,t,d,x" character,
  88                 representing the following:
  89                         r -> ACCESS4_READ
  90                         l -> ACCESS4_LOOKUP
  91                         m -> ACCESS4_MODIFY
  92                         t -> ACCESS4_EXTEND
  93                         d -> ACCESS4_DELETE
  94                         x -> ACCESS4_EXECUTE
  95                         i -> 0x00000100 (illegal access bit)
  96 
  97                 The result prints out the supported and the access
  98                 value returned by the server.
  99 
 100         Close
 101                 { seqid stateid{seqid other} } -> { stateid{seqid other} }
 102 
 103                 This operation requires 2 arguments, the seqid and 
 104                 stateid where stateid is a two fields argument consists
 105                 of {seqid other} returning by Open op, closes the file 
 106                 with <cfh> and prints out the stateid.
 107 
 108         Commit
 109                 { offset count } -> { writeverf }
 110 
 111                 This operation requires 2 arguments, the offset and
 112                 the count, which the data to be flushed out.
 113 
 114                 The result prints out the write verifier.
 115         
 116         Create
 117                 { objname {{name val} ...} {s | f | d | l linkdata |
 118                         b specd1 specd2 | c specd1 specd2}
 119                         -> { {atomic before after} { {name val} {name val} ... }
 120 
 121                 This operation requires 2 arguments.  First argument
 122                 is the objname.  The second argument is a single
 123                 character from the following list:
 124                         l -> of type NF4LNK
 125                         b -> of type NF4BLK
 126                         c -> of type NF4CHR
 127                         s -> of type NF4SOCK
 128                         f -> of type NF4FIFO
 129                         d -> of type NF4DIR
 130 
 131                 Some type from the above list need more arguments.
 132                 Thus, the usage for each type looks like:
 133                         l -> Create objname l linkdata
 134                         b -> Create object b specd1 specd2
 135                         c -> Create object c specd1 specd2
 136                         s -> Create object
 137                         f -> Create object
 138                         d -> Create object
 139 
 140                 The result prints out true/false of atomic,
 141                 before and after ids.  The before and after
 142                 ids are 64-bit values represented as decimal
 143                 numbers.  It also returns the attribute list.
 144 
 145         Delegpurge
 146                 { clientid } -> (null)
 147 
 148                 This operation takes the clientid argument, purges
 149                 all of the delegations awaiting recovery for a 
 150                 given client.
 151 
 152                 The status of the operation will be printed.
 153 
 154         Delegreturn
 155                 { stateid{seqid other} } -> (null)
 156 
 157                 This operation takes the stateid (which is a two
 158                 fields) argument, returns the delegation represented
 159                 by the given stateid.
 160 
 161                 The status of the operation will be printed.
 162 
 163         Getattr
 164                 { name name ... } -> { {name val} {name val} ...}
 165 
 166                 The argument is a list of attribute names that
 167                 are to be retrieved.  The names are converted
 168                 to a protocol bitmap.
 169 
 170                 The result is a list of attributes, each as a 
 171                 name/value pair.  Each name/value pair is presented
 172                 as a sublist, e.g. "{ type dir }". More complex
 173                 attribute values are presented as sublists, e.g.
 174                 "{ time_modify { 1288560 0 }}"
 175                 Attribute names are string values derived from
 176                 the protocol spec.
 177 
 178         Getfh
 179                 (null) -> filehandle
 180 
 181                 Returns the value of the current filehandle.
 182                 Most commonly follows an Lookup.
 183                 The filehandle value is presented as a
 184                 hexadecimal string.
 185 
 186         Link
 187                 { newname } -> { atomic before after }
 188 
 189                 The argument is the new name to be created.
 190 
 191                 The results prints out true/false of atomic,
 192                 before and after ids.  The before and after
 193                 ids are 64-bit values represented as decimal
 194                 numbers.
 195 
 196         Lock
 197                 { ltype reclaim(T|F) offset length newlock(T|F)
 198                   stateid{seqid other} lseqid {oseqid clientid owner} }
 199                         -> { stateid access }
 200 
 201                 This operation requires 8 arguments, including
 202                 the locktype in numeric, with the following:
 203                         1 - READ_LT 
 204                         2 - WRITE_LT
 205                         3 - READW_LT  ( blocking read )
 206                         4 - WRITEW_LT ( blocking write) 
 207 
 208                 the reclaim, which would be a single letter of 'T' 
 209                 (true) or 'F' (false); the offset and length in the 
 210                 file from <cfh> to be locked; the stateid with 2 fields
 211                 {seqid other}, the lock_seqid; If this is new lock, 
 212                 the open_seqid, clientid and owner are also required.
 213 
 214                 If the operation is successful, the stateid will
 215                 be printed.  If the lock is denied, the owner,
 216                 offset and length of conflicted lock on file.
 217 
 218         Lockt
 219                 { type clientid owner_val offset length } -> { owner }
 220 
 221                 Similar to Lock operation, it takes the following
 222                 locktype as the first argument:
 223                         1 - READ_LT 
 224                         2 - WRITE_LT
 225                         3 - READW_LT  ( blocking read )
 226                         4 - WRITEW_LT ( blocking write) 
 227 
 228                 the other arguments includes clientid, the owner
 229                 name and the offset and length of the lock to be
 230                 tested.
 231                 
 232                 If the operation is successful, the stateid will
 233                 be printed.  If the lock is denied, the owner,
 234                 offset and length of conflicted lock on file.
 235 
 236         Locku
 237                 { type seqid stateid{seqid other} offset length }
 238                         -> { stateid }
 239 
 240                 Similar to Lockt operation, it takes the following
 241                 locktype as the first argument:
 242                         1 - READ_LT 
 243                         2 - WRITE_LT
 244                         3 - READW_LT  ( blocking read )
 245                         4 - WRITEW_LT ( blocking write) 
 246 
 247                 the other arguments includes lock_seqid, stateid with
 248                 2 fields {seqid other}, the offset and length in the
 249                 file to be unlocked.
 250                 
 251                 If the operation is successful, the stateid will
 252                 be printed.  If the lock is denied, the stateid
 253                 will be printed.
 254 
 255         Lookup
 256                 { name } -> (null)
 257 
 258                 Accepts the component name to be looked and sets the 
 259                 current filehandle to it.  The result status will be
 260                 returned.
 261                 
 262         Lookupp
 263                 (null) -> (null)
 264                 
 265                 Returns the result status.
 266 
 267         Nverify
 268                 { {name val} {name {v1 v2}} ... } -> (null)
 269                 
 270                 Accepts a list of attributes in the form of
 271                 {name val} pairs.  Returns the result status.
 272 
 273         Open
 274                 { seqid access deny {clientid owner}
 275                   {opentype createmode {{name val} {name val}...} | createverf}
 276                   {claim {filename | delegate_type | delegate_stateid filename}}
 277                 }
 278                     -> { stateid{seqid other} cinfo rflags {{name val} ...}
 279                          delegation }
 280 
 281                 This operation takes 6 arguments with some
 282                 arguments have different fields. Basically
 283                 it needs:
 284                   the open_seqid
 285                   and the share_access (1-READ, 2-WRITE, 3-ACCESS_BOTH)
 286                   and the share_deny   (0-DENY_NONE, 1-DENY_READ,
 287                                         2-DENY_WRITE, and 3-DENY_BOTH)
 288                   and { clientid owner }                (the owner pair)
 289                   and one of the following open_type(s):
 290                     { 0 junkfield1 junkfield2 }         (NOCREATE)
 291                     { 1 
 292                         { 0 { {name val} {name val} ... } } (CREATE/UNCHECKED)
 293                         { 1 { {name val} {name val} ... } } (CREATE/GARDED)
 294                         { 2 createverf } }              (CREATE/EXCLUSIVE)
 295                     }                                   (CREATE)
 296                   and one of the following claim_type(s):
 297                     { 0 filename }                      (CLAIM_NULL)
 298                     { 1 delegate_type }                 (CLAIM_PREVIOUS)
 299                     { 2 {filename delegate_stateid } }  (CLAIM_DELEGATE_CUR)
 300                     { 3 filename }                      (CLAIM_DELEGATE_PREV)
 301                 arguments.
 302 
 303                 The results returned from server will be printed 
 304                 based on the argument, including status, stateid
 305                 {seqid other}, change_info, rflags, attributes and the 
 306                 delegation_type.
 307 
 308                 See "Examples" section for the compound sample of Open call. 
 309 
 310         Openattr
 311                 { createdir } -> (null)
 312 
 313                 It takes an argument of createdir, "T" (true) or "F"
 314                 (false) value; sets the current filehandle of the named 
 315                 attribute directory associated with the current filehandle.
 316 
 317         Open_confirm
 318                 { open_stateid{seqid other} seqid } -> { stateid }
 319 
 320                 This operation takes the open_stateid and the sequence id 
 321                 confirms the stateid and owner.
 322 
 323                 If it is successful, the stateid will be printed.
 324 
 325         Open_downgrade
 326                 { stateid{seqid other} seqid access deny } 
 327                         -> { stateid{seqid other} }
 328 
 329                   This operation takes the stateid, sequence id 
 330                   access and deny, 4 arguments; and to reduce
 331                   the Open file access.
 332 
 333                   If it is successful, the stateid will be printed.
 334 
 335         Putfh
 336                 { filehandle } -> (null)
 337 
 338                 Accepts a hexadecimal encoded filehandle as
 339                 and argument and sets the current filehandle.
 340 
 341         Putpubfh
 342                 (null) -> (null)
 343 
 344                 Sets the current filehandle to the public
 345                 filehandle.
 346 
 347         Putrootfh
 348                 (null) -> (null)
 349 
 350                 Sets the current filehandle to the root
 351                 filehandle.
 352 
 353         Read
 354                 { stateid{seqid other}, offset, count } -> { eof len data }
 355 
 356                 It takes 3 arguments, the open_stateid (with 2 fields,
 357                 seqid and other), the offset and the length to read.
 358 
 359                 The result prints out the true/false value of eof,
 360                 the len and the data.  Right now the data is printed 
 361                 as binary string. 
 362 
 363         Readdir
 364                 { cookie verifier dircount maxcount { name name ...} }
 365                         -> { verifier { { cookie name 
 366                                 { {name val} {name val} ...} } ... } }
 367 
 368                 One of the more complex compound ops.  Readdir op
 369                 takes 5 arguments.  The cookie and verifier values
 370                 are given as hexadecimal strings. On the first
 371                 call a cookie of "0" is used.  The final argument
 372                 is a list of attributes to be returned for
 373                 each directory entry.
 374 
 375                 The result begins with a verifier, followed by
 376                 a list of entries.  Each entry begins with the
 377                 entry cookie followed by the entry name.  The
 378                 third element of each entry is a list of attribute
 379                 names and values - as would be returned by Getattr.
 380                 The final value returned is a boolean eof value.
 381                 if eof is set to "true" then the end of the
 382                 directory has been reached.  The readdir.tcl
 383                 script shows an example of readdir use.
 384 
 385         Readlink
 386                 (null) -> { linkdata }
 387 
 388                 Reads the linkdata pointed by the <cfh>; 
 389                 Returns the result status and linkdata.
 390 
 391         Release_lockowner
 392                 { clientid lock_owner } -> { null }
 393 
 394                 It takes the clientid and lock_owner value to
 395                 the server to release the state related to this
 396                 lockowner.  The result status will be printed.
 397 
 398         Remove 
 399                 { target } -> (null)
 400 
 401                 Accepts the target name to be removed.
 402                 Returns the result status.
 403 
 404         Rename
 405                 { oldname newname } ->
 406                                 { source { atomic before after }
 407                                   target { atomic before after }}
 408 
 409                 This operation requires 2 arguments as string,
 410                 oldname and newname, which the oldname will be
 411                 renamed to the newname.
 412 
 413                 The results prints out true/false of atomic,
 414                 before and after ids.  The before and after
 415                 ids are 64-bit values represented as decimal
 416                 numbers.
 417 
 418         Renew
 419                 { clientid } -> (null)
 420 
 421                 This operation takes the clientid to renew the 
 422                 leased holds at the server.
 423 
 424         Restorefh
 425                 (null) -> (null)
 426 
 427                 Restore the saved filehandle to the current
 428                 filehandle.
 429 
 430         Savefh
 431                 (null) -> (null)
 432         
 433                 Save the current filehandle.
 434 
 435         Secinfo
 436                 { name } -> { sec_favor_info }
 437 
 438                 Given the filename, this operation returns the 
 439                 security mechanisms information based on the 
 440                 favor.  If the favor is RPCSEC_GSS, the security
 441                 triple of the rpc_gss_svc will be printed out.
 442 
 443         Setattr
 444                 { stateid{seqid other} { {name val} {name {v1 v2}} ... } }
 445                         -> { attr_name attr_name }
 446                         
 447                 This operation sends the request to server
 448                 to set the attributes listed in the {name val}
 449                 pairs.  It requires 2 arguments.  The first
 450                 argument is the stateid with 2 fields (seqid other).  
 451                 The second argument is the sublist of {name val} 
 452                 pairs of the attributes to be set.  The "name" must
 453                 be all lower case and the same names as defined in 
 454                 the spec.  If the "val" portion has two values,
 455                 e.g. the seconds and nseconds in nfstime4 
 456                 structures for time attribute, the { } must be
 457                 used. An example of the Setattr command can be:
 458                 Setattr 0 { {mode 0666} {owner v4user}
 459                             {time_modify_set {sec nsec}} }
 460 
 461                 You may use the "clock seconds" TCL command
 462                 to get the current time second value.
 463 
 464                 The result prints the names of the bits 
 465                 that are set by the server.
 466 
 467         Setclientid
 468                 { verifier id_string {cb_prog netid addr} } 
 469                         -> { clientid setclientid_confirm }
 470 
 471                 Given the verifier and client id_string pair,
 472                 this operation sets the client id.  
 473                 
 474                 Note: the callback function for delegation 
 475                 has not yet been implemented.  The callback
 476                 cb_program is currently set to 0, and same
 477                 as the callback_ident.
 478 
 479         Setclientid_confirm
 480                 { clientid setclientid_confirm } -> (null)
 481 
 482                 Given the clientid and the setclientid_confirm
 483                 verifier returned by the server from the 
 484                 Setclientid call as the argument, this operation 
 485                 confirms the clientid.
 486                 
 487         Verify
 488                 { {name val} {name {v1 v2}} ... } -> (null)
 489                 
 490                 Accepts a list of attributes in the form of
 491                 {name val} pairs.  Returns the result status.
 492 
 493         Write
 494                 { stateid{seqid other} offset stable_how datatype data } 
 495                         -> { count committed verifier }
 496 
 497                 Accepts regular list of 5 arguments, where the
 498                 "stable_how" is asking for one character with
 499                 the following representation:
 500                         u -> UNSTABLE
 501                         d -> DATA_SYNC
 502                         f -> FILE_SYNC
 503                 e.g. "Write {0 0} 2 f a {data to write}" means to
 504                 write (to cfh) the data starting at offset=2,
 505                 and stateid={0 0} and file_sync the 'ascii' data.
 506 
 507                 Currently it takes only ascii string for the data.
 508                 Hex string will be supported in the future.
 509 
 510                 The result prints out the count, committed level
 511                 and the verifier returned from the server.
 512 
 513                 Note: the writing of hex (UTF8) characters has not
 514                 yet been implemented.  Currently it only works for
 515                 ASCII characters.
 516 -----------------------------------------
 517 
 518 Other commands
 519 --------------
 520 
 521 If the "tclprocs" TCL procedures scripts is included
 522 in the currently directory, all procedures/commands
 523 can be freely used in 'nfsh'.  Please see the tclprocs
 524 script for the available procedures.
 525 
 526 -----------------------------------------
 527 
 528 Examples
 529 --------
 530 
 531         There are tcl scripts under 'scripts' directory which
 532         show how the tool is used in batch mode, including:
 533         
 534           tclprocs    - commonly used TCL procedures 
 535           attributes  - prints the attributes of a file/dir
 536           ckerrors    - checks server error responses of ops
 537           lock_neg    - test some irregular conditions of Lock/Open/Close
 538           opensimple  - simple test for open ops
 539           pathhandles - evaluates a path and prints FH
 540           readdir     - reads a directory
 541           setattr     - set attributes on a file
 542           tcopy       - local-to-remote or remote-to-local file copy
 543           test        - a test for some basic ops
 544           trylock     - test Open/Lock/Locku/Lockt/Close operations
 545           walk        - walks down a directory
 546 
 547         For example:
 548 
 549         - Output of the "trylock" script:
 550           $./trylock wnfspc /export/test
 551 
 552           Setclientid 103129416501010 16746 ...
 553           Res: {Setclientid OK {3d77d559000000e2 0000000000000000}}
 554 
 555           Setclientid_confirm 3d77d559000000e2 0000000000000000 ...
 556           Res: {Setclientid_confirm OK}
 557 
 558           Open to create tfile.16746 ...
 559             Open 1 3 0 {3d77d559000000e2 16746} {1 0 {{mode 0664} {size 88}}} {0 tfile.16746}
 560             Res: {Putfh OK} {Open OK {0 3D77D559000000E800000000} {{atomic false} {before 3d784b4514a46c80} {after 3d784bda1f426160}} 6 {size mode} NONE} {Getfh OK 01D8000700000002000A0000000004EF2A51238A000A00000000000C0012BEA20000000000000000} {Getattr OK {{size 88} {mode 664}}}
 561 
 562             Lock 2 F 0 1024 T (0 3D77D559000000E800000000) 1 (2 3d77d559000000e2 16746)
 563             Res: {Putfh OK} {Lock OK {1 3D77D559400000E800000080}}
 564 
 565             first LOCKT with owner(3d77d559000000e2 fake_owner) of region 0-1024
 566             Res: {Putfh OK} {Lockt DENIED {0 1024 2} {3d77d559000000e2 16746}}
 567 
 568             second LOCKT with owner(3d77d559000000e2 fake_owner) of region 1025-2048
 569             Res: {Putfh OK} {Lockt OK}
 570 
 571             third LOCKT with owner(3d77d559000000e2 16746) of region 0-1024
 572             Res: {Putfh OK} {Lockt OK}
 573 
 574             Locku 2 2 (1 3D77D559400000E800000080) 0 1024
 575             Res: {Putfh OK} {Locku OK {2 3D77D559400000E800000080}}
 576 
 577             forth LOCKT with owner(3d77d559000000e2 fake_owner) of region 0-1024
 578             Res: {Putfh OK} {Lockt OK}
 579 
 580             Final Close 2 (0 3D77D559000000E800000000) ...
 581             Res: {Putfh OK} {Close OK {1 3D77D559000000E800000000}}
 582 
 583             Open with/non-CREATE tfile.16746 ...
 584               Open 2 3 0 {3d77d559000000e2 16746} {0 0 {{mode 0664} {size 88}}} {0 tfile.16746}
 585               Res: {Putfh OK} {Open OK {0 3D77D559000000E900000000} {{atomic true} {before 3d784bda1f6f7470} {after 3d784bda1f6f7470}} 6 {} NONE} {Getfh OK 01D8000700000002000A0000000004EF2A51238A000A00000000000C0012BEA20000000000000000}
 586 
 587               Final Close 2 (0 3D77D559000000E900000000) ...
 588               Res: {Putfh OK} {Close OK {1 3D77D559000000E900000000}}
 589 
 590               Remove tfile.16746 ...
 591               Res: {Putfh OK} {Remove OK {{atomic false} {before 3d784bda1f426160} {after 3d784bda26ec0128}}}
 592 
 593 
 594         - Try another script "setattr":
 595           $ setattr javanfs2 /export/test
 596           Attributes Before Setattr (at Fri Jan 18 12:01:37 PST 2002): 
 597                   File size        = 0
 598                   Mode bits        = 640
 599                   Owner            = tuser1@eng.sun.com
 600                   Group            = staff@eng.sun.com
 601                   Access time      = 1011383961 230000000 - Fri Jan 18 11:59:21 PST 2002
 602                   Modified time    = 1011383961 230000000 - Fri Jan 18 11:59:21 PST 2002
 603           Now sleep for 30 seconds ...
 604           New attributes after Setattr (at Fri Jan 18 12:02:08 PST 2002): 
 605                   File size        = 8888
 606                   Mode bits        = 765
 607                   Owner            = tuser1@eng.sun.com
 608                   Group            = staff@eng.sun.com
 609                   Access time      = 1011383910 0 - Fri Jan 18 11:58:30 PST 2002
 610                   Modified time    = 1011383991 309992000 - Fri Jan 18 11:59:51 PST 2002
 611           $
 612 
 613 
 614 
 615         The tool can also be used interactively from command line.
 616         For example:
 617 
 618         $ nfsh
 619         % connect krbsec3
 620         % compound {Putrootfh; Lookup {export v4}; Getattr {type}}
 621         {Putrootfh OK} {Lookup OK} {Getattr OK {{type dir}}}
 622         % 
 623         % set fh [ get_fh {export v4 dir1} ]
 624         0080000700000002000A000000005900099ACD63000A0000000016406A35C71700000000
 625         % 
 626         % set res [ compound {Putfh $fh; Readdir 0 0 1024 1024 {type size}} ]
 627         {Putfh OK} {Readdir OK 0000000000000000 {{0000000000000028 file1 
 628         {{type reg} {size 30}}} {0000000000000038 dir2 {{type dir} {size 512}}}
 629         {000000000000004C file.empty {{type reg} {size 0}}} {0000000000000060
 630         file_noperm {{type reg} {size 30}}} {0000000000000200 file.bin 
 631         {{type reg} {size 18204}}}} true}
 632         % 
 633         % prn_dirlist [ lindex [lindex $res 1] 3 ]
 634           file1
 635                 File type        = file
 636                 File size        = 30
 637           dir2
 638                 File type        = dir
 639                 File size        = 512
 640           file.empty
 641                 File type        = file
 642                 File size        = 0
 643           file_noperm
 644                 File type        = file
 645                 File size        = 30
 646           file.bin
 647                 File type        = file
 648                 File size        = 18204
 649         % 
 650         % disconnect
 651         % exit
 652 
 653 
 654         Results can also be verified and formatted with TCL
 655         commands using the scripts.
 656 
 657 
 658         Here is a simple example for the Open call to create
 659         a file called "file.2" with mode=0644 under the sun-8 directory:
 660 
 661         $ nfsh
 662         % connect -t udp wnfspc
 663         % compound {Setclientid 188888 aowner {0 0 0}}
 664         {Setclientid OK {3d77d559000000e3 0000000000000000}}
 665         %  compound {Setclientid_confirm 3d77d559000000e3 0000000000000000}
 666         {Setclientid_confirm OK}
 667         % set dfh [get_fh {export test}]
 668         01D8000700000002000A00000000000C0012BEA2000A00000000000C0012BEA20000000000000000
 669         % set res [compound {Putfh $dfh; Open 1 3 0 {3d77d559000000e3 aowner} {1 0 {{mode 0644}}} {0 file.2}; Getfh}]
 670         {Putfh OK} {Open OK {0 3D77D559000000EA00000000} {{atomic false} {before 3d784bda26ec0128} {after 3d784d1405223968}} 6 {mode} NONE} {Getfh OK 01D8000700000002000A00000000091A3143D7C6000A00000000000C0012BEA20000000000000000}
 671         % set stateid [lindex [lindex $res 1] 2]
 672         0 3D77D559000000EA00000000
 673         % set fh [lindex [lindex $res 2] 2]
 674         01D8000700000002000A00000000091A3143D7C6000A00000000000C0012BEA20000000000000000
 675         % compound {Putfh $fh; Open_confirm $stateid 2}
 676         {Putfh OK} {Open_confirm OK {0 3D77D559000000EA00000000}}
 677         % 
 678 
 679 
 680 Note - we can use variables inside NFS operation's parameters. Actually, this 
 681 shell support all normal TCL substitutions (backslash, variable and command).
 682 
 683 -----------------------------------------
 684 Variables
 685 ---------
 686 
 687 The client uses sets some Tcl variables:
 688 
 689         nfsh_version
 690                 The current version of nfsv4shell
 691                 tool.  If "Unknown" is returned,
 692                 the NFSH_VERS is not set at compile
 693                 time.
 694 
 695         status
 696                 The status value returned by a
 697                 compound operation.  It will be
 698                 "OK" if the compound op completed
 699                 successfully.  Otherwise, it will
 700                 be the error code. The error code
 701                 is the same as the protocol spec
 702                 with the "NFS4ERR_" prefix removed,
 703                 e.g. "STALE".   
 704         tag
 705                 If set, the tag string will be used
 706                 as the compound tag.  The variable
 707                 is set to the returned tag (in case
 708                 the server changed it).
 709 
 710         opcount
 711                 A count of the number of compound
 712                 ops that were successfully executed
 713                 by the server.
 714 
 715 
 716