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