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 }