xfstests: RESULTS_DIR needs to be an absolute path
[xfstests-dev.git] / common / dump
1 ##/bin/bash
2 #
3 # Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.  All Rights Reserved.
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License as
7 # published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it would be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write the Free Software Foundation,
16 # Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17 #
18 #
19 # Functions useful for xfsdump/xfsrestore tests
20 #
21
22 # --- initializations ---
23 rm -f $seqres.full
24
25 if [ -n "$DEBUGDUMP" ]; then
26         _dump_debug=-v4
27         _restore_debug=-v4
28         _invutil_debug=-d
29
30         # Use dump/restore in qa directory (copy them here) for debugging
31         export PATH="$here:$PATH"
32         export __XFSDUMP_PROG="`set_prog_path xfsdump`"
33         export XFSDUMP_PROG="$__XFSDUMP_PROG -e"
34         export XFSRESTORE_PROG="`set_prog_path xfsrestore`"
35         export XFSINVUTIL_PROG="`set_prog_path xfsinvutil`"
36         [ -x $here/xfsdump ]    && echo "Using xfstests' xfsdump for debug"
37         [ -x $here/xfsrestore ] && echo "Using xfstests' xfsrestore for debug"
38         [ -x $here/xfsinvutil ] && echo "Using xfstests' xfsinvutil for debug"
39 fi
40
41 [ "$XFSDUMP_PROG" = "" ]    && _notrun "xfsdump not found"
42 [ "$XFSRESTORE_PROG" = "" ] && _notrun "xfsrestore not found"
43 [ "$XFSINVUTIL_PROG" = "" ] && _notrun "xfsinvutil not found"
44
45 # status returned for not run tests
46 NOTRUNSTS=2
47
48 # name those directories
49 dump_file=$tmp.dumpfile
50 # dump_file=$here/dumpfile #TEMP OVERRIDE DUMP FILE
51 dump_sdir=dumpdir
52 dump_dir=$SCRATCH_MNT/$dump_sdir
53 restore_sdir=restoredir
54 restore_dir=$SCRATCH_MNT/$restore_sdir
55 multi=3
56 dumptape=$TAPE_DEV
57 media_label="stress_tape_media"
58 session_label="stress_$seq"
59
60 nobody=4 # define this uid/gid as a number
61 do_quota_check=true # do quota check if quotas enabled
62
63 _need_to_be_root
64
65 # install our cleaner
66 trap "_cleanup; exit \$status" 0 1 2 3 15
67
68 # start inventory from a known base - move it aside for test
69 for dir in /var/xfsdump/inventory /var/lib/xfsdump/inventory; do
70     if [ -d $dir ]; then
71         [ -d $dir.$seq ] && rm -rf $dir.$seq
72         mv $dir $dir.$seq
73     fi
74 done
75
76 have_mtvariable=false
77 [ `uname` = "Linux" ] && have_mtvariable=true
78
79
80 _require_multi_stream()
81 {
82     $XFSDUMP_PROG -JF -f /dev/null -f /dev/null 2> /dev/null |
83     grep -q "too many -f arguments" &&
84     _notrun "xfsdump multi-stream support required"
85 }
86
87 _require_legacy_v2_format()
88 {
89     $XFSDUMP_PROG 2>&1 |
90     grep -q "generate format 2 dump" ||
91     _notrun "xfsdump -K option required"
92
93     $XFSRESTORE_PROG 2>&1 |
94     grep -q "force use of format 2 generation" ||
95     _notrun "xfsrestore -K option required"
96 }
97
98 #
99 # do a remote/local mt
100 #
101 _mt()
102 {
103     op=$1
104     if _isrmt; then
105         # REMOTE
106         _rmtdev=`echo $dumptape | $AWK_PROG -F: '{print $2}'`
107
108         if echo $dumptape | grep '@' >/dev/null; then
109             _spec=`echo $dumptape | $AWK_PROG -F: '{print $1}'`
110             _rmtuser=`echo $_spec | $AWK_PROG -F@ '{print $1}'`
111             _rmthost=`echo $_spec | $AWK_PROG -F@ '{print $2}'`
112             rsh -n -l $_rmtuser $_rmthost "mt -t $_rmtdev $op"
113         else
114             _rmthost=`echo $dumptape | $AWK_PROG -F: '{print $1}'`
115             rsh -n $_rmthost "mt -t $_rmtdev $op"
116         fi
117     else
118         #LOCAL
119         mt -t $dumptape $op
120     fi
121 }
122
123 _check_onl()
124 {
125     _limit=10
126     i=0
127     while [ $i -lt $_limit ]; do
128         echo "Checking online..." >>$seqres.full
129         if _mt status >$tmp.status 2>&1; then
130             break;
131         else
132             sleep 1
133         fi
134         let i=$i+1
135     done
136
137
138     if [ $i -eq $_limit ]; then
139         echo "ERROR: mt -f $dumptape failed"
140         cat $tmp.status
141
142         echo "mt -f $dumptape failed" >$seq.notrun
143         status=$NOTRUNSTS
144         exit
145     fi
146
147
148     if egrep -i 'onl|ready' $tmp.status | grep -iv 'not ready' >/dev/null; then
149         :
150     else
151         echo "ERROR: $dumptape is not online"
152         cat $tmp.status
153
154         echo "dumptape, $dumptape, is not online" >$seq.notrun
155         status=$NOTRUNSTS
156         exit
157     fi
158 }
159
160 _wait_tape()
161 {
162     echo "Wait for tape, $dumptape, ..." >>$seqres.full
163
164     i=0
165     while [ $i -lt 20 ]; do
166         echo "Checking status..." >>$seqres.full
167         if _mt status 2>&1 | tee -a $seqres.full | egrep -i "onl|ready" >/dev/null; then
168             break;
169         else
170             sleep 1
171         fi
172         let i=$i+1
173     done
174 }
175
176 #
177 # Keep trying so we know we really have rewound
178 #
179 _rewind()
180 {
181     echo "Initiate rewind..." >>$seqres.full
182     _wait_tape
183     _mt rewind >/dev/null
184     _wait_tape
185 }
186
187 #
188 # Do a custom erase because:
189 # (i) some machines don't support it
190 # (ii) some machines take forever to do it
191 #
192 _erase_soft()
193 {
194     echo "Erasing tape" | tee -a $seqres.full
195     _rewind
196     _mt weof 3
197     _rewind
198 }
199
200 _erase_hard()
201 {
202     echo "Erasing tape" | tee -a $seqres.full
203     _mt erase
204 }
205
206 _isrmt()
207 {
208     echo $dumptape | grep ':' >/dev/null
209 }
210
211 #
212 # Get tape ready
213 #
214 _set_variable()
215 {
216     $have_mtvariable || return
217
218     if _isrmt; then
219         :
220     else
221         # LOCAL
222         echo "Put scsi tape driver into variable block size mode"
223         mt -f $dumptape setblk 0
224     fi
225 }
226
227 _require_tape()
228 {
229     dumptape=$1
230
231     if [ -z "$dumptape" -o "@" == "$dumptape" ]; then
232         echo "This test requires a dump tape - none was specified"
233         echo "No dump tape specified" >$seqres.notrun
234         status=$NOTRUNSTS
235         exit
236     fi
237
238     _check_onl
239     _set_variable
240 }
241
242 _wipe_fs()
243 {
244     _require_scratch
245
246     _scratch_mkfs_xfs >>$seqres.full || _fail "mkfs failed"
247     _scratch_mount >>$seqres.full || _fail "mount failed"
248 }
249
250 #
251 # Cleanup created dirs and files
252 # Called by trap
253 #
254 _cleanup()
255 {
256     # Some tests include this before checking _supported_fs xfs
257     # and the sleeps & checks here get annoying
258     if [ "$FSTYP" != "xfs" ]; then
259        return
260     fi
261
262     cd $here
263     rm -f $tmp.*
264
265     if [ -n "$DEBUGDUMP" ]; then
266         # save it for inspection
267         for dir in /var/xfsdump/inventory /var/lib/xfsdump/inventory; do
268             [ -d $dir ] || continue
269             tar -cvf $seqres.inventory.tar $dir
270             ls -nR $dir >$seqres.inventory.ls
271         done
272     fi
273
274     # put inventory dir back
275     for dir in /var/xfsdump/inventory /var/lib/xfsdump/inventory; do
276         [ -d $dir.$seq ] || continue
277         rm -rf $dir             # get rid of new one
278         mv $dir.$seq $dir
279     done
280
281     if [ $status -ne $NOTRUNSTS ]; then
282         # Sleep added to stop _check_scratch_fs from complaining that the
283         # scratch_dev is still busy
284         sleep 10
285
286         _check_scratch_fs
287     fi
288 }
289
290 #
291 # ensure that bulkstat data will
292 # match with incore data
293 # by forcing disk data to be written out
294 #
295 _stable_fs()
296 {
297     _saveddir=`pwd`; cd /
298     umount $SCRATCH_MNT >>$seqres.full || _fail "unmount failed"
299     _scratch_mount >>$seqres.full || _fail "mount failed"
300     cd $_saveddir
301 }
302
303 #
304 # Run fsstress to create a mixture of
305 # files,dirs,links,symlinks
306 #
307 # Pinched from test 013.
308 #
309 _create_dumpdir_stress()
310 {
311     echo "Creating directory system to dump using fsstress."
312
313     _wipe_fs
314
315     _param="-f link=10 -f creat=10 -f mkdir=10 -f truncate=5 -f symlink=10"
316     _count=240
317     rm -rf $dump_dir
318     if ! mkdir $dump_dir; then
319         echo "    failed to mkdir $dump_dir"
320         status=1
321         exit
322     fi
323     echo ""
324     echo "-----------------------------------------------"
325     echo "fsstress : $_param"
326     echo "-----------------------------------------------"
327     if ! $here/ltp/fsstress $_param -s 1 $FSSTRESS_AVOID -n $_count -d $dump_dir >$tmp.out 2>&1
328     then
329         echo "    fsstress (count=$_count) returned $? - see $seqres.full"
330
331         echo "--------------------------------------"       >>$seqres.full
332         echo "output from fsstress:"                        >>$seqres.full
333         echo "--------------------------------------"       >>$seqres.full
334         cat $tmp.out                                        >>$seqres.full
335         status=1
336     fi
337
338     _stable_fs
339 }
340
341 _mk_fillconfig1()
342 {
343     cat <<End-of-File >$tmp.config
344 # pathname      size in bytes   owner   group
345 #
346 small           10      $nobody $nobody
347 big             102400  daemon  sys
348 sub/small       10      bin     bin
349 sub/big         102400  $nobody sys
350 #
351 sub/a           1       $nobody $nobody
352 sub/b           2       $nobody $nobody
353 sub/c           4       $nobody $nobody
354 sub/d           8       $nobody $nobody
355 sub/e           16      $nobody $nobody
356 sub/f           32      $nobody $nobody
357 sub/g           64      $nobody $nobody
358 sub/h           128     $nobody $nobody
359 sub/i           256     $nobody $nobody
360 sub/j           512     $nobody $nobody
361 sub/k           1024    $nobody $nobody
362 sub/l           2048    $nobody $nobody
363 sub/m           4096    $nobody $nobody
364 sub/n           8192    $nobody $nobody
365 #
366 sub/a00         100     $nobody $nobody
367 sub/b00         200     $nobody $nobody
368 sub/c00         400     $nobody $nobody
369 sub/d00         800     $nobody $nobody
370 sub/e00         1600    $nobody $nobody
371 sub/f00         3200    $nobody $nobody
372 sub/g00         6400    $nobody $nobody
373 sub/h00         12800   $nobody $nobody
374 sub/i00         25600   $nobody $nobody
375 sub/j00         51200   $nobody $nobody
376 sub/k00         102400  $nobody $nobody
377 sub/l00         204800  $nobody $nobody
378 sub/m00         409600  $nobody $nobody
379 sub/n00         819200  $nobody $nobody
380 #
381 sub/a000        1000    $nobody $nobody
382 sub/e000        16000   $nobody $nobody
383 sub/h000        128000  $nobody $nobody
384 sub/k000        1024000 $nobody $nobody
385 End-of-File
386 }
387
388 _mk_fillconfig2()
389 {
390     cat <<End-of-File >$tmp.config
391 # pathname      size in bytes
392 #
393 smalll          10      $nobody $nobody
394 biggg           102400  $nobody $nobody
395 sub/smalll      10      $nobody $nobody
396 sub/biggg       102400  $nobody $nobody
397 End-of-File
398 }
399
400 _mk_fillconfig_perm()
401 {
402     # dir_guid: ugo=rwx,g+s on dir is for IRIX chmod(1)
403
404     cat <<End-of-File >$tmp.config
405 # pathname      size/dir  user group mode
406 #
407 file_suid       10      $nobody $nobody 04777
408 file_guid       10      $nobody $nobody 02777
409 file_sticky     10      $nobody $nobody 01777
410 file_mix1       10      $nobody $nobody 761
411 file_mix2       10      $nobody $nobody 642
412 dir_suid        d       $nobody $nobody 04777
413 dir_guid        d       $nobody $nobody ugo=rwx,g+s
414 dir_sticky      d       $nobody $nobody 01777
415 dir_mix1        d       $nobody $nobody 761
416 dir_mix2        d       $nobody $nobody 642
417 End-of-File
418 }
419
420 _mk_fillconfig_ea()
421 {
422     cat <<End-of-File >$tmp.config
423 # pathname      size    user    group    perm   name value namespace
424 #
425 smalll          10      $nobody $nobody  777    attr1 some_text   user
426 biggg           102400  $nobody $nobody  777    attr2 some_text2  root
427 sub/smalll      10      $nobody $nobody  777    attr3 some_text3  user
428 sub/biggg       102400  $nobody $nobody  777    attr4 some_text4  root
429 dir             d       $nobody $nobody  777    attr5 dir_text    user
430 #
431 # Add more files so that there are more than the number
432 # of streams.
433 # There are bugs in dump/restore for # non-dir files < # streams
434 # It can be tested in another configuration.
435 # It is a pathalogical case.
436 #
437 sub/a           1       $nobody $nobody
438 sub/b           2       $nobody $nobody
439 sub/c           4       $nobody $nobody
440 sub/d           8       $nobody $nobody
441 sub/e           16      $nobody $nobody
442 sub/f           32      $nobody $nobody
443 sub/g           64      $nobody $nobody
444 sub/h           128     $nobody $nobody
445 sub/i           256     $nobody $nobody
446 sub/j           512     $nobody $nobody
447 sub/k           1024    $nobody $nobody
448 sub/l           2048    $nobody $nobody
449 sub/m           4096    $nobody $nobody
450 sub/n           8192    $nobody $nobody
451 End-of-File
452 }
453
454 #
455 # extended file attribute flags
456 #
457 _mk_fillconfig_xattr()
458 {
459     cat <<End-of-File >$tmp.config
460 # pathname      size    user    group    perm   name
461 #
462 xflag_realtime  10      $nobody $nobody  777    XFS_XFLAG_REALTIME
463 xflag_prealloc  10      $nobody $nobody  777    XFS_XFLAG_PREALLOC
464 xflag_immutable 10      $nobody $nobody  777    XFS_XFLAG_IMMUTABLE
465 xflag_append    10      $nobody $nobody  777    XFS_XFLAG_APPEND
466 xflag_sync      10      $nobody $nobody  777    XFS_XFLAG_SYNC
467 xflag_noatime   10      $nobody $nobody  777    XFS_XFLAG_NOATIME
468 xflag_nodump    10      $nobody $nobody  777    XFS_XFLAG_NODUMP
469 xflag_hasattr   10      $nobody $nobody  777    XFS_XFLAG_HASATTR
470 End-of-File
471 }
472
473 #
474 # Create a bunch of directories/files of different sizes
475 # filled with data.
476 #
477 # Pinched from test 001.
478 #
479 _do_create_dumpdir_fill()
480 {
481     echo "Creating directory system to dump using src/fill."
482
483     mkdir -p $dump_dir || _fail "cannot mkdir \"$dump_dir\""
484     cd $dump_dir
485
486     $verbose && echo -n "Setup "
487     sed -e '/^#/d' $tmp.config \
488     | while read file nbytes owner group perms ea_name ea_value namespace
489     do
490         if [ $nbytes = "d" ]; then
491             # create a directory
492             dir=$file
493             if [ ! -d $dir ]
494             then
495                 if mkdir $dir
496                 then
497                     :
498                 else
499                     $verbose && echo
500                     echo "Error: cannot mkdir \"$dir\""
501                     exit 1
502                 fi
503             fi
504         else
505             # create a directory/file
506             dir=`dirname $file`
507             if [ "$dir" != "." ]
508             then
509                 if [ ! -d $dir ]
510                 then
511                     if mkdir $dir
512                     then
513                         :
514                     else
515                         $verbose && echo
516                         echo "Error: cannot mkdir \"$dir\""
517                         exit 1
518                     fi
519                 fi
520             fi
521             rm -f $file
522             if $here/src/fill $file $file $nbytes
523             then
524                 :
525             else
526                 $verbose && echo
527                 echo "Error: cannot create \"$file\""
528                 exit 1
529             fi
530         fi
531         if [ -n "$owner" -a -n "$group" ]; then
532             chown $owner.$group $file
533         fi
534         if [ -n "$perms" ]; then
535             chmod $perms $file
536         fi
537
538         # extended attributes (EA)
539         if [ -n "$ea_name" -a -n "$ea_value" ]; then
540             if [ "X$namespace" = "Xroot" ]; then
541                 attr -R -s $ea_name -V $ea_value $file
542             else
543                 attr -s $ea_name -V $ea_value $file
544             fi
545         # extended file attribute flags - no value - NOT EAs
546         elif [ -n "$ea_name" -a -z "$ea_value" ]; then
547             # set the flag
548             # TODO XXX
549             # use xfs_io to send the ioctl
550             :
551         fi
552         $verbose && echo -n "."
553     done
554     $verbose && echo
555
556     cd $here
557 }
558
559 _mk_fillconfig_multi()
560 {
561     _mk_fillconfig1
562     cat <<End-of-File >>$tmp.config
563 # pathname      size in bytes
564 #
565 large000        8874368 $nobody $nobody
566 large111        2582912 $nobody $nobody
567 large222        7825792 $nobody $nobody
568 End-of-File
569 }
570
571 _create_dumpdir_largefile()
572 {
573     _wipe_fs
574     mkdir -p $dump_dir || _fail "cannot mkdir \"$dump_dir\""
575     _largesize=4294967297
576     _largefile=$dump_dir/largefile
577     echo "dd a largefile at offset $_largesize"
578     POSIXLY_CORRECT=yes \
579     dd if=/dev/zero of=$_largefile bs=1 seek=$_largesize count=10 2>&1
580     _stable_fs
581 }
582
583 _create_dumpdir_fill()
584 {
585     _wipe_fs
586     _mk_fillconfig1
587     _do_create_dumpdir_fill
588     _stable_fs
589 }
590
591 _create_dumpdir_fill2()
592 {
593     _wipe_fs
594     _mk_fillconfig2
595     _do_create_dumpdir_fill
596     _stable_fs
597 }
598
599 _create_dumpdir_fill_perm()
600 {
601     _wipe_fs
602     _mk_fillconfig_perm
603     _do_create_dumpdir_fill
604     _stable_fs
605 }
606
607 _create_dumpdir_fill_ea()
608 {
609     _wipe_fs
610     _mk_fillconfig_ea
611     _do_create_dumpdir_fill
612     _stable_fs
613 }
614
615 #
616 # Create enough files, and a few large enough files, so that
617 # some files are likely to be split across streams.
618 #
619 _create_dumpdir_fill_multi()
620 {
621     _wipe_fs
622     _mk_fillconfig_multi
623     _do_create_dumpdir_fill
624     _stable_fs
625 }
626
627 #
628 # Append a subset of the fill'ed files
629 # So we can see if just these get dumped on an incremental
630 #
631 _append_dumpdir_fill()
632 {
633     cd $dump_dir
634     cat <<End-of-File >$tmp.config
635 # pathname
636 #
637 small
638 sub/big
639 #
640 sub/a
641 sub/c
642 sub/e
643 End-of-File
644     sed -e '/^#/d' $tmp.config \
645     | while read file
646     do
647         echo 'Extra text' >>$file
648     done
649
650     cd $here
651     _stable_fs
652 }
653
654 _do_create_dump_symlinks()
655 {
656     echo "Creating directory system of symlinks to dump."
657
658     mkdir -p $dump_dir || _fail "cannot mkdir \"$dump_dir\""
659     cd $dump_dir
660
661     $verbose && echo -n "Setup "
662     sed -e '/^#/d' $tmp.config \
663     | while read file nbytes owner group owner2 group2 perms perms2
664     do
665         dir=`dirname $file`
666         if [ "$dir" != "." ]
667         then
668             if [ ! -d $dir ]
669             then
670                 if mkdir $dir
671                 then
672                     :
673                 else
674                     $verbose && echo
675                     echo "Error: cannot mkdir \"$dir\""
676                     exit 1
677                 fi
678             fi
679         fi
680         rm -f $file
681         touch $file
682
683         # Do chmod on symlink using umask.
684         # This won't do the right thing as it subtracts permissions.
685         # However, I don't care, as long as I get some different perms
686         # for testing.
687         if [ -n "$perms2" ]; then
688             omask=`umask`
689             umask $perms2
690         fi
691         ln -s $file $file-link
692         if [ -n "$perms2" ]; then
693             umask $omask
694         fi
695
696         if [ -n "$owner" -a -n "$group" ]; then
697             chown $owner.$group $file
698         fi
699         if [ -n "$owner" -a -n "$group" ]; then
700             chown -h $owner.$group $file-link
701         fi
702         if [ -n "$perms" ]; then
703             chmod $perms $file
704         fi
705         $verbose && echo -n "."
706     done
707     $verbose && echo
708
709     cd $here
710 }
711
712 _mk_symlink_config()
713 {
714     cat <<End-of-File >$tmp.config
715 # path  size    owner1  group1  owner2  group2  perm1   perm2
716 #
717 a       0       $nobody $nobody daemon  sys     124     421
718 b       0       daemon  sys     bin     bin     347     743
719 sub/a   0       bin     bin     $nobody sys     777     777
720 sub/b   0       $nobody sys     $nobody $nobody 367     763
721 End-of-File
722 }
723
724 _create_dumpdir_symlinks()
725 {
726     _wipe_fs
727     _mk_symlink_config
728     _do_create_dump_symlinks
729     _stable_fs
730 }
731
732 #
733 # create hardlinks of form $_fname, $_fname_h1 $_fname_h2 ...
734 #
735 _create_hardlinks()
736 {
737     _fname=$1
738     _numlinks=$2
739
740     touch $_fname
741     _j=1
742     while [ $_j -le $_numlinks ]; do
743         _suffix=_h$_j
744         _hardlink=$_fname$_suffix
745         echo "creating hardlink $_hardlink to $_fname"
746         ln $_fname $_hardlink
747         let _j=$_j+1
748     done
749 }
750
751 #
752 # create a set of hardlinks
753 # create hardlinks of form file1, file1_h1 file1_h2 ...
754 # create hardlinks of form file2, file2_h1 file2_h2 ...
755 # create hardlinks of form file3, file3_h1 file3_h2 ...
756 #
757 _create_hardset()
758 {
759     _numsets=$1
760     _i=1
761     while [ $_i -le $_numsets ]; do
762         _create_hardlinks file$_i 5
763         let _i=$_i+1
764     done
765 }
766
767
768 _modify_level()
769 {
770     _level=$1
771     echo "mod level $_level" >$dump_dir/file$_level
772 }
773
774 _create_dumpdir_hardlinks()
775 {
776     _numsets=$1
777     _wipe_fs
778     echo "Creating directory system of hardlinks to incrementally dump."
779
780     mkdir -p $dump_dir || _fail "cannot mkdir \"$dump_dir\""
781     cd $dump_dir
782
783     _create_hardset $_numsets
784
785     cd $here
786     _stable_fs
787 }
788
789 #
790 # Filter for ls
791 # Filter out times and dates on symlinks and char devices.
792 # Filter out size on directories because this can differ
793 # when transitioning to long inode numbers (ie. 64 bits).
794 #
795 _ls_filter()
796 {
797   $AWK_PROG '
798         /^l/ { date = $8; time = $7; sub(date,"DATE"); sub(time,"TIME"); print}
799         /^c/ { date = $9; time = $7; sub(date,"DATE"); sub(time,"TIME"); print}
800         /^d/ { size = $5; sub(size,"SIZE"); print}
801         {print}' \
802   | sed -e 's/total [0-9][0-9]*/total TOTAL/'
803 }
804
805 #
806 # Filtering of Irix character hwgraph device names
807 # e.g.
808 # chardev: /hw/node/xtalk/15/pci/0/scsi_ctlr/0/target/1/lun/0/disk/partition/4/char
809 # blkdev:  /dev/dsk/dks0d1s4
810 #
811 _filter_devchar()
812 {
813     $AWK_PROG '
814         /\/hw\/node/ {
815             sub(/\/hw.*scsi_ctlr\//,"/dev/dsk/dks")  # blah blah /dev/dsk/dks0/target/1/....
816             sub(/\/target\//,"d")                    # blah blah /dev/dsk/dks0d1/lun/0/disk.....
817             sub(/\/lun.*partition\//,"s")            # blah blah /dev/dsk/dks0d1s4/char
818             sub(/\/char/,"")                         # blah blah /dev/dsk/dks0d1s4
819         }
820         { print }
821     '
822 }
823
824
825 #
826 # Filter out the non-deterministic dump msgs from
827 # xfsdump and xfsrestore
828 #
829 _dump_filter_main()
830 {
831   _filter_devchar |\
832   sed \
833       -e "s#$__XFSDUMP_PROG#xfsdump#"                   \
834       -e "s#$XFSRESTORE_PROG#xfsrestore#"               \
835       -e "s#$XFSINVUTIL_PROG#xfsinvutil#"               \
836       -e "s/`hostname`/HOSTNAME/"                       \
837       -e "s#$SCRATCH_DEV#SCRATCH_DEV#"                  \
838       -e "s#$SCRATCH_RAWDEV#SCRATCH_DEV#"               \
839       -e "s#$dumptape#TAPE_DEV#"                        \
840       -e "s#$SCRATCH_MNT#SCRATCH_MNT#"                  \
841       -e "s#$dump_file#DUMP_FILE#"                      \
842       -e 's#/var/lib/xfsdump#/var/xfsdump#'             \
843       -e 's/session id:[        ]*[0-9a-f-]*/session id: ID/'  \
844       -e '/filesystem id:[      ]*[0-9a-f-]*/d'         \
845       -e 's/time:[      ].*/time: TIME/'                \
846       -e 's/date:[      ].*/date: DATE/'                \
847       -e 's/dump begun .*/dump begun DATE/'             \
848       -e 's/previously begun .*/previously begun DATE/' \
849       -e 's/[0-9][0-9]* seconds/SECS seconds/'          \
850       -e 's/restore.[0-9][0-9]*/restore.PID/'           \
851       -e 's/ino [0-9][0-9]*/ino INO/g'                  \
852       -e '/stream [0-9]:/s/offset [0-9][0-9]*/offset NUM/g'     \
853       -e '/: dump size/s/[0-9][0-9]*/NUM/'              \
854       -e '/dump size:/s/[0-9][0-9]*/NUM/'               \
855       -e '/dump size per stream:/s/[0-9][0-9]*/NUM/'    \
856       -e 's/\(media file size[   ]*\)[0-9][0-9]*/\1NUM/' \
857       -e 's/\(mfile size:[       ]*\)[0-9][0-9]*/\1NUM/' \
858       -e '/drive[        ]*[0-9][0-9]*:/d'              \
859       -e '/\/dev\/tty/d'                                \
860       -e '/inventory session uuid/d'                    \
861       -e '/ - Running single-threaded/d'                \
862       -e '/Mount point match/d'                         \
863       -e '/^.*I\/O metrics: .*$/d'                      \
864       -e 's/1048576/BLOCKSZ/'                           \
865       -e 's/2097152/BLOCKSZ/'                           \
866       -e 's/(pid[        ]*[1-9][0-9]*)/\(pid PID\)/'   \
867       -e '/version [3-9]\.[0-9]/d'                      \
868       -e 's/\/hw\/module.*$/SCRATCH_DEV/'               \
869       -e 's/xfsdump: ino map phase 1: .*/xfsdump: ino map <PHASES>/' \
870       -e '/xfsdump: ino map phase [2]/,1d'              \
871       -e '/xfsdump: ino map phase [3]/,1d'              \
872       -e '/xfsdump: ino map phase [4]/,1d'              \
873       -e '/xfsdump: ino map phase [5]/,1d'              \
874       -e 's/id:[[:space:]]*[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}/ID: ID/'                                              \
875       -e 's/\[y\/n\][- ]----------------------*/\[y\/n\]/'              \
876       -e '/skip attribute set/d'                                \
877   | perl -ne '
878         # filter out all the output between the lines "Dump Summary:"
879         # and "Dump Status:"
880         if ($_ =~ /(?:Dump|Restore) Summary/) {
881                 $skip = 1;
882         } elsif ($_ =~ /(?:Dump|Restore) Status/) {
883                 $skip = 0;
884         }
885         print if (! $skip);' \
886   | perl -ne '
887         # correct the file count if large scratch devices are being used
888         $skip = 0;
889         if ($_ =~ /(\S+) directories and (\S+) entries/) {
890                 $foo = $2;
891                 if ($ENV{'LARGE_SCRATCH_DEV'} && $foo > 0) {
892                         $foo -= 1;
893                 }
894                 printf("xfsrestore: %u directories and %u entries processed\n",
895                                                 $1, $foo);
896                 $skip = 1;
897         }
898         print if (! $skip);'
899 }
900
901 _dump_filter()
902 {
903    if $do_quota_check
904    then
905        _dump_filter_main | _check_quota_dumprestore | _check_quota_entries
906    else
907        _dump_filter_main
908    fi
909 }
910
911 _invutil_filter()
912 {
913   _dump_filter_main \
914   | sed \
915         -e 's/UUID[     ]*:[    ][0-9a-f-]*/UUID                :       ID/' \
916         -e 's/TIME OF DUMP[     ]*:.*/TIME OF DUMP      :       TIME/' \
917         -e 's/HOSTNAME:SCRATCH_MNT.*/HOSTNAME:SCRATCH_MNT/' \
918         -e 's#inventory/[0-9a-f-]*#inventory/UUID#' \
919
920 }
921
922
923 _dir_filter()
924 {
925   sed \
926     -e "s#$dump_file#DUMP_FILE#g"      \
927     -e "s#$SCRATCH_DEV#SCRATCH_DEV#"        \
928     -e "s#$SCRATCH_RAWDEV#SCRATCH_DEV#"    \
929     -e "s#$dumptape#TAPE_DEV#"         \
930     -e "s#$dump_dir#DUMP_DIR#g"       \
931     -e "s#$restore_dir#RESTORE_DIR#g" \
932     -e "s#$SCRATCH_MNT#SCRATCH_MNT#g"       \
933     -e "s#$dump_sdir#DUMP_SUBDIR#g"   \
934     -e "s#$restore_sdir#RESTORE_SUBDIR#g" \
935     -e "s#$$#PID#g" \
936     -e "/Only in SCRATCH_MNT: .use_space/d" \
937
938 }
939
940 #
941 # Parse xfsdump arguments.
942 # Note: requires a space between option letter and argument
943 #
944 _parse_dump_args()
945 {
946     OPTIND=0
947     dump_args=""
948     while [ $# -gt 0 ]
949     do
950         case $1
951         in
952         -f)
953             [ -z "$2" ] && _fail "missing argument for -f"
954             dumptape=$2
955             dump_file=$2
956             shift
957             ;;
958         -L)
959             [ -z "$2" ] && _fail "missing argument for -L"
960             session_label=$2
961             shift
962             ;;
963         --multi)
964             [ -z "$2" ] && _fail "missing argument for --multi"
965             multi=$2
966             shift
967             ;;
968         --check-quota)
969             do_quota_check=true
970             ;;
971         --no-check-quota)
972             do_quota_check=false
973             ;;
974         -o|-D|-F|-K)
975             dump_args="$dump_args $1"
976             ;;
977         -l|-d)
978             [ -z "$2" ] && _fail "missing argument for $1"
979             dump_args="$dump_args $1$2"
980             shift
981             ;;
982         *)
983             _fail "invalid argument to common.dump function: $1"
984             ;;
985         esac
986         shift
987     done
988 }
989
990 #
991 # Parse xfsrestore arguments.
992 # Note: requires a space between option letter and argument
993 #
994 _parse_restore_args()
995 {
996     OPTIND=0
997     restore_args=""
998     while [ $# -gt 0 ]
999     do
1000         case $1
1001         in
1002         -f)
1003             [ -z "$2" ] && _fail "missing argument for -f"
1004             dumptape=$2
1005             dump_file=$2
1006             shift
1007             ;;
1008         -L)
1009             [ -z "$2" ] && _fail "missing argument for -L"
1010             session_label=$2
1011             shift
1012             ;;
1013         --multi)
1014             [ -z "$2" ] && _fail "missing argument for --multi"
1015             multi=$2
1016             shift
1017             ;;
1018         --check-quota)
1019             do_quota_check=true
1020             ;;
1021         --no-check-quota)
1022             do_quota_check=false
1023             ;;
1024         -K|-R)
1025             restore_args="$restore_args $1"
1026             ;;
1027         *)
1028             _fail "invalid argument to common.dump function: $1"
1029             ;;
1030         esac
1031         shift
1032     done
1033 }
1034
1035
1036 #
1037 # Dump a subdir
1038 #
1039 _do_dump_sub()
1040 {
1041     _parse_dump_args $*
1042
1043     echo "Dumping to tape..."
1044     opts="$_dump_debug$dump_args -s $dump_sdir -f $dumptape -M $media_label -L $session_label $SCRATCH_MNT"
1045     echo "xfsdump $opts" | _dir_filter
1046     $XFSDUMP_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1047 }
1048
1049 #
1050 # Do dump to tape
1051 #
1052 _do_dump()
1053 {
1054     _parse_dump_args $*
1055
1056     echo "Dumping to tape..."
1057     opts="$_dump_debug$dump_args -f $dumptape -M $media_label -L $session_label $SCRATCH_MNT"
1058     echo "xfsdump $opts" | _dir_filter
1059     $XFSDUMP_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1060 }
1061
1062
1063 #
1064 # Do full dump with -m
1065 #
1066 _do_dump_min()
1067 {
1068     _parse_dump_args $*
1069
1070     echo "Dumping to tape..."
1071     onemeg=1048576
1072     opts="$_dump_debug$dump_args -m -b $onemeg -l0 -f $dumptape -M $media_label -L $session_label $SCRATCH_MNT"
1073     echo "xfsdump $opts" | _dir_filter
1074     $XFSDUMP_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1075 }
1076
1077
1078 #
1079 # Do full dump to file
1080 #
1081 _do_dump_file()
1082 {
1083     _parse_dump_args $*
1084
1085     echo "Dumping to file..."
1086     opts="$_dump_debug$dump_args -f $dump_file -M $media_label -L $session_label $SCRATCH_MNT"
1087     echo "xfsdump $opts" | _dir_filter
1088     $XFSDUMP_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1089 }
1090
1091 #
1092 # Do full dump to multiple files
1093 #
1094 _do_dump_multi_file()
1095 {
1096     _parse_dump_args $*
1097
1098     multi_args=""
1099
1100     i=0
1101     while [ $i -lt $multi ]
1102     do
1103         multi_args="$multi_args -f $dump_file.$i -M $media_label.$i"
1104         let i=$i+1
1105     done
1106
1107     echo "Dumping to files..."
1108     opts="$_dump_debug$dump_args $multi_args -L $session_label $SCRATCH_MNT"
1109     echo "xfsdump $opts" | _dir_filter
1110     $XFSDUMP_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1111 }
1112
1113
1114 _prepare_restore_dir()
1115 {
1116     rm -rf $restore_dir
1117     mkdir $restore_dir || _fail "failed to mkdir $restore_dir"
1118 }
1119
1120
1121 #
1122 # Get tape ready and restore dir
1123 #
1124 _prepare_restore()
1125 {
1126     _prepare_restore_dir
1127
1128     echo "Rewinding tape"
1129     _rewind
1130 }
1131
1132 #
1133 # Restore the tape into $restore_dir
1134 #
1135 _do_restore()
1136 {
1137     _parse_restore_args $*
1138     _prepare_restore
1139
1140     echo "Restoring from tape..."
1141     opts="$_restore_debug$restore_args -f $dumptape  -L $session_label $restore_dir"
1142     echo "xfsrestore $opts" | _dir_filter
1143     $XFSRESTORE_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1144 }
1145
1146 #
1147 # Restore the tape into $restore_dir using -m
1148 #
1149 _do_restore_min()
1150 {
1151     _parse_restore_args $*
1152     _prepare_restore
1153
1154     echo "Restoring from tape..."
1155     onemeg=1048576
1156     opts="$_restore_debug$restore_args -m -b $onemeg -f $dumptape  -L $session_label $restore_dir"
1157     echo "xfsrestore $opts" | _dir_filter
1158     $XFSRESTORE_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1159 }
1160
1161 #
1162 # Restore the tape from a dump file
1163 #
1164 _do_restore_file()
1165 {
1166     _parse_restore_args $*
1167     _prepare_restore_dir
1168
1169     echo "Restoring from file..."
1170     opts="$_restore_debug$restore_args -f $dump_file  -L $session_label $restore_dir"
1171     echo "xfsrestore $opts" | _dir_filter
1172     $XFSRESTORE_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1173 }
1174
1175 #
1176 # Cumulative restore from a file
1177 # Must call _prepare_restore_dir before the first
1178 # (and only the first) call to this function.
1179 #
1180 _do_restore_file_cum()
1181 {
1182     _parse_restore_args $*
1183
1184     echo "Restoring cumumlative from file..."
1185     opts="$_restore_debug$restore_args -f $dump_file -r $restore_dir"
1186     echo "xfsrestore $opts" | _dir_filter
1187     $XFSRESTORE_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1188 }
1189
1190 _do_restore_toc()
1191 {
1192     _parse_restore_args $*
1193
1194     echo "Contents of dump ..."
1195     opts="$_restore_debug$restore_args -f $dump_file -t"
1196     echo "xfsrestore $opts" | _dir_filter
1197     cd $SCRATCH_MNT # for IRIX which needs xfs cwd
1198     $XFSRESTORE_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter_main |\
1199     _check_quota_file |\
1200     _check_quota_entries |\
1201     $AWK_PROG 'NF != 1 { print; next }
1202                {files = sprintf("%s\n%s", files, $1)}
1203                 END { print files | "sort" } '
1204     # the above awk code is to alpha sort only the output
1205     # of files (and not the verbose restore msgs)
1206     cd $here # put back
1207 }
1208
1209 #
1210 # Restore the tape from multiple dump files
1211 #
1212 _do_restore_multi_file()
1213 {
1214     _parse_restore_args $*
1215     _prepare_restore_dir
1216
1217     multi_args=""
1218
1219     i=0
1220     while [ $i -lt $multi ]
1221     do
1222         multi_args="$multi_args -f $dump_file.$i"
1223         let i=$i+1
1224     done
1225
1226     echo "Restoring from file..."
1227     opts="$_restore_debug$restore_args $multi_args -L $session_label $restore_dir"
1228     echo "xfsrestore $opts" | _dir_filter
1229     $XFSRESTORE_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1230 }
1231
1232 #
1233 # Do xfsdump piped into xfsrestore - xfsdump | xfsrestore
1234 # Pass dump options in $1 and restore options in $2, if required. e.g.:
1235 #     _do_dump_restore "-o -F" "-R"
1236 #     _do_dump_restore "" "-R"
1237 #
1238 # Use -s as we want to dump and restore to the same xfs partition
1239 #
1240 _do_dump_restore()
1241 {
1242     _parse_dump_args $1
1243     _parse_restore_args $2
1244     _prepare_restore_dir
1245     echo "xfsdump|xfsrestore ..."
1246     restore_opts="$_restore_debug$restore_args - $restore_dir"
1247     dump_opts="$_dump_debug$dump_args -s $dump_sdir - $SCRATCH_MNT"
1248     echo "xfsdump $dump_opts | xfsrestore $restore_opts" | _dir_filter
1249     $XFSDUMP_PROG $dump_opts 2>$tmp.dump.mlog | $XFSRESTORE_PROG $restore_opts 2>&1 | tee -a $seqres.full | _dump_filter
1250     _dump_filter <$tmp.dump.mlog
1251 }
1252
1253 #
1254 # Compare dumped subdirectory with restored dir
1255 # using ls -nR.
1256 # Thus no contents are compared but permissions, sizes,
1257 # owners, etc... are.
1258 #
1259 _ls_compare_sub()
1260 {
1261     #
1262     # verify we got back what we dumped
1263     #
1264     echo "Comparing listing of dump directory with restore directory"
1265     ls -nR $dump_dir | tee -a $seqres.full | _ls_filter >$tmp.dump_dir
1266     ls -nR $restore_dir/$dump_sdir | tee -a $seqres.full | _ls_filter \
1267     | sed -e "s#$restore_sdir\/##" >$tmp.restore_dir
1268
1269     diff -bcs $tmp.dump_dir $tmp.restore_dir | sed -e "s#$tmp#TMP#g"
1270 }
1271
1272 #
1273 # filter out the date fields
1274 #
1275 _ls_nodate_filter()
1276 {
1277     $AWK_PROG 'NF == 9 { print $1, $2, $3, $4, $9 }'
1278 }
1279
1280 #
1281 # _ls_compare_sub but don't compare dates
1282 _ls_nodate_compare_sub()
1283 {
1284     #
1285     # verify we got back what we dumped
1286     #
1287     echo "Comparing listing of dump directory with restore directory"
1288     ls -nR $dump_dir | tee -a $seqres.full | _ls_filter | _ls_nodate_filter >$tmp.dump_dir
1289     ls -nR $restore_dir/$dump_sdir | tee -a $seqres.full | _ls_filter \
1290     | _ls_nodate_filter | sed -e "s#$restore_sdir\/##" >$tmp.restore_dir
1291
1292     diff -bcs $tmp.dump_dir $tmp.restore_dir | sed -e "s#$tmp#TMP#g"
1293 }
1294
1295 #
1296 # Compare using recursive diff the files of the dumped
1297 # subdirectory.
1298 # This one will compare the contents.
1299 #
1300 _diff_compare_sub()
1301 {
1302     echo "Comparing dump directory with restore directory"
1303     diff -rs $dump_dir $restore_dir/$dump_sdir | _dir_filter
1304 }
1305
1306 _get_eas_on_path()
1307 {
1308     _path=$1
1309
1310 # Tim - this is the IRIX way...
1311     # find $_path -exec attr -l {} \; |\
1312     # awk '{print $9, $2}' |\
1313     # sed 's/["]//g' |\
1314     # sort |\
1315 # and this is now the Linux way...
1316     echo "User names"
1317     getfattr --absolute-names -Rh -m user $_path |\
1318     perl -wn -e '
1319         if (m/^# file: (\S+)/) { $file = $1 }
1320         elsif (m/^user\.(\w+)/) { print $file, " ",$1,"\n" }' |\
1321     sort |\
1322     while read file ea_name; do
1323         attr -g $ea_name $file
1324     done
1325
1326     if [ "$USE_ATTR_SECURE" = yes ]; then
1327         echo "Security names"
1328         getfattr --absolute-names -Rh -m security $_path |\
1329         perl -wn -e '
1330             if (m/^# file: (\S+)/) { $file = $1 }
1331             elsif (m/^security\.(\w+)/) { print $file, " ",$1,"\n" }' |\
1332         sort |\
1333         while read file ea_name; do
1334             attr -g $ea_name $file
1335         done
1336     fi
1337
1338     echo "Root names"
1339     getfattr --absolute-names -Rh -m trusted $_path |\
1340     perl -wn -e '
1341         if (m/^# file: (\S+)/) { $file = $1 }
1342         elsif (m/^trusted\.(\w+)/) { print $file, " ",$1,"\n" }' |\
1343     sort |\
1344     while read file ea_name; do
1345         attr -R -g $ea_name $file
1346     done
1347 }
1348
1349 #
1350 # Compare the extended attributes of the files/dirs
1351 # b/w the dumped and restore dirs.
1352 #
1353 #
1354 # Attribute "attr5" had a 8 byte value for /spare1/dump.5460/dir:
1355 # Attribute "attr5" had a 8 byte value for /spare1/restore.5460/dump.5460/dir:
1356 #
1357 _diff_compare_eas()
1358 {
1359     echo "Comparing dump directory with restore directory"
1360     echo "Looking at the extended attributes (EAs)"
1361     echo "EAs on dump"
1362     _get_eas_on_path $dump_dir | tee $seqres.ea1 | _dir_filter
1363     echo "EAs on restore"
1364     _get_eas_on_path $restore_dir/$dump_sdir \
1365     | sed -e "s#$restore_sdir\/##" \
1366     | tee $seqres.ea2 \
1367     | _dir_filter
1368     diff -s $seqres.ea1 $seqres.ea2
1369 }
1370
1371
1372 #
1373 # Compare using recursive diff the files of the dumped
1374 # filesystem
1375 #
1376 _diff_compare()
1377 {
1378     echo "Comparing dump directory with restore directory"
1379     diff -rs $SCRATCH_MNT $restore_dir | _dir_filter | _check_quota_diff
1380 }
1381
1382 #
1383 # Check out the dump inventory
1384 #
1385 _dump_inventory()
1386 {
1387     $XFSDUMP_PROG $_dump_debug -I | tee -a $seqres.full | _dump_filter_main
1388 }
1389
1390 #
1391 # Do the xfsinvutil cmd with debug and filters
1392 # Need to set variable: "$middate" to the invutil date
1393 #
1394 _do_invutil()
1395 {
1396     host=`hostname`
1397     echo "xfsinvutil $_invutil_debug -M $host:$SCRATCH_MNT \"$middate\" $*" >$seqres.full
1398     $XFSINVUTIL_PROG $_invutil_debug $* -M $host:$SCRATCH_MNT "$middate" \
1399     | tee -a $seqres.full | _invutil_filter
1400 }
1401
1402 #
1403 # ensure we can find the user quota msg if user quotas are on
1404 # ensure we can find the group quota msg if group quotas are on
1405 #
1406 _check_quota()
1407 {
1408     usermsg=$1
1409     groupmsg=$2
1410     projectmsg=$3
1411     uquota=0
1412     gquota=0
1413     pquota=0
1414     $here/src/feature -U $SCRATCH_DEV && uquota=1
1415     $here/src/feature -G $SCRATCH_DEV && gquota=1
1416     $here/src/feature -P $SCRATCH_DEV && pquota=1
1417
1418     $AWK_PROG -v uquota=$uquota -v gquota=$gquota -v pquota=$pquota \
1419               -v full=$seqres.full -v usermsg="$usermsg" \
1420               -v groupmsg="$groupmsg" -v projectmsg="$projectmsg" '
1421         $0 ~ projectmsg {
1422                         print "Found project quota:", $0 >>full
1423                         found_pquota = 1
1424                         if (!pquota) {
1425                             print "Found extra:", $0
1426                         }
1427                         next
1428         }
1429         $0 ~ groupmsg {
1430                         print "Found group quota:", $0 >>full
1431                         found_gquota = 1
1432                         if (!gquota) {
1433                             print "Found extra:", $0
1434                         }
1435                         next
1436         }
1437         $0 ~ usermsg {
1438                         print "Found user quota:", $0 >>full
1439                         found_uquota = 1
1440                         if (!uquota) {
1441                             print "Found extra:", $0
1442                         }
1443                         next
1444         }
1445                         { print }
1446         END {
1447                 if (uquota && !found_uquota) {
1448                     print "Missing user quota msg:", usermsg
1449                 }
1450                 if (gquota && !found_gquota) {
1451                     print "Missing group quota msg:", groupmsg
1452                 }
1453                 if (pquota && !found_pquota) {
1454                     print "Missing project quota msg:", projectmsg
1455                 }
1456         }
1457     '
1458 }
1459
1460 #
1461 # xfsrestore: 3 directories and 40 entries processed
1462 #   $5 = 40
1463 #   num entries needs to be reduced by num quota file(s)
1464 #
1465 _check_quota_entries()
1466 {
1467     uquota=0
1468     gquota=0
1469     pquota=0
1470     $here/src/feature -U $SCRATCH_DEV && uquota=1
1471     $here/src/feature -G $SCRATCH_DEV && gquota=1
1472     $here/src/feature -P $SCRATCH_DEV && pquota=1
1473     $AWK_PROG -v uquota=$uquota -v gquota=$gquota -v pquota=$pquota '
1474         /entries processed/ {
1475                 if (uquota) $5--
1476                 if (gquota) $5--
1477                 if (pquota) $5--
1478         }
1479         {print}'
1480 }
1481
1482 #
1483 # Look for:
1484 # xfsdump: saving user quota information for: SCRATCH_MNT
1485 # xfsdump: saving group quota information for: SCRATCH_MNT
1486 # xfsdump: saving project quota information for: SCRATCH_MNT
1487 # xfsrestore: user quota information written to ...'
1488 # xfsrestore: group quota information written to ...'
1489 # xfsrestore: project quota information written to ...'
1490 #
1491 # If on IRIX then look for:
1492 # xfsrestore: use 'edquota' to restore quotas
1493 # Else look for:
1494 # xfsrestore: use 'xfs_quota' to restore quotas
1495 #
1496 _check_quota_dumprestore()
1497 {
1498     if [ "$HOSTOS" == "IRIX" ]; then
1499         _check_quota 'user quota information' \
1500                      'group quota information' \
1501                      'project quota information' | \
1502         sed "/xfsrestore:.*use 'edquota' to restore quotas/d"
1503     else
1504         _check_quota 'user quota information' \
1505                      'group quota information' \
1506                      'project quota information' | \
1507         sed "/xfsrestore:.*use 'xfs_quota' to restore quotas/d"
1508     fi
1509 }
1510
1511 #
1512 # Look for:
1513 # Only in RESTORE_DIR: xfsdump_quotas
1514 # Only in RESTORE_DIR: xfsdump_quotas_group
1515 # Only in RESTORE_DIR: xfsdump_quotas_project
1516 #
1517 _check_quota_diff()
1518 {
1519    _check_quota 'Only in RESTORE_DIR: xfsdump_quotas' \
1520         'Only in RESTORE_DIR: xfsdump_quotas_group' \
1521         'Only in RESTORE_DIR: xfsdump_quotas_proj'
1522 }
1523
1524 #
1525 # Look for the quota file in the output
1526 # Ensure that it is there if it should be
1527 # Filter it out so that the output is always the same
1528 # even with no quotas
1529 #
1530 _check_quota_file()
1531 {
1532    _check_quota 'xfsdump_quotas' 'xfsdump_quotas_group' 'xfsdump_quotas_proj'
1533 }
1534
1535
1536 # make sure this script returns success
1537 /bin/true