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 # lcltools.tcl - procedures used for some tests (less general than
  27 #                       those in tclproc.tcl)
  28 
  29 
  30 #--------------------------------------------------------------------
  31 # ownid()
  32 #       Create string for owner id information.
  33 #       Returns the string with owner id, the tag send and last 5 digits
  34 #               of the internal clock in seconds.
  35 #
  36 
  37 proc ownid {{tag ""}} {
  38         putmsg stdout 1 "\n"
  39         putmsg stdout 1 "ownid $tag"
  40         set ret "owner$tag[string range [clock clicks] end-5 end]"
  41         putmsg stdout 1 "returned $ret"
  42         return $ret
  43 }
  44 
  45 #--------------------------------------------------------------------
  46 # grpid()
  47 #       Create string for owner id information.
  48 #       Returns the string with group id, the tag send and last 5 digits
  49 #               of the internal clock in seconds.
  50 #
  51 
  52 proc grpid {{tag ""}} {
  53         putmsg stdout 1 "\n"
  54         putmsg stdout 1 "grpid $tag"
  55         set ret "group$tag[string range [clock clicks] end-5 end]"
  56         putmsg stdout 1 "returned $ret"
  57         return $ret
  58 }
  59 
  60 #--------------------------------------------------------------------
  61 # openv4()
  62 #       Wrap for open and open_confirm ops.
  63 #       Returns the new filehandle if success, else NULL.
  64 #
  65 
  66 proc openv4 {filename Aclientid Astateid Aseqid {owner "one"}\
  67         {opentype 1} {Ares "DEADBEEF"}} {
  68         global NULL OPEN4_RESULT_CONFIRM DELM
  69         upvar 1 $Aclientid clientid
  70         upvar 1 $Astateid stateid
  71         upvar 1 $Aseqid oseqid
  72         set clientid ""
  73         if {$Ares != "DEADBEEF"} {
  74                 upvar 1 $Ares res
  75         }
  76         append owner [clock clicks]
  77         putmsg stdout 1 "\n"
  78         putmsg stdout 1 "openv4 $filename $Aclientid $Astateid $Aseqid"
  79         putmsg stdout 1 "\t$owner $opentype $Ares"
  80 
  81         # pass status if exists as global
  82         if {[info vars ::status] != ""} {
  83                 upvar 1 status status
  84         }
  85 
  86         # pass tag if exists as global
  87         if {[info vars ::tag] != ""} {
  88                 upvar 1 tag tag
  89         }
  90 
  91         # convert pathname to list, store filename and path separated;
  92         set path [ path2comp $filename $DELM ]
  93         set filename [lindex $path end]
  94         set pathdir [lrange $path 0 end-1]
  95                                                                           
  96         putmsg stdout 1 "filename=$filename"
  97         putmsg stdout 1 "pathdir=$pathdir"
  98 
  99         # set clientid with server
 100         set verifier ""
 101         if {[setclient [clock clicks] $owner clientid verifier res] == "OK"} {
 102                 if {[setclientconf $clientid $verifier res] != "OK"} {
 103                         putmsg stdout 1 "cannot open temp file"
 104                         return $NULL
 105                 }
 106         }
 107 
 108         # XXX add catch here later
 109         set dfh [get_fh $pathdir]
 110 
 111         # create a seqid var if not exists to avoid test brakes
 112         if {[info vars oseqid] != ""} {
 113                 set oseqid ""
 114                 putmsg stdout 1 "WARNING: $Aseqid in caller did not exist."
 115                 putmsg stdout 1 "\t$Aseqid created and initialized to 1"
 116         }
 117         # if oseqid uninitialized
 118         if {$oseqid == ""} {
 119                 set oseqid 1
 120         }
 121 
 122         set oclaim 0
 123         set creat 0
 124         set res [compound {Putfh $dfh; Open $oseqid 3 0 {$clientid $owner} \
 125                 {$opentype $creat {{mode 0777}}} {$oclaim $filename}; Getfh}]
 126         putmsg stdout 1 "compound {Putfh $dfh;"
 127         putmsg stdout 1 "\tOpen $oseqid 3 0 {$clientid $owner}{$opentype $creat"
 128         putmsg stdout 1 "\t{{mode 0777}}} {$oclaim $filename}; Getfh}"
 129         putmsg stdout 1 "Res: $res"
 130         if {$status != "OK"} {
 131                 putmsg stdout 1 "Cannot open ($filename)."
 132                 return $NULL
 133         }
 134 
 135         set stateid [lindex [lindex $res 1] 2]
 136         set rflags [lindex [lindex $res 1] 4] 
 137         set nfh [lindex [lindex $res 2] 2]
 138         putmsg stdout 1 "stateid = $stateid\nrflags = $rflags\nnfh = $nfh"
 139 
 140         # do open_confirm if needed, e.g. rflags has OPEN4_RESULT_CONFIRM set
 141         if {[expr $rflags & $OPEN4_RESULT_CONFIRM] == $OPEN4_RESULT_CONFIRM} {
 142                 incr oseqid
 143                 set res [compound {Putfh $nfh; Open_confirm $stateid $oseqid}]
 144                 putmsg stdout 1 "compound {Putfh $nfh;"
 145                 putmsg stdout 1 "Open_confirm $stateid $oseqid}"
 146                 putmsg stdout 1 "Res: $res"
 147                 if {$status != "OK"} {
 148                         putmsg stdout 1 \
 149                                 "unable to open confirm file $filename."
 150                         return $NULL
 151                 }
 152                 set stateid [lindex [lindex $res 1] 2]
 153         }
 154         incr oseqid
 155         putmsg stdout 1 "stateid = $stateid\nseqid = $oseqid"
 156 
 157         putmsg stdout 1 "return nfh = $nfh"
 158         return $nfh
 159 }
 160 
 161 #--------------------------------------------------------------------
 162 # opencnftst()
 163 #       Wrap for open op.
 164 #       Returns the new filehandle if success, else NULL.
 165 #
 166 
 167 proc opencnftst {dfh filename clientid Astateid Aseqid Arflags {owner "SeT"}} {
 168         global NULL env
 169         upvar 1 $Astateid stateid
 170         upvar 1 $Aseqid oseqid
 171         upvar 1 $Arflags rflags
 172         if {$owner == "SeT"} {
 173                 set owner "$env(USER)[clock clicks]"
 174         }
 175         putmsg stdout 1 "\n"
 176         putmsg stdout 1 "opencnftst $dfh $filename $clientid $Astateid"
 177         putmsg stdout 1 "\t$Aseqid $Arflags $owner"
 178 
 179         # pass status if exists as global
 180         if {[info vars ::status] != ""} {
 181                 upvar 1 status status
 182         }
 183 
 184         # pass tag if exists as global
 185         if {[info vars ::tag] != ""} {
 186                 upvar 1 tag tag
 187         }
 188 
 189         if {$oseqid == ""} {
 190                 set oseqid 1
 191         }
 192 
 193         set oclaim 0
 194         set creat 0
 195         set opentype 1
 196         set res [compound {Putfh $dfh; Open $oseqid 3 0 {$clientid $owner} \
 197                 {$opentype $creat {{mode 0777}}} {$oclaim $filename}; Getfh}]
 198         putmsg stdout 1 "compound {Putfh $dfh;"
 199         putmsg stdout 1 "\tOpen $oseqid 3 0 {$clientid $owner}"
 200         putmsg stdout 1 "\t{$opentype $creat {{mode 0777}}}"
 201         putmsg stdout 1 "\t{$oclaim $filename}; Getfh}"
 202         if {$status != "OK"} {
 203                 putmsg stdout 1 "Cannot open ($filename)."
 204                 putmsg stdout 1 "Res: $res"
 205                 return $NULL
 206         }
 207 
 208         incr oseqid
 209         set stateid [lindex [lindex $res 1] 2]
 210         set rflags [lindex [lindex $res 1] 4] 
 211         set nfh [lindex [lindex $res 2] 2]
 212         putmsg stdout 1 "stateid = $stateid\nrflags = $rflags\nseqid = $oseqid"
 213 
 214         putmsg stdout 1 "return nfh = $nfh"
 215         return $nfh
 216 }
 217 
 218 #--------------------------------------------------------------------
 219 # openconf4()
 220 #       Wrap for open_confirm op.
 221 #       Returns the status of the operation.
 222 #
 223 
 224 proc openconf4 {nfh rflags Astateid Aseqid {Ares "DEADBEEF"}} {
 225         global OPEN4_RESULT_CONFIRM
 226         upvar 1 $Astateid stateid
 227         upvar 1 $Aseqid oseqid
 228         if {$Ares != "DEADBEEF"} {
 229                 upvar 1 $Ares res
 230         }
 231         set status "UNCONFIRMED"
 232         putmsg stdout 1 "\n"
 233         putmsg stdout 1 "openconf4 $nfh $rflags $Astateid $Aseqid $Ares"
 234         putmsg stdout 1 "status = $status"
 235 
 236         # pass tag if exists as global
 237         if {[info vars ::tag] != ""} {
 238                 upvar 1 tag tag
 239         }
 240 
 241         # do open_confirm if needed, e.g. rflags has OPEN4_RESULT_CONFIRM set
 242 #XXX check if this is what we want
 243 #       if {[expr $rflags & $OPEN4_RESULT_CONFIRM] == $OPEN4_RESULT_CONFIRM} {
 244                 if {$nfh == ""} {
 245                         set res [compound {Open_confirm $stateid $oseqid}]
 246                         putmsg stdout 1 \
 247                                 "compound {Open_confirm $stateid $oseqid}"
 248                 } else {
 249                         set res [compound {Putfh $nfh; \
 250                                 Open_confirm $stateid $oseqid}]
 251                         putmsg stdout 1 "compound {Putfh $nfh;"
 252                         putmsg stdout 1 "\tOpen_confirm $stateid $oseqid}"
 253                 }
 254                 if {$status != "OK"} {
 255                         putmsg stdout 1 \
 256                                 "unable to open confirm file."
 257                         putmsg stdout 1 "Res: $res"
 258                         return $status
 259                 } else {
 260                         if {$nfh == ""} {
 261                                 set stateid [lindex 2]
 262                         } else {
 263                                 set stateid [lindex [lindex $res 1] 2]
 264                         }
 265                 catch {incr oseqid}
 266                 }
 267 #       }
 268         putmsg stdout 1 "stateid = $stateid\nseqid = $oseqid"
 269 
 270         putmsg stdout 1 "return $status"
 271         return $status
 272 }
 273 
 274 #--------------------------------------------------------------------
 275 # closev4()
 276 #       Wrap for close op and removal of the file just closed.
 277 #       Returns OK if success, else NULL.
 278 #
 279 
 280 proc closev4 {filename fh stateid seqid } {
 281         global NULL DELM
 282         putmsg stdout 1 "\n"
 283         putmsg stdout 1 "closev4 $filename $fh $stateid $seqid"
 284 
 285         # pass status if exists as global
 286         if {[info vars ::status] != ""} {
 287                 upvar 1 status status
 288         }
 289 
 290         # pass tag if exists as global
 291         if {[info vars ::tag] != ""} {
 292                 upvar 1 tag tag
 293         }
 294 
 295         # convert pathname to list, store filename and path separated;
 296         set path [ path2comp $filename $DELM ]
 297         set filename [lindex $path end]
 298         set pathdir [lrange $path 0 end-1]
 299                                                                           
 300         putmsg stdout 1 "filename=$filename"
 301         putmsg stdout 1 "pathdir=$pathdir"
 302 
 303         set result "OK"
 304 
 305        # XXX add catch here later
 306         set dfh [get_fh $pathdir]
 307         set fh [get_fh "$pathdir $filename"]
 308 
 309         # close file
 310         set res [compound {Putfh $fh; Close $seqid $stateid}]
 311         putmsg stdout 1 "compound {Putfh $fh;\n\tClose $seqid $stateid}"
 312         putmsg stdout 1 "Res: $res"
 313         if {$status != "OK"} {
 314                 putmsg stdout 1 "Can not close file $filename"
 315                 putmsg stdout 1 "Status = $status"
 316                 set result $NULL
 317         }
 318 
 319         # remove file
 320         set res [compound {Putfh $dfh; Remove $filename}]
 321         putmsg stdout 1 "compound {Putfh $dfh;\n\tRemove $filename}"
 322         putmsg stdout 1 "Res: $res"
 323         if {$status != "OK"} {
 324                 putmsg stdout 1 "Can not remove file $filename"
 325                 putmsg stdout 1 "Status = $status"
 326                 set result  $NULL
 327         }
 328 
 329         putmsg stdout 1 "return $result"
 330         return $result
 331 }
 332 
 333 #--------------------------------------------------------------------
 334 # closetst()
 335 #       Wrap for close op.
 336 #       Returns the status of the operation.
 337 #
 338 
 339 proc closetst {fh stateid seqid Ares} {
 340         global NULL DELM
 341 
 342         upvar 1 $Ares res
 343         putmsg stdout 1 "\n"
 344         putmsg stdout 1 "closetst $fh $stateid $seqid $Ares"
 345 
 346         # pass tag if exists as global
 347         if {[info vars ::tag] != ""} {
 348                 upvar 1 tag tag
 349         }
 350 
 351         # close file
 352         if {$fh == ""} {
 353                 set res [compound {Close $seqid $stateid}]
 354                 putmsg stdout 1 "compound{Close $seqid $stateid}"
 355         } else {
 356                 set res [compound {Putfh $fh; Close $seqid $stateid}]
 357                 putmsg stdout 1 "compound{Putfh $fh;\n\tClose $seqid $stateid}"
 358         }
 359         putmsg stdout 1 "Res: $res"
 360         if {$status != "OK"} {
 361                 putmsg stdout 1 "Can not close file"
 362                 return $status
 363         }
 364 
 365         putmsg stdout 1 "return $status"
 366         return $status
 367 }
 368 
 369 #--------------------------------------------------------------------
 370 # removev4()
 371 #       Wrap for remove op.
 372 #       Returns OK if success, else NULL.
 373 #
 374 
 375 proc removev4 {filename} {
 376         global NULL DELM
 377         putmsg stdout 1 "\n"
 378         putmsg stdout 1 "removev4 $filename"
 379 
 380         # pass status if exists as global
 381         if {[info vars ::status] != ""} {
 382                 upvar 1 status status
 383         }
 384 
 385         # pass tag if exists as global
 386         if {[info vars ::tag] != ""} {
 387                 upvar 1 tag tag
 388         }
 389 
 390         # convert pathname to list, store filename and path separated;
 391         set path [ path2comp $filename $DELM ]
 392         set filename [lindex $path end]
 393         set pathdir [lrange $path 0 end-1]
 394         putmsg stdout 1 "filename = $filename"
 395         putmsg stdout 1 "pathdir = $pathdir"
 396 
 397         # XXX add catch here later
 398         set dfh [get_fh $pathdir]
 399 
 400         # remove file
 401         set res [compound {Putfh $dfh; Remove $filename}]
 402         putmsg stdout 1 "compound {Putfh $dfh;\n\tRemove $filename}"
 403         putmsg stdout 1 "Res: $res"
 404         if {$status != "OK"} {
 405                 putmsg stdout 1 "Can not remove file $filename"
 406                 return $NULL
 407         }
 408 
 409         putmsg stdout 1 "return $status"
 410         return $status
 411 }
 412 
 413 #--------------------------------------------------------------------
 414 # uid_map()
 415 #       Wrap for testing uid mapping assertions via setattr and
 416 #               verifying with getattr op.
 417 #       Returns PASS if success, else either FAIL or OTHER problem.
 418 #               parameters Aown Aowngrp are set to final attrs of file
 419 #
 420 
 421 proc uid_map {ufh sid Aown Aowngrp Ares {Eown ""} {Egrp ""}} {
 422         # initialize attributes parameter
 423         upvar 1 $Aown own
 424         upvar 1 $Aowngrp owngrp
 425         upvar 1 $Ares res
 426         set status "UNRESOLVED"
 427         putmsg stdout 1 "\n"
 428         putmsg stdout 1 "uid_map $ufh $sid $Aown $Aowngrp $Ares $Eown $Egrp"
 429         putmsg stdout 1 "status = $status"
 430 
 431         global PASS FAIL OTHER
 432         set attrib {}
 433         set attrs {}
 434         set O 0
 435         set G 0
 436 
 437         # pass tag if exists as global
 438         if {[info vars ::tag] != ""} {
 439                 upvar 1 tag tag
 440         }
 441 
 442         if {[string length $own] > 0}  {
 443                 lappend attrib "owner $own"
 444                 lappend attrs "owner"
 445                 set O 1
 446         }
 447         if {[string length $owngrp] > 0} {
 448                 lappend attrib "owner_group $owngrp"
 449                 lappend attrs "owner_group"
 450                 set G 1
 451         }
 452         putmsg stdout 1 "attrib = <$attrib>"
 453         putmsg stdout 1 "attrs = <$attrs>"
 454 
 455         set orig_owner ""
 456         set orig_owner_group ""
 457         # get original values to verify on Setattr failure
 458         set sto [catch {compound {Putfh $ufh; Getattr $attrs}} reso]
 459         putmsg stdout 1 "compound{Putfh $ufh;\n\tGetattr $attrs}"
 460         putmsg stdout 1 "res: <$reso>"
 461         if {$status != "OK"} {
 462                 putmsg stdout 0 "\twarning: first Getattr failed ($status)."
 463                 putmsg stdout 1 "return status=$status"
 464                 putmsg stdout 1 "catch result = $sto"
 465         } else {
 466                 set rattrs [lindex [lindex $reso 1] 2]
 467                 putmsg stdout 1 "returned attrs = $rattrs"
 468                 foreach attr $rattrs {
 469                         set name [ lindex $attr 0]
 470                         set val  [ lindex $attr 1]
 471         
 472                         switch $name {
 473                                 owner   { 
 474                                         set orig_owner $val
 475                                 }
 476                                 owner_group     {
 477                                         set orig_owner_group $val
 478                                 }
 479                                 default {}
 480                         }
 481                 }
 482         putmsg stdout 1 "owner = $orig_owner\nowner_group = $orig_owner_group"
 483         }
 484 
 485         set Sstatus "OK"
 486         # Generate a compound request to change the attributes
 487         set st [catch {compound {Putfh $ufh; Setattr $sid {$attrib}}} res]
 488         #set res [compound {Putfh $ufh; Setattr $sid {$attrib}}]
 489         putmsg stdout 1 "compound{Putfh $ufh;\n\tSetattr $sid $attrib}"
 490         putmsg stdout 1 "res: <$res>"
 491         if {$status != "OK"} {
 492                 putmsg stdout 1 "setattr return status=$status"
 493                 putmsg stdout 1 "catch result = $st"
 494                 set Sstatus $status
 495                 # now expected values are original values for the file
 496                 set Eown $orig_owner
 497                 set Egrp $orig_owner_group
 498         }
 499 
 500         #verify the change in attribute
 501         set st2 [catch {compound {Putfh $ufh; Getattr $attrs}} res2]
 502         putmsg stdout 1 "compound{Putfh $ufh;\n\tGetattr $attrs}"
 503         putmsg stdout 1 "res: <$res2>"
 504         if {$status != "OK"} {
 505                 putmsg stdout 0 "\twarning: second Getattr failed ($status)."
 506                 putmsg stdout 1 "return status=$status"
 507                 putmsg stdout 1 "catch result = $st2"
 508                 return $Sstatus
 509         } else {
 510                 set rattrs [lindex [lindex $res2 1] 2]
 511                 set owner ""
 512                 set owner_group ""
 513                 putmsg stdout 1 "returned attrs = $rattrs"
 514                 foreach attr $rattrs {
 515                         set name [ lindex $attr 0]
 516                         set val  [ lindex $attr 1]
 517 
 518                         switch $name {
 519                                 owner   { 
 520                                         set owner $val
 521                                 }
 522                                 owner_group     {
 523                                         set owner_group $val
 524                                 }
 525                                 default {}
 526                         }
 527                 }
 528                 putmsg stdout 1 "owner = $owner\nowner_group = $owner_group"
 529         }
 530 
 531         set Cstatus ""
 532         # if expected value different than value used
 533         if {$Eown != ""} {
 534                 set own $Eown
 535         }
 536         if {$Egrp != ""} {
 537                 set owngrp $Egrp
 538         }
 539         # compare to requested values
 540         # XXX should we enhance to ignore the case of the domain?
 541         if {$O == 1 && [string equal $own $owner] != 1} {
 542                 putmsg stdout 1 "owner set to $own, but is $owner"
 543                 set own $owner
 544                 set Cstatus "${Cstatus}OwnerMismatch"
 545         }
 546         if {$G == 1 && [string equal $owngrp $owner_group] != 1} {
 547                 putmsg stdout 1\
 548                         "group set to $owngrp, but is $owner_group"
 549                 set owngrp $owner_group
 550                 set Cstatus "${Cstatus}GroupMismatch"
 551         }
 552 
 553         # Setattr status (failure condition) has highest priority
 554         set status $Sstatus
 555         # comparisons second
 556         if {$status == "OK" && $Cstatus != ""} {
 557                 set status $Cstatus
 558         }
 559 
 560         putmsg stdout 1 "return $status"
 561         return $status
 562 }
 563 
 564 #--------------------------------------------------------------------
 565 # ckfilev4()
 566 #       Wrap for testing results of assertions and handling logs.
 567 #       Returns true or false.
 568 #
 569 
 570 proc ckfilev4 {op status {prn 0}} {
 571         global DEBUG NULL
 572         putmsg stdout 1 "\n"
 573         putmsg stderr 1 "ckfilev4 $op $status $prn"
 574 
 575         if {$status == $NULL} {
 576                 putmsg stdout 0 "\t Test FAIL: $op"
 577                 return false
 578         } else {
 579                 if {$prn == 0} {
 580                         putmsg stdout 0 "\t Test PASS"
 581                 }
 582                 return true
 583         }
 584 }
 585 
 586 #--------------------------------------------------------------------
 587 # env2path()
 588 #       Build complete file name based on env var and optional path.
 589 #       Default path is $BASEDIR.
 590 #       Returns true or false.
 591 #
 592 
 593 proc env2path {envvar {path "default"}} {
 594         global env BASEDIR DELM
 595 
 596         if {$path == "default"} {
 597                 set path $BASEDIR
 598         }
 599         putmsg stdout 1 "\n"
 600         putmsg stdout 1 "env2path $envvar $path"
 601 
 602         set name [file join $path $env($envvar)]
 603         set path [ path2comp $name $DELM ]
 604 
 605         putmsg stdout 1 "return $path"
 606         return $path
 607 }
 608 
 609 #--------------------------------------------------------------------
 610 # getfileowner()
 611 #       Get owner and owner_group attributes for a file
 612 #       Returns the file's owner and owner_group on success, otherwise
 613 #       it returns null.
 614 
 615 proc getfileowner {fh} {
 616         set attrs "owner owner_group"
 617         set status "UNRESOLVED"
 618         
 619         set st [catch {compound {Putfh $fh; Getattr $attrs}} res] 
 620         if {$st != 0} {
 621                 # syntax error
 622                 putmsg stderr 0 "\terror: compound proc failed"
 623                 putmsg stderr 0 "error code: $st"
 624                 putmsg stderr 0 "error message: $res"
 625         } elseif {$status != "OK"} {
 626                 # request failed
 627                 putmsg stderr 0 "\twarning: Getattr failed($status)."
 628         } else {
 629                 # parse the result
 630                 set rattrs [lindex [lindex $res 1] 2]
 631                 putmsg stdout 1 "returned attrs = $rattrs"
 632                 foreach attr $rattrs {
 633                         set name [lindex $attr 0]
 634                         set val [lindex $attr 1]
 635                         switch $name {
 636                                 owner {
 637                                         set owner $val
 638                                 }
 639                                 owner_group {
 640                                         set owner_group $val
 641                                 }
 642                                 default {}
 643                         }
 644                 }
 645                 return "$owner $owner_group"
 646         }
 647 }