Print this page
7290 ZFS test suite needs to control what utilities it can run
Reviewed by: Dan Kimmel <dan.kimmel@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/test/zfs-tests/tests/functional/acl/acl_common.kshlib
+++ new/usr/src/test/zfs-tests/tests/functional/acl/acl_common.kshlib
1 1 #
2 2 # CDDL HEADER START
3 3 #
4 4 # The contents of this file are subject to the terms of the
5 5 # Common Development and Distribution License (the "License").
6 6 # You may not use this file except in compliance with the License.
7 7 #
8 8 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 # or http://www.opensolaris.org/os/licensing.
10 10 # See the License for the specific language governing permissions
11 11 # and limitations under the License.
12 12 #
13 13 # When distributing Covered Code, include this CDDL HEADER in each
14 14 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 # If applicable, add the following below this CDDL HEADER, with the
16 16 # fields enclosed by brackets "[]" replaced with your own identifying
|
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
17 17 # information: Portions Copyright [yyyy] [name of copyright owner]
18 18 #
19 19 # CDDL HEADER END
20 20 #
21 21
22 22 #
23 23 # Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 # Use is subject to license terms.
25 25 #
26 26
27 +#
28 +# Copyright (c) 2016 by Delphix. All rights reserved.
29 +#
30 +
27 31 . $STF_SUITE/tests/functional/acl/acl.cfg
28 32 . $STF_SUITE/include/libtest.shlib
29 33
30 34 #
31 35 # Get the given file/directory access mode
32 36 #
33 37 # $1 object -- file or directroy
34 38 #
35 39 function get_mode #<obj>
36 40 {
37 41 typeset obj=$1
38 42 if (( ${#obj} == 0 )); then
39 43 return 1
40 44 fi
41 45
42 - $LS -ld $obj | $AWK '{print $1}'
46 + ls -ld $obj | awk '{print $1}'
43 47 }
44 48
45 49 #
46 50 # Get the given file/directory ACL
47 51 #
48 52 # $1 object -- file or directroy
49 53 #
50 54 function get_acl #<obj>
51 55 {
52 56 typeset obj=$1
53 57 if (( ${#obj} == 0 )); then
54 58 return 1
55 59 fi
56 60
57 - $LS -vd $obj | $NAWK '(NR != 1) {print $0}'
61 + ls -vd $obj | nawk '(NR != 1) {print $0}'
58 62 }
59 63
60 64 #
61 65 # Get the given file/directory ACL
62 66 #
63 67 # $1 object -- file or directroy
64 68 #
65 69 function get_compact_acl #<obj>
66 70 {
67 71 typeset obj=$1
68 72 if (( ${#obj} == 0 )); then
69 73 return 1
70 74 fi
71 75
72 - $LS -Vd $obj | $NAWK '(NR != 1) {print $0}'
76 + ls -Vd $obj | nawk '(NR != 1) {print $0}'
73 77 }
74 78
75 79 #
76 80 # Check the given two files/directories have the same ACLs
77 81 #
78 82 # Return 0, if source object acl is equal to target object acl.
79 83 #
80 84 # $1 source object
81 85 # $2 target object
82 86 #
83 87 function compare_acls #<src> <tgt>
84 88 {
85 89 typeset src=$1
86 90 typeset tgt=$2
|
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
87 91
88 92 (( ${#src} == 0 || ${#tgt} == 0 )) && return 1
89 93 [[ $src == $tgt ]] && return 0
90 94
91 95 typeset tmpsrc=/tmp/compare_acls.src.$$
92 96 typeset tmptgt=/tmp/compare_acls.tgt.$$
93 97
94 98 get_acl $src > $tmpsrc
95 99 get_acl $tgt > $tmptgt
96 100 typeset -i ret=0
97 - $DIFF $tmpsrc $tmptgt > /dev/null 2>&1
101 + diff $tmpsrc $tmptgt > /dev/null 2>&1
98 102 ret=$?
99 - $RM -f $tmpsrc $tmptgt
103 + rm -f $tmpsrc $tmptgt
100 104
101 105 if (( ret != 0 )); then
102 106 return $ret
103 107 fi
104 108
105 109 get_compact_acl $src > $tmpsrc
106 110 get_compact_acl $tgt > $tmptgt
107 - $DIFF $tmpsrc $tmptgt > /dev/null 2>&1
111 + diff $tmpsrc $tmptgt > /dev/null 2>&1
108 112 ret=$?
109 - $RM -f $tmpsrc $tmptgt
113 + rm -f $tmpsrc $tmptgt
110 114
111 115 return $ret
112 116 }
113 117
114 118 #
115 119 # Check that the given two objects have the same modes.
116 120 # Return 0, if their modes are equal with each other. Otherwise, return 1.
117 121 #
118 122 # $1 source object
119 123 # $2 target object
120 124 #
121 125 function compare_modes #<src> <tgt>
122 126 {
123 127 typeset src=$1
124 128 typeset tgt=$2
125 129 typeset -i i=0
126 130 set -A mode
127 131
128 132 (( ${#src} == 0 || ${#tgt} == 0 )) && return 1
129 133 [[ $src == $tgt ]] && return 0
130 134
131 135 typeset obj
132 136 for obj in $src $tgt
133 137 do
134 138 mode[i]=$(get_mode $obj)
135 139
136 140 (( i = i + 1 ))
137 141 done
138 142
139 143 [[ ${mode[0]} != ${mode[1]} ]] && return 1
140 144
141 145 return 0
142 146 }
143 147
144 148 #
145 149 # Check that the given two objects have the same xattrs.
146 150 # Return 0, if their xattrs are equal with each other. Otherwise, return 1.
147 151 #
148 152 # $1 source object
149 153 # $2 target object
150 154 #
151 155 function compare_xattrs #<src> <tgt>
152 156 {
153 157 typeset src=$1
154 158 typeset tgt=$2
|
↓ open down ↓ |
35 lines elided |
↑ open up ↑ |
155 159
156 160 (( ${#src} == 0 || ${#tgt} == 0 )) && return 1
157 161 [[ $src == $tgt ]] && return 0
158 162
159 163 typeset tmpsrc=/tmp/compare_xattrs.src.$$
160 164 typeset tmptgt=/tmp/compare_xattrs.tgt.$$
161 165
162 166 get_xattr $src > $tmpsrc
163 167 get_xattr $tgt > $tmptgt
164 168 typeset -i ret=0
165 - $DIFF $tmpsrc $tmptgt > /dev/null 2>&1
169 + diff $tmpsrc $tmptgt > /dev/null 2>&1
166 170 ret=$?
167 - $RM -f $tmpsrc $tmptgt
171 + rm -f $tmpsrc $tmptgt
168 172
169 173 return $ret
170 174 }
171 175
172 176 #
173 177 # Check '+' is set for a given file/directory with 'ls [-l]' command
174 178 #
175 179 # $1 object -- file or directory.
176 180 #
177 181 function plus_sign_check_l #<obj>
178 182 {
179 183 typeset obj=$1
180 184 if (( ${#obj} == 0 )); then
181 185 return 1
182 186 fi
183 187
184 - $LS -ld $obj | $AWK '{print $1}' | $GREP "+\>" > /dev/null
188 + ls -ld $obj | awk '{print $1}' | grep "+\>" > /dev/null
185 189
186 190 return $?
187 191 }
188 192
189 193 #
190 194 # Check '+' is set for a given file/directory with 'ls [-v]' command
191 195 #
192 196 # $1 object -- file or directory.
193 197 #
194 198 function plus_sign_check_v #<obj>
195 199 {
196 200 typeset obj=$1
197 201 if (( ${#obj} == 0 )); then
198 202 return 1
199 203 fi
200 204
201 - $LS -vd $obj | $NAWK '(NR == 1) {print $1}' | $GREP "+\>" > /dev/null
205 + ls -vd $obj | nawk '(NR == 1) {print $1}' | grep "+\>" > /dev/null
202 206
203 207 return $?
204 208 }
205 209
206 210 #
207 211 # A wrapper function of c program
208 212 #
209 213 # $1 legal login name
210 214 # $2-n commands and options
211 215 #
212 216 function chgusr_exec #<login_name> <commands> [...]
213 217 {
214 - $CHG_USR_EXEC $@
218 + chg_usr_exec $@
215 219 return $?
216 220 }
217 221
218 222 #
219 223 # Export the current user for the following usr_exec operating.
220 224 #
221 225 # $1 legal login name
222 226 #
223 227 function set_cur_usr #<login_name>
224 228 {
225 229 export ZFS_ACL_CUR_USER=$1
226 230 }
227 231
228 232 #
229 233 # Run commands by $ZFS_ACL_CUR_USER
230 234 #
231 235 # $1-n commands and options
232 236 #
233 237 function usr_exec #<commands> [...]
234 238 {
235 - $CHG_USR_EXEC "$ZFS_ACL_CUR_USER" $@
239 + chg_usr_exec "$ZFS_ACL_CUR_USER" $@
236 240 return $?
237 241 }
238 242
239 243 #
240 244 # Count how many ACEs for the speficied file or directory.
241 245 #
242 246 # $1 file or directroy name
243 247 #
244 248 function count_ACE #<file or dir name>
245 249 {
246 250 if [[ ! -e $1 ]]; then
247 251 log_note "Need input file or directroy name."
248 252 return 1
249 253 fi
250 254
251 - $LS -vd $1 | $NAWK 'BEGIN {count=0}
255 + ls -vd $1 | nawk 'BEGIN {count=0}
252 256 (NR != 1)&&(/[0-9]:/) {count++}
253 257 END {print count}'
254 258
255 259 return 0
256 260 }
257 261
258 262 #
259 263 # Get specified number ACE content of specified file or directory.
260 264 #
261 265 # $1 file or directory name
262 266 # $2 specified number
263 267 #
264 268 function get_ACE #<file or dir name> <specified number> <verbose|compact>
265 269 {
266 270 if [[ ! -e $1 || $2 -ge $(count_ACE $1) ]]; then
267 271 return 1
268 272 fi
269 273
270 274 typeset file=$1
271 275 typeset -i num=$2
272 276 typeset format=${3:-verbose}
273 277 typeset -i next_num=-1
274 278
275 279 typeset tmpfile=/tmp/tmp_get_ACE.$$
276 280 typeset line=""
277 281 typeset args
278 282
|
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
279 283 case $format in
280 284 verbose) args="-vd"
281 285 ;;
282 286 compact) args="-Vd"
283 287 ;;
284 288 *) log_fail "Invalid parameter as ($format), " \
285 289 "only verbose|compact is supported."
286 290 ;;
287 291 esac
288 292
289 - $LS $args $file > $tmpfile
290 - (( $? != 0 )) && log_fail "FAIL: $LS $args $file > $tmpfile"
293 + ls $args $file > $tmpfile
294 + (( $? != 0 )) && log_fail "FAIL: ls $args $file > $tmpfile"
291 295 while read line; do
292 296 [[ -z $line ]] && continue
293 297 if [[ $args == -vd ]]; then
294 298 if [[ $line == "$num":* ]]; then
295 299 (( next_num = num + 1 ))
296 300 fi
297 301 if [[ $line == "$next_num":* ]]; then
298 302 break
299 303 fi
300 304 if (( next_num != -1 )); then
301 305 print -n $line
302 306 fi
303 307 else
304 308 if (( next_num == num )); then
305 309 print -n $line
306 310 fi
307 311 (( next_num += 1 ))
308 312 fi
309 313 done < $tmpfile
310 314
311 - $RM -f $tmpfile
312 - (( $? != 0 )) && log_fail "FAIL: $RM -f $tmpfile"
315 + rm -f $tmpfile
316 + (( $? != 0 )) && log_fail "FAIL: rm -f $tmpfile"
313 317 }
314 318
315 319 #
316 320 # Cleanup exist user/group.
317 321 #
318 322 function cleanup_user_group
319 323 {
320 324 del_user $ZFS_ACL_ADMIN
321 325
322 326 del_user $ZFS_ACL_STAFF1
323 327 del_user $ZFS_ACL_STAFF2
324 328 del_group $ZFS_ACL_STAFF_GROUP
325 329
326 330 del_user $ZFS_ACL_OTHER1
327 331 del_user $ZFS_ACL_OTHER2
328 332 del_group $ZFS_ACL_OTHER_GROUP
329 333
|
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
330 334 return 0
331 335 }
332 336
333 337 #
334 338 # Clean up testfile and test directory
335 339 #
336 340 function cleanup
337 341 {
338 342 if [[ -d $TESTDIR ]]; then
339 343 cd $TESTDIR
340 - $RM -rf $TESTDIR/*
344 + rm -rf $TESTDIR/*
341 345 fi
342 346 }
343 347
344 348 #
345 349 # According to specified access or acl_spec, do relevant operating by using the
346 350 # specified user.
347 351 #
348 352 # $1 specified user
349 353 # $2 node
350 354 # $3 acl_spec or access
351 355 #
352 356 function rwx_node #user node acl_spec|access
353 357 {
354 358 typeset user=$1
355 359 typeset node=$2
|
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
356 360 typeset acl_spec=$3
357 361
358 362 if [[ $user == "" || $node == "" || $acl_spec == "" ]]; then
359 363 log_note "node or acl_spec are not defined."
360 364 return 1
361 365 fi
362 366
363 367 if [[ -d $node ]]; then
364 368 case $acl_spec in
365 369 *:read_data:*|read_data)
366 - chgusr_exec $user $LS -l $node > /dev/null 2>&1
370 + chgusr_exec $user ls -l $node > /dev/null 2>&1
367 371 return $? ;;
368 372 *:write_data:*|write_data)
369 373 if [[ -f ${node}/tmpfile ]]; then
370 - log_must $RM -f ${node}/tmpfile
374 + log_must rm -f ${node}/tmpfile
371 375 fi
372 - chgusr_exec $user $TOUCH ${node}/tmpfile > \
376 + chgusr_exec $user touch ${node}/tmpfile > \
373 377 /dev/null 2>&1
374 378 return $? ;;
375 379 *"execute:"*|execute)
376 - chgusr_exec $user $FIND $node > /dev/null 2>&1
380 + chgusr_exec $user find $node > /dev/null 2>&1
377 381 return $? ;;
378 382 esac
379 383 else
380 384 case $acl_spec in
381 385 *:read_data:*|read_data)
382 - chgusr_exec $user $CAT $node > /dev/null 2>&1
386 + chgusr_exec $user cat $node > /dev/null 2>&1
383 387 return $? ;;
384 388 *:write_data:*|write_data)
385 - chgusr_exec $user $DD if=/usr/bin/ls of=$node > \
389 + chgusr_exec $user dd if=/usr/bin/ls of=$node > \
386 390 /dev/null 2>&1
387 391 return $? ;;
388 392 *"execute:"*|execute)
389 393 ZFS_ACL_ERR_STR=$(chgusr_exec $user $node 2>&1)
390 394 return $? ;;
391 395 esac
392 396 fi
393 397 }
394 398
395 399 #
396 400 # Get the given file/directory xattr
397 401 #
|
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
398 402 # $1 object -- file or directroy
399 403 #
400 404 function get_xattr #<obj>
401 405 {
402 406 typeset obj=$1
403 407 typeset xattr
404 408 if (( ${#obj} == 0 )); then
405 409 return 1
406 410 fi
407 411
408 - for xattr in `$RUNAT $obj $LS | \
412 + for xattr in `runat $obj ls | \
409 413 /usr/xpg4/bin/egrep -v -e SUNWattr_ro -e SUNWattr_rw` ; do
410 - $RUNAT $obj $SUM $xattr
414 + runat $obj sum $xattr
411 415 done
412 416 }
413 417
414 418 #
415 419 # Get the owner of a file/directory
416 420 #
417 421 function get_owner #node
418 422 {
419 423 typeset node=$1
420 424 typeset value
421 425
422 426 if [[ -z $node ]]; then
423 427 log_fail "node are not defined."
424 428 fi
425 429
426 430 if [[ -d $node ]]; then
427 - value=$($LS -dl $node | $AWK '{print $3}')
431 + value=$(ls -dl $node | awk '{print $3}')
428 432 elif [[ -e $node ]]; then
429 - value=$($LS -l $node | $AWK '{print $3}')
433 + value=$(ls -l $node | awk '{print $3}')
430 434 fi
431 435
432 - $ECHO $value
436 + echo $value
433 437 }
434 438
435 439 #
436 440 # Get the group of a file/directory
437 441 #
438 442 function get_group #node
439 443 {
440 444 typeset node=$1
441 445 typeset value
442 446
443 447 if [[ -z $node ]]; then
444 448 log_fail "node are not defined."
445 449 fi
446 450
447 451 if [[ -d $node ]]; then
448 - value=$($LS -dl $node | $AWK '{print $4}')
452 + value=$(ls -dl $node | awk '{print $4}')
449 453 elif [[ -e $node ]]; then
450 - value=$($LS -l $node | $AWK '{print $4}')
454 + value=$(ls -l $node | awk '{print $4}')
451 455 fi
452 456
453 - $ECHO $value
457 + echo $value
454 458 }
455 459
456 460
457 461 #
458 462 # Get the group name that a UID belongs to
459 463 #
460 464 function get_user_group #uid
461 465 {
462 466 typeset uid=$1
463 467 typeset value
464 468
465 469 if [[ -z $uid ]]; then
466 470 log_fail "UID not defined."
467 471 fi
468 472
469 473 value=$(id $uid)
470 474
471 475 if [[ $? -eq 0 ]]; then
472 476 value=${value##*\(}
473 477 value=${value%%\)*}
474 - $ECHO $value
478 + echo $value
475 479 else
476 480 log_fail "Invalid UID (uid)."
477 481 fi
478 482 }
479 483
480 484 #
481 485 # Get the specified item of the specified string
482 486 #
483 487 # $1: Item number, count from 0.
484 488 # $2-n: strings
485 489 #
486 490 function getitem
487 491 {
488 492 typeset -i n=$1
489 493 shift
490 494
491 495 (( n += 1 ))
492 496 eval echo \${$n}
493 497 }
494 498
495 499 #
496 500 # This function calculate the specified directory files checksum and write
497 501 # to the specified array.
498 502 #
499 503 # $1 directory in which the files will be cksum.
500 504 # $2 file array name which was used to store file cksum information.
501 505 # $3 attribute array name which was used to store attribute information.
|
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
502 506 #
503 507 function cksum_files #<dir> <file_array_name> <attribute_array_name>
504 508 {
505 509 typeset dir=$1
506 510 typeset farr_name=$2
507 511 typeset aarr_name=$3
508 512
509 513 [[ ! -d $dir ]] && return
510 514 typeset oldpwd=$PWD
511 515 cd $dir
512 - typeset files=$($LS file*)
516 + typeset files=$(ls file*)
513 517
514 518 typeset -i i=0
515 519 typeset -i n=0
516 520 while (( i < NUM_FILE )); do
517 521 typeset f=$(getitem $i $files)
518 - eval $farr_name[$i]=\$\(\$CKSUM $f\)
522 + eval $farr_name[$i]=\$\(\cksum $f\)
519 523
520 524 typeset -i j=0
521 525 while (( j < NUM_ATTR )); do
522 - eval $aarr_name[$n]=\$\(\$RUNAT \$f \$CKSUM \
526 + eval $aarr_name[$n]=\$\(\runat \$f \cksum \
523 527 attribute.$j\)
524 528
525 529 (( j += 1 ))
526 530 (( n += 1 ))
527 531 done
528 532
529 533 (( i += 1 ))
530 534 done
531 535
532 536 cd $oldpwd
533 537 }
534 538
535 539 #
536 540 # This function compare two cksum results array.
537 541 #
538 542 # $1 The array name which stored the cksum before operation.
539 543 # $2 The array name which stored the cksum after operation.
540 544 #
541 545 function compare_cksum #<array1> <array2>
542 546 {
543 547 typeset before=$1
544 548 typeset after=$2
545 549 eval typeset -i count=\${#$before[@]}
546 550
547 551 typeset -i i=0
548 552 while (( i < count )); do
549 553 eval typeset var1=\${$before[$i]}
550 554 eval typeset var2=\${$after[$i]}
551 555
552 556 if [[ $var1 != $var2 ]]; then
553 557 return 1
554 558 fi
555 559
556 560 (( i += 1 ))
557 561 done
558 562
559 563 return 0
560 564 }
561 565
562 566 #
563 567 # This function calculate all the files cksum information in current directory
|
↓ open down ↓ |
31 lines elided |
↑ open up ↑ |
564 568 # and output them to the specified file.
565 569 #
566 570 # $1 directory from which the files will be cksum.
567 571 # $2 cksum output file
568 572 #
569 573 function record_cksum #<outfile>
570 574 {
571 575 typeset dir=$1
572 576 typeset outfile=$2
573 577
574 - [[ ! -d ${outfile%/*} ]] && usr_exec $MKDIR -p ${outfile%/*}
578 + [[ ! -d ${outfile%/*} ]] && usr_exec mkdir -p ${outfile%/*}
575 579
576 - usr_exec cd $dir ; $FIND . -depth -type f -exec cksum {} \\\; | \
577 - $SORT > $outfile
578 - usr_exec cd $dir ; $FIND . -depth -type f -xattr -exec runat {} \
579 - cksum attribute* \\\; | $SORT >> $outfile
580 + usr_exec cd $dir ; find . -depth -type f -exec cksum {} \\\; | \
581 + sort > $outfile
582 + usr_exec cd $dir ; find . -depth -type f -xattr -exec runat {} \
583 + cksum attribute* \\\; | sort >> $outfile
580 584 }
581 585
582 586 #
583 587 # The function create_files creates the directories and files that the script
584 588 # will operate on to test extended attribute functionality.
585 589 #
586 590 # $1 The base directory in which to create directories and files.
587 591 #
588 592 function create_files #<directory>
589 593 {
590 594 typeset basedir=$1
591 595
592 - [[ ! -d $basedir ]] && usr_exec $MKDIR -m 777 $basedir
593 - [[ ! -d $RES_DIR ]] && usr_exec $MKDIR -m 777 $RES_DIR
594 - [[ ! -d $INI_DIR ]] && usr_exec $MKDIR -m 777 $INI_DIR
595 - [[ ! -d $TST_DIR ]] && usr_exec $MKDIR -m 777 $TST_DIR
596 - [[ ! -d $TMP_DIR ]] && usr_exec $MKDIR -m 777 $TMP_DIR
596 + [[ ! -d $basedir ]] && usr_exec mkdir -m 777 $basedir
597 + [[ ! -d $RES_DIR ]] && usr_exec mkdir -m 777 $RES_DIR
598 + [[ ! -d $INI_DIR ]] && usr_exec mkdir -m 777 $INI_DIR
599 + [[ ! -d $TST_DIR ]] && usr_exec mkdir -m 777 $TST_DIR
600 + [[ ! -d $TMP_DIR ]] && usr_exec mkdir -m 777 $TMP_DIR
597 601
598 602 #
599 603 # Create the original file and its attribute files.
600 604 #
601 605 [[ ! -a $RES_DIR/file ]] && \
602 - usr_exec $FILE_WRITE -o create -f $RES_DIR/file \
606 + usr_exec file_write -o create -f $RES_DIR/file \
603 607 -b 1024 -d 0 -c 1
604 608 [[ ! -a $RES_DIR/attribute ]] && \
605 - usr_exec $CP $RES_DIR/file $RES_DIR/attribute
609 + usr_exec cp $RES_DIR/file $RES_DIR/attribute
606 610
607 611 typeset oldpwd=$PWD
608 612 cd $INI_DIR
609 613
610 614 typeset -i i=0
611 615 while (( i < NUM_FILE )); do
612 616 typeset dstfile=$INI_DIR/file.$$.$i
613 - usr_exec $CP $RES_DIR/file $dstfile
617 + usr_exec cp $RES_DIR/file $dstfile
614 618
615 619 typeset -i j=0
616 620 while (( j < NUM_ATTR )); do
617 - usr_exec $RUNAT $dstfile \
618 - $CP $RES_DIR/attribute ./attribute.$j
621 + usr_exec runat $dstfile \
622 + cp $RES_DIR/attribute ./attribute.$j
619 623 (( j += 1 ))
620 624 done
621 625
622 626 (( i += 1 ))
623 627 done
624 628
625 629 cd $oldpwd
626 630 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX